diff --git a/.gitignore b/.gitignore index 378eac25d3..d59a62b7e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ build +tmp diff --git a/.gitmodules b/.gitmodules index 12e758c23a..95053091cf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "aux/btest"] path = aux/btest url = git://git.bro-ids.org/btest +[submodule "cmake"] + path = cmake + url = git://git.bro-ids.org/cmake diff --git a/CHANGES b/CHANGES index aa795ed8e4..6f0ed943ca 100644 --- a/CHANGES +++ b/CHANGES @@ -1,4 +1,1243 @@ +2.0-301 | 2012-04-17 17:58:55 -0700 + + * Bro now support ICMPv6. (Matti Mantere, Jon Siwek, Robin Sommer, + Daniel Thayer). + + Overall, Bro now raises the following ICMP events for v4 and v6 as + appropiate: + + event icmp_sent(c: connection, icmp: icmp_conn); + event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string); + event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string); + event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context); + event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context); + event icmp_packet_too_big(c: connection, icmp: icmp_conn, code: count, context: icmp_context); + event icmp_time_exceeded(c: connection, icmp: icmp_conn, code: count, context: icmp_context); + event icmp_parameter_problem(c: connection, icmp: icmp_conn, code: count, context: icmp_context); + event icmp_router_solicitation(c: connection, icmp: icmp_conn); + event icmp_router_advertisement(c: connection, icmp: icmp_conn, hop_limit: count, managed: bool, router_lifetime: count, reachable_time: interval, retrans_timer: interval); + event icmp_neighbor_solicitation(c: connection, icmp: icmp_conn, tgt:addr); + event icmp_neighbor_advertisement(c: connection, icmp: icmp_conn, tgt:addr); + event icmp_redirect(c: connection, icmp: icmp_conn, tgt: addr, dest: addr); + + The `icmp_conn` record got a new boolean field 'v6' that indicates + whether the ICMP message is v4 or v6. + + This change also includes further low-level work on existing IP + and ICMP code, including a reorganization of how ICMPv4 is + handled. + +2.0-281 | 2012-04-17 17:40:39 -0700 + + * Small updates for the bittorrent analyzer to support 64bit types + in binpac. (Seth Hall) + + * Removed the attempt at bittorrent resynchronization. (Seth Hall) + +2.0-276 | 2012-04-17 17:35:56 -0700 + + * Add more support for 's that lack some structure + definitions. (Jon Siwek) + +2.0-273 | 2012-04-16 18:08:56 -0700 + + * Removing QR flag from DNS log in response, which should not have + been there in the first place. (Seth Hall) + + * Sync up patricia.c/h with pysubnettree repo. (Daniel Thayer) + + * Adding missing leak groups to a couple tests. Also activating leak + checking for proxy in basic-cluster test. (Robin Sommer) + +2.0-267 | 2012-04-09 17:47:28 -0700 + + * Add support for mobile IPv6 Mobility Header (RFC 6275). (Jon + Siwek) + + - Enabled through a new --enable-mobile-ipv6 configure-time + option. If not enabled, the mobility header (routing type 2) and + Home Address Destination option are ignored. + + - Accessible at script-layer through 'mobile_ipv6_message' event. + + * Refactor IP_Hdr routing header handling, add MobileIPv6 Home + Address handling. Packets that use the Home Address Destination + option use that option's address as the connection's originator. + (Jon Siwek) + + * Revert TCP checksumming to cache common data, like it did before. + (Jon Siwek) + + * Improve handling of IPv6 routing type 0 extension headers. (Jon + Siwek) + + - flow_weird event with name argument value of "routing0_hdr" is raised + for packets containing an IPv6 routing type 0 header because this + type of header is now deprecated according to RFC 5095. + + - Packets with a routing type 0 header and non-zero segments left + now use the last address in that header in order to associate + with a connection/flow and for calculating TCP/UDP checksums. + + - Added a set of IPv4/IPv6 TCP/UDP checksum unit tests (Jon Siwek) + + * Fix table expiry for values assigned in bro_init() when reading + live. (Jon Siwek) + +2.0-257 | 2012-04-05 15:32:43 -0700 + + * Fix CMake from warning about unused ENABLE_PERFTOOLS_DEBUG + variable. (Jon Siwek) + + * Fix handling of IPv6 atomic fragments. (Jon Siwek) + + * Fix that prevents Bro processes that do neither local logging nor + request remote logs from spawning threads. (Robin Sommer) + + * Fixing perftools-debug support. (Robin Sommer) + + * Reverting SocketComm change tuning I/O behaviour. (Robin Sommer) + + * Adding notice_policy.log canonification for external tests. (Robin Sommer) + + +2.0-245 | 2012-04-04 17:25:20 -0700 + + * Internal restructuring of the logging framework: we now spawn + threads doing the I/O. From a user's perspective not much should + change, except that the OS may now show a bunch of Bro threads. + (Gilbert Clark and Robin Sommer). + + * When building Bro, we now always link in tcmalloc if it's found at + configure time. If it's installed but not picked up, + --with-perftools may help. (Robin Sommer) + + * Renaming the configure option --enable-perftools to + --enable-perftool-debug to indicate that the switch is only + relevant for debugging the heap. It's not needed to pick up + tcmalloc for better performance. (Robin Sommer) + +2.0-184 | 2012-03-28 15:11:11 -0700 + + * Improve handling of IPv6 Routing Type 0 headers. (Jon Siwek) + + - For RH0 headers with non-zero segments left, a + "routing0_segleft" flow_weird event is raised (with a + destination indicating the last address in the routing header), + and an "rh0_segleft" event can also be handled if the other + contents of the packet header are of interest. No further + analysis is done as the complexity required to correctly + identify destination endpoints of connections doesn't seem worth + it as RH0 has been deprecated by RFC 5095. + + - For RH0 headers without any segments left, a "routing0_header" + flow_weird event is raised, but further analysis still occurs as + normal. + +2.0-182 | 2012-03-28 15:01:57 -0700 + + * Remove dead tcp_checksum function from net_util. (Jon Siwek) + + * Change routing0_data_to_addrs BIF to return vector of addresses. + The order of addresses in type 0 routing headers is + interesting/important. (Jon Siwek) + + +2.0-179 | 2012-03-23 17:43:31 -0700 + + * Remove the default "tcp or udp or icmp" filter. In default mode, + Bro would load the packet filter script framework which installs a + filter that allows all packets, but in bare mode (the -b option), + this old filter would not follow IPv6 protocol chains and thus + filter out packets with extension headers. (Jon Siwek) + + * Update PacketFilter/Discarder code for IP version independence. + (Jon Siwek) + + * Fix some IPv6 header related bugs. (Jon Siwek) + + * Add IPv6 fragment reassembly. (Jon Siwek) + + * Add handling for IPv6 extension header chains. Addresses #531. + (Jon Siwek) + + - The script-layer 'pkt_hdr' type is extended with a new 'ip6' field + representing the full IPv6 header chain. + + - The 'new_packet' event is now raised for IPv6 packets. Addresses + #523. + + - A new event called 'ipv6_ext_header' is raised for any IPv6 + packet containing extension headers. + + - A new event called 'esp_packet' is raised for any packets using + ESP ('new_packet' and 'ipv6_ext_header' events provide + connection info, but that info can't be provided here since the + upper-layer payload is encrypted). + + - The 'unknown_protocol' weird is now raised more reliably when + Bro sees a transport protocol or IPv6 extension header it can't + handle. Addresses #522. + + * Add unit tests for IPv6 fragment reassembly, ipv6_ext_headers and + esp_packet events. (Jon Siwek) + + * Adapt FreeBSD's inet_ntop implementation for internal use. Now we + get consistent text representations of IPv6 addresses across + platforms. (Jon Siwek) + + * Update documentation for new syntax of IPv6 literals. (Jon Siwek) + + +2.0-150 | 2012-03-13 16:16:22 -0700 + + * Changing the regular expression to allow Site::local_nets in + signatures. (Julien Sentier) + + * Removing a line of dead code. Found by . Closes #786. (Julien + Sentier) + +2.0-146 | 2012-03-13 15:39:38 -0700 + + * Change IPv6 literal constant syntax to require encasing square + brackets. (Jon Siwek) + +2.0-145 | 2012-03-09 15:10:35 -0800 + + * Remove the match expression. 'match' and 'using' are no longer + keywords. Addressed #753. (Jon Siwek) + +2.0-143 | 2012-03-09 15:07:42 -0800 + + * Fix a BRO_PROFILER_FILE/mkstemp portability issue. Addresses #794. + (Jon Siwek) + +2.0-139 | 2012-03-02 09:33:04 -0800 + + * Changes to how script coverage integrates with test suites. (Jon Siwek) + + - BRO_PROFILER_FILE now passes .X* templated filenames to mkstemp + for generating unique coverage state files. + + - Rearranging Makefile targets. The general rule is that if the + all/brief target fails out due to a test failure, then the dependent + coverage target won't run, but can still be invoked directly later. + (e.g. make brief || make coverage) + + * Standardized on the &default function for SSL constants. (Seth + Hall) + + * Adding btest group "leaks" to leak tests. (Robin Sommer) + + * Adding btest group "comm" to communication tests for parallelizing + execution with new btest version. (Robin Sommer) + + * Sorting all output for diffing in the external tests. (Robin + Sommer) + + * Cleaned up dead code from the old SSL analyzers. Reported by + Julien Sentier. (Seth Hall) + + * Update/add tests for broccoli IPv6 addr/subnet support. Addresses + #448. (Jon Siwek) + + * Remove connection compressor. Addresses #559. (Jon Siwek) + + * Refactor IP_Hdr class ctors. Addresses #532. (Jon Siwek) + + +2.0-121 | 2012-02-24 16:34:17 -0800 + + * A number of smaller memory fixes and code cleanups. (Julien + Sentier) + + * Add to_subnet bif. Fixes #782). (Jon Siwek) + + * Fix IPAddr::Mask/ReverseMask not allowing argument of 0. (Jon + Siwek) + + * Refactor IPAddr v4 initialization from string. Fixes #775. (Jon Siwek) + + * Parse the dotted address string directly instead of canonicalizing + and passing to inet_pton. (Jon Siwek) + + +2.0-108 | 2012-02-24 15:21:07 -0800 + + * Refactoring a number of usages of new IPAddr class. (Jon Siwek) + + * Fixed a bug in remask_addr bif. (Jon Siwek) + +2.0-106 | 2012-02-24 15:02:20 -0800 + + * Raise minimum required CMake version to 2.6.3. (Jon Siwek) + +2.0-104 | 2012-02-24 14:59:12 -0800 + + * Add test case for FTP over IPv4. (Daniel Thayer) + + * Fix IPv6 URLs in ftp.log. (Daniel Thayer) + + * Add a test for FTP over IPv6 (Daniel Thayer) + + * Fix parsing of FTP EPRT command and EPSV response. (Daniel Thayer) + +2.0-95 | 2012-02-22 05:27:34 -0800 + + * GeoIP installation documentation update. (Seth Hall) + + * Decrease strictness of parsing IPv4 strings into addrs. Fixes #775. (Jon Siwek) + + * Fix memory leak in DNS manager. Fixes #777. (Jon Siwek) + + * Fix IPAddr/IPPrefix serialization bugs. (Jon Siwek) + + * Fix compile error. (Jon Siwek) + +2.0-86 | 2012-02-17 15:41:06 -0800 + + * Changing ARP detection to always kick in even if no analyzer is + activated. (Robin Sommer) + + * DNS name lookups performed by Bro now also query AAAA records. + DNS_Mgr handles combining the results of the A and AAAA queries + for a given hostname such that at the scripting layer, the name + resolution can yield a set with both IPv4 and IPv6 addresses. (Jon + Siwek) + + * Add counts_to_addr and addr_to_counts conversion BIFs. (Jon Siwek) + + * Change HashKey threshold for using H3 to 36 bytes. (Jon Siwek) + + * Remove mention of --enable-brov6 in docs. (Daniel Thayer) + + * Remove --enable-brov6 from configure usage text (Daniel Thayer) + + * Add a test and baseline for addr_to_ptr_name BiF. (Daniel Thayer) + + * Adding a test and baseline for ptr_name_to_addr BiF. (Seth Hall) + + * Fix the ptr_name_to_addr BiF to work with IPv6 (Daniel Thayer) + + * Fix a memory leak that perftools now complains about. (Jon Siwek) + + * Remove --enable-brov6 flag, IPv6 now supported by default. (Jon Siwek) + + Some script-layer changes of note: + + - dns_AAAA_reply event signature changed: the string representation + of an IPv6 addr is easily derived from the addr value, it doesn't + need to be another parameter. This event also now generated directly + by the DNS analyzer instead of being "faked" into a dns_A_reply event. + + - Removed addr_to_count BIF. It used to return the host-order + count representation of IPv4 addresses only. To make it more + generic, we might later add a BIF to return a vector of counts + in order to support IPv6. + + - Changed the result of enclosing addr variables in vertical pipes + (e.g. |my_addr|) to return the bit-width of the address type which + is 128 for IPv6 and 32 for IPv4. It used to function the same + way as addr_to_count mentioned above. + + - Remove bro_has_ipv6 BIF + +2.0-57 | 2012-02-10 00:02:35 -0800 + + * Fix typos in the documentation. (Daniel Thayer) + + * Fix compiler warning about Brofiler ctor init list order. (Jon Siwek) + + * Fix missing optional field access in webapp signature_match handler. (Jon Siwek) + +2.0-41 | 2012-02-03 04:10:53 -0500 + + * Updates to the Software framework to simplify the API. (Bernhard + Amann) + +2.0-40 | 2012-02-03 01:55:27 -0800 + + * Fix typos in documentation. (Daniel Thayer) + + * Fix sorting of lines in Brofiler coverage.log. (Daniel Thayer) + +2.0-38 | 2012-01-31 11:50:53 -0800 + + * Canonify sorting of lines in Brofiler coverage.log. (Daniel + Thayer) + +2.0-36 | 2012-01-27 10:38:14 -0800 + + * New "Brofiler" mode that tracks and records script statements + executed during runtime. (Jon Siwek) + + Use the BROFILER_FILE environment variable to point to a file in + which statement usage statistics from Bro script-layer can be + output. + + Script statements that should be ignored can be marked with a "# + @no-test" comment. For example: + + print "don't cover"; # @no-test + + if ( F ) + { # @no-test + ... + } + + * Integrated coverage measurement into test-suite. (Jon Siwek) + +2.0-20 | 2012-01-25 16:34:51 -0800 + + * BiF cleanup (Matthias Vallentin) + + - Rename NFS3::mode2string to a more generic file_mode(). + + - Unify do_profiling()/make_connection_persistent()/expect_connection() + to return any (i.e., nothing) instead of bools. + + - Perform type checking on count-to-port conversion. Related to #684. + + - Remove redundant connection_record() BiF. The same + functionality is provided by lookup_connection(). + + - Remove redundant active_connection() BiF. The same + functionality is provided by connection_exists(). + + - exit() now takes the exit code as argument. + + - to_port() now received a string instead of a count. + +2.0-9 | 2012-01-25 13:47:13 -0800 + + * Allow local table variables to be initialized with {} list + expressions. (Jon Siwek) + +2.0-7 | 2012-01-25 13:38:09 -0800 + + * Teach CompHash to allow indexing by records with vector/table/set + fields. Addresses #464. (Jon Siwek) + +2.0-5 | 2012-01-25 13:25:19 -0800 + + * Fixed a bug resulting in over-logging of detected webapps. (Seth Hall) + + * Make communication log baseline test more reliable. (Jon Siwek) + + * Fixed some broken links in documentation. (Daniel Thayer) + +2.0 | 2012-01-11 13:52:22 -0800 + + * Adding script reference documentation. (The Team). + +2.0-beta-194 | 2012-01-10 10:44:32 -0800 + + * Added an option for filtering out URLs before they are turned into + HTTP::Incorrect_File_Type notices. (Seth Hall) + + * Fix ref counting bug in BIFs that call internal_type. Addresses + #740. (Jon Siwek) + + * Adding back the stats.bro file. (Seth Hall) + + +2.0-beta-188 | 2012-01-10 09:49:29 -0800 + + * Change SFTP/SCP log rotators to use 4-digit year in filenames + Fixes #745. (Jon Siwek) + + * Adding back the stats.bro file. Addresses #656. (Seth Hall) + +2.0-beta-185 | 2012-01-09 18:00:50 -0800 + + * Tweaks for OpenBSD support. (Jon Siwek) + +2.0-beta-181 | 2012-01-08 20:49:04 -0800 + + * Add SFTP log postprocessor that transfers logs to remote hosts. + Addresses #737. (Jon Siwek) + + * Add FAQ entry about disabling NIC offloading features. (Jon Siwek) + + * Add a file NEWS with release notes. (Robin Sommer) + +2.0-beta-177 | 2012-01-05 15:01:07 -0800 + + * Replace the --snaplen/-l command line option with a + scripting-layer option called "snaplen" (which can also be + redefined on the command line, e.g. `bro -i eth0 snaplen=65535`). + + * Reduce snaplen default from 65535 to old default of 8192. Fixes + #720. (Jon Siwek) + +2.0-beta-174 | 2012-01-04 12:47:10 -0800 + + * SSL improvements. (Seth Hall) + + - Added the ssl_session_ticket_handshake event back. + + - Fixed a few bugs. + + - Removed the SSLv2.cc file since it's not used. + +2.0-beta-169 | 2012-01-04 12:44:39 -0800 + + * Tuning the pretty-printed alarm mails, which now include the + covered time range into the subject. (Robin Sommer) + + * Adding top-level "test" target to Makefile. (Robin Sommer) + + * Adding SWIG as dependency to INSTALL. (Robin Sommer) + +2.0-beta-155 | 2012-01-03 15:42:32 -0800 + + * Remove dead code related to record type inheritance. (Jon Siwek) + +2.0-beta-152 | 2012-01-03 14:51:34 -0800 + + * Notices now record the transport-layer protocol. (Bernhard Amann) + +2.0-beta-150 | 2012-01-03 14:42:45 -0800 + + * CMake 2.6 top-level 'install' target compat. Fixes #729. (Jon Siwek) + + * Minor fixes to test process. Addresses #298. + + * Increase timeout interval of communication-related btests. (Jon Siwek) + +2.0-beta-145 | 2011-12-19 11:37:15 -0800 + + * Empty fields are now logged as "(empty)" by default. (Robin + Sommer) + + * In log headers, only escape information when necessary. (Robin + Sommer) + +2.0-beta-139 | 2011-12-19 07:06:29 -0800 + + * The hostname notice email extension works now, plus a general + mechanism for adding delayed information to notices. (Seth Hall) + + * Fix &default fields in records not being initialized in coerced + assignments. Addresses #722. (Jon Siwek) + + * Make log headers include the type of data stored inside a set or + vector ("vector[string]"). (Bernhard Amann) + +2.0-beta-126 | 2011-12-18 15:18:05 -0800 + + * DNS updates. (Seth Hall) + + - Fixed some bugs with capturing data in the base DNS script. + + - Answers and TTLs are now vectors. + + - A warning that was being generated (dns_reply_seen_after_done) + from transaction ID reuse is fixed. + + * SSL updates. (Seth Hall) + + - Added is_orig fields to the SSL events and adapted script. + + - Added a field named last_alert to the SSL log. + + - The x509_certificate function has an is_orig field now instead + of is_server and its position in the argument list has moved. + + - A bit of reorganization and cleanup in the core analyzer. (Seth + Hall) + +2.0-beta-121 | 2011-12-18 15:10:15 -0800 + + * Enable warnings for malformed Broxygen xref roles. (Jon Siwek) + + * Fix Broxygen confusing scoped IDs at start of line as function + parameter. (Jon Siwek) + + * Allow Broxygen markup "##<" for more general use. (Jon Siwek) + +2.0-beta-116 | 2011-12-16 02:38:27 -0800 + + * Cleanup some misc Broxygen css/js stuff. (Jon Siwek) + + * Add search box to Broxygen docs. Fixes #726. (Jon Siwek) + + * Fixed major bug with cluster synchronization, which was not + working. (Seth Hall) + + * Fix missing action in notice policy for looking up GeoIP data. + (Jon Siwek) + + * Better persistent state configuration warning messages (fixes + #433). (Jon Siwek) + + * Renaming HTTP::SQL_Injection_Attack_Against to + HTTP::SQL_Injection_Victim. (Seth Hall). + + * Fixed DPD signatures for IRC. Fixes #311. (Seth Hall) + + * Removing Off_Port_Protocol_Found notice. (Seth Hall) + + * Teach Broxygen to more generally reference attribute values by name. (Jon Siwek) + + * SSH::Interesting_Hostname_Login cleanup. Fixes #664. (Seth Hall) + + * Fixed bug that was causing the malware hash registry script to + break. (Seth Hall) + + * Remove remnant of libmagic optionality. (Jon Siwek) + +2.0-beta-98 | 2011-12-07 08:12:08 -0800 + + * Adapting test-suite's diff-all so that it expands globs in both + current and baseline directory. Closes #677. (Robin Sommer) + +2.0-beta-97 | 2011-12-06 11:49:29 -0800 + + * Omit loading local-.bro scripts from base cluster framework. + Addresses #663 (Jon Siwek) + +2.0-beta-94 | 2011-12-03 15:57:19 -0800 + + * Adapting attribute serialization when talking to Broccoli. (Robin + Sommer) + +2.0-beta-92 | 2011-12-03 15:56:03 -0800 + + * Changes to Broxygen master script package index. (Jon Siwek) + + - Now only lists packages as those directories in the script hierarchy + that contain an __load__.bro file. + + - Script packages (dirs with a __load__.bro file), can now include + a README (in reST format) that will automatically be appended + under the link to a specific package in the master package + index. + +2.0-beta-88 | 2011-12-02 17:00:58 -0800 + + * Teach LogWriterAscii to use BRO_LOG_SUFFIX environemt variable. + Addresses #704. (Jon Siwek) + + * Fix double-free of DNS_Mgr_Request object. Addresses #661. + + * Add a remote_log_peer event which comes with an event_peer record + parameter. Addresses #493. (Jon Siwek) + + * Remove example redef of SMTP::entity_excerpt_len from local.bro. + Fixes error emitted when loading local.bro in bare mode. (Jon + Siwek) + + * Add missing doc targets to top Makefile; remove old doc/Makefile. + Fixes #705. (Jon Siwek) + + * Turn some globals into constants. Addresses #633. (Seth Hall) + + * Rearrange packet filter and DPD documentation. (Jon Siwek) + +2.0-beta-72 | 2011-11-30 20:16:09 -0800 + + * Fine-tuning the Sphinx layout to better match www. (Jon Siwek and + Robin Sommer) + +2.0-beta-69 | 2011-11-29 16:55:31 -0800 + + * Fixing ASCII logger to escape the unset-field place holder if + written out literally. (Robin Sommer) + +2.0-beta-68 | 2011-11-29 15:23:12 -0800 + + * Lots of documentation polishing. (Jon Siwek) + + * Teach Broxygen the ".. bro:see::" directive. (Jon Siwek) + + * Teach Broxygen :bro:see: role for referencing any identifier in + the Bro domain. (Jon Siwek) + + * Teach Broxygen to generate an index of Bro notices. (Jon Siwek) + + * Fix order of include directories. (Jon Siwek) + + * Catch if logged vectors do not contain only atomic types. + (Bernhard Amann) + +2.0-beta-47 | 2011-11-16 08:24:33 -0800 + + * Catch if logged sets do not contain only atomic types. (Bernhard + Amann) + + * Promote libz and libmagic to required dependencies. (Jon Siwek) + + * Fix parallel make from top-level to work on more platforms. (Jon + Siwek) + + * Add decode_base64_custom(). Addresses #670 (Jon Siwek) + + * A bunch of Sphinx-doc reorgs and polishing. (Jon Siwek) + +2.0-beta-28 | 2011-11-14 20:09:28 -0800 + + * Binary packaging script tweaks. We now require CMake 2.8.6. (Jon Siwek) + + * More default "weird" tuning for the "SYN_with_data" notice. (Seth + Hall) + + * Tiny bugfix for http file extraction along with test. (Seth Hall) + +2.0-beta-21 | 2011-11-06 19:27:22 -0800 + + * Quickstart doc fixes. (Jon Siwek) + +2.0-beta-19 | 2011-11-03 17:41:00 -0700 + + * Fixing packet filter test. (Robin Sommer) + +2.0-beta-12 | 2011-11-03 15:21:08 -0700 + + * No longer write to the PacketFilter::LOG stream if not reading + traffic. (Seth Hall) + +2.0-beta-10 | 2011-11-03 15:17:08 -0700 + + * Notice framework documentation update. (Seth Hall) + + * Fixing compiler warnings (addresses #388) (Jon Siwek) + +2.0-beta | 2011-10-27 17:46:28 -0700 + + * Preliminary fix for SSH login detection: we need a counted measure + of payload bytes (not ack tracking and not with the IP header + which is what we have now). (Seth Hall) + + * Fixing send_id() problem. We no longer update &redef functions. + Updating code on the fly isn't fully supported. (Robin Sommer) + + * Tuning the format of the pretty-printed alarm summaries. (Robin + Sommer) + +1.6-dev-1508 | 2011-10-26 17:24:50 -0700 + + * Updating submodule(s). (Robin Sommer) + +1.6-dev-1507 | 2011-10-26 15:10:18 -0700 + + * Baseline updates. (Robin Sommer) + +1.6-dev-1506 | 2011-10-26 14:48:43 -0700 + + * Updating submodule(s). (Robin Sommer) + +1.6-dev-1505 | 2011-10-26 14:43:58 -0700 + + * A new base script that pretty-prints alarms in the regular + summary. (Robin Sommer) + + * Adding a dummy log writer WRITER_NONE that just discards + everything. (Robin Sommer) + +1.6-dev-1498 | 2011-10-26 14:30:15 -0700 + + * Adding instructions to local.bro how to do ACTION_ALARM by + default. (Seth Hall) + +1.6-dev-1495 | 2011-10-26 10:15:58 -0500 + + * Updated unit test baselines. (Seth Hall) + +1.6-dev-1491 | 2011-10-25 20:22:56 -0700 + + * Updating submodule(s). (Robin Sommer) + +1.6-dev-1482 | 2011-10-25 19:08:32 -0700 + + * Fixing bug in log managers predicate evaluation. (Robin Sommer) + +1.6-dev-1481 | 2011-10-25 18:17:03 -0700 + + * Fix a problem with DNS servers being logged that aren't actually + servers. (Seth Hall) + + * Changed generated root cert DN format for RFC2253 compliance. (Jon + Siwek) + + * Removed :bro doc directives from notice documentation. (Seth Hall) + + * New notice framework docs. (Seth Hall) + + * Adding sub messages to emails. (Seth Hall) + + * Adding extra fields to smtp and http to track transaction depth. + (Seth Hall) + + * Fix for SSH login detection heuristic. (Seth Hall) + + * Removed some fields from http analysis that weren't commonly + needed or were wrong. (Seth Hall) + + * Updated/fixed MSIE version parsing in the software framework. + (Seth Hall) + + * Update Mozilla trust roots to index certs by subject distinguished + name. (Jon Siwek) + + * weird.bro rewrite. (Seth Hall) + + * More notice email tuning. (Seth Hall) + + * Slightly restructured http file hashing to fix a bug. (Seth Hall) + + * Changed the notice name for interesting ssh logins to correctly + reflect semantics of the notice. (Seth Hall) + + * Field name change to notice framwork. $result -> $action + + - $result is renamed to $action to reflect changes to the notice + framework since there is already another result-like field + ($suppress_for) and there may be more in the future. + + - Slipped in a change to add connection information to notice + emails too. (Seth Hall) + + * Small script refinements and documentation updates. (Seth Hall) + + * Pass over upgrade guide. (Robin Sommer) + + +1.6-dev-1430 | 2011-10-21 10:39:09 -0700 + + * Fixing crash with unknown debug streams. Closes #643. (Robin + Sommer) + + * Code to better handle interpreter errors, which can now be turned + into non-fatal runtime errors rather than immediate aborts. (Robin + Sommer). + + * Remove old make-src-packages script. (Jon Siwek) + + * Fixing a bunch of format strings. Closes #567. (Robin Sommer) + + * Cleaning up some distribution files. (Robin Sommer) + + * Various test, doc, and installation fixes/tweaks. (Seth Hall, Jon + Siwek and Robin Sommer). + + * Varios smaller policy fixes and tweaks (Seth Hall). + + * Moving docs from web server into distribution. (Robin Sommer) + + * Fixing more (small) memory leaks. (Robin Sommer) + + * Profiling support for DNS_Mgr and triggers. With + misc/profiling.bro, both now report a line in prof.log with some + counters on usage. (Robin Sommer) + + * Fixing DNS memory leaks. Closes #534. (Robin Sommer) + + * Fix code for disabling analyzers. Closes #577. (Robin Sommer) + + * Changed communication option from listen_encrypted to listen_ssl. + (Seth Hall) + + * Modification to the Communication framework API. (Seth Hall) + + - Simplified the communication API and made it easier to change + to encrypted connections by not having separate variables to + define encrypted and unencrypted ports. + + - Now, to enable listening without configuring nodes just + load the frameworks/communication/listen script. + + - If encrypted listening is desired set the following: + redef Communication::listen_encrypted=T; + + * Connection compressor now disabled by default. Addresses #559. + (Robin Sommer) + + +1.6-dev-1372 | 2011-10-06 18:09:17 -0700 + + * Filtering some potentially high-volume DNS weirds. (Robin Sommer) + + * DNS now raises DPD events. Closes #577. (Robin Sommer) + + * Fixing a bunch of compiler warnings. (Robin Sommer) + + * Remote logs are auto-flushed if the last write was longer than a + second ago. Addresses #498. (Robin Sommer) + + * Fix missing from previous MIME commit. (Robin Sommer) + +1.6-dev-1366 | 2011-10-06 17:05:21 -0700 + + * Make CompHash computation/recovery for functions deterministic. + Closes #636. (Jon Siwek) + + * Removing unnecessary @load in local.bro. (Robin Sommer) + + * Optimizing some MIME code. (Robin Sommer) + + * Speed improvements in logging code. (Robin Sommer) + + * Consolidating some node-specific functionality from scripts in + broctl repo. (Jon Siwek) + + * Another fix the for 1xx script code. (Robin Sommer) + +1.6-dev-1352 | 2011-10-05 16:20:51 -0700 + + * Fix for optional HTTP::Info status_code. (Jon Siwek) + + * Teaking some external testing scripts. (Jon Siwek) + + * HTTP bug fix reported by Martin Holste. (Seth Hall) + + * More script tuning. (Seth Hall) + + - Moved some of the weird events back to the base/ directory. + + - SSL fixes, updates, and performance optimization. + + * More adjustment to reduce Weird volumes. (Seth Hall) + + * Fixed an error when calculating x509 certificate hashes (reported + by Martin Holste). (Seth Hall) + + * Clean up to cluster framework to make event handling clearer. + (Seth Hall) + + * Fixed a bug in the notice framework. (Seth Hall) + + * Bug fix for FTP analysis script. (Seth Hall) + +1.6-dev-1333 | 2011-09-29 22:29:51 -0700 + + * Fixing a number of memory leaks. (Robin Sommer) + + * Loaded_scripts.log is indented with spaces now and makes more + sense to look at. (Seth Hall) + + * Teach HTTP parser to derive content length of multipart/byteranges + bodies. Addresses #488. (Jon Siwek) + + * Change logging of HTTP 1xx responses to occur in their own + columns. Addresses #411. (Jon Siwek) + + * Fix handling of HTTP 1xx response codes. Addresses #411). + + * Taking advantage of yet another trick to get installed browser + plugins. (Seth Hall) + + - With the software-browser-plugins script you can watch for Omniture + advertising servers to grab the list of installed plugins. + + - I reorganized the plugin detection a bit too to abstract it better. + + - Removed the WEB_ prefix from all of the Software::Type HTTP enums. + They were essentially redundant due to the full name already being + HTTP::SERVER (for example). + +1.6-dev-1316 | 2011-09-28 16:50:05 -0700 + + * Unit test cleanup. Updated README and collected coverage-related + tests in a common dir. (Jon Siwek) + + * Fixes for known-services. (Seth Hall) + + * Ported and 2.0ized the capture-loss script. (Seth Hall) + + * Communication fix and extension.(Robin Sommer) + + - Removing unnecessary log flushing. Closes #498. + + - Adding new BiF disconnect() that shuts a connection to a peer down. + + - terminate_connection() now first flushes any still buffered log + messages. + + * Fix for high SSL memory usage by adding &transient attribute to + top-level SSL pac array type. Closes #574. (Robin Sommer) + + * Fix a small bug in the metrics framework. (Seth Hall) + + * Temporarily removing scripts that aren't ready to be included. + Will return before next release. (Seth Hall) + + * New SSL policy scripts. (Seth Hall) + + - protocols/ssl/expiring-certs uses time based information from + certificates to determine if they will expire soon, have already + expired, or haven't yet become valid. + + - protocols/ssl/extract-certs-pem is a script for taking certs off + the line and converting them to PEM certificates with the openssl + command line tool then dumping them to a file. + + * Notice::type_suppression_intervals: table[Notice::Type] of + interval can be used to modify the suppression intervals for + entire types of notices. (Seth Hall) + + * EOF SSL protocol violations are only generated a single time now. + (Seth Hall) + + * Script level fixes. (Seth Hall) + + - Fixed a type name conflict in the Known namespace. + + - Fixed a DPD framework bug that was causing Reporter messages. + + - Fixed the notice_policy log. + + - Predicate functions are now logged. + + - Predicate functions are now optional. If not given, it's assumed that + the result should always apply. (Seth Hall) + + - Fix a problem with accidental and mistaken HTTP log lines. + +1.6-dev-1293 | 2011-09-22 19:44:37 -0700 + + * Smaller script tweaks. (Seth Hall) + + * Duplicate notice suppression. (Seth Hall) + + - Duplicate notices are discovered with the new Notice::Info + field $identifier. It's a string that is left up to the + notice implementor to define which would indicate a + fundamentally duplicate notice. The field is optional and + if it's not included it's not possible for notice + suppression to take place. + + - Duplicate notices are suppressed by default for the interval + defined by the Notice::default_suppression_interval variable + (1 hour by default). + + - A new notice action was defined ACTION_NO_SUPPRESS to prevent + suppression for a specific notice instance. A convenience set + named not_suppressed_types was also created to not suppress + entire notice types. + + - A new field was added to the PolicyItem type to modify the length + of time a notice should be suppressed if the predicate matches. + The field is named $suppress_for. This name makes the code more + readable like this: $suppress_for = 1day + + - New events were created to give visibility into the notice + framework's suppression activity. + - event Notice::begin_suppression(n: Notice::Info) + - event Notice::suppressed(n: Notice::Info) + - event Notice::end_suppression(n: Notice::Info) + + - The suppression.bro script doesn't have a baseline because + it is causing a segfault in Bro. This one test is the + reason that this is being integrated into a branch instead + of master. (Seth Hall) + + * Fix crash on exit. Addresses #607. (Jon Siwek) + + * Fix PktSrc setting next_timestamp even when no packet available. + (Jon Siwek) + + * Fix lack of NUL-termination in to_upper/to_lower BIF's return val. + (Jon Siwek) + + * Fixing unit tests and some minor bugs. (Jon Siwek) + + * Fix broctl cluster log rotation. Addresses #619. (Jon Siwek) + + * Added session ID to the SSL logging. (Seth Hall) + + * Adding "install-aux" target + updating bro-aux submodule. (Jon + Siwek) + + * Cleaning up INSTALL and README. (Jon Siwek) + + * Remove $Id$ tags. (Jon Siwek) + + * Remove policy.old directory. Addresses #511. (Jon Siwek) + + * Small rework with ssl base script to reduce memory usage. (Seth + Hall) + + * Updated the mozilla root certs. (Seth Hall) + +1.6-dev-1261 | 2011-09-15 17:13:55 -0700 + + * Memory leak fixes. Addresses #574 (Jon Siwek) + + * Add configure options for ruby/bindings integration. (Jon Siwek) + + * Fix filter path_func to allow record argument as a subset of + stream's columns. Addresses #600. (Jon Siwek) + + * Log rotation is now controlled directly through Filter records. (Jon Siwek) + + * Fix indexing for record types with optional fields. Addresses #378 + (Jon Siwek) + +1.6-dev-1248 | 2011-09-15 16:01:32 -0700 + + * Removed custom malloc() implementation for FreeBSD. Closes #557. + (Jon Siwek) + + * Testing/external scripts no longer compute MD5 checksums for SMTP + entities. (Robin Sommer) + + * External tests no longer include the full content of mismatching + files in the diagnostics output. (Robin Sommer) + +1.6-dev-1241 | 2011-09-14 22:51:52 -0400 + + * Fixing a major memory utilization issues with SSL analysis. (Seth + Hall) + + * Enhancements to HTTP analysis: (Seth Hall) + + - More options for the header-names.bro script. + + - New script for logging header names and values. Closes #519. + (Seth Hall) + + - HTTP body size measurement added to http.log. + + - The value of the content-length headers has now been removed + in the default output but it could be added back locally at an + installation by a user. + + - Added fields to indicate if some parsing interruption happened + during the body transfer. Closes #581 (Seth Hall) + + * Misc smaller usability and correctness updates: (Seth Hall) + + - Removed an notice definition from the base SSL scripts. + + - Moved a logging stream ID into the export section for known-services + and bumped priority for creating the stream. + + - Adding configuration knobs for the SQL injection attack detection + script and renaming the HTTP::SQL_Injection_Attack notice to + HTTP::SQL_Injection_Attack_Against + + - Bumped priority when creating Known::CERTS_LOG. + + - Fixing a warning from the cluster framework. (Seth Hall) + + * Bugfix for log writer, which didn't escape binary stuff in some + situations. Closes #585. (Robin Sommer) + + * A larget set of changes to the testing/external infrastructure. + The traces for external test-suites are no longer kept inside the + repositories themselves but downloaded separately via curl. This + is because git is pretty bad at dealing with large files. See the + README for more information. (Robin Sommer) + +1.6-dev-1221 | 2011-09-08 08:41:17 -0700 + + * Updates for documentation framework and script docs. (Jon Siwek) + + * The script level PF_RING support isn't working so removing it. + (Seth Hall) + + * Delete SSL certificates from memory after ssl_established event. + (Seth Hall) + + * Small fixes for SSL analysis. (Seth Hall) + +1.6-dev-1212 | 2011-09-07 16:15:28 -0700 + + * Internally, the UID generation can now return values from + different pool for better reproducability in testing mode. + (Gilbert Clark). + + * Added new BiF unique_id_from(pool: string, prefix: string) that + allows the user to specify a randomness pool. (Gilbert Clark) + +1.6-dev-1198 | 2011-09-07 11:03:36 -0700 + + * Extended header for ASCII log that make it easier for scripts to + parse Bro log files. (Gilbert Clark) + + * Potential fix for rotation crashes. Addresses #588. (Robin Sommer) + + * Added PF_RING load balancing support to the scripting layer, + enabled by loading the misc/pf-ring-load-balancing script. (Seth + Hall) + + * Added a BiF setenv() for setting environment variables. (Seth + Hall) + +1.6-dev-1184 | 2011-09-04 09:34:50 -0700 + + * FindPCAP now links against thread library when necessary (e.g. + PF_RING's libpcap). (Jon Siwek) + + * Install binaries with an RPATH. (Jon Siwek) + + * Fix for a case where nested records weren't coerced even though + possible. (Jon Siwek) + + * Changed ASCII writer to delay creation of log after rotation until + next write. + + * Changed default snaplen to 65535 and added a -l/--snaplen command + line option to set it explicitly. Addresses #447. (Jon Siwek) + + * Various updates to logging framework. (Seth Hall) + + * Changed presentation of enum labels to include namespace. (Jon + Siwek) + + * HTTP analyzer is now enabled with any of the HTTP events. (Seth + Hall) + + * Fixed missing format string that caused some segfaults. (Gregor + Maier) + + * ASCII writer nows prints time interval with 6 decimal places. + (Gregor Maier) + + * Added a Reporter::fatal BIF. (Jon Siwek) + + * Fixes for GeoIP support. Addresses #538. (Jon Siwek) + + * Fixed excessive memory usage of SSL analyzer on connections with + gaps. (Gregor Maier) + + * Added a log postprocessing function that can SCP rotated logs to + remote hosts. (Jon Siwek) + + * Added a BiF for getting the current Bro version string. (Jon + Siwek) + + * Misc. doc/script/test cleanup. (Jon Siwek) + + * Fixed bare-mode @load dependency problems. (Jon Siwek) + + * Fixed check_for_unused_event_handlers option. (Jon Siwek) + + * Fixing some more bare-mode @load dependency issues (Jon Siwek) + + * Reorganizing btest/policy directory to match new scripts/ + organization. Addresses #545 (Jon Siwek) + + * bro scripts generated from bifs now install to + $prefix/share/bro/base. Addresses #545 (Jon Siwek) + + * Changeed/fixed some cluster script error reporting. (Jon Siwek) + + * Various script normalization. (Jon Siwek) + + * Add a test that checks each individual script can be loaded in + bare-mode. Adressess #545. (Jon Siwek) + + * Tune when c$conn is set. Addresses #554. (Gregor Maier) + + * Add ConnSize_Analyzer's fields to conn.log. (Gregor Maier) + + * Fixing bug in "interesting hostnames" detection. (Seth Hall) + + * Adding metrics framework intermediate updates. (Seth Hall) + 1.6-dev-1120 | 2011-08-19 19:00:15 -0700 * Fix for the CompHash fix. (Robin Sommer) @@ -24,7 +1263,7 @@ framework updates. (Seth Hall) * Metrics framework now works on cluster setups. (Seth Hall) - + * Reclassifying more DNS manager errors as non-fatal errors. (Robin Sommer) @@ -40,9 +1279,9 @@ Siwek) * Workaround for FreeBSD CMake port missing debug flags. (Jon Siwek) - + * piped_exec() can now deal with null bytes. (Seth Hall) - + * Fix vector initialization for lists of records with optional types. Closes #485. (Jon Siwek) @@ -56,19 +1295,19 @@ (Jon Siwek) * Fixing reporter's location tracking. Closes #492. (Robin Sommer) - + * Turning DNS errors into warnings. Closes #255. (Robin Sommer) - + * Logging's path_func now receives the log record as argument. Closes #555. (Robin Sommer) - * Functions can now be logged; their full body gets recorded. + * Functions can now be logged; their full body gets recorded. Closes #506. (Robin Sommer) * Bugfix for hostname notice email extension. (Seth Hall) - + * Updates for notice framework. (Seth Hall) - + - New ACTION_ADD_GEODATA to add geodata to notices in an extension field named remote_location. @@ -78,7 +1317,7 @@ * Updates to local.bro (Seth Hall) * Added the profiling script. (Seth Hall) - + * Updates for SSH scripts. (Seth Hall) * ConnSize analyzer is turned on by default now. (Seth Hall) @@ -89,12 +1328,12 @@ * HTTP now uses the extract_filename_from_content_disposition function. (Seth Hall) * Major SMTP script refactor. Closes #509. (Jon Siwek and Seth Hall) - + * New variable Site::local_nets_table in utils/site for mapping address to defined local subnet. * Metrics framework updates, more to come. (Seth Hall) - + 1.6-dev-1061 | 2011-08-08 18:25:27 -0700 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a4d48c6eb..d27fa2d40b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,35 +1,6 @@ project(Bro C CXX) - -if (NOT CMAKE_C_COMPILER) - message(FATAL_ERROR "Could not find prerequisite C compiler") -endif () - -if (NOT CMAKE_CXX_COMPILER) - message(FATAL_ERROR "Could not find prerequisite C++ compiler") -endif () - -######################################################################## -## CMake Configuration -cmake_minimum_required(VERSION 2.6 FATAL_ERROR) - -# Prohibit in-source builds. -if ("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}") - message(FATAL_ERROR "In-source builds are not allowed. Please use " - "./configure to choose a build directory and " - "initialize the build configuration.") -endif () - -set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) - -if ("${PROJECT_SOURCE_DIR}" STREQUAL "${CMAKE_SOURCE_DIR}") - # uninstall target - configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" - "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" - @ONLY) - - add_custom_target(uninstall COMMAND - ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) -endif () +cmake_minimum_required(VERSION 2.6.3 FATAL_ERROR) +include(cmake/CommonCMakeConfig.cmake) ######################################################################## ## Project/Build Configuration @@ -61,25 +32,9 @@ list(GET version_numbers 0 VERSION_MAJOR) list(GET version_numbers 1 VERSION_MINOR) set(VERSION_MAJ_MIN "${VERSION_MAJOR}.${VERSION_MINOR}") -set(EXTRA_COMPILE_FLAGS "-Wall -Wno-unused") - -if (ENABLE_DEBUG) - set(CMAKE_BUILD_TYPE Debug) - # manual add of -g works around its omission in FreeBSD's CMake port - set(EXTRA_COMPILE_FLAGS "${EXTRA_COMPILE_FLAGS} -g -DDEBUG") -else () - set(CMAKE_BUILD_TYPE RelWithDebInfo) -endif () - -# Compiler flags may already exist in CMake cache (e.g. when specifying -# CFLAGS environment variable before running cmake for the the first time) -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_COMPILE_FLAGS}") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EXTRA_COMPILE_FLAGS}") - ######################################################################## ## Dependency Configuration -include(MacDependencyPaths) include(FindRequiredPackage) # Check cache value first to avoid displaying "Found sed" messages everytime @@ -98,6 +53,8 @@ FindRequiredPackage(BISON) FindRequiredPackage(PCAP) FindRequiredPackage(OpenSSL) FindRequiredPackage(BIND) +FindRequiredPackage(LibMagic) +FindRequiredPackage(ZLIB) if (NOT BinPAC_ROOT_DIR AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/aux/binpac/CMakeLists.txt) @@ -117,26 +74,12 @@ include_directories(BEFORE ${OpenSSL_INCLUDE_DIR} ${BIND_INCLUDE_DIR} ${BinPAC_INCLUDE_DIR} + ${LibMagic_INCLUDE_DIR} + ${ZLIB_INCLUDE_DIR} ) # Optional Dependencies -set(HAVE_LIBMAGIC false) -find_package(LibMagic) -if (LIBMAGIC_FOUND) - set(HAVE_LIBMAGIC true) - include_directories(BEFORE ${LibMagic_INCLUDE_DIR}) - list(APPEND OPTLIBS ${LibMagic_LIBRARY}) -endif () - -set(HAVE_LIBZ false) -find_package(ZLIB) -if (ZLIB_FOUND) - set(HAVE_LIBZ true) - include_directories(BEFORE ${ZLIB_INCLUDE_DIR}) - list(APPEND OPTLIBS ${ZLIB_LIBRARY}) -endif () - set(USE_GEOIP false) find_package(LibGeoIP) if (LIBGEOIP_FOUND) @@ -146,15 +89,39 @@ if (LIBGEOIP_FOUND) endif () set(USE_PERFTOOLS false) -if (ENABLE_PERFTOOLS) - find_package(GooglePerftools) - if (GOOGLEPERFTOOLS_FOUND) - set(USE_PERFTOOLS true) - include_directories(BEFORE ${GooglePerftools_INCLUDE_DIR}) +set(USE_PERFTOOLS_DEBUG false) + +find_package(GooglePerftools) + +if (GOOGLEPERFTOOLS_FOUND) + include_directories(BEFORE ${GooglePerftools_INCLUDE_DIR}) + set(USE_PERFTOOLS true) + + if (ENABLE_PERFTOOLS_DEBUG) + # Enable heap debugging with perftools. + set(USE_PERFTOOLS_DEBUG true) + list(APPEND OPTLIBS ${GooglePerftools_LIBRARIES_DEBUG}) + else () + # Link in tcmalloc for better performance. list(APPEND OPTLIBS ${GooglePerftools_LIBRARIES}) endif () endif () +if (ENABLE_PERFTOOLS_DEBUG) + # Just a no op to prevent CMake from complaining about manually-specified + # ENABLE_PERFTOOLS_DEBUG not being used if google perftools weren't found +endif () + +set(brodeps + ${BinPAC_LIBRARY} + ${PCAP_LIBRARY} + ${OpenSSL_LIBRARIES} + ${BIND_LIBRARY} + ${LibMagic_LIBRARY} + ${ZLIB_LIBRARY} + ${OPTLIBS} +) + ######################################################################## ## System Introspection @@ -229,23 +196,10 @@ message( "\nAux. Tools: ${INSTALL_AUX_TOOLS}" "\n" "\nGeoIP: ${USE_GEOIP}" - "\nlibz: ${HAVE_LIBZ}" - "\nlibmagic: ${HAVE_LIBMAGIC}" "\nGoogle perftools: ${USE_PERFTOOLS}" + "\n debugging: ${USE_PERFTOOLS_DEBUG}" "\n" "\n================================================================\n" ) -######################################################################## -## Show warning when installing user is different from the one that configured - -install(CODE " - if (NOT $ENV{USER} STREQUAL \$ENV{USER}) - message(STATUS \"ATTENTION: Install is being performed by user \" - \"'\$ENV{USER}', but the build directory was configured by \" - \"user '$ENV{USER}'. This may result in a permissions error \" - \"when writing the install manifest, but you can ignore it \" - \"and consider the installation as successful if you don't \" - \"care about the install manifest.\") - endif () -") +include(UserChangedWarning) diff --git a/COPYING b/COPYING index f9bba2b90e..7b0a94a03b 100644 --- a/COPYING +++ b/COPYING @@ -1,11 +1,12 @@ -Copyright (c) 1995-2010, The Regents of the University of California, -through Lawrence Berkeley National Laboratory. All rights reserved. +Copyright (c) 1995-2012, The Regents of the University of California +through the Lawrence Berkeley National Laboratory and the +International Computer Science Institute. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: -(1) Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. +(1) Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. (2) Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the @@ -29,20 +30,5 @@ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -Note that some files in the Bro distribution carry their own copyright -notices. The above applies to the Bro scripts in policy/ (other than as -noted below) and the source files in src/, other than: - - policy/sigs/p0fsyn.osf - src/H3.h - src/OSFinger.cc - src/OSFinger.h - src/bsd-getopt-long.c - src/bsd-getopt-long.h - src/md5.c - src/md5.h - src/patricia.c - src/patricia.h - -In addition, other components, such as the build system, may have -separate copyrights. +Note that some files in the distribution may carry their own copyright +notices. diff --git a/INSTALL b/INSTALL index 5f61d0d663..d4aa93d11f 100644 --- a/INSTALL +++ b/INSTALL @@ -8,98 +8,85 @@ Prerequisites Bro relies on the following libraries and tools, which need to be installed before you begin: - * A C/C++ compiler + * CMake 2.6.3 or greater http://www.cmake.org - * Libpcap headers and libraries - Network traffic capture library + * Libpcap (headers and libraries) http://www.tcpdump.org - * Flex (Fast Lexical Analyzer) - Flex is already installed on most systems, so with luck you can - skip having to install it yourself. + * OpenSSL (headers and libraries) http://www.openssl.org - * Bison (GNU Parser Generator) - This comes with many systems, but if you get errors compiling - parse.y, you will need to install it. - - * Perl - Used only during the Bro build process - - * sed - Used only during the Bro build process - - * BIND8 headers and libraries - These are usually already installed as well. - - * OpenSSL headers and libraries - For analysis of SSL certificates by the HTTP analyzer, and - for encrypted Bro-to-Bro communication. These are likely installed, - though some platforms may require installation of a 'devel' package - for the headers. - - * CMake 2.6 or greater - CMake is a cross-platform, open-source build system, typically - not installed by default. See http://www.cmake.org for more - information regarding CMake and the installation steps below for - how to use it to build this distribution. CMake generates native - Makefiles that depend on GNU Make by default. - -Bro can also make uses of some optional libraries if they are found at -installation time: + * SWIG http://www.swig.org * Libmagic - For identifying file types (e.g., in FTP transfers). - - * LibGeoIP - For geo-locating IP addresses. * Libz - For decompressing HTTP bodies by the HTTP analyzer, and for - compressed Bro-to-Bro communication. + +Bro can make uses of some optional libraries if they are found at +installation time: + + * LibGeoIP For geo-locating IP addresses. + +Bro also needs the following tools, but on most systems they will +already come preinstalled: + + * Bash (For Bro Control). + * BIND8 (headers and libraries) + * Bison (GNU Parser Generator) + * Flex (Fast Lexical Analyzer) + * Perl (Used only during the Bro build process) + Installation ============ -To build and install into /usr/local/bro: +To build and install into ``/usr/local/bro``:: - > ./configure - > cd build - > make - > make install + ./configure + make + make install -This will perform an out-of-source build into a directory called -build/, using default build options. It then installs the Bro binary -into /usr/local/bro/bin. Depending on the Bro package you -downloaded, there may be auxiliary tools and libraries available in -the aux/ directory. If so, they will be installed by default as well -if not explicitly disabled via configure options and may also have -additional installation/configuration instructions that you can -find in their source directories. +This will first build Bro into a directory inside the distribution +called ``build/``, using default build options. It then installs all +required files into ``/usr/local/bro``, including the Bro binary in +``/usr/local/bro/bin/bro``. -You can specify a different installation directory with +You can specify a different installation directory with:: - > ./configure --prefix= + ./configure --prefix= -Note that "/usr" and "/opt/bro" are standard prefixes for binary -packages to be installed, so those are typically not good choices -unless you are creating such a package. +Note that ``/usr`` and ``/opt/bro`` are the standard prefixes for +binary Bro packages to be installed, so those are typically not good +choices unless you are creating such a package. -Run "./configure --help" for more options. +Run ``./configure --help`` for more options. + +Depending on the Bro package you downloaded, there may be auxiliary +tools and libraries available in the ``aux/`` directory. All of them +except for ``aux/bro-aux`` will also be built and installed by doing +``make install``. To install the programs that come in the +``aux/bro-aux`` directory, use ``make install-aux``. There are +``--disable-*`` options that can be given to the configure script to +turn off unwanted auxiliary projects. + +OpenBSD users, please see our `FAQ +` if you are having +problems installing Bro. Running Bro =========== Bro is a complex program and it takes a bit of time to get familiar -with it. In the following we give a few simple examples. See the -quickstart guide at http://www.bro-ids.org for more information; you -can the source that in doc/quick-start. +with it. A good place for newcomers to start is the Quickstart Guide +at http://www.bro-ids.org/documentation/quickstart.html. -For developers that wish to run Bro from the the build/ directory -after performing "make", but without performing "make install", they -will have to first set BROPATH to look for scripts inside the build -directory. Sourcing either build/bro-path-dev.sh or build/bro-path-dev.csh -as appropriate for the current shell accomplishes this. e.g.: +For developers that wish to run Bro directly from the ``build/`` +directory (i.e., without performing ``make install``), they will have +to first adjust ``BROPATH`` to look for scripts inside the build +directory. Sourcing either ``build/bro-path-dev.sh`` or +``build/bro-path-dev.csh`` as appropriate for the current shell +accomplishes this and also augments your ``PATH`` so you can use the +Bro binary directly:: - > ./configure - > make - > source build/bro-path-dev.sh - > ./build/src/bro + ./configure + make + source build/bro-path-dev.sh + bro diff --git a/Makefile b/Makefile index 863440661e..455fa6ed88 100644 --- a/Makefile +++ b/Makefile @@ -2,47 +2,56 @@ # A simple static wrapper for a number of standard Makefile targets, # mostly just forwarding to build/Makefile. This is provided only for # convenience and supports only a subset of what CMake's Makefile -# to offer. For more, execute that one directly. +# offers. For more, execute that one directly. # -SOURCE=$(PWD) -BUILD=$(SOURCE)/build -TMP=/tmp/bro-dist.$(UID) -BRO_V=`cat $(SOURCE)/VERSION` -BROCCOLI_V=`cat $(SOURCE)/aux/broccoli/VERSION` -BROCTL_V=`cat $(SOURCE)/aux/broctl/VERSION` +BUILD=build +REPO=`basename \`git config --get remote.origin.url\`` +VERSION_FULL=$(REPO)-`cat VERSION` +VERSION_MIN=$(REPO)-`cat VERSION`-minimal +HAVE_MODULES=git submodule | grep -v cmake >/dev/null all: configured - ( cd $(BUILD) && make ) + $(MAKE) -C $(BUILD) $@ -install: configured - ( cd $(BUILD) && make install ) +install: configured all + $(MAKE) -C $(BUILD) $@ -clean: configured - ( cd $(BUILD) && make clean ) - ( cd $(BUILD) && make docclean && make restclean ) +install-aux: configured + $(MAKE) -C $(BUILD) $@ + +clean: configured docclean + $(MAKE) -C $(BUILD) $@ doc: configured - ( cd $(BUILD) && make doc ) + $(MAKE) -C $(BUILD) $@ docclean: configured - ( cd $(BUILD) && make docclean && make restclean ) + $(MAKE) -C $(BUILD) $@ + +restdoc: configured + $(MAKE) -C $(BUILD) $@ + +restclean: configured + $(MAKE) -C $(BUILD) $@ + +broxygen: configured + $(MAKE) -C $(BUILD) $@ + +broxygenclean: configured + $(MAKE) -C $(BUILD) $@ dist: - @( mkdir -p $(BUILD) && rm -rf $(TMP) && mkdir $(TMP) ) - @cp -R $(SOURCE) $(TMP)/Bro-$(BRO_V) - @( cd $(TMP) && find . -name .git\* | xargs rm -rf ) - @( cd $(TMP) && find . -name \*.swp | xargs rm -rf ) - @( cd $(TMP) && find . -type d -name build | xargs rm -rf ) - @( cd $(TMP) && tar -czf $(BUILD)/Bro-all-$(BRO_V).tar.gz Bro-$(BRO_V) ) - @( cd $(TMP)/Bro-$(BRO_V)/aux && mv broccoli Broccoli-$(BROCCOLI_V) && \ - tar -czf $(BUILD)/Broccoli-$(BROCCOLI_V).tar.gz Broccoli-$(BROCCOLI_V) ) - @( cd $(TMP)/Bro-$(BRO_V)/aux && mv broctl Broctl-$(BROCTL_V) && \ - tar -czf $(BUILD)/Broctl-$(BROCTL_V).tar.gz Broctl-$(BROCTL_V) ) - @( cd $(TMP)/Bro-$(BRO_V)/aux && rm -rf Broctl* Broccoli* ) - @( cd $(TMP) && tar -czf $(BUILD)/Bro-$(BRO_V).tar.gz Bro-$(BRO_V) ) - @rm -rf $(TMP) - @echo "Distribution source tarballs have been compiled in $(BUILD)" + @rm -rf $(VERSION_FULL) $(VERSION_FULL).tgz + @rm -rf $(VERSION_MIN) $(VERSION_MIN).tgz + @mkdir $(VERSION_FULL) + @tar --exclude=$(VERSION_FULL)* --exclude=$(VERSION_MIN)* --exclude=.git -cf - . | ( cd $(VERSION_FULL) && tar -xpf - ) + @( cd $(VERSION_FULL) && cp -R ../.git . && git reset -q --hard HEAD && git clean -xdfq && rm -rf .git ) + @tar -czf $(VERSION_FULL).tgz $(VERSION_FULL) && echo Package: $(VERSION_FULL).tgz && rm -rf $(VERSION_FULL) + @$(HAVE_MODULES) && mkdir $(VERSION_MIN) || exit 0 + @$(HAVE_MODULES) && tar --exclude=$(VERSION_FULL)* --exclude=$(VERSION_MIN)* --exclude=.git `git submodule | awk '{print "--exclude="$$2}' | grep -v cmake | tr '\n' ' '` -cf - . | ( cd $(VERSION_MIN) && tar -xpf - ) || exit 0 + @$(HAVE_MODULES) && ( cd $(VERSION_MIN) && cp -R ../.git . && git reset -q --hard HEAD && git clean -xdfq && rm -rf .git ) || exit 0 + @$(HAVE_MODULES) && tar -czf $(VERSION_MIN).tgz $(VERSION_MIN) && echo Package: $(VERSION_MIN).tgz && rm -rf $(VERSION_MIN) || exit 0 bindist: @( cd pkg && ( ./make-deb-packages || ./make-mac-packages || \ @@ -51,6 +60,9 @@ bindist: distclean: rm -rf $(BUILD) +test: + @(cd testing && make ) + configured: @test -d $(BUILD) || ( echo "Error: No build/ directory found. Did you run configure?" && exit 1 ) @test -e $(BUILD)/Makefile || ( echo "Error: No build/Makefile found. Did you run configure?" && exit 1 ) diff --git a/NEWS b/NEWS new file mode 100644 index 0000000000..c48b243552 --- /dev/null +++ b/NEWS @@ -0,0 +1,108 @@ + +Release Notes +============= + +This document summarizes the most important changes in the current Bro +release. For a complete list of changes, see the ``CHANGES`` file. + + +Bro 2.1 +------- + +- Dependencies: + + * Bro now requires CMake >= 2.6.3. + + * Bro now links in tcmalloc (part of Google perftools) if found at + configure time. Doing so can significantly improve memory and + CPU use. + +- Bro now supports IPv6 out of the box; the configure switch + --enable-brov6 is gone. + +- DNS name lookups performed by Bro now also query AAAA records. The + results of the A and AAAA queries for a given hostname are combined + such that at the scripting layer, the name resolution can yield a + set with both IPv4 and IPv6 addresses. + +- The connection compressor was already deprecated in 2.0 and has now + been removed from the code base. + +- We removed the "match" statement, which was no longer used by any of + the default scripts, nor was it likely to be used by anybody anytime + soon. With that, "match" and "using" are no longer reserved keywords. + +- The syntax for IPv6 literals changed from "2607:f8b0:4009:802::1012" + to "[2607:f8b0:4009:802::1012]". + +- Bro now spawn threads for doing its logging. From a user's + perspective not much should change, except that the OS may now show + a bunch of Bro threads. + +- We renamed the configure option --enable-perftools to + --enable-perftool-debug to indicate that the switch is only relevant + for debugging the heap. + +- Bro's ICMP analyzer now handles both IPv4 and IPv6 messages with a + joint set of events. The `icmp_conn` record got a new boolean field + 'v6' that indicates whether the ICMP message is v4 or v6. + + +TODO: Extend. + +Bro 2.0 +------- + +As the version number jump suggests, Bro 2.0 is a major upgrade and +lots of things have changed. We have assembled a separate upgrade +guide with the most important changes compared to Bro 1.5 at +http://www.bro-ids.org/documentation/upgrade.html. You can find +the offline version of that document in ``doc/upgrade.rst.``. + +Compared to the earlier 2.0 Beta version, the major changes in the +final release are: + + * The default scripts now come with complete reference + documentation. See + http://www.bro-ids.org/documentation/index.html. + + * libz and libmagic are now required dependencies. + + * Reduced snaplen default from 65535 to old default of 8192. The + large value was introducing performance problems on many + systems. + + * Replaced the --snaplen/-l command line option with a + scripting-layer option called "snaplen". The new option can also + be redefined on the command line, e.g. ``bro -i eth0 + snaplen=65535``. + + * Reintroduced the BRO_LOG_SUFFIX environment variable that the + ASCII logger now respects to add a suffix to the log files it + creates. + + * The ASCII logs now include further header information, and + fields set to an empty value are now logged as ``(empty)`` by + default (instead of ``-``, which is already used for fields that + are not set at all). + + * Some NOTICES were renamed, and the signatures of some SSL events + have changed. + + * bro-cut got some new capabilities: + + - If no field names are given on the command line, we now pass + through all fields. + + - New options -u/-U for time output in UTC. + + - New option -F to give output field separator. + + * Broccoli supports more types internally, allowing to send + complex records. + + * Many smaller bug fixes, portability improvements, and general + polishing across all modules. + + + diff --git a/README b/README index 66a580fa19..c837afaf92 100644 --- a/README +++ b/README @@ -1,31 +1,21 @@ -This is release 1.6 of Bro, a system for detecting network intruders in -real-time using passive network monitoring. +============================ +Bro Network Security Monitor +============================ -Please see the file INSTALL for installation instructions and -pointers for getting started. For more documentation, see the -documentation on Bro's home page: +Bro is a powerful framework for network analysis and security +monitoring. Please see the INSTALL file for installation instructions +and pointers for getting started. NEWS contains release notes for the +current version, and CHANGES has the complete history of changes. +Please see COPYING for licensing information. - http://www.bro-ids.org/docs +For more documentation, research publications, and community contact +information, please see Bro's home page: -The main parts of Bro's documentation are also available in the doc/ -directory of the distribution. (Please note that the documentation -is still a work in progress; there will be more in future releases.) + http://www.bro-ids.org -Numerous other Bro-related publications, including a paper describing the -system, can be found at - - http://www.bro-ids.org/publications.html - -Send comments, etc., to the Bro mailing list, bro@bro-ids.org. -However, please note that you must first subscribe to the list in -order to be able to post to it. - -- Vern Paxson & Robin Sommer, on behalf of the Bro development team +On behalf of the Bro Development Team, +Vern Paxson & Robin Sommer, +International Computer Science Institute & Lawrence Berkeley National Laboratory -University of California, Berkeley USA - -ICSI Center for Internet Research (ICIR) -International Computer Science Institute -Berkeley, CA USA vern@icir.org / robin@icir.org diff --git a/VERSION b/VERSION index 89d00dee1a..ad5d9a37c3 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.6-dev-1120 +2.0-301 diff --git a/aux/binpac b/aux/binpac index a3a9410ded..71c37019bc 160000 --- a/aux/binpac +++ b/aux/binpac @@ -1 +1 @@ -Subproject commit a3a9410dedc842f6bb9859642f334ed354633b57 +Subproject commit 71c37019bc371eb7863fb6aa47a7daa4540f4f1f diff --git a/aux/bro-aux b/aux/bro-aux index d68b98bb99..d885987e79 160000 --- a/aux/bro-aux +++ b/aux/bro-aux @@ -1 +1 @@ -Subproject commit d68b98bb995a105b257f805ec4ff22c4929c7476 +Subproject commit d885987e7968669e34504b0403ac89bd13928e9a diff --git a/aux/broccoli b/aux/broccoli index 743f10dda8..bead1168ae 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 743f10dda8cd5655ea3dc6eb705ff5414ed4f535 +Subproject commit bead1168ae9c2d2ae216dd58522fbc05498ff2c8 diff --git a/aux/broctl b/aux/broctl index cf4ce9dfc5..44cc3de5f6 160000 --- a/aux/broctl +++ b/aux/broctl @@ -1 +1 @@ -Subproject commit cf4ce9dfc5d6dc4e6d311955eeaec2d679e8669b +Subproject commit 44cc3de5f6f98a86b2516bdc48dd168e6a6a28fd diff --git a/aux/btest b/aux/btest index d1c620d98c..1897d224ce 160000 --- a/aux/btest +++ b/aux/btest @@ -1 +1 @@ -Subproject commit d1c620d98ce9d9c0b203314108b413784965d2ed +Subproject commit 1897d224ce295e91d20e458851759c99734a0a74 diff --git a/cmake b/cmake new file mode 160000 index 0000000000..49278736c1 --- /dev/null +++ b/cmake @@ -0,0 +1 @@ +Subproject commit 49278736c1404cb8c077272b80312c947e68bf52 diff --git a/cmake/ChangeMacInstallNames.cmake b/cmake/ChangeMacInstallNames.cmake deleted file mode 100644 index 1e7370d3e7..0000000000 --- a/cmake/ChangeMacInstallNames.cmake +++ /dev/null @@ -1,87 +0,0 @@ -# Calling this macro with the name of a list variable will modify that -# list such that any third party libraries that do not come with a -# vanilla Mac OS X system will be replaced by an adjusted library that -# has an install_name relative to the location of any executable that -# links to it. -# -# Also, it will schedule the modified libraries for installation in a -# 'support_libs' subdirectory of the CMAKE_INSTALL_PREFIX. -# -# The case of third party libraries depending on other third party -# libraries is currently not handled by this macro. -# -# Ex. -# -# set(libs /usr/lib/libz.dylib -# /usr/lib/libssl.dylib -# /usr/local/lib/libmagic.dylib -# /usr/local/lib/libGeoIP.dylib -# /usr/local/lib/somestaticlib.a) -# -# include(ChangeMacInstallNames) -# ChangeMacInstallNames(libs) -# -# Should result in ${libs} containing: -# /usr/lib/libz.dylib -# /usr/lib/libssl.dylib -# ${CMAKE_BINARY_DIR}/darwin_support_libs/libmagic.dylib -# ${CMAKE_BINARY_DIR}/darwin_support_libs/libGeoIP.dylib -# /usr/local/lib/somestaticlib.a -# -# such that we can now do: -# -# add_executable(some_exe ${srcs}) -# target_link_libraries(some_exe ${libs}) -# -# Any binary packages created from such a build should be self-contained -# and provide working installs on vanilla OS X systems. - -macro(ChangeMacInstallNames libListVar) - if (APPLE) - find_program(INSTALL_NAME_TOOL install_name_tool) - - set(MAC_INSTALL_NAME_DEPS) - set(SUPPORT_BIN_DIR ${CMAKE_BINARY_DIR}/darwin_support_libs) - set(SUPPORT_INSTALL_DIR support_libs) - - file(MAKE_DIRECTORY ${SUPPORT_BIN_DIR}) - - foreach (_lib ${${libListVar}}) - # only care about install_name for shared libraries that are - # not shipped in Apple's vanilla OS X installs - string(REGEX MATCH ^/usr/lib/* apple_provided_lib ${_lib}) - string(REGEX MATCH dylib$ is_shared_lib ${_lib}) - - if (NOT apple_provided_lib AND is_shared_lib) - get_filename_component(_libname ${_lib} NAME) - set(_adjustedLib ${SUPPORT_BIN_DIR}/${_libname}) - set(_tmpLib - ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/${_libname}) - - # make a tempory copy so we can adjust permissions - configure_file(${_lib} ${_tmpLib} COPYONLY) - - # copy to build directory with correct write permissions - file(COPY ${_tmpLib} - DESTINATION ${SUPPORT_BIN_DIR} - FILE_PERMISSIONS OWNER_READ OWNER_WRITE - GROUP_READ WORLD_READ) - - # remove the old library from the list provided as macro - # argument and add the new library with modified install_name - list(REMOVE_ITEM ${libListVar} ${_lib}) - list(APPEND ${libListVar} ${_adjustedLib}) - - # update the install target to install the third party libs - # with modified install_name - install(FILES ${_adjustedLib} - DESTINATION ${SUPPORT_INSTALL_DIR}) - - # perform the install_name change - execute_process(COMMAND install_name_tool -id - @executable_path/../${SUPPORT_INSTALL_DIR}/${_libname} - ${_adjustedLib}) - endif () - endforeach () - endif () -endmacro() diff --git a/cmake/CheckFunctions.cmake b/cmake/CheckFunctions.cmake deleted file mode 100644 index e378ef237b..0000000000 --- a/cmake/CheckFunctions.cmake +++ /dev/null @@ -1,12 +0,0 @@ -include(CheckFunctionExists) - -check_function_exists(getopt_long HAVE_GETOPT_LONG) -check_function_exists(mallinfo HAVE_MALLINFO) -check_function_exists(strcasestr HAVE_STRCASESTR) -check_function_exists(strerror HAVE_STRERROR) -check_function_exists(strsep HAVE_STRSEP) -check_function_exists(sigset HAVE_SIGSET) - -if (NOT HAVE_SIGSET) - check_function_exists(sigaction HAVE_SIGACTION) -endif () diff --git a/cmake/CheckHeaders.cmake b/cmake/CheckHeaders.cmake deleted file mode 100644 index ff206679d2..0000000000 --- a/cmake/CheckHeaders.cmake +++ /dev/null @@ -1,28 +0,0 @@ -include(CheckIncludeFiles) -include(CheckStructHasMember) - -check_include_files(getopt.h HAVE_GETOPT_H) -check_include_files(magic.h HAVE_MAGIC_H) -check_include_files(memory.h HAVE_MEMORY_H) -check_include_files("sys/socket.h;netinet/in.h;net/if.h;netinet/if_ether.h" - HAVE_NETINET_IF_ETHER_H) -check_include_files("sys/socket.h;netinet/in.h;net/if.h;netinet/ip6.h" - HAVE_NETINET_IP6_H) -check_include_files("sys/socket.h;net/if.h;net/ethernet.h" HAVE_NET_ETHERNET_H) -check_include_files(sys/ethernet.h HAVE_SYS_ETHERNET_H) -check_include_files(sys/time.h HAVE_SYS_TIME_H) -check_include_files("time.h;sys/time.h" TIME_WITH_SYS_TIME) -check_include_files(os-proto.h HAVE_OS_PROTO_H) - -check_struct_has_member(HISTORY_STATE entries "stdio.h;readline/readline.h" - HAVE_READLINE_HISTORY_ENTRIES) -check_include_files("stdio.h;readline/readline.h" HAVE_READLINE_READLINE_H) -check_include_files("stdio.h;readline/history.h" HAVE_READLINE_HISTORY_H) - -if (HAVE_READLINE_READLINE_H AND - HAVE_READLINE_HISTORY_H AND - HAVE_READLINE_HISTORY_ENTRIES) - set(HAVE_READLINE true) -endif () - -check_struct_has_member("struct sockaddr_in" sin_len "netinet/in.h" SIN_LEN) diff --git a/cmake/CheckNameserCompat.cmake b/cmake/CheckNameserCompat.cmake deleted file mode 100644 index 1a71411f1b..0000000000 --- a/cmake/CheckNameserCompat.cmake +++ /dev/null @@ -1,21 +0,0 @@ -include(CheckCSourceCompiles) - -# Check whether the namser compatibility header is required -# This can be the case on the Darwin platform - -check_c_source_compiles(" - #include - int main() { HEADER *hdr; int d = NS_IN6ADDRSZ; return 0; }" - have_nameser_header) - -if (NOT have_nameser_header) - check_c_source_compiles(" - #include - #include - int main() { HEADER *hdr; int d = NS_IN6ADDRSZ; return 0; }" - NEED_NAMESER_COMPAT_H) - if (NOT NEED_NAMESER_COMPAT_H) - message(FATAL_ERROR - "Asynchronous DNS support compatibility check failed.") - endif () -endif () diff --git a/cmake/CheckOptionalBuildSources.cmake b/cmake/CheckOptionalBuildSources.cmake deleted file mode 100644 index f901d432f6..0000000000 --- a/cmake/CheckOptionalBuildSources.cmake +++ /dev/null @@ -1,21 +0,0 @@ -# A macro that checks whether optional sources exist and if they do, they -# are added to the build/install process, else a warning is issued -# -# _dir: the subdir of the current source dir in which the optional -# sources are located -# _packageName: a string that identifies the package -# _varName: name of the variable indicating whether package is scheduled -# to be installed - -macro(CheckOptionalBuildSources _dir _packageName _varName) - if (${_varName}) - if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${_dir}/CMakeLists.txt) - add_subdirectory(${_dir}) - else () - message(WARNING "${_packageName} source code does not exist in " - "${CMAKE_CURRENT_SOURCE_DIR}/${_dir} " - "so it will not be built or installed") - set(${_varName} false) - endif () - endif () -endmacro(CheckOptionalBuildSources) diff --git a/cmake/CheckTypes.cmake b/cmake/CheckTypes.cmake deleted file mode 100644 index 1fab29e3f8..0000000000 --- a/cmake/CheckTypes.cmake +++ /dev/null @@ -1,31 +0,0 @@ -include(CheckTypeSize) - -check_type_size("long int" SIZEOF_LONG_INT) -check_type_size("long long" SIZEOF_LONG_LONG) -check_type_size("void *" SIZEOF_VOID_P) - -# checks existence of ${_type}, and if it does not, sets CMake variable ${_var} -# to alternative type, ${_alt_type} -macro(CheckType _type _alt_type _var) - # don't perform check if we have a result from a previous CMake run - if (NOT HAVE_${_var}) - check_type_size(${_type} ${_var}) - if (NOT ${_var}) - set(${_var} ${_alt_type}) - else () - unset(${_var}) - unset(${_var} CACHE) - endif () - endif () -endmacro(CheckType _type _alt_type _var) - -set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h) -CheckType(int32_t int int32_t) -CheckType(u_int32_t u_int u_int32_t) -CheckType(u_int16_t u_short u_int16_t) -CheckType(u_int8_t u_char u_int8_t) -set(CMAKE_EXTRA_INCLUDE_FILES) - -set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) -CheckType(socklen_t int socklen_t) -set(CMAKE_EXTRA_INCLUDE_FILES) diff --git a/cmake/ConfigurePackaging.cmake b/cmake/ConfigurePackaging.cmake deleted file mode 100644 index 6d7cb3d76f..0000000000 --- a/cmake/ConfigurePackaging.cmake +++ /dev/null @@ -1,238 +0,0 @@ -# A collection of macros to assist in configuring CMake/Cpack -# source and binary packaging - -# Sets CPack version variables by splitting the first macro argument -# using "." as a delimiter. If the length of the split list is -# greater than 2, all remaining elements are tacked on to the patch -# level version. Not that the version set by the macro is internal -# to binary packaging, the file name of our package will reflect the -# exact version number. -macro(SetPackageVersion _version) - string(REPLACE "." " " version_numbers ${_version}) - separate_arguments(version_numbers) - - list(GET version_numbers 0 CPACK_PACKAGE_VERSION_MAJOR) - list(REMOVE_AT version_numbers 0) - list(GET version_numbers 0 CPACK_PACKAGE_VERSION_MINOR) - list(REMOVE_AT version_numbers 0) - list(LENGTH version_numbers version_length) - - while (version_length GREATER 0) - list(GET version_numbers 0 patch_level) - if (CPACK_PACKAGE_VERSION_PATCH) - set(CPACK_PACKAGE_VERSION_PATCH - "${CPACK_PACKAGE_VERSION_PATCH}.${patch_level}") - else () - set(CPACK_PACKAGE_VERSION_PATCH ${patch_level}) - endif () - list(REMOVE_AT version_numbers 0) - list(LENGTH version_numbers version_length) - endwhile () - - if (APPLE) - # Mac PackageMaker package requires only numbers in the versioning - string(REGEX REPLACE "[_a-zA-Z-]" "" CPACK_PACKAGE_VERSION_MAJOR - ${CPACK_PACKAGE_VERSION_MAJOR}) - string(REGEX REPLACE "[_a-zA-Z-]" "" CPACK_PACKAGE_VERSION_MINOR - ${CPACK_PACKAGE_VERSION_MINOR}) - if (CPACK_PACKAGE_VERSION_PATCH) - string(REGEX REPLACE "[_a-zA-Z-]" "" CPACK_PACKAGE_VERSION_PATCH - ${CPACK_PACKAGE_VERSION_PATCH}) - endif () - endif () - - if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - # RPM version accepts letters, but not dashes. - string(REGEX REPLACE "[-]" "" CPACK_PACKAGE_VERSION_MAJOR - ${CPACK_PACKAGE_VERSION_MAJOR}) - string(REGEX REPLACE "[-]" "" CPACK_PACKAGE_VERSION_MINOR - ${CPACK_PACKAGE_VERSION_MINOR}) - if (CPACK_PACKAGE_VERSION_PATCH) - string(REGEX REPLACE "[-]" "" CPACK_PACKAGE_VERSION_PATCH - ${CPACK_PACKAGE_VERSION_PATCH}) - endif () - endif () - - # Minimum supported OS X version - set(CPACK_OSX_PACKAGE_VERSION 10.5) -endmacro(SetPackageVersion) - -# Sets the list of desired package types to be created by the make -# package target. A .tar.gz is only made for source packages, and -# binary pacakage format depends on the operating system: -# -# Darwin - PackageMaker -# Linux - RPM if the platform has rpmbuild installed -# DEB if the platform has dpkg-shlibdeps installed -# -# CPACK_GENERATOR is set by this macro -# CPACK_SOURCE_GENERATOR is set by this macro -macro(SetPackageGenerators) - set(CPACK_SOURCE_GENERATOR TGZ) - #set(CPACK_GENERATOR TGZ) - if (APPLE) - list(APPEND CPACK_GENERATOR PackageMaker) - elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - find_program(RPMBUILD_EXE rpmbuild) - find_program(DPKGSHLIB_EXE dpkg-shlibdeps) - if (RPMBUILD_EXE) - set(CPACK_GENERATOR ${CPACK_GENERATOR} RPM) - endif () - if (DPKGSHLIB_EXE) - set(CPACK_GENERATOR ${CPACK_GENERATOR} DEB) - set(CPACK_DEBIAN_PACKAGE_SHLIBDEPS true) - endif () - endif () -endmacro(SetPackageGenerators) - -# Sets CPACK_PACKAGE_FILE_NAME in the following format: -# -# --- -# -# and CPACK_SOURCE_PACKAGE_FILE_NAME as: -# -# - -macro(SetPackageFileName _version) - if (PACKAGE_NAME_PREFIX) - set(CPACK_PACKAGE_FILE_NAME "${PACKAGE_NAME_PREFIX}-${_version}") - set(CPACK_SOURCE_PACKAGE_FILE_NAME "${PACKAGE_NAME_PREFIX}-${_version}") - else () - set(CPACK_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${_version}") - set(CPACK_SOURCE_PACKAGE_FILE_NAME "${CMAKE_PROJECT_NAME}-${_version}") - endif () - - set(CPACK_PACKAGE_FILE_NAME - "${CPACK_PACKAGE_FILE_NAME}-${CMAKE_SYSTEM_NAME}") - - if (APPLE) - # Only Intel-based Macs are supported. CMAKE_SYSTEM_PROCESSOR may - # return the confusing 'i386' if running a 32-bit kernel, but chances - # are the binary is x86_64 (or more generally 'Intel') compatible. - set(arch "Intel") - else () - set (arch ${CMAKE_SYSTEM_PROCESSOR}) - endif () - - set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_FILE_NAME}-${arch}") -endmacro(SetPackageFileName) - -# Sets up binary package metadata -macro(SetPackageMetadata) - set(CPACK_PACKAGE_VENDOR "Lawrence Berkeley National Laboratory") - set(CPACK_PACKAGE_CONTACT "info@bro-ids.org") - set(CPACK_PACKAGE_DESCRIPTION_SUMMARY - "The Bro Network Intrusion Detection System") - - # CPack may enforce file name extensions for certain package generators - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README - ${CMAKE_CURRENT_BINARY_DIR}/README.txt - COPYONLY) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/COPYING - ${CMAKE_CURRENT_BINARY_DIR}/COPYING.txt - COPYONLY) - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake/MAC_PACKAGE_INTRO - ${CMAKE_CURRENT_BINARY_DIR}/MAC_PACKAGE_INTRO.txt) - - set(CPACK_PACKAGE_DESCRIPTION_FILE ${CMAKE_CURRENT_BINARY_DIR}/README.txt) - set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_BINARY_DIR}/COPYING.txt) - set(CPACK_RESOURCE_FILE_README ${CMAKE_CURRENT_BINARY_DIR}/README.txt) - set(CPACK_RESOURCE_FILE_WELCOME - ${CMAKE_CURRENT_BINARY_DIR}/MAC_PACKAGE_INTRO.txt) - - set(CPACK_RPM_PACKAGE_LICENSE "BSD") -endmacro(SetPackageMetadata) - -# Sets pre and post install scripts for PackageMaker packages. -# The main functionality that such scripts offer is a way to make backups -# of "configuration" files that a user may have modified. -# Note that RPMs already have a robust mechanism for dealing with -# user-modified files, so we do not need this additional functionality -macro(SetPackageInstallScripts VERSION) - - if (INSTALLED_CONFIG_FILES) - # Remove duplicates from the list of installed config files - separate_arguments(INSTALLED_CONFIG_FILES) - list(REMOVE_DUPLICATES INSTALLED_CONFIG_FILES) - # Space delimit the list again - foreach (_file ${INSTALLED_CONFIG_FILES}) - set(_tmp "${_tmp} ${_file}") - endforeach () - set(INSTALLED_CONFIG_FILES "${_tmp}" CACHE STRING "" FORCE) - endif () - - if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - # DEB packages can automatically handle configuration files - # if provided in a "conffiles" file in the packaging - set(conffiles_file ${CMAKE_CURRENT_BINARY_DIR}/conffiles) - if (INSTALLED_CONFIG_FILES) - string(REPLACE " " ";" conffiles ${INSTALLED_CONFIG_FILES}) - endif () - file(WRITE ${conffiles_file} "") - foreach (_file ${conffiles}) - file(APPEND ${conffiles_file} "${_file}\n") - endforeach () - - list(APPEND CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA - ${CMAKE_CURRENT_BINARY_DIR}/conffiles) - - # RPMs don't need any explicit direction regarding config files. - - # Leaving the set of installed config files empty will just - # bypass the logic in the default pre/post install scripts and let - # the RPMs/DEBs do their own thing (regarding backups, etc.) - # when upgrading packages. - set(INSTALLED_CONFIG_FILES "") - endif () - - if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_preinstall.sh.in) - configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_preinstall.sh.in - ${CMAKE_CURRENT_BINARY_DIR}/package_preinstall.sh - @ONLY) - configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_preinstall.sh.in - ${CMAKE_CURRENT_BINARY_DIR}/preinst - @ONLY) - set(CPACK_PREFLIGHT_SCRIPT - ${CMAKE_CURRENT_BINARY_DIR}/package_preinstall.sh) - set(CPACK_RPM_PRE_INSTALL_SCRIPT_FILE - ${CMAKE_CURRENT_BINARY_DIR}/package_preinstall.sh) - list(APPEND CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA - ${CMAKE_CURRENT_BINARY_DIR}/preinst) - endif () - - if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_postupgrade.sh.in) - configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_postupgrade.sh.in - ${CMAKE_CURRENT_BINARY_DIR}/package_postupgrade.sh - @ONLY) - configure_file( - ${CMAKE_CURRENT_SOURCE_DIR}/cmake/package_postupgrade.sh.in - ${CMAKE_CURRENT_BINARY_DIR}/postinst - @ONLY) - set(CPACK_POSTUPGRADE_SCRIPT - ${CMAKE_CURRENT_BINARY_DIR}/package_postupgrade.sh) - set(CPACK_RPM_POST_INSTALL_SCRIPT_FILE - ${CMAKE_CURRENT_BINARY_DIR}/package_postupgrade.sh) - list(APPEND CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA - ${CMAKE_CURRENT_BINARY_DIR}/postinst) - endif () -endmacro(SetPackageInstallScripts) - -# Main macro to configure all the packaging options -macro(ConfigurePackaging _version) - SetPackageVersion(${_version}) - SetPackageGenerators() - SetPackageFileName(${_version}) - SetPackageMetadata() - SetPackageInstallScripts(${_version}) - - set(CPACK_SET_DESTDIR true) - set(CPACK_PACKAGING_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) - - # add default files/directories to ignore for source package - # user may specify others via configure script - list(APPEND CPACK_SOURCE_IGNORE_FILES ${CMAKE_BINARY_DIR} ".git") - - include(CPack) -endmacro(ConfigurePackaging) diff --git a/cmake/FindBIND.cmake b/cmake/FindBIND.cmake deleted file mode 100644 index 4cbc481ae6..0000000000 --- a/cmake/FindBIND.cmake +++ /dev/null @@ -1,101 +0,0 @@ -# - Try to find libpcap include dirs and libraries -# -# Usage of this module as follows: -# -# find_package(BIND) -# -# Variables used by this module, they can change the default behaviour and need -# to be set before calling find_package: -# -# BIND_ROOT_DIR Set this variable to the root installation of BIND -# if the module has problems finding the proper -# installation path. -# -# Variables defined by this module: -# -# BIND_FOUND System has BIND, include and library dirs found -# BIND_INCLUDE_DIR The BIND include directories. -# BIND_LIBRARY The BIND library (if any) required for -# ns_inittab and res_mkquery symbols - -find_path(BIND_ROOT_DIR - NAMES include/resolv.h -) - -find_path(BIND_INCLUDE_DIR - NAMES resolv.h - HINTS ${BIND_ROOT_DIR}/include -) - -if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - # the static resolv library is preferred because - # on some systems, the ns_initparse symbol is not - # exported in the shared library (strangely) - # see http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=291609 - set(bind_libs none libresolv.a resolv bind) -else () - set(bind_libs none resolv bind) -endif () - -include(CheckCSourceCompiles) - -# Find which library has the res_mkquery and ns_initparse symbols -set(CMAKE_REQUIRED_INCLUDES ${BIND_INCLUDE_DIR}) -foreach (bindlib ${bind_libs}) - if (NOT ${bindlib} MATCHES "none") - find_library(BIND_LIBRARY - NAMES ${bindlib} - HINTS ${BIND_ROOT_DIR}/lib - ) - endif () - - set(CMAKE_REQUIRED_LIBRARIES ${BIND_LIBRARY}) - - check_c_source_compiles(" - #include - int main() { - ns_initparse(0, 0, 0); - return 0; - } -" ns_initparse_works_${bindlib}) - - check_c_source_compiles(" - #include - #include - #include - #include - #include - int main() { - int (*p)() = res_mkquery; - } -" res_mkquery_works_${bindlib}) - - set(CMAKE_REQUIRED_LIBRARIES) - - if (ns_initparse_works_${bindlib} AND res_mkquery_works_${bindlib}) - break () - else () - set(BIND_LIBRARY BIND_LIBRARY-NOTFOUND) - endif () -endforeach () -set(CMAKE_REQUIRED_INCLUDES) - -include(FindPackageHandleStandardArgs) - -if (ns_initparse_works_none AND res_mkquery_works_none) - # system does not require linking to a BIND library - find_package_handle_standard_args(BIND DEFAULT_MSG - BIND_INCLUDE_DIR - ) -else () - find_package_handle_standard_args(BIND DEFAULT_MSG - BIND_LIBRARY - BIND_INCLUDE_DIR - ) -endif () - -mark_as_advanced( - BIND_ROOT_DIR - BIND_LIBRARY - BIND_INCLUDE_DIR -) diff --git a/cmake/FindBISON.cmake b/cmake/FindBISON.cmake deleted file mode 100644 index 3f6d11d04f..0000000000 --- a/cmake/FindBISON.cmake +++ /dev/null @@ -1,221 +0,0 @@ -# - Find bison executable and provides macros to generate custom build rules -# The module defines the following variables: -# -# BISON_EXECUTABLE - path to the bison program -# BISON_VERSION - version of bison -# BISON_FOUND - true if the program was found -# -# If bison is found, the module defines the macros: -# BISON_TARGET( [VERBOSE ] -# [COMPILE_FLAGS ] [HEADER ]) -# which will create a custom rule to generate a parser. is -# the path to a yacc file. is the name of the source file -# generated by bison. A header file containing the token list is also -# generated according to bison's -d option by default or if the HEADER -# option is used, the argument is passed to bison's --defines option to -# specify output file. If COMPILE_FLAGS option is specified, the next -# parameter is added in the bison command line. if VERBOSE option is -# specified, is created and contains verbose descriptions of the -# grammar and parser. The macro defines a set of variables: -# BISON_${Name}_DEFINED - true is the macro ran successfully -# BISON_${Name}_INPUT - The input source file, an alias for -# BISON_${Name}_OUTPUT_SOURCE - The source file generated by bison -# BISON_${Name}_OUTPUT_HEADER - The header file generated by bison -# BISON_${Name}_OUTPUTS - The sources files generated by bison -# BISON_${Name}_COMPILE_FLAGS - Options used in the bison command line -# -# ==================================================================== -# Example: -# -# find_package(BISON) -# BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp) -# add_executable(Foo main.cpp ${BISON_MyParser_OUTPUTS}) -# ==================================================================== - -#============================================================================= -# Copyright 2009 Kitware, Inc. -# Copyright 2006 Tristan Carel -# Modified 2010 by Jon Siwek, adding HEADER option -# -# Distributed under the OSI-approved BSD License (the "License"): -# CMake - Cross Platform Makefile Generator -# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium -# All rights reserved. - -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# * Neither the names of Kitware, Inc., the Insight Software Consortium, -# nor the names of their contributors may be used to endorse or promote -# products derived from this software without specific prior written -# permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= - -FIND_PROGRAM(BISON_EXECUTABLE bison DOC "path to the bison executable") -MARK_AS_ADVANCED(BISON_EXECUTABLE) - -IF(BISON_EXECUTABLE) - - EXECUTE_PROCESS(COMMAND ${BISON_EXECUTABLE} --version - OUTPUT_VARIABLE BISON_version_output - ERROR_VARIABLE BISON_version_error - RESULT_VARIABLE BISON_version_result - OUTPUT_STRIP_TRAILING_WHITESPACE) - IF(NOT ${BISON_version_result} EQUAL 0) - MESSAGE(SEND_ERROR "Command \"${BISON_EXECUTABLE} --version\" failed with output:\n${BISON_version_error}") - ELSE() - STRING(REGEX REPLACE "^bison \\(GNU Bison\\) ([^\n]+)\n.*" "\\1" - BISON_VERSION "${BISON_version_output}") - ENDIF() - - # internal macro - MACRO(BISON_TARGET_option_verbose Name BisonOutput filename) - LIST(APPEND BISON_TARGET_cmdopt "--verbose") - GET_FILENAME_COMPONENT(BISON_TARGET_output_path "${BisonOutput}" PATH) - GET_FILENAME_COMPONENT(BISON_TARGET_output_name "${BisonOutput}" NAME_WE) - ADD_CUSTOM_COMMAND(OUTPUT ${filename} - COMMAND ${CMAKE_COMMAND} - ARGS -E copy - "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output" - "${filename}" - DEPENDS - "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output" - COMMENT "[BISON][${Name}] Copying bison verbose table to ${filename}" - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) - SET(BISON_${Name}_VERBOSE_FILE ${filename}) - LIST(APPEND BISON_TARGET_extraoutputs - "${BISON_TARGET_output_path}/${BISON_TARGET_output_name}.output") - ENDMACRO(BISON_TARGET_option_verbose) - - # internal macro - MACRO(BISON_TARGET_option_extraopts Options) - SET(BISON_TARGET_extraopts "${Options}") - SEPARATE_ARGUMENTS(BISON_TARGET_extraopts) - LIST(APPEND BISON_TARGET_cmdopt ${BISON_TARGET_extraopts}) - ENDMACRO(BISON_TARGET_option_extraopts) - - #============================================================ - # BISON_TARGET (public macro) - #============================================================ - # - MACRO(BISON_TARGET Name BisonInput BisonOutput) - SET(BISON_TARGET_output_header "") - #SET(BISON_TARGET_command_opt "") - SET(BISON_TARGET_cmdopt "") - SET(BISON_TARGET_outputs "${BisonOutput}") - IF(NOT ${ARGC} EQUAL 3 AND - NOT ${ARGC} EQUAL 5 AND - NOT ${ARGC} EQUAL 7 AND - NOT ${ARGC} EQUAL 9) - MESSAGE(SEND_ERROR "Usage") - ELSE() - # Parsing parameters - IF(${ARGC} GREATER 5 OR ${ARGC} EQUAL 5) - IF("${ARGV3}" STREQUAL "VERBOSE") - BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${ARGV4}") - ENDIF() - IF("${ARGV3}" STREQUAL "COMPILE_FLAGS") - BISON_TARGET_option_extraopts("${ARGV4}") - ENDIF() - IF("${ARGV3}" STREQUAL "HEADER") - set(BISON_TARGET_output_header "${ARGV4}") - ENDIF() - ENDIF() - - IF(${ARGC} GREATER 7 OR ${ARGC} EQUAL 7) - IF("${ARGV5}" STREQUAL "VERBOSE") - BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${ARGV6}") - ENDIF() - - IF("${ARGV5}" STREQUAL "COMPILE_FLAGS") - BISON_TARGET_option_extraopts("${ARGV6}") - ENDIF() - - IF("${ARGV5}" STREQUAL "HEADER") - set(BISON_TARGET_output_header "${ARGV6}") - ENDIF() - ENDIF() - - IF(${ARGC} EQUAL 9) - IF("${ARGV7}" STREQUAL "VERBOSE") - BISON_TARGET_option_verbose(${Name} ${BisonOutput} "${ARGV8}") - ENDIF() - - IF("${ARGV7}" STREQUAL "COMPILE_FLAGS") - BISON_TARGET_option_extraopts("${ARGV8}") - ENDIF() - - IF("${ARGV7}" STREQUAL "HEADER") - set(BISON_TARGET_output_header "${ARGV8}") - ENDIF() - ENDIF() - - IF(BISON_TARGET_output_header) - # Header's name passed in as argument to be used in --defines option - LIST(APPEND BISON_TARGET_cmdopt - "--defines=${BISON_TARGET_output_header}") - set(BISON_${Name}_OUTPUT_HEADER ${BISON_TARGET_output_header}) - ELSE() - # Header's name generated by bison (see option -d) - LIST(APPEND BISON_TARGET_cmdopt "-d") - STRING(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\2" _fileext "${ARGV2}") - STRING(REPLACE "c" "h" _fileext ${_fileext}) - STRING(REGEX REPLACE "^(.*)(\\.[^.]*)$" "\\1${_fileext}" - BISON_${Name}_OUTPUT_HEADER "${ARGV2}") - ENDIF() - - LIST(APPEND BISON_TARGET_outputs "${BISON_${Name}_OUTPUT_HEADER}") - - ADD_CUSTOM_COMMAND(OUTPUT ${BISON_TARGET_outputs} - ${BISON_TARGET_extraoutputs} - COMMAND ${BISON_EXECUTABLE} - ARGS ${BISON_TARGET_cmdopt} -o ${ARGV2} ${ARGV1} - DEPENDS ${ARGV1} - COMMENT "[BISON][${Name}] Building parser with bison ${BISON_VERSION}" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - - # define target variables - SET(BISON_${Name}_DEFINED TRUE) - SET(BISON_${Name}_INPUT ${ARGV1}) - SET(BISON_${Name}_OUTPUTS ${BISON_TARGET_outputs}) - SET(BISON_${Name}_COMPILE_FLAGS ${BISON_TARGET_cmdopt}) - SET(BISON_${Name}_OUTPUT_SOURCE "${BisonOutput}") - - ENDIF(NOT ${ARGC} EQUAL 3 AND - NOT ${ARGC} EQUAL 5 AND - NOT ${ARGC} EQUAL 7 AND - NOT ${ARGC} EQUAL 9) - ENDMACRO(BISON_TARGET) - # - #============================================================ - -ENDIF(BISON_EXECUTABLE) - -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(BISON DEFAULT_MSG BISON_EXECUTABLE) - -# FindBISON.cmake ends here diff --git a/cmake/FindBinPAC.cmake b/cmake/FindBinPAC.cmake deleted file mode 100644 index 5cd1697bb3..0000000000 --- a/cmake/FindBinPAC.cmake +++ /dev/null @@ -1,53 +0,0 @@ -# - Try to find BinPAC binary and library -# -# Usage of this module as follows: -# -# find_package(BinPAC) -# -# Variables used by this module, they can change the default behaviour and need -# to be set before calling find_package: -# -# BinPAC_ROOT_DIR Set this variable to the root installation of -# BinPAC if the module has problems finding the -# proper installation path. -# -# Variables defined by this module: -# -# BINPAC_FOUND System has BinPAC binary and library -# BinPAC_EXE The binpac executable -# BinPAC_LIBRARY The libbinpac.a library -# BinPAC_INCLUDE_DIR The binpac headers - -# look for BinPAC in standard locations or user-provided root -find_path(BinPAC_ROOT_DIR - NAMES include/binpac.h -) - -find_file(BinPAC_EXE - NAMES binpac - HINTS ${BinPAC_ROOT_DIR}/bin -) - -find_library(BinPAC_LIBRARY - NAMES libbinpac.a - HINTS ${BinPAC_ROOT_DIR}/lib -) - -find_path(BinPAC_INCLUDE_DIR - NAMES binpac.h - HINTS ${BinPAC_ROOT_DIR}/include -) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(BinPAC DEFAULT_MSG - BinPAC_EXE - BinPAC_LIBRARY - BinPAC_INCLUDE_DIR -) - -mark_as_advanced( - BinPAC_ROOT_DIR - BinPAC_EXE - BinPAC_LIBRARY - BinPAC_INCLUDE_DIR -) diff --git a/cmake/FindFLEX.cmake b/cmake/FindFLEX.cmake deleted file mode 100644 index c56e8edad8..0000000000 --- a/cmake/FindFLEX.cmake +++ /dev/null @@ -1,179 +0,0 @@ -# - Find flex executable and provides a macro to generate custom build rules -# -# The module defines the following variables: -# FLEX_FOUND - true is flex executable is found -# FLEX_EXECUTABLE - the path to the flex executable -# FLEX_VERSION - the version of flex -# FLEX_LIBRARIES - The flex libraries -# -# The minimum required version of flex can be specified using the -# standard syntax, e.g. FIND_PACKAGE(FLEX 2.5.13) -# -# -# If flex is found on the system, the module provides the macro: -# FLEX_TARGET(Name FlexInput FlexOutput [COMPILE_FLAGS ]) -# which creates a custom command to generate the file from -# the file. If COMPILE_FLAGS option is specified, the next -# parameter is added to the flex command line. Name is an alias used to -# get details of this custom command. Indeed the macro defines the -# following variables: -# FLEX_${Name}_DEFINED - true is the macro ran successfully -# FLEX_${Name}_OUTPUTS - the source file generated by the custom rule, an -# alias for FlexOutput -# FLEX_${Name}_INPUT - the flex source file, an alias for ${FlexInput} -# -# Flex scanners oftenly use tokens defined by Bison: the code generated -# by Flex depends of the header generated by Bison. This module also -# defines a macro: -# ADD_FLEX_BISON_DEPENDENCY(FlexTarget BisonTarget) -# which adds the required dependency between a scanner and a parser -# where and are the first parameters of -# respectively FLEX_TARGET and BISON_TARGET macros. -# -# ==================================================================== -# Example: -# -# find_package(BISON) -# find_package(FLEX) -# -# BISON_TARGET(MyParser parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp -# FLEX_TARGET(MyScanner lexer.l ${CMAKE_CURRENT_BIANRY_DIR}/lexer.cpp) -# ADD_FLEX_BISON_DEPENDENCY(MyScanner MyParser) -# -# include_directories(${CMAKE_CURRENT_BINARY_DIR}) -# add_executable(Foo -# Foo.cc -# ${BISON_MyParser_OUTPUTS} -# ${FLEX_MyScanner_OUTPUTS} -# ) -# ==================================================================== - -#============================================================================= -# Copyright 2009 Kitware, Inc. -# Copyright 2006 Tristan Carel -# Modified 2010 by Jon Siwek, backporting for CMake 2.6 compat -# -# Distributed under the OSI-approved BSD License (the "License"): -# CMake - Cross Platform Makefile Generator -# Copyright 2000-2009 Kitware, Inc., Insight Software Consortium -# All rights reserved. - -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# * Neither the names of Kitware, Inc., the Insight Software Consortium, -# nor the names of their contributors may be used to endorse or promote -# products derived from this software without specific prior written -# permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# This software is distributed WITHOUT ANY WARRANTY; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -# See the License for more information. -#============================================================================= - -FIND_PROGRAM(FLEX_EXECUTABLE flex DOC "path to the flex executable") -MARK_AS_ADVANCED(FLEX_EXECUTABLE) - -FIND_LIBRARY(FL_LIBRARY NAMES fl - DOC "path to the fl library") -MARK_AS_ADVANCED(FL_LIBRARY) -SET(FLEX_LIBRARIES ${FL_LIBRARY}) - -IF(FLEX_EXECUTABLE) - - EXECUTE_PROCESS(COMMAND ${FLEX_EXECUTABLE} --version - OUTPUT_VARIABLE FLEX_version_output - ERROR_VARIABLE FLEX_version_error - RESULT_VARIABLE FLEX_version_result - OUTPUT_STRIP_TRAILING_WHITESPACE) - IF(NOT ${FLEX_version_result} EQUAL 0) - IF(FLEX_FIND_REQUIRED) - MESSAGE(SEND_ERROR "Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}") - ELSE() - MESSAGE("Command \"${FLEX_EXECUTABLE} --version\" failed with output:\n${FLEX_version_output}\n${FLEX_version_error}\nFLEX_VERSION will not be available") - ENDIF() - ELSE() - STRING(REGEX REPLACE "^flex (.*)$" "\\1" - FLEX_VERSION "${FLEX_version_output}") - ENDIF() - - #============================================================ - # FLEX_TARGET (public macro) - #============================================================ - # - MACRO(FLEX_TARGET Name Input Output) - SET(FLEX_TARGET_usage "FLEX_TARGET( [COMPILE_FLAGS ]") - IF(${ARGC} GREATER 3) - IF(${ARGC} EQUAL 5) - IF("${ARGV3}" STREQUAL "COMPILE_FLAGS") - SET(FLEX_EXECUTABLE_opts "${ARGV4}") - SEPARATE_ARGUMENTS(FLEX_EXECUTABLE_opts) - ELSE() - MESSAGE(SEND_ERROR ${FLEX_TARGET_usage}) - ENDIF() - ELSE() - MESSAGE(SEND_ERROR ${FLEX_TARGET_usage}) - ENDIF() - ENDIF() - - ADD_CUSTOM_COMMAND(OUTPUT ${Output} - COMMAND ${FLEX_EXECUTABLE} - ARGS ${FLEX_EXECUTABLE_opts} -o${Output} ${Input} - DEPENDS ${Input} - COMMENT "[FLEX][${Name}] Building scanner with flex ${FLEX_VERSION}" - WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) - - SET(FLEX_${Name}_DEFINED TRUE) - SET(FLEX_${Name}_OUTPUTS ${Output}) - SET(FLEX_${Name}_INPUT ${Input}) - SET(FLEX_${Name}_COMPILE_FLAGS ${FLEX_EXECUTABLE_opts}) - ENDMACRO(FLEX_TARGET) - #============================================================ - - - #============================================================ - # ADD_FLEX_BISON_DEPENDENCY (public macro) - #============================================================ - # - MACRO(ADD_FLEX_BISON_DEPENDENCY FlexTarget BisonTarget) - - IF(NOT FLEX_${FlexTarget}_OUTPUTS) - MESSAGE(SEND_ERROR "Flex target `${FlexTarget}' does not exists.") - ENDIF() - - IF(NOT BISON_${BisonTarget}_OUTPUT_HEADER) - MESSAGE(SEND_ERROR "Bison target `${BisonTarget}' does not exists.") - ENDIF() - - SET_SOURCE_FILES_PROPERTIES(${FLEX_${FlexTarget}_OUTPUTS} - PROPERTIES OBJECT_DEPENDS ${BISON_${BisonTarget}_OUTPUT_HEADER}) - ENDMACRO(ADD_FLEX_BISON_DEPENDENCY) - #============================================================ - -ENDIF(FLEX_EXECUTABLE) - -INCLUDE(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(FLEX FLEX_EXECUTABLE - FLEX_VERSION) - -# FindFLEX.cmake ends here diff --git a/cmake/FindGooglePerftools.cmake b/cmake/FindGooglePerftools.cmake deleted file mode 100644 index 7ddd5a532e..0000000000 --- a/cmake/FindGooglePerftools.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# - Try to find GooglePerftools headers and libraries -# -# Usage of this module as follows: -# -# find_package(GooglePerftools) -# -# Variables used by this module, they can change the default behaviour and need -# to be set before calling find_package: -# -# GooglePerftools_ROOT_DIR Set this variable to the root installation of -# GooglePerftools if the module has problems finding -# the proper installation path. -# -# Variables defined by this module: -# -# GOOGLEPERFTOOLS_FOUND System has GooglePerftools libs/headers -# GooglePerftools_LIBRARIES The GooglePerftools libraries -# GooglePerftools_INCLUDE_DIR The location of GooglePerftools headers - -find_path(GooglePerftools_ROOT_DIR - NAMES include/google/heap-profiler.h -) - -find_library(GooglePerftools_LIBRARIES - NAMES tcmalloc - HINTS ${GooglePerftools_ROOT_DIR}/lib -) - -find_path(GooglePerftools_INCLUDE_DIR - NAMES google/heap-profiler.h - HINTS ${GooglePerftools_ROOT_DIR}/include -) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(GooglePerftools DEFAULT_MSG - GooglePerftools_LIBRARIES - GooglePerftools_INCLUDE_DIR -) - -mark_as_advanced( - GooglePerftools_ROOT_DIR - GooglePerftools_LIBRARIES - GooglePerftools_INCLUDE_DIR -) diff --git a/cmake/FindLibGeoIP.cmake b/cmake/FindLibGeoIP.cmake deleted file mode 100644 index 618dba6463..0000000000 --- a/cmake/FindLibGeoIP.cmake +++ /dev/null @@ -1,52 +0,0 @@ -# - Try to find GeoIP headers and libraries -# -# Usage of this module as follows: -# -# find_package(LibGeoIP) -# -# Variables used by this module, they can change the default behaviour and need -# to be set before calling find_package: -# -# LibGeoIP_ROOT_DIR Set this variable to the root installation of -# libGeoIP if the module has problems finding the -# proper installation path. -# -# Variables defined by this module: -# -# LIBGEOIP_FOUND System has GeoIP libraries and headers -# LibGeoIP_LIBRARY The GeoIP library -# LibGeoIP_INCLUDE_DIR The location of GeoIP headers - -find_path(LibGeoIP_ROOT_DIR - NAMES include/GeoIPCity.h -) - -if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - # the static version of the library is preferred on OS X for the - # purposes of making packages (libGeoIP doesn't ship w/ OS X) - set(libgeoip_names libGeoIp.a GeoIP) -else () - set(libgeoip_names GeoIP) -endif () - -find_library(LibGeoIP_LIBRARY - NAMES ${libgeoip_names} - HINTS ${LibGeoIP_ROOT_DIR}/lib -) - -find_path(LibGeoIP_INCLUDE_DIR - NAMES GeoIPCity.h - HINTS ${LibGeoIP_ROOT_DIR}/include -) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(LibGeoIP DEFAULT_MSG - LibGeoIP_LIBRARY - LibGeoIP_INCLUDE_DIR -) - -mark_as_advanced( - LibGeoIP_ROOT_DIR - LibGeoIP_LIBRARY - LibGeoIP_INCLUDE_DIR -) diff --git a/cmake/FindLibMagic.cmake b/cmake/FindLibMagic.cmake deleted file mode 100644 index 23cc7efe39..0000000000 --- a/cmake/FindLibMagic.cmake +++ /dev/null @@ -1,52 +0,0 @@ -# - Try to find libmagic header and library -# -# Usage of this module as follows: -# -# find_package(LibMagic) -# -# Variables used by this module, they can change the default behaviour and need -# to be set before calling find_package: -# -# LibMagic_ROOT_DIR Set this variable to the root installation of -# libmagic if the module has problems finding the -# proper installation path. -# -# Variables defined by this module: -# -# LIBMAGIC_FOUND System has libmagic and magic.h -# LibMagic_LIBRARY The libmagic library -# LibMagic_INCLUDE_DIR The location of magic.h - -find_path(LibMagic_ROOT_DIR - NAMES include/magic.h -) - -if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - # the static version of the library is preferred on OS X for the - # purposes of making packages (libmagic doesn't ship w/ OS X) - set(libmagic_names libmagic.a magic) -else () - set(libmagic_names magic) -endif () - -find_library(LibMagic_LIBRARY - NAMES ${libmagic_names} - HINTS ${LibMagic_ROOT_DIR}/lib -) - -find_path(LibMagic_INCLUDE_DIR - NAMES magic.h - HINTS ${LibMagic_ROOT_DIR}/include -) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(LibMagic DEFAULT_MSG - LibMagic_LIBRARY - LibMagic_INCLUDE_DIR -) - -mark_as_advanced( - LibMagic_ROOT_DIR - LibMagic_LIBRARY - LibMagic_INCLUDE_DIR -) diff --git a/cmake/FindOpenSSL.cmake b/cmake/FindOpenSSL.cmake deleted file mode 100644 index 599a846f0a..0000000000 --- a/cmake/FindOpenSSL.cmake +++ /dev/null @@ -1,56 +0,0 @@ -# - Try to find openssl include dirs and libraries -# -# Usage of this module as follows: -# -# find_package(OpenSSL) -# -# Variables used by this module, they can change the default behaviour and need -# to be set before calling find_package: -# -# OpenSSL_ROOT_DIR Set this variable to the root installation of -# openssl if the module has problems finding the -# proper installation path. -# -# Variables defined by this module: -# -# OPENSSL_FOUND System has openssl, include and library dirs found -# OpenSSL_INCLUDE_DIR The openssl include directories. -# OpenSSL_LIBRARIES The openssl libraries. -# OpenSSL_CYRPTO_LIBRARY The openssl crypto library. -# OpenSSL_SSL_LIBRARY The openssl ssl library. - -find_path(OpenSSL_ROOT_DIR - NAMES include/openssl/ssl.h -) - -find_path(OpenSSL_INCLUDE_DIR - NAMES openssl/ssl.h - HINTS ${OpenSSL_ROOT_DIR}/include -) - -find_library(OpenSSL_SSL_LIBRARY - NAMES ssl ssleay32 ssleay32MD - HINTS ${OpenSSL_ROOT_DIR}/lib -) - -find_library(OpenSSL_CRYPTO_LIBRARY - NAMES crypto - HINTS ${OpenSSL_ROOT_DIR}/lib -) - -set(OpenSSL_LIBRARIES ${OpenSSL_SSL_LIBRARY} ${OpenSSL_CRYPTO_LIBRARY} - CACHE STRING "OpenSSL SSL and crypto libraries" FORCE) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(OpenSSL DEFAULT_MSG - OpenSSL_LIBRARIES - OpenSSL_INCLUDE_DIR -) - -mark_as_advanced( - OpenSSL_ROOT_DIR - OpenSSL_INCLUDE_DIR - OpenSSL_LIBRARIES - OpenSSL_CRYPTO_LIBRARY - OpenSSL_SSL_LIBRARY -) diff --git a/cmake/FindPCAP.cmake b/cmake/FindPCAP.cmake deleted file mode 100644 index 61ce602821..0000000000 --- a/cmake/FindPCAP.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# - Try to find libpcap include dirs and libraries -# -# Usage of this module as follows: -# -# find_package(PCAP) -# -# Variables used by this module, they can change the default behaviour and need -# to be set before calling find_package: -# -# PCAP_ROOT_DIR Set this variable to the root installation of -# libpcap if the module has problems finding the -# proper installation path. -# -# Variables defined by this module: -# -# PCAP_FOUND System has libpcap, include and library dirs found -# PCAP_INCLUDE_DIR The libpcap include directories. -# PCAP_LIBRARY The libpcap library. - -find_path(PCAP_ROOT_DIR - NAMES include/pcap.h -) - -find_path(PCAP_INCLUDE_DIR - NAMES pcap.h - HINTS ${PCAP_ROOT_DIR}/include -) - -find_library(PCAP_LIBRARY - NAMES pcap - HINTS ${PCAP_ROOT_DIR}/lib -) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(PCAP DEFAULT_MSG - PCAP_LIBRARY - PCAP_INCLUDE_DIR -) - -mark_as_advanced( - PCAP_ROOT_DIR - PCAP_INCLUDE_DIR - PCAP_LIBRARY -) diff --git a/cmake/FindRequiredPackage.cmake b/cmake/FindRequiredPackage.cmake deleted file mode 100644 index ff76b646cc..0000000000 --- a/cmake/FindRequiredPackage.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# A wrapper macro around the standard CMake find_package macro that -# facilitates displaying better error messages by default, or even -# accepting custom error messages on a per package basis. -# -# If a package is not found, then the MISSING_PREREQS variable gets -# set to true and either a default or custom error message appended -# to MISSING_PREREQ_DESCS. -# -# The caller can use these variables to display a list of any missing -# packages and abort the build/configuration if there were any. -# -# Use as follows: -# -# include(FindRequiredPackage) -# FindRequiredPackage(Perl) -# FindRequiredPackage(FLEX "You need to install flex (Fast Lexical Analyzer)") -# -# if (MISSING_PREREQS) -# foreach (prereq ${MISSING_PREREQ_DESCS}) -# message(SEND_ERROR ${prereq}) -# endforeach () -# message(FATAL_ERROR "Configuration aborted due to missing prerequisites") -# endif () - -macro(FindRequiredPackage packageName) - find_package(${packageName}) - string(TOUPPER ${packageName} canonPackageName) - if (NOT ${canonPackageName}_FOUND) - set(MISSING_PREREQS true) - - set(customDesc) - foreach (descArg ${ARGN}) - set(customDesc "${customDesc} ${descArg}") - endforeach () - - if (customDesc) - # append the custom error message that was provided as an argument - list(APPEND MISSING_PREREQ_DESCS ${customDesc}) - else () - list(APPEND MISSING_PREREQ_DESCS - " Could not find prerequisite package '${packageName}'") - endif () - endif () -endmacro(FindRequiredPackage) diff --git a/cmake/InstallClobberImmune.cmake b/cmake/InstallClobberImmune.cmake deleted file mode 100644 index f3da8b88bb..0000000000 --- a/cmake/InstallClobberImmune.cmake +++ /dev/null @@ -1,26 +0,0 @@ -# Determines at `make install` time if a file, typically a configuration -# file placed in $PREFIX/etc, shouldn't be installed to prevent overwrite -# of an existing file. -# -# _srcfile: the file to install -# _dstfile: the absolute file name after installation - -macro(InstallClobberImmune _srcfile _dstfile) - install(CODE " - if (EXISTS ${_dstfile}) - message(STATUS \"Skipping: ${_dstfile} (already exists)\") - execute_process(COMMAND \"${CMAKE_COMMAND}\" -E compare_files - ${_srcfile} ${_dstfile} RESULT_VARIABLE _diff) - if (NOT \"\${_diff}\" STREQUAL \"0\") - message(STATUS \"Installing: ${_dstfile}.example\") - configure_file(${_srcfile} ${_dstfile}.example COPY_ONLY) - endif () - else () - message(STATUS \"Installing: ${_dstfile}\") - # install() is not scriptable within install(), and - # configure_file() is the next best thing - configure_file(${_srcfile} ${_dstfile} COPY_ONLY) - # TODO: create additional install_manifest files? - endif () - ") -endmacro(InstallClobberImmune) diff --git a/cmake/InstallPackageConfigFile.cmake b/cmake/InstallPackageConfigFile.cmake deleted file mode 100644 index 5850bb3783..0000000000 --- a/cmake/InstallPackageConfigFile.cmake +++ /dev/null @@ -1,42 +0,0 @@ -include(InstallClobberImmune) - -# This macro can be used to install configuration files which -# users are expected to modify after installation. It will: -# -# - If binary packaging is enabled: -# Install the file in the typical CMake fashion, but append to the -# INSTALLED_CONFIG_FILES cache variable for use with the Mac package's -# pre/post install scripts -# - If binary packaging is not enabled: -# Install the script in a way such that it will check at `make install` -# time whether the file does not exist. See InstallClobberImmune.cmake -# -# _srcfile: the absolute path to the file to install -# _dstdir: absolute path to the directory in which to install the file -# _dstfilename: how to (re)name the file inside _dstdir - -macro(InstallPackageConfigFile _srcfile _dstdir _dstfilename) - set(_dstfile ${_dstdir}/${_dstfilename}) - - if (BINARY_PACKAGING_MODE) - # If packaging mode is enabled, always install the distribution's - # version of the file. The Mac package's pre/post install scripts - # or native functionality of RPMs will take care of not clobbering it. - install(FILES ${_srcfile} DESTINATION ${_dstdir} RENAME ${_dstfilename}) - # This cache variable is what the Mac package pre/post install scripts - # use to avoid clobbering user-modified config files - set(INSTALLED_CONFIG_FILES - "${INSTALLED_CONFIG_FILES} ${_dstfile}" CACHE STRING "" FORCE) - - # Additionally, the Mac PackageMaker packages don't have any automatic - # handling of configuration file conflicts so install an example file - # that the post install script will cleanup in the case it's extraneous - if (APPLE) - install(FILES ${_srcfile} DESTINATION ${_dstdir} - RENAME ${_dstfilename}.example) - endif () - else () - # Have `make install` check at run time whether the file does not exist - InstallClobberImmune(${_srcfile} ${_dstfile}) - endif () -endmacro(InstallPackageConfigFile) diff --git a/cmake/MAC_PACKAGE_INTRO b/cmake/MAC_PACKAGE_INTRO deleted file mode 100644 index ef37e62a1a..0000000000 --- a/cmake/MAC_PACKAGE_INTRO +++ /dev/null @@ -1,20 +0,0 @@ -This package will install @CMAKE_PROJECT_NAME@ into the following location: - - @CMAKE_INSTALL_PREFIX@ - -You may choose to update your PATH environment variable: - - # For Bash - export PATH=@CMAKE_INSTALL_PREFIX@/bin:$PATH - - # For CSH - setenv PATH @CMAKE_INSTALL_PREFIX@/bin:$PATH - -If you have more than one volume, please choose the install -destination as the one that contains the root filesystem. - -If you have existing configuration files that are modified or -otherwise different from the version included in the package, -this installer will attempt to prevent overwirting them, -but its also advisable to make your own backups of important -files before proceeding. diff --git a/cmake/MacDependencyPaths.cmake b/cmake/MacDependencyPaths.cmake deleted file mode 100644 index 9a8c6efc6a..0000000000 --- a/cmake/MacDependencyPaths.cmake +++ /dev/null @@ -1,10 +0,0 @@ -if (NOT _MAC_DEPENDENCY_PATHS) -set(_MAC_DEPENDENCY_PATHS) - # As of CMake 2.8.3, Fink and MacPorts search paths are appended to the - # default search prefix paths, but the nicer thing would be if they are - # prepended to the default, so that is fixed here. - if (APPLE) - list(INSERT CMAKE_SYSTEM_PREFIX_PATH 0 /opt/local) # MacPorts - list(INSERT CMAKE_SYSTEM_PREFIX_PATH 0 /sw) # Fink - endif () -endif () diff --git a/cmake/MiscTests.cmake b/cmake/MiscTests.cmake deleted file mode 100644 index da46dd83d7..0000000000 --- a/cmake/MiscTests.cmake +++ /dev/null @@ -1,34 +0,0 @@ -include(CheckCXXSourceCompiles) -include(CheckCSourceCompiles) - -# This autoconf variable is obsolete; it's portable to assume C89 and signal -# handlers returning void -set(RETSIGTYPE "void") -set(RETSIGVAL "") - -check_c_source_compiles(" - #include - #include - extern int socket(int, int, int); - extern int connect(int, const struct sockaddr *, int); - extern int send(int, const void *, int, int); - extern int recvfrom(int, void *, int, int, struct sockaddr *, int *); - int main() { return 0; } -" DO_SOCK_DECL) -if (DO_SOCK_DECL) - message(STATUS "socket() and friends need explicit declaration") -endif () - -check_cxx_source_compiles(" - #include - #include - extern \"C\" { - int openlog(const char* ident, int logopt, int facility); - int syslog(int priority, const char* message_fmt, ...); - int closelog(); - } - int main() { return 0; } -" SYSLOG_INT) -if (SYSLOG_INT) - message(STATUS "syslog prototypes need declaration") -endif () diff --git a/cmake/OSSpecific.cmake b/cmake/OSSpecific.cmake deleted file mode 100644 index 03788813c3..0000000000 --- a/cmake/OSSpecific.cmake +++ /dev/null @@ -1,66 +0,0 @@ -if (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") - # alternate malloc is faster for FreeBSD, but needs more testing - # need to add way to set this from the command line - set(USE_NMALLOC true) - -elseif (${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD") - set(USE_NMALLOC true) - -elseif (${CMAKE_SYSTEM_NAME} MATCHES "Darwin") - -elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set(HAVE_LINUX true) - -elseif (${CMAKE_SYSTEM_NAME} MATCHES "Solaris") - set(SOCKET_LIBS nsl socket) - -elseif (${CMAKE_SYSTEM_NAME} MATCHES "osf") - # Workaround ip_hl vs. ip_vhl problem in netinet/ip.h - add_definitions(-D__STDC__=2) - -elseif (${CMAKE_SYSTEM_NAME} MATCHES "irix") - list(APPEND CMAKE_C_FLAGS -xansi -signed -g3) - list(APPEND CMAKE_CXX_FLAGS -xansi -signed -g3) - -elseif (${CMAKE_SYSTEM_NAME} MATCHES "ultrix") - list(APPEND CMAKE_C_FLAGS -std1 -g3) - list(APPEND CMAKE_CXX_FLAGS -std1 -g3) - include(CheckCSourceCompiles) - check_c_source_compiles(" - #include - int main() { - void c(const struct a *); - return 0; - } - " have_ultrix_const) - if (NOT have_ultrix_const) - set(NEED_ULTRIX_CONST_HACK true) - endif () - -elseif (${CMAKE_SYSTEM_NAME} MATCHES "hpux" OR - ${CMAKE_SYSTEM_NAME} MATCHES "HP-UX") - include(CheckCSourceCompiles) - set(CMAKE_REQUIRED_FLAGS -Aa) - set(CMAKE_REQUIRED_DEFINITIONS -D_HPUX_SOURCE) - check_c_source_compiles(" - #include - int main() { - int frob(int, char *); - return 0; - } - " have_ansi_prototypes) - set(CMAKE_REQUIRED_FLAGS) - set(CMAKE_REQUIRED_DEFINITIONS) - - if (have_ansi_prototypes) - add_definitions(-D_HPUX_SOURCE) - list(APPEND CMAKE_C_FLAGS -Aa) - list(APPEND CMAKE_CXX_FLAGS -Aa) - endif () - - if (NOT have_ansi_prototypes) - message(FATAL_ERROR "Can't get HPUX compiler to handle ANSI prototypes") - endif () -endif () - - diff --git a/cmake/OpenSSLTests.cmake b/cmake/OpenSSLTests.cmake deleted file mode 100644 index 1b418135e4..0000000000 --- a/cmake/OpenSSLTests.cmake +++ /dev/null @@ -1,72 +0,0 @@ -include(CheckCSourceCompiles) -include(CheckCXXSourceCompiles) - -set(CMAKE_REQUIRED_LIBRARIES ${OpenSSL_LIBRARIES}) -set(CMAKE_REQUIRED_INCLUDES ${OpenSSL_INCLUDE_DIR}) - -check_c_source_compiles(" - #include - int main() { return 0; } -" including_ssl_h_works) - -if (NOT including_ssl_h_works) - # On Red Hat we may need to include Kerberos header. - set(CMAKE_REQUIRED_INCLUDES ${OpenSSL_INCLUDE_DIR} /usr/kerberos/include) - check_c_source_compiles(" - #include - #include - int main() { return 0; } - " NEED_KRB5_H) - set(CMAKE_REQUIRED_INCLUDES ${OpenSSL_INCLUDE_DIR}) - if (NOT NEED_KRB5_H) - message(FATAL_ERROR - "OpenSSL test failure. See CmakeError.log for details.") - else () - message(STATUS "OpenSSL requires Kerberos header") - include_directories("/usr/kerberos/include") - endif () -endif () - -# check for OPENSSL_add_all_algorithms_conf function -# and thus OpenSSL >= v0.9.7 -check_c_source_compiles(" - #include - int main() { - OPENSSL_add_all_algorithms_conf(); - return 0; - } -" openssl_greater_than_0_9_7) - -if (NOT openssl_greater_than_0_9_7) - message(FATAL_ERROR "OpenSSL >= v0.9.7 required") -endif () - -check_cxx_source_compiles(" -#include - int main() { - const unsigned char** cpp = 0; - X509** x =0; - d2i_X509(x, cpp, 0); - return 0; - } -" OPENSSL_D2I_X509_USES_CONST_CHAR) - -if (NOT OPENSSL_D2I_X509_USES_CONST_CHAR) - # double check that it compiles without const - check_cxx_source_compiles(" - #include - int main() { - unsigned char** cpp = 0; - X509** x =0; - d2i_X509(x, cpp, 0); - return 0; - } - " OPENSSL_D2I_X509_USES_CHAR) - if (NOT OPENSSL_D2I_X509_USES_CHAR) - message(FATAL_ERROR - "Can't determine if openssl_d2i_x509() takes const char parameter") - endif () -endif () - -set(CMAKE_REQUIRED_INCLUDES) -set(CMAKE_REQUIRED_LIBRARIES) diff --git a/cmake/PCAPTests.cmake b/cmake/PCAPTests.cmake deleted file mode 100644 index 1b62d3ab57..0000000000 --- a/cmake/PCAPTests.cmake +++ /dev/null @@ -1,63 +0,0 @@ -include(CheckFunctionExists) -include(CheckCSourceCompiles) -include(CheckIncludeFiles) - -set(CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIR}) -set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARY}) - -check_include_files(pcap-int.h HAVE_PCAP_INT_H) - -check_function_exists(pcap_freecode HAVE_LIBPCAP_PCAP_FREECODE) -if (NOT HAVE_LIBPCAP_PCAP_FREECODE) - set(DONT_HAVE_LIBPCAP_PCAP_FREECODE true) - message(STATUS "No implementation for pcap_freecode()") -endif () - -check_c_source_compiles(" -#include -int main () { - int snaplen; - int linktype; - struct bpf_program fp; - int optimize; - bpf_u_int32 netmask; - char str[10]; - char error[1024]; - snaplen = 50; - linktype = DLT_EN10MB; - optimize = 1; - netmask = 0L; - str[0] = 'i'; str[1] = 'p'; str[2] = '\\\\0'; - (void)pcap_compile_nopcap( - snaplen, linktype, &fp, str, optimize, netmask, &error); - return 0; -} -" LIBPCAP_PCAP_COMPILE_NOPCAP_HAS_ERROR_PARAMETER) -if (NOT LIBPCAP_PCAP_COMPILE_NOPCAP_HAS_ERROR_PARAMETER) - # double check - check_c_source_compiles(" -#include -int main () { - int snaplen; - int linktype; - struct bpf_program fp; - int optimize; - bpf_u_int32 netmask; - char str[10]; - snaplen = 50; - linktype = DLT_EN10MB; - optimize = 1; - netmask = 0L; - str[0] = 'i'; str[1] = 'p'; str[2] = '\\\\0'; - (void)pcap_compile_nopcap(snaplen, linktype, &fp, str, optimize, netmask); - return 0; -} -" LIBPCAP_PCAP_COMPILE_NOPCAP_NO_ERROR_PARAMETER) - if (NOT LIBPCAP_PCAP_COMPILE_NOPCAP_NO_ERROR_PARAMETER) - message(FATAL_ERROR - "Can't determine if pcap_compile_nopcap takes an error parameter") - endif () -endif () - -set(CMAKE_REQUIRED_INCLUDES) -set(CMAKE_REQUIRED_LIBRARIES) diff --git a/cmake/cmake_uninstall.cmake.in b/cmake/cmake_uninstall.cmake.in deleted file mode 100644 index bed4da63d3..0000000000 --- a/cmake/cmake_uninstall.cmake.in +++ /dev/null @@ -1,35 +0,0 @@ -function(uninstall_manifest manifestPath) - file(READ "${manifestPath}" files) - string(REGEX REPLACE "\n" ";" files "${files}") - foreach (file ${files}) - set(fileName $ENV{DESTDIR}${file}) - - if (EXISTS "${fileName}" OR IS_SYMLINK "${fileName}") - message(STATUS "Uninstalling: ${fileName}") - - execute_process( - COMMAND "@CMAKE_COMMAND@" -E remove "${fileName}" - OUTPUT_VARIABLE rm_out - RESULT_VARIABLE rm_retval - ) - - if (NOT ${rm_retval} EQUAL 0) - message(FATAL_ERROR "Problem when removing: ${fileName}") - endif () - else () - message(STATUS "Does not exist: ${fileName}") - endif () - - endforeach () -endfunction(uninstall_manifest) - -file(GLOB install_manifests @CMAKE_CURRENT_BINARY_DIR@/install_manifest*.txt) - -if (install_manifests) - foreach (manifest ${install_manifests}) - uninstall_manifest(${manifest}) - endforeach () -else () - message(FATAL_ERROR "Cannot find any install manifests in: " - "\"@CMAKE_CURRENT_BINARY_DIR@/install_manifest*.txt\"") -endif () diff --git a/cmake/package_postupgrade.sh.in b/cmake/package_postupgrade.sh.in deleted file mode 100755 index 7d40950fc1..0000000000 --- a/cmake/package_postupgrade.sh.in +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/sh - -# This script is meant to be used by binary packages post-installation. -# Variables between @ symbols are replaced by CMake at configure time. - -backupNamesFile=/tmp/bro_install_backups -version=@VERSION@ -sampleFiles="" - -# check whether it's safe to remove backup configuration files that -# the most recent package install created - -if [ -e ${backupNamesFile} ]; then - backupFileList=`cat ${backupNamesFile}` - - for backupFile in ${backupFileList}; do - origFileName=`echo ${backupFile} | sed 's/\(.*\)\..*/\1/'` - - diff ${origFileName} ${backupFile} > /dev/null 2>&1 - - if [ $? -eq 0 ]; then - # if the installed version and the backup version don't differ - # then we can remove the backup version and the example file - rm ${backupFile} - rm ${origFileName}.example - else - # The backup file differs from the newly installed version, - # since we can't tell if the backup version has been modified - # by the user, we should restore it to its original location - # and rename the new version appropriately. - - sampleFiles="${sampleFiles}\n${origFileName}.example" - - mv ${backupFile} ${origFileName} - fi - - done - - rm ${backupNamesFile} -fi - -if [ -n "${sampleFiles}" ]; then -# Use some apple script to display a message to user -/usr/bin/osascript << EOF - tell application "System Events" - activate - display alert "Existing configuration files differ from the ones that would be installed by this package. To avoid overwriting configuration which you may have modified, the following new config files have been installed:\n${sampleFiles}\n\nIf you have previously modified configuration files, please make sure that they are still compatible, else you should update your config files to the new versions." - end tell -EOF -fi - -# Set up world writeable spool and logs directory for broctl, making sure -# to set the sticky bit so that unprivileged users can't rename/remove files. -# (CMake/CPack is supposed to install them, but has problems with empty dirs) -if [ -n "@EMPTY_WORLD_DIRS@" ]; then - for dir in "@EMPTY_WORLD_DIRS@"; do - mkdir -p ${dir} - chmod 777 ${dir} - chmod +t ${dir} - done -fi diff --git a/cmake/package_preinstall.sh.in b/cmake/package_preinstall.sh.in deleted file mode 100755 index 749b01fdfc..0000000000 --- a/cmake/package_preinstall.sh.in +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/sh - -# This script is meant to be used by binary packages pre-installation. -# Variables between @ symbols are replaced by CMake at configure time. - -configFiles="@INSTALLED_CONFIG_FILES@" -backupNamesFile=/tmp/bro_install_backups - -# Checks if a config file exists in a default location and makes a backup -# so that a modified version is not clobbered -backupFile () { - origFile="$1" - - if [ -e ${origFile} ]; then - # choose a file suffix that doesn't already exist - ver=1 - while [ -e ${origFile}.${ver} ]; do - ver=$(( ver + 1 )) - done - - backupFile=${origFile}.${ver} - - cp -p ${origFile} ${backupFile} - - # the post upgrade script will check whether the installed - # config file actually differs from existing version - # and delete unnecessary backups - echo "${backupFile}" >> ${backupNamesFile} - fi -} - -for file in ${configFiles}; do - backupFile "${file}" -done diff --git a/config.h.in b/config.h.in index 2820875b78..b8e2cb9a88 100644 --- a/config.h.in +++ b/config.h.in @@ -1,6 +1,3 @@ -/* enable IPV6 processing */ -#cmakedefine BROv6 - /* Old libpcap versions (< 0.6.1) need defining pcap_freecode and pcap_compile_nopcap */ #cmakedefine DONT_HAVE_LIBPCAP_PCAP_FREECODE @@ -14,18 +11,9 @@ /* Define if you have the `getopt_long' function. */ #cmakedefine HAVE_GETOPT_LONG -/* Define if you have the `magic' library (-lmagic). */ -#cmakedefine HAVE_LIBMAGIC - -/* Define if you have the `z' library (-lz). */ -#cmakedefine HAVE_LIBZ - /* We are on a Linux system */ #cmakedefine HAVE_LINUX -/* Define if you have the header file. */ -#cmakedefine HAVE_MAGIC_H - /* Define if you have the `mallinfo' function. */ #cmakedefine HAVE_MALLINFO @@ -41,8 +29,8 @@ /* Define if you have the header file. */ #cmakedefine HAVE_NET_ETHERNET_H -/* We are on a OpenBSD system */ -#cmakedefine HAVE_OPENBSD +/* Define if you have the header file. */ +#cmakedefine HAVE_NET_ETHERTYPES_H /* have os-proto.h */ #cmakedefine HAVE_OS_PROTO_H @@ -114,8 +102,17 @@ /* GeoIP geographic lookup functionality */ #cmakedefine USE_GEOIP +/* Whether the found GeoIP API supports IPv6 Country Edition */ +#cmakedefine HAVE_GEOIP_COUNTRY_EDITION_V6 + +/* Whether the found GeoIP API supports IPv6 City Edition */ +#cmakedefine HAVE_GEOIP_CITY_EDITION_REV0_V6 + /* Use Google's perftools */ -#cmakedefine USE_PERFTOOLS +#cmakedefine USE_PERFTOOLS_DEBUG + +/* Analyze Mobile IPv6 traffic */ +#cmakedefine ENABLE_MOBILE_IPV6 /* Version number of package */ #define VERSION "@VERSION@" @@ -148,3 +145,54 @@ /* Define u_int8_t */ #cmakedefine u_int8_t @u_int8_t@ + +/* OpenBSD's bpf.h may not declare this data link type, but it's supposed to be + used consistently for the same purpose on all platforms. */ +#cmakedefine HAVE_DLT_PPP_SERIAL +#ifndef HAVE_DLT_PPP_SERIAL +#define DLT_PPP_SERIAL @DLT_PPP_SERIAL@ +#endif + +/* IPv6 Next Header values defined by RFC 3542 */ +#cmakedefine HAVE_IPPROTO_HOPOPTS +#ifndef HAVE_IPPROTO_HOPOPTS +#define IPPROTO_HOPOPTS 0 +#endif +#cmakedefine HAVE_IPPROTO_IPV6 +#ifndef HAVE_IPPROTO_IPV6 +#define IPPROTO_IPV6 41 +#endif +#cmakedefine HAVE_IPPROTO_ROUTING +#ifndef HAVE_IPPROTO_ROUTING +#define IPPROTO_ROUTING 43 +#endif +#cmakedefine HAVE_IPPROTO_FRAGMENT +#ifndef HAVE_IPPROTO_FRAGMENT +#define IPPROTO_FRAGMENT 44 +#endif +#cmakedefine HAVE_IPPROTO_ESP +#ifndef HAVE_IPPROTO_ESP +#define IPPROTO_ESP 50 +#endif +#cmakedefine HAVE_IPPROTO_AH +#ifndef HAVE_IPPROTO_AH +#define IPPROTO_AH 51 +#endif +#cmakedefine HAVE_IPPROTO_ICMPV6 +#ifndef HAVE_IPPROTO_ICMPV6 +#define IPPROTO_ICMPV6 58 +#endif +#cmakedefine HAVE_IPPROTO_NONE +#ifndef HAVE_IPPROTO_NONE +#define IPPROTO_NONE 59 +#endif +#cmakedefine HAVE_IPPROTO_DSTOPTS +#ifndef HAVE_IPPROTO_DSTOPTS +#define IPPROTO_DSTOPTS 60 +#endif + +/* IPv6 options structure defined by RFC 3542 */ +#cmakedefine HAVE_IP6_OPT + +/* Common IPv6 extension structure */ +#cmakedefine HAVE_IP6_EXT diff --git a/configure b/configure index 2e168f0550..3c1cca8c9d 100755 --- a/configure +++ b/configure @@ -27,11 +27,13 @@ Usage: $0 [OPTION]... [VAR=VALUE]... Optional Features: --enable-debug compile in debugging mode - --enable-brov6 enable IPv6 processing - --enable-perftools use Google's perftools + --enable-mobile-ipv6 analyze mobile IPv6 features defined by RFC 6275 + --enable-perftools-debug use Google's perftools for debugging --disable-broccoli don't build or install the Broccoli library --disable-broctl don't install Broctl --disable-auxtools don't build or install auxilliary tools + --disable-python don't try to build python bindings for broccoli + --disable-ruby don't try to build ruby bindings for broccoli Required Packages in Non-Standard Locations: --with-openssl=PATH path to OpenSSL install root @@ -49,6 +51,9 @@ Usage: $0 [OPTION]... [VAR=VALUE]... --with-python=PATH path to Python interpreter --with-python-lib=PATH path to libpython --with-python-inc=PATH path to Python headers + --with-ruby=PATH path to ruby interpreter + --with-ruby-lib=PATH path to ruby library + --with-ruby-inc=PATH path to ruby headers --with-swig=PATH path to SWIG executable Packaging Options (for developers): @@ -87,14 +92,14 @@ append_cache_entry BRO_ROOT_DIR PATH /usr/local/bro append_cache_entry PY_MOD_INSTALL_DIR PATH /usr/local/bro/lib/broctl append_cache_entry BRO_SCRIPT_INSTALL_PATH STRING /usr/local/bro/share/bro append_cache_entry ENABLE_DEBUG BOOL false -append_cache_entry BROv6 BOOL false -append_cache_entry ENABLE_PERFTOOLS BOOL false +append_cache_entry ENABLE_PERFTOOLS_DEBUG BOOL false append_cache_entry BinPAC_SKIP_INSTALL BOOL true append_cache_entry BUILD_SHARED_LIBS BOOL true append_cache_entry INSTALL_AUX_TOOLS BOOL true append_cache_entry INSTALL_BROCCOLI BOOL true append_cache_entry INSTALL_BROCTL BOOL true append_cache_entry CPACK_SOURCE_IGNORE_FILES STRING +append_cache_entry ENABLE_MOBILE_IPV6 BOOL false # parse arguments while [ $# -ne 0 ]; do @@ -129,11 +134,11 @@ while [ $# -ne 0 ]; do --enable-debug) append_cache_entry ENABLE_DEBUG BOOL true ;; - --enable-brov6) - append_cache_entry BROv6 BOOL true + --enable-mobile-ipv6) + append_cache_entry ENABLE_MOBILE_IPV6 BOOL true ;; - --enable-perftools) - append_cache_entry ENABLE_PERFTOOLS BOOL true + --enable-perftools-debug) + append_cache_entry ENABLE_PERFTOOLS_DEBUG BOOL true ;; --disable-broccoli) append_cache_entry INSTALL_BROCCOLI BOOL false @@ -144,6 +149,12 @@ while [ $# -ne 0 ]; do --disable-auxtools) append_cache_entry INSTALL_AUX_TOOLS BOOL false ;; + --disable-python) + append_cache_entry DISABLE_PYTHON_BINDINGS BOOL true + ;; + --disable-ruby) + append_cache_entry DISABLE_RUBY_BINDINGS BOOL true + ;; --with-openssl=*) append_cache_entry OpenSSL_ROOT_DIR PATH $optarg ;; @@ -172,7 +183,6 @@ while [ $# -ne 0 ]; do append_cache_entry LibGeoIP_ROOT_DIR PATH $optarg ;; --with-perftools=*) - append_cache_entry ENABLE_PERFTOOLS BOOL true append_cache_entry GooglePerftools_ROOT_DIR PATH $optarg ;; --with-python=*) @@ -185,6 +195,16 @@ while [ $# -ne 0 ]; do append_cache_entry PYTHON_INCLUDE_DIR PATH $optarg append_cache_entry PYTHON_INCLUDE_PATH PATH $optarg ;; + --with-ruby=*) + append_cache_entry RUBY_EXECUTABLE PATH $optarg + ;; + --with-ruby-lib=*) + append_cache_entry RUBY_LIBRARY PATH $optarg + ;; + --with-ruby-inc=*) + append_cache_entry RUBY_INCLUDE_DIRS PATH $optarg + append_cache_entry RUBY_INCLUDE_PATH PATH $optarg + ;; --with-swig=*) append_cache_entry SWIG_EXECUTABLE PATH $optarg ;; diff --git a/doc/.gitignore b/doc/.gitignore new file mode 100644 index 0000000000..15972ee82a --- /dev/null +++ b/doc/.gitignore @@ -0,0 +1,2 @@ +html +*.pyc diff --git a/doc/CHANGES b/doc/CHANGES new file mode 120000 index 0000000000..3e8bc8c0c8 --- /dev/null +++ b/doc/CHANGES @@ -0,0 +1 @@ +../CHANGES \ No newline at end of file diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt index e2c3f25f4e..bdbb0e7b69 100644 --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -1 +1,75 @@ +set(BIF_SRC_DIR ${PROJECT_SOURCE_DIR}/src) +set(RST_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/rest_output) +set(DOC_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/out) +set(DOC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) +set(DOC_SOURCE_WORKDIR ${CMAKE_CURRENT_BINARY_DIR}/sphinx-sources) + +set(MASTER_POLICY_INDEX ${CMAKE_CURRENT_BINARY_DIR}/scripts/policy_index) +set(MASTER_PACKAGE_INDEX ${CMAKE_CURRENT_BINARY_DIR}/scripts/pkg_index) + +file(GLOB_RECURSE DOC_SOURCES FOLLOW_SYMLINKS "*") + +# configure the Sphinx config file (expand variables CMake might know about) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in + ${CMAKE_CURRENT_BINARY_DIR}/conf.py + @ONLY) + add_subdirectory(scripts) + +# The "broxygen" target generates reST documentation for any outdated bro +# scripts and then uses Sphinx to generate HTML documentation from the reST +add_custom_target(broxygen + # copy the template documentation to the build directory + # to give as input for sphinx + COMMAND "${CMAKE_COMMAND}" -E copy_directory + ${DOC_SOURCE_DIR} + ${DOC_SOURCE_WORKDIR} + # copy generated policy script documentation into the + # working copy of the template documentation + COMMAND "${CMAKE_COMMAND}" -E copy_directory + ${RST_OUTPUT_DIR} + ${DOC_SOURCE_WORKDIR}/scripts + # append to the master index of all policy scripts + COMMAND cat ${MASTER_POLICY_INDEX} >> + ${DOC_SOURCE_WORKDIR}/scripts/index.rst + # append to the master index of all policy packages + COMMAND cat ${MASTER_PACKAGE_INDEX} >> + ${DOC_SOURCE_WORKDIR}/scripts/packages.rst + # construct a reST file for each group + COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/bin/group_index_generator.py + ${CMAKE_CURRENT_BINARY_DIR}/scripts/group_list + ${CMAKE_CURRENT_BINARY_DIR}/scripts + ${DOC_SOURCE_WORKDIR}/scripts + # tell sphinx to generate html + COMMAND sphinx-build + -b html + -c ${CMAKE_CURRENT_BINARY_DIR} + -d ${DOC_OUTPUT_DIR}/doctrees + ${DOC_SOURCE_WORKDIR} + ${DOC_OUTPUT_DIR}/html + # create symlink to the html output directory for convenience + COMMAND "${CMAKE_COMMAND}" -E create_symlink + ${DOC_OUTPUT_DIR}/html + ${CMAKE_BINARY_DIR}/html + # copy Broccoli API reference into output dir if it exists + COMMAND test -d ${CMAKE_BINARY_DIR}/aux/broccoli/doc/html && ( rm -rf ${CMAKE_BINARY_DIR}/html/broccoli-api && cp -r ${CMAKE_BINARY_DIR}/aux/broccoli/doc/html ${CMAKE_BINARY_DIR}/html/broccoli-api ) || true + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "[Sphinx] Generating HTML policy script docs" + # SOURCES just adds stuff to IDE projects as a convenience + SOURCES ${DOC_SOURCES}) + +# The "sphinxclean" target removes just the Sphinx input/output directories +# from the build directory. +add_custom_target(broxygenclean + COMMAND "${CMAKE_COMMAND}" -E remove_directory + ${DOC_SOURCE_WORKDIR} + COMMAND "${CMAKE_COMMAND}" -E remove_directory + ${DOC_OUTPUT_DIR} + VERBATIM) + +add_dependencies(broxygen broxygenclean restdoc) + +add_custom_target(doc) +add_custom_target(docclean) +add_dependencies(doc broxygen) +add_dependencies(docclean broxygenclean restclean) diff --git a/doc/INSTALL.rst b/doc/INSTALL.rst new file mode 120000 index 0000000000..99d491b4f8 --- /dev/null +++ b/doc/INSTALL.rst @@ -0,0 +1 @@ +../INSTALL \ No newline at end of file diff --git a/doc/README b/doc/README index 1333ed77b7..0ba0a8587f 100644 --- a/doc/README +++ b/doc/README @@ -1 +1,47 @@ -TODO + +Documentation +============= + +This directory contains Bro documentation in reStructuredText format +(see http://docutils.sourceforge.net/rst.html). + +It is the root of a Sphinx source tree and can be modified to add more +common/general documentation, style sheets, JavaScript, etc. The Sphinx +config file is produced from ``conf.py.in``, and can be edited to change +various Sphinx options. + +There is also a custom Sphinx domain implemented in ``source/ext/bro.py`` +which adds some reST directives and roles that aid in generating useful +index entries and cross-references. Other extensions can be added in +a similar fashion. + +Either the ``make doc`` or ``make broxygen`` targets in the top-level +Makefile can be used to locally render the reST files into HTML. +Those targets depend on: + +* Python interpreter >= 2.5 +* `Sphinx `_ >= 1.0.1 + +After completion, HTML documentation is symlinked in ``build/html``. + +There's also ``make docclean`` and ``make broxygenclean`` targets to +clean the resulting documentation. + +Notes for Writing Documentation +------------------------------- + +* If you want to refer to a document that's part of the + distribution, it currently needs to be copied or otherwise symlinked + somewhere in to this Sphinx source tree. Then, it can be referenced + in a toc tree or with the :doc: role. Use the :download: role to + refer to static files that will not undergo sphinx rendering. + +* If you want to refer to a page on the Bro web site, use an HTTP URL. + +Guidelines +---------- + +TODO. + + + diff --git a/doc/_static/960.css b/doc/_static/960.css new file mode 100644 index 0000000000..22c5e18180 --- /dev/null +++ b/doc/_static/960.css @@ -0,0 +1 @@ +body{min-width:960px}.container_12,.container_16{margin-left:auto;margin-right:auto;width:960px}.grid_1,.grid_2,.grid_3,.grid_4,.grid_5,.grid_6,.grid_7,.grid_8,.grid_9,.grid_10,.grid_11,.grid_12,.grid_13,.grid_14,.grid_15,.grid_16{display:inline;float:left;margin-left:10px;margin-right:10px}.push_1,.pull_1,.push_2,.pull_2,.push_3,.pull_3,.push_4,.pull_4,.push_5,.pull_5,.push_6,.pull_6,.push_7,.pull_7,.push_8,.pull_8,.push_9,.pull_9,.push_10,.pull_10,.push_11,.pull_11,.push_12,.pull_12,.push_13,.pull_13,.push_14,.pull_14,.push_15,.pull_15{position:relative}.container_12 .grid_3,.container_16 .grid_4{width:220px}.container_12 .grid_6,.container_16 .grid_8{width:460px}.container_12 .grid_9,.container_16 .grid_12{width:700px}.container_12 .grid_12,.container_16 .grid_16{width:940px}.alpha{margin-left:0}.omega{margin-right:0}.container_12 .grid_1{width:60px}.container_12 .grid_2{width:140px}.container_12 .grid_4{width:300px}.container_12 .grid_5{width:380px}.container_12 .grid_7{width:540px}.container_12 .grid_8{width:620px}.container_12 .grid_10{width:780px}.container_12 .grid_11{width:860px}.container_16 .grid_1{width:40px}.container_16 .grid_2{width:100px}.container_16 .grid_3{width:160px}.container_16 .grid_5{width:280px}.container_16 .grid_6{width:340px}.container_16 .grid_7{width:400px}.container_16 .grid_9{width:520px}.container_16 .grid_10{width:580px}.container_16 .grid_11{width:640px}.container_16 .grid_13{width:760px}.container_16 .grid_14{width:820px}.container_16 .grid_15{width:880px}.container_12 .prefix_3,.container_16 .prefix_4{padding-left:240px}.container_12 .prefix_6,.container_16 .prefix_8{padding-left:480px}.container_12 .prefix_9,.container_16 .prefix_12{padding-left:720px}.container_12 .prefix_1{padding-left:80px}.container_12 .prefix_2{padding-left:160px}.container_12 .prefix_4{padding-left:320px}.container_12 .prefix_5{padding-left:400px}.container_12 .prefix_7{padding-left:560px}.container_12 .prefix_8{padding-left:640px}.container_12 .prefix_10{padding-left:800px}.container_12 .prefix_11{padding-left:880px}.container_16 .prefix_1{padding-left:60px}.container_16 .prefix_2{padding-left:120px}.container_16 .prefix_3{padding-left:180px}.container_16 .prefix_5{padding-left:300px}.container_16 .prefix_6{padding-left:360px}.container_16 .prefix_7{padding-left:420px}.container_16 .prefix_9{padding-left:540px}.container_16 .prefix_10{padding-left:600px}.container_16 .prefix_11{padding-left:660px}.container_16 .prefix_13{padding-left:780px}.container_16 .prefix_14{padding-left:840px}.container_16 .prefix_15{padding-left:900px}.container_12 .suffix_3,.container_16 .suffix_4{padding-right:240px}.container_12 .suffix_6,.container_16 .suffix_8{padding-right:480px}.container_12 .suffix_9,.container_16 .suffix_12{padding-right:720px}.container_12 .suffix_1{padding-right:80px}.container_12 .suffix_2{padding-right:160px}.container_12 .suffix_4{padding-right:320px}.container_12 .suffix_5{padding-right:400px}.container_12 .suffix_7{padding-right:560px}.container_12 .suffix_8{padding-right:640px}.container_12 .suffix_10{padding-right:800px}.container_12 .suffix_11{padding-right:880px}.container_16 .suffix_1{padding-right:60px}.container_16 .suffix_2{padding-right:120px}.container_16 .suffix_3{padding-right:180px}.container_16 .suffix_5{padding-right:300px}.container_16 .suffix_6{padding-right:360px}.container_16 .suffix_7{padding-right:420px}.container_16 .suffix_9{padding-right:540px}.container_16 .suffix_10{padding-right:600px}.container_16 .suffix_11{padding-right:660px}.container_16 .suffix_13{padding-right:780px}.container_16 .suffix_14{padding-right:840px}.container_16 .suffix_15{padding-right:900px}.container_12 .push_3,.container_16 .push_4{left:240px}.container_12 .push_6,.container_16 .push_8{left:480px}.container_12 .push_9,.container_16 .push_12{left:720px}.container_12 .push_1{left:80px}.container_12 .push_2{left:160px}.container_12 .push_4{left:320px}.container_12 .push_5{left:400px}.container_12 .push_7{left:560px}.container_12 .push_8{left:640px}.container_12 .push_10{left:800px}.container_12 .push_11{left:880px}.container_16 .push_1{left:60px}.container_16 .push_2{left:120px}.container_16 .push_3{left:180px}.container_16 .push_5{left:300px}.container_16 .push_6{left:360px}.container_16 .push_7{left:420px}.container_16 .push_9{left:540px}.container_16 .push_10{left:600px}.container_16 .push_11{left:660px}.container_16 .push_13{left:780px}.container_16 .push_14{left:840px}.container_16 .push_15{left:900px}.container_12 .pull_3,.container_16 .pull_4{left:-240px}.container_12 .pull_6,.container_16 .pull_8{left:-480px}.container_12 .pull_9,.container_16 .pull_12{left:-720px}.container_12 .pull_1{left:-80px}.container_12 .pull_2{left:-160px}.container_12 .pull_4{left:-320px}.container_12 .pull_5{left:-400px}.container_12 .pull_7{left:-560px}.container_12 .pull_8{left:-640px}.container_12 .pull_10{left:-800px}.container_12 .pull_11{left:-880px}.container_16 .pull_1{left:-60px}.container_16 .pull_2{left:-120px}.container_16 .pull_3{left:-180px}.container_16 .pull_5{left:-300px}.container_16 .pull_6{left:-360px}.container_16 .pull_7{left:-420px}.container_16 .pull_9{left:-540px}.container_16 .pull_10{left:-600px}.container_16 .pull_11{left:-660px}.container_16 .pull_13{left:-780px}.container_16 .pull_14{left:-840px}.container_16 .pull_15{left:-900px}.clear{clear:both;display:block;overflow:hidden;visibility:hidden;width:0;height:0}.clearfix:before,.clearfix:after{content:'\0020';display:block;overflow:hidden;visibility:hidden;width:0;height:0}.clearfix:after{clear:both}.clearfix{zoom:1} diff --git a/doc/_static/basic.css b/doc/_static/basic.css new file mode 100644 index 0000000000..1332c7b048 --- /dev/null +++ b/doc/_static/basic.css @@ -0,0 +1,513 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar input[type="text"] { + width: 170px; +} + +div.sphinxsidebar input[type="submit"] { + width: 30px; +} + +img { + border: 0; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable dl, table.indextable dd { + margin-top: 0; + margin-bottom: 0; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- general body styles --------------------------------------------------- */ + +a.headerlink { + visibility: hidden; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.field-list ul { + padding-left: 1em; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.refcount { + color: #060; +} + +.optional { + font-size: 1.3em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +tt.descname { + background-color: transparent; + font-weight: bold; +# font-size: 1.2em; +} + +tt.descclassname { + background-color: transparent; +} + +tt.xref, a tt { + background-color: transparent; +# font-weight: bold; +} + +h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} diff --git a/doc/_static/broxygen-extra.css b/doc/_static/broxygen-extra.css new file mode 100644 index 0000000000..051e12e0be --- /dev/null +++ b/doc/_static/broxygen-extra.css @@ -0,0 +1,160 @@ + +a.toc-backref { + color: #333; +} + +h1, h2, h3, h4, h5, h6, +h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { + padding:0 0 0px 0; +} + +ul { + padding-bottom: 0px; +} + +h1 { + font-weight: bold; + font-size: 32px; + line-height:32px; + text-align: center; + padding-top: 3px; + margin-bottom: 30px; + font-family: Palatino,'Palatino Linotype',Georgia,serif;; + color: #000; + border-bottom: 0px; +} + +th.field-name +{ + white-space:nowrap; +} + +h2 { + margin-top: 50px; + padding-bottom: 5px; + margin-bottom: 30px; + border-bottom: 1px solid; + border-color: #aaa; + font-style: normal; +} + +div.section h3 { + font-style: normal; + } + +h3 { + font-size: 20px; + margin-top: 40px; + margin-bottom: 0¡px; + font-weight: bold; + font-style: normal; +} + +h3.widgettitle { + font-style: normal; +} + +h4 { + font-size:18px; + font-style: normal; + margin-bottom: 0em; + margin-top: 40px; + font-style: italic; +} + +h5 { + font-size:16px; +} + +h6 { + font-size:15px; +} + +.toc-backref { + color: #333; +} + +.contents ul { + padding-bottom: 1em; +} + +dl.namespace { + display: none; +} + +dl dt { + font-weight: normal; +} + +table.docutils tbody { + margin: 1em 1em 1em 1em; +} + +table.docutils td { + padding: 5pt 5pt 5pt 5pt; + font-size: 14px; + border-left: 0; + border-right: 0; +} + +dl pre { + font-size: 14px; +} + +table.docutils th { + padding: 5pt 5pt 5pt 5pt; + font-size: 14px; + font-style: normal; + border-left: 0; + border-right: 0; +} + +table.docutils tr:first-child td { + #border-top: 1px solid #aaa; +} + +.download { + font-family:"Courier New", Courier, mono; + font-weight: normal; +} + +dt:target, .highlighted { + background-color: #ccc; +} + +p { + padding-bottom: 0px; +} + +p.last { + margin-bottom: 0px; +} + +dl { + padding: 1em 1em 1em 1em; + background: #fffff0; + border: 1px solid #aaa; + +} + +dl { + margin-bottom: 10px; +} + + +table.docutils { + background: #fffff0; + border-collapse: collapse; + border: 1px solid #ddd; +} + +dl table.docutils { + border: 0; +} + +table.docutils dl { + border: 1px dashed #666; +} + + + diff --git a/policy.old/ftp-safe-words.bro b/doc/_static/broxygen-extra.js similarity index 100% rename from policy.old/ftp-safe-words.bro rename to doc/_static/broxygen-extra.js diff --git a/doc/_static/broxygen.css b/doc/_static/broxygen.css new file mode 100644 index 0000000000..967dcd6eaa --- /dev/null +++ b/doc/_static/broxygen.css @@ -0,0 +1,437 @@ +/* Automatically generated. Do not edit. */ + + + + + +#bro-main, #bro-standalone-main { + padding: 0 0 0 0; + position:relative; + z-index:1; +} + +#bro-main { + margin-bottom: 2em; + } + +#bro-standalone-main { + margin-bottom: 0em; + padding-left: 50px; + padding-right: 50px; + } + +#bro-outer { + color: #333; + background: #ffffff; +} + +#bro-title { + font-weight: bold; + font-size: 32px; + line-height:32px; + text-align: center; + padding-top: 3px; + margin-bottom: 30px; + font-family: Palatino,'Palatino Linotype',Georgia,serif;; + color: #000; + } + +.opening:first-letter { + font-size: 24px; + font-weight: bold; + letter-spacing: 0.05em; + } + +.opening { + font-size: 17px; +} + +.version { + text-align: right; + font-size: 12px; + color: #aaa; + line-height: 0; + height: 0; +} + +.git-info-version { + position: relative; + height: 2em; + top: -1em; + color: #ccc; + float: left; + font-size: 12px; +} + +.git-info-date { + position: relative; + height: 2em; + top: -1em; + color: #ccc; + float: right; + font-size: 12px; +} + +body { + font-family:Arial, Helvetica, sans-serif; + font-size:15px; + line-height:22px; + color: #333; + margin: 0px; +} + +h1, h2, h3, h4, h5, h6, +h1 a, h2 a, h3 a, h4 a, h5 a, h6 a { + padding:0 0 20px 0; + font-weight:bold; + text-decoration:none; +} + +div.section h3, div.section h4, div.section h5, div.section h6 { + font-style: italic; +} + +h1, h2 { + font-size:27px; + letter-spacing:-1px; +} + +h3 { + margin-top: 1em; + font-size:18px; +} + +h4 { + font-size:16px; +} + +h5 { + font-size:15px; +} + +h6 { + font-size:12px; +} + +p { + padding:0 0 20px 0; +} + +hr { + background:none; + height:1px; + line-height:1px; + border:0; + margin:0 0 20px 0; +} + +ul, ol { + margin:0 20px 20px 0; + padding-left:40px; +} + +ul.simple, ol.simple { + margin:0 0px 0px 0; +} + +blockquote { + margin:0 0 0 40px; +} + +strong, dfn { + font-weight:bold; +} + +em, dfn { + font-style:italic; +} + +sup, sub { + line-height:0; +} + +pre { + white-space:pre; +} + +pre, code, tt { + font-family:"Courier New", Courier, mono; +} + +dl { + margin: 0 0 20px 0; +} + +dl dt { + font-weight: bold; +} + +dd { + margin:0 0 20px 20px; +} + +small { + font-size:75%; +} + +a:link, +a:visited, +a:active +{ + color: #2a85a7; +} + +a:hover +{ + color:#c24444; +} + +h1, h2, h3, h4, h5, h6, +h1 a, h2 a, h3 a, h4 a, h5 a, h6 a +{ + color: #333; +} + +hr { + border-bottom:1px solid #ddd; +} + +pre { + color: #333; + background: #FFFAE2; + padding: 7px 5px 3px 5px; + margin-bottom: 25px; + margin-top: 0px; +} + +ul { + padding-bottom: 5px; + } + +h1, h2 { + margin-top: 30px; + } + +h1 { + margin-bottom: 50px; + margin-bottom: 20px; + padding-bottom: 5px; + border-bottom: 1px solid; + border-color: #aaa; + } + +h2 { + font-size: 24px; + } + +pre { + -moz-box-shadow:0 0 6px #ddd; + -webkit-box-shadow:0 0 6px #ddd; + box-shadow:0 0 6px #ddd; +} + +a { + text-decoration:none; + } + +p { + padding-bottom: 15px; + } + +p, dd, li { + text-align: justify; + } + +li { + margin-bottom: 5px; + } + + + +#footer .widget_links ul a, +#footer .widget_links ol a +{ + color: #ddd; +} + +#footer .widget_links ul a:hover, +#footer .widget_links ol a:hover +{ + color:#c24444; +} + + +#footer .widget li { + padding-bottom:10px; +} + +#footer .widget_links li { + padding-bottom:1px; +} + +#footer .widget li:last-child { + padding-bottom:0; +} + +#footer .widgettitle { + color: #ddd; +} + + +.widget { + margin:0 0 40px 0; +} + +.widget, .widgettitle { + font-size:12px; + line-height:18px; +} + +.widgettitle { + font-weight:bold; + text-transform:uppercase; + padding:0 0 10px 0; + margin:0 0 20px 0; + line-height:100%; +} + +.widget UL, .widget OL { + list-style-type:none; + margin:0; + padding:0; +} + +.widget p { + padding:0; +} + +.widget li { + padding-bottom:10px; +} + +.widget a { + text-decoration:none; +} + +#bro-main .widgettitle, +{ + color: #333; +} + + +.widget img.left { + padding:5px 10px 10px 0; +} + +.widget img.right { + padding:5px 0 10px 10px; +} + +.ads .widgettitle { + margin-right:16px; +} + +.widget { + margin-left: 1em; +} + +.widgettitle { + color: #333; +} + +.widgettitle { + border-bottom:1px solid #ddd; +} + + +.sidebar-toc ul li { + padding-bottom: 0px; + text-align: left; + list-style-type: square; + list-style-position: inside; + padding-left: 1em; + text-indent: -1em; + } + +.sidebar-toc ul li li { + margin-left: 1em; + margin-bottom: 0px; + list-style-type: square; + } + +.sidebar-toc ul li li a { + font-size: 8pt; +} + +.contents { + padding: 10px; + background: #FFFAE2; + margin: 20px; + } + +.topic-title { + font-size: 20px; + font-weight: bold; + padding: 0px 0px 5px 0px; + text-align: center; + padding-top: .5em; +} + +.contents li { + margin-bottom: 0px; + list-style-type: square; +} + +.contents ul ul li { + margin-left: 0px; + padding-left: 0px; + padding-top: 0em; + font-size: 90%; + list-style-type: square; + font-weight: normal; +} + +.contents ul ul ul li { + list-style-type: none; +} + +.contents ul ul ul ul li { + display:none; +} + +.contents ul li { + padding-top: 1em; + list-style-type: none; + font-weight: bold; +} + +.contents ul { + margin-left: 0px; + padding-left: 2em; + margin: 0px 0px 0px 0px; +} + +.note, .warning, .error { + margin-left: 2em; + margin-right: 2em; + margin-top: 1.5em; + margin-bottom: 1.5em; + padding: 0.5em 1em 0.5em 1em; + overflow: auto; + border-left: solid 3px #aaa; + font-size: 15px; + color: #333; +} + +.admonition p { + margin-left: 1em; + } + +.admonition-title { + font-size: 16px; + font-weight: bold; + color: #000; + padding-bottom: 0em; + margin-bottom: .5em; + margin-top: 0em; +} \ No newline at end of file diff --git a/doc/_static/logo-bro.png b/doc/_static/logo-bro.png new file mode 100644 index 0000000000..96cc5d443c Binary files /dev/null and b/doc/_static/logo-bro.png differ diff --git a/doc/_static/pygments.css b/doc/_static/pygments.css new file mode 100644 index 0000000000..3c96f6ae4e --- /dev/null +++ b/doc/_static/pygments.css @@ -0,0 +1,58 @@ +.hll { background-color: #ffffcc } +.c { color: #aaaaaa; font-style: italic } /* Comment */ +.err { color: #F00000; background-color: #F0A0A0 } /* Error */ +.k { color: #0000aa } /* Keyword */ +.cm { color: #aaaaaa; font-style: italic } /* Comment.Multiline */ +.cp { color: #4c8317 } /* Comment.Preproc */ +.c1 { color: #aaaaaa; font-style: italic } /* Comment.Single */ +.cs { color: #0000aa; font-style: italic } /* Comment.Special */ +.gd { color: #aa0000 } /* Generic.Deleted */ +.ge { font-style: italic } /* Generic.Emph */ +.gr { color: #aa0000 } /* Generic.Error */ +.gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.gi { color: #00aa00 } /* Generic.Inserted */ +.go { color: #888888 } /* Generic.Output */ +.gp { color: #555555 } /* Generic.Prompt */ +.gs { font-weight: bold } /* Generic.Strong */ +.gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.gt { color: #aa0000 } /* Generic.Traceback */ +.kc { color: #0000aa } /* Keyword.Constant */ +.kd { color: #0000aa } /* Keyword.Declaration */ +.kn { color: #0000aa } /* Keyword.Namespace */ +.kp { color: #0000aa } /* Keyword.Pseudo */ +.kr { color: #0000aa } /* Keyword.Reserved */ +.kt { color: #00aaaa } /* Keyword.Type */ +.m { color: #009999 } /* Literal.Number */ +.s { color: #aa5500 } /* Literal.String */ +.na { color: #1e90ff } /* Name.Attribute */ +.nb { color: #00aaaa } /* Name.Builtin */ +.nc { color: #00aa00; text-decoration: underline } /* Name.Class */ +.no { color: #aa0000 } /* Name.Constant */ +.nd { color: #888888 } /* Name.Decorator */ +.ni { color: #800000; font-weight: bold } /* Name.Entity */ +.nf { color: #00aa00 } /* Name.Function */ +.nn { color: #00aaaa; text-decoration: underline } /* Name.Namespace */ +.nt { color: #1e90ff; font-weight: bold } /* Name.Tag */ +.nv { color: #aa0000 } /* Name.Variable */ +.ow { color: #0000aa } /* Operator.Word */ +.w { color: #bbbbbb } /* Text.Whitespace */ +.mf { color: #009999 } /* Literal.Number.Float */ +.mh { color: #009999 } /* Literal.Number.Hex */ +.mi { color: #009999 } /* Literal.Number.Integer */ +.mo { color: #009999 } /* Literal.Number.Oct */ +.sb { color: #aa5500 } /* Literal.String.Backtick */ +.sc { color: #aa5500 } /* Literal.String.Char */ +.sd { color: #aa5500 } /* Literal.String.Doc */ +.s2 { color: #aa5500 } /* Literal.String.Double */ +.se { color: #aa5500 } /* Literal.String.Escape */ +.sh { color: #aa5500 } /* Literal.String.Heredoc */ +.si { color: #aa5500 } /* Literal.String.Interpol */ +.sx { color: #aa5500 } /* Literal.String.Other */ +.sr { color: #009999 } /* Literal.String.Regex */ +.s1 { color: #aa5500 } /* Literal.String.Single */ +.ss { color: #0000aa } /* Literal.String.Symbol */ +.bp { color: #00aaaa } /* Name.Builtin.Pseudo */ +.vc { color: #aa0000 } /* Name.Variable.Class */ +.vg { color: #aa0000 } /* Name.Variable.Global */ +.vi { color: #aa0000 } /* Name.Variable.Instance */ +.il { color: #009999 } /* Literal.Number.Integer.Long */ diff --git a/doc/_templates/layout.html b/doc/_templates/layout.html new file mode 100644 index 0000000000..77d9d1de1c --- /dev/null +++ b/doc/_templates/layout.html @@ -0,0 +1,113 @@ +{% extends "!layout.html" %} + +{% block extrahead %} + + + + + + +{% endblock %} + +{% block header %} + +{% endblock %} + +{% block relbar2 %}{% endblock %} +{% block relbar1 %}{% endblock %} + +{% block content %} + +
+
+ +
+ +
+ {{ relbar() }} +
+ +
+ {% block body %} + {% endblock %} +
+
+ + +
+ +
+ +
+
+ + + + + {% if next %} +
+

+ Next Page +

+

+ {{ next.title }} +

+
+ {% endif %} + + {% if prev %} +
+

+ Previous Page +

+

+ {{ prev.title }} +

+
+ {% endif %} + + {%- if pagename != "search" %} + + + {%- endif %} + +
+
+ +
+
+
+ + Copyright {{ copyright }}. + Last updated on {{ last_updated }}. + Created using Sphinx {{ sphinx_version }}. + +
+
+
+
+ + +{% endblock %} + +{% block footer %} + +{% endblock %} diff --git a/doc/scripts/group_index_generator.py b/doc/bin/group_index_generator.py similarity index 97% rename from doc/scripts/group_index_generator.py rename to doc/bin/group_index_generator.py index e9e17f3ca9..720081e8b5 100755 --- a/doc/scripts/group_index_generator.py +++ b/doc/bin/group_index_generator.py @@ -49,6 +49,7 @@ with open(group_list, 'r') as f_group_list: if not os.path.exists(os.path.dirname(group_file)): os.makedirs(os.path.dirname(group_file)) with open(group_file, 'w') as f_group_file: + f_group_file.write(":orphan:\n\n") title = "Package Index: %s\n" % os.path.dirname(group) f_group_file.write(title); for n in range(len(title)): diff --git a/doc/cluster.rst b/doc/cluster.rst new file mode 100644 index 0000000000..ba26471edc --- /dev/null +++ b/doc/cluster.rst @@ -0,0 +1,84 @@ +Bro Cluster +=========== + +Intro +------ + +Bro is not multithreaded, so once the limitations of a single processor core are reached, the only option currently is to spread the workload across many cores or even many physical computers. The cluster deployment scenario for Bro is the current solution to build these larger systems. The accompanying tools and scripts provide the structure to easily manage many Bro processes examining packets and doing correlation activities but acting as a singular, cohesive entity. + +Architecture +--------------- + +The figure below illustrates the main components of a Bro cluster. + +.. image:: images/deployment.png + +Tap +*** +This is a mechanism that splits the packet stream in order to make a copy +available for inspection. Examples include the monitoring port on a switch and +an optical splitter for fiber networks. + +Frontend +******** +This is a discrete hardware device or on-host technique that will split your traffic into many streams or flows. The Bro binary does not do this job. There are numerous ways to accomplish this task, some of which are described below in `Frontend Options`_. + +Manager +******* +This is a Bro process which has two primary jobs. It receives log messages and notices from the rest of the nodes in the cluster using the Bro communications protocol. The result is that you will end up with single logs for each log instead of many discrete logs that you have to later combine in some manner with post processing. The manager also takes the opportunity to de-duplicate notices and it has the ability to do so since it’s acting as the choke point for notices and how notices might be processed into actions such as emailing, paging, or blocking. + +The manager process is started first by BroControl and it only opens it’s designated port and waits for connections, it doesn’t initiate any connections to the rest of the cluster. Once the workers are started and connect to the manager, logs and notices will start arriving to the manager process from the workers. + +Proxy +***** +This is a Bro process which manages synchronized state. Variables can be synchronized across connected Bro processes automatically in Bro and proxies will help the workers by alleviating the need for all of the workers to connect directly to each other. + +Examples of synchronized state from the scripts that ship with Bro are things such as the full list of “known” hosts and services which are hosts or services which have been detected as performing full TCP handshakes or an analyzed protocol has been found on the connection. If worker A detects host 1.2.3.4 as an active host, it would be beneficial for worker B to know that as well so worker A shares that information as an insertion to a set which travels to the cluster’s proxy and the proxy then sends that same set insertion to worker B. The result is that worker A and worker B have shared knowledge about host and services that are active on the network being monitored. + +The proxy model extends to having multiple proxies as well if necessary for performance reasons, it only adds one additional step for the Bro processes. Each proxy connects to another proxy in a ring and the workers are shared between them as evenly as possible. When a proxy receives some new bit of state, it will share that with it’s proxy which is then shared around the ring of proxies and down to all of the workers. From a practical standpoint, there are no rules of thumb established yet for the number of proxies necessary for the number of workers they are serving. Best is to start with a single proxy and add more if communication performance problems are found. + +Bro processes acting as proxies don’t tend to be extremely intense to CPU or memory and users frequently run proxy processes on the same physical host as the manager. + +Worker +****** +This is the Bro process that sniffs network traffic and does protocol analysis on the reassembled traffic streams. Most of the work of an active cluster takes place on the workers and as such, the workers typically represent the bulk of the Bro processes that are running in a cluster. The fastest memory and CPU core speed you can afford is best here since all of the protocol parsing and most analysis will take place here. There are no particular requirements for the disks in workers since almost all logging is done remotely to the manager and very little is normally written to disk. + +The rule of thumb we have followed recently is to allocate approximately 1 core for every 80Mbps of traffic that is being analyzed, however this estimate could be extremely traffic mix specific. It has generally worked for mixed traffic with many users and servers. For example, if your traffic peaks around 2Gbps (combined) and you want to handle traffic at peak load, you may want to have 26 cores available (2048 / 80 == 25.6). If the 80Mbps estimate works for your traffic, this could be handled by 3 physical hosts dedicated to being workers with each one containing dual 6-core processors. + +Once a flow based load balancer is put into place this model is extremely easy to scale as well so it’s recommended that you guess at the amount of hardware you will need to fully analyze your traffic. If it turns out that you need more, it’s relatively easy to increase the size of the cluster in most cases. + +Frontend Options +---------------- + +There are many options for setting up a frontend flow distributor and in many cases it may even be beneficial to do multiple stages of flow distribution on the network and on the host. + +Discrete hardware flow balancers +******************************** + +cPacket +^^^^^^^ + +If you are monitoring one or more 10G physical interfaces, the recommended solution is to use either a cFlow or cVu device from cPacket because they are currently being used very successfully at a number of sites. These devices will perform layer-2 load balancing by rewriting the destination ethernet MAC address to cause each packet associated with a particular flow to have the same destination MAC. The packets can then be passed directly to a monitoring host where each worker has a BPF filter to limit its visibility to only that stream of flows or onward to a commodity switch to split the traffic out to multiple 1G interfaces for the workers. This can ultimately greatly reduce costs since workers can use relatively inexpensive 1G interfaces. + +OpenFlow Switches +^^^^^^^^^^^^^^^^^ + +We are currently exploring the use of OpenFlow based switches to do flow based load balancing directly on the switch which can greatly reduce frontend costs for many users. This document will be updated when we have more information. + +On host flow balancing +********************** + +PF_RING +^^^^^^^ + +The PF_RING software for Linux has a “clustering” feature which will do flow based load balancing across a number of processes that are sniffing the same interface. This will allow you to easily take advantage of multiple cores in a single physical host because Bro’s main event loop is single threaded and can’t natively utilize all of the cores. More information about Bro with PF_RING can be found here: (someone want to write a quick Bro/PF_RING tutorial to link to here? document installing kernel module, libpcap wrapper, building Bro with the --with-pcap configure option) + +Netmap +^^^^^^ + +FreeBSD has an in-progress project named Netmap which will enable flow based load balancing as well. When it becomes viable for real world use, this document will be updated. + +Click! Software Router +^^^^^^^^^^^^^^^^^^^^^^ + +Click! can be used for flow based load balancing with a simple configuration. (link to an example for the config). This solution is not recommended on Linux due to Bro’s PF_RING support and only as a last resort on other operating systems since it causes a lot of overhead due to context switching back and forth between kernel and userland several times per packet. diff --git a/doc/components/binpac/README.rst b/doc/components/binpac/README.rst new file mode 120000 index 0000000000..4eb90ef658 --- /dev/null +++ b/doc/components/binpac/README.rst @@ -0,0 +1 @@ +../../../aux/binpac/README \ No newline at end of file diff --git a/doc/components/bro-aux/README.rst b/doc/components/bro-aux/README.rst new file mode 120000 index 0000000000..628879525d --- /dev/null +++ b/doc/components/bro-aux/README.rst @@ -0,0 +1 @@ +../../../aux/bro-aux/README \ No newline at end of file diff --git a/doc/components/broccoli-python/README.rst b/doc/components/broccoli-python/README.rst new file mode 120000 index 0000000000..4187e87202 --- /dev/null +++ b/doc/components/broccoli-python/README.rst @@ -0,0 +1 @@ +../../../aux/broccoli/bindings/broccoli-python/README \ No newline at end of file diff --git a/doc/components/broccoli-ruby/README.rst b/doc/components/broccoli-ruby/README.rst new file mode 120000 index 0000000000..da71663099 --- /dev/null +++ b/doc/components/broccoli-ruby/README.rst @@ -0,0 +1 @@ +../../../aux/broccoli/bindings/broccoli-ruby/README \ No newline at end of file diff --git a/doc/components/broccoli/README.rst b/doc/components/broccoli/README.rst new file mode 120000 index 0000000000..d32c70ccd9 --- /dev/null +++ b/doc/components/broccoli/README.rst @@ -0,0 +1 @@ +../../../aux/broccoli/README \ No newline at end of file diff --git a/doc/components/broccoli/broccoli-manual.rst b/doc/components/broccoli/broccoli-manual.rst new file mode 120000 index 0000000000..bd5e8d711f --- /dev/null +++ b/doc/components/broccoli/broccoli-manual.rst @@ -0,0 +1 @@ +../../../aux/broccoli/doc/broccoli-manual.rst \ No newline at end of file diff --git a/doc/components/broctl/README.rst b/doc/components/broctl/README.rst new file mode 120000 index 0000000000..cba305f48a --- /dev/null +++ b/doc/components/broctl/README.rst @@ -0,0 +1 @@ +../../../aux/broctl/doc/broctl.rst \ No newline at end of file diff --git a/doc/components/btest/README.rst b/doc/components/btest/README.rst new file mode 120000 index 0000000000..0da2935df1 --- /dev/null +++ b/doc/components/btest/README.rst @@ -0,0 +1 @@ +../../../aux/btest/README \ No newline at end of file diff --git a/doc/components/capstats/README.rst b/doc/components/capstats/README.rst new file mode 120000 index 0000000000..cb2380145d --- /dev/null +++ b/doc/components/capstats/README.rst @@ -0,0 +1 @@ +../../../aux/broctl/aux/capstats/README \ No newline at end of file diff --git a/doc/components/pysubnettree/README.rst b/doc/components/pysubnettree/README.rst new file mode 120000 index 0000000000..42ce17d303 --- /dev/null +++ b/doc/components/pysubnettree/README.rst @@ -0,0 +1 @@ +../../../aux/broctl/aux/pysubnettree/README \ No newline at end of file diff --git a/doc/components/trace-summary/README.rst b/doc/components/trace-summary/README.rst new file mode 120000 index 0000000000..78778364bd --- /dev/null +++ b/doc/components/trace-summary/README.rst @@ -0,0 +1 @@ +../../../aux/broctl/aux/trace-summary/README \ No newline at end of file diff --git a/doc/scripts/conf.py.in b/doc/conf.py.in similarity index 90% rename from doc/scripts/conf.py.in rename to doc/conf.py.in index 419209f580..2e93e82502 100644 --- a/doc/scripts/conf.py.in +++ b/doc/conf.py.in @@ -15,7 +15,7 @@ import sys, os # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -sys.path.insert(0, os.path.abspath('source/ext')) +sys.path.insert(0, os.path.abspath('sphinx-sources/ext')) # -- General configuration ----------------------------------------------------- @@ -24,10 +24,10 @@ sys.path.insert(0, os.path.abspath('source/ext')) # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['bro'] +extensions = ['bro', 'rst_directive', 'sphinx.ext.todo', 'adapt-toc'] # Add any paths that contain templates here, relative to this directory. -templates_path = ['source/_templates'] +templates_path = ['sphinx-sources/_templates', 'sphinx-sources/_static'] # The suffix of source filenames. source_suffix = '.rst' @@ -40,7 +40,7 @@ master_doc = 'index' # General information about the project. project = u'Bro' -copyright = u'2011, The Bro Project' +copyright = u'2012, The Bro Project' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -59,7 +59,7 @@ release = '@VERSION@' # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -90,18 +90,20 @@ pygments_style = 'sphinx' # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' +html_theme = 'basic' + +html_last_updated_fmt = '%B %d, %Y' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +html_theme_options = { } # Add any paths that contain custom themes here, relative to this directory. #html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". +# " v Documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. @@ -119,7 +121,7 @@ html_theme = 'default' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['source/_static'] +html_static_path = ['sphinx-sources/_static'] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. @@ -130,7 +132,9 @@ html_static_path = ['source/_static'] #html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +html_sidebars = { +'**': ['localtoc.html', 'sourcelink.html', 'searchbox.html'], +} # Additional templates that should be rendered to pages, maps page names to # template names. @@ -163,8 +167,9 @@ html_static_path = ['source/_static'] #html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'Brodoc' +htmlhelp_basename = 'Broxygen' +html_add_permalinks = None # -- Options for LaTeX output -------------------------------------------------- @@ -204,7 +209,6 @@ latex_documents = [ # If false, no module index is generated. #latex_domain_indices = True - # -- Options for manual page output -------------------------------------------- # One entry per manual page. List of tuples @@ -213,3 +217,6 @@ man_pages = [ ('index', 'bro', u'Bro Documentation', [u'The Bro Project'], 1) ] + +# -- Options for todo plugin -------------------------------------------- +todo_include_todos=True diff --git a/doc/ext/adapt-toc.py b/doc/ext/adapt-toc.py new file mode 100644 index 0000000000..12ee006977 --- /dev/null +++ b/doc/ext/adapt-toc.py @@ -0,0 +1,29 @@ + +import sys +import re + +# Removes the first TOC level, which is just the page title. +def process_html_toc(app, pagename, templatename, context, doctree): + + if not "toc" in context: + return + + toc = context["toc"] + + lines = toc.strip().split("\n") + lines = lines[2:-2] + + toc = "\n".join(lines) + toc = "
    " + toc + + context["toc"] = toc + + # print >>sys.stderr, pagename + # print >>sys.stderr, context["toc"] + # print >>sys.stderr, "-----" + # print >>sys.stderr, toc + # print >>sys.stderr, "====" + +def setup(app): + app.connect('html-page-context', process_html_toc) + diff --git a/doc/scripts/source/ext/bro.py b/doc/ext/bro.py similarity index 58% rename from doc/scripts/source/ext/bro.py rename to doc/ext/bro.py index 7ec02f76a8..9bdd86bd9a 100644 --- a/doc/scripts/source/ext/bro.py +++ b/doc/ext/bro.py @@ -4,6 +4,9 @@ def setup(Sphinx): Sphinx.add_domain(BroDomain) + Sphinx.add_node(see) + Sphinx.add_directive_to_domain('bro', 'see', SeeDirective) + Sphinx.connect('doctree-resolved', process_see_nodes) from sphinx import addnodes from sphinx.domains import Domain, ObjType, Index @@ -18,7 +21,57 @@ from docutils.parsers.rst import Directive from docutils.parsers.rst import directives from docutils.parsers.rst.roles import set_classes +class see(nodes.General, nodes.Element): + refs = [] + +class SeeDirective(Directive): + has_content = True + + def run(self): + n = see('') + n.refs = string.split(string.join(self.content)) + return [n] + +def process_see_nodes(app, doctree, fromdocname): + for node in doctree.traverse(see): + content = [] + para = nodes.paragraph() + para += nodes.Text("See also:", "See also:") + for name in node.refs: + join_str = " " + if name != node.refs[0]: + join_str = ", " + link_txt = join_str + name; + + if name not in app.env.domaindata['bro']['idtypes']: + # Just create the text and issue warning + app.env.warn(fromdocname, + 'unknown target for ".. bro:see:: %s"' % (name)) + para += nodes.Text(link_txt, link_txt) + else: + # Create a reference + typ = app.env.domaindata['bro']['idtypes'][name] + todocname = app.env.domaindata['bro']['objects'][(typ, name)] + + newnode = nodes.reference('', '') + innernode = nodes.literal(_(name), _(name)) + newnode['refdocname'] = todocname + newnode['refuri'] = app.builder.get_relative_uri( + fromdocname, todocname) + newnode['refuri'] += '#' + typ + '-' + name + newnode.append(innernode) + para += nodes.Text(join_str, join_str) + para += newnode + + content.append(para) + node.replace_self(content) + class BroGeneric(ObjectDescription): + def update_type_map(self, idname): + if 'idtypes' not in self.env.domaindata['bro']: + self.env.domaindata['bro']['idtypes'] = {} + self.env.domaindata['bro']['idtypes'][idname] = self.objtype + def add_target_and_index(self, name, sig, signode): targetname = self.objtype + '-' + name if targetname not in self.state.document.ids: @@ -29,9 +82,6 @@ class BroGeneric(ObjectDescription): objects = self.env.domaindata['bro']['objects'] key = (self.objtype, name) -# this is commented out mostly just to avoid having a special directive -# for events in order to avoid the duplicate warnings in that case - """ if key in objects: self.env.warn(self.env.docname, 'duplicate description of %s %s, ' % @@ -39,8 +89,9 @@ class BroGeneric(ObjectDescription): 'other instance in ' + self.env.doc2path(objects[key]), self.lineno) - """ objects[key] = self.env.docname + self.update_type_map(name) + indextext = self.get_index_text(self.objtype, name) if indextext: self.indexnode['entries'].append(('single', indextext, @@ -65,6 +116,8 @@ class BroNamespace(BroGeneric): objects = self.env.domaindata['bro']['objects'] key = (self.objtype, name) objects[key] = self.env.docname + self.update_type_map(name) + indextext = self.get_index_text(self.objtype, name) self.indexnode['entries'].append(('single', indextext, targetname, targetname)) @@ -91,10 +144,17 @@ class BroEnum(BroGeneric): objects = self.env.domaindata['bro']['objects'] key = (self.objtype, name) objects[key] = self.env.docname + self.update_type_map(name) + indextext = self.get_index_text(self.objtype, name) #self.indexnode['entries'].append(('single', indextext, # targetname, targetname)) m = sig.split() + if m[1] == "Notice::Type": + if 'notices' not in self.env.domaindata['bro']: + self.env.domaindata['bro']['notices'] = [] + self.env.domaindata['bro']['notices'].append( + (m[0], self.env.docname, targetname)) self.indexnode['entries'].append(('single', "%s (enum values); %s" % (m[1], m[0]), targetname, targetname)) @@ -113,6 +173,26 @@ class BroAttribute(BroGeneric): def get_index_text(self, objectname, name): return _('%s (attribute)') % (name) +class BroNotices(Index): + """ + Index subclass to provide the Bro notices index. + """ + + name = 'noticeindex' + localname = l_('Bro Notice Index') + shortname = l_('notices') + + def generate(self, docnames=None): + content = {} + for n in self.domain.env.domaindata['bro']['notices']: + modname = n[0].split("::")[0] + entries = content.setdefault(modname, []) + entries.append([n[0], 0, n[1], n[2], '', '', '']) + + content = sorted(content.iteritems()) + + return content, False + class BroDomain(Domain): """Bro domain.""" name = 'bro' @@ -140,8 +220,13 @@ class BroDomain(Domain): 'id': XRefRole(), 'enum': XRefRole(), 'attr': XRefRole(), + 'see': XRefRole(), } + indices = [ + BroNotices, + ] + initial_data = { 'objects': {}, # fullname -> docname, objtype } @@ -154,13 +239,27 @@ class BroDomain(Domain): def resolve_xref(self, env, fromdocname, builder, typ, target, node, contnode): objects = self.data['objects'] - objtypes = self.objtypes_for_role(typ) - for objtype in objtypes: - if (objtype, target) in objects: - return make_refnode(builder, fromdocname, - objects[objtype, target], - objtype + '-' + target, - contnode, target + ' ' + objtype) + if typ == "see": + if target not in self.data['idtypes']: + self.env.warn(fromdocname, + 'unknown target for ":bro:see:`%s`"' % (target)) + return [] + objtype = self.data['idtypes'][target] + return make_refnode(builder, fromdocname, + objects[objtype, target], + objtype + '-' + target, + contnode, target + ' ' + objtype) + else: + objtypes = self.objtypes_for_role(typ) + for objtype in objtypes: + if (objtype, target) in objects: + return make_refnode(builder, fromdocname, + objects[objtype, target], + objtype + '-' + target, + contnode, target + ' ' + objtype) + else: + self.env.warn(fromdocname, + 'unknown target for ":bro:%s:`%s`"' % (typ, target)) def get_objects(self): for (typ, name), docname in self.data['objects'].iteritems(): diff --git a/testing/btest/Baseline/doc.blacklist-reminder/.stderr b/doc/ext/bro_lexer/__init__.py similarity index 100% rename from testing/btest/Baseline/doc.blacklist-reminder/.stderr rename to doc/ext/bro_lexer/__init__.py diff --git a/doc/ext/bro_lexer/__init__.pyc b/doc/ext/bro_lexer/__init__.pyc new file mode 100644 index 0000000000..1b03eaf1c1 Binary files /dev/null and b/doc/ext/bro_lexer/__init__.pyc differ diff --git a/doc/ext/bro_lexer/bro.py b/doc/ext/bro_lexer/bro.py new file mode 100644 index 0000000000..8cb4475f3b --- /dev/null +++ b/doc/ext/bro_lexer/bro.py @@ -0,0 +1,76 @@ +from pygments.lexer import RegexLexer, bygroups, include +from pygments.token import * + +__all__ = ["BroLexer"] + +class BroLexer(RegexLexer): + name = 'Bro' + aliases = ['bro'] + filenames = ['*.bro'] + + _hex = r'[0-9a-fA-F_]+' + _float = r'((\d*\.?\d+)|(\d+\.?\d*))([eE][-+]?\d+)?' + _h = r'[A-Za-z0-9][-A-Za-z0-9]*' + + tokens = { + 'root': [ + # Whitespace + ('^@.*?\n', Comment.Preproc), + (r'#.*?\n', Comment.Single), + (r'\n', Text), + (r'\s+', Text), + (r'\\\n', Text), + # Keywords + (r'(add|alarm|break|case|const|continue|delete|do|else|enum|event' + r'|export|for|function|if|global|local|module|next' + r'|of|print|redef|return|schedule|when|while)\b', Keyword), + (r'(addr|any|bool|count|counter|double|file|int|interval|net' + r'|pattern|port|record|set|string|subnet|table|time|timer' + r'|vector)\b', Keyword.Type), + (r'(T|F)\b', Keyword.Constant), + (r'(&)((?:add|delete|expire)_func|attr|(create|read|write)_expire' + r'|default|disable_print_hook|raw_output|encrypt|group|log' + r'|mergeable|optional|persistent|priority|redef' + r'|rotate_(?:interval|size)|synchronized)\b', bygroups(Punctuation, + Keyword)), + (r'\s+module\b', Keyword.Namespace), + # Addresses, ports and networks + (r'\d+/(tcp|udp|icmp|unknown)\b', Number), + (r'(\d+\.){3}\d+', Number), + (r'(' + _hex + r'){7}' + _hex, Number), + (r'0x' + _hex + r'(' + _hex + r'|:)*::(' + _hex + r'|:)*', Number), + (r'((\d+|:)(' + _hex + r'|:)*)?::(' + _hex + r'|:)*', Number), + (r'(\d+\.\d+\.|(\d+\.){2}\d+)', Number), + # Hostnames + (_h + r'(\.' + _h + r')+', String), + # Numeric + (_float + r'\s+(day|hr|min|sec|msec|usec)s?\b', Literal.Date), + (r'0[xX]' + _hex, Number.Hex), + (_float, Number.Float), + (r'\d+', Number.Integer), + (r'/', String.Regex, 'regex'), + (r'"', String, 'string'), + # Operators + (r'[!%*/+-:<=>?~|]', Operator), + (r'([-+=&|]{2}|[+-=!><]=)', Operator), + (r'(in|match)\b', Operator.Word), + (r'[{}()\[\]$.,;]', Punctuation), + # Identfier + (r'([_a-zA-Z]\w*)(::)', bygroups(Name, Name.Namespace)), + (r'[a-zA-Z_][a-zA-Z_0-9]*', Name) + ], + 'string': [ + (r'"', String, '#pop'), + (r'\\([\\abfnrtv"\']|x[a-fA-F0-9]{2,4}|[0-7]{1,3})', String.Escape), + (r'[^\\"\n]+', String), + (r'\\\n', String), + (r'\\', String) + ], + 'regex': [ + (r'/', String.Regex, '#pop'), + (r'\\[\\nt/]', String.Regex), # String.Escape is too intense. + (r'[^\\/\n]+', String.Regex), + (r'\\\n', String.Regex), + (r'\\', String.Regex) + ] + } diff --git a/doc/ext/bro_lexer/bro.pyc b/doc/ext/bro_lexer/bro.pyc new file mode 100644 index 0000000000..6471e1528d Binary files /dev/null and b/doc/ext/bro_lexer/bro.pyc differ diff --git a/doc/ext/rst_directive.py b/doc/ext/rst_directive.py new file mode 100644 index 0000000000..434eef2c61 --- /dev/null +++ b/doc/ext/rst_directive.py @@ -0,0 +1,180 @@ +def setup(app): + pass + +# -*- coding: utf-8 -*- +""" + +Modified version of the the Pygments reStructuredText directive. -Robin + +This provides two new directives: + + - .. code:: [] + + Highlights the following code block according to if + given (e.g., "c", "python", etc.). + + - .. console:: + + Highlits the following code block as a shell session. + + For compatibility with the original version, "sourcecode" is + equivalent to "code". + +Original comment: + + The Pygments reStructuredText directive + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + This fragment is a Docutils_ 0.5 directive that renders source code + (to HTML only, currently) via Pygments. + + To use it, adjust the options below and copy the code into a module + that you import on initialization. The code then automatically + registers a ``sourcecode`` directive that you can use instead of + normal code blocks like this:: + + .. sourcecode:: python + + My code goes here. + + If you want to have different code styles, e.g. one with line numbers + and one without, add formatters with their names in the VARIANTS dict + below. You can invoke them instead of the DEFAULT one by using a + directive option:: + + .. sourcecode:: python + :linenos: + + My code goes here. + + Look at the `directive documentation`_ to get all the gory details. + + .. _Docutils: http://docutils.sf.net/ + .. _directive documentation: + http://docutils.sourceforge.net/docs/howto/rst-directives.html + + :copyright: Copyright 2006-2010 by the Pygments team, see AUTHORS. + :license: BSD, see LICENSE for details. +""" + +# Options +# ~~~~~~~ + +# Set to True if you want inline CSS styles instead of classes +INLINESTYLES = False + +from pygments.formatters import HtmlFormatter + +class MyHtmlFormatter(HtmlFormatter): + def format_unencoded(self, tokensource, outfile): + + # A NOP currently. + new_tokens = [] + for (i, piece) in tokensource: + new_tokens += [(i, piece)] + + return super(MyHtmlFormatter, self).format_unencoded(new_tokens, outfile) + +# The default formatter +DEFAULT = MyHtmlFormatter(noclasses=INLINESTYLES, cssclass="pygments") + +# Add name -> formatter pairs for every variant you want to use +VARIANTS = { + # 'linenos': HtmlFormatter(noclasses=INLINESTYLES, linenos=True), +} + + +import textwrap + +from docutils import nodes +from docutils.parsers.rst import directives, Directive + +from pygments import highlight +from pygments.lexers import get_lexer_by_name, guess_lexer, TextLexer +from pygments.token import Text, Keyword, Error, Operator, Name +from pygments.filter import Filter + +# Ugly hack to register the Bro lexer. I'm sure there's a better way to do it, +# but it's not obvious ... +from bro_lexer.bro import BroLexer +from pygments.lexers._mapping import LEXERS +LEXERS['BroLexer'] = ('bro_lexer.bro', BroLexer.name, BroLexer.aliases, BroLexer.filenames, ()) + +class Pygments(Directive): + """ Source code syntax hightlighting. + """ + #max_line_length = 68 + max_line_length = 0 + + required_arguments = 0 + optional_arguments = 1 + final_argument_whitespace = True + option_spec = dict([(key, directives.flag) for key in VARIANTS]) + has_content = True + + def wrapped_content(self): + content = [] + + if Console.max_line_length: + for line in self.content: + content += textwrap.wrap(line, Console.max_line_length, subsequent_indent=" ") + else: + content = self.content + + return u'\n'.join(content) + + def run(self): + self.assert_has_content() + + content = self.wrapped_content() + + if len(self.arguments) > 0: + try: + lexer = get_lexer_by_name(self.arguments[0]) + except (ValueError, IndexError): + # lexer not found, use default. + lexer = TextLexer() + else: + lexer = guess_lexer(content) + + # import sys + # print >>sys.stderr, self.arguments, lexer.__class__ + + # take an arbitrary option if more than one is given + formatter = self.options and VARIANTS[self.options.keys()[0]] or DEFAULT + parsed = highlight(content, lexer, formatter) + return [nodes.raw('', parsed, format='html')] + +class MyFilter(Filter): + def filter(self, lexer, stream): + + bol = True + + for (ttype, value) in stream: + # Color the '>' prompt sign. + if bol and ttype is Text and value == ">": + ttype = Name.Variable.Class # This gives us a nice red. + + # Discolor builtin, that can look funny. + if ttype is Name.Builtin: + ttype = Text + + bol = value.endswith("\n") + + yield (ttype, value) + +class Console(Pygments): + required_arguments = 0 + optional_arguments = 0 + + def run(self): + self.assert_has_content() + content = self.wrapped_content() + lexer = get_lexer_by_name("sh") + lexer.add_filter(MyFilter()) + parsed = highlight(content, lexer, DEFAULT) + return [nodes.raw('', parsed, format='html')] + +directives.register_directive('sourcecode', Pygments) +directives.register_directive('code', Pygments) +directives.register_directive('console', Console) diff --git a/doc/faq.rst b/doc/faq.rst new file mode 100644 index 0000000000..8545cc57ee --- /dev/null +++ b/doc/faq.rst @@ -0,0 +1,171 @@ + +========================== +Frequently Asked Questions +========================== + +.. raw:: html + +
    + +.. contents:: + +Installation and Configuration +============================== + +How can I tune my operating system for best capture performance? +---------------------------------------------------------------- + +Here are some pointers to more information: + +* Fabian Schneider's research on `high performance packet capture + `_ + +* `NSMWiki `_ has page on + *Collecting Data*. + +* An `IMC 2010 paper + `_ by + Lothar Braun et. al evaluates packet capture performance on + commodity hardware + +Are there any gotchas regarding interface configuration for live capture? Or why might I be seeing abnormally large packets much greater than interface MTU? +------------------------------------------------------------------------------------------------------------------------------------------------------------- + +Some NICs offload the reassembly of traffic into "superpackets" so that +fewer packets are then passed up the stack (e.g. "TCP segmentation +offload", or "generic segmentation offload"). The result is that the +capturing application will observe packets much larger than the MTU size +of the interface they were captured from and may also interfere with the +maximum packet capture length, ``snaplen``, so it's a good idea to disable +an interface's offloading features. + +You can use the ``ethtool`` program on Linux to view and disable +offloading features of an interface. See this page for more explicit +directions: + +http://securityonion.blogspot.com/2011/10/when-is-full-packet-capture-not-full.html + +What does an error message like ``internal error: NB-DNS error`` mean? +--------------------------------------------------------------------------------------------------------------------------------- + +That often means that DNS is not set up correctly on the system +running Bro. Try verifying from the command line that DNS lookups +work, e.g., ``host www.google.com``. + +I am using OpenBSD and having problems installing Bro? +------------------------------------------------------ + +One potential issue is that the top-level Makefile may not work with +OpenBSD's default make program, in which case you can either install +the ``gmake`` package and use it instead or first change into the +``build/`` directory before doing either ``make`` or ``make install`` +such that the CMake-generated Makefile's are used directly. + +Generally, please note that we do not regularly test OpenBSD builds. +We appreciate any patches that improve Bro's support for this +platform. + + +Usage +===== + +How can I identify backscatter? +------------------------------- + +Identifying backscatter via connections labeled as ``OTH`` is not a reliable +means to detect backscatter. Backscatter is however visible by interpreting +the contents of the ``history`` field in the ``conn.log`` file. The basic idea +is to watch for connections that never had an initial ``SYN`` but started +instead with a ``SYN-ACK`` or ``RST`` (though this latter generally is just +discarded). Here are some history fields which provide backscatter examples: +``hAFf``, ``r``. Refer to the conn protocol analysis scripts to interpret the +individual character meanings in the history field. + +Is there help for understanding Bro's resource consumption? +----------------------------------------------------------- + +There are two scripts that collect statistics on resource usage: +``misc/stats.bro`` and ``misc/profiling.bro``. The former is quite +lightweight, while the latter should only be used for debugging. + +How can I capture packets as an unprivileged user? +-------------------------------------------------- + +Normally, unprivileged users cannot capture packets from a network interface, +which means they would not be able to use Bro to read/analyze live traffic. +However, there are operating system specific ways to enable packet capture +permission for non-root users, which is worth doing in the context of using +Bro to monitor live traffic. + +With Linux Capabilities +^^^^^^^^^^^^^^^^^^^^^^^ + +Fully implemented since Linux kernel 2.6.24, capabilities are a way of +parceling superuser privileges into distinct units. Attach capabilities +required to capture packets to the ``bro`` executable file like this: + +.. console:: + + sudo setcap cap_net_raw,cap_net_admin=eip /path/to/bro + +Now any unprivileged user should have the capability to capture packets +using Bro provided that they have the traditional file permissions to +read/execute the ``bro`` binary. + +With BPF Devices +^^^^^^^^^^^^^^^^ + +Systems using Berkeley Packet Filter (BPF) (e.g. FreeBSD & Mac OS X) +can allow users with read access to a BPF device to capture packets from +it using libpcap. + +* Example of manually changing BPF device permissions to allow users in + the ``admin`` group to capture packets: + +.. console:: + + sudo chgrp admin /dev/bpf* + sudo chmod g+r /dev/bpf* + +* Example of configuring devfs to set permissions of BPF devices, adding + entries to ``/etc/devfs.conf`` to grant ``admin`` group permission to + capture packets: + +.. console:: + + sudo sh -c 'echo "own bpf root:admin" >> /etc/devfs.conf' + sudo sh -c 'echo "perm bpf 0640" >> /etc/devfs.conf' + sudo service devfs restart + +.. note:: As of Mac OS X 10.6, the BPF device is on devfs, but the used version + of devfs isn't capable of setting the device permissions. The permissions + can be changed manually, but they will not survive a reboot. + +Why isn't Bro producing the logs I expect? (A Note About Checksums) +------------------------------------------------------------------- + +Normally, Bro's event engine will discard packets which don't have valid +checksums. This can be a problem if one wants to analyze locally +generated/captured traffic on a system that offloads checksumming to the +network adapter. In that case, all transmitted/captured packets will have +bad checksums because they haven't yet been calculated by the NIC, thus +such packets will not undergo analysis defined in Bro policy scripts as they +normally would. Bad checksums in traces may also be a result of some packet +alteration tools. + +Bro has two options to workaround such situations and ignore bad checksums: + +1) The ``-C`` command line option to ``bro``. +2) An option called ``ignore_checksums`` that can be redefined at the + policy script layer (e.g. in your ``$PREFIX/share/bro/site/local.bro``): + + .. code:: bro + + redef ignore_checksums = T; + +The other alternative is to disable checksum offloading for your +network adapter, but this is not always possible or desirable. + +.. raw:: html + +
    diff --git a/doc/geoip.rst b/doc/geoip.rst new file mode 100644 index 0000000000..bd9ae0c08d --- /dev/null +++ b/doc/geoip.rst @@ -0,0 +1,102 @@ + +=========== +GeoLocation +=========== + +.. rst-class:: opening + + During the process of creating policy scripts the need may arise + to find the geographic location for an IP address. Bro has support + for the `GeoIP library `__ at the + policy script level beginning with release 1.3 to account for this + need. + +.. contents:: + +GeoIPLite Database Installation +------------------------------------ + +A country database for GeoIPLite is included when you do the C API +install, but for Bro, we are using the city database which includes +cities and regions in addition to countries. + +`Download `__ the geolitecity +binary database and follow the directions to install it. + +FreeBSD Quick Install +--------------------- + +.. console:: + + pkg_add -r GeoIP + wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz + gunzip GeoLiteCity.dat.gz + mv GeoLiteCity.dat /usr/local/share/GeoIP/GeoIPCity.dat + + # Set your environment correctly before running Bro's configure script + export CFLAGS=-I/usr/local/include + export LDFLAGS=-L/usr/local/lib + + +CentOS Quick Install +-------------------- + +.. console:: + + yum install GeoIP-devel + + wget http://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz + gunzip GeoLiteCity.dat.gz + mkdir -p /var/lib/GeoIP/ + mv GeoLiteCity.dat /var/lib/GeoIP/GeoIPCity.dat + + # Set your environment correctly before running Bro's configure script + export CFLAGS=-I/usr/local/include + export LDFLAGS=-L/usr/local/lib + + +Usage +----- + +There is a single built in function that provides the GeoIP +functionality: + +.. code:: bro + + function lookup_location(a:addr): geo_location + +There is also the ``geo_location`` data structure that is returned +from the ``lookup_location`` function: + +.. code:: bro + + type geo_location: record { + country_code: string; + region: string; + city: string; + latitude: double; + longitude: double; + }; + + +Example +------- + +To write a line in a log file for every ftp connection from hosts in +Ohio, this is now very easy: + +.. code:: bro + + global ftp_location_log: file = open_log_file("ftp-location"); + + event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool) + { + local client = c$id$orig_h; + local loc = lookup_location(client); + if (loc$region == "OH" && loc$country_code == "US") + { + print ftp_location_log, fmt("FTP Connection from:%s (%s,%s,%s)", client, loc$city, loc$region, loc$country_code); + } + } + + diff --git a/doc/images/deployment.png b/doc/images/deployment.png new file mode 100644 index 0000000000..abd9b92722 Binary files /dev/null and b/doc/images/deployment.png differ diff --git a/doc/index.rst b/doc/index.rst new file mode 100644 index 0000000000..ec67b76fd8 --- /dev/null +++ b/doc/index.rst @@ -0,0 +1,89 @@ +.. Bro documentation master file + +================= +Bro Documentation +================= + +Guides +------ + +.. toctree:: + :maxdepth: 1 + + INSTALL + quickstart + upgrade + faq + reporting-problems + +Frameworks +---------- + +.. toctree:: + :maxdepth: 1 + + notice + logging + cluster + signatures + +How-Tos +------- + +.. toctree:: + :maxdepth: 1 + + geoip + +Script Reference +---------------- + +.. toctree:: + :maxdepth: 1 + + scripts/packages + scripts/index + scripts/builtins + scripts/bifs + +Other Bro Components +-------------------- + +The following are snapshots of documentation for components that come +with this version of Bro (|version|). Since they can also be used +independently, see the `download page +`_ for documentation of any +current, independent component releases. + +.. toctree:: + :maxdepth: 1 + + BinPAC - A protocol parser generator + Broccoli - The Bro Client Communication Library (README) + Broccoli - User Manual + Broccoli Python Bindings + Broccoli Ruby Bindings + BroControl - Interactive Bro management shell + Bro-Aux - Small auxiliary tools for Bro + BTest - A unit testing framework + Capstats - Command-line packet statistic tool + PySubnetTree - Python module for CIDR lookups + trace-summary - Script for generating break-downs of network traffic + +The `Broccoli API Reference `_ may also be of +interest. + +Other Indices and References +---------------------------- + +* :ref:`General Index ` +* `Notice Index `_ +* :ref:`search` + +Internal References +------------------- + +.. toctree:: + :maxdepth: 1 + + scripts/internal diff --git a/doc/logging.rst b/doc/logging.rst new file mode 100644 index 0000000000..30a793df7d --- /dev/null +++ b/doc/logging.rst @@ -0,0 +1,375 @@ +========================== +Customizing Bro's Logging +========================== + +.. rst-class:: opening + + Bro comes with a flexible key-value based logging interface that + allows fine-grained control of what gets logged and how it is + logged. This document describes how logging can be customized and + extended. + +.. contents:: + +Terminology +=========== + +Bro's logging interface is built around three main abstractions: + + Log streams + A stream corresponds to a single log. It defines the set of + fields that a log consists of with their names and fields. + Examples are the ``conn`` for recording connection summaries, + and the ``http`` stream for recording HTTP activity. + + Filters + Each stream has a set of filters attached to it that determine + what information gets written out. By default, each stream has + one default filter that just logs everything directly to disk + with an automatically generated file name. However, further + filters can be added to record only a subset, split a stream + into different outputs, or to even duplicate the log to + multiple outputs. If all filters are removed from a stream, + all output is disabled. + + Writers + A writer defines the actual output format for the information + being logged. At the moment, Bro comes with only one type of + writer, which produces tab separated ASCII files. In the + future we will add further writers, like for binary output and + direct logging into a database. + +Basics +====== + +The data fields that a stream records are defined by a record type +specified when it is created. Let's look at the script generating Bro's +connection summaries as an example, +:doc:`scripts/base/protocols/conn/main`. It defines a record +:bro:type:`Conn::Info` that lists all the fields that go into +``conn.log``, each marked with a ``&log`` attribute indicating that it +is part of the information written out. To write a log record, the +script then passes an instance of :bro:type:`Conn::Info` to the logging +framework's :bro:id:`Log::write` function. + +By default, each stream automatically gets a filter named ``default`` +that generates the normal output by recording all record fields into a +single output file. + +In the following, we summarize ways in which the logging can be +customized. We continue using the connection summaries as our example +to work with. + +Filtering +--------- + +To create a new output file for an existing stream, you can add a +new filter. A filter can, e.g., restrict the set of fields being +logged: + +.. code:: bro + + event bro_init() + { + # Add a new filter to the Conn::LOG stream that logs only + # timestamp and originator address. + local filter: Log::Filter = [$name="orig-only", $path="origs", $include=set("ts", "id.orig_h")]; + Log::add_filter(Conn::LOG, filter); + } + +Note the fields that are set for the filter: + + ``name`` + A mandatory name for the filter that can later be used + to manipulate it further. + + ``path`` + The filename for the output file, without any extension (which + may be automatically added by the writer). Default path values + are generated by taking the stream's ID and munging it slightly. + :bro:enum:`Conn::LOG` is converted into ``conn``, + :bro:enum:`PacketFilter::LOG` is converted into + ``packet_filter``, and :bro:enum:`Notice::POLICY_LOG` is + converted into ``notice_policy``. + + ``include`` + A set limiting the fields to the ones given. The names + correspond to those in the :bro:type:`Conn::Info` record, with + sub-records unrolled by concatenating fields (separated with + dots). + +Using the code above, you will now get a new log file ``origs.log`` +that looks like this:: + + #separator \x09 + #path origs + #fields ts id.orig_h + #types time addr + 1128727430.350788 141.42.64.125 + 1128727435.450898 141.42.64.125 + +If you want to make this the only log file for the stream, you can +remove the default filter (which, conveniently, has the name +``default``): + +.. code:: bro + + event bro_init() + { + # Remove the filter called "default". + Log::remove_filter(Conn::LOG, "default"); + } + +An alternate approach to "turning off" a log is to completely disable +the stream: + +.. code:: bro + + event bro_init() + { + Log::disable_stream(Conn::LOG); + } + +If you want to skip only some fields but keep the rest, there is a +corresponding ``exclude`` filter attribute that you can use instead of +``include`` to list only the ones you are not interested in. + +A filter can also determine output paths *dynamically* based on the +record being logged. That allows, e.g., to record local and remote +connections into separate files. To do this, you define a function +that returns the desired path: + +.. code:: bro + + function split_log(id: Log::ID, path: string, rec: Conn::Info) : string + { + # Return "conn-local" if originator is a local IP, otherwise "conn-remote". + local lr = Site::is_local_addr(rec$id$orig_h) ? "local" : "remote"; + return fmt("%s-%s", path, lr); + } + + event bro_init() + { + local filter: Log::Filter = [$name="conn-split", $path_func=split_log, $include=set("ts", "id.orig_h")]; + Log::add_filter(Conn::LOG, filter); + } + +Running this will now produce two files, ``local.log`` and +``remote.log``, with the corresponding entries. One could extend this +further for example to log information by subnets or even by IP +address. Be careful, however, as it is easy to create many files very +quickly ... + +.. sidebar:: A More Generic Path Function + + The ``split_log`` method has one draw-back: it can be used + only with the :bro:enum:`Conn::LOG` stream as the record type is hardcoded + into its argument list. However, Bro allows to do a more generic + variant: + + .. code:: bro + + function split_log(id: Log::ID, path: string, rec: record { id: conn_id; } ) : string + { + return Site::is_local_addr(rec$id$orig_h) ? "local" : "remote"; + } + + This function can be used with all log streams that have records + containing an ``id: conn_id`` field. + +While so far we have seen how to customize the columns being logged, +you can also control which records are written out by providing a +predicate that will be called for each log record: + +.. code:: bro + + function http_only(rec: Conn::Info) : bool + { + # Record only connections with successfully analyzed HTTP traffic + return rec$service == "http"; + } + + event bro_init() + { + local filter: Log::Filter = [$name="http-only", $path="conn-http", $pred=http_only]; + Log::add_filter(Conn::LOG, filter); + } + +This will result in a log file ``conn-http.log`` that contains only +traffic detected and analyzed as HTTP traffic. + +Extending +--------- + +You can add further fields to a log stream by extending the record +type that defines its content. Let's say we want to add a boolean +field ``is_private`` to :bro:type:`Conn::Info` that indicates whether the +originator IP address is part of the :rfc:`1918` space: + +.. code:: bro + + # Add a field to the connection log record. + redef record Conn::Info += { + ## Indicate if the originator of the connection is part of the + ## "private" address space defined in RFC1918. + is_private: bool &default=F &log; + }; + + +Now we need to set the field. A connection's summary is generated at +the time its state is removed from memory. We can add another handler +at that time that sets our field correctly: + +.. code:: bro + + event connection_state_remove(c: connection) + { + if ( c$id$orig_h in Site::private_address_space ) + c$conn$is_private = T; + } + +Now ``conn.log`` will show a new field ``is_private`` of type +``bool``. + +Notes: + +- For extending logs this way, one needs a bit of knowledge about how + the script that creates the log stream is organizing its state + keeping. Most of the standard Bro scripts attach their log state to + the :bro:type:`connection` record where it can then be accessed, just + as the ``c$conn`` above. For example, the HTTP analysis adds a field + ``http`` of type :bro:type:`HTTP::Info` to the :bro:type:`connection` + record. See the script reference for more information. + +- When extending records as shown above, the new fields must always be + declared either with a ``&default`` value or as ``&optional``. + Furthermore, you need to add the ``&log`` attribute or otherwise the + field won't appear in the output. + +Hooking into the Logging +------------------------ + +Sometimes it is helpful to do additional analysis of the information +being logged. For these cases, a stream can specify an event that will +be generated every time a log record is written to it. All of Bro's +default log streams define such an event. For example, the connection +log stream raises the event :bro:id:`Conn::log_conn`. You +could use that for example for flagging when a connection to a +specific destination exceeds a certain duration: + +.. code:: bro + + redef enum Notice::Type += { + ## Indicates that a connection remained established longer + ## than 5 minutes. + Long_Conn_Found + }; + + event Conn::log_conn(rec: Conn::Info) + { + if ( rec$duration > 5mins ) + NOTICE([$note=Long_Conn_Found, + $msg=fmt("unusually long conn to %s", rec$id$resp_h), + $id=rec$id]); + } + +Often, these events can be an alternative to post-processing Bro logs +externally with Perl scripts. Much of what such an external script +would do later offline, one may instead do directly inside of Bro in +real-time. + +Rotation +-------- + +By default, no log rotation occurs, but it's globally controllable for all +filters by redefining the :bro:id:`Log::default_rotation_interval` option: + +.. code:: bro + + redef Log::default_rotation_interval = 1 hr; + +Or specifically for certain :bro:type:`Log::Filter` instances by setting +their ``interv`` field. Here's an example of changing just the +:bro:enum:`Conn::LOG` stream's default filter rotation. + +.. code:: bro + + event bro_init() + { + local f = Log::get_filter(Conn::LOG, "default"); + f$interv = 1 min; + Log::remove_filter(Conn::LOG, "default"); + Log::add_filter(Conn::LOG, f); + } + +ASCII Writer Configuration +-------------------------- + +The ASCII writer has a number of options for customizing the format of +its output, see :doc:`scripts/base/frameworks/logging/writers/ascii`. + +Adding Streams +============== + +It's easy to create a new log stream for custom scripts. Here's an +example for the ``Foo`` module: + +.. code:: bro + + module Foo; + + export { + # Create an ID for our new stream. By convention, this is + # called "LOG". + redef enum Log::ID += { LOG }; + + # Define the fields. By convention, the type is called "Info". + type Info: record { + ts: time &log; + id: conn_id &log; + }; + + # Define a hook event. By convention, this is called + # "log_". + global log_foo: event(rec: Info); + + } + + # This event should be handled at a higher priority so that when + # users modify your stream later and they do it at priority 0, + # their code runs after this. + event bro_init() &priority=5 + { + # Create the stream. This also adds a default filter automatically. + Log::create_stream(Foo::LOG, [$columns=Info, $ev=log_foo]); + } + +You can also add the state to the :bro:type:`connection` record to make +it easily accessible across event handlers: + +.. code:: bro + + redef record connection += { + foo: Info &optional; + } + +Now you can use the :bro:id:`Log::write` method to output log records and +save the logged ``Foo::Info`` record into the connection record: + +.. code:: bro + + event connection_established(c: connection) + { + local rec: Foo::Info = [$ts=network_time(), $id=c$id]; + c$foo = rec; + Log::write(Foo::LOG, rec); + } + +See the existing scripts for how to work with such a new connection +field. A simple example is :doc:`scripts/base/protocols/syslog/main`. + +When you are developing scripts that add data to the :bro:type:`connection` +record, care must be given to when and how long data is stored. +Normally data saved to the connection record will remain there for the +duration of the connection and from a practical perspective it's not +uncommon to need to delete that data before the end of the connection. diff --git a/doc/notice.rst b/doc/notice.rst new file mode 100644 index 0000000000..5849e605a9 --- /dev/null +++ b/doc/notice.rst @@ -0,0 +1,395 @@ + +Notice Framework +================ + +.. rst-class:: opening + + One of the easiest ways to customize Bro is writing a local notice + policy. Bro can detect a large number of potentially interesting + situations, and the notice policy tells which of them the user wants to be + acted upon in some manner. In particular, the notice policy can specify + actions to be taken, such as sending an email or compiling regular + alarm emails. This page gives an introduction into writing such a notice + policy. + +.. contents:: + +Overview +-------- + +Let's start with a little bit of background on Bro's philosophy on reporting +things. Bro ships with a large number of policy scripts which perform a wide +variety of analyses. Most of these scripts monitor for activity which might be +of interest for the user. However, none of these scripts determines the +importance of what it finds itself. Instead, the scripts only flag situations +as *potentially* interesting, leaving it to the local configuration to define +which of them are in fact actionable. This decoupling of detection and +reporting allows Bro to address the different needs that sites have: +definitions of what constitutes an attack or even a compromise differ quite a +bit between environments, and activity deemed malicious at one site might be +fully acceptable at another. + +Whenever one of Bro's analysis scripts sees something potentially +interesting it flags the situation by calling the :bro:see:`NOTICE` +function and giving it a single :bro:see:`Notice::Info` record. A Notice +has a :bro:see:`Notice::Type`, which reflects the kind of activity that +has been seen, and it is usually also augmented with further context +about the situation. + +More information about raising notices can be found in the `Raising Notices`_ +section. + +Once a notice is raised, it can have any number of actions applied to it by +the :bro:see:`Notice::policy` set which is described in the `Notice Policy`_ +section below. Such actions can be to send a mail to the configured +address(es) or to simply ignore the notice. Currently, the following actions +are defined: + +.. list-table:: + :widths: 20 80 + :header-rows: 1 + + * - Action + - Description + + * - Notice::ACTION_LOG + - Write the notice to the :bro:see:`Notice::LOG` logging stream. + + * - Notice::ACTION_ALARM + - Log into the :bro:see:`Notice::ALARM_LOG` stream which will rotate + hourly and email the contents to the email address or addresses + defined in the :bro:see:`Notice::mail_dest` variable. + + * - Notice::ACTION_EMAIL + - Send the notice in an email to the email address or addresses given in + the :bro:see:`Notice::mail_dest` variable. + + * - Notice::ACTION_PAGE + - Send an email to the email address or addresses given in the + :bro:see:`Notice::mail_page_dest` variable. + + * - Notice::ACTION_NO_SUPPRESS + - This action will disable the built in notice suppression for the + notice. Keep in mind that this action will need to be applied to + every notice that shouldn't be suppressed including each of the future + notices that would have normally been suppressed. + +How these notice actions are applied to notices is discussed in the +`Notice Policy`_ and `Notice Policy Shortcuts`_ sections. + +Processing Notices +------------------ + +Notice Policy +************* + +The predefined set :bro:see:`Notice::policy` provides the mechanism for +applying actions and other behavior modifications to notices. Each entry +of :bro:see:`Notice::policy` is a record of the type +:bro:see:`Notice::PolicyItem` which defines a condition to be matched +against all raised notices and one or more of a variety of behavior +modifiers. The notice policy is defined by adding any number of +:bro:see:`Notice::PolicyItem` records to the :bro:see:`Notice::policy` +set. + +Here's a simple example which tells Bro to send an email for all notices of +type :bro:see:`SSH::Login` if the server is 10.0.0.1: + +.. code:: bro + + redef Notice::policy += { + [$pred(n: Notice::Info) = { + return n$note == SSH::Login && n$id$resp_h == 10.0.0.1; + }, + $action = Notice::ACTION_EMAIL] + }; + +.. note:: + + Keep in mind that the semantics of the SSH::Login notice are + such that it is only raised when Bro heuristically detects a successful + login. No apparently failed logins will raise this notice. + +While the syntax might look a bit convoluted at first, it provides a lot of +flexibility due to having access to Bro's full programming language. + +Predicate Field +^^^^^^^^^^^^^^^ + +The :bro:see:`Notice::PolicyItem` record type has a field name ``$pred`` +which defines the entry's condition in the form of a predicate written +as a Bro function. The function is passed the notice as a +:bro:see:`Notice::Info` record and it returns a boolean value indicating +if the entry is applicable to that particular notice. + +.. note:: + + The lack of a predicate in a ``Notice::PolicyItem`` is implicitly true + (``T``) since an implicit false (``F``) value would never be used. + +Bro evaluates the predicates of each entry in the order defined by the +``$priority`` field in :bro:see:`Notice::PolicyItem` records. The valid +values are 0-10 with 10 being earliest evaluated. If ``$priority`` is +omitted, the default priority is 5. + +Behavior Modification Fields +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There are a set of fields in the :bro:see:`Notice::PolicyItem` record type that +indicate ways that either the notice or notice processing should be modified +if the predicate field (``$pred``) evaluated to true (``T``). Those fields are +explained in more detail in the following table. + +.. list-table:: + :widths: 20 30 20 + :header-rows: 1 + + * - Field + - Description + - Example + + * - ``$action=`` + - Each :bro:see:`Notice::PolicyItem` can have a single action + applied to the notice with this field. + - ``$action = Notice::ACTION_EMAIL`` + + * - ``$suppress_for=`` + - This field makes it possible for a user to modify the behavior of the + notice framework's automated suppression of intrinsically similar + notices. More information about the notice framework's automated + suppression can be found in the `Automated Suppression`_ section of + this document. + - ``$suppress_for = 10mins`` + + * - ``$halt=`` + - This field can be used for modification of the notice policy + evaluation. To stop processing of notice policy items before + evaluating all of them, set this field to ``T`` and make the ``$pred`` + field return ``T``. :bro:see:`Notice::PolicyItem` records defined at + a higher priority as defined by the ``$priority`` field will still be + evaluated but those at a lower priority won't. + - ``$halt = T`` + + + +.. code:: bro + + redef Notice::policy += { + [$pred(n: Notice::Info) = { + return n$note == SSH::Login && n$id$resp_h == 10.0.0.1; + }, + $action = Notice::ACTION_EMAIL, + $priority=5] + }; + + +Notice Policy Shortcuts +*********************** + +Although the notice framework provides a great deal of flexibility and +configurability there are many times that the full expressiveness isn't needed +and actually becomes a hindrance to achieving results. The framework provides +a default :bro:see:`Notice::policy` suite as a way of giving users the +shortcuts to easily apply many common actions to notices. + +These are implemented as sets and tables indexed with a +:bro:see:`Notice::Type` enum value. The following table shows and describes +all of the variables available for shortcut configuration of the notice +framework. + +.. list-table:: + :widths: 32 40 + :header-rows: 1 + + * - Variable name + - Description + + * - :bro:see:`Notice::ignored_types` + - Adding a :bro:see:`Notice::Type` to this set results in the notice + being ignored. It won't have any other action applied to it, not even + :bro:see:`Notice::ACTION_LOG`. + + * - :bro:see:`Notice::emailed_types` + - Adding a :bro:see:`Notice::Type` to this set results in + :bro:see:`Notice::ACTION_EMAIL` being applied to the notices of + that type. + + * - :bro:see:`Notice::alarmed_types` + - Adding a :bro:see:`Notice::Type` to this set results in + :bro:see:`Notice::ACTION_ALARM` being applied to the notices of + that type. + + * - :bro:see:`Notice::not_suppressed_types` + - Adding a :bro:see:`Notice::Type` to this set results in that notice + no longer undergoing the normal notice suppression that would + take place. Be careful when using this in production it could + result in a dramatic increase in the number of notices being + processed. + + * - :bro:see:`Notice::type_suppression_intervals` + - This is a table indexed on :bro:see:`Notice::Type` and yielding an + interval. It can be used as an easy way to extend the default + suppression interval for an entire :bro:see:`Notice::Type` + without having to create a whole :bro:see:`Notice::policy` entry + and setting the ``$suppress_for`` field. + +Raising Notices +--------------- + +A script should raise a notice for any occurrence that a user may want +to be notified about or take action on. For example, whenever the base +SSH analysis scripts sees an SSH session where it is heuristically +guessed to be a successful login, it raises a Notice of the type +:bro:see:`SSH::Login`. The code in the base SSH analysis script looks +like this: + +.. code:: bro + + NOTICE([$note=SSH::Login, + $msg="Heuristically detected successful SSH login.", + $conn=c]); + +:bro:see:`NOTICE` is a normal function in the global namespace which +wraps a function within the ``Notice`` namespace. It takes a single +argument of the :bro:see:`Notice::Info` record type. The most common +fields used when raising notices are described in the following table: + +.. list-table:: + :widths: 32 40 + :header-rows: 1 + + * - Field name + - Description + + * - ``$note`` + - This field is required and is an enum value which represents the + notice type. + + * - ``$msg`` + - This is a human readable message which is meant to provide more + information about this particular instance of the notice type. + + * - ``$sub`` + - This is a sub-message meant for human readability but will + frequently also be used to contain data meant to be matched with the + ``Notice::policy``. + + * - ``$conn`` + - If a connection record is available when the notice is being raised + and the notice represents some attribute of the connection, then the + connection record can be given here. Other fields such as ``$id`` and + ``$src`` will automatically be populated from this value. + + * - ``$id`` + - If a conn_id record is available when the notice is being raised and + the notice represents some attribute of the connection, then the + connection can be given here. Other fields such as ``$src`` will + automatically be populated from this value. + + * - ``$src`` + - If the notice represents an attribute of a single host then it's + possible that only this field should be filled out to represent the + host that is being "noticed". + + * - ``$n`` + - This normally represents a number if the notice has to do with some + number. It's most frequently used for numeric tests in the + ``Notice::policy`` for making policy decisions. + + * - ``$identifier`` + - This represents a unique identifier for this notice. This field is + described in more detail in the `Automated Suppression`_ section. + + * - ``$suppress_for`` + - This field can be set if there is a natural suppression interval for + the notice that may be different than the default value. The + value set to this field can also be modified by a user's + :bro:see:`Notice::policy` so the value is not set permanently + and unchangeably. + +When writing Bro scripts which raise notices, some thought should be given to +what the notice represents and what data should be provided to give a consumer +of the notice the best information about the notice. If the notice is +representative of many connections and is an attribute of a host (e.g. a +scanning host) it probably makes most sense to fill out the ``$src`` field and +not give a connection or conn_id. If a notice is representative of a +connection attribute (e.g. an apparent SSH login) then it makes sense to fill +out either ``$conn`` or ``$id`` based on the data that is available when the +notice is raised. Using care when inserting data into a notice will make later +analysis easier when only the data to fully represent the occurrence that +raised the notice is available. If complete connection information is +available when an SSL server certificate is expiring, the logs will be very +confusing because the connection that the certificate was detected on is a +side topic to the fact that an expired certificate was detected. It's possible +in many cases that two or more separate notices may need to be generated. As +an example, one could be for the detection of the expired SSL certificate and +another could be for if the client decided to go ahead with the connection +neglecting the expired certificate. + +Automated Suppression +--------------------- + +The notice framework supports suppression for notices if the author of the +script that is generating the notice has indicated to the notice framework how +to identify notices that are intrinsically the same. Identification of these +"intrinsically duplicate" notices is implemented with an optional field in +:bro:see:`Notice::Info` records named ``$identifier`` which is a simple string. +If the ``$identifier`` and ``$type`` fields are the same for two notices, the +notice framework actually considers them to be the same thing and can use that +information to suppress duplicates for a configurable period of time. + +.. note:: + + If the ``$identifier`` is left out of a notice, no notice suppression + takes place due to the framework's inability to identify duplicates. This + could be completely legitimate usage if no notices could ever be + considered to be duplicates. + +The ``$identifier`` field is typically comprised of several pieces of +data related to the notice that when combined represent a unique +instance of that notice. Here is an example of the script +:doc:`scripts/policy/protocols/ssl/validate-certs` raising a notice +for session negotiations where the certificate or certificate chain did +not validate successfully against the available certificate authority +certificates. + +.. code:: bro + + NOTICE([$note=SSL::Invalid_Server_Cert, + $msg=fmt("SSL certificate validation failed with (%s)", c$ssl$validation_status), + $sub=c$ssl$subject, + $conn=c, + $identifier=cat(c$id$resp_h,c$id$resp_p,c$ssl$validation_status,c$ssl$cert_hash)]); + +In the above example you can see that the ``$identifier`` field contains a +string that is built from the responder IP address and port, the validation +status message, and the MD5 sum of the server certificate. Those fields in +particular are chosen because different SSL certificates could be seen on any +port of a host, certificates could fail validation for different reasons, and +multiple server certificates could be used on that combination of IP address +and port with the ``server_name`` SSL extension (explaining the addition of +the MD5 sum of the certificate). The result is that if a certificate fails +validation and all four pieces of data match (IP address, port, validation +status, and certificate hash) that particular notice won't be raised again for +the default suppression period. + +Setting the ``$identifier`` field is left to those raising notices because +it's assumed that the script author who is raising the notice understands the +full problem set and edge cases of the notice which may not be readily +apparent to users. If users don't want the suppression to take place or simply +want a different interval, they can always modify it with the +:bro:see:`Notice::policy`. + + +Extending Notice Framework +-------------------------- + +Adding Custom Notice Actions +**************************** + +Extending Notice Emails +*********************** + +Cluster Considerations +---------------------- + diff --git a/doc/quickstart.rst b/doc/quickstart.rst new file mode 100644 index 0000000000..cc18956836 --- /dev/null +++ b/doc/quickstart.rst @@ -0,0 +1,598 @@ +.. _CMake: http://www.cmake.org +.. _SWIG: http://www.swig.org +.. _MacPorts: http://www.macports.org +.. _Fink: http://www.finkproject.org +.. _Homebrew: http://mxcl.github.com/homebrew +.. _bro downloads page: http://bro-ids.org/download/index.html + +================= +Quick Start Guide +================= + +.. rst-class:: opening + + The short story for getting Bro up and running in a simple configuration + for analysis of either live traffic from a network interface or a packet + capture trace file. + +.. contents:: + +Installation +============ + +Bro works on most modern, Unix-based systems and requires no custom +hardware. It can be downloaded in either pre-built binary package or +source code forms. + +Pre-Built Binary Release Packages +--------------------------------- + +See the `bro downloads page`_ for currently supported/targeted platforms. + +* RPM + + .. console:: + + sudo yum localinstall Bro-*.rpm + +* DEB + + .. console:: + + sudo gdebi Bro-*.deb + +* MacOS Disk Image with Installer + + Just open the ``Bro-*.dmg`` and then run the ``.pkg`` installer. + Everything installed by the package will go into ``/opt/bro``. + +The primary install prefix for binary packages is ``/opt/bro``. +Non-MacOS packages that include BroControl also put variable/runtime +data (e.g. Bro logs) in ``/var/opt/bro``. + +Building From Source +-------------------- + +Required Dependencies +~~~~~~~~~~~~~~~~~~~~~ + +The following dependencies are required to build Bro: + +* RPM/RedHat-based Linux: + + .. console:: + + sudo yum install cmake make gcc gcc-c++ flex bison libpcap-devel openssl-devel python-devel swig zlib-devel file-devel + +* DEB/Debian-based Linux: + + .. console:: + + sudo apt-get install cmake make gcc g++ flex bison libpcap-dev libssl-dev python-dev swig zlib1g-dev libmagic-dev + +* FreeBSD + + Most required dependencies should come with a minimal FreeBSD install + except for the following. + + .. console:: + + sudo pkg_add -r bash cmake swig bison python + + Note that ``bash`` needs to be in ``PATH``, which by default it is + not. The FreeBSD package installs the binary into + ``/usr/local/bin``. + +* Mac OS X + + Snow Leopard (10.6) comes with all required dependencies except for CMake_. + + Lion (10.7) comes with all required dependencies except for CMake_ and SWIG_. + + Distributions of these dependencies can be obtained from the project websites + linked above, but they're also likely available from your preferred Mac OS X + package management system (e.g. MacPorts_, Fink_, or Homebrew_). + + Note that the MacPorts ``swig`` package may not include any specific + language support so you may need to also install ``swig-ruby`` and + ``swig-python``. + +Optional Dependencies +~~~~~~~~~~~~~~~~~~~~~ + +Bro can use libGeoIP for geo-locating IP addresses, and sendmail for +sending emails. + +* RedHat Enterprise Linux: + + .. console:: + + sudo yum install geoip-devel sendmail + +* CentOS Linux: + + .. console:: + + sudo yum install GeoIP-devel sendmail + +* DEB/Debian-based Linux: + + .. console:: + + sudo apt-get install libgeoip-dev sendmail + +* Ports-based FreeBSD + + .. console:: + + sudo pkg_add -r GeoIP + + sendmail is typically already available. + +* Mac OS X + + Vanilla OS X installations don't ship with libmagic or libGeoIP, but + if installed from your preferred package management system (e.g. MacPorts, + Fink, or Homebrew), they should be automatically detected and Bro will compile + against them. + +Additional steps may be needed to :doc:`get the right GeoIP database ` + +Compiling Bro Source Code +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Bro releases are bundled into source packages for convenience and +available from the `bro downloads page`_. + +The latest Bro development versions are obtainable through git +repositories hosted at `git.bro-ids.org `_. See +our `git development documentation +`_ for comprehensive +information on Bro's use of git revision control, but the short story +for downloading the full source code experience for Bro via git is: + +.. console:: + + git clone --recursive git://git.bro-ids.org/bro + +.. note:: If you choose to clone the ``bro`` repository non-recursively for + a "minimal Bro experience", be aware that compiling it depends on + BinPAC, which has its own ``binpac`` repository. Either install it + first or initialize/update the cloned ``bro`` repository's + ``aux/binpac`` submodule. + +See the ``INSTALL`` file included with the source code for more information +on compiling, but this is the typical way to build and install from source +(of course, changing the value of the ``--prefix`` option to point to the +desired root install path): + +.. console:: + + ./configure --prefix=/desired/install/path + make + make install + +The default installation prefix is ``/usr/local/bro``, which would typically +require root privileges when doing the ``make install``. + +Configure the Run-Time Environment +---------------------------------- + +Just remember that you may need to adjust your ``PATH`` environment variable +according to the platform/shell/package you're using. For example: + +Bourne-Shell Syntax: + +.. console:: + + export PATH=/usr/local/bro/bin:$PATH + +C-Shell Syntax: + +.. console:: + + setenv PATH /usr/local/bro/bin:$PATH + +Or substitute ``/opt/bro/bin`` instead if you installed from a binary package. + +Using BroControl +================ + +BroControl is an interactive shell for easily operating/managing Bro +installations on a single system or even across multiple systems in a +traffic-monitoring cluster. + +.. note:: Below, ``$PREFIX`` is used to reference the Bro installation + root directory. + +A Minimal Starting Configuration +-------------------------------- + +These are the basic configuration changes to make for a minimal BroControl installation +that will manage a single Bro instance on the ``localhost``: + +1) In ``$PREFIX/etc/node.cfg``, set the right interface to monitor. +2) In ``$PREFIX/etc/networks.cfg``, comment out the default settings and add + the networks that Bro will consider local to the monitored environment. +3) In ``$PREFIX/etc/broctl.cfg``, change the ``MailTo`` email address to a + desired recipient and the ``LogRotationInterval`` to a desired log + archival frequency. + +Now start the BroControl shell like: + +.. console:: + + broctl + +Since this is the first-time use of the shell, perform an initial installation +of the BroControl configuration: + +.. console:: + + [BroControl] > install + +Then start up a Bro instance: + +.. console:: + + [BroControl] > start + +If there are errors while trying to start the Bro instance, you can +can view the details with the ``diag`` command. If started successfully, +the Bro instance will begin analyzing traffic according to a default +policy and output the results in ``$PREFIX/logs``. + +.. note:: The user starting BroControl needs permission to capture + network traffic. If you are not root, you may need to grant further + privileges to the account you're using; see the :doc:`FAQ `. + Also, if it looks like Bro is not seeing any traffic, check out + the FAQ entry on checksum offloading. + +You can leave it running for now, but to stop this Bro instance you would do: + +.. console:: + + [BroControl] > stop + +We also recommend to insert the following entry into `crontab`:: + + 0-59/5 * * * * $PREFIX/bin/broctl cron + +This will perform a number of regular housekeeping tasks, including +verifying that the process is still running (and restarting if not in +case of any abnormal termination). + +Browsing Log Files +------------------ + +By default, logs are written out in human-readable (ASCII) format and +data is organized into columns (tab-delimited). Logs that are part of +the current rotation interval are accumulated in +``$PREFIX/logs/current/`` (if Bro is not running, the directory will +be empty). For example, the ``http.log`` contains the results of Bro +HTTP protocol analysis. Here are the first few columns of +``http.log``:: + + # ts uid orig_h orig_p resp_h resp_p + 1311627961.8 HSH4uV8KVJg 192.168.1.100 52303 192.150.187.43 80 + +Logs that deal with analysis of a network protocol will often start like this: +a timestamp, a unique connection identifier (UID), and a connection 4-tuple +(originator host/port and responder host/port). The UID can be used to +identify all logged activity (possibly across multiple log files) associated +with a given connection 4-tuple over its lifetime. + +The remaining columns of protocol-specific logs then detail the +protocol-dependent activity that's occurring. E.g. ``http.log``'s next few +columns (shortened for brevity) show a request to the root of Bro website:: + + # method host uri referrer user_agent + GET bro-ids.org / - <...>Chrome/12.0.742.122<...> + +Some logs are worth explicit mention: + + ``weird.log`` + Contains unusual/exceptional activity that can indicate + malformed connections, traffic that doesn't conform to a particular + protocol, malfunctioning/misconfigured hardware, or even an attacker + attempting to avoid/confuse a sensor. Without context, it's hard to + judge whether this category of activity is interesting and so that is + left up to the user to configure. + + ``notice.log`` + Identifies specific activity that Bro recognizes as + potentially interesting, odd, or bad. In Bro-speak, such + activity is called a "notice". + + +By default, ``BroControl`` regularly takes all the logs from +``$PREFIX/logs/current`` and archives/compresses them to a directory +named by date, e.g. ``$PREFIX/logs/2011-10-06``. The frequency at +which this is done can be configured via the ``LogRotationInterval`` +option in ``$PREFIX/etc/broctl.cfg``. + +Deployment Customization +------------------------ + +The goal of most Bro *deployments* may be to send email alarms when a network +event requires human intervention/investigation, but sometimes that conflicts +with Bro's goal as a *distribution* to remain policy and site neutral -- the +events on one network may be less noteworthy than the same events on another. +As a result, deploying Bro can be an iterative process of +updating its policy to take different actions for events that are noticed, and +using its scripting language to programmatically extend traffic analysis +in a precise way. + +One of the first steps to take in customizing Bro might be to get familiar +with the notices it can generate by default and either tone down or escalate +the action that's taken when specific ones occur. + +Let's say that we've been looking at the ``notice.log`` for a bit and see two +changes we want to make: + +1) ``SSL::Invalid_Server_Cert`` (found in the ``note`` column) is one type of + notice that means an SSL connection was established and the server's + certificate couldn't be validated using Bro's default trust roots, but + we want to ignore it. +2) ``SSH::Login`` is a notice type that is triggered when an SSH connection + attempt looks like it may have been successful, and we want email when + that happens, but only for certain servers. + +So we've defined *what* we want to do, but need to know *where* to do it. +The answer is to use a script written in the Bro programming language, so +let's do a quick intro to Bro scripting. + +Bro Scripts +~~~~~~~~~~~ + +Bro ships with many pre-written scripts that are highly customizable +to support traffic analysis for your specific environment. By +default, these will be installed into ``$PREFIX/share/bro`` and can be +identified by the use of a ``.bro`` file name extension. These files +should **never** be edited directly as changes will be lost when +upgrading to newer versions of Bro. The exception to this rule is the +directory ``$PREFIX/share/bro/site`` where local site-specific files +can be put without fear of being clobbered later. The other main +script directories under ``$PREFIX/share/bro`` are ``base`` and +``policy``. By default, Bro automatically loads all scripts under +``base`` (unless the ``-b`` command line option is supplied), which +deal either with collecting basic/useful state about network +activities or providing frameworks/utilities that extend Bro's +functionality without any performance cost. Scripts under the +``policy`` directory may be more situational or costly, and so users +must explicitly choose if they want to load them. + +The main entry point for the default analysis configuration of a standalone +Bro instance managed by BroControl is the ``$PREFIX/share/bro/site/local.bro`` +script. So we'll be adding to that in the following sections, but first +we have to figure out what to add. + +Redefining Script Option Variables +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Many simple customizations just require you to redefine a variable +from a standard Bro script with your own value, using Bro's ``redef`` +operator. + +The typical way a standard Bro script advertises tweak-able options to users +is by defining variables with the ``&redef`` attribute and ``const`` qualifier. +A redefineable constant might seem strange, but what that really means is that +the variable's value may not change at run-time, but whose initial value can be +modified via the ``redef`` operator at parse-time. + +So let's continue on our path to modify the behavior for the two SSL +and SSH notices. Looking at :doc:`scripts/base/frameworks/notice/main`, +we see that it advertises: + +.. code:: bro + + module Notice; + + export { + ... + ## Ignored notice types. + const ignored_types: set[Notice::Type] = {} &redef; + } + +That's exactly what we want to do for the SSL notice. So add to ``local.bro``: + +.. code:: bro + + redef Notice::ignored_types += { SSL::Invalid_Server_Cert }; + +.. note:: The ``Notice`` namespace scoping is necessary here because the + variable was declared and exported inside the ``Notice`` module, but is + being referenced from outside of it. Variables declared and exported + inside a module do not have to be scoped if referring to them while still + inside the module. + +Then go into the BroControl shell to check whether the configuration change +is valid before installing it and then restarting the Bro instance: + +.. console:: + + [BroControl] > check + bro is ok. + [BroControl] > install + removing old policies in /usr/local/bro/spool/policy/site ... done. + removing old policies in /usr/local/bro/spool/policy/auto ... done. + creating policy directories ... done. + installing site policies ... done. + generating standalone-layout.bro ... done. + generating local-networks.bro ... done. + generating broctl-config.bro ... done. + updating nodes ... done. + [BroControl] > restart + stopping bro ... + starting bro ... + +Now that the SSL notice is ignored, let's look at how to send an email on +the SSH notice. The notice framework has a similar option called +``emailed_types``, but that can't differentiate between SSH servers and we +only want email for logins to certain ones. Then we come to the ``PolicyItem`` +record and ``policy`` set and realize that those are actually what get used +to implement the simple functionality of ``ignored_types`` and +``emailed_types``, but it's extensible such that the condition and action taken +on notices can be user-defined. + +In ``local.bro``, let's add a new ``PolicyItem`` record to the ``policy`` set +that only takes the email action for SSH logins to a defined set of servers: + +.. code:: bro + + const watched_servers: set[addr] = { + 192.168.1.100, + 192.168.1.101, + 192.168.1.102, + } &redef; + + redef Notice::policy += { + [$action = Notice::ACTION_EMAIL, + $pred(n: Notice::Info) = + { + return n$note == SSH::Login && n$id$resp_h in watched_servers; + } + ] + }; + +You'll just have to trust the syntax for now, but what we've done is +first declare our own variable to hold a set of watched addresses, +``watched_servers``; then added a record to the policy that will generate +an email on the condition that the predicate function evaluates to true, which +is whenever the notice type is an SSH login and the responding host stored +inside the ``Info`` record's connection field is in the set of watched servers. + +.. note:: record field member access is done with the '$' character + instead of a '.' as might be expected from other languages, in + order to avoid ambiguity with the builtin address type's use of '.' + in IPv4 dotted decimal representations. + +Remember, to finalize that configuration change perform the ``check``, +``install``, ``restart`` commands in that order inside the BroControl shell. + +Next Steps +---------- + +By this point, we've learned how to set up the most basic Bro instance and +tweak the most basic options. Here's some suggestions on what to explore next: + +* We only looked at how to change options declared in the notice framework, + there's many more options to look at in other script packages. +* Look at the scripts in ``$PREFIX/share/bro/policy`` for further ones + you may want to load. +* Reading the code of scripts that ship with Bro is also a great way to gain + understanding of the language and how you can start writing your own custom + analysis. +* Review the :doc:`FAQ `. +* Continue reading below for another mini-tutorial on using Bro as a standalone + command-line utility. + +Bro, the Command-Line Utility +============================= + +If you prefer not to use BroControl (e.g. don't need its automation and +management features), here's how to directly control Bro for your analysis +activities. + +Monitoring Live Traffic +----------------------- + +Analyzing live traffic from an interface is simple: + +.. console:: + + bro -i en0 + +``en0`` can be replaced by the interface of your choice and for the list of +scripts, you can just use "all" for now to perform all the default analysis +that's available. + +Bro will output log files into the working directory. + +.. note:: The :doc:`FAQ ` entries about + capturing as an unprivileged user and checksum offloading are particularly + relevant at this point. + +To use the site-specific ``local.bro`` script, just add it to the +command-line: + +.. console:: + + bro -i en0 local + +This will cause Bro to print a warning about lacking the +``Site::local_nets`` variable being configured. You can supply this +information at the command line like this (supply your "local" subnets +in place of the example subnets): + +.. console:: + + bro -r mypackets.trace local "Site::local_nets += { 1.2.3.0/24, 5.6.7.0/24 }" + + +Reading Packet Capture (pcap) Files +----------------------------------- + +Capturing packets from an interface and writing them to a file can be done +like this: + +.. console:: + + sudo tcpdump -i en0 -s 0 -w mypackets.trace + +Where ``en0`` can be replaced by the correct interface for your system as +shown by e.g. ``ifconfig``. (The ``-s 0`` argument tells it to capture +whole packets; in cases where it's not supported use ``-s 65535`` instead). + +After a while of capturing traffic, kill the ``tcpdump`` (with ctrl-c), +and tell Bro to perform all the default analysis on the capture which primarily includes : + +.. console:: + + bro -r mypackets.trace + +Bro will output log files into the working directory. + +If you are interested in more detection, you can again load the ``local`` +script that we include as a suggested configuration: + +.. console:: + + bro -r mypackets.trace local + + +Telling Bro Which Scripts to Load +--------------------------------- + +A command-line invocation of Bro typically looks like: + +.. console:: + + bro + +Where the last arguments are the specific policy scripts that this Bro +instance will load. These arguments don't have to include the ``.bro`` +file extension, and if the corresponding script resides under the default +installation path, ``$PREFIX/share/bro``, then it requires no path +qualification. Further, a directory of scripts can be specified as +an argument to be loaded as a "package" if it contains a ``__load__.bro`` +script that defines the scripts that are part of the package. + +This example does all of the base analysis (primarily protocol +logging) and adds SSL certificate validation. + +.. console:: + + bro -r mypackets.trace protocols/ssl/validate-certs + +You might notice that a script you load from the command line uses the +``@load`` directive in the Bro language to declare dependence on other scripts. +This directive is similar to the ``#include`` of C/C++, except the semantics +are "load this script if it hasn't already been loaded". + +.. note:: If one wants Bro to be able to load scripts that live outside the + default directories in Bro's installation root, the ``BROPATH`` environment + variable will need to be extended to include all the directories that need + to be searched for scripts. See the default search path by doing + ``bro --help``. + diff --git a/doc/reporting-problems.rst b/doc/reporting-problems.rst new file mode 100644 index 0000000000..5e55b2ac90 --- /dev/null +++ b/doc/reporting-problems.rst @@ -0,0 +1,194 @@ + +Reporting Problems +================== + +.. rst-class:: opening + + Here we summarize some steps to follow when you see Bro doing + something it shouldn't. To provide help, it is often crucial for + us to have a way of reliably reproducing the effect you're seeing. + Unfortunately, reproducing problems can be rather tricky with Bro + because more often than not, they occur only in either very rare + situations or only after Bro has been running for some time. In + particular, getting a small trace showing a specific effect can be + a real problem. In the following, we'll summarize some strategies + to this end. + +Reporting Problems +------------------ + +Generally, when you encounter a problem with Bro, the best thing to do +is opening a new ticket in `Bro's issue tracker +`__ and include information on how to +reproduce the issue. Ideally, your ticket should come with the +following: + +* The Bro version you're using (if working directly from the git + repository, the branch and revision number.) + +* The output you're seeing along with a description of what you'd expect + Bro to do instead. + +* A *small* trace in `libpcap format `__ + demonstrating the effect (assuming the problem doesn't happen right + at startup already). + +* The exact command-line you're using to run Bro with that trace. If + you can, please try to run the Bro binary directly from the command + line rather than using BroControl. + +* Any non-standard scripts you're using (but please only those really + necessary; just a small code snippet triggering the problem would + be perfect). + +* If you encounter a crash, information from the core dump, such as + the stack backtrace, can be very helpful. See below for more on + this. + + +How Do I Get a Trace File? +-------------------------- + +As Bro is usually running live, coming up with a small trace file that +reproduces a problem can turn out to be quite a challenge. Often it +works best to start with a large trace that triggers the problem, +and then successively thin it out as much as possible. + +To get to the initial large trace, here are a few things you can try: + +* Capture a trace with `tcpdump `__, either + on the same interface Bro is running on, or on another host where + you can generate traffic of the kind likely triggering the problem + (e.g., if you're seeing problems with the HTTP analyzer, record some + of your Web browsing on your desktop.) When using tcpdump, don't + forget to record *complete* packets (``tcpdump -s 0 ...``). You can + reduce the amount of traffic captured by using a suitable BPF filter + (e.g., for HTTP only, try ``port 80``). + +* Bro's command-line option ``-w `` records all packets it + processes into the given file. You can then later run Bro + offline on this trace and it will process the packets in the same + way as it did live. This is particularly helpful with problems that + only occur after Bro has already been running for some time. For + example, sometimes a crash may be triggered by a particular kind of + traffic only occurring rarely. Running Bro live with ``-w`` and + then, after the crash, offline on the recorded trace might, with a + little bit of luck, reproduce the problem reliably. However, be + careful with ``-w``: it can result in huge trace files, quickly + filling up your disk. (One way to mitigate the space issues is to + periodically delete the trace file by configuring + ``rotate-logs.bro`` accordingly. BroControl does that for you if you + set its ``SaveTraces`` option.) + +* Finally, you can try running Bro on a publically available trace + file, such as `anonymized FTP traffic `__, `headers-only enterprise traffic + `__, or + `Defcon traffic `__. Some of these + particularly stress certain components of Bro (e.g., the Defcon + traces contain tons of scans). + +Once you have a trace that demonstrates the effect, you will often +notice that it's pretty big, in particular if recorded from the link +you're monitoring. Therefore, the next step is to shrink its size as +much as possible. Here are a few things you can try to this end: + +* Very often, a single connection is able to demonstrate the problem. + If you can identify which one it is (e.g., from one of Bro's + ``*.log`` files) you can extract the connection's packets from the + trace using tcpdump by filtering for the corresponding 4-tuple of + addresses and ports: + + .. console:: + + > tcpdump -r large.trace -w small.trace host and port and host and port + +* If you can't reduce the problem to a connection, try to identify + either a host pair or a single host triggering it, and filter down + the trace accordingly. + +* You can try to extract a smaller time slice from the trace using + `TCPslice `__. For example, to + extract the first 100 seconds from the trace: + + .. console:: + + # Test comment + > tcpslice +100 out + +Alternatively, tcpdump extracts the first ``n`` packets with its +option ``-c ``. + + +Getting More Information After a Crash +-------------------------------------- + +If Bro crashes, a *core dump* can be very helpful to nail down the +problem. Examining a core is not for the faint of heart but can reveal +extremely useful information. + +First, you should configure Bro with the option ``--enable-debug`` and +recompile; this will disable all compiler optimizations and thus make +the core dump more useful (don't expect great performance with this +version though; compiling Bro without optimization has a noticeable +impact on its CPU usage.). Then enable core dumps if you haven't +already (e.g., ``ulimit -c unlimited`` if you're using bash). + +Once Bro has crashed, start gdb with the Bro binary and the file +containing the core dump. (Alternatively, you can also run Bro +directly inside gdb instead of working from a core file.) The first +helpful information to include with your tracker ticket is a stack +backtrace, which you get with gdb's ``bt`` command: + +.. console:: + + > gdb bro core + [...] + > bt + + +If the crash occurs inside Bro's script interpreter, the next thing to +do is identifying the line of script code processed just before the +abnormal termination. Look for methods in the stack backtrace which +belong to any of the script interpreter's classes. Roughly speaking, +these are all classes with names ending in ``Expr``, ``Stmt``, or +``Val``. Then climb up the stack with ``up`` until you reach the first +of these methods. The object to which ``this`` is pointing will have a +``Location`` object, which in turn contains the file name and line +number of the corresponding piece of script code. Continuing the +example from above, here's how to get that information: + +.. console:: + + [in gdb] + > up + > ... + > up + > print this->location->filename + > print this->location->first_line + + +If the crash occurs while processing input packets but you cannot +directly tell which connection is responsible (and thus not extract +its packets from the trace as suggested above), try getting the +4-tuple of the connection currently being processed from the core dump +by again examining the stack backtrace, this time looking for methods +belonging to the ``Connection`` class. That class has members +``orig_addr``/``resp_addr`` and ``orig_port``/``resp_port`` storing +(pointers to) the IP addresses and ports respectively: + +.. console:: + + [in gdb] + > up + > ... + > up + > printf "%08x:%04x %08x:%04x\n", *this->orig_addr, this->orig_port, *this->resp_addr, this->resp_port + + +Note that these values are stored in `network byte order +`__ +so you will need to flip the bytes around if you are on a low-endian +machine (which is why the above example prints them in hex). For +example, if an IP address prints as ``0100007f`` , that's 127.0.0.1 . + diff --git a/doc/scripts/CMakeLists.txt b/doc/scripts/CMakeLists.txt index cb7a42929c..33d473b005 100644 --- a/doc/scripts/CMakeLists.txt +++ b/doc/scripts/CMakeLists.txt @@ -1,16 +1,3 @@ -set(BIF_SRC_DIR ${PROJECT_SOURCE_DIR}/src) -set(RST_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/rest_output) -set(DOC_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/out) -set(DOC_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/source) -set(DOC_SOURCE_WORKDIR ${CMAKE_CURRENT_BINARY_DIR}/source) - -file(GLOB_RECURSE DOC_SOURCES FOLLOW_SYMLINKS "*") - -# configure the Sphinx config file (expand variables CMake might know about) -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/conf.py.in - ${CMAKE_CURRENT_BINARY_DIR}/conf.py - @ONLY) - # find out what BROPATH to use when executing bro execute_process(COMMAND ${CMAKE_BINARY_DIR}/bro-path-dev OUTPUT_VARIABLE BROPATH @@ -48,7 +35,7 @@ endif () # which summary text can be extracted at build time # ${group}_doc_names: a running list of reST style document names that can be # given to a :doc: role, shared indices with ${group}_files -# + macro(REST_TARGET srcDir broInput) set(absSrcPath ${srcDir}/${broInput}) get_filename_component(basename ${broInput} NAME) @@ -86,12 +73,14 @@ macro(REST_TARGET srcDir broInput) elseif (${extension} STREQUAL ".bif.bro") set(group bifs) elseif (relDstDir) - set(pkgIndex scripts/${relDstDir}/index) - set(group ${pkgIndex}) + set(group ${relDstDir}/index) # add package index to master package list if not already in it - list(FIND MASTER_PKG_LIST ${pkgIndex} _found) + # and if a __load__.bro exists in the original script directory + list(FIND MASTER_PKG_LIST ${relDstDir} _found) if (_found EQUAL -1) - list(APPEND MASTER_PKG_LIST ${pkgIndex}) + if (EXISTS ${CMAKE_SOURCE_DIR}/scripts/${relDstDir}/__load__.bro) + list(APPEND MASTER_PKG_LIST ${relDstDir}) + endif () endif () else () set(group "") @@ -119,7 +108,7 @@ macro(REST_TARGET srcDir broInput) ARGS -E remove_directory .state # generate the reST documentation using bro COMMAND BROPATH=${BROPATH}:${srcDir} ${CMAKE_BINARY_DIR}/src/bro - ARGS --doc-scripts ${broInput} || (rm -rf .state *.log *.rst && exit 1) + ARGS -b -Z ${broInput} || (rm -rf .state *.log *.rst && exit 1) # move generated doc into a new directory tree that # defines the final structure of documents COMMAND "${CMAKE_COMMAND}" @@ -134,6 +123,7 @@ macro(REST_TARGET srcDir broInput) ARGS -rf .state *.log *.rst DEPENDS bro DEPENDS ${absSrcPath} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} COMMENT "[Bro] Generating reST docs for ${broInput}" ) @@ -143,19 +133,21 @@ endmacro(REST_TARGET) include(DocSourcesList.cmake) # create temporary list of all docs to include in the master policy/index file -set(MASTER_POLICY_INDEX ${CMAKE_CURRENT_BINARY_DIR}/policy_index) file(WRITE ${MASTER_POLICY_INDEX} "${MASTER_POLICY_INDEX_TEXT}") # create the temporary list of all packages to include in the master # policy/packages.rst file -set(MASTER_PACKAGE_INDEX ${CMAKE_CURRENT_BINARY_DIR}/pkg_index) set(MASTER_PKG_INDEX_TEXT "") foreach (pkg ${MASTER_PKG_LIST}) - # strip of the trailing /index for the link name - get_filename_component(lnktxt ${pkg} PATH) - # pretty-up the link name by removing common scripts/ prefix - string(REPLACE "scripts/" "" lnktxt "${lnktxt}") - set(MASTER_PKG_INDEX_TEXT "${MASTER_PKG_INDEX_TEXT}\n ${lnktxt} <${pkg}>") + set(MASTER_PKG_INDEX_TEXT + "${MASTER_PKG_INDEX_TEXT}\n:doc:`${pkg} <${pkg}/index>`\n") + if (EXISTS ${CMAKE_SOURCE_DIR}/scripts/${pkg}/README) + file(STRINGS ${CMAKE_SOURCE_DIR}/scripts/${pkg}/README pkgreadme) + foreach (line ${pkgreadme}) + set(MASTER_PKG_INDEX_TEXT "${MASTER_PKG_INDEX_TEXT}\n ${line}") + endforeach () + set(MASTER_PKG_INDEX_TEXT "${MASTER_PKG_INDEX_TEXT}\n") + endif () endforeach () file(WRITE ${MASTER_PACKAGE_INDEX} "${MASTER_PKG_INDEX_TEXT}") @@ -186,11 +178,11 @@ if (EXISTS ${RST_OUTPUT_DIR}) list(FIND ALL_REST_OUTPUTS ${_doc} _found) if (_found EQUAL -1) file(REMOVE ${_doc}) - message(STATUS "AutoDoc: remove stale reST doc: ${_doc}") + message(STATUS "Broxygen: remove stale reST doc: ${_doc}") string(REPLACE .rst .bro _brofile ${_doc}) if (EXISTS ${_brofile}) file(REMOVE ${_brofile}) - message(STATUS "AutoDoc: remove stale bro source: ${_brofile}") + message(STATUS "Broxygen: remove stale bro source: ${_brofile}") endif () endif () endforeach () @@ -211,54 +203,3 @@ add_custom_target(restclean COMMAND "${CMAKE_COMMAND}" -E remove_directory ${RST_OUTPUT_DIR} VERBATIM) - -# The "doc" target generates reST documentation for any outdated bro scripts -# and then uses Sphinx to generate HTML documentation from the reST -add_custom_target(doc - # copy the template documentation to the build directory - # to give as input for sphinx - COMMAND "${CMAKE_COMMAND}" -E copy_directory - ${DOC_SOURCE_DIR} - ${DOC_SOURCE_WORKDIR} - # copy generated policy script documentation into the - # working copy of the template documentation - COMMAND "${CMAKE_COMMAND}" -E copy_directory - ${RST_OUTPUT_DIR} - ${DOC_SOURCE_WORKDIR}/scripts - # append to the master index of all policy scripts - COMMAND cat ${MASTER_POLICY_INDEX} >> - ${DOC_SOURCE_WORKDIR}/scripts/index.rst - # append to the master index of all policy packages - COMMAND cat ${MASTER_PACKAGE_INDEX} >> - ${DOC_SOURCE_WORKDIR}/packages.rst - # construct a reST file for each group - COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/group_index_generator.py - ${CMAKE_CURRENT_BINARY_DIR}/group_list - ${CMAKE_CURRENT_BINARY_DIR} - ${DOC_SOURCE_WORKDIR} - # tell sphinx to generate html - COMMAND sphinx-build - -b html - -c ${CMAKE_CURRENT_BINARY_DIR} - -d ${DOC_OUTPUT_DIR}/doctrees - ${DOC_SOURCE_WORKDIR} - ${DOC_OUTPUT_DIR}/html - # create symlink to the html output directory for convenience - COMMAND "${CMAKE_COMMAND}" -E create_symlink - ${DOC_OUTPUT_DIR}/html - ${CMAKE_BINARY_DIR}/html - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} - COMMENT "[Sphinx] Generating HTML policy script docs" - # SOURCES just adds stuff to IDE projects as a convenience - SOURCES ${DOC_SOURCES}) - -# The "docclean" target removes just the Sphinx input/output directories -# from the build directory. -add_custom_target(docclean - COMMAND "${CMAKE_COMMAND}" -E remove_directory - ${DOC_SOURCE_WORKDIR} - COMMAND "${CMAKE_COMMAND}" -E remove_directory - ${DOC_OUTPUT_DIR} - VERBATIM) - -add_dependencies(doc docclean restdoc) diff --git a/doc/scripts/DocSourcesList.cmake b/doc/scripts/DocSourcesList.cmake index 37f4b41279..e6ed45502a 100644 --- a/doc/scripts/DocSourcesList.cmake +++ b/doc/scripts/DocSourcesList.cmake @@ -16,13 +16,13 @@ rest_target(${CMAKE_CURRENT_SOURCE_DIR} example.bro internal) rest_target(${psd} base/init-default.bro internal) rest_target(${psd} base/init-bare.bro internal) -rest_target(${CMAKE_BINARY_DIR}/src bro.bif.bro) -rest_target(${CMAKE_BINARY_DIR}/src const.bif.bro) -rest_target(${CMAKE_BINARY_DIR}/src event.bif.bro) -rest_target(${CMAKE_BINARY_DIR}/src logging.bif.bro) -rest_target(${CMAKE_BINARY_DIR}/src reporter.bif.bro) -rest_target(${CMAKE_BINARY_DIR}/src strings.bif.bro) -rest_target(${CMAKE_BINARY_DIR}/src types.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/src base/bro.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/src base/const.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/src base/event.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/src base/logging.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/src base/reporter.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/src base/strings.bif.bro) +rest_target(${CMAKE_BINARY_DIR}/src base/types.bif.bro) rest_target(${psd} base/frameworks/cluster/main.bro) rest_target(${psd} base/frameworks/cluster/nodes/manager.bro) rest_target(${psd} base/frameworks/cluster/nodes/proxy.bro) @@ -33,12 +33,18 @@ rest_target(${psd} base/frameworks/control/main.bro) rest_target(${psd} base/frameworks/dpd/main.bro) rest_target(${psd} base/frameworks/intel/main.bro) rest_target(${psd} base/frameworks/logging/main.bro) +rest_target(${psd} base/frameworks/logging/postprocessors/scp.bro) +rest_target(${psd} base/frameworks/logging/postprocessors/sftp.bro) rest_target(${psd} base/frameworks/logging/writers/ascii.bro) +rest_target(${psd} base/frameworks/metrics/cluster.bro) rest_target(${psd} base/frameworks/metrics/main.bro) +rest_target(${psd} base/frameworks/metrics/non-cluster.bro) rest_target(${psd} base/frameworks/notice/actions/add-geodata.bro) rest_target(${psd} base/frameworks/notice/actions/drop.bro) rest_target(${psd} base/frameworks/notice/actions/email_admin.bro) rest_target(${psd} base/frameworks/notice/actions/page.bro) +rest_target(${psd} base/frameworks/notice/actions/pp-alarms.bro) +rest_target(${psd} base/frameworks/notice/cluster.bro) rest_target(${psd} base/frameworks/notice/extend-email/hostnames.bro) rest_target(${psd} base/frameworks/notice/main.bro) rest_target(${psd} base/frameworks/notice/weird.bro) @@ -47,7 +53,6 @@ rest_target(${psd} base/frameworks/packet-filter/netstats.bro) rest_target(${psd} base/frameworks/reporter/main.bro) rest_target(${psd} base/frameworks/signatures/main.bro) rest_target(${psd} base/frameworks/software/main.bro) -rest_target(${psd} base/frameworks/time-machine/notice.bro) rest_target(${psd} base/protocols/conn/contents.bro) rest_target(${psd} base/protocols/conn/inactivity.bro) rest_target(${psd} base/protocols/conn/main.bro) @@ -60,15 +65,9 @@ rest_target(${psd} base/protocols/http/file-extract.bro) rest_target(${psd} base/protocols/http/file-hash.bro) rest_target(${psd} base/protocols/http/file-ident.bro) rest_target(${psd} base/protocols/http/main.bro) -rest_target(${psd} base/protocols/http/partial-content.bro) rest_target(${psd} base/protocols/http/utils.bro) rest_target(${psd} base/protocols/irc/dcc-send.bro) rest_target(${psd} base/protocols/irc/main.bro) -rest_target(${psd} base/protocols/mime/base.bro) -rest_target(${psd} base/protocols/mime/file-extract.bro) -rest_target(${psd} base/protocols/mime/file-hash.bro) -rest_target(${psd} base/protocols/mime/file-ident.bro) -rest_target(${psd} base/protocols/rpc/base.bro) rest_target(${psd} base/protocols/smtp/entities-excerpt.bro) rest_target(${psd} base/protocols/smtp/entities.bro) rest_target(${psd} base/protocols/smtp/main.bro) @@ -88,8 +87,7 @@ rest_target(${psd} base/utils/patterns.bro) rest_target(${psd} base/utils/site.bro) rest_target(${psd} base/utils/strings.bro) rest_target(${psd} base/utils/thresholds.bro) -rest_target(${psd} policy/frameworks/communication/listen-clear.bro) -rest_target(${psd} policy/frameworks/communication/listen-ssl.bro) +rest_target(${psd} policy/frameworks/communication/listen.bro) rest_target(${psd} policy/frameworks/control/controllee.bro) rest_target(${psd} policy/frameworks/control/controller.bro) rest_target(${psd} policy/frameworks/dpd/detect-protocols.bro) @@ -100,15 +98,17 @@ rest_target(${psd} policy/frameworks/metrics/ssl-example.bro) rest_target(${psd} policy/frameworks/software/version-changes.bro) rest_target(${psd} policy/frameworks/software/vulnerable.bro) rest_target(${psd} policy/frameworks/tunnel.bro) -rest_target(${psd} policy/integration/barnyard2/base.bro) -rest_target(${psd} policy/integration/barnyard2/event.bro) +rest_target(${psd} policy/integration/barnyard2/main.bro) rest_target(${psd} policy/integration/barnyard2/types.bro) rest_target(${psd} policy/misc/analysis-groups.bro) +rest_target(${psd} policy/misc/capture-loss.bro) rest_target(${psd} policy/misc/loaded-scripts.bro) rest_target(${psd} policy/misc/profiling.bro) +rest_target(${psd} policy/misc/stats.bro) rest_target(${psd} policy/misc/trim-trace-file.bro) rest_target(${psd} policy/protocols/conn/known-hosts.bro) rest_target(${psd} policy/protocols/conn/known-services.bro) +rest_target(${psd} policy/protocols/conn/weirds.bro) rest_target(${psd} policy/protocols/dns/auth-addl.bro) rest_target(${psd} policy/protocols/dns/detect-external-names.bro) rest_target(${psd} policy/protocols/ftp/detect.bro) @@ -117,7 +117,8 @@ rest_target(${psd} policy/protocols/http/detect-MHR.bro) rest_target(${psd} policy/protocols/http/detect-intel.bro) rest_target(${psd} policy/protocols/http/detect-sqli.bro) rest_target(${psd} policy/protocols/http/detect-webapps.bro) -rest_target(${psd} policy/protocols/http/headers.bro) +rest_target(${psd} policy/protocols/http/header-names.bro) +rest_target(${psd} policy/protocols/http/software-browser-plugins.bro) rest_target(${psd} policy/protocols/http/software.bro) rest_target(${psd} policy/protocols/http/var-extraction-cookies.bro) rest_target(${psd} policy/protocols/http/var-extraction-uri.bro) @@ -128,10 +129,12 @@ rest_target(${psd} policy/protocols/ssh/detect-bruteforcing.bro) rest_target(${psd} policy/protocols/ssh/geo-data.bro) rest_target(${psd} policy/protocols/ssh/interesting-hostnames.bro) rest_target(${psd} policy/protocols/ssh/software.bro) +rest_target(${psd} policy/protocols/ssl/cert-hash.bro) +rest_target(${psd} policy/protocols/ssl/expiring-certs.bro) +rest_target(${psd} policy/protocols/ssl/extract-certs-pem.bro) rest_target(${psd} policy/protocols/ssl/known-certs.bro) rest_target(${psd} policy/protocols/ssl/validate-certs.bro) rest_target(${psd} policy/tuning/defaults/packet-fragments.bro) -rest_target(${psd} policy/tuning/defaults/remove-high-volume-notices.bro) rest_target(${psd} policy/tuning/defaults/warnings.bro) rest_target(${psd} policy/tuning/track-all-assets.bro) rest_target(${psd} site/local-manager.bro) diff --git a/doc/scripts/README b/doc/scripts/README index ca7f28492b..a15812609c 100644 --- a/doc/scripts/README +++ b/doc/scripts/README @@ -1,6 +1,6 @@ This directory contains scripts and templates that can be used to automate the generation of Bro script documentation. Several build targets are defined -by CMake: +by CMake and available in the top-level Makefile: ``restdoc`` @@ -15,29 +15,10 @@ by CMake: ``build/`` directory inside ``reST`` (a symlink to ``doc/scripts/rest_output``). -``doc`` - - This target depends on a Python interpreter (>=2.5) and - `Sphinx `_ being installed. Sphinx can be - installed like:: - - > sudo easy_install sphinx - - This target will first build ``restdoc`` target and then copy the - resulting reST files as an input directory to Sphinx. - - After completion, HTML documentation can be located in the CMake - ``build/`` directory inside ``html`` (a symlink to - ``doc/scripts/out/html``) - ``restclean`` This target removes any reST documentation that has been generated so far. -``docclean`` - - This target removes Sphinx inputs and outputs from the CMake ``build/`` dir. - The ``genDocSourcesList.sh`` script can be run to automatically generate ``DocSourcesList.cmake``, which is the file CMake uses to define the list of documentation targets. This script should be run after adding new @@ -54,18 +35,10 @@ script's name to the blacklist, then append a ``rest_target()`` to the ``statictext`` variable where the first argument is the source directory containing the policy script to document, the second argument is the file name of the policy script, and the third argument is the path/name of a -pre-created reST document in the ``source/`` directory to which the +pre-created reST document in the ``../`` source directory to which the ``make doc`` process can append script documentation references. This pre-created reST document should also then be linked to from the TOC tree -in ``source/index.rst``. - -The Sphinx source tree template in ``source/`` can be modified to add more -common/general documentation, style sheets, JavaScript, etc. The Sphinx -config file is produced from ``conf.py.in``, so that can be edited to change -various Sphinx options, like setting the default HTML rendering theme. -There is also a custom Sphinx domain implemented in ``source/ext/bro.py`` -which adds some reST directives and roles that aid in generating useful -index entries and cross-references. +in ``../index.rst``. See ``example.bro`` for an example of how to document a Bro script such that ``make doc`` will be able to produce reST/HTML documentation for it. diff --git a/doc/scripts/bifs.rst b/doc/scripts/bifs.rst new file mode 100644 index 0000000000..eaae0e13b8 --- /dev/null +++ b/doc/scripts/bifs.rst @@ -0,0 +1,5 @@ +.. This is a stub doc to which broxygen appends during the build process + +Built-In Functions (BIFs) +========================= + diff --git a/doc/scripts/builtins.rst b/doc/scripts/builtins.rst new file mode 100644 index 0000000000..32908f71fd --- /dev/null +++ b/doc/scripts/builtins.rst @@ -0,0 +1,642 @@ +Builtin Types and Attributes +============================ + +Types +----- + +The Bro scripting language supports the following built-in types. + +.. bro:type:: void + + An internal Bro type representing an absence of a type. Should + most often be seen as a possible function return type. + +.. bro:type:: bool + + Reflects a value with one of two meanings: true or false. The two + ``bool`` constants are ``T`` and ``F``. + +.. bro:type:: int + + A numeric type representing a signed integer. An ``int`` constant + is a string of digits preceded by a ``+`` or ``-`` sign, e.g. + ``-42`` or ``+5``. When using type inferencing use care so that the + intended type is inferred, e.g. ``local size_difference = 0`` will + infer :bro:type:`count`, while ``local size_difference = +0`` + will infer :bro:type:`int`. + +.. bro:type:: count + + A numeric type representing an unsigned integer. A ``count`` + constant is a string of digits, e.g. ``1234`` or ``0``. + +.. bro:type:: counter + + An alias to :bro:type:`count`. + +.. TODO: is there anything special about this type? + +.. bro:type:: double + + A numeric type representing a double-precision floating-point + number. Floating-point constants are written as a string of digits + with an optional decimal point, optional scale-factor in scientific + notation, and optional ``+`` or ``-`` sign. Examples are ``-1234``, + ``-1234e0``, ``3.14159``, and ``.003e-23``. + +.. bro:type:: time + + A temporal type representing an absolute time. There is currently + no way to specify a ``time`` constant, but one can use the + :bro:id:`current_time` or :bro:id:`network_time` built-in functions + to assign a value to a ``time``-typed variable. + +.. bro:type:: interval + + A temporal type representing a relative time. An ``interval`` + constant can be written as a numeric constant followed by a time + unit where the time unit is one of ``usec``, ``sec``, ``min``, + ``hr``, or ``day`` which respectively represent microseconds, + seconds, minutes, hours, and days. Whitespace between the numeric + constant and time unit is optional. Appending the letter "s" to the + time unit in order to pluralize it is also optional (to no semantic + effect). Examples of ``interval`` constants are ``3.5 min`` and + ``3.5mins``. An ``interval`` can also be negated, for example ``- + 12 hr`` represents "twelve hours in the past". Intervals also + support addition, subtraction, multiplication, division, and + comparison operations. + +.. bro:type:: string + + A type used to hold character-string values which represent text. + String constants are created by enclosing text in double quotes (") + and the backslash character (\\) introduces escape sequences. + + Note that Bro represents strings internally as a count and vector of + bytes rather than a NUL-terminated byte string (although string + constants are also automatically NUL-terminated). This is because + network traffic can easily introduce NULs into strings either by + nature of an application, inadvertently, or maliciously. And while + NULs are allowed in Bro strings, when present in strings passed as + arguments to many functions, a run-time error can occur as their + presence likely indicates a sort of problem. In that case, the + string will also only be represented to the user as the literal + "" string. + +.. bro:type:: pattern + + A type representing regular-expression patterns which can be used + for fast text-searching operations. Pattern constants are created + by enclosing text within forward slashes (/) and is the same syntax + as the patterns supported by the `flex lexical analyzer + `_. The speed of + regular expression matching does not depend on the complexity or + size of the patterns. Patterns support two types of matching, exact + and embedded. + + In exact matching the ``==`` equality relational operator is used + with one :bro:type:`string` operand and one :bro:type:`pattern` + operand to check whether the full string exactly matches the + pattern. In this case, the ``^`` beginning-of-line and ``$`` + end-of-line anchors are redundant since pattern is implicitly + anchored to the beginning and end of the line to facilitate an exact + match. For example:: + + "foo" == /foo|bar/ + + yields true, while:: + + /foo|bar/ == "foobar" + + yields false. The ``!=`` operator would yield the negation of ``==``. + + In embedded matching the ``in`` operator is again used with one + :bro:type:`string` operand and one :bro:type:`pattern` operand + (which must be on the left-hand side), but tests whether the pattern + appears anywhere within the given string. For example:: + + /foo|bar/ in "foobar" + + yields true, while:: + + /^oob/ in "foobar" + + is false since "oob" does not appear at the start of "foobar". The + ``!in`` operator would yield the negation of ``in``. + +.. bro:type:: enum + + A type allowing the specification of a set of related values that + have no further structure. The only operations allowed on + enumerations are equality comparisons and they do not have + associated values or ordering. An example declaration: + + .. code:: bro + + type color: enum { Red, White, Blue, }; + + The last comma after ``Blue`` is optional. + +.. bro:type:: timer + +.. TODO: is this a type that's exposed to users? + +.. bro:type:: port + + A type representing transport-level port numbers. Besides TCP and + UDP ports, there is a concept of an ICMP "port" where the source + port is the ICMP message type and the destination port the ICMP + message code. A ``port`` constant is written as an unsigned integer + followed by one of ``/tcp``, ``/udp``, ``/icmp``, or ``/unknown``. + + Ports can be compared for equality and also for ordering. When + comparing order across transport-level protocols, ``unknown`` < + ``tcp`` < ``udp`` < ``icmp``, for example ``65535/tcp`` is smaller + than ``0/udp``. + +.. bro:type:: addr + + A type representing an IP address. + + IPv4 address constants are written in "dotted quad" format, + ``A1.A2.A3.A4``, where Ai all lie between 0 and 255. + + IPv6 address constants are written as colon-separated hexadecimal form + as described by :rfc:`2373`, but additionally encased in square brackets. + The mixed notation with embedded IPv4 addresses as dotted-quads in the + lower 32 bits is also allowed. + Some examples: ``[2001:db8::1]``, ``[::ffff:192.168.1.100]``, or + ``[aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222]``. + + Hostname constants can also be used, but since a hostname can + correspond to multiple IP addresses, the type of such variable is a + :bro:type:`set` of :bro:type:`addr` elements. For example: + + .. code:: bro + + local a = www.google.com; + + Addresses can be compared for (in)equality using ``==`` and ``!=``. + They can also be masked with ``/`` to produce a :bro:type:`subnet`: + + .. code:: bro + + local a: addr = 192.168.1.100; + local s: subnet = 192.168.0.0/16; + if ( a/16 == s ) + print "true"; + + And checked for inclusion within a :bro:type:`subnet` using ``in`` : + + .. code:: bro + + local a: addr = 192.168.1.100; + local s: subnet = 192.168.0.0/16; + if ( a in s ) + print "true"; + +.. bro:type:: subnet + + A type representing a block of IP addresses in CIDR notation. A + ``subnet`` constant is written as an :bro:type:`addr` followed by a + slash (/) and then the network prefix size specified as a decimal + number. For example, ``192.168.0.0/16`` or ``[fe80::]/64``. + +.. bro:type:: any + + Used to bypass strong typing. For example, a function can take an + argument of type ``any`` when it may be of different types. + +.. bro:type:: table + + An associate array that maps from one set of values to another. The + values being mapped are termed the *index* or *indices* and the + result of the mapping is called the *yield*. Indexing into tables + is very efficient, and internally it is just a single hash table + lookup. + + The table declaration syntax is:: + + table [ type^+ ] of type + + where *type^+* is one or more types, separated by commas. For example: + + .. code:: bro + + global a: table[count] of string; + + declares a table indexed by :bro:type:`count` values and yielding + :bro:type:`string` values. The yield type can also be more complex: + + .. code:: bro + + global a: table[count] of table[addr, port] of string; + + which declares a table indexed by :bro:type:`count` and yielding + another :bro:type:`table` which is indexed by an :bro:type:`addr` + and :bro:type:`port` to yield a :bro:type:`string`. + + Initialization of tables occurs by enclosing a set of initializers within + braces, for example: + + .. code:: bro + + global t: table[count] of string = { + [11] = "eleven", + [5] = "five", + }; + + Accessing table elements if provided by enclosing values within square + brackets (``[]``), for example: + + .. code:: bro + + t[13] = "thirteen"; + + And membership can be tested with ``in``: + + .. code:: bro + + if ( 13 in t ) + ... + + Iterate over tables with a ``for`` loop: + + .. code:: bro + + local t: table[count] of string; + for ( n in t ) + ... + + local services: table[addr, port] of string; + for ( [a, p] in services ) + ... + + Remove individual table elements with ``delete``: + + .. code:: bro + + delete t[13]; + + Nothing happens if the element with value ``13`` isn't present in + the table. + + Table size can be obtained by placing the table identifier between + vertical pipe (|) characters: + + .. code:: bro + + |t| + +.. bro:type:: set + + A set is like a :bro:type:`table`, but it is a collection of indices + that do not map to any yield value. They are declared with the + syntax:: + + set [ type^+ ] + + where *type^+* is one or more types separated by commas. + + Sets are initialized by listing elements enclosed by curly braces: + + .. code:: bro + + global s: set[port] = { 21/tcp, 23/tcp, 80/tcp, 443/tcp }; + global s2: set[port, string] = { [21/tcp, "ftp"], [23/tcp, "telnet"] }; + + The types are explicitly shown in the example above, but they could + have been left to type inference. + + Set membership is tested with ``in``: + + .. code:: bro + + if ( 21/tcp in s ) + ... + + Elements are added with ``add``: + + .. code:: bro + + add s[22/tcp]; + + And removed with ``delete``: + + .. code:: bro + + delete s[21/tcp]; + + Set size can be obtained by placing the set identifier between + vertical pipe (|) characters: + + .. code:: bro + + |s| + +.. bro:type:: vector + + A vector is like a :bro:type:`table`, except it's always indexed by a + :bro:type:`count`. A vector is declared like: + + .. code:: bro + + global v: vector of string; + + And can be initialized with the vector constructor: + + .. code:: bro + + global v: vector of string = vector("one", "two", "three"); + + Adding an element to a vector involves accessing/assigning it: + + .. code:: bro + + v[3] = "four" + + Note how the vector indexing is 0-based. + + Vector size can be obtained by placing the vector identifier between + vertical pipe (|) characters: + + .. code:: bro + + |v| + +.. bro:type:: record + + A ``record`` is a collection of values. Each value has a field name + and a type. Values do not need to have the same type and the types + have no restrictions. An example record type definition: + + .. code:: bro + + type MyRecordType: record { + c: count; + s: string &optional; + }; + + Access to a record field uses the dollar sign (``$``) operator: + + .. code:: bro + + global r: MyRecordType; + r$c = 13; + + Record assignment can be done field by field or as a whole like: + + .. code:: bro + + r = [$c = 13, $s = "thirteen"]; + + When assigning a whole record value, all fields that are not + :bro:attr:`&optional` or have a :bro:attr:`&default` attribute must + be specified. + + To test for existence of a field that is :bro:attr:`&optional`, use the + ``?$`` operator: + + .. code:: bro + + if ( r?$s ) + ... + +.. bro:type:: file + + Bro supports writing to files, but not reading from them. For + example, declare, open, and write to a file and finally close it + like: + + .. code:: bro + + global f: file = open("myfile"); + print f, "hello, world"; + close(f); + + Writing to files like this for logging usually isn't recommended, for better + logging support see :doc:`/logging`. + +.. bro:type:: func + + See :bro:type:`function`. + +.. bro:type:: function + + Function types in Bro are declared using:: + + function( argument* ): type + + where *argument* is a (possibly empty) comma-separated list of + arguments, and *type* is an optional return type. For example: + + .. code:: bro + + global greeting: function(name: string): string; + + Here ``greeting`` is an identifier with a certain function type. + The function body is not defined yet and ``greeting`` could even + have different function body values at different times. To define + a function including a body value, the syntax is like: + + .. code:: bro + + function greeting(name: string): string + { + return "Hello, " + name; + } + + Note that in the definition above, it's not necessary for us to have + done the first (forward) declaration of ``greeting`` as a function + type, but when it is, the argument list and return type much match + exactly. + + Function types don't need to have a name and can be assigned anonymously: + + .. code:: bro + + greeting = function(name: string): string { return "Hi, " + name; }; + + And finally, the function can be called like: + + .. code:: bro + + print greeting("Dave"); + +.. bro:type:: event + + Event handlers are nearly identical in both syntax and semantics to + a :bro:type:`function`, with the two differences being that event + handlers have no return type since they never return a value, and + you cannot call an event handler. Instead of directly calling an + event handler from a script, event handler bodies are executed when + they are invoked by one of three different methods: + + - From the event engine + + When the event engine detects an event for which you have + defined a corresponding event handler, it queues an event for + that handler. The handler is invoked as soon as the event + engine finishes processing the current packet and flushing the + invocation of other event handlers that were queued first. + + - With the ``event`` statement from a script + + Immediately queuing invocation of an event handler occurs like: + + .. code:: bro + + event password_exposed(user, password); + + This assumes that ``password_exposed`` was previously declared + as an event handler type with compatible arguments. + + - Via the ``schedule`` expression in a script + + This delays the invocation of event handlers until some time in + the future. For example: + + .. code:: bro + + schedule 5 secs { password_exposed(user, password) }; + + Multiple event handler bodies can be defined for the same event handler + identifier and the body of each will be executed in turn. Ordering + of execution can be influenced with :bro:attr:`&priority`. + +Attributes +---------- + +Attributes occur at the end of type/event declarations and change their +behavior. The syntax is ``&key`` or ``&key=val``, e.g., ``type T: +set[count] &read_expire=5min`` or ``event foo() &priority=-3``. The Bro +scripting language supports the following built-in attributes. + +.. bro:attr:: &optional + + Allows a record field to be missing. For example the type ``record { + a: int, b: port &optional }`` could be instantiated both as + singleton ``[$a=127.0.0.1]`` or pair ``[$a=127.0.0.1, $b=80/tcp]``. + +.. bro:attr:: &default + + Uses a default value for a record field or container elements. For + example, ``table[int] of string &default="foo" }`` would create a + table that returns the :bro:type:`string` ``"foo"`` for any + non-existing index. + +.. bro:attr:: &redef + + Allows for redefinition of initial object values. This is typically + used with constants, for example, ``const clever = T &redef;`` would + allow the constant to be redefined at some later point during script + execution. + +.. bro:attr:: &rotate_interval + + Rotates a file after a specified interval. + +.. bro:attr:: &rotate_size + + Rotates a file after it has reached a given size in bytes. + +.. bro:attr:: &add_func + +.. TODO: needs to be documented. + +.. bro:attr:: &delete_func + +.. TODO: needs to be documented. + +.. bro:attr:: &expire_func + + Called right before a container element expires. The function's + first parameter is of the same type of the container and the second + parameter the same type of the container's index. The return + value is a :bro:type:`interval` indicating the amount of additional + time to wait before expiring the container element at the given + index (which will trigger another execution of this function). + +.. bro:attr:: &read_expire + + Specifies a read expiration timeout for container elements. That is, + the element expires after the given amount of time since the last + time it has been read. Note that a write also counts as a read. + +.. bro:attr:: &write_expire + + Specifies a write expiration timeout for container elements. That + is, the element expires after the given amount of time since the + last time it has been written. + +.. bro:attr:: &create_expire + + Specifies a creation expiration timeout for container elements. That + is, the element expires after the given amount of time since it has + been inserted into the container, regardless of any reads or writes. + +.. bro:attr:: &persistent + + Makes a variable persistent, i.e., its value is writen to disk (per + default at shutdown time). + +.. bro:attr:: &synchronized + + Synchronizes variable accesses across nodes. The value of a + ``&synchronized`` variable is automatically propagated to all peers + when it changes. + +.. bro:attr:: &postprocessor + +.. TODO: needs to be documented. + +.. bro:attr:: &encrypt + + Encrypts files right before writing them to disk. + +.. TODO: needs to be documented in more detail. + +.. bro:attr:: &match + +.. TODO: needs to be documented. + +.. bro:attr:: &disable_print_hook + + Deprecated. Will be removed. + +.. bro:attr:: &raw_output + + Opens a file in raw mode, i.e., non-ASCII characters are not + escaped. + +.. bro:attr:: &mergeable + + Prefers set union to assignment for synchronized state. This + attribute is used in conjunction with :bro:attr:`&synchronized` + container types: when the same container is updated at two peers + with different value, the propagation of the state causes a race + condition, where the last update succeeds. This can cause + inconsistencies and can be avoided by unifying the two sets, rather + than merely overwriting the old value. + +.. bro:attr:: &priority + + Specifies the execution priority of an event handler. Higher values + are executed before lower ones. The default value is 0. + +.. bro:attr:: &group + + Groups event handlers such that those in the same group can be + jointly activated or deactivated. + +.. bro:attr:: &log + + Writes a record field to the associated log stream. + +.. bro:attr:: &error_handler + +.. TODO: needs documented + +.. bro:attr:: (&tracked) + +.. TODO: needs documented or removed if it's not used anywhere. diff --git a/doc/scripts/example.bro b/doc/scripts/example.bro index a50bff625a..9f6f656ee1 100644 --- a/doc/scripts/example.bro +++ b/doc/scripts/example.bro @@ -1,24 +1,20 @@ -##! This is an example script that demonstrates how to document. Comments -##! of the form ``##!`` are for the script summary. The contents of +##! This is an example script that demonstrates documentation features. +##! Comments of the form ``##!`` are for the script summary. The contents of ##! these comments are transferred directly into the auto-generated ##! `reStructuredText `_ ##! (reST) document's summary section. ##! ##! .. tip:: You can embed directives and roles within ``##``-stylized comments. ##! -##! A script's logging information has to be documented manually as minimally -##! shown below. Note that references may not always be possible (e.g. -##! anonymous filter functions) and a script may not need to document -##! each of "columns", "event", "filter" depending on exactly what it's doing. +##! There's also a custom role to reference any identifier node in +##! the Bro Sphinx domain that's good for "see alsos", e.g. ##! -##! **Logging Stream ID:** :bro:enum:`Example::EXAMPLE` -##! :Columns: :bro:type:`Example::Info` -##! :Event: :bro:id:`Example::log_example` -##! :Filter: ``example-filter`` -##! uses :bro:id:`Example::filter_func` to determine whether to -##! exclude the ``ts`` field +##! See also: :bro:see:`Example::a_var`, :bro:see:`Example::ONE`, +##! :bro:see:`SSH::Info` ##! -##! :Author: Jon Siwek +##! And a custom directive does the equivalent references: +##! +##! .. bro:see:: Example::a_var Example::ONE SSH::Info # Comments that use a single pound sign (#) are not significant to # a script's auto-generated documentation, but ones that use a @@ -26,8 +22,8 @@ # field comments, it's necessary to disambiguate the field with # which a comment associates: e.g. "##<" can be used on the same line # as a field to signify the comment relates to it and not the -# following field. "##<" is not meant for general use, just -# record/enum fields. +# following field. "##<" can also be used more generally in any +# variable declarations to associate with the last-declared identifier. # # Generally, the auto-doc comments (##) are associated with the # next declaration/identifier found in the script, but the doc framework @@ -80,7 +76,7 @@ redef enum Notice::Type += { # Comments of the "##" form can be use to further document it, but it's # better to do all documentation related to logging in the summary section # as is shown above. -redef enum Log::ID += { EXAMPLE }; +redef enum Log::ID += { LOG }; # Anything declared in the export section will show up in the rendered # documentation's "public interface" section @@ -155,7 +151,7 @@ export { const an_option: set[addr, addr, string] &redef; # default initialization will be self-documenting - const option_with_init = 0.01 secs &redef; + const option_with_init = 0.01 secs &redef; ##< More docs can be added here. ############## state variables ############ # right now, I'm defining this as any global @@ -187,6 +183,7 @@ export { ## Summarize "an_event" here. ## Give more details about "an_event" here. + ## Example::an_event should not be confused as a parameter. ## name: describe the argument here global an_event: event(name: string); @@ -218,8 +215,8 @@ type PrivateRecord: record { event bro_init() { - Log::create_stream(EXAMPLE, [$columns=Info, $ev=log_example]); - Log::add_filter(EXAMPLE, [ + Log::create_stream(Example::LOG, [$columns=Info, $ev=log_example]); + Log::add_filter(Example::LOG, [ $name="example-filter", $path="example-filter", $pred=filter_func, diff --git a/doc/scripts/example.rst b/doc/scripts/example.rst new file mode 100644 index 0000000000..b76b9af59b --- /dev/null +++ b/doc/scripts/example.rst @@ -0,0 +1,291 @@ +.. Automatically generated. Do not edit. + +example.bro +=========== + +:download:`Original Source File ` + +Overview +-------- +This is an example script that demonstrates how to document. Comments +of the form ``##!`` are for the script summary. The contents of +these comments are transferred directly into the auto-generated +`reStructuredText `_ +(reST) document's summary section. + +.. tip:: You can embed directives and roles within ``##``-stylized comments. + +:Imports: :doc:`policy/frameworks/software/vulnerable ` + +Summary +~~~~~~~ +Options +####### +============================================================================ ====================================== +:bro:id:`Example::an_option`: :bro:type:`set` :bro:attr:`&redef` add documentation for "an_option" here + +:bro:id:`Example::option_with_init`: :bro:type:`interval` :bro:attr:`&redef` +============================================================================ ====================================== + +State Variables +############### +=========================================================================== ======================================= +:bro:id:`Example::a_var`: :bro:type:`bool` put some documentation for "a_var" here + +:bro:id:`Example::var_with_attr`: :bro:type:`count` :bro:attr:`&persistent` + +:bro:id:`Example::var_without_explicit_type`: :bro:type:`string` +=========================================================================== ======================================= + +Types +##### +====================================================== ========================================================== +:bro:type:`Example::SimpleEnum`: :bro:type:`enum` documentation for "SimpleEnum" + goes here. + +:bro:type:`Example::SimpleRecord`: :bro:type:`record` general documentation for a type "SimpleRecord" + goes here. + +:bro:type:`Example::ComplexRecord`: :bro:type:`record` general documentation for a type "ComplexRecord" goes here + +:bro:type:`Example::Info`: :bro:type:`record` An example record to be used with a logging stream. +====================================================== ========================================================== + +Events +###### +================================================= ============================================================= +:bro:id:`Example::an_event`: :bro:type:`event` Summarize "an_event" here. + +:bro:id:`Example::log_example`: :bro:type:`event` This is a declaration of an example event that can be used in + logging streams and is raised once for each log entry. +================================================= ============================================================= + +Functions +######### +=============================================== ======================================= +:bro:id:`Example::a_function`: :bro:type:`func` Summarize purpose of "a_function" here. +=============================================== ======================================= + +Redefinitions +############# +===================================================== ======================================== +:bro:type:`Log::ID`: :bro:type:`enum` + +:bro:type:`Example::SimpleEnum`: :bro:type:`enum` document the "SimpleEnum" redef here + +:bro:type:`Example::SimpleRecord`: :bro:type:`record` document the record extension redef here +===================================================== ======================================== + +Namespaces +~~~~~~~~~~ +.. bro:namespace:: Example + +Notices +~~~~~~~ +:bro:type:`Notice::Type` + + :Type: :bro:type:`enum` + + .. bro:enum:: Example::Notice_One Notice::Type + + any number of this type of comment + will document "Notice_One" + + .. bro:enum:: Example::Notice_Two Notice::Type + + any number of this type of comment + will document "Notice_Two" + + .. bro:enum:: Example::Notice_Three Notice::Type + + .. bro:enum:: Example::Notice_Four Notice::Type + +Public Interface +---------------- +Options +~~~~~~~ +.. bro:id:: Example::an_option + + :Type: :bro:type:`set` [:bro:type:`addr`, :bro:type:`addr`, :bro:type:`string`] + :Attributes: :bro:attr:`&redef` + :Default: ``{}`` + + add documentation for "an_option" here + +.. bro:id:: Example::option_with_init + + :Type: :bro:type:`interval` + :Attributes: :bro:attr:`&redef` + :Default: ``10.0 msecs`` + +State Variables +~~~~~~~~~~~~~~~ +.. bro:id:: Example::a_var + + :Type: :bro:type:`bool` + + put some documentation for "a_var" here + +.. bro:id:: Example::var_with_attr + + :Type: :bro:type:`count` + :Attributes: :bro:attr:`&persistent` + +.. bro:id:: Example::var_without_explicit_type + + :Type: :bro:type:`string` + :Default: ``"this works"`` + +Types +~~~~~ +.. bro:type:: Example::SimpleEnum + + :Type: :bro:type:`enum` + + .. bro:enum:: Example::ONE Example::SimpleEnum + + and more specific info for "ONE" + can span multiple lines + + .. bro:enum:: Example::TWO Example::SimpleEnum + + or more info like this for "TWO" + can span multiple lines + + .. bro:enum:: Example::THREE Example::SimpleEnum + + documentation for "SimpleEnum" + goes here. + +.. bro:type:: Example::SimpleRecord + + :Type: :bro:type:`record` + + field1: :bro:type:`count` + counts something + + field2: :bro:type:`bool` + toggles something + + general documentation for a type "SimpleRecord" + goes here. + +.. bro:type:: Example::ComplexRecord + + :Type: :bro:type:`record` + + field1: :bro:type:`count` + counts something + + field2: :bro:type:`bool` + toggles something + + field3: :bro:type:`Example::SimpleRecord` + + msg: :bro:type:`string` :bro:attr:`&default` = ``"blah"`` :bro:attr:`&optional` + attributes are self-documenting + + general documentation for a type "ComplexRecord" goes here + +.. bro:type:: Example::Info + + :Type: :bro:type:`record` + + ts: :bro:type:`time` :bro:attr:`&log` + + uid: :bro:type:`string` :bro:attr:`&log` + + status: :bro:type:`count` :bro:attr:`&log` :bro:attr:`&optional` + + An example record to be used with a logging stream. + +Events +~~~~~~ +.. bro:id:: Example::an_event + + :Type: :bro:type:`event` (name: :bro:type:`string`) + + Summarize "an_event" here. + Give more details about "an_event" here. + + :param name: describe the argument here + +.. bro:id:: Example::log_example + + :Type: :bro:type:`event` (rec: :bro:type:`Example::Info`) + + This is a declaration of an example event that can be used in + logging streams and is raised once for each log entry. + +Functions +~~~~~~~~~ +.. bro:id:: Example::a_function + + :Type: :bro:type:`function` (tag: :bro:type:`string`, msg: :bro:type:`string`) : :bro:type:`string` + + Summarize purpose of "a_function" here. + Give more details about "a_function" here. + Separating the documentation of the params/return values with + empty comments is optional, but improves readability of script. + + + :param tag: function arguments can be described + like this + + :param msg: another param + + + :returns: describe the return type here + +Redefinitions +~~~~~~~~~~~~~ +:bro:type:`Log::ID` + + :Type: :bro:type:`enum` + + .. bro:enum:: Example::LOG Log::ID + +:bro:type:`Example::SimpleEnum` + + :Type: :bro:type:`enum` + + .. bro:enum:: Example::FOUR Example::SimpleEnum + + and some documentation for "FOUR" + + .. bro:enum:: Example::FIVE Example::SimpleEnum + + also "FIVE" for good measure + + document the "SimpleEnum" redef here + +:bro:type:`Example::SimpleRecord` + + :Type: :bro:type:`record` + + field_ext: :bro:type:`string` :bro:attr:`&optional` + document the extending field here + (or here) + + document the record extension redef here + +Port Analysis +------------- +:ref:`More Information ` + +SSL:: + + [ports={ + 443/tcp, + 562/tcp + }] + +Packet Filter +------------- +:ref:`More Information ` + +Filters added:: + + [ssl] = tcp port 443, + [nntps] = tcp port 562 + diff --git a/doc/scripts/genDocSourcesList.sh b/doc/scripts/genDocSourcesList.sh index 8ef4ff9c14..a10121221a 100755 --- a/doc/scripts/genDocSourcesList.sh +++ b/doc/scripts/genDocSourcesList.sh @@ -11,6 +11,8 @@ # Specific scripts can be blacklisted below when e.g. they currently aren't # parseable or they just aren't meant to be documented. +export LC_ALL=C # Make sorting stable. + blacklist () { if [[ "$blacklist" == "" ]]; then @@ -34,9 +36,6 @@ blacklist all.bro blacklist init-default.bro blacklist init-bare.bro -tmp_blacklist hot.conn.bro -tmp_blacklist scan.bro - statictext="\ # DO NOT EDIT # This file is auto-generated from the "genDocSourcesList.sh" script. @@ -68,12 +67,12 @@ sourcedir=${thisdir}/../.. echo "$statictext" > $outfile -bifs=`( cd ${sourcedir}/build/src && find . -name \*\.bro | sort )` +bifs=`( cd ${sourcedir}/src && find . -name \*\.bif | sort )` for file in $bifs do - f=${file:2} - echo "rest_target(\${CMAKE_BINARY_DIR}/src $f)" >> $outfile + f=${file:2}.bro + echo "rest_target(\${CMAKE_BINARY_DIR}/src base/$f)" >> $outfile done scriptfiles=`( cd ${sourcedir}/scripts && find . -name \*\.bro | sort )` diff --git a/doc/scripts/index.rst b/doc/scripts/index.rst new file mode 100644 index 0000000000..bf0fa25f10 --- /dev/null +++ b/doc/scripts/index.rst @@ -0,0 +1,8 @@ +.. This is a stub doc to which broxygen appends during the build process + +Index of All Individual Bro Scripts +=================================== + +.. toctree:: + :maxdepth: 1 + diff --git a/doc/scripts/internal.rst b/doc/scripts/internal.rst new file mode 100644 index 0000000000..a6c10f1cfb --- /dev/null +++ b/doc/scripts/internal.rst @@ -0,0 +1,5 @@ +.. This is a stub doc to which broxygen appends during the build process + +Internal Scripts +================ + diff --git a/doc/scripts/source/packages.rst b/doc/scripts/packages.rst similarity index 76% rename from doc/scripts/source/packages.rst rename to doc/scripts/packages.rst index 35f6633fd4..56909ffbc6 100644 --- a/doc/scripts/source/packages.rst +++ b/doc/scripts/packages.rst @@ -1,7 +1,7 @@ -.. This is a stub doc to which the build process can append. +.. This is a stub doc to which broxygen appends during the build process -Bro Script Packages -=================== +Index of All Bro Script Packages +================================ Bro has the following script packages (e.g. collections of related scripts in a common directory). If the package directory contains a ``__load__.bro`` @@ -10,8 +10,3 @@ script, it supports being loaded in mass as a whole directory for convenience. Packages/scripts in the ``base/`` directory are all loaded by default, while ones in ``policy/`` provide functionality and customization options that are more appropriate for users to decide whether they'd like to load it or not. - -.. toctree:: - :maxdepth: 1 - - diff --git a/doc/scripts/source/_static/showhide.js b/doc/scripts/source/_static/showhide.js deleted file mode 100644 index d6a8923143..0000000000 --- a/doc/scripts/source/_static/showhide.js +++ /dev/null @@ -1,64 +0,0 @@ -// make literal blocks corresponding to identifier initial values -// hidden by default -$(document).ready(function() { - - var showText='(Show Value)'; - var hideText='(Hide Value)'; - - var is_visible = false; - - // select field-list tables that come before a literal block - tables = $('.highlight-python').prev('table.docutils.field-list'); - - tables.find('th.field-name').filter(function(index) { - return $(this).html() == "Default :"; - }).next().append(''+showText+''); - - // hide all literal blocks that follow a field-list table - tables.next('.highlight-python').hide(); - - // register handler for clicking a "toggle" link - $('a.toggleLink').click(function() { - is_visible = !is_visible; - - $(this).html( (!is_visible) ? showText : hideText); - - // the link is inside a
    and the next - // literal block after the table is the literal block that we want - // to show/hide - $(this).parent().parent().parent().parent().next('.highlight-python').slideToggle('fast'); - - // override default link behavior - return false; - }); -}); - -// make "Private Interface" sections hidden by default -$(document).ready(function() { - - var showText='Show Private Interface (for internal use)'; - var hideText='Hide Private Interface'; - - var is_visible = false; - - // insert show/hide links - $('#private-interface').children(":first-child").after(''+showText+''); - - // wrap all sub-sections in a new div that can be hidden/shown - $('#private-interface').children(".section").wrapAll('
    '); - - // hide the given class - $('.private').hide(); - - // register handler for clicking a "toggle" link - $('a.privateToggle').click(function() { - is_visible = !is_visible; - - $(this).html( (!is_visible) ? showText : hideText); - - $('.private').slideToggle('fast'); - - // override default link behavior - return false; - }); -}); diff --git a/doc/scripts/source/_templates/layout.html b/doc/scripts/source/_templates/layout.html deleted file mode 100644 index 5685e1dc37..0000000000 --- a/doc/scripts/source/_templates/layout.html +++ /dev/null @@ -1,5 +0,0 @@ -{% extends "!layout.html" %} -{% block extrahead %} - - {{ super() }} -{% endblock %} diff --git a/doc/scripts/source/bifs.rst b/doc/scripts/source/bifs.rst deleted file mode 100644 index 6a42cafafc..0000000000 --- a/doc/scripts/source/bifs.rst +++ /dev/null @@ -1,5 +0,0 @@ -.. This is a stub doc to which the build process can append. - -Built-In Functions (BIFs) -========================= - diff --git a/doc/scripts/source/builtins.rst b/doc/scripts/source/builtins.rst deleted file mode 100644 index e6a9e9b829..0000000000 --- a/doc/scripts/source/builtins.rst +++ /dev/null @@ -1,118 +0,0 @@ -Builtin Types and Attributes -============================ - -Types ------ - -The Bro scripting language supports the following built-in types. - -.. TODO: add documentation - -.. bro:type:: void - -.. bro:type:: bool - -.. bro:type:: int - -.. bro:type:: count - -.. bro:type:: counter - -.. bro:type:: double - -.. bro:type:: time - -.. bro:type:: interval - -.. bro:type:: string - -.. bro:type:: pattern - -.. bro:type:: enum - -.. bro:type:: timer - -.. bro:type:: port - -.. bro:type:: addr - -.. bro:type:: net - -.. bro:type:: subnet - -.. bro:type:: any - -.. bro:type:: table - -.. bro:type:: union - -.. bro:type:: record - -.. bro:type:: types - -.. bro:type:: func - -.. bro:type:: file - -.. bro:type:: vector - -.. TODO: below are kind of "special cases" that bro knows about? - -.. bro:type:: set - -.. bro:type:: function - -.. bro:type:: event - -Attributes ----------- - -The Bro scripting language supports the following built-in attributes. - -.. TODO: add documentation - -.. bro:attr:: &optional - -.. bro:attr:: &default - -.. bro:attr:: &redef - -.. bro:attr:: &rotate_interval - -.. bro:attr:: &rotate_size - -.. bro:attr:: &add_func - -.. bro:attr:: &delete_func - -.. bro:attr:: &expire_func - -.. bro:attr:: &read_expire - -.. bro:attr:: &write_expire - -.. bro:attr:: &create_expire - -.. bro:attr:: &persistent - -.. bro:attr:: &synchronized - -.. bro:attr:: &postprocessor - -.. bro:attr:: &encrypt - -.. bro:attr:: &match - -.. bro:attr:: &disable_print_hook - -.. bro:attr:: &raw_output - -.. bro:attr:: &mergeable - -.. bro:attr:: &priority - -.. bro:attr:: &group - -.. bro:attr:: &log - -.. bro:attr:: (&tracked) diff --git a/doc/scripts/source/common.rst b/doc/scripts/source/common.rst deleted file mode 100644 index 6105585b2c..0000000000 --- a/doc/scripts/source/common.rst +++ /dev/null @@ -1,19 +0,0 @@ -Common Documentation -==================== - -.. _common_port_analysis_doc: - -Port Analysis -------------- - -TODO: add some stuff here - -.. _common_packet_filter_doc: - -Packet Filter -------------- - -TODO: add some stuff here - -.. note:: Filters are only relevant when dynamic protocol detection (DPD) - is explicitly turned off (Bro release 1.6 enabled DPD by default). diff --git a/doc/scripts/source/index.rst b/doc/scripts/source/index.rst deleted file mode 100644 index a144644208..0000000000 --- a/doc/scripts/source/index.rst +++ /dev/null @@ -1,23 +0,0 @@ -.. Bro documentation master file - -Welcome to Bro's documentation! -=============================== - -Contents: - -.. toctree:: - :maxdepth: 1 - :glob: - - common - builtins - internal - bifs - packages - scripts/index - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`search` diff --git a/doc/scripts/source/internal.rst b/doc/scripts/source/internal.rst deleted file mode 100644 index 817c76e725..0000000000 --- a/doc/scripts/source/internal.rst +++ /dev/null @@ -1,5 +0,0 @@ -.. This is a stub doc to which the build process can append. - -Internal Scripts -================ - diff --git a/doc/scripts/source/scripts/index.rst b/doc/scripts/source/scripts/index.rst deleted file mode 100644 index fd11a3924e..0000000000 --- a/doc/scripts/source/scripts/index.rst +++ /dev/null @@ -1,6 +0,0 @@ -Index of All Bro Script Documentation -===================================== - -.. toctree:: - :maxdepth: 1 - diff --git a/doc/signatures.rst b/doc/signatures.rst new file mode 100644 index 0000000000..7a1b164dbb --- /dev/null +++ b/doc/signatures.rst @@ -0,0 +1,390 @@ + +========== +Signatures +========== + +.. rst-class:: opening + + Bro relies primarily on its extensive scripting language for + defining and analyzing detection policies. In addition, however, + Bro also provides an independent *signature language* for doing + low-level, Snort-style pattern matching. While signatures are + *not* Bro's preferred detection tool, they sometimes come in handy + and are closer to what many people are familiar with from using + other NIDS. This page gives a brief overview on Bro's signatures + and covers some of their technical subtleties. + +.. contents:: + :depth: 2 + +Basics +====== + +Let's look at an example signature first: + +.. code:: bro-sig + + signature my-first-sig { + ip-proto == tcp + dst-port == 80 + payload /.*root/ + event "Found root!" + } + + +This signature asks Bro to match the regular expression ``.*root`` on +all TCP connections going to port 80. When the signature triggers, Bro +will raise an event :bro:id:`signature_match` of the form: + +.. code:: bro + + event signature_match(state: signature_state, msg: string, data: string) + +Here, ``state`` contains more information on the connection that +triggered the match, ``msg`` is the string specified by the +signature's event statement (``Found root!``), and data is the last +piece of payload which triggered the pattern match. + +To turn such :bro:id:`signature_match` events into actual alarms, you can +load Bro's :doc:`/scripts/base/frameworks/signatures/main` script. +This script contains a default event handler that raises +:bro:enum:`Signatures::Sensitive_Signature` :doc:`Notices ` +(as well as others; see the beginning of the script). + +As signatures are independent of Bro's policy scripts, they are put +into their own file(s). There are two ways to specify which files +contain signatures: By using the ``-s`` flag when you invoke Bro, or +by extending the Bro variable :bro:id:`signature_files` using the ``+=`` +operator. If a signature file is given without a path, it is searched +along the normal ``BROPATH``. The default extension of the file name +is ``.sig``, and Bro appends that automatically when necessary. + +Signature language +================== + +Let's look at the format of a signature more closely. Each individual +signature has the format ``signature { }``. ```` +is a unique label for the signature. There are two types of +attributes: *conditions* and *actions*. The conditions define when the +signature matches, while the actions declare what to do in the case of +a match. Conditions can be further divided into four types: *header*, +*content*, *dependency*, and *context*. We discuss these all in more +detail in the following. + +Conditions +---------- + +Header Conditions +~~~~~~~~~~~~~~~~~ + +Header conditions limit the applicability of the signature to a subset +of traffic that contains matching packet headers. For TCP, this match +is performed only for the first packet of a connection. For other +protocols, it is done on each individual packet. + +There are pre-defined header conditions for some of the most used +header fields. All of them generally have the format `` +``, where ```` names the header field; ``cmp`` is +one of ``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``; and +```` is a list of comma-separated values to compare +against. The following keywords are defined: + +``src-ip``/``dst-ip `` + Source and destination address, respectively. Addresses can be + given as IP addresses or CIDR masks. + +``src-port``/``dst-port`` ```` + Source and destination port, respectively. + +``ip-proto tcp|udp|icmp`` + IP protocol. + +For lists of multiple values, they are sequentially compared against +the corresponding header field. If at least one of the comparisons +evaluates to true, the whole header condition matches (exception: with +``!=``, the header condition only matches if all values differ). + +In addition to these pre-defined header keywords, a general header +condition can be defined either as + +.. code:: bro-sig + + header [:] [& ] + +This compares the value found at the given position of the packet +header with a list of values. ``offset`` defines the position of the +value within the header of the protocol defined by ``proto`` (which +can be ``ip``, ``tcp``, ``udp`` or ``icmp``). ``size`` is either 1, 2, +or 4 and specifies the value to have a size of this many bytes. If the +optional ``& `` is given, the packet's value is first masked +with the integer before it is compared to the value-list. ``cmp`` is +one of ``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``. ``value-list`` is +a list of comma-separated integers similar to those described above. +The integers within the list may be followed by an additional ``/ +mask`` where ``mask`` is a value from 0 to 32. This corresponds to the +CIDR notation for netmasks and is translated into a corresponding +bitmask applied to the packet's value prior to the comparison (similar +to the optional ``& integer``). + +Putting it all together, this is an example condition that is +equivalent to ``dst-ip == 1.2.3.4/16, 5.6.7.8/24``: + +.. code:: bro-sig + + header ip[16:4] == 1.2.3.4/16, 5.6.7.8/24 + +Internally, the predefined header conditions are in fact just +short-cuts and mapped into a generic condition. + +Content Conditions +~~~~~~~~~~~~~~~~~~ + +Content conditions are defined by regular expressions. We +differentiate two kinds of content conditions: first, the expression +may be declared with the ``payload`` statement, in which case it is +matched against the raw payload of a connection (for reassembled TCP +streams) or of each packet (for ICMP, UDP, and non-reassembled TCP). +Second, it may be prefixed with an analyzer-specific label, in which +case the expression is matched against the data as extracted by the +corresponding analyzer. + +A ``payload`` condition has the form: + +.. code:: bro-sig + + payload // + +Currently, the following analyzer-specific content conditions are +defined (note that the corresponding analyzer has to be activated by +loading its policy script): + +``http-request //`` + The regular expression is matched against decoded URIs of HTTP + requests. Obsolete alias: ``http``. + +``http-request-header //`` + The regular expression is matched against client-side HTTP headers. + +``http-request-body //`` + The regular expression is matched against client-side bodys of + HTTP requests. + +``http-reply-header //`` + The regular expression is matched against server-side HTTP headers. + +``http-reply-body //`` + The regular expression is matched against server-side bodys of + HTTP replys. + +``ftp //`` + The regular expression is matched against the command line input + of FTP sessions. + +``finger //`` + The regular expression is matched against finger requests. + +For example, ``http-request /.*(etc/(passwd|shadow)/`` matches any URI +containing either ``etc/passwd`` or ``etc/shadow``. To filter on request +types, e.g. ``GET``, use ``payload /GET /``. + +Note that HTTP pipelining (that is, multiple HTTP transactions in a +single TCP connection) has some side effects on signature matches. If +multiple conditions are specified within a single signature, this +signature matches if all conditions are met by any HTTP transaction +(not necessarily always the same!) in a pipelined connection. + +Dependency Conditions +~~~~~~~~~~~~~~~~~~~~~ + +To define dependencies between signatures, there are two conditions: + + +``requires-signature [!] `` + Defines the current signature to match only if the signature given + by ``id`` matches for the same connection. Using ``!`` negates the + condition: The current signature only matches if ``id`` does not + match for the same connection (using this defers the match + decision until the connection terminates). + +``requires-reverse-signature [!] `` + Similar to ``requires-signature``, but ``id`` has to match for the + opposite direction of the same connection, compared to the current + signature. This allows to model the notion of requests and + replies. + +Context Conditions +~~~~~~~~~~~~~~~~~~ + +Context conditions pass the match decision on to other components of +Bro. They are only evaluated if all other conditions have already +matched. The following context conditions are defined: + +``eval `` + The given policy function is called and has to return a boolean + confirming the match. If false is returned, no signature match is + going to be triggered. The function has to be of type ``function + cond(state: signature_state, data: string): bool``. Here, + ``content`` may contain the most recent content chunk available at + the time the signature was matched. If no such chunk is available, + ``content`` will be the empty string. ``signature_state`` is + defined as follows: + + .. code:: bro + + type signature_state: record { + id: string; # ID of the signature + conn: connection; # Current connection + is_orig: bool; # True if current endpoint is originator + payload_size: count; # Payload size of the first packet + }; + + +``payload-size `` + Compares the integer to the size of the payload of a packet. For + reassembled TCP streams, the integer is compared to the size of + the first in-order payload chunk. Note that the latter is not very + well defined. + +``same-ip`` + Evaluates to true if the source address of the IP packets equals + its destination address. + +``tcp-state `` + Imposes restrictions on the current TCP state of the connection. + ``state-list`` is a comma-separated list of the keywords + ``established`` (the three-way handshake has already been + performed), ``originator`` (the current data is send by the + originator of the connection), and ``responder`` (the current data + is send by the responder of the connection). + + +Actions +------- + +Actions define what to do if a signature matches. Currently, there are +two actions defined: + +``event `` + Raises a :bro:id:`signature_match` event. The event handler has the + following type: + + .. code:: bro + + event signature_match(state: signature_state, msg: string, data: string) + + The given string is passed in as ``msg``, and data is the current + part of the payload that has eventually lead to the signature + match (this may be empty for signatures without content + conditions). + +``enable `` + Enables the protocol analyzer ```` for the matching + connection (``"http"``, ``"ftp"``, etc.). This is used by Bro's + dynamic protocol detection to activate analyzers on the fly. + +Things to keep in mind when writing signatures +============================================== + +* Each signature is reported at most once for every connection, + further matches of the same signature are ignored. + +* The content conditions perform pattern matching on elements + extracted from an application protocol dialogue. For example, ``http + /.*passwd/`` scans URLs requested within HTTP sessions. The thing to + keep in mind here is that these conditions only perform any matching + when the corresponding application analyzer is actually *active* for + a connection. Note that by default, analyzers are not enabled if the + corresponding Bro script has not been loaded. A good way to + double-check whether an analyzer "sees" a connection is checking its + log file for corresponding entries. If you cannot find the + connection in the analyzer's log, very likely the signature engine + has also not seen any application data. + +* As the name indicates, the ``payload`` keyword matches on packet + *payload* only. You cannot use it to match on packet headers; use + the header conditions for that. + +* For TCP connections, header conditions are only evaluated for the + *first packet from each endpoint*. If a header condition does not + match the initial packets, the signature will not trigger. Bro + optimizes for the most common application here, which is header + conditions selecting the connections to be examined more closely + with payload statements. + +* For UDP and ICMP flows, the payload matching is done on a per-packet + basis; i.e., any content crossing packet boundaries will not be + found. For TCP connections, the matching semantics depend on whether + Bro is *reassembling* the connection (i.e., putting all of a + connection's packets in sequence). By default, Bro is reassembling + the first 1K of every TCP connection, which means that within this + window, matches will be found without regards to packet order or + boundaries (i.e., *stream-wise matching*). + +* For performance reasons, by default Bro *stops matching* on a + connection after seeing 1K of payload; see the section on options + below for how to change this behaviour. The default was chosen with + Bro's main user of signatures in mind: dynamic protocol detection + works well even when examining just connection heads. + +* Regular expressions are implicitly anchored, i.e., they work as if + prefixed with the ``^`` operator. For reassembled TCP connections, + they are anchored at the first byte of the payload *stream*. For all + other connections, they are anchored at the first payload byte of + each packet. To match at arbitrary positions, you can prefix the + regular expression with ``.*``, as done in the examples above. + +* To match on non-ASCII characters, Bro's regular expressions support + the ``\x`` operator. CRs/LFs are not treated specially by the + signature engine and can be matched with ``\r`` and ``\n``, + respectively. Generally, Bro follows `flex's regular expression + syntax + `_. + See the DPD signatures in ``base/frameworks/dpd/dpd.sig`` for some examples + of fairly complex payload patterns. + +* The data argument of the :bro:id:`signature_match` handler might not carry + the full text matched by the regular expression. Bro performs the + matching incrementally as packets come in; when the signature + eventually fires, it can only pass on the most recent chunk of data. + + +Options +======= + +The following options control details of Bro's matching process: + +``dpd_reassemble_first_packets: bool`` (default: ``T``) + If true, Bro reassembles the beginning of every TCP connection (of + up to ``dpd_buffer_size`` bytes, see below), to facilitate + reliable matching across packet boundaries. If false, only + connections are reassembled for which an application-layer + analyzer gets activated (e.g., by Bro's dynamic protocol + detection). + +``dpd_match_only_beginning : bool`` (default: ``T``) + If true, Bro performs packet matching only within the initial + payload window of ``dpd_buffer_size``. If false, it keeps matching + on subsequent payload as well. + +``dpd_buffer_size: count`` (default: ``1024``) + Defines the buffer size for the two preceding options. In + addition, this value determines the amount of bytes Bro buffers + for each connection in order to activate application analyzers + even after parts of the payload have already passed through. This + is needed by the dynamic protocol detection capability to defer + the decision which analyzers to use. + + +So, how about using Snort signatures with Bro? +============================================== + +There was once a script, ``snort2bro``, that converted Snort +signatures automatically into Bro's signature syntax. However, in our +experience this didn't turn out to be a very useful thing to do +because by simply using Snort signatures, one can't benefit from the +additional capabilities that Bro provides; the approaches of the two +systems are just too different. We therefore stopped maintaining the +``snort2bro`` script, and there are now many newer Snort options which +it doesn't support. The script is now no longer part of the Bro +distribution. + diff --git a/doc/upgrade.rst b/doc/upgrade.rst new file mode 100644 index 0000000000..9c1537754a --- /dev/null +++ b/doc/upgrade.rst @@ -0,0 +1,247 @@ + +============================= +Upgrading From Bro 1.5 to 2.0 +============================= + +.. rst-class:: opening + + This guide details differences between Bro versions 1.5 and 2.0 + that may be important for users to know as they work on updating + their Bro deployment/configuration to the later version. + +.. contents:: + + +Introduction +============ + +As the version number jump suggests, Bro 2.0 is a major upgrade and +lots of things have changed. Most importantly, we have rewritten +almost all of Bro's default scripts from scratch, using quite +different structure now and focusing more on operational deployment. +The result is a system that works much better "out of the box", even +without much initial site-specific configuration. The down-side is +that 1.x configurations will need to be adapted to work with the new +version. The two rules of thumb are: + + (1) If you have written your own Bro scripts + that do not depend on any of the standard scripts formerly + found in ``policy/``, they will most likely just keep working + (although you might want to adapt them to use some of the new + features, like the new logging framework; see below). + + (2) If you have custom code that depends on specifics of 1.x + default scripts (including most configuration tuning), that is + unlikely to work with 2.x. We recommend to start by using just + the new scripts first, and then port over any customizations + incrementally as necessary (they may be much easier to do now, + or even unnecessary). Send mail to the Bro user mailing list + if you need help. + +Below we summarize changes from 1.x to 2.x in more detail. This list +isn't complete, see the :download:`CHANGES ` file in the +distribution for the full story. + +Default Scripts +=============== + +Organization +------------ + +In versions before 2.0, Bro scripts were all maintained in a flat +directory called ``policy/`` in the source tree. This directory is now +renamed to ``scripts/`` and contains major subdirectories ``base/``, +``policy/``, and ``site/``, each of which may also be subdivided +further. + +The contents of the new ``scripts/`` directory, like the old/flat +``policy/`` still gets installed under the ``share/bro`` +subdirectory of the installation prefix path just like previous +versions. For example, if Bro was compiled like ``./configure +--prefix=/usr/local/bro && make && make install``, then the script +hierarchy can be found in ``/usr/local/bro/share/bro``. + +The main +subdirectories of that hierarchy are as follows: + +- ``base/`` contains all scripts that are loaded by Bro by default + (unless the ``-b`` command line option is used to run Bro in a + minimal configuration). Note that is a major conceptual change: + rather than not loading anything by default, Bro now uses an + extensive set of default scripts out of the box. + + The scripts under this directory generally either accumulate/log + useful state/protocol information for monitored traffic, configure a + default/recommended mode of operation, or provide extra Bro + scripting-layer functionality that has no significant performance cost. + +- ``policy/`` contains all scripts that a user will need to explicitly + tell Bro to load. These are scripts that implement + functionality/analysis that not all users may want to use and may have + more significant performance costs. For a new installation, you + should go through these and see what appears useful to load. + +- ``site/`` remains a directory that can be used to store locally + developed scripts. It now comes with some preinstalled example + scripts that contain recommended default configurations going beyond + the ``base/`` setup. E.g. ``local.bro`` loads extra scripts from + ``policy/`` and does extra tuning. These files can be customized in + place without being overwritten by upgrades/reinstalls, unlike + scripts in other directories. + +With version 2.0, the default ``BROPATH`` is set to automatically +search for scripts in ``policy/``, ``site/`` and their parent +directory, but **not** ``base/``. Generally, everything under +``base/`` is loaded automatically, but for users of the ``-b`` option, +it's important to know that loading a script in that directory +requires the extra ``base/`` path qualification. For example, the +following two scripts: + +* ``$PREFIX/share/bro/base/protocols/ssl/main.bro`` +* ``$PREFIX/share/bro/policy/protocols/ssl/validate-certs.bro`` + +are referenced from another Bro script like: + +.. code:: bro + + @load base/protocols/ssl/main + @load protocols/ssl/validate-certs + +Notice how ``policy/`` can be omitted as a convenience in the second +case. ``@load`` can now also use relative path, e.g., ``@load +../main``. + + +Logging Framework +----------------- + +- The logs generated by scripts that ship with Bro are entirely redone + to use a standardized, machine parsable format via the new logging + framework. Generally, the log content has been restructured towards + making it more directly useful to operations. Also, several + analyzers have been significantly extended and thus now log more + information. Take a look at ``ssl.log``. + + * A particular format change that may be useful to note is that the + ``conn.log`` ``service`` field is derived from DPD instead of + well-known ports (while that was already possible in 1.5, it was + not the default). + + * Also, ``conn.log`` now reports raw number of packets/bytes per + endpoint. + +- The new logging framework makes it possible to extend, customize, + and filter logs very easily. See the :doc:`logging framework ` + for more information on usage. + +- A common pattern found in the new scripts is to store logging stream + records for protocols inside the ``connection`` records so that + state can be collected until enough is seen to log a coherent unit + of information regarding the activity of that connection. This + state is now frequently seen/accessible in event handlers, for + example, like ``c$`` where ```` is replaced by + the name of the protocol. This field is added to the ``connection`` + record by ``redef``'ing it in a + ``base/protocols//main.bro`` script. + +- The logging code has been rewritten internally, with script-level + interface and output backend now clearly separated. While ASCII + logging is still the default, we will add further output types in + the future (binary format, direct database logging). + + +Notice Framework +---------------- + +The way users interact with "notices" has changed significantly in +order to make it easier to define a site policy and more extensible +for adding customized actions. See the :doc:`notice framework `. + + +New Default Settings +-------------------- + +- Dynamic Protocol Detection (DPD) is now enabled/loaded by default. + +- The default packet filter now examines all packets instead of + dynamically building a filter based on which protocol analysis scripts + are loaded. See ``PacketFilter::all_packets`` for how to revert to old + behavior. + +API Changes +----------- + +- The ``@prefixes`` directive works differently now. + Any added prefixes are now searched for and loaded *after* all input + files have been parsed. After all input files are parsed, Bro + searches ``BROPATH`` for prefixed, flattened versions of all of the + parsed input files. For example, if ``lcl`` is in ``@prefixes``, and + ``site.bro`` is loaded, then a file named ``lcl.site.bro`` that's in + ``BROPATH`` would end up being automatically loaded as well. Packages + work similarly, e.g. loading ``protocols/http`` means a file named + ``lcl.protocols.http.bro`` in ``BROPATH`` gets loaded automatically. + +- The ``make_addr`` BIF now returns a ``subnet`` versus an ``addr`` + + +Variable Naming +--------------- + +- ``Module`` is more widely used for namespacing. E.g. the new + ``site.bro`` exports the ``local_nets`` identifier (among other + things) into the ``Site`` module. + +- Identifiers may have been renamed to conform to new `scripting + conventions + `_ + + +BroControl +========== + +BroControl looks pretty much similar to the version coming with Bro 1.x, +but has been cleaned up and streamlined significantly internally. + +BroControl has a new ``process`` command to process a trace on disk +offline using a similar configuration to what BroControl installs for +live analysis. + +BroControl now has an extensive plugin interface for adding new +commands and options. Note that this is still considered experimental. + +We have removed the ``analysis`` command, and BroControl currently +does not send daily alarm summaries anymore (this may be restored +later). + +Removed Functionality +===================== + +We have remove a bunch of functionality that was rarely used and/or +had not been maintained for a while already: + + - The ``net`` script data type. + - The ``alarm`` statement; use the notice framework instead. + - Trace rewriting. + - DFA state expiration in regexp engine. + - Active mapping. + - Native DAG support (may come back eventually) + - ClamAV support. + - The connection compressor is now disabled by default, and will + be removed in the future. + +Development Infrastructure +========================== + +Bro development has moved from using SVN to Git for revision control. +Users that want to use the latest Bro development snapshot by checking it out +from the source repositories should see the `development process +`_. Note that all the various +sub-components now reside in their own repositories. However, the +top-level Bro repository includes them as git submodules so it's easy +to check them all out simultaneously. + +Bro now uses `CMake `_ for its build system so +that is a new required dependency when building from source. + +Bro now comes with a growing suite of regression tests in +``testing/``. diff --git a/pkg/check-cmake b/pkg/check-cmake index 2c3ed765a6..17531af2f7 100755 --- a/pkg/check-cmake +++ b/pkg/check-cmake @@ -5,7 +5,7 @@ # version of CMake is required to obtain consistency, but can be increased # as new versions of CMake come out that also produce working packages. -CMAKE_PACK_REQ="cmake version 2.8.4" +CMAKE_PACK_REQ="cmake version 2.8.6" CMAKE_VER=`cmake -version` if [ "${CMAKE_VER}" != "${CMAKE_PACK_REQ}" ]; then diff --git a/pkg/make-deb-packages b/pkg/make-deb-packages index a9de210e52..432de8336a 100755 --- a/pkg/make-deb-packages +++ b/pkg/make-deb-packages @@ -27,21 +27,21 @@ cd .. # Minimum Bro ./configure --prefix=${prefix} --disable-broccoli --disable-broctl \ - --pkg-name-prefix=Bro --binary-package + --pkg-name-prefix=Bro-minimal --binary-package ( cd build && make package ) # Full Bro package -./configure --prefix=${prefix} --pkg-name-prefix=Bro-all --binary-package +./configure --prefix=${prefix} --pkg-name-prefix=Bro --binary-package ( cd build && make package ) # Broccoli cd aux/broccoli ./configure --prefix=${prefix} --binary-package -( cd build && make package && mv Broccoli*.deb ../../../build/ ) +( cd build && make package && mv *.deb ../../../build/ ) cd ../.. # Broctl cd aux/broctl ./configure --prefix=${prefix} --binary-package -( cd build && make package && mv Broctl*.deb ../../../build/ ) +( cd build && make package && mv *.deb ../../../build/ ) cd ../.. diff --git a/pkg/make-mac-packages b/pkg/make-mac-packages index a8f7f965c8..829a64ca25 100755 --- a/pkg/make-mac-packages +++ b/pkg/make-mac-packages @@ -35,25 +35,25 @@ cd .. # Minimum Bro CMAKE_OSX_ARCHITECTURES=${arch} ./configure --prefix=${prefix} \ - --disable-broccoli --disable-broctl --pkg-name-prefix=Bro \ + --disable-broccoli --disable-broctl --pkg-name-prefix=Bro-minimal \ --binary-package ( cd build && make package ) # Full Bro package CMAKE_OSX_ARCHITECTURES=${arch} ./configure --prefix=${prefix} \ - --pkg-name-prefix=Bro-all --binary-package + --pkg-name-prefix=Bro --binary-package ( cd build && make package ) # Broccoli cd aux/broccoli CMAKE_OSX_ARCHITECTURES=${arch} ./configure --prefix=${prefix} \ --binary-package -( cd build && make package && mv Broccoli*.dmg ../../../build/ ) +( cd build && make package && mv *.dmg ../../../build/ ) cd ../.. # Broctl cd aux/broctl CMAKE_OSX_ARCHITECTURES=${arch} ./configure --prefix=${prefix} \ --binary-package -( cd build && make package && mv Broctl*.dmg ../../../build/ ) +( cd build && make package && mv *.dmg ../../../build/ ) cd ../.. diff --git a/pkg/make-rpm-packages b/pkg/make-rpm-packages index ac8dfa97b4..9560cc80ff 100755 --- a/pkg/make-rpm-packages +++ b/pkg/make-rpm-packages @@ -20,21 +20,21 @@ cd .. # Minimum Bro ./configure --prefix=${prefix} --disable-broccoli --disable-broctl \ - --pkg-name-prefix=Bro --binary-package + --pkg-name-prefix=Bro-minimal --binary-package ( cd build && make package ) # Full Bro package -./configure --prefix=${prefix} --pkg-name-prefix=Bro-all --binary-package +./configure --prefix=${prefix} --pkg-name-prefix=Bro --binary-package ( cd build && make package ) # Broccoli cd aux/broccoli ./configure --prefix=${prefix} --binary-package -( cd build && make package && mv Broccoli*.rpm ../../../build/ ) +( cd build && make package && mv *.rpm ../../../build/ ) cd ../.. # Broctl cd aux/broctl ./configure --prefix=${prefix} --binary-package -( cd build && make package && mv Broctl*.rpm ../../../build/ ) +( cd build && make package && mv *.rpm ../../../build/ ) cd ../.. diff --git a/policy.old/OS-fingerprint.bro b/policy.old/OS-fingerprint.bro deleted file mode 100644 index 8f00fe93fd..0000000000 --- a/policy.old/OS-fingerprint.bro +++ /dev/null @@ -1,18 +0,0 @@ -# $Id: OS-fingerprint.bro 1071 2005-03-08 14:09:31Z vern $ -# -# Tracks operating system versioning using the "software" framework. - -@load software - -event OS_version_found(c: connection, host: addr, OS: OS_version) - { - local version: software_version; - version$major = version$minor = version$minor2 = -1; - version$addl = OS$detail; - - local sw: software; - sw$name = OS$genre; - sw$version = version; - - event software_version_found(c, host, sw, "OS"); - } diff --git a/policy.old/adu.bro b/policy.old/adu.bro deleted file mode 100644 index 3c2168784a..0000000000 --- a/policy.old/adu.bro +++ /dev/null @@ -1,278 +0,0 @@ -# $Id: adu.bro 5152 2007-12-04 21:48:56Z vern $ - -@load conn-id - -module adu; - -# This script parses application-layer data (ADU) units, or "messages", -# out of the packet streams. Since the analysis is generic, we define -# an ADU simply as all application-layer data in a 5-tuple flow going -# in one direction without any data going the other way. Once we see -# data in the other direction, we finish the current ADU and start -# a new one (going the other way). While this approach is only -# approximate, it can work well for both UDP and TCP. -# -# The script reports ADUs as strings, up to a configurable maximum size, and -# up to a configurable depth into the flow. -# -# Generated events: -# -# - adu_tx(c: connection, a: adu_state) reports an ADU seen from -# c's originator to its responder. -# -# - adu_rx(c: connection, a: adu_state) reports an ADU seen from -# c's responder to the originator. -# -# - adu_done(c: connection) indicates that no more ADUs will be seen -# on connection c. This is useful to know in case your statekeeping -# relies on event connection_state_remove(), which is also used by -# adu.bro. -# - -# --- Input configuration -- which ports to look at -------------------- - -# Right now: everything! -# -redef tcp_content_deliver_all_orig = T; -redef tcp_content_deliver_all_resp = T; -redef udp_content_deliver_all_orig = T; -redef udp_content_deliver_all_resp = T; - -# --- Debugging -- should really be a separate policy ------------------ - -# Comment out to disable debugging output: -#global adu_debug = T; - -# Uncomment to enable tests: -#global adu_test = T; - -@ifdef (adu_debug) -function DBG(msg: string) { print fmt("DBG[adu.bro]: %s", msg); } -@else -function DBG(msg: string) { } -@endif - -export { - -# --- Constants -------------------------------------------------------- - - # The maximum depth in bytes up to which we follow a flow. - # This is counting bytes seen in both directions. - const adu_conn_max_depth = 100000 &redef; - - # The maximum message depth that we report. - const adu_max_depth = 3 &redef; - - # The maximum message size in bytes that we report. - const adu_max_size = 1000 &redef; - - # Whether ADUs are reported beyond content gaps. - const adu_gaps_ok = F &redef; - -# --- Types ------------------------------------------------------------ - - # adu_state records contain the latest ADU and aditional flags to help - # the user identify the direction of the message, its depth in the flow, - # etc. - type adu_state: record { - adu: string &default = ""; # the current ADU - - # Message counter (>= 1), orig->resp and resp->orig. - depth_tx: count &default = 1; - depth_rx: count &default = 1; - - # TCP: seqno tracking to recognize gaps. - seen_tx: count &default = 0; - seen_rx: count &default = 0; - - size: count &default = 0; # total connection size in bytes - is_orig: bool &default = F; # whether ADU is orig->resp - ignore: bool &default = F; # ignore future activity on conn - }; - - # Tell the ADU policy that you do not wish to receive further - # adu_tx/adu_rx events for a given connection. Other policies - # may continue to process the connection. - # - global adu_skip_further_processing: function(cid: conn_id); -} - - -# --- Globals ---------------------------------------------------------- - -# A global table that tracks each flow's messages. -global adu_conns: table[conn_id] of adu_state; - -# Testing invokes the following events. -global adu_tx: event(c: connection, astate: adu_state); -global adu_rx: event(c: connection, astate: adu_state); -global adu_done: event(c: connection); - -# --- Functions -------------------------------------------------------- - -function adu_skip_further_processing(cid: conn_id) - { - if ( cid !in adu_conns ) - return; - - adu_conns[cid]$ignore = T; - } - -function flow_contents(c: connection, is_orig: bool, seq: count, contents: string) - { - local astate: adu_state; - - DBG(fmt("contents %s, %s: %s", id_string(c$id), is_orig, contents)); - - # Ensure we track the given connection. - if ( c$id !in adu_conns ) - adu_conns[c$id] = astate; - else - astate = adu_conns[c$id]; - - # Forget it if we've been asked to ignore. - # - if ( astate$ignore == T ) - return; - - # Don't report if flow is too big. - # - if ( astate$size >= adu_conn_max_depth ) - return; - - # If we have an assembled message, we may now have something - # to report. - if ( |astate$adu| > 0 ) - { - # If application-layer data flow is switching - # from resp->orig to orig->resp, report the assembled - # message as a received ADU. - if ( is_orig && ! astate$is_orig ) - { - event adu_rx(c, copy(astate)); - astate$adu = ""; - - if ( ++astate$depth_rx > adu_max_depth ) - adu_skip_further_processing(c$id); - } - - # If application-layer data flow is switching - # from orig->resp to resp->orig, report the assembled - # message as a transmitted ADU. - # - if ( !is_orig && astate$is_orig ) - { - event adu_tx(c, copy(astate)); - astate$adu = ""; - - if ( ++astate$depth_tx > adu_max_depth ) - adu_skip_further_processing(c$id); - } - } - - # Check for content gaps. If we identify one, only continue - # if user allowed it. - # - if ( !adu_gaps_ok && seq > 0 ) - { - if ( is_orig ) - { - if ( seq > astate$seen_tx + 1 ) - return; - else - astate$seen_tx += |contents|; - } - else - { - if ( seq > astate$seen_rx + 1 ) - return; - else - astate$seen_rx += |contents|; - } - } - - # Append the contents to the end of the currently - # assembled message, if the message hasn't already - # reached the maximum size. - # - if ( |astate$adu| < adu_max_size ) - { - astate$adu += contents; - - # As a precaution, clip the string to the maximum - # size. A long content string with astate$adu just - # below its maximum allowed size could exceed that - # limit by a lot. - ### str_clip(astate$adu, adu_max_size); - } - - - # Note that this counter is bumped up even if we have - # exceeded the maximum size of an individual message. - # - astate$size += |contents|; - - astate$is_orig = is_orig; - } - -# --- Event Handlers --------------------------------------------------- - -event tcp_contents(c: connection, is_orig: bool, seq: count, contents: string) - { - flow_contents(c, is_orig, seq, contents); - } - -event udp_contents(u: connection, is_orig: bool, contents: string) - { - flow_contents(u, is_orig, 0, contents); - } - -event connection_state_remove(c: connection) - { - if ( c$id !in adu_conns ) - return; - - local astate = adu_conns[c$id]; - - # Forget it if we've been asked to ignore. - # - if ( astate$ignore == T ) - return; - - # Report the remaining data now, if any. - # - if ( |astate$adu| > 0 ) { - if ( astate$is_orig ) - { - if ( astate$depth_tx <= adu_max_depth ) - event adu_tx(c, copy(astate)); - } - else - { - if ( astate$depth_rx <= adu_max_depth ) - event adu_rx(c, copy(astate)); - } - } - - delete adu_conns[c$id]; - event adu_done(c); -} - - -# --- Tests ------------------------------------------------------------ - -@ifdef (adu_test) - -event adu_tx(c: connection, astate: adu_state) - { - print fmt("%s ---- %s, %d -> ----", network_time(), id_string(c$id), astate$depth_tx); -# print astate$adu; - } - -event adu_rx(c: connection, astate: adu_state) - { - print fmt("%s ---- %s, %d <- ----", network_time(), id_string(c$id), astate$depth_rx); -# print astate$adu; - } - -@endif diff --git a/policy.old/alarm.bro b/policy.old/alarm.bro deleted file mode 100644 index 4c4943c948..0000000000 --- a/policy.old/alarm.bro +++ /dev/null @@ -1,3 +0,0 @@ -# $Id: alarm.bro 340 2004-09-09 06:38:27Z vern $ - -redef bro_alarm_file = open_log_file("alarm"); diff --git a/policy.old/all.bro b/policy.old/all.bro deleted file mode 100644 index 4bbe3e8afe..0000000000 --- a/policy.old/all.bro +++ /dev/null @@ -1,141 +0,0 @@ -@load heavy-analysis -@load OS-fingerprint -@load adu -@load alarm -@load analy -@load anon -@load arp -@load backdoor -@load bittorrent -@load blaster -@load bt-tracker -@load brolite-backdoor -@load capture-events -@load capture-loss -@load capture-state-updates -@load checkpoint -@load clear-passwords -@load conn-flood -@load conn-id -@load conn -@load contents -@load cpu-adapt -@load dce -@load demux -@load detect-protocols-http -@load detect-protocols -@load dhcp -@load dns-info -@load dns-lookup -@load dns -@load dpd -@load drop-adapt -@load dyn-disable -@load file-flush -@load finger -@load firewall -@load flag-irc -@load flag-warez -@load frag -@load ftp -@load gnutella -@load hot-ids -@load hot -@load http-abstract -@load http-anon-server -@load http-anon-useragent -@load http-anon-utils -@load http-body -@load http-detect-passwd -@load http-entity -@load http-event -@load http-header -@load http-identified-files.bro -@load http-reply -@load http-request -@load http-rewriter -@load http -@load icmp -@load ident-rewriter -@load ident -@load inactivity -@load interconn -@load irc-bot-syslog -@load irc-bot -@load irc -@load large-conns -@load listen-clear -@load listen-ssl -@load load-level -@load load-sample -@load log-append -@load login -@load mime-pop -@load mime -@load mt -@load ncp -@load netflow -@load netstats -@load nfs -@load notice-action-filters -@load notice -@load ntp -@load passwords -@load pcap -@load pkt-profile -@load pop3 -@load port-name -@load portmapper -@load print-filter -@load print-globals -@load print-resources -@load print-sig-states -@load profiling -@load proxy -@load remote-pcap -@load remote-ping -@load remote-print-id-reply -@load remote-print-id -@load remote-print -@load remote-report-notices -@load remote-send-id -@load remote -@load rotate-logs -@load rsh -@load scan -@load secondary-filter -@load sensor-sshd -@load server-ports -@load service-probe -@load signatures -@load site -@load smb -@load smtp-relay -@load smtp-rewriter -@load smtp -@load snort -@load software -@load ssh -@load ssh-stepping -@load ssl-alerts -@load ssl-ciphers -@load ssl-errors -@load ssl-worm -@load ssl -@load stats -@load stepping -@load synflood -@load targeted-scan -@load tcp -@load tftp -@load trw-impl -@load trw -@load udp-common -@load udp -@load vlan -@load weird -@load worm -@load notice-policy - -# The following keeps us running after the bro_init event. -redef PrintFilter::terminate_bro = F; diff --git a/policy.old/analy.bro b/policy.old/analy.bro deleted file mode 100644 index 714c1deb41..0000000000 --- a/policy.old/analy.bro +++ /dev/null @@ -1,16 +0,0 @@ -# Statistical analysis of TCP connection in terms of the packet streams -# in each direction. - -@load dns-lookup -@load udp - - -event conn_stats(c: connection, os: endpoint_stats, rs: endpoint_stats) - { - local id = c$id; - - print fmt("%.6f %s %s %s %s %s %s %s %s %s", - c$start_time, c$duration, id$orig_p, id$resp_p, - conn_size(c$orig, tcp), conn_size(c$resp, tcp), - id$orig_h, id$resp_h, os, rs); - } diff --git a/policy.old/anon.bro b/policy.old/anon.bro deleted file mode 100644 index f2532cb38e..0000000000 --- a/policy.old/anon.bro +++ /dev/null @@ -1,193 +0,0 @@ -# $Id: anon.bro 6889 2009-08-21 16:45:17Z vern $ - -redef anonymize_ip_addr = T; - -const orig_addr_anonymization = RANDOM_MD5 &redef; -const resp_addr_anonymization = RANDOM_MD5 &redef; -const other_addr_anonymization = SEQUENTIALLY_NUMBERED &redef; - -const preserve_orig_addr: set[addr] = {} &redef; -const preserve_resp_addr: set[addr] = {} &redef; -const preserve_other_addr: set[addr] = { - 0.0.0.0, -} &redef; - -const preserved_subnet: set[subnet] = { -# 192.150.186/23, -} &redef; - -const preserved_net: set[net] = { -# 192.150.186, 192.150.187, -} &redef; - -global anon_log = open_log_file("anon") &redef; - -global anonymized_args: table[string] of string; - -global ip_anon_mapping: set[addr, addr]; - -event bro_init() - { - for ( n in preserved_net ) - preserve_net(n); - } - -function anonymize_address(a: addr, id: conn_id): addr - { - if ( a == id$orig_h ) - return anonymize_addr(a, ORIG_ADDR); - else if ( a == id$resp_h ) - return anonymize_addr(a, RESP_ADDR); - else - return anonymize_addr(a, OTHER_ADDR); - } - -event anonymization_mapping(orig: addr, mapped: addr) - { - if ( [orig, mapped] !in ip_anon_mapping ) - { - add ip_anon_mapping[orig, mapped]; - print anon_log, fmt("%s -> %s", orig, mapped); - } - } - -function string_anonymized(from: string, to: string, seed: count) - { - print anon_log, fmt("\"%s\" %d=> \"%s\"", from, seed, to); - } - -global num_string_id: count = 0 &redef; -global anonymized_strings: table[string] of record { - s: string; - c: count; -} &redef; - -# Hopefully, the total number of strings to anonymize is much less than -# 36^unique_string_length. -const unique_string_length = 8 &redef; -# const anonymized_string_pattern = /U[0-9a-f]+U/; -global unique_string_set: set[string]; - -event bro_init() - { - for ( s in anonymized_strings ) - add unique_string_set[anonymized_strings[s]$s]; - } - -function unique_string(s: string, seed: count): string - { - local t = cat("U", sub_bytes(md5_hmac(seed, s), - 1, unique_string_length), "U"); - if ( t in unique_string_set ) - return unique_string(s, seed+1); - - anonymized_strings[s] = [$s = t, $c = 1]; - add unique_string_set[t]; - string_anonymized(s, t, seed); - - return t; - } - -function anonymize_string(from: string): string - { - if ( from in anonymized_strings ) - { - ++anonymized_strings[from]$c; - return anonymized_strings[from]$s; - } - - local t = unique_string(from, 0); - return t; - } - -function anonymize_arg(typ: string, arg: string): string - { - if ( arg == "" ) - return ""; # an empty argument is safe - - local arg_seed = string_cat(typ, arg); - - if ( arg_seed in anonymized_args ) - return anonymized_args[arg_seed]; - - local a = anonymize_string(arg_seed); - anonymized_args[arg_seed] = a; - - print anon_log, fmt("anonymize_arg: (%s) {%s} -> %s ", - typ, to_string_literal(arg), to_string_literal(a)); - return a; - } - - -# Does not contain ? and ends with an allowed suffix. -const path_to_file_pat = - /\/[^?]+\.(html|ico|icon|pdf|ps|doc|ppt|htm|js|crl|swf|shtml|h|old|c|cc|java|class|src|cfm|gif|jpg|php|rdf|rss|asp|bmp|owl|phtml|jpeg|jsp|cgi|png|txt|xml|css|avi|tex|dvi)/ - ; - -# Acceptable domain names. -const kosher_dom_pat = - /ar|au|biz|br|ca|cc|cl|cn|co|com|cx|cz|de|ec|es|edu|fi|fm|fr|gov|hn|il|is|it|jp|lv|mx|net|no|nz|org|pe|pl|ru|sk|tv|tw|uk|us|arpa/ - ; - -# Simple filename pattern. -const simple_filename = - /[0-9\-A-Za-z]+\.(html|ico|icon|pdf|ps|doc|ppt|htm|js|crl|swf|shtml|h|old|c|cc|java|class|src|cfm|gif|jpg|php|rdf|rss|asp|bmp|owl|phtml|jpeg|jsp|cgi|png|txt|xml|css|avi|tex|dvi)/ - ; - -function anonymize_path(path: string): string - { - local hashed_path = ""; - - if ( to_lower(path) != path_to_file_pat ) - { - hashed_path = anonymize_arg("path", path); - return hashed_path; - } - - local file_parts = split(path, /\./); - - local i = 1; - for ( part in file_parts ) - { - # This looks broken to me - VP. - hashed_path = fmt("%s.%s", hashed_path, file_parts[i]); - if ( ++i == length(file_parts) ) - break; - } - - return fmt("%s.%s", anonymize_arg("path", hashed_path), file_parts[i]); - } - -function anonymize_host(host: string): string - { - local hashed_host = ""; - local host_parts = split(host, /\./); - - local i = 1; - for ( hosty in host_parts ) - { - if ( i == length(host_parts) ) - break; - - # Check against "kosher" tld list. - hashed_host = fmt("%s%s.", hashed_host, - anonymize_arg("host", host_parts[i])); - - ++i; - } - - if ( host_parts[i] == kosher_dom_pat ) - return string_cat(hashed_host, host_parts[i]); - - print anon_log, fmt("anonymize_host: non-kosher domain %s", host); - return string_cat(hashed_host, anonymize_arg("host", host_parts[i])); - } - -event bro_done() - { - for ( s in anonymized_strings ) - { - print anon_log, fmt("appearance: %d: \"%s\" => \"%s\"", - anonymized_strings[s]$c, s, anonymized_strings[s]$s); - } - } diff --git a/policy.old/arp.bro b/policy.old/arp.bro deleted file mode 100644 index dfae133b38..0000000000 --- a/policy.old/arp.bro +++ /dev/null @@ -1,160 +0,0 @@ -# $Id: arp.bro 4909 2007-09-24 02:26:36Z vern $ - -@load notice - -module ARP; - -export { - redef enum Notice += { - ARPSourceMAC_Mismatch, # source MAC doesn't match mappings - ARPAddlMAC_Mapping, # another MAC->addr seen beyond just one - ARPUnsolicitedReply, # could be poisoning; or just gratuitous - # ARPRequestProvidesTargetAddr, # request includes non-triv addr - - # MAC/addr pair seen in request/reply different from - # that in the cache. - ARPCacheInconsistency, - - # ARP reply gives different value than previously seen. - ARPMappingChanged, - }; - - const arp_log = open_log_file("arp") &redef; -} - -redef capture_filters += { ["arp"] = "arp" }; - -# Abbreviations taken from RFC 826: -# -# SHA: source hardware address -# SPA: source protocol address (i.e., IP address) -# THA: target hardware address -# TPA: target protocol address - -# ARP requests indexed on SHA/SPA/TPA (no THA, as it's what it's being -# queried). -global arp_requests: set[string, addr, addr] &create_expire = 1 min; - -# ARP responses we've seen: indexed by IP address, yielding MAC address. -global ARP_cache: table[addr] of string; - - -# Bad ARPs can occur when: -# - type/size pairs are not OK for HW and L3 addresses (Ethernet=6, IP=4) -# - opcode is neither request (1) nor reply (2) -# - MAC src address != ARP sender MAC address -event bad_arp(SPA: addr, SHA: string, TPA: addr, THA: string, - explanation: string) - { - print arp_log, fmt("%.06f bad-arp %s(%s) ? %s(%s): %s", - network_time(), SPA, SHA, TPA, THA, explanation); - } - - -# The first of these maps a MAC address to the last protocol address seen -# for it. The second tracks every protocol address seen. -global mac_addr_map: table[string] of addr; -global mac_addr_associations: table[string] of set[addr]; - -# A somewhat general notion of broadcast MAC/IP addresses. -const broadcast_mac_addrs = { "00:00:00:00:00:00", "ff:ff:ff:ff:ff:ff", }; -const broadcast_addrs = { 0.0.0.0, 255.255.255.255, }; - - -# Called to note that we've seen an association between a MAC address -# and an IP address. Note that this is *not* an association advertised -# in an ARP reply (those are tracked in ARP_cache), but instead the -# pairing of hardware address + protocol address as expressed in -# an ARP request or reply header. -function mac_addr_association(mac_addr: string, a: addr) - { - # Ignore placeholders. - if ( mac_addr in broadcast_mac_addrs || a in broadcast_addrs ) - return; - - local is_addl = F; - if ( mac_addr in mac_addr_associations ) - is_addl = a !in mac_addr_associations[mac_addr]; - else - mac_addr_associations[mac_addr] = set(); - - print arp_log, fmt("%.06f association %s -> %s%s", network_time(), - mac_addr, a, is_addl ? " " : ""); - - mac_addr_map[mac_addr] = a; - add mac_addr_associations[mac_addr][a]; - - if ( a in ARP_cache && ARP_cache[a] != mac_addr ) - NOTICE([$note=ARPCacheInconsistency, $src=a, - $msg=fmt("mapping for %s to %s doesn't match cache of %s", - mac_addr, a, ARP_cache[a])]); - } - -# Returns the IP address associated with a MAC address, if we've seen one. -# Otherwise just returns the MAC address. -function addr_from_mac(mac_addr: string): string - { - return mac_addr in mac_addr_map ? - fmt("%s", mac_addr_map[mac_addr]) : mac_addr; - } - -event arp_request(mac_src: string, mac_dst: string, SPA: addr, SHA: string, - TPA: addr, THA: string) - { - mac_addr_association(SHA, SPA); - - local msg = fmt("%s -> %s who-has %s", - addr_from_mac(mac_src), addr_from_mac(mac_dst), TPA); - - local mismatch = SHA != mac_src; - if ( mismatch ) - NOTICE([$note=ARPSourceMAC_Mismatch, $src=SPA, $msg=msg]); - - # It turns out that some hosts fill in the THA field even though - # that doesn't make sense. (The RFC specifically allows this, - # however.) Perhaps there's an attack that can be launched - # doing so, but it's hard to see what it might be, so for now - # we don't bother notice'ing these. - # if ( THA !in broadcast_addrs ) - # NOTICE([$note=ARPRequestProvidesTargetAddr, $src=SPA, - # $msg=fmt("%s: %s", msg, THA)]); - - print arp_log, fmt("%.06f %s%s", network_time(), msg, - mismatch ? " " : ""); - - add arp_requests[SHA, SPA, TPA]; - } - -event arp_reply(mac_src: string, mac_dst: string, SPA: addr, SHA: string, - TPA: addr, THA: string) - { - mac_addr_association(SHA, SPA); - mac_addr_association(THA, TPA); - - local msg = fmt("%s -> %s: %s is-at %s", - addr_from_mac(mac_src), addr_from_mac(mac_dst), - SPA, SHA); - - local unsolicited = [THA, TPA, SPA] !in arp_requests; - delete arp_requests[THA, TPA, SPA]; - if ( unsolicited ) - NOTICE([$note=ARPUnsolicitedReply, $src=SPA, - $msg=fmt("%s: request[%s, %s, %s]", msg, THA, TPA, SPA)]); - - local mismatch = SHA != mac_src; - if ( mismatch ) - NOTICE([$note=ARPSourceMAC_Mismatch, $src=SPA, $msg=msg]); - - local mapping_changed = SPA in ARP_cache && ARP_cache[SPA] != SHA; - if ( mapping_changed ) - NOTICE([$note=ARPMappingChanged, $src=SPA, - $msg=fmt("%s: was %s", msg, ARP_cache[SPA])]); - - print arp_log, fmt("%.06f %s%s%s%s", network_time(), msg, - unsolicited ? " " : "", - mismatch ? " " : "", - mapping_changed ? - fmt(" ", ARP_cache[SPA]) : ""); - - ARP_cache[SPA] = SHA; - } diff --git a/policy.old/backdoor.bro b/policy.old/backdoor.bro deleted file mode 100644 index f611d424fa..0000000000 --- a/policy.old/backdoor.bro +++ /dev/null @@ -1,559 +0,0 @@ -# $Id: backdoor.bro 4909 2007-09-24 02:26:36Z vern $ - -# Looks for a variety of applications running on ports other than -# their usual ports. -# -# Note that this script by itself does *not* change capture_filters -# to add in the extra ports to look at. You need to specify that -# separately. - - -# Some tcpdump filters can be used to replace or work together with -# some detection algorithms. They could be used with the "secondary -# filter" for more efficient (but in some cases potentially less reliable) -# matching: -# -# - looking for "SSH-1." or "SSH-2." at the beginning of the packet; -# somewhat weaker than ssh-sig in that ssh-sig only looks for such -# pattern in the first packet of a connection: -# -# tcp[(tcp[12]>>2):4] = 0x5353482D and -# (tcp[((tcp[12]>>2)+4):2] = 0x312e or tcp[((tcp[12]>>2)+4):2] = 0x322e) -# -# - looking for pkts with 8k+4 (<=128) bytes of data (combined with ssh-len); -# only effective for ssh 1.x: -# -# (ip[2:2] - ((ip[0]&0x0f)<<2) - (tcp[12]>>2)) & 0xFF87 = 4 -# -# - looking for packets with <= 512 bytes of data that ends with a NUL -# (can be potentially combined with rlogin-sig or rlogin-sig-1byte): -# -# (tcp[(ip[2:2] - ((ip[0]&0x0f)<<2))-1] == 0) and -# ((ip[2:2] - ((ip[0]&0x0f)<<2) - (tcp[12]>>2)) != 0) and -# ((ip[2:2] - ((ip[0]&0x0f)<<2) - (tcp[12]>>2)) <= 512) -# -# - looking for telnet negotiation (can be combined with telnet-sig(-3byte)): -# -# (tcp[(tcp[12]>>2):2] > 0xfffa) and -# (tcp[(tcp[12]>>2):2] < 0xffff) and -# ((ip[2:2] - ((ip[0]&0x0f)<<2) - (tcp[12] >> 2)) >= 3) -# -# - looking for packets with <= 20 bytes of data (combined with small-pkt): -# -# (ip[2:2] - ((ip[0]&0x0f)<<2) - (tcp[12]>>2)) <= 20 -# -# - looking for FTP servers by the initial "220-" or "220 " sent by the server: -# -# tcp[(tcp[12]>>2):4] = 0x3232302d or tcp[(tcp[12]>>2):4] = 0x32323020 -# -# - looking for root backdoors by seeing a server payload of exactly "# ": -# -# tcp[(tcp[12]>>2):2] = 0x2320 and -# (ip[2:2] - ((ip[0]&0x0f)<<2) - (tcp[12]>>2)) == 2 -# -# - looking for Napster by the initial "GET" or "SEND" sent by the originator: -# -# ((ip[2:2]-((ip[0]&0x0f)<<2)-(tcp[12]>>2))=4 and -# tcp[(tcp[12]>>2):4]=0x53454e44) or -# ((ip[2:2]-((ip[0]&0x0f)<<2)-(tcp[12]>>2))=3 and -# tcp[(tcp[12]>>2):2]=0x4745 and tcp[(tcp[12]>>2)+2]=0x54) -# -# - looking for Gnutella handshaking "GNUTELLA " -# -# tcp[(tcp[12]>>2):4] = 0x474e5554 and -# tcp[(4+(tcp[12]>>2)):4] = 0x454c4c41 and -# tcp[8+(tcp[12]>>2)] = 0x20 -# -# - looking for KaZaA via "GIVE " (not present in all connections) -# -# tcp[(tcp[12]>>2):4] = 0x47495645 and -# tcp[(4+(tcp[12]>>2)):1] = 0x20 -# - -@load site -@load port-name -@load demux -@load notice - -redef enum Notice += { BackdoorFound, }; - -# Set to dump the packets that trigger the backdoor detector to a file. -const dump_backdoor_packets = F &redef; - -redef backdoor_stat_period = 60 sec; -redef backdoor_stat_backoff = 2.0; - -const ssh_min_num_pkts = 8 &redef; -const ssh_min_ssh_pkts_ratio = 0.6 &redef; - -const backdoor_min_num_lines = 2 &redef; -const backdoor_min_normal_line_ratio = 0.5 &redef; - -const backdoor_min_bytes = 10 &redef; -const backdoor_min_7bit_ascii_ratio = 0.75 &redef; - -type rlogin_conn_info : record { - o_num_null: count; - o_len: count; - r_num_null: count; - r_len: count; -}; - -const backdoor_demux_disabled = T &redef; -const backdoor_demux_skip_tags: set[string] &redef; - -const ftp_backdoor_sigs = "ftp-sig"; -const ssh_backdoor_sigs = { "ssh-sig", "ssh-len-v1.x", "ssh-len-v2.x" }; -const rlogin_backdoor_sigs = { "rlogin-sig", "rlogin-sig-1byte" }; -const root_backdoor_sigs = "root-bd-sig"; -const telnet_backdoor_sigs = { "telnet-sig", "telnet-sig-3byte" }; -const napster_backdoor_sigs = "napster-sig"; -const gnutella_backdoor_sigs = "gnutella-sig"; -const kazaa_backdoor_sigs = "kazaa-sig"; -const http_backdoor_sigs = "http-sig"; -const http_proxy_backdoor_sigs = "http-proxy-sig"; -const smtp_backdoor_sigs = "smtp-sig"; -const irc_backdoor_sigs = "irc-sig"; -const gaobot_backdoor_sigs = "gaobot-sig"; - -# List of backdoors, so you can use it when defining sets and tables -# with values over all of them. -const backdoor_sigs = { - ftp_backdoor_sigs, ssh_backdoor_sigs, rlogin_backdoor_sigs, - root_backdoor_sigs, telnet_backdoor_sigs, - napster_backdoor_sigs, gnutella_backdoor_sigs, kazaa_backdoor_sigs, - http_backdoor_sigs, http_proxy_backdoor_sigs, - smtp_backdoor_sigs, irc_backdoor_sigs, gaobot_backdoor_sigs, -}; - -# List of address-port pairs that if present in a backdoor are ignored. -# Note that these can be either the client and its source port (unusual) -# or the server and its service port (the common case). -const backdoor_ignore_host_port_pairs: set[addr, port] &redef; - -const backdoor_ignore_ports: table[string, port] of bool = { - # The following ignore backdoors that are detected on their - # usual ports. The definitions for ftp-sig, telnet-sig and - # telnet-sig-3byte are somehwat broad since those backdoors - # are also frequently triggered for other similar protocols. - - [ftp_backdoor_sigs, [ftp, smtp, 587/tcp ]] = T, - [ssh_backdoor_sigs, ssh] = T, - [rlogin_backdoor_sigs , [512/tcp, rlogin, 514/tcp]] = T, - [root_backdoor_sigs, [telnet, 512/tcp, rlogin, 514/tcp]] = T, - [telnet_backdoor_sigs, [telnet, ftp, smtp, 143/tcp, 110/tcp]] = T, - - # The following don't have well-known ports (well, Napster does - # somewhat, as shown below), hence the definitions are F rather - # than T. - [napster_backdoor_sigs, [6688/tcp, 6699/tcp]] = F, - [gnutella_backdoor_sigs, 6346/tcp] = F, - - [kazaa_backdoor_sigs, 1214/tcp] = F, - - [http_backdoor_sigs, [http, 8000/tcp, 8080/tcp]] = T, - - [smtp_backdoor_sigs, [smtp, 587/tcp]] = T, - - # Skip FTP, as "USER foo" generates false positives. There's - # also a lot of IRC on 7000/tcp. - [irc_backdoor_sigs, [ftp, 6666/tcp, 6667/tcp, 7000/tcp]] = T, - - # The following are examples of wildcards, and since they're defined - # to be F, they don't affect the policy unless redefined. - ["*", http] = F, # entry for "any backdoor, service http" - ["ssh-sig", 0/tcp] = F, # entry for "ssh-sig, any port" - -} &redef &default = F; - -# Indexed by the backdoor, indicates which backdoors residing on -# a local (remote) host should be ignored. -const backdoor_ignore_local: set[string] &redef; -const backdoor_ignore_remote: set[string] &redef; - -# Indexed by the source (destination) address and the backdoor. -# Also indexed by the /24 and /16 versions of the source address. -# backdoor "*" means "all backdoors". -const backdoor_ignore_src_addrs: table[string, addr] of bool &redef &default=F; -const backdoor_ignore_dst_addrs: table[string, addr] of bool &redef &default=F; - -const backdoor_standard_ports = { - telnet, rlogin, 512/tcp, 514/tcp, ftp, ssh, smtp, 143/tcp, - 110/tcp, 6667/tcp, -} &redef; -const backdoor_annotate_standard_ports = T &redef; - -const backdoor_ignore_hosts: set[addr] &redef; -const backdoor_ignore_src_nets: set[subnet] &redef; -const backdoor_ignore_dst_nets: set[subnet] &redef; - -# Most backdoors are enabled by default, but a few are disabled by -# default (T below) because they generated too many false positives -# (or, for HTTP, too many uninteresting true positives). -const ftp_sig_disabled = F &redef; -const gaobot_sig_disabled = F &redef; -const gnutella_sig_disabled = F &redef; -const http_proxy_sig_disabled = T &redef; -const http_sig_disabled = T &redef; -const irc_sig_disabled = F &redef; -const kazaa_sig_disabled = F &redef; -const napster_sig_disabled = F &redef; -const rlogin_sig_1byte_disabled = T &redef; -const rlogin_sig_disabled = T &redef; -const root_backdoor_sig_disabled = T &redef; -const smtp_sig_disabled = F &redef; - # Note, for the following there's a corresponding variable - # interconn_ssh_len_disabled in interconn.bro. -const ssh_len_disabled = T &redef; -const ssh_sig_disabled = F &redef; -const telnet_sig_3byte_disabled = T &redef; -const telnet_sig_disabled = T &redef; - -global ssh_len_conns: set[conn_id]; -global rlogin_conns: table[conn_id] of rlogin_conn_info; -global root_backdoor_sig_conns: set[conn_id]; - -global did_sig_conns: table[conn_id] of set[string]; - -const BACKDOOR_UNKNOWN = 0; -const BACKDOOR_YES = 1; -const BACKDOOR_NO = 2; -const BACKDOOR_SIG_FOUND = 3; - -global telnet_sig_conns: table[conn_id] of count; -global telnet_sig_3byte_conns: table[conn_id] of count; - -global smtp_sig_conns: table[conn_id] of count; -global irc_sig_conns: table[conn_id] of count; -global gaobot_sig_conns: table[conn_id] of count; - -const backdoor_log = open_log_file("backdoor") &redef; - -function ignore_backdoor_conn(c: connection, bd: string): bool - { - local oa = c$id$orig_h; - local ra = c$id$resp_h; - local op = c$id$orig_p; - local rp = c$id$resp_p; - - if ( backdoor_ignore_ports[bd, op] || - backdoor_ignore_ports[bd, rp] || - - # Check port wildcards. - backdoor_ignore_ports[bd, 0/tcp] || - - (ra in local_nets && bd in backdoor_ignore_local) || - (ra !in local_nets && bd in backdoor_ignore_remote) || - - backdoor_ignore_src_addrs[bd, oa] || - backdoor_ignore_src_addrs[bd, mask_addr(oa, 16)] || - backdoor_ignore_src_addrs[bd, mask_addr(oa, 24)] || - - backdoor_ignore_dst_addrs[bd, ra] || - backdoor_ignore_dst_addrs[bd, mask_addr(ra, 16)] || - backdoor_ignore_dst_addrs[bd, mask_addr(ra, 24)] ) - return T; - - if ( [oa, op] in backdoor_ignore_host_port_pairs || - [ra, rp] in backdoor_ignore_host_port_pairs ) - return T; - - if ( bd != "*" ) - # Evaluate again, but for wildcarding the backdoor. - return ignore_backdoor_conn(c, "*"); - else - return F; - } - -function log_backdoor(c: connection, tag: string): bool - { - if ( ignore_backdoor_conn(c, tag) ) - return F; - - local id = c$id; - - if ( backdoor_annotate_standard_ports && - (id$orig_p in backdoor_standard_ports || - id$resp_p in backdoor_standard_ports) ) - append_addl(c, fmt("[%s]", tag)); - - else if ( id$orig_h in backdoor_ignore_hosts || - id$resp_h in backdoor_ignore_hosts || - id$orig_h in backdoor_ignore_src_nets || - id$resp_h in backdoor_ignore_dst_nets ) - return F; - - else - { - print backdoor_log, fmt("%.6f %s > %s %s", - c$start_time, - endpoint_id(id$orig_h, id$orig_p), - endpoint_id(id$resp_h, id$resp_p), - tag); - - NOTICE([$note=BackdoorFound, $msg=tag, $conn=c]); - - if ( dump_backdoor_packets ) - { - mkdir("backdoor-packets"); - local fname = fmt("backdoor-packets/%s:%.2f", - tag, current_time()); - dump_current_packet(fname); - } - - if ( backdoor_demux_disabled || - tag in backdoor_demux_skip_tags ) - { - if ( active_connection(c$id) ) - skip_further_processing(c$id); - } - else - demux_conn(id, tag, "orig", "resp"); - } - - return T; - } - -event new_connection(c: connection) - { - local id = c$id; - - if ( ! rlogin_sig_disabled || ! rlogin_sig_1byte_disabled ) - { - local i: rlogin_conn_info; - i$o_num_null = i$o_len = i$r_num_null = i$r_len = 0; - - rlogin_conns[id] = i; - } - } - -event backdoor_remove_conn(c: connection) - { - local id = c$id; - - delete ssh_len_conns[id]; - delete telnet_sig_conns[id]; - delete telnet_sig_3byte_conns[id]; - delete rlogin_conns[id]; - delete root_backdoor_sig_conns[id]; - delete smtp_sig_conns[id]; - delete irc_sig_conns[id]; - delete gaobot_sig_conns[id]; - - delete did_sig_conns[id]; - } - -event root_backdoor_signature_found(c: connection) - { - if ( root_backdoor_sig_disabled || - ignore_backdoor_conn(c, "root-bd-sig") ) - return; - - local id = c$id; - - # For root backdoors, don't ignore standard ports. This is because - # we shouldn't see such a backdoor even 23/tcp or 513/tcp! - - if ( id !in root_backdoor_sig_conns ) - { - add root_backdoor_sig_conns[id]; - log_backdoor(c, "root-bd-sig"); - } - } - -function signature_found(c: connection, sig_disabled: bool, sig_name: string) - { - if ( sig_disabled ) - return; - - if ( ignore_backdoor_conn(c, sig_name) ) - return; - - if ( c$id !in did_sig_conns ) - did_sig_conns[c$id] = set(); - - if ( sig_name !in did_sig_conns[c$id] ) - { - add did_sig_conns[c$id][sig_name]; - log_backdoor(c, sig_name); - } - } - -event ftp_signature_found(c: connection) - { - signature_found(c, ftp_sig_disabled, "ftp-sig"); - } - -event napster_signature_found(c: connection) - { - signature_found(c, napster_sig_disabled, "napster-sig"); - } - -event gnutella_signature_found(c: connection) - { - signature_found(c, gnutella_sig_disabled, "gnutella-sig"); - } - -event kazaa_signature_found(c: connection) - { - signature_found(c, kazaa_sig_disabled, "kazaa-sig"); - } - -event http_signature_found(c: connection) - { - signature_found(c, http_sig_disabled, "http-sig"); - } - -event http_proxy_signature_found(c: connection) - { - signature_found(c, http_proxy_sig_disabled, "http-proxy-sig"); - } - -event ssh_signature_found(c: connection, is_orig: bool) - { - signature_found(c, ssh_sig_disabled, "ssh-sig"); - } - -event smtp_signature_found(c: connection) - { - signature_found(c, smtp_sig_disabled, "smtp-sig"); - } - -event irc_signature_found(c: connection) - { - signature_found(c, irc_sig_disabled, "irc-sig"); - } - -event gaobot_signature_found(c: connection) - { - signature_found(c, gaobot_sig_disabled, "gaobot-sig"); - } - -event telnet_signature_found(c: connection, is_orig: bool, len: count) - { - local id = c$id; - - if ( ignore_backdoor_conn(c, "telnet-sig") ) - return; - - if ( ! telnet_sig_disabled && id !in telnet_sig_conns ) - telnet_sig_conns[id] = BACKDOOR_SIG_FOUND; - - if ( ! telnet_sig_3byte_disabled && len == 3 && - id !in telnet_sig_3byte_conns ) - telnet_sig_3byte_conns[id] = BACKDOOR_SIG_FOUND; - } - -event rlogin_signature_found(c: connection, is_orig: bool, - num_null: count, len: count) - { - local id = c$id; - - if ( (rlogin_sig_disabled && rlogin_sig_1byte_disabled) || - ignore_backdoor_conn(c, "rlogin-sig") ) - return; - - local ri = rlogin_conns[id]; - if ( is_orig && ri$o_num_null == 0 ) - ri$o_num_null = num_null; - - else if ( ! is_orig && ri$r_num_null == 0 ) - { - ri$r_num_null = num_null; - ri$r_len = len; - } - else - return; - - if ( ri$o_num_null == 0 || ri$r_num_null == 0 ) - return; - - if ( ! rlogin_sig_1byte_disabled && ri$r_len == 1 ) - log_backdoor(c, "rlogin-sig-1byte"); - - if ( ! rlogin_sig_disabled ) - log_backdoor(c, "rlogin-sig"); - } - - -function ssh_len_stats(c: connection, os: backdoor_endp_stats, - rs: backdoor_endp_stats) : bool - { - if ( ssh_len_disabled || c$id in ssh_len_conns ) - return F; - - if ( os$num_pkts == 0 || rs$num_pkts == 0 ) - return F; - - # xxx: only use ssh-len for partial connection - - local is_partial = os$is_partial || rs$is_partial; - if ( ! is_partial ) - return F; - - local num_pkts = os$num_pkts + rs$num_pkts; - - if ( num_pkts < ssh_min_num_pkts ) - return F; - - local num_8k0_pkts = os$num_8k0_pkts + rs$num_8k0_pkts; - local num_8k4_pkts = os$num_8k4_pkts + rs$num_8k4_pkts; - - local id = c$id; - if ( num_8k0_pkts >= num_pkts * ssh_min_ssh_pkts_ratio ) - { - add ssh_len_conns[id]; - log_backdoor(c, "ssh-len-v2.x"); - } - - else if ( num_8k4_pkts >= num_pkts * ssh_min_ssh_pkts_ratio ) - { - add ssh_len_conns[id]; - log_backdoor(c, "ssh-len-v1.x"); - } - - return T; - } - -function telnet_stats(c: connection, os: backdoor_endp_stats, - rs: backdoor_endp_stats) : bool - { - local num_lines = os$num_lines + rs$num_lines; - local num_normal_lines = os$num_normal_lines + rs$num_normal_lines; - - if ( num_lines < backdoor_min_num_lines || - num_normal_lines < num_lines * backdoor_min_normal_line_ratio ) - return F; - - local num_bytes = os$num_bytes + rs$num_bytes; - local num_7bit_ascii = os$num_7bit_ascii + rs$num_7bit_ascii; - - if ( num_bytes < backdoor_min_bytes || - num_7bit_ascii < num_bytes * backdoor_min_7bit_ascii_ratio ) - return F; - - local id = c$id; - - if ( id in telnet_sig_conns && - telnet_sig_conns[id] != BACKDOOR_YES ) - { - telnet_sig_conns[id] = BACKDOOR_YES; - log_backdoor(c, "telnet-sig"); - } - - if ( id in telnet_sig_3byte_conns && - telnet_sig_3byte_conns[id] != BACKDOOR_YES ) - { - telnet_sig_3byte_conns[id] = BACKDOOR_YES; - log_backdoor(c, "telnet-sig-3byte"); - } - - return T; - } - -event backdoor_stats(c: connection, - os: backdoor_endp_stats, rs: backdoor_endp_stats) - { - telnet_stats(c, os, rs); - ssh_len_stats(c, os, rs); - } diff --git a/policy.old/bittorrent.bro b/policy.old/bittorrent.bro deleted file mode 100644 index 7a1576abf5..0000000000 --- a/policy.old/bittorrent.bro +++ /dev/null @@ -1,277 +0,0 @@ -# $Id:$ -# -# bittorrent.bro - policy script for analyzing BitTorrent traffic -# --------------------------------------------------------------- -# This code contributed by Nadi Sarrar. - -@load dpd -@load weird - -module BitTorrent; - -export { - # Whether to log the length of PDUs. - global log_pdu_length = T &redef; -} - -redef capture_filters += { ["bittorrent"] = "tcp" }; - -type bt_peer_state: enum { - choked, # peer won't receive any responses to requests (initial state) - unchoked # peer may do requests -}; - -type bt_peer_info: record { - # Total of pure peer wire protocol overhead data (w/o pieces). - protocol_total: count &default = 0; - - # State of the peer - choked or unchoked. - state: bt_peer_state &default = choked; - - # Total number of seconds the peer was unchoked. - unchoked: interval &default = 0 secs; - - # Time of the last received unchoke message. - time_last_unchoked: time; -}; - -type bt_peer_conn: record { - id: count; - orig: bt_peer_info; - resp: bt_peer_info; - weird: bool &default = F; -}; - -global bittorrent_log = open_log_file("bittorrent") &redef; -global bt_peer_conns : table[conn_id] of bt_peer_conn; -global peer_conn_count = 0; - -function record_peer_protocol_traffic(c: connection, is_orig: bool, - protocol_len: count): count - { - if ( c$id in bt_peer_conns ) - { - local pc = bt_peer_conns[c$id]; - - if ( is_orig ) - pc$orig$protocol_total += protocol_len; - else - pc$resp$protocol_total += protocol_len; - - return pc$id; - } - - return 0; - } - -function record_choke(pi: bt_peer_info, now: time) - { - if ( pi$state == unchoked ) - { - pi$state = choked; - pi$unchoked += now - pi$time_last_unchoked; - } - } - -function record_unchoke(pi: bt_peer_info, now: time) - { - if ( pi$state == choked ) - { - pi$state = unchoked; - pi$time_last_unchoked = now; - } - } - -function lookup_bt_peer(id: conn_id): bt_peer_conn - { - if ( id in bt_peer_conns ) - return bt_peer_conns[id]; - - local orig: bt_peer_info; - local resp: bt_peer_info; - local pc: bt_peer_conn; - pc$orig = orig; - pc$resp = resp; - pc$id = ++peer_conn_count; - bt_peer_conns[id] = pc; - - return pc; - } - -function bt_log_id(id: conn_id, cid: count, tag: string, is_orig: bool): string - { - return fmt("%.6f P%d %s %s:%d %s %s:%d", - network_time(), cid, tag, id$orig_h, id$orig_p, - is_orig ? ">" : "<", id$resp_h, id$resp_p); - } - -function pdu_log_len(len: count): string - { - return log_pdu_length ? fmt("[PDU-len:%d]", len) : ""; - } - -function log_pdu(c: connection, is_orig: bool, tag: string, len: count): count - { - local cid = record_peer_protocol_traffic(c, is_orig, len); - print bittorrent_log, - fmt("%s %s", bt_log_id(c$id, cid, tag, is_orig), - pdu_log_len(len)); - - return cid; - } - -function log_pdu_str(c: connection, is_orig: bool, tag: string, len: count, - str: string) - { - local cid = record_peer_protocol_traffic(c, is_orig, len); - print bittorrent_log, - fmt("%s %s %s", bt_log_id(c$id, cid, tag, is_orig), - pdu_log_len(len), str); - } - -function log_pdu_str_n(c: connection, is_orig: bool, tag: string, len: count, - n: count, str: string) - { - local cid = record_peer_protocol_traffic(c, is_orig, len); - print bittorrent_log, - fmt("%s %s %s", bt_log_id(c$id, cid, tag, is_orig), - pdu_log_len(n), str); - } - -event bittorrent_peer_handshake(c: connection, is_orig: bool, reserved: string, - info_hash: string, peer_id: string) - { - local pc = lookup_bt_peer(c$id); - log_pdu_str(c, is_orig, "handshake", 68, - fmt("[peer_id:%s info_hash:%s reserved:%s]", - bytestring_to_hexstr(peer_id), - bytestring_to_hexstr(info_hash), - bytestring_to_hexstr(reserved))); - } - -event bittorrent_peer_keep_alive(c: connection, is_orig: bool) - { - log_pdu(c, is_orig, "keep-alive", 4); - } - -event bittorrent_peer_choke(c: connection, is_orig: bool) - { - local cid = log_pdu(c, is_orig, "choke", 5); - if ( cid > 0 ) - { - local pc = bt_peer_conns[c$id]; - record_choke(is_orig ? pc$resp : pc$orig, network_time()); - } - } - -event bittorrent_peer_unchoke(c: connection, is_orig: bool) - { - local cid = log_pdu(c, is_orig, "unchoke", 5); - if ( cid > 0 ) - { - local pc = bt_peer_conns[c$id]; - record_unchoke(is_orig ? pc$resp : pc$orig, network_time()); - } - } - -event bittorrent_peer_interested(c: connection, is_orig: bool) - { - log_pdu(c, is_orig, "interested", 5); - } - -event bittorrent_peer_not_interested(c: connection, is_orig: bool) - { - log_pdu(c, is_orig, "not-interested", 5); - } - -event bittorrent_peer_have(c: connection, is_orig: bool, piece_index: count) - { - log_pdu(c, is_orig, "have", 9); - } - -event bittorrent_peer_bitfield(c: connection, is_orig: bool, bitfield: string) - { - log_pdu_str(c, is_orig, "bitfield", 5 + byte_len(bitfield), - fmt("[bitfield:%s]", - bytestring_to_hexstr(bitfield))); - } - -event bittorrent_peer_request(c: connection, is_orig: bool, index: count, - begin: count, length: count) - { - log_pdu_str(c, is_orig, "request", 17, - fmt("[index:%d begin:%d length:%d]", index, begin, length)); - } - -event bittorrent_peer_piece(c: connection, is_orig: bool, index: count, - begin: count, piece_length: count) - { - log_pdu_str_n(c, is_orig, "piece", 13, 13 + piece_length, - fmt("[index:%d begin:%d piece_length:%d]", - index, begin, piece_length)); - } - -event bittorrent_peer_cancel(c: connection, is_orig: bool, index: count, - begin: count, length: count) - { - log_pdu_str(c, is_orig, "cancel", 7, - fmt("[index:%d begin:%d length:%d]", - index, begin, length)); - } - -event bittorrent_peer_port(c: connection, is_orig: bool, listen_port: port) - { - log_pdu_str(c, is_orig, "port", 5, - fmt("[listen_port:%s]", listen_port)); - } - -event bittorrent_peer_unknown(c: connection, is_orig: bool, message_id: count, - data: string) - { - log_pdu_str(c, is_orig, "", 5 + byte_len(data), - fmt("[message_id:%d]", message_id)); - } - -event bittorrent_peer_weird(c: connection, is_orig: bool, msg: string) - { - local pc = lookup_bt_peer(c$id); - pc$weird = T; - - print bittorrent_log, - fmt("%s [%s]", bt_log_id(c$id, pc$id, "", is_orig), msg); - - event conn_weird(msg, c); - } - -function log_close(c: connection, pc: bt_peer_conn, is_orig: bool) - { - local endp = is_orig ? c$orig : c$resp; - local peer_i = is_orig ? pc$orig : pc$resp; - - local status = - pc$weird ? - fmt("size:%d", endp$size) : - fmt("unchoked:%.06f size_protocol:%d size_pieces:%d", - peer_i$unchoked, peer_i$protocol_total, - endp$size - peer_i$protocol_total); - - print bittorrent_log, - fmt("%s [duration:%.06f %s]", - bt_log_id(c$id, pc$id, "", is_orig), - c$duration, status); - } - -event connection_state_remove(c: connection) - { - if ( c$id !in bt_peer_conns ) - return; - - local pc = bt_peer_conns[c$id]; - delete bt_peer_conns[c$id]; - - record_choke(pc$orig, c$start_time + c$duration); - record_choke(pc$resp, c$start_time + c$duration); - - log_close(c, pc, T); - log_close(c, pc, F); - } diff --git a/policy.old/blaster.bro b/policy.old/blaster.bro deleted file mode 100644 index 07cc542199..0000000000 --- a/policy.old/blaster.bro +++ /dev/null @@ -1,52 +0,0 @@ -# $Id: blaster.bro 5952 2008-07-13 19:45:15Z vern $ -# -# Identifies W32.Blaster-infected hosts by observing their scanning -# activity. - -@load notice -@load site - -# Which hosts have scanned which addresses via 135/tcp. -global w32b_scanned: table[addr] of set[addr] &write_expire = 5min; -global w32b_reported: set[addr] &persistent; - -const W32B_port = 135/tcp; -const W32B_MIN_ATTEMPTS = 50 &redef; - -redef enum Notice += { - W32B_SourceLocal, - W32B_SourceRemote, -}; - -event connection_attempt(c: connection) - { - if ( c$id$resp_p != W32B_port ) - return; - - local ip = c$id$orig_h; - - if ( ip in w32b_reported ) - return; - - if ( ip in w32b_scanned ) - { - add (w32b_scanned[ip])[c$id$resp_h]; - - if ( length(w32b_scanned[ip]) >= W32B_MIN_ATTEMPTS ) - { - if ( is_local_addr(ip) ) - NOTICE([$note=W32B_SourceLocal, $conn=c, - $msg=fmt("W32.Blaster local source: %s", - ip)]); - else - NOTICE([$note=W32B_SourceRemote, $conn=c, - $msg=fmt("W32.Blaster remote source: %s", - ip)]); - - add w32b_reported[ip]; - } - } - - else - w32b_scanned[ip] = set(ip) &mergeable; - } diff --git a/policy.old/brolite-backdoor.bro b/policy.old/brolite-backdoor.bro deleted file mode 100644 index c2a378f907..0000000000 --- a/policy.old/brolite-backdoor.bro +++ /dev/null @@ -1,55 +0,0 @@ -# $Id: brolite-backdoor.bro 2956 2006-05-14 01:08:34Z vern $ - -# Sample file for running backdoor detector -# -# Note, this can consume significant processing resources when running -# on live traffic. -# -# To run bro with this script using a Bro Lite setup: -# -# rename this script to hostname.bro -# run: $BROHOME/etc/bro.rc start -# or bro -i interface brolite-backdoor.bro - -@load site - -@load backdoor -@load weird - -# By default, do backdoor detection on everything except standard HTTP -# and SMTP ports. -redef capture_filters += [ ["tcp"] = "tcp" ]; -redef restrict_filters += - [ ["not-http"] = "not (port 80 or port 8000 or port 8080)" ]; -redef restrict_filters += [ ["not-smtp"] = "not (port 25 or port 587)" ]; - -redef use_tagging = T; - -# Set if you want to dump packets that trigger the detections. -redef dump_backdoor_packets = T; - -# Disable (set to T) if you don't care about this traffic. -# redef gnutella_sig_disabled = T; -# redef kazaa_sig_disabled = T; - -redef napster_sig_disabled = T; # too many false positives - -# Ignore outgoing, only report incoming backdoors. -redef backdoor_ignore_remote += { - ftp_backdoor_sigs, ssh_backdoor_sigs, rlogin_backdoor_sigs, - http_backdoor_sigs, http_proxy_backdoor_sigs, smtp_backdoor_sigs, -}; - -# Set these to send mail on backdoor alarms. -# redef mail_dest = "youremail@yourhost.dom"; -# redef notice_action_filters += { -# [BackdoorFound] = send_email_notice, -#}; - -# Tuning: use more aggressive timeouts to reduce CPU and memory, as these -# have little effect on backdoor analysis. -redef tcp_SYN_timeout = 1 sec; -redef tcp_attempt_delay = 1 sec; -redef tcp_inactivity_timeout = 1 min; -redef udp_inactivity_timeout = 5 secs; -redef icmp_inactivity_timeout = 5 secs; diff --git a/policy.old/brolite-sigs.bro b/policy.old/brolite-sigs.bro deleted file mode 100644 index 33b5be7730..0000000000 --- a/policy.old/brolite-sigs.bro +++ /dev/null @@ -1,82 +0,0 @@ -# $Id: brolite-sigs.bro 3856 2006-12-02 00:18:57Z vern $ - -# Bro Lite signature configuration file - -# General policy - these scripts are more infrastructural than service -# oriented, so in general avoid changing anything here. - -# Set global constant. This can be used in ifdef statements to determine -# if signatures are enabled. -const use_signatures = T; - -@load snort # basic definitions for signatures -@load signatures # the signature policy engine -@load sig-functions # addl. functions added for signature accuracy -@load sig-action # actions related to particular signatures - -# Flag HTTP worm sources such as Code Red. -@load worm - -# Do worm processing -redef notice_action_filters += { [RemoteWorm] = file_notice }; - -# Ports that need to be captured for signatures to see a useful -# cross section of traffic. -redef capture_filters += { - ["sig-http"] = - "tcp port 80 or tcp port 8080 or tcp port 8000 or tcp port 8001", - ["sig-ftp"] = "port ftp", - ["sig-telnet"] = "port telnet", - ["sig-portmapper"] = "port 111", - ["sig-smtp"] = "port smtp", - ["sig-imap"] = "port 143", - ["sig-snmp"] = "port 161 or port 162", - ["sig-dns"] = "port 53", - - # rsh/rlogin/rexec - ["sig-rfoo"] = "port 512 or port 513 or port 515", - - # Range of TCP ports for general RPC traffic. This can also - # occur on other ports, but these should catch a lot without - # a major performance hit. We skip ports assosciated with - # HTTP, SSH and M$. - ["sig-rpc"] = "tcp[2:2] > 32770 and tcp[2:2] < 32901 and tcp[0:2] != 80 and tcp[0:2] != 22 and tcp[0:2] != 139", -}; - -### Why is this called "tcp3"? -# Catch outbound M$ scanning. Returns filter listing local addresses -# along with the interesting ports. -function create_tcp3_filter(): string - { - local local_addrs = ""; - local firsttime = T; - - for ( l in local_nets ) - { - if ( firsttime ) - { - local_addrs = fmt("src net %s", l); - firsttime = F; - } - else - local_addrs = fmt("%s or src net %s", local_addrs, l); - } - - local MS_scan_ports = - "dst port 135 or dst port 137 or dst port 139 or dst port 445"; - - if ( local_addrs == "" ) - return MS_scan_ports; - else - return fmt("(%s) and (%s)", local_addrs, MS_scan_ports); - } - -# Create and apply the filter. -redef capture_filters += { ["tcp3"] = create_tcp3_filter()}; - -# Turn on ICMP analysis. -redef capture_filters += { ["icmp"] = "icmp"}; - -# Load the addendum signatures. These are utility signatures that do not -# produce event messages. -redef signature_files += "sig-addendum"; diff --git a/policy.old/brolite.bro b/policy.old/brolite.bro deleted file mode 100644 index 36d9ad3653..0000000000 --- a/policy.old/brolite.bro +++ /dev/null @@ -1,195 +0,0 @@ -# Bro Lite base configuration file. - -# General policy - these scripts are more infrastructural than service -# oriented, so in general avoid changing anything here. - -@load site # defines local and neighbor networks from static config -@load tcp # initialize BPF filter for SYN/FIN/RST TCP packets -@load weird # initialize generic mechanism for unusual events -@load conn # access and record connection events -@load hot # defines certain forms of sensitive access -@load frag # process TCP fragments -@load print-resources # on exit, print resource usage information - -# Scan detection policy. -@load scan # generic scan detection mechanism -@load trw # additional, more sensitive scan detection -#@load drop # include if installation has ability to drop hostile remotes - -# Application level policy - these scripts operate on the specific service. -@load http # general http analyzer, low level of detail -@load http-request # detailed analysis of http requests -@load http-reply # detailed analysis of http reply's - -# Track software versions; required for some signature matching. Also -# can be used by http and ftp policies. -@load software - -@load ftp # FTP analysis -@load portmapper # record and analyze RPC portmapper requests -@load tftp # identify and log TFTP sessions -@load login # rlogin/telnet analyzer -@load irc # IRC analyzer -@load blaster # blaster worm detection -@load stepping # "stepping stone" detection -@load synflood # synflood attacks detection -@load smtp # record and analyze email traffic - somewhat expensive - -@load notice-policy # tuning of notices to downgrade some alarms - -# off by default -#@load icmp # icmp analysis - -# Tuning of memory consumption. -@load inactivity # time out connections for certain services more quickly -# @load print-globals # on exit, print the size of global script variables - -# Record system statistics to the notice file -@load stats - -# udp analysis - potentially expensive, depending on a site's traffic profile -#@load udp.all -#@load remove-multicast - -# Prints the pcap filter and immediately exits. Not used during -# normal operation. -#@load print-filter - -## End policy script loading. - -## General configuration. - -@load rotate-logs -redef log_rotate_base_time = "0:00"; -redef log_rotate_interval = 24 hr; - - -# Set additional policy prefixes. -@prefixes += lite - -## End basic configuration. - - -## Scan configuration. -@ifdef ( Scan::analyze_all_services ) - redef Scan::analyze_all_services = T; - - # The following turns off scan detection. - #redef Scan::suppress_scan_checks = T; - - # Be a bit more aggressive than default (though the defaults - # themselves should be fixed). - redef Scan::report_outbound_peer_scan = { 100, 1000, }; - - # These services are skipped for scan detection due to excessive - # background noise. - redef Scan::skip_services += { - http, # Avoid Code Red etc. overload - 27374/tcp, # Massive scanning in Jan 2002 - 1214/tcp, # KaZaa scans - 12345/tcp, # Massive scanning in Apr 2002 - 445/tcp, # Massive distributed scanning Oct 2002 - 135/tcp, # These days, NetBIOS scanning is endemic - 137/udp, # NetBIOS - 139/tcp, # NetBIOS - 1025/tcp, - 6129/tcp, # Dameware - 3127/tcp, # MyDoom worms worms worms! - 2745/tcp, # Bagel worm - 1433/tcp, # Distributed scanning, April 2004 - 5000/tcp, # Distributed scanning, May 2004 - 5554/tcp, # More worm food, May 2004 - 9898/tcp, # Worms attacking worms. ugh - May 2004 - 3410/tcp, # More worm food, June 2004 - 3140/tcp, # Dyslexic worm food, June 2004 - 27347/tcp, # Can't kids type anymore? - 1023/tcp, # Massive scanning, July 2004 - 17300/tcp, # Massive scanning, July 2004 - }; - -@endif - -@ifdef ( ICMP::detect_scans ) - # Whether to detect ICMP scans. - redef ICMP::detect_scans = F; - redef ICMP::scan_threshold = 100; -@endif - -@ifdef ( TRW::TRWAddressScan ) - # remove logging TRW scan events - redef notice_action_filters += { - [TRW::TRWAddressScan] = ignore_notice, - }; -@endif - -# Note: default scan configuration is conservative in terms of memory use and -# might miss slow scans. Consider uncommenting these based on your sites scan -# traffic. -#redef distinct_peers &create_expire = 30 mins; -#redef distinct_ports &create_expire = 30 mins; -#redef distinct_low_ports &create_expire= 30 mins; - - -## End scan configuration. - -## additional IRC checks -redef IRC::hot_words += /.*exe/ ; - - -## Dynamic Protocol Detection configuration -# -# This is off by default, as it requires a more powerful Bro host. -# Uncomment next line to activate. -# const use_dpd = T; - -@ifdef ( use_dpd ) - @load dpd - @load irc-bot - @load dyn-disable - @load detect-protocols - @load detect-protocols-http - @load proxy - @load ssh - - # By default, DPD looks at all traffic except port 80. - # For lightly loaded networks, comment out the restrict_filters line. - # For heavily loaded networks, try adding addition ports (e.g., 25) to - # the restrict filters. - redef capture_filters += [ ["tcp"] = "tcp" ]; - redef restrict_filters += [ ["not-http"] = "not (port 80)" ]; -@endif - -@ifdef ( ProtocolDetector::ServerFound ) -# Report servers on non-standard ports only for local addresses. -redef notice_policy += { - [$pred(a: notice_info) = - { return a$note == ProtocolDetector::ServerFound && - ! is_local_addr(a$src); }, - $result = NOTICE_FILE, - $priority = 1], - - # Report protocols on non-standard ports only for local addresses - # (unless it's IRC). - [$pred(a: notice_info) = - { return a$note == ProtocolDetector::ProtocolFound && - ! is_local_addr(a$dst) && - a$sub != "IRC"; }, - $result = NOTICE_FILE, - $priority = 1], -}; -@endif - -# The following is used to transfer state between Bro's when one -# takes over from another. -# -# NOTE: not implemented in the production version, so ignored for now. -@ifdef ( remote_peers_clear ) - redef remote_peers_clear += { - [127.0.0.1, 55555/tcp] = [$hand_over = T], - [127.0.0.1, 0/tcp] = [$hand_over = T] - }; -@endif - -# Use tagged log files for notices. -redef use_tagging = T; - diff --git a/policy.old/bt-tracker.bro b/policy.old/bt-tracker.bro deleted file mode 100644 index dfc948a9e2..0000000000 --- a/policy.old/bt-tracker.bro +++ /dev/null @@ -1,190 +0,0 @@ -# $Id:$ -# -# bt-tracker.bro - analysis of BitTorrent tracker traffic -# ------------------------------------------------------------------------------ -# This code contributed by Nadi Sarrar. - -@load dpd -@load weird - -module BitTorrent; - -export { - # Whether to log tracker URIs. - global log_tracker_request_uri = F &redef; -} - -redef capture_filters += { ["bittorrent"] = "tcp", }; - -global bt_tracker_log = open_log_file("bt-tracker") &redef; - -global bt_tracker_conns: table[conn_id] of count; -global tracker_conn_count: count = 0; - - -function bt_log_tag(id: conn_id, cid: count, tag: string, is_orig: bool): string - { - return fmt("%.6f T%d %s %s:%d %s %s:%d", - network_time(), cid, tag, id$orig_h, id$orig_p, - is_orig ? ">" : "<", id$resp_h, id$resp_p); - } - -event bt_tracker_request(c: connection, uri: string, - headers: bt_tracker_headers) - { - # Parse and validate URI. - local pair = split1(uri, /\?/); - local keys = split(pair[2], /&/); - - local info_hash = ""; - local peer_ide = ""; - local peer_port = 0/udp; - local uploaded = -1; - local downloaded = -1; - local left = -1; - local compact = T; - local peer_event = "empty"; - - for ( idx in keys ) - { - local keyval = split1(keys[idx], /=/); - if ( length(keyval) != 2 ) - next; - - local key = to_lower(keyval[1]); - local val = keyval[2]; - - if ( key == "info_hash" ) - info_hash = unescape_URI(val); - else if ( key == "peer_id" ) - peer_ide = unescape_URI(val); - else if ( key == "port" ) - peer_port = to_port(to_count(val), tcp); - else if ( key == "uploaded" ) - uploaded = to_int(val); - else if ( key == "downloaded" ) - downloaded = to_int(val); - else if ( key == "left" ) - left = to_int(val); - else if ( key == "compact" ) - compact = (to_int(val) == 1); - - else if ( key == "event" ) - { - val = to_lower(val); - if ( val == /started|stopped|completed/ ) - peer_event = val; - } - } - - if ( info_hash == "" || peer_ide == "" || peer_port == 0/udp ) - { # Does not look like BitTorrent. - disable_analyzer(c$id, current_analyzer()); - delete bt_tracker_conns[c$id]; - return; - } - - if ( peer_port != 0/tcp ) - expect_connection(to_addr("0.0.0.0"), c$id$orig_h, - peer_port, ANALYZER_BITTORRENT, 1 min); - - local id: count; - if ( c$id in bt_tracker_conns ) - id = bt_tracker_conns[c$id]; - else - { - id = ++tracker_conn_count; - bt_tracker_conns[c$id] = id; - } - - print bt_tracker_log, - fmt("%s [peer_id:%s info_hash:%s port:%s event:%s up:%d down:%d left:%d compact:%s]%s", - bt_log_tag(c$id, id, "request", T), - bytestring_to_hexstr(peer_ide), - bytestring_to_hexstr(info_hash), - peer_port, peer_event, - uploaded, downloaded, left, - compact ? "yes" : "no", - log_tracker_request_uri ? fmt(" GET %s", uri) : ""); - } - -function benc_status(benc: bittorrent_benc_dir, tag: string): string - { - if ( tag !in benc || ! benc[tag]?$i ) - return ""; - - local fmt_tag = sub(tag, / /, "_"); - return fmt("%s:%d", fmt_tag, benc[tag]$i); - } - -event bt_tracker_response(c: connection, status: count, - headers: bt_tracker_headers, - peers: bittorrent_peer_set, - benc: bittorrent_benc_dir) - { - if ( c$id !in bt_tracker_conns ) - return; - - local id = bt_tracker_conns[c$id]; - - for ( peer in peers ) - expect_connection(c$id$orig_h, peer$h, peer$p, - ANALYZER_BITTORRENT, 1 min); - - if ( "failure reason" in benc ) - { - print bt_tracker_log, - fmt("%s [failure_reason:\"%s\"]", - bt_log_tag(c$id, id, "response", F), - benc["failure reason"]?$s ? - benc["failure reason"]$s : ""); - return; - } - - print bt_tracker_log, - fmt("%s [%s%s%s%s%speers:%d]", - bt_log_tag(c$id, id, "response", F), - benc_status(benc, "warning message"), - benc_status(benc, "complete"), - benc_status(benc, "incomplete"), - benc_status(benc, "interval"), - benc_status(benc, "min interval"), - length(peers)); - } - -event bt_tracker_response_not_ok(c: connection, status: count, - headers: bt_tracker_headers) - { - if ( c$id in bt_tracker_conns ) - { - local id = bt_tracker_conns[c$id]; - print bt_tracker_log, - fmt("%s [status:%d]", - bt_log_tag(c$id, id, "response", F), status); - } - } - -event bt_tracker_weird(c: connection, is_orig: bool, msg: string) - { - local id = (c$id in bt_tracker_conns) ? bt_tracker_conns[c$id] : 0; - print bt_tracker_log, - fmt("%s [%s]", bt_log_tag(c$id, id, "", is_orig), msg); - - event conn_weird(msg, c); - } - -event connection_state_remove(c: connection) - { - if ( c$id !in bt_tracker_conns ) - return; - - local id = bt_tracker_conns[c$id]; - delete bt_tracker_conns[c$id]; - - print bt_tracker_log, - fmt("%s [duration:%.06f total:%d]", - # Ideally the direction here wouldn't be T or F - # but both, displayed as "<>". - bt_log_tag(c$id, id, "", T), c$duration, - c$orig$size + c$resp$size); - } diff --git a/policy.old/capture-events.bro b/policy.old/capture-events.bro deleted file mode 100644 index 2ba6eba7b7..0000000000 --- a/policy.old/capture-events.bro +++ /dev/null @@ -1,9 +0,0 @@ -#! $Id: capture-events.bro 4674 2007-07-30 22:00:43Z vern $ -# -# Captures all events to events.bst. -# - -event bro_init() - { - capture_events("events.bst"); - } diff --git a/policy.old/capture-loss.bro b/policy.old/capture-loss.bro deleted file mode 100644 index a641749bd4..0000000000 --- a/policy.old/capture-loss.bro +++ /dev/null @@ -1,74 +0,0 @@ -# $Id:$ - -# Logs evidence regarding the degree to which the packet capture process -# suffers from measurment loss. -# -# By default, only reports loss computed in terms of number of "gap events" -# (ACKs for a sequence number that's above a gap). You can also get an -# estimate in terms of number of bytes missing; this however is sometimes -# heavily affected by miscomputations due to broken packets with incorrect -# sequence numbers. (These packets also affect the first estimator, but -# only to a quite minor degree.) - -@load notice - -module CaptureLoss; - -export { - redef enum Notice += { - CaptureLossReport, # interval report - CaptureLossSummary, # end-of-run summary - }; - - # Whether to also report byte-weighted estimates. - global report_byte_based_estimates = F &redef; - - # Whether to generate per-interval reports even if there - # was no evidence of loss. - global report_if_none = F &redef; - - # Whether to generate a summary even if there was no - # evidence of loss. - global summary_if_none = F &redef; -} - - -# Redefine this to be non-zero to get per-interval reports. -redef gap_report_freq = 0 sec; - -event gap_report(dt: interval, info: gap_info) - { - if ( info$gap_events > 0 || report_if_none ) - { - local msg = report_byte_based_estimates ? - fmt("gap-dt=%.6f acks=%d bytes=%d gaps=%d gap-bytes=%d", - dt, info$ack_events, info$ack_bytes, - info$gap_events, info$gap_bytes) : - fmt("gap-dt=%.6f acks=%d gaps=%d", - dt, info$ack_events, info$gap_events); - - NOTICE([$note=CaptureLossReport, $msg=msg]); - } - } - -event bro_done() - { - local g = get_gap_summary(); - - local gap_rate = - g$ack_events == 0 ? 0.0 : - (1.0 * g$gap_events) / (1.0 * g$ack_events); - local gap_bytes = - g$ack_bytes == 0 ? 0.0 : - (1.0 * g$gap_bytes) / (1.0 * g$ack_bytes); - - if ( gap_rate == 0.0 && gap_bytes == 0.0 && ! summary_if_none ) - return; - - local msg = report_byte_based_estimates ? - fmt("estimated rate = %g / %g (events/bytes)", - gap_rate, gap_bytes) : - fmt("estimated rate = %g", gap_rate); - - NOTICE([$note=CaptureLossSummary, $msg=msg]); - } diff --git a/policy.old/capture-state-updates.bro b/policy.old/capture-state-updates.bro deleted file mode 100644 index 7630015365..0000000000 --- a/policy.old/capture-state-updates.bro +++ /dev/null @@ -1,9 +0,0 @@ -#! $Id: capture-events.bro 6 2004-04-30 00:31:26Z jason $ -# -# Captures all operations on &synchronized variables to state-updates.bst. -# - -event bro_init() - { - capture_state_updates("state-updates.bst"); - } diff --git a/policy.old/checkpoint.bro b/policy.old/checkpoint.bro deleted file mode 100644 index 2222d69c0c..0000000000 --- a/policy.old/checkpoint.bro +++ /dev/null @@ -1,54 +0,0 @@ -# $Id: checkpoint.bro 6724 2009-06-07 09:23:03Z vern $ -# -# Checkpoints Bro's persistent state at regular intervals and scans -# the state directory for external updates. - -const state_rescan_interval = 15 secs &redef; -const state_checkpoint_interval = 15 min &redef; - -# Services for which the internal connection state is stored. -const persistent_services = { - 21/tcp, # ftp - 22/tcp, # ssh - 23/tcp, # telnet - 513/tcp, # rlogin -} &redef; - -# The first timer fires immediately. This flags lets us ignore it. -global state_ignore_first = T; - -event state_checkpoint() - { - if ( state_ignore_first ) - state_ignore_first = F; - - else if ( ! bro_is_terminating() ) - checkpoint_state(); - - if ( state_checkpoint_interval > 0 secs ) - schedule state_checkpoint_interval { state_checkpoint() }; - } - -event state_rescan() - { - rescan_state(); - - if ( state_rescan_interval > 0 secs ) - schedule state_rescan_interval { state_rescan() }; - } - -event bro_init() - { - if ( state_checkpoint_interval > 0 secs ) - schedule state_checkpoint_interval { state_checkpoint() }; - - if ( state_rescan_interval > 0 secs ) - schedule state_rescan_interval { state_rescan() }; - } - -event connection_established(c: connection) - { - # Buggy? - # if ( c$id$resp_p in persistent_services ) - # make_connection_persistent(c); - } diff --git a/policy.old/clear-passwords.bro b/policy.old/clear-passwords.bro deleted file mode 100644 index 7607738dcc..0000000000 --- a/policy.old/clear-passwords.bro +++ /dev/null @@ -1,36 +0,0 @@ -# $Id: clear-passwords.bro 4758 2007-08-10 06:49:23Z vern $ - -# Monitoring for use of cleartext passwords. - -@load ftp -@load login -@load pop3 -@load irc - -const passwd_file = open_log_file("passwords") &redef; - -# ftp, login and pop3 call login_{success,failure}, which in turn -# calls account_tried(), so we can snarf all at once here: -event account_tried(c: connection, user: string, passwd: string) - { - print passwd_file, fmt("%s account name '%s', password '%s': %s", - is_local_addr(c$id$orig_h) ? "local" : "remote", - user, passwd, id_string(c$id)); - } - -# IRC raises a different event on login, so we hook into it here: -event irc_join_message(c: connection, info_list: irc_join_list) - { - for ( l in info_list) - { - print passwd_file, fmt("IRC JOIN name '%s', password '%s'", - l$nick, l$password); - } - } - -# Raised if IRC user tries to become operator: -event irc_oper_message(c: connection, user: string, password: string) - { - print passwd_file, fmt("IRC OPER name '%s', password '%s'", - user, password); - } diff --git a/policy.old/conn-flood.bro b/policy.old/conn-flood.bro deleted file mode 100644 index 7da1cccff4..0000000000 --- a/policy.old/conn-flood.bro +++ /dev/null @@ -1,71 +0,0 @@ -# $Id$ -# -# Script which alarms if the number of connections per time interval -# exceeds a threshold. -# -# This script is mainly meant as a demonstration; it hasn't been hardened -# with/for operational use. - -@load notice - -module ConnFlood; - -export { - redef enum Notice += { - ConnectionFloodStart, ConnectionFloodEnd, - }; - - # Thresholds to reports (conns/sec). - const thresholds: set[count] = - { 1000, 2000, 4000, 6000, 8000, 10000, 20000, 50000 } - &redef; - - # Average over this time interval. - const avg_interval = 10 sec &redef; -} - -global conn_counter = 0; -global last_thresh = 0; - -# Note: replace with connection_attempt if too expensive. -event new_connection(c: connection) - { - ++conn_counter; - } - -event check_flood() - { - local thresh = 0; - local rate = double_to_count(interval_to_double((conn_counter / avg_interval))); - - # Find the largest threshold reached this interval. - for ( i in thresholds ) - { - if ( rate >= i && rate > thresh ) - thresh = i; - } - - # Report if larger than last reported threshold. - if ( thresh > last_thresh ) - { - NOTICE([$note=ConnectionFloodStart, $n=thresh, - $msg=fmt("flood begins at rate %d conns/sec", rate)]); - last_thresh = thresh; - } - - # If no threshold was reached, the flood is over. - else if ( thresh == 0 && last_thresh > 0 ) - { - NOTICE([$note=ConnectionFloodEnd, $n=thresh, - $msg=fmt("flood ends at rate %d conns/sec", rate)]); - last_thresh = 0; - } - - conn_counter = 0; - schedule avg_interval { check_flood() }; - } - -event bro_init() - { - schedule avg_interval { check_flood() }; - } diff --git a/policy.old/conn-id.bro b/policy.old/conn-id.bro deleted file mode 100644 index 9a81e307c9..0000000000 --- a/policy.old/conn-id.bro +++ /dev/null @@ -1,24 +0,0 @@ -# $Id: conn-id.bro 45 2004-06-09 14:29:49Z vern $ - -# Simple functions for generating ASCII connection identifiers. - -@load port-name - -function id_string(id: conn_id): string - { - return fmt("%s > %s", - endpoint_id(id$orig_h, id$orig_p), - endpoint_id(id$resp_h, id$resp_p)); - } - -function reverse_id_string(id: conn_id): string - { - return fmt("%s < %s", - endpoint_id(id$orig_h, id$orig_p), - endpoint_id(id$resp_h, id$resp_p)); - } - -function directed_id_string(id: conn_id, is_orig: bool): string - { - return is_orig ? id_string(id) : reverse_id_string(id); - } diff --git a/policy.old/conn.bro b/policy.old/conn.bro deleted file mode 100644 index 6491c9b8e1..0000000000 --- a/policy.old/conn.bro +++ /dev/null @@ -1,425 +0,0 @@ -# $Id: conn.bro 6782 2009-06-28 02:19:03Z vern $ - -@load notice -@load hot -@load port-name -@load netstats -@load conn-id - -redef enum Notice += { - SensitiveConnection, # connection marked "hot" -}; - -const conn_closed = { TCP_CLOSED, TCP_RESET }; - -global have_FTP = F; # if true, we've loaded ftp.bro -global have_SMTP = F; # if true, we've loaded smtp.bro - -# TODO: Do we have a nicer way of doing this? -export { global FTP::is_ftp_data_conn: function(c: connection): bool; } - -# Whether to include connection state history in the logs generated -# by record_connection. -const record_state_history = F &redef; - -# Whether to translate the local address in SensitiveConnection notices -# to a hostname. Meant as a demonstration of the "when" construct. -const xlate_hot_local_addr = F &redef; - -# Whether to use DPD for generating the service field in the summaries. -# Default off, because it changes the format of conn.log in a way -# potentially incompatible with existing scripts. -const dpd_conn_logs = F &redef; - -# Maps a given port on a given server's address to an RPC service. -# If we haven't loaded portmapper.bro, then it will be empty -# (and, ideally, queries to it would be optimized away ...). -global RPC_server_map: table[addr, port] of string; - -const conn_file = open_log_file("conn") &redef; - -function conn_state(c: connection, trans: transport_proto): string - { - local os = c$orig$state; - local rs = c$resp$state; - - local o_inactive = os == TCP_INACTIVE || os == TCP_PARTIAL; - local r_inactive = rs == TCP_INACTIVE || rs == TCP_PARTIAL; - - if ( trans == tcp ) - { - if ( rs == TCP_RESET ) - { - if ( os == TCP_SYN_SENT || os == TCP_SYN_ACK_SENT || - (os == TCP_RESET && - c$orig$size == 0 && c$resp$size == 0) ) - return "REJ"; - else if ( o_inactive ) - return "RSTRH"; - else - return "RSTR"; - } - else if ( os == TCP_RESET ) - return r_inactive ? "RSTOS0" : "RSTO"; - else if ( rs == TCP_CLOSED && os == TCP_CLOSED ) - return "SF"; - else if ( os == TCP_CLOSED ) - return r_inactive ? "SH" : "S2"; - else if ( rs == TCP_CLOSED ) - return o_inactive ? "SHR" : "S3"; - else if ( os == TCP_SYN_SENT && rs == TCP_INACTIVE ) - return "S0"; - else if ( os == TCP_ESTABLISHED && rs == TCP_ESTABLISHED ) - return "S1"; - else - return "OTH"; - } - - else if ( trans == udp ) - { - if ( os == UDP_ACTIVE ) - return rs == UDP_ACTIVE ? "SF" : "S0"; - else - return rs == UDP_ACTIVE ? "SHR" : "OTH"; - } - - else - return "OTH"; - } - -function conn_size(e: endpoint, trans: transport_proto): string - { - if ( e$size > 0 || (trans == tcp && e$state == TCP_CLOSED) ) - return fmt("%d", e$size); - else - ### should return 0 for TCP_RESET that went through TCP_CLOSED - return "?"; - } - -function service_name(c: connection): string - { - local p = c$id$resp_p; - - if ( p in port_names ) - return port_names[p]; - else - return "other"; - } - -const state_graphic = { - ["OTH"] = "?>?", ["REJ"] = "[", - ["RSTO"] = ">]", ["RSTOS0"] = "}]", ["RSTR"] = ">[", ["RSTRH"] = "<[", - ["S0"] = "}", ["S1"] = ">", ["S2"] = "}2", ["S3"] = "}3", - ["SF"] = ">", ["SH"] = ">h", ["SHR"] = " 0 ) - log_hot_conn(c); - - if ( trans == tcp ) - { - if ( c$orig$state in conn_closed || c$resp$state in conn_closed ) - duration = fmt("%.06f", c$duration); - else - duration = "?"; - } - else - duration = fmt("%.06f", c$duration); - - local addl = c$addl; - -@ifdef ( estimate_flow_size_and_remove ) - # Annotate connection with separately-estimated size, if present. - local orig_est = estimate_flow_size_and_remove(id, T); - local resp_est = estimate_flow_size_and_remove(id, F); - - if ( orig_est$have_est ) - addl = fmt("%s olower=%.0fMB oupper=%.0fMB oincon=%s", addl, - orig_est$lower / 1e6, orig_est$upper / 1e6, - orig_est$num_inconsistent); - - if ( resp_est$have_est ) - addl = fmt("%s rlower=%.0fMB rupper=%.0fMB rincon=%s", addl, - resp_est$lower / 1e6, resp_est$upper / 1e6, - resp_est$num_inconsistent); -@endif - - local service = determine_service(c); - - local log_msg = - fmt("%.6f %s %s %s %s %d %d %s %s %s %s %s", - c$start_time, duration, id$orig_h, id$resp_h, service, - id$orig_p, id$resp_p, trans, - conn_size(c$orig, trans), conn_size(c$resp, trans), - conn_state(c, trans), flags); - - if ( record_state_history ) - log_msg = fmt("%s %s", log_msg, - c$history == "" ? "X" : c$history); - - if ( addl != "" ) - log_msg = fmt("%s %s", log_msg, addl); - - print f, log_msg; - } - -event connection_established(c: connection) - { - Hot::check_hot(c, Hot::CONN_ESTABLISHED); - - if ( c$hot > 0 ) - log_hot_conn(c); - } - -event partial_connection(c: connection) - { - if ( c$orig$state == TCP_PARTIAL && c$resp$state == TCP_INACTIVE ) - # This appears to be a stealth scan. Don't do hot-checking - # as there wasn't an established connection. - ; - else - { - Hot::check_hot(c, Hot::CONN_ESTABLISHED); - Hot::check_hot(c, Hot::APPL_ESTABLISHED); # assume it's been established - } - - if ( c$hot > 0 ) - log_hot_conn(c); - } - -event connection_attempt(c: connection) - { - Hot::check_spoof(c); - Hot::check_hot(c, Hot::CONN_ATTEMPTED); - } - -event connection_finished(c: connection) - { - if ( c$orig$size == 0 || c$resp$size == 0 ) - # Hard to get excited about this - not worth logging again. - c$hot = 0; - else - Hot::check_hot(c, Hot::CONN_FINISHED); - } - -event connection_partial_close(c: connection) - { - if ( c$orig$size == 0 || c$resp$size == 0 ) - # Hard to get excited about this - not worth logging again. - c$hot = 0; - else - Hot::check_hot(c, Hot::CONN_FINISHED); - } - -event connection_half_finished(c: connection) - { - Hot::check_hot(c, Hot::CONN_ATTEMPTED); - } - -event connection_rejected(c: connection) - { - Hot::check_hot(c, Hot::CONN_REJECTED); - } - -event connection_reset(c: connection) - { - Hot::check_hot(c, Hot::CONN_FINISHED); - } - -event connection_pending(c: connection) - { - if ( c$orig$state in conn_closed && - (c$resp$state == TCP_INACTIVE || c$resp$state == TCP_PARTIAL) ) - # This is a stray FIN or RST - don't bother reporting. - return; - - if ( c$orig$state == TCP_RESET || c$resp$state == TCP_RESET ) - # We already reported this connection when the RST - # occurred. - return; - - Hot::check_hot(c, Hot::CONN_FINISHED); - } - -function connection_gone(c: connection, gone_type: string) - { - if ( c$orig$size == 0 || c$resp$size == 0 ) - { - if ( c$orig$state == TCP_RESET && c$resp$state == TCP_INACTIVE) - # A bare RST, no other context. Ignore it. - return; - - # Hard to get excited about this - not worth logging again, - # per connection_finished(). - c$hot = 0; - } - else - Hot::check_hot(c, Hot::CONN_TIMEOUT); - } - -event connection_state_remove(c: connection) &priority = -10 - { - local os = c$orig$state; - local rs = c$resp$state; - - if ( os == TCP_ESTABLISHED && rs == TCP_ESTABLISHED ) - # It was still active, no summary generated. - connection_gone(c, "remove"); - - else if ( (os == TCP_CLOSED || rs == TCP_CLOSED) && - (os == TCP_ESTABLISHED || rs == TCP_ESTABLISHED) ) - # One side has closed, the other hasn't - it's in state S2 - # or S3, hasn't been reported yet. - connection_gone(c, "remove"); - - record_connection(conn_file, c); - - delete hot_conns_reported[c$id]; - } diff --git a/policy.old/contents.bro b/policy.old/contents.bro deleted file mode 100644 index 152b54ed3b..0000000000 --- a/policy.old/contents.bro +++ /dev/null @@ -1,40 +0,0 @@ -# $Id: contents.bro 47 2004-06-11 07:26:32Z vern $ - -redef capture_filters += { ["contents"] = "tcp" }; - -# Keeps track of to which given contents files we've written. -global contents_files: set[string]; - -event new_connection_contents(c: connection) - { - local id = c$id; - - local orig_file = - fmt("contents.%s.%d-%s.%d", - id$orig_h, id$orig_p, id$resp_h, id$resp_p); - local resp_file = - fmt("contents.%s.%d-%s.%d", - id$resp_h, id$resp_p, id$orig_h, id$orig_p); - - local orig_f: file; - local resp_f: file; - - if ( orig_file !in contents_files ) - { - add contents_files[orig_file]; - orig_f = open(orig_file); - } - else - orig_f = open_for_append(orig_file); - - if ( resp_file !in contents_files ) - { - add contents_files[resp_file]; - resp_f = open(resp_file); - } - else - resp_f = open_for_append(resp_file); - - set_contents_file(id, CONTENTS_ORIG, orig_f); - set_contents_file(id, CONTENTS_RESP, resp_f); - } diff --git a/policy.old/cpu-adapt.bro b/policy.old/cpu-adapt.bro deleted file mode 100644 index 7376e0780a..0000000000 --- a/policy.old/cpu-adapt.bro +++ /dev/null @@ -1,62 +0,0 @@ -# $Id: cpu-adapt.bro 1904 2005-12-14 03:27:15Z vern $ -# -# Adjust load level based on cpu load. - -@load load-level - -# We increase the load-level if the average CPU load (percentage) is -# above this limit. -global cpu_upper_limit = 70.0 &redef; - -# We derease the load-level if the average CPU load is below this limit. -global cpu_lower_limit = 30.0 &redef; - -# Time interval over which we average the CPU load. -global cpu_interval = 1 min &redef; - -global cpu_last_proc_time = 0 secs; -global cpu_last_wall_time: time = 0; - -event cpu_measure_load() - { - local res = resource_usage(); - local proc_time = res$user_time + res$system_time; - local wall_time = current_time(); - - if ( cpu_last_proc_time > 0 secs ) - { - local dproc = proc_time - cpu_last_proc_time; - local dwall = wall_time - cpu_last_wall_time; - local load = dproc / dwall * 100.0; - - print ll_file, fmt("%.6f CPU load %.02f", network_time(), load); - - # Second test is for whether we have any room to change - # things. It shouldn't be hardwired to "xxx10" .... - if ( load > cpu_upper_limit && - current_load_level != LoadLevel10 ) - { - print ll_file, fmt("%.6f CPU load above limit: %.02f", - network_time(), load); - increase_load_level(); - } - - else if ( load < cpu_lower_limit && - current_load_level != LoadLevel1 ) - { - print ll_file, fmt("%.6f CPU load below limit: %.02f", - network_time(), load); - decrease_load_level(); - } - } - - cpu_last_proc_time = proc_time; - cpu_last_wall_time = wall_time; - - schedule cpu_interval { cpu_measure_load() }; - } - -event bro_init() - { - schedule cpu_interval { cpu_measure_load() }; - } diff --git a/policy.old/dce.bro b/policy.old/dce.bro deleted file mode 100644 index 51b82d3894..0000000000 --- a/policy.old/dce.bro +++ /dev/null @@ -1,8 +0,0 @@ -# $Id:$ - -redef capture_filters += { ["dce"] = "port 135" }; - -global dce_ports = { 135/tcp } &redef; -redef dpd_config += { [ANALYZER_DCE_RPC] = [$ports = dce_ports] }; - -# No default implementation for events. diff --git a/policy.old/demux.bro b/policy.old/demux.bro deleted file mode 100644 index cfb70d6686..0000000000 --- a/policy.old/demux.bro +++ /dev/null @@ -1,41 +0,0 @@ -# $Id: demux.bro 4758 2007-08-10 06:49:23Z vern $ - -const demux_dir = log_file_name("xscript") &redef; -global created_demux_dir = F; - -# Table of which connections we're demuxing. -global demuxed_conn: set[conn_id]; - -# tag: identifier to use for the reason for demuxing -# otag: identifier to use for originator side of the connection -# rtag: identifier to use for responder side of the connection -function demux_conn(id: conn_id, tag: string, otag: string, rtag: string): bool - { - if ( id in demuxed_conn || ! active_connection(id) ) - return F; - - if ( ! created_demux_dir ) - { - mkdir(demux_dir); - created_demux_dir = T; - } - - local orig_file = - fmt("%s/%s.%s.%s.%d-%s.%d", demux_dir, otag, tag, - id$orig_h, id$orig_p, id$resp_h, id$resp_p); - local resp_file = - fmt("%s/%s.%s.%s.%d-%s.%d", demux_dir, rtag, tag, - id$resp_h, id$resp_p, id$orig_h, id$orig_p); - - set_contents_file(id, CONTENTS_ORIG, open(orig_file)); - set_contents_file(id, CONTENTS_RESP, open(resp_file)); - - add demuxed_conn[id]; - - return T; - } - -event connection_finished(c: connection) - { - delete demuxed_conn[c$id]; - } diff --git a/policy.old/detect-protocols-http.bro b/policy.old/detect-protocols-http.bro deleted file mode 100644 index fb1fed33ac..0000000000 --- a/policy.old/detect-protocols-http.bro +++ /dev/null @@ -1,156 +0,0 @@ -# $Id: detect-protocols-http.bro,v 1.1.4.2 2006/05/31 00:16:21 sommer Exp $ -# -# Identifies protocols that use HTTP. - -@load detect-protocols - -module DetectProtocolHTTP; - -export { - # Defines characteristics of a protocol. All attributes must match - # to trigger the detection. We match patterns against lower-case - # versions of the data. - type protocol : record { - url: pattern &optional; - client_header: pattern &optional; - client_header_content: pattern &optional; - server_header: pattern &optional; - server_header_content: pattern &optional; - }; - - const protocols: table[string] of protocol = { - ["Kazaa"] = [$url=/^\/\.hash=.*/, $server_header=/^x-kazaa.*/], - ["Gnutella"] = [$url=/^\/(uri-res|gnutella).*/, - $server_header=/^x-gnutella-.*/], - ["Gnutella_"] = [$url=/^\/(uri-res|gnutella).*/, - $server_header=/^x-(content-urn|features).*/], - ["Gnutella__"] = [$url=/^\/(uri-res|gnutella).*/, - $server_header=/^content-type/, - $server_header_content=/.*x-gnutella.*/], - ["BitTorrent"] = [$url=/^.*\/(scrape|announce)\?.*info_hash.*/], - ["SOAP"] = [$client_header=/^([:print:]+-)?(soapaction|methodname|messagetype).*/], - ["Squid"] = [$server_header=/^x-squid.*/], - } &redef; -} - -# Bit masks. -const url_found = 1; -const client_header_found = 2; -const server_header_found = 2; - -type index : record { - id: conn_id; - pid: string; -}; - -# Maps to characteristics found so far. -# FIXME: An integer would suffice for the bit-field -# if we had bit-operations ... -global conns: table[index] of set[count] &read_expire = 1hrs; - -function check_match(c: connection, pid: string, mask: set[count]) - { - conns[[$id=c$id, $pid=pid]] = mask; - - local p = protocols[pid]; - - if ( p?$url && url_found !in mask ) - return; - - if ( p?$client_header && client_header_found !in mask ) - return; - - if ( p?$server_header && server_header_found !in mask ) - return; - - # All found. - - ProtocolDetector::found_protocol(c, ANALYZER_HTTP, pid); - } - -event http_request(c: connection, method: string, original_URI: string, - unescaped_URI: string, version: string) - { - for ( pid in protocols ) - { - local p = protocols[pid]; - - if ( ! p?$url ) - next; - - local mask: set[count]; - local idx = [$id=c$id, $pid=pid]; - if ( idx in conns ) - mask = conns[idx]; - - if ( url_found in mask ) - # Already found a match. - next; - - # FIXME: There are people putting NULs into the URLs - # (BitTorrent), which to_lower() does not like. Not sure - # what the right fix is, though. - unescaped_URI = subst_string(unescaped_URI, "\x00", ""); - - if ( to_lower(unescaped_URI) == p$url ) - { - add mask[url_found]; - check_match(c, pid, mask); - } - } - } - -event http_header(c: connection, is_orig: bool, name: string, value: string) - { - if ( name == /[sS][eE][rR][vV][eE][rR]/ ) - { - # Try to extract the server software. - local s = split1(strip(value), /[[:space:]\/]/); - if ( s[1] == /[-a-zA-Z0-9_]+/ ) - ProtocolDetector::found_protocol(c, ANALYZER_HTTP, s[1]); - } - - for ( pid in protocols ) - { - local p = protocols[pid]; - - local mask: set[count]; - local idx = [$id=c$id, $pid=pid]; - if ( idx in conns ) - mask = conns[idx]; - - if ( p?$client_header && is_orig ) - { - if ( client_header_found in mask ) - return; - - if ( to_lower(name) == p$client_header ) - { - if ( p?$client_header_content ) - if ( to_lower(value) != - p$client_header_content ) - return; - - add mask[client_header_found]; - check_match(c, pid, mask); - } - } - - if ( p?$server_header && ! is_orig ) - { - if ( server_header_found in mask ) - return; - - if ( to_lower(name) == p$server_header ) - { - if ( p?$server_header_content ) - if ( to_lower(value) != - p$server_header_content ) - return; - - add mask[server_header_found]; - check_match(c, pid, mask); - } - } - } - } diff --git a/policy.old/detect-protocols.bro b/policy.old/detect-protocols.bro deleted file mode 100644 index 49f02e60e9..0000000000 --- a/policy.old/detect-protocols.bro +++ /dev/null @@ -1,258 +0,0 @@ -# $Id: detect-protocols.bro,v 1.1.4.4 2006/05/31 18:07:27 sommer Exp $ -# -# Finds connections with protocols on non-standard ports using the DPM -# framework. - -@load site - -@load conn-id -@load notice - -module ProtocolDetector; - -export { - redef enum Notice += { - ProtocolFound, # raised for each connection found - ServerFound, # raised once per dst host/port/protocol tuple - }; - - # Table of (protocol, resp_h, resp_p) tuples known to be uninteresting - # in the given direction. For all other protocols detected on - # non-standard ports, we raise a ProtocolFound notice. (More specific - # filtering can then be done via notice_filters.) - # - # Use 0.0.0.0 for to wildcard-match any resp_h. - - type dir: enum { NONE, INCOMING, OUTGOING, BOTH }; - - const valids: table[count, addr, port] of dir = { - # A couple of ports commonly used for benign HTTP servers. - - # For now we want to see everything. - - # [ANALYZER_HTTP, 0.0.0.0, 81/tcp] = OUTGOING, - # [ANALYZER_HTTP, 0.0.0.0, 82/tcp] = OUTGOING, - # [ANALYZER_HTTP, 0.0.0.0, 83/tcp] = OUTGOING, - # [ANALYZER_HTTP, 0.0.0.0, 88/tcp] = OUTGOING, - # [ANALYZER_HTTP, 0.0.0.0, 8001/tcp] = OUTGOING, - # [ANALYZER_HTTP, 0.0.0.0, 8090/tcp] = OUTGOING, - # [ANALYZER_HTTP, 0.0.0.0, 8081/tcp] = OUTGOING, - # - # [ANALYZER_HTTP, 0.0.0.0, 6346/tcp] = BOTH, # Gnutella - # [ANALYZER_HTTP, 0.0.0.0, 6347/tcp] = BOTH, # Gnutella - # [ANALYZER_HTTP, 0.0.0.0, 6348/tcp] = BOTH, # Gnutella - } &redef; - - # Set of analyzers for which we suppress ServerFound notices - # (but not ProtocolFound). Along with avoiding clutter in the - # log files, this also saves memory because for these we don't - # need to remember which servers we already have reported, which - # for some can be a lot. - const suppress_servers: set [count] = { - # ANALYZER_HTTP - } &redef; - - # We consider a connection to use a protocol X if the analyzer for X - # is still active (i) after an interval of minimum_duration, or (ii) - # after a payload volume of minimum_volume, or (iii) at the end of the - # connection. - const minimum_duration = 30 secs &redef; - const minimum_volume = 4e3 &redef; # bytes - - # How often to check the size of the connection. - const check_interval = 5 secs; - - # Entry point for other analyzers to report that they recognized - # a certain (sub-)protocol. - global found_protocol: function(c: connection, analyzer: count, - protocol: string); - - # Table keeping reported (server, port, analyzer) tuples (and their - # reported sub-protocols). - global servers: table[addr, port, string] of set[string] - &read_expire = 14 days; -} - -# Table that tracks currently active dynamic analyzers per connection. -global conns: table[conn_id] of set[count]; - -# Table of reports by other analyzers about the protocol used in a connection. -global protocols: table[conn_id] of set[string]; - -type protocol : record { - a: string; # analyzer name - sub: string; # "sub-protocols" reported by other sources -}; - -function get_protocol(c: connection, a: count) : protocol - { - local str = ""; - if ( c$id in protocols ) - { - for ( p in protocols[c$id] ) - str = |str| > 0 ? fmt("%s/%s", str, p) : p; - } - - return [$a=analyzer_name(a), $sub=str]; - } - -function fmt_protocol(p: protocol) : string - { - return p$sub != "" ? fmt("%s (via %s)", p$sub, p$a) : p$a; - } - -function do_notice(c: connection, a: count, d: dir) - { - if ( d == BOTH ) - return; - - if ( d == INCOMING && is_local_addr(c$id$resp_h) ) - return; - - if ( d == OUTGOING && ! is_local_addr(c$id$resp_h) ) - return; - - local p = get_protocol(c, a); - local s = fmt_protocol(p); - - NOTICE([$note=ProtocolFound, - $msg=fmt("%s %s on port %s", id_string(c$id), s, c$id$resp_p), - $sub=s, $conn=c, $n=a]); - - # We report multiple ServerFound's per host if we find a new - # sub-protocol. - local known = [c$id$resp_h, c$id$resp_p, p$a] in servers; - - local newsub = F; - if ( known ) - newsub = (p$sub != "" && - p$sub !in servers[c$id$resp_h, c$id$resp_p, p$a]); - - if ( (! known || newsub) && a !in suppress_servers ) - { - NOTICE([$note=ServerFound, - $msg=fmt("%s: %s server on port %s%s", c$id$resp_h, s, - c$id$resp_p, (known ? " (update)" : "")), - $p=c$id$resp_p, $sub=s, $conn=c, $src=c$id$resp_h, $n=a]); - - if ( ! known ) - servers[c$id$resp_h, c$id$resp_p, p$a] = set(); - - add servers[c$id$resp_h, c$id$resp_p, p$a][p$sub]; - } - } - -function report_protocols(c: connection) - { - # We only report the connection if both sides have transferred data. - if ( c$resp$size == 0 || c$orig$size == 0 ) - { - delete conns[c$id]; - delete protocols[c$id]; - return; - } - - local analyzers = conns[c$id]; - - for ( a in analyzers ) - { - if ( [a, c$id$resp_h, c$id$resp_p] in valids ) - do_notice(c, a, valids[a, c$id$resp_h, c$id$resp_p]); - - else if ( [a, 0.0.0.0, c$id$resp_p] in valids ) - do_notice(c, a, valids[a, 0.0.0.0, c$id$resp_p]); - else - do_notice(c, a, NONE); - - append_addl(c, analyzer_name(a)); - } - - delete conns[c$id]; - delete protocols[c$id]; - } - -event ProtocolDetector::check_connection(c: connection) - { - if ( c$id !in conns ) - return; - - local duration = network_time() - c$start_time; - local size = c$resp$size + c$orig$size; - - if ( duration >= minimum_duration || size >= minimum_volume ) - report_protocols(c); - else - { - local delay = min_interval(minimum_duration - duration, - check_interval); - schedule delay { ProtocolDetector::check_connection(c) }; - } - } - -event connection_state_remove(c: connection) - { - if ( c$id !in conns ) - { - delete protocols[c$id]; - return; - } - - # Reports all analyzers that have remained to the end. - report_protocols(c); - } - -event protocol_confirmation(c: connection, atype: count, aid: count) - { - # Don't report anything running on a well-known port. - if ( atype in dpd_config && c$id$resp_p in dpd_config[atype]$ports ) - return; - - if ( c$id in conns ) - { - local analyzers = conns[c$id]; - add analyzers[atype]; - } - else - { - conns[c$id] = set(atype); - - local delay = min_interval(minimum_duration, check_interval); - schedule delay { ProtocolDetector::check_connection(c) }; - } - } - -# event connection_analyzer_disabled(c: connection, analyzer: count) -# { -# if ( c$id !in conns ) -# return; -# -# delete conns[c$id][analyzer]; -# } - -function append_proto_addl(c: connection) - { - for ( a in conns[c$id] ) - append_addl(c, fmt_protocol(get_protocol(c, a))); - } - -function found_protocol(c: connection, analyzer: count, protocol: string) - { - # Don't report anything running on a well-known port. - if ( analyzer in dpd_config && - c$id$resp_p in dpd_config[analyzer]$ports ) - return; - - if ( c$id !in protocols ) - protocols[c$id] = set(); - - add protocols[c$id][protocol]; - } - -event connection_state_remove(c: connection) - { - if ( c$id !in conns ) - return; - - append_proto_addl(c); - } - diff --git a/policy.old/dhcp.bro b/policy.old/dhcp.bro deleted file mode 100644 index 2c60f73fe4..0000000000 --- a/policy.old/dhcp.bro +++ /dev/null @@ -1,525 +0,0 @@ -# $Id: dhcp.bro 4054 2007-08-14 21:45:58Z pclin $ - -@load dpd -@load weird - -module DHCP; - -export { - # Set to false to disable printing to dhcp.log. - const logging = T &redef; -} - -# Type of states in DHCP client. See Figure 5 in RFC 2131. -# Each state name is prefixed with DHCP_ to avoid name conflicts. -type dhcp_state: enum { - - DHCP_INIT_REBOOT, - DHCP_INIT, - DHCP_SELECTING, - DHCP_REQUESTING, - DHCP_REBINDING, - DHCP_BOUND, - DHCP_RENEWING, - DHCP_REBOOTING, - - # This state is not in Figure 5. Client has been externally configured. - DHCP_INFORM, -}; - -global dhcp_log: file; - -# Source port 68: client -> server; source port 67: server -> client. -global dhcp_ports: set[port] = { 67/udp, 68/udp } &redef; - -redef dpd_config += { [ANALYZER_DHCP_BINPAC] = [$ports = dhcp_ports] }; - -# Default handling for peculiarities in DHCP analysis. -redef Weird::weird_action += { - ["DHCP_no_type_option"] = Weird::WEIRD_FILE, - ["DHCP_wrong_op_type"] = Weird::WEIRD_FILE, - ["DHCP_wrong_msg_type"] = Weird::WEIRD_FILE, -}; - -# Types of DHCP messages, identified from the 'options' field. See RFC 1533. -global dhcp_msgtype_name: table[count] of string = { - [1] = "DHCP_DISCOVER", - [2] = "DHCP_OFFER", - [3] = "DHCP_REQUEST", - [4] = "DHCP_DECLINE", - [5] = "DHCP_ACK", - [6] = "DHCP_NAK", - [7] = "DHCP_RELEASE", - [8] = "DHCP_INFORM", -}; - -# Type of DHCP client state, inferred from the messages. See RFC 2131, fig 5. -global dhcp_state_name: table[dhcp_state] of string = { - [DHCP_INIT_REBOOT] = "INIT-REBOOT", - [DHCP_INIT] = "INIT", - [DHCP_SELECTING] = "SELECTING", - [DHCP_REQUESTING] = "REQUESTING", - [DHCP_REBINDING] = "REBINDING", - [DHCP_BOUND] = "BOUND", - [DHCP_RENEWING] = "RENEWING", - [DHCP_REBOOTING] = "REBOOTING", - [DHCP_INFORM] = "INFORM", -}; - -type dhcp_session_info: record { - state: dhcp_state; # the state of a DHCP client - seq: count; # sequence of session in the trace - lease: interval; # lease time of an IP address - h_addr: string; # hardware/MAC address of the client -}; - -# Track the DHCP session info of each client, indexed by the transaction ID. -global dhcp_session: table[count] of dhcp_session_info - &default = record($state = DHCP_INIT_REBOOT, $seq = 0, $lease = 0 sec, - $h_addr = "") - &write_expire = 5 min -; - -# We need the following table to track some DHCPINFORM messages since they -# use xid = 0 (I do not know why), starting from the second pair of INFORM -# and ACK. Since the client address is ready before DHCPINFORM, we can use -# it as the index to find its corresponding xid. -global session_xid: table[addr] of count &read_expire = 30 sec; - -# Count how many DHCP sessions have been detected, for use in dhcp_session_seq. -global pkt_cnt: count = 0; -global session_cnt: count = 0; - -# Record the address of client that sends a DHCPINFORM message with xid = 0. -global recent_client: addr; - -global BROADCAST_ADDR = 255.255.255.255; -global NULL_ADDR = 0.0.0.0; - -# Used to detect if an ACK is duplicated. They are used only in dhcp_ack(). -# We put them here since Bro scripts lacks the equivalent of "static" variables. -global ack_from: addr; -global duplicated_ack: bool; - - -function warning_wrong_state(msg_type: count): string - { - return fmt("%s not sent in a correct state.", - dhcp_msgtype_name[msg_type]); - } - -function dhcp_message(c: connection, seq: count, show_conn: bool): string - { - local conn_info = fmt("%.06f #%d", network_time(), seq); - if ( show_conn ) - return fmt("%s %s > %s", conn_info, - endpoint_id(c$id$orig_h, c$id$orig_p), - endpoint_id(c$id$resp_h, c$id$resp_p)); - - return conn_info; - } - -function new_dhcp_session(xid: count, state: dhcp_state, h_addr: string) -: dhcp_session_info - { - local session: dhcp_session_info; - session$state = state; - session$seq = ++session_cnt; - session$lease = 0 sec; - session$h_addr = h_addr; - - dhcp_session[xid] = session; - - return session; - } - - -event bro_init() - { - if ( logging ) - dhcp_log = open_log_file("dhcp"); - } - -event dhcp_discover(c: connection, msg: dhcp_msg, req_addr: addr) - { - local old_session = T; - - if ( msg$xid !in dhcp_session ) - { - local session = - new_dhcp_session(msg$xid, DHCP_SELECTING, msg$h_addr); - old_session = F; - } - - if ( logging ) - { - if ( old_session && - dhcp_session[msg$xid]$state == DHCP_SELECTING ) - print dhcp_log, fmt("%s DISCOVER (duplicated)", - dhcp_message(c, dhcp_session[msg$xid]$seq, F)); - else - print dhcp_log, - fmt("%s DISCOVER (xid = %x, client state = %s)", - dhcp_message(c, dhcp_session[msg$xid]$seq, T), - msg$xid, dhcp_state_name[dhcp_session[msg$xid]$state]); - } - } - -event dhcp_offer(c: connection, msg: dhcp_msg, mask: addr, - router: dhcp_router_list, lease: interval, serv_addr: addr) - { - local standalone = msg$xid !in dhcp_session; - local err_state = - standalone && dhcp_session[msg$xid]$state != DHCP_SELECTING; - - if ( logging ) - { - # Note that no OFFER messages are considered duplicated, - # since they may come from multiple DHCP servers in a session. - if ( standalone ) - print dhcp_log, fmt("%s OFFER (standalone)", - dhcp_message(c, ++session_cnt, T)); - - else if ( err_state ) - print dhcp_log, fmt("%s OFFER (in error state %s)", - dhcp_message(c, dhcp_session[msg$xid]$seq, T), - dhcp_state_name[dhcp_session[msg$xid]$state]); - - else - print dhcp_log, fmt("%s OFFER (client state = %s)", - dhcp_message(c, dhcp_session[msg$xid]$seq, T), - dhcp_state_name[DHCP_SELECTING]); - } - } - -event dhcp_request(c: connection, msg: dhcp_msg, - req_addr: addr, serv_addr: addr) - { - local log_info: string; - - if ( msg$xid in dhcp_session ) - { - if ( ! logging ) - return; - - local state = dhcp_session[msg$xid]$state; - - if ( state == DHCP_REBOOTING ) - recent_client = req_addr; - else - recent_client = c$id$orig_h; - - session_xid[recent_client] = msg$xid; - - if ( state == DHCP_RENEWING || state == DHCP_REBINDING || - state == DHCP_REQUESTING || state == DHCP_REBOOTING ) - print dhcp_log, fmt("%s REQUEST (duplicated)", - dhcp_message(c, dhcp_session[msg$xid]$seq, F)); - else - { - log_info = dhcp_message(c, dhcp_session[msg$xid]$seq, T); - print dhcp_log, fmt("%s REQUEST (in error state %s)", - log_info, - dhcp_state_name[dhcp_session[msg$xid]$state]); - } - } - else - { - local d_state = DHCP_REBOOTING; - - if ( c$id$resp_h != BROADCAST_ADDR ) - d_state = DHCP_RENEWING; - else if ( msg$ciaddr != NULL_ADDR ) - d_state = DHCP_REBINDING; - else if ( serv_addr != NULL_ADDR ) - d_state = DHCP_REQUESTING; - - local session = new_dhcp_session(msg$xid, d_state, msg$h_addr); - - if ( session$state == DHCP_REBOOTING ) - recent_client = req_addr; - else - recent_client = c$id$orig_h; - - session_xid[recent_client] = msg$xid; - - if ( logging ) - { - log_info = dhcp_message(c, session$seq, T); - if ( req_addr != NULL_ADDR ) - log_info = fmt("%s REQUEST %As", - log_info, req_addr); - else - log_info = fmt("%s REQUEST", log_info); - - print dhcp_log, fmt("%s (xid = %x, client state = %s)", - log_info, msg$xid, - dhcp_state_name[session$state]); - } - } - } - -event dhcp_decline(c: connection, msg: dhcp_msg) - { - local old_session = msg$xid in dhcp_session; - local err_state = F; - - if ( old_session ) - { - if ( dhcp_session[msg$xid]$state == DHCP_REQUESTING ) - dhcp_session[msg$xid]$state = DHCP_INIT; - else - err_state = T; - } - else - new_dhcp_session(msg$xid, DHCP_INIT, ""); - - if ( ! logging ) - return; - - if ( old_session ) - { - if ( err_state ) - print dhcp_log, fmt("%s DECLINE (in error state %s)", - dhcp_message(c, dhcp_session[msg$xid]$seq, T), - dhcp_state_name[dhcp_session[msg$xid]$state]); - else - print dhcp_log, fmt("%s DECLINE (duplicated)", - dhcp_message(c, dhcp_session[msg$xid]$seq, F)); - } - else - print dhcp_log, fmt("%s DECLINE (xid = %x)", - dhcp_message(c, ++session_cnt, T), msg$xid); - } - -event dhcp_ack(c: connection, msg: dhcp_msg, mask: addr, - router: dhcp_router_list, lease: interval, serv_addr: addr) - { - local log_info: string; - - if ( msg$xid == 0 ) - { # An ACK for a DHCPINFORM message with xid = 0. - local xid = - c$id$orig_h in session_xid ? - # An ACK to the client. - session_xid[c$id$orig_h] - : - # Assume ACK from a relay agent to the server. - session_xid[recent_client]; - - local seq: count; - - if ( xid > 0 ) - { - duplicated_ack = dhcp_session[xid]$state != DHCP_INFORM; - dhcp_session[xid]$state = DHCP_BOUND; - seq = dhcp_session[xid]$seq; - } - else - { - # This is a weird situation. We arbitrarily set - # duplicated_ack to false to have more information - # shown. - duplicated_ack = F; - seq = session_cnt; - } - - if ( ! logging ) - return; - - log_info = dhcp_message(c, seq, F); - if ( c$id$orig_h in session_xid ) - { - if ( duplicated_ack ) - print dhcp_log, fmt("%s ACK (duplicated)", - log_info); - else - print dhcp_log, - fmt("%s ACK (client state = %s)", - log_info, - dhcp_state_name[DHCP_BOUND]); - } - else - print dhcp_log, - fmt("%s ACK (relay agent at = %As)", - log_info, c$id$orig_h); - return; - } - - if ( msg$xid in dhcp_session ) - { - local last_state = dhcp_session[msg$xid]$state; - local from_reboot_state = last_state == DHCP_REBOOTING; - - if ( last_state == DHCP_REQUESTING || - last_state == DHCP_REBOOTING || - last_state == DHCP_RENEWING || - last_state == DHCP_REBINDING || - last_state == DHCP_INFORM ) - { - dhcp_session[msg$xid]$state = DHCP_BOUND; - dhcp_session[msg$xid]$lease = lease; - } - - if ( ! logging ) - return; - - if ( last_state == DHCP_BOUND ) - { - log_info = dhcp_message(c, dhcp_session[msg$xid]$seq, F); - if ( c$id$orig_h == ack_from ) - log_info = fmt("%s ACK (duplicated)", - log_info); - - else - # Not a duplicated ACK. - log_info = fmt("%s ACK (relay agent at = %As)", - log_info, c$id$orig_h); - } - else - { - ack_from = c$id$orig_h; - - # If in a reboot state, we had better - # explicitly show the original address - # and the destination address of ACK, - # because the client initally has a - # zero address. - if ( from_reboot_state ) - log_info = dhcp_message(c, dhcp_session[msg$xid]$seq, T); - else - log_info = dhcp_message(c, dhcp_session[msg$xid]$seq, F); - - if ( last_state != DHCP_INFORM && - lease > 0 sec ) - log_info = fmt("%s ACK (lease time = %s, ", - log_info, lease); - else - log_info = fmt("%s ACK (", log_info); - - log_info = fmt("%sclient state = %s)", - log_info, - dhcp_state_name[dhcp_session[msg$xid]$state]); - } - - print dhcp_log, log_info; - } - - else if ( logging ) - print dhcp_log, fmt("%s ACK (standalone)", - dhcp_message(c, ++session_cnt, T)); - } - -event dhcp_nak(c: connection, msg: dhcp_msg) - { - if ( msg$xid in dhcp_session ) - { - local last_state = dhcp_session[msg$xid]$state; - - if ( last_state == DHCP_REQUESTING || - last_state == DHCP_REBOOTING || - last_state == DHCP_RENEWING || - last_state == DHCP_REBINDING ) - dhcp_session[msg$xid]$state = DHCP_INIT; - - if ( logging ) - print dhcp_log, fmt("%s NAK (client state = %s)", - dhcp_message(c, dhcp_session[msg$xid]$seq, F), - dhcp_state_name[dhcp_session[msg$xid]$state]); - } - - else if ( logging ) - print dhcp_log, fmt("%s NAK (standalone)", - dhcp_message(c, ++session_cnt, T)); - } - -event dhcp_release(c: connection, msg: dhcp_msg) - { - local old_session = msg$xid in dhcp_session; - - if ( ! old_session ) - # We assume the client goes back to DHCP_INIT - # because the RFC does not specify which state to go to. - new_dhcp_session(msg$xid, DHCP_INIT, ""); - - if ( ! logging ) - return; - - if ( old_session ) - { - if ( dhcp_session[msg$xid]$state == DHCP_INIT ) - print dhcp_log, fmt("%s RELEASE (duplicated)", - dhcp_message(c, dhcp_session[msg$xid]$seq, F)); - else - print dhcp_log, fmt("%s RELEASE, (client state = %s)", - dhcp_message(c, dhcp_session[msg$xid]$seq, F), - dhcp_state_name[dhcp_session[msg$xid]$state]); - } - else - print dhcp_log, fmt("%s RELEASE (xid = %x, IP addr = %As)", - dhcp_message(c, session_cnt, T), msg$xid, c$id$orig_h); - } - -event dhcp_inform(c: connection, msg: dhcp_msg) - { - recent_client = c$id$orig_h; - - if ( msg$xid == 0 ) - { - # Oops! Try to associate message with transaction ID 0 with - # a previous session. - local xid: count; - local seq: count; - - if ( c$id$orig_h in session_xid ) - { - xid = session_xid[c$id$orig_h]; - dhcp_session[xid]$state = DHCP_INFORM; - seq = dhcp_session[xid]$seq; - } - else - { - # Weird: xid = 0 and no previous INFORM-ACK dialog. - xid = 0; - seq = ++session_cnt; - - # Just record that a INFORM message has appeared, - # although the xid is not useful. - session_xid[c$id$orig_h] = 0; - } - - if ( logging ) - print dhcp_log, - fmt("%s INFORM (xid = %x, client state = %s)", - dhcp_message(c, seq, T), - xid, dhcp_state_name[DHCP_INFORM]); - return; - } - - if ( msg$xid in dhcp_session ) - { - if ( logging ) - if ( dhcp_session[msg$xid]$state == DHCP_INFORM ) - print dhcp_log, fmt("%s INFORM (duplicated)", - dhcp_message(c, dhcp_session[msg$xid]$seq, F)); - else { - print dhcp_log, - fmt("%s INFORM (duplicated, client state = %s)", - dhcp_message(c, dhcp_session[msg$xid]$seq, F), - dhcp_state_name[dhcp_session[msg$xid]$state]); - } - - return; - } - - local session = new_dhcp_session(msg$xid, DHCP_INFORM, msg$h_addr); - - # Associate this transaction ID with the host so we can identify - # subsequent pairs of INFORM/ACK if client uses xid=0. - session_xid[c$id$orig_h] = msg$xid; - - if ( logging ) - print dhcp_log, fmt("%s INFORM (xid = %x, client state = %s)", - dhcp_message(c, session$seq, T), - msg$xid, dhcp_state_name[session$state]); - } diff --git a/policy.old/dns-info.bro b/policy.old/dns-info.bro deleted file mode 100644 index 3ad36d461e..0000000000 --- a/policy.old/dns-info.bro +++ /dev/null @@ -1,81 +0,0 @@ -# $Id: dns-info.bro 3919 2007-01-14 00:27:09Z vern $ - -# Types, errors, and fields for analyzing DNS data. A helper file -# for dns.bro. - -const PTR = 12; -const EDNS = 41; -const ANY = 255; - -const query_types = { - [1] = "A", [2] = "NS", [3] = "MD", [4] = "MF", - [5] = "CNAME", [6] = "SOA", [7] = "MB", [8] = "MG", - [9] = "MR", [10] = "NULL", [11] = "WKS", [PTR] = "PTR", - [13] = "HINFO", [14] = "MINFO", [15] = "MX", [16] = "TXT", - [17] = "RP", [18] = "AFSDB", [19] = "X25", [20] = "ISDN", - [21] = "RT", [22] = "NSAP", [23] = "NSAP-PTR", [24] = "SIG", - [25] = "KEY", [26] = "PX" , [27] = "GPOS", [28] = "AAAA", - [29] = "LOC", [30] = "EID", [31] = "NIMLOC", [32] = "NB", - [33] = "SRV", [34] = "ATMA", [35] = "NAPTR", [36] = "KX", - [37] = "CERT", [38] = "A6", [39] = "DNAME", [40] = "SINK", - [EDNS] = "EDNS", [42] = "APL", [43] = "DS", [44] = "SINK", - [45] = "SSHFP", [46] = "RRSIG", [47] = "NSEC", [48] = "DNSKEY", - [49] = "DHCID", [99] = "SPF", [100] = "DINFO", [101] = "UID", - [102] = "GID", [103] = "UNSPEC", [249] = "TKEY", [250] = "TSIG", - [251] = "IXFR", [252] = "AXFR", [253] = "MAILB", [254] = "MAILA", - [32768] = "TA", [32769] = "DLV", - [ANY] = "*", -} &default = function(n: count): string { return fmt("query-%d", n); }; - -const DNS_code_types = { - [0] = "X0", - [1] = "Xfmt", - [2] = "Xsrv", - [3] = "Xnam", - [4] = "Ximp", - [5] = "X[", -} &default = function(n: count): string { return "?"; }; - -# Used for non-TSIG/EDNS types. -const base_error = { - [0] = "NOERROR", # No Error - [1] = "FORMERR", # Format Error - [2] = "SERVFAIL", # Server Failure - [3] = "NXDOMAIN", # Non-Existent Domain - [4] = "NOTIMP", # Not Implemented - [5] = "REFUSED", # Query Refused - [6] = "YXDOMAIN", # Name Exists when it should not - [7] = "YXRRSET", # RR Set Exists when it should not - [8] = "NXRRSet", # RR Set that should exist does not - [9] = "NOTAUTH", # Server Not Authoritative for zone - [10] = "NOTZONE", # Name not contained in zone - [11] = "unassigned-11", # available for assignment - [12] = "unassigned-12", # available for assignment - [13] = "unassigned-13", # available for assignment - [14] = "unassigned-14", # available for assignment - [15] = "unassigned-15", # available for assignment - [16] = "BADVERS", # for EDNS, collision w/ TSIG - [17] = "BADKEY", # Key not recognized - [18] = "BADTIME", # Signature out of time window - [19] = "BADMODE", # Bad TKEY Mode - [20] = "BADNAME", # Duplicate key name - [21] = "BADALG", # Algorithm not supported - [22] = "BADTRUNC", # draft-ietf-dnsext-tsig-sha-05.txt - [3842] = "BADSIG", # 16 <= number collision with EDNS(16); - # this is a translation from TSIG(16) -} &default = function(n: count): string { return "?"; }; - -# This deciphers EDNS Z field values. -const edns_zfield = { - [0] = "NOVALUE", # regular entry - [32768] = "DNS_SEC_OK", # accepts DNS Sec RRs -} &default = function(n: count): string { return "?"; }; - -const dns_class = { - [1] = "C_INTERNET", - [2] = "C_CSNET", - [3] = "C_CHAOS", - [4] = "C_HESOD", - [254] = "C_NONE", - [255] = "C_ANY", -} &default = function(n: count): string { return "?"; }; diff --git a/policy.old/dns-lookup.bro b/policy.old/dns-lookup.bro deleted file mode 100644 index 8ef1dd4f0a..0000000000 --- a/policy.old/dns-lookup.bro +++ /dev/null @@ -1,65 +0,0 @@ -# $Id: dns-lookup.bro 340 2004-09-09 06:38:27Z vern $ - -@load notice - -redef enum Notice += { - DNS_MappingChanged, # some sort of change WRT previous Bro lookup -}; - -const dns_interesting_changes = { - "unverified", "old name", "new name", "mapping", -} &redef; - -function dump_dns_mapping(msg: string, dm: dns_mapping): bool - { - if ( msg in dns_interesting_changes || - 127.0.0.1 in dm$addrs ) - { - local req = dm$req_host == "" ? - fmt("%As", dm$req_addr) : dm$req_host; - NOTICE([$note=DNS_MappingChanged, - $msg=fmt("DNS %s: %s/%s %s-> %As", msg, req, - dm$hostname, dm$valid ? - "" : "(invalid) ", dm$addrs), - $sub=msg]); - - return T; - } - else - return F; - } - -event dns_mapping_valid(dm: dns_mapping) - { - dump_dns_mapping("valid", dm); - } - -event dns_mapping_unverified(dm: dns_mapping) - { - dump_dns_mapping("unverified", dm); - } - -event dns_mapping_new_name(dm: dns_mapping) - { - dump_dns_mapping("new name", dm); - } - -event dns_mapping_lost_name(dm: dns_mapping) - { - dump_dns_mapping("lost name", dm); - } - -event dns_mapping_name_changed(old_dm: dns_mapping, new_dm: dns_mapping) - { - if ( dump_dns_mapping("old name", old_dm) ) - dump_dns_mapping("new name", new_dm); - } - -event dns_mapping_altered(dm: dns_mapping, - old_addrs: set[addr], new_addrs: set[addr]) - { - if ( dump_dns_mapping("mapping", dm) ) - NOTICE([$note=DNS_MappingChanged, - $msg=fmt("changed addresses: %As -> %As", old_addrs, new_addrs), - $sub="changed addresses"]); - } diff --git a/policy.old/dns.bro b/policy.old/dns.bro deleted file mode 100644 index 812e7245cc..0000000000 --- a/policy.old/dns.bro +++ /dev/null @@ -1,675 +0,0 @@ -# $Id: dns.bro 6724 2009-06-07 09:23:03Z vern $ - -@load notice -@load weird -@load udp-common -@load dns-info - -module DNS; - -export { - # Lookups of hosts in here are flagged ... - const sensitive_lookup_hosts: set[addr] &redef; - - # ... unless the lookup comes from one of these hosts. - const okay_to_lookup_sensitive_hosts: set[addr] &redef; - - # Start considering whether we're seeing PTR scanning if we've seen - # at least this many rejected PTR queries. - const report_rejected_PTR_thresh = 100 &redef; - - # Generate a PTR_scan event if at any point (once we're above - # report_rejected_PTR_thresh) we see this many more distinct - # rejected PTR requests than distinct answered PTR requests. - const report_rejected_PTR_factor = 2.0 &redef; - - # The following sources are allowed to do PTR scanning. - const allow_PTR_scans: set[addr] &redef; - - # Annotations that if returned for a PTR lookup actually indicate - # a rejected query; for example, "illegal-address.lbl.gov". - const actually_rejected_PTR_anno: set[string] &redef; - - # Hosts allowed to do zone transfers. - const zone_transfers_okay: set[addr] &redef; - - # Set to false to disable printing to dns.log. - const logging = T &redef; - - redef enum Notice += { - SensitiveDNS_Lookup, # DNS lookup of sensitive hostname/addr - DNS_PTR_Scan, # A set of PTR lookups - DNS_PTR_Scan_Summary, # Summary of a set of PTR lookups - ResolverInconsistency, # DNS answer changed - ZoneTransfer, # a DNS zone transfer request was seen - - }; - - # This is a list of domains that have a history of providing - # more RR's in response than they are supposed to. There is - # some danger here in that record inconsistancies will not be - # identified for these domains... - const bad_domain_resp: set[string] &redef; - - # Same idea, except that it applies to a list of host names. - const bad_host_resp: set[string] &redef; - - # Turn resolver consistancy checking on/off. - const resolver_consist_check = F &redef; - - # Should queries be checked against 'bad' domains? - const check_domain_list = T; - - # List of 'bad' domains. - const hostile_domain_list: set[string] &redef; - - # Used for PTR scan detection. Exported so their timeouts can be - # adjusted. - global distinct_PTR_requests: - table[addr, string] of count &default = 0 &write_expire = 5 min; - global distinct_rejected_PTR_requests: - table[addr] of count &default = 0 &write_expire = 5 min; - global distinct_answered_PTR_requests: - table[addr] of count &default = 0 &write_expire = 5 min; -} - -redef capture_filters += { - ["dns"] = "port 53", - ["netbios-ns"] = "udp port 137", -}; - -# DPM configuration. -global dns_ports = { 53/udp, 53/tcp, 137/udp } &redef; -redef dpd_config += { [ANALYZER_DNS] = [$ports = dns_ports] }; - -global dns_udp_ports = { 53/udp, 137/udp } &redef; -global dns_tcp_ports = { 53/tcp } &redef; -redef dpd_config += { [ANALYZER_DNS_UDP_BINPAC] = [$ports = dns_udp_ports] }; -redef dpd_config += { [ANALYZER_DNS_TCP_BINPAC] = [$ports = dns_tcp_ports] }; - -# Default handling for peculiarities in DNS analysis. You can redef these -# again in your site-specific script if you want different behavior. -redef Weird::weird_action += { - ["DNS_AAAA_neg_length"] = Weird::WEIRD_FILE, - ["DNS_Conn_count_too_large"] = Weird::WEIRD_FILE, - ["DNS_NAME_too_long"] = Weird::WEIRD_FILE, - ["DNS_RR_bad_length"] = Weird::WEIRD_FILE, - ["DNS_RR_length_mismatch"] = Weird::WEIRD_FILE, - ["DNS_RR_unknown_type"] = Weird::WEIRD_FILE, - ["DNS_label_forward_compress_offset"] = Weird::WEIRD_FILE, - ["DNS_label_len_gt_name_len"] = Weird::WEIRD_FILE, - ["DNS_label_len_gt_pkt"] = Weird::WEIRD_FILE, - ["DNS_label_too_long"] = Weird::WEIRD_FILE, - ["DNS_name_too_long"] = Weird::WEIRD_FILE, - ["DNS_truncated_RR_rdlength_lt_len"] = Weird::WEIRD_FILE, - ["DNS_truncated_ans_too_short"] = Weird::WEIRD_FILE, - ["DNS_truncated_len_lt_hdr_len"] = Weird::WEIRD_FILE, - ["DNS_truncated_quest_too_short"] = Weird::WEIRD_FILE, -}; - -type dns_session_info: record { - id: count; - is_zone_transfer: bool; - last_active: time; # when we last saw activity - - # Indexed by query id, returns string annotation corresponding to - # queries for which no answer seen yet. - pending_queries: table[count] of string; -}; - -# Indexed by client and server. -global dns_sessions: table[addr, addr, count] of dns_session_info; -global num_dns_sessions = 0; - -const PTR_pattern = /[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+\.in-addr\.arpa/; - -# Keeps track of for which addresses we processed a PTR_scan event. -global did_PTR_scan_event: table[addr] of count &default = 0; - -# The following definitions relate to tracking when DNS records -# change and whether they do so in a consistent fashion. -type dns_response_record: record { - dns_name: string; # domain name in question - dns_type: count; # type of query - num_resp: count; # number of responses - resp_count: count; # how many responses have been registered - addrs: set[addr]; # addresses in response -}; - -global dns_history: table[string, count, count] of dns_response_record; - -global did_zone_transfer_notice: table[addr] of count &default = 0; - -# Sample known irregular domains. -redef bad_domain_resp += { "instacontent.net", "mirror-image.net", }; - -# Sample hostile domains. -redef hostile_domain_list += { "undernet.org", "afraid.org", }; - -global dns_log : file; - -event bro_init() - { - if ( logging ) - dns_log = open_log_file("dns"); - } - -event remove_name(name: string, qtype: count, id: count) - { - if ( [name, qtype, id] in dns_history ) - { - # We need to remove the dns_history record and the assosciated - # dns_consistency_info records. - - local drr = dns_history[name, qtype, id]; - local a: addr; - - for ( a in drr$addrs ) - delete drr$addrs[a]; - - delete dns_history[name, qtype, id]; - } - else if ( logging ) - print dns_log, fmt("ERROR in history session removal: %s/%d doesn't exist", name, qtype); - } - -# Returns the second-level domain, so for example an argument of "a.b.c.d" -# returns "c.d". -function second_level_domain(name: string): string - { - local split_on_dots = split(name, /\./); - local num_dots = length(split_on_dots); - - if ( num_dots <= 1 ) - return name; - - return fmt("%s.%s", split_on_dots[num_dots-1], split_on_dots[num_dots]); - } - -function insert_name(c: connection, msg: dns_msg, ans: dns_answer, a: addr) - { - local drr: dns_response_record; - - if ( [ans$query, ans$qtype, msg$id] !in dns_history ) - { # add record - drr$dns_name = ans$query; - drr$dns_type = ans$qtype; - - # Here we modified the expected number of addresses to allow - # for the number of answer RR's along with the provided - # additional RR's. - drr$num_resp = msg$num_answers+msg$num_addl; - drr$resp_count = 0; - add drr$addrs[a]; - - dns_history[ans$query, ans$qtype, msg$id] = drr; - - if ( ans$TTL < 0 sec ) - # Strangely enough, the spec allows this, - # though it's hard to see why! But because - # of that, we don't generate a Weird, we - # just change the TTL to 0. - ans$TTL = 0 sec; - - # Check the TTL, but allow a smidgen of skew to avoid - # possible race conditions. - schedule ans$TTL + 1 sec - { remove_name(ans$query, ans$qtype, msg$id) }; - } - else - { # extract record and do some counting - drr = dns_history[ans$query, ans$qtype, msg$id]; - - # In some broken records, the number of reported records is 0. - # This makes the test below fail, to 'fix' set to 1 ... - if ( drr$num_resp == 0 ) - drr$num_resp = 1; - - # Check if we have filled in the expected number of responses - # already - it should be > current responder count to allow - # for resolver timeouts. Addresses are only added if they - # are not already prsent. This comes at a slight performance - # cost. - if ( a !in drr$addrs ) - { - add drr$addrs[a]; - ++drr$resp_count; - dns_history[ans$query, ans$qtype, msg$id]=drr; - } - - if ( drr$num_resp >= drr$resp_count ) - return; - - if ( second_level_domain(ans$query) in bad_domain_resp ) - return; - - if ( ans$query in bad_host_resp ) - return; - - # Too many responses to the request, or some other - # inconsistency has been introduced. - - NOTICE([$note=ResolverInconsistency, $conn=c, - $msg=fmt("address inconsistency for %s, %s", ans$query, a), - $dst=a]); - } - } - -event expire_DNS_session(orig: addr, resp: addr, trans_id: count) - { - if ( [orig, resp, trans_id] in dns_sessions ) - { - local session = dns_sessions[orig, resp, trans_id]; - local last_active = session$last_active; - if ( network_time() > last_active + dns_session_timeout || - done_with_network ) - { - # Flush out any pending requests. - if ( logging ) - { - for ( query in session$pending_queries ) - print dns_log, fmt("%0.6f #%d %s", - network_time(), session$id, - session$pending_queries[query]); - - print dns_log, fmt("%.06f #%d finish", - network_time(), session$id); - } - - delete dns_sessions[orig, resp, trans_id]; - } - - else - schedule dns_session_timeout { - expire_DNS_session(orig, resp, trans_id) - }; - } - } - -function lookup_DNS_session(c: connection, trans_id: count): dns_session_info - { - local id = c$id; - local orig = id$orig_h; - local resp = id$resp_h; - - if ( [orig, resp, trans_id] !in dns_sessions ) - { - local session: dns_session_info; - session$id = ++num_dns_sessions; - session$last_active = network_time(); - session$is_zone_transfer = F; - - if ( logging ) - print dns_log, fmt("%.06f #%d %s start", - c$start_time, session$id, id_string(id)); - - dns_sessions[orig, resp, trans_id] = session; - - schedule 15 sec { expire_DNS_session(orig, resp, trans_id) }; - - append_addl(c, fmt("#%d", session$id)); - - return session; - } - - else - return dns_sessions[orig, resp, trans_id]; - } - -event sensitive_addr_lookup(c: connection, a: addr, is_query: bool) - { - local orig = c$id$orig_h; - local resp = c$id$resp_h; - local holding = 0; - - if ( orig in okay_to_lookup_sensitive_hosts ) - return; - - local session_id: string; - if ( [orig, resp, holding] in dns_sessions ) - session_id = fmt("#%d", dns_sessions[orig, resp, holding]$id); - else - session_id = "#?"; - - local id = fmt("%s > %s (%s)", orig, resp, session_id); - - if ( is_query ) - NOTICE([$note=SensitiveDNS_Lookup, $conn=c, - $msg=fmt("%s PTR lookup of %s", id, a), - $sub="PTR lookup"]); - else - NOTICE([$note=SensitiveDNS_Lookup, $conn=c, - $msg=fmt("%s name lookup of %s", id, a), - $sub="name lookup"]); - } - -function DNS_query_annotation(c: connection, msg: dns_msg, query: string, - qtype: count, is_zone_xfer: bool): string - { - local anno: string; - - if ( (qtype == PTR || qtype == ANY) && query == PTR_pattern ) - { - # convert PTR text to more readable form. - local a = ptr_name_to_addr(query); - if ( a in sensitive_lookup_hosts && ! is_zone_xfer ) - event sensitive_addr_lookup(c, a, T); - - anno = fmt("?%s %As", query_types[qtype], a); - } - else - anno = fmt("%s %s", query_types[qtype], query); - - if ( ! is_zone_xfer && - (msg$num_answers > 0 || msg$num_auth > 0 || msg$num_addl > 0) ) - anno = fmt("%s ", anno, - msg$num_answers, msg$num_auth, msg$num_addl); - - return anno; - } - - -event dns_zone_transfer_request(c: connection, session: dns_session_info, - msg: dns_msg, query: string) - { - session$is_zone_transfer = T; - - if ( ! is_tcp_port(c$id$orig_p) ) - event conn_weird("UDP_zone_transfer", c); - - local src = c$id$orig_h; - if ( src !in zone_transfers_okay && - ++did_zone_transfer_notice[src] == 1 ) - { - NOTICE([$note=ZoneTransfer, $src=src, $conn=c, - $msg=fmt("transfer of %s requested by %s", query, src)]); - } - } - -event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) - { - local id = c$id; - local orig = id$orig_h; - local resp = id$resp_h; - local session = lookup_DNS_session(c, msg$id); - local anno = DNS_query_annotation(c, msg, query, qtype, F); - - local report = fmt("%.06f #%d %s", network_time(), session$id, c$id$orig_h); - local q: string; - - if ( query_types[qtype] == "AXFR" ) - { - event dns_zone_transfer_request(c, session, msg, query); - - q = DNS_query_annotation(c, msg, query, qtype, T); - report = fmt("%s ?%s", report, q); - } - else - report = fmt("%s %s Trunc:%s Recurs:%s", - report, query_types[qtype], query, msg$TC, msg$RD); - - if ( logging ) - print dns_log, fmt("%s", report); - - # Check to see if this is a host or MX lookup for a designated - # hostile domain. - if ( check_domain_list && - (query_types[qtype] == "A" || query_types[qtype] == "MX") && - second_level_domain(query) in hostile_domain_list ) - { - NOTICE([$note=SensitiveDNS_Lookup, $conn=c, - $msg=fmt("%s suspicious domain lookup: %s", id, query)]); - } - - session$pending_queries[msg$id] = anno; - session$last_active = network_time(); - } - -event dns_rejected(c: connection, msg: dns_msg, - query: string, qtype: count, qclass: count) - { - local session = lookup_DNS_session(c, msg$id); - local code = DNS_code_types[msg$rcode]; - local id = msg$id; - - if ( id in session$pending_queries ) - { - if ( logging ) - print dns_log, fmt("%.06f #%d %s %s", network_time(), - session$id, - session$pending_queries[id], - code); - - delete session$pending_queries[id]; - } - - else if ( logging ) - { - if ( c$start_time == network_time() ) - print dns_log, fmt("%.06f #%d [?%s] %s", network_time(), - session$id, query, code); - else - print dns_log, fmt("%.06f #%d %s", network_time(), - session$id, code); - } - } - -event PTR_scan_summary(src: addr) - { - NOTICE([$note=DNS_PTR_Scan_Summary, $src=src, - $msg=fmt("%s totaled %d/%d un/successful PTR lookups", src, - distinct_rejected_PTR_requests[src], - distinct_answered_PTR_requests[src]), - $sub="final summary"]); - } - -event PTR_scan(src: addr) - { - ++did_PTR_scan_event[src]; - - if ( src !in allow_PTR_scans && src !in okay_to_lookup_sensitive_hosts ) - { - NOTICE([$note=DNS_PTR_Scan, $src=src, - $msg=fmt("%s has made %d/%d un/successful PTR lookups", - src, distinct_rejected_PTR_requests[src], - distinct_answered_PTR_requests[src]), - $sub="scan detected"]); - - schedule 1 day { PTR_scan_summary(src) }; - } - } - -function check_PTR_scan(src: addr) - { - if ( src !in did_PTR_scan_event && - distinct_rejected_PTR_requests[src] >= - distinct_answered_PTR_requests[src] * report_rejected_PTR_factor ) - event PTR_scan(src); - } - -function DNS_answer(c: connection, msg: dns_msg, - ans: dns_answer, annotation: string) - { - local is_answer = ans$answer_type == DNS_ANS; - local session = lookup_DNS_session(c, msg$id); - local report = - fmt("%.06f #%d %s", network_time(), session$id, c$id$orig_h); - local id = msg$id; - local query: string; - - if ( id in session$pending_queries ) - { - query = fmt("%s = ", session$pending_queries[id], - query_types[ans$qtype]); - delete session$pending_queries[id]; - report = fmt("%s %s", report, query); - } - - else if ( session$is_zone_transfer ) - { # need to provide the query directly. - query = fmt("", query_types[ans$qtype]); - report = fmt("%s ?%s", report, query); - } - - else - { - # No corresponding query. This can happen if it's - # already been deleted because we've already processed - # an answer to it; or if the session itself was timed - # out prior to this answer being generated. In the - # first case, we don't want to provide the query again; - # in the second, we do. We can determine that we're - # likely in the second case if either (1) this session - # was just now created, or (2) we're now processing the - # sole answer to the original query. - # - # However, for now we punt. - # - # if ( c$start_time == network_time() || - # (is_answer && msg$num_answers == 1) ) - # { - # query = DNS_query_annotation(c, msg, ans$query, ans$qtype, F); - # report = fmt("%s [?%s]", report, query); - # } - # else - # query = ""; - - query = fmt("", query_types[ans$qtype]); - report = fmt("%s %s", report, query); - } - - # Append a bunch of additional annotation. - report = fmt("%s %s RCode:%s AA=%s TR=%s %s/%s/%s/%s", - report, annotation, base_error[msg$rcode], msg$AA, msg$TC, - msg$num_queries, msg$num_answers, msg$num_auth, msg$num_addl ); - - local src = c$id$orig_h; - - if ( msg$rcode != 0 ) - { - if ( /\?(PTR|\*.*in-addr).*/ in query ) - ##### should check for private address - { - if ( ++distinct_PTR_requests[src, query] == 1 && - ++distinct_rejected_PTR_requests[src] >= - report_rejected_PTR_thresh ) - check_PTR_scan(src); - } - - report = fmt("%s %s", report, DNS_code_types[msg$rcode]); - } - - else if ( is_answer ) - { - if ( /\?(PTR|\*.*in-addr).*/ in query ) - { - if ( annotation in actually_rejected_PTR_anno ) - { - if ( ++distinct_PTR_requests[src, query] == 1 && - ++distinct_rejected_PTR_requests[src] >= - report_rejected_PTR_thresh ) - check_PTR_scan(src); - } - else - { - if ( ++distinct_PTR_requests[src, query] == 1 ) - ++distinct_answered_PTR_requests[src]; - } - } - } - - if ( logging ) - print dns_log, fmt("%s TTL=%g", report, ans$TTL); - - ### Note, DNS_AUTH and DNS_ADDL not processed. - - session$last_active = network_time(); - } - -event dns_A_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) - { - if ( a in sensitive_lookup_hosts ) - event sensitive_addr_lookup(c, a, F); - - DNS_answer(c, msg, ans, fmt("%As", a)); - - if ( resolver_consist_check ) - insert_name(c, msg, ans, a ); - - } - -event dns_NS_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string) - { - DNS_answer(c, msg, ans, fmt("%s", name)); - } - -event dns_CNAME_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string) - { - DNS_answer(c, msg, ans, fmt("%s %s", query_types[ans$qtype], name)); - } - -event dns_PTR_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string) - { - DNS_answer(c, msg, ans, fmt("%s", name)); - } - -event dns_SOA_reply(c: connection, msg: dns_msg, ans: dns_answer, soa: dns_soa) - { - DNS_answer(c, msg, ans, fmt("%s", soa$mname)); - } - -event dns_MX_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string, - preference: count) - { - DNS_answer(c, msg, ans, fmt("%s/%d", name, preference)); - } - -event dns_EDNS(c: connection, msg: dns_msg, ans: dns_answer) - { - DNS_answer(c, msg, ans, "<---?--->"); - } - - -# From here on down we need to modify the way that data is recorded. The -# standard resource record format is no longer universally applicable in -# that we may see modified structs or some number of value pairs that may take -# more flexability in reporting. - -event dns_EDNS_addl(c: connection, msg: dns_msg, ans: dns_edns_additional) - { - local session = lookup_DNS_session(c, msg$id); - local report = - fmt("%.06f #%d %s", network_time(), session$id, c$id$orig_h); - - if ( ans$is_query == 1 ) - report = fmt("%s ", report); - else - report = fmt("%s ", report); - - if ( logging ) - print dns_log, fmt("%s pldsize:%s RCode:%s VER:%s Z:%s", - report, ans$payload_size, - base_error[ans$extended_rcode], - ans$version, edns_zfield[ans$z_field]); - } - -event dns_TSIG_addl(c: connection, msg: dns_msg, ans: dns_tsig_additional) - { - local session = lookup_DNS_session(c, msg$id); - local report = - fmt("%.06f #%d %s", network_time(), session$id, c$id$orig_h); - - # Error handling with this is a little odd: number collision with EDNS. - # We set the collided value to the first private space number. gross. - local trans_error_num = (ans$rr_error == 16) ? 3842 : ans$rr_error; - - if ( ans$is_query == 1 ) - report = fmt("%s ", report); - else - report = fmt("%s ", report); - - if ( logging ) - print dns_log, fmt("%s name:%s alg:%s origID:%s RCode:%s", - report, ans$query, ans$alg_name, - ans$orig_id, base_error[trans_error_num]); - } diff --git a/policy.old/drop-adapt.bro b/policy.old/drop-adapt.bro deleted file mode 100644 index b599770ded..0000000000 --- a/policy.old/drop-adapt.bro +++ /dev/null @@ -1,74 +0,0 @@ -# $Id: drop-adapt.bro 6940 2009-11-14 00:38:53Z robin $ -# -# Adjust load level based on packet drops. -# - -@load load-level - -# Increase load-level if packet drops are successively 'count' times -# above 'threshold' percent. -const drop_increase_count = 5 &redef; -const drop_increase_threshold = 5.0 &redef; - -# Same for decreasing load-level. -const drop_decrease_count = 15 &redef; -const drop_decrease_threshold = 0.0 &redef; - -# Minimum time to wait after a load-level increase before new decrease. -const drop_decrease_wait = 20 mins &redef; - -global drop_last_stat: net_stats; -global drop_have_stats = F; -global drop_above = 0; -global drop_below = 0; - -global drop_last_increase: time = 0; - -event net_stats_update(t: time, ns: net_stats) - { - if ( drop_have_stats ) - { - local new_recvd = ns$pkts_recvd - drop_last_stat$pkts_recvd; - local new_dropped = - ns$pkts_dropped - drop_last_stat$pkts_dropped; - - local p = new_dropped * 100.0 / new_recvd; - - drop_last_stat = ns; - - if ( p >= 0 ) - { - if ( p >= drop_increase_threshold ) - { - if ( ++drop_above >= drop_increase_count ) - { - increase_load_level(); - drop_above = 0; - drop_last_increase = t; - } - } - else - drop_above = 0; - - if ( t - drop_last_increase < drop_decrease_wait ) - return; - - if ( p <= drop_decrease_threshold ) - { - if ( ++drop_below >= drop_decrease_count ) - { - decrease_load_level(); - drop_below = 0; - } - } - else - drop_below = 0; - - } - } - else - { - drop_have_stats = T; - drop_last_stat = ns; - } - } diff --git a/policy.old/drop.bro b/policy.old/drop.bro deleted file mode 100644 index b2e75fa269..0000000000 --- a/policy.old/drop.bro +++ /dev/null @@ -1,340 +0,0 @@ -# $Id:$ -# -# drop.bro implements a drop/restore policy termed "catch-and-release" -# whereby the first time an address is dropped, it is restored a while after -# the last connection attempt seen. If a connection attempt is subsequently -# seen, however, then the system is blocked again, and for a longer time. -# -# This policy has significant benefits when using Bro to update router -# ACLs for which: -# - The router has a limited number of ACLs slots. -# - You care about possible reuse of IP addresses by now-benign hosts, -# so don't want blocks to last forever. -# -# Original code by Jim Mellander, LBNL. -# Updated by Brian Tierney, LBNL and by Robin Sommer, ICSI. - -@load site - -module Drop; - -export { - redef enum Notice += { - # Connectivity with given address has been dropped. - AddressDropped, - - # A request to drop connectivity has been ignored. - AddressDropIgnored, - - # Connectivity with given address has been restored. - AddressRestored, - - AddressAlreadyDropped, # host is already dropped - - # Previously dropped host connects again. - AddressSeenAgain, - - # Previous offenders re-dropped or re-restored. - RepeatAddressDropped, - RepeatAddressRestored, - }; - - # True if we have the capability to drop hosts at all. - const can_drop_connectivity = F &redef; - - # True if we never want to drop local addresses. - const dont_drop_locals = T &redef; - - # True if we should use the catch-and-release scheme. If not then - # we simply drop addresses via the drop_connectivity_script and - # never restore them (they must be restored out-of-band). - const use_catch_release = F &redef; - - # Catch-and-release parameters. - - # Interval to wait for release following inactivity after - # first offense. - global drop_time = 5 min &redef; - - # For repeat offenders: if the total time a host has already been - # dropped reaches persistent_offender_time, we drop the host for - # long_drop_time. Setting persistent_offender_time to zero disables - # this functionality. - const persistent_offender_time = 2 hr &redef; - global long_drop_time = 12 hr &redef; - - # Scripts to perform the actual dropping/restore. They get the - # IP address as their first argument. - const drop_connectivity_script = "drop-connectivity" &redef; - const restore_connectivity_script = "restore-connectivity" &redef; - - const root_servers = { - a.root-servers.net, b.root-servers.net, c.root-servers.net, - d.root-servers.net, e.root-servers.net, f.root-servers.net, - g.root-servers.net, h.root-servers.net, i.root-servers.net, - j.root-servers.net, k.root-servers.net, l.root-servers.net, - m.root-servers.net, - } &redef; - - const gtld_servers = { - a.gtld-servers.net, b.gtld-servers.net, c.gtld-servers.net, - d.gtld-servers.net, e.gtld-servers.net, f.gtld-servers.net, - g.gtld-servers.net, h.gtld-servers.net, i.gtld-servers.net, - j.gtld-servers.net, k.gtld-servers.net, l.gtld-servers.net, - m.gtld-servers.net, - } &redef; - - const never_shut_down = { - root_servers, gtld_servers, - } &redef; - - const never_drop_nets: set[subnet] &redef; - - # Drop the connectivity for the address. "msg" gives a reason. - # It returns a copy of the NOTICE generated for the drop, which - # gives more information about the kind of dropping performed. - # If the notice type is NoticeNone, the drop was not successful - # (e.g., because this Bro instance is not configured to do drops.) - global drop_address: function(a: addr, msg: string) : notice_info; - - # The following events are used to communicate information about the - # drops, in particular for C&R in the cluster setting. - - # Address has been dropped. - global address_dropped: event(a: addr); - - # Raised when an IP is restored. - global address_restored: event(a: addr); - - # Raised when an that was dropped in the past is no - # longer monitored specifically for new connections. - global address_cleared: event(a: addr); - - const debugging = F &redef; - global debug_log: function(msg: string); -} - -type drop_rec: record { - tot_drop_count: count &default=0; - tot_restore_count: count &default=0; - actual_restore_count: count &default=0; - tot_drop_time: interval &default=0secs; - last_timeout: interval &default=0secs; -}; - -global clear_host: function(t: table[addr] of drop_rec, a: addr): interval; - -global drop_info: table[addr] of drop_rec - &read_expire = 1 days &expire_func=clear_host &persistent; - -global last_notice: notice_info; - -function do_notice(n: notice_info) - { - last_notice = n; - NOTICE(n); - } - -function dont_drop(a: addr) : bool - { - return ! can_drop_connectivity || a in never_shut_down || - a in never_drop_nets || (dont_drop_locals && is_local_addr(a)); - } - -function is_dropped(a: addr) : bool - { - if ( a !in drop_info ) - return F; - - local di = drop_info[a]; - - if ( di$tot_drop_count < di$tot_restore_count ) - { # This shouldn't happen. - # FIXME: We need an assert(). - print "run-time error: more restores than drops!"; - return F; - } - - return di$tot_drop_count > di$tot_restore_count; - } - -global debug_log_file: file; - -function debug_log(msg: string) - { - if ( ! debugging ) - return; - - print debug_log_file, - fmt("%.6f [%s] %s", network_time(), peer_description, msg); - } - -event bro_init() - { - if ( debugging ) - { - debug_log_file = - open_log_file(fmt("drop-debug.%s", peer_description)); - set_buf(debug_log_file, F); - } - } - -function do_direct_drop(a: addr, msg: string) - { - if ( msg != "" ) - msg = fmt(" (%s)", msg); - - if ( a !in drop_info ) - { - local tmp: drop_rec; - drop_info[a] = tmp; - } - - local di = drop_info[a]; - - if ( is_dropped(a) ) - # Already dropped. Nothing to do. - do_notice([$note=Drop::AddressAlreadyDropped, $src=a, - $msg=fmt("%s%s", a, msg)]); - else - { - system(fmt("%s %s", Drop::drop_connectivity_script, a)); - - debug_log(fmt("sending drop for %s", a)); - event Drop::address_dropped(a); - - if ( di$tot_drop_count == 0 ) - do_notice([$note=Drop::AddressDropped, $src=a, - $msg=fmt("%s%s", a, msg)]); - else - { - local s = fmt("(%d times)", di$tot_drop_count + 1); - do_notice([$note=Drop::RepeatAddressDropped, - $src=a, $n=di$tot_drop_count+1, - $msg=fmt("%s%s %s", a, msg, s), $sub=s]); - } - } - - ++di$tot_drop_count; - debug_log(fmt("dropped %s: tot_drop_count=%d tot_restore_count=%d", - a, di$tot_drop_count, di$tot_restore_count)); - } - -# Restore a previously dropped address. -global do_restore: function(a: addr, force: bool); - -event restore_dropped_address(a: addr) - { - do_restore(a, F); - } - -function do_catch_release_drop(a: addr, msg: string) - { - do_direct_drop(a, msg); - - local di = drop_info[a]; - - local t = (persistent_offender_time != 0 sec && - di$tot_drop_time >= persistent_offender_time) ? - long_drop_time : drop_time; - - di$tot_drop_time += t; - di$last_timeout = t; - - schedule t { restore_dropped_address(a) }; - } - -function do_restore(a: addr, force: bool) - { - if ( a !in drop_info ) - return; - - local di = drop_info[a]; - ++drop_info[a]$tot_restore_count; - debug_log(fmt("restored %s: tot_drop_count=%d tot_restore_count=%d force=%s", a, drop_info[a]$tot_drop_count, drop_info[a]$tot_restore_count, force)); - - if ( di$tot_drop_count == di$tot_restore_count || force ) - { - ++di$actual_restore_count; - system(fmt("%s %s", Drop::restore_connectivity_script, a)); - - debug_log(fmt("sending restored for %s", a)); - event Drop::address_restored(a); - - local t = di$last_timeout; - - if ( di$actual_restore_count == 1 ) - { - local s1 = fmt("(timeout %.1f)", t); - do_notice([$note=Drop::AddressRestored, $src=a, - $msg=fmt("%s %s", a, s1), $sub=s1]); - } - - else - { - local s2 = fmt("(%d times, timeout %.1f)", - di$actual_restore_count, t); - do_notice([$note=Drop::RepeatAddressRestored, $src=a, - $n=di$tot_restore_count, - $msg=fmt("%s %s", a, s2), $sub=s2]); - } - } - } - -function clear_host(t: table[addr] of drop_rec, a: addr): interval - { - if ( is_dropped(a) ) - # Restore address. - do_restore(a, T); - - debug_log(fmt("sending cleared for %s", a)); - event Drop::address_cleared(a); - - return 0 secs; - } - -# Returns true if drop was successful (or IP was already dropped). -function drop_address(a: addr, msg: string) : notice_info - { - debug_log(fmt("drop_address(%s, %s)", a, msg)); - - last_notice = [$note=NoticeNone]; - - if ( dont_drop(a) ) - do_notice([$note=AddressDropIgnored, $src=a, - $msg=fmt("ignoring request to drop %s (%s)", a, msg)]); - else if ( use_catch_release ) - do_catch_release_drop(a, msg); - else - do_direct_drop(a, msg); - - if ( last_notice$note == NoticeNone ) - print "run-time error: drop_address did not raise a NOTICE"; - - return last_notice; - } - -event new_connection(c: connection) - { - if ( ! can_drop_connectivity ) - return; - - # With Catch & Release, 1 connection from a previously dropped system - # triggers an immediate redrop. - if ( ! use_catch_release ) - return; - - local a = c$id$orig_h; - - if ( a !in drop_info ) - # Never dropped. - return; - - local di = drop_info[a]; - if ( is_dropped(a) ) - # Still dropped. - return; - - NOTICE([$note=AddressSeenAgain, $src=a, - $msg=fmt("%s seen again after release", a)]); - } diff --git a/policy.old/dyn-disable.bro b/policy.old/dyn-disable.bro deleted file mode 100644 index b1b5bd937e..0000000000 --- a/policy.old/dyn-disable.bro +++ /dev/null @@ -1,53 +0,0 @@ -# $Id: dyn-disable.bro,v 1.1.4.3 2006/05/31 01:52:02 sommer Exp $ -# -# When this script is loaded, analyzers that raise protocol_violation events -# are disabled for the affected connection. - -# Note that this a first-shot solution. Eventually, we should make the -# disable-decision more fine-grained/sophisticated. - -@load conn -@load notice - -module DynDisable; - -export { - redef enum Notice += { - ProtocolViolation - }; - - # Ignore violations which go this many bytes into the connection. - const max_volume = 10 * 1024 &redef; -} - -global conns: table[conn_id] of set[count]; - -event protocol_violation(c: connection, atype: count, aid: count, - reason: string) - { - if ( c$id in conns && aid in conns[c$id] ) - return; - - local size = c$orig$size + c$resp$size; - - if ( max_volume > 0 && size > max_volume ) - return; - - # Disable the analyzer that raised the last core-generated event. - disable_analyzer(c$id, aid); - - NOTICE([$note=ProtocolViolation, $conn=c, - $msg=fmt("%s analyzer %s disabled due to protocol violation", - id_string(c$id), analyzer_name(atype)), - $sub=reason, $n=atype]); - - if ( c$id !in conns ) - conns[c$id] = set(); - - add conns[c$id][aid]; - } - -event connection_state_remove(c: connection) - { - delete conns[$id=c$id]; - } diff --git a/policy.old/file-flush.bro b/policy.old/file-flush.bro deleted file mode 100644 index 481d078e59..0000000000 --- a/policy.old/file-flush.bro +++ /dev/null @@ -1,18 +0,0 @@ -# $Id: file-flush.bro 786 2004-11-24 08:25:16Z vern $ - -# Causes all files to be flushed every file_flush_interval seconds. -# Useful if you want to poke through the log files in real time, -# particularly if network traffic is light. - -global file_flush_interval = 10 sec &redef; - -event file_flush_event() - { - flush_all(); - schedule file_flush_interval { file_flush_event() }; - } - -event bro_init() - { - schedule file_flush_interval { file_flush_event() }; - } diff --git a/policy.old/finger.bro b/policy.old/finger.bro deleted file mode 100644 index 7765ce45c6..0000000000 --- a/policy.old/finger.bro +++ /dev/null @@ -1,69 +0,0 @@ -# $Id: finger.bro 4758 2007-08-10 06:49:23Z vern $ - -module Finger; - -export { - const hot_names = { - "root", "lp", "uucp", "nuucp", "demos", "operator", "sync", - "r00t", "tutor", "tour", "admin", "system", "guest", "visitor", - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", - } &redef; - - const max_finger_request_len = 80 &redef; -} - -redef capture_filters += { ["finger"] = "port finger" }; - -# DPM configuration. -global finger_ports = { 79/tcp } &redef; -redef dpd_config += { [ANALYZER_FINGER] = [$ports = finger_ports] }; - -function public_user(user: string): bool - { - return T; - } - -function authorized_client(host: addr): bool - { - return T; - } - -event finger_request(c: connection, full: bool, username: string, hostname: string) - { - local id = c$id; - local request: string; - - if ( hostname != "" ) - request = cat(username, "@", hostname); - else - request = username; - - if ( byte_len(request) > max_finger_request_len ) - { - request = fmt("%s...", sub_bytes(request, 1, max_finger_request_len)); - ++c$hot; - } - - if ( hostname != "" ) - ++c$hot; - - if ( username in hot_names ) - ++c$hot; - - local req = request == "" ? "ALL" : fmt("\"%s\"", request); - - if ( full ) - req = fmt("%s (/W)", req); - - if ( c$addl != "" ) - # This is an additional request. - req = fmt("(%s)", req); - - append_addl_marker(c, req, " *"); - } - -function is_finger_conn(c: connection): bool - { - return c$id$resp_p == finger; - } - diff --git a/policy.old/firewall.bro b/policy.old/firewall.bro deleted file mode 100644 index 59a92206b4..0000000000 --- a/policy.old/firewall.bro +++ /dev/null @@ -1,195 +0,0 @@ -# $Id: firewall.bro 4758 2007-08-10 06:49:23Z vern $ -# -# Firewall-like rules. - -@load notice -@load conn -@load ftp - -module Firewall; - -export { - type action: enum { ALLOW, DENY }; - type cmp: enum { EQ, NE }; - - type rule: record { - label: string &default = ""; - orig: subnet &default = 0.0.0.0/0; - orig_set: set[addr] &optional; - orig_cmp: cmp &default = EQ; - orig_p: port &default = 0/tcp; - orig_p_cmp: cmp &default = EQ; - resp: subnet &default = 0.0.0.0/0; - resp_set: set[addr] &optional; - resp_cmp: cmp &default = EQ; - resp_p: port &default = 0/tcp; - resp_p_cmp: cmp &default = EQ; - prot: transport_proto &default = unknown_transport; - prot_cmp: cmp &default = EQ; - state: string &default = ""; - state_cmp: cmp &default = EQ; - is_ftp: bool &default = F; - - action: action &default = ALLOW; - }; - - redef enum Notice += { - DenyRuleMatched - }; - - global begin: function(c: connection); - global match_rule: function(c: connection, r: rule); -} - -const log_file = open_log_file("firewall") &redef; - -global stop_matching = F; - -function do_match(c: connection, r: rule): bool - { - if ( r$orig_cmp == EQ ) - { - if ( r?$orig_set ) - { - if ( c$id$orig_h !in r$orig_set && c$id$orig_h !in r$orig ) - return F; - } - else - { - if ( c$id$orig_h !in r$orig ) - return F; - } - } - else - { - if ( r?$orig_set ) - { - if ( c$id$orig_h in r$orig_set || c$id$orig_h in r$orig ) - return F; - } - else - { - if ( c$id$orig_h in r$orig ) - return F; - } - } - - if ( r$resp_cmp == EQ ) - { - if ( r?$resp_set ) - { - if ( c$id$resp_h !in r$resp_set && c$id$resp_h !in r$resp ) - return F; - } - else - { - if ( c$id$resp_h !in r$resp ) - return F; - } - } - else - { - if ( r?$resp_set ) - { - if ( c$id$resp_h in r$resp_set || c$id$resp_h in r$resp ) - return F; - } - else - { - if ( c$id$resp_h in r$resp ) - return F; - } - } - - if ( r$orig_p != 0/tcp ) - { - if ( r$orig_p_cmp == EQ ) - { - if ( c$id$orig_p != r$orig_p ) - return F; - } - else - if ( c$id$orig_p == r$orig_p ) - return F; - } - - if ( r$resp_p != 0/tcp ) - { - if ( r$resp_p_cmp == EQ ) - { - if ( c$id$resp_p != r$resp_p ) - return F; - } - else - if ( c$id$resp_p == r$resp_p ) - return F; - } - - if ( r$state != "" ) - { - local state = conn_state(c, get_port_transport_proto(c$id$orig_p)); - if ( r$state_cmp == EQ ) - { - if ( state != r$state ) - return F; - } - else - if ( state == r$state ) - return F; - } - - if ( r$prot != unknown_transport ) - { - local proto = get_port_transport_proto(c$id$orig_p); - if ( r$prot_cmp == EQ ) - { - if ( proto != r$prot ) - return F; - } - else - if ( proto == r$prot ) - return F; - } - - if ( r$is_ftp && ! FTP::is_ftp_data_conn(c) ) - return F; - - return T; - } - - -function report_violation(c: connection, r:rule) - { - local trans = get_port_transport_proto(c$id$orig_p); - local state = conn_state(c, trans); - - NOTICE([$note=DenyRuleMatched, - $msg=fmt("%s %s", - id_string(c$id), trans), $conn=c, $sub=r$label]); - append_addl(c, fmt("<%s>", r$label)); - record_connection(log_file, c); - } - -function begin(c: connection) - { - stop_matching = F; - } - -function match_rule(c: connection, r: rule) - { - if ( stop_matching ) - return; - - if ( do_match(c, r) ) - { - stop_matching = T; - - if ( r$action == DENY ) - report_violation(c, r); - } - } - -event bro_init() - { - set_buf(log_file, F); - } diff --git a/policy.old/flag-irc.bro b/policy.old/flag-irc.bro deleted file mode 100644 index 60d687bff7..0000000000 --- a/policy.old/flag-irc.bro +++ /dev/null @@ -1,18 +0,0 @@ -# $Id: flag-irc.bro 4758 2007-08-10 06:49:23Z vern $ -# -# include this module to flag various forms of IRC access. - -@load ftp - -redef FTP::hot_files += - /.*eggdrop.*/ - | /.*eggsun.*/ - ; - -redef Hot::flag_successful_inbound_service: table[port] of string += { - [[6666/tcp, 6667/tcp]] = "inbound IRC", -}; - -redef Hot::hot_dsts: table[addr] of string += { - [bitchx.com] = "IRC source sites", -}; diff --git a/policy.old/flag-warez.bro b/policy.old/flag-warez.bro deleted file mode 100644 index 6781252338..0000000000 --- a/policy.old/flag-warez.bro +++ /dev/null @@ -1,11 +0,0 @@ -# $Id: flag-warez.bro 416 2004-09-17 03:52:28Z vern $ -# -# include this module to flag various forms of Warez access. - -@load hot-ids -@load ftp - -redef FTP::hot_files += /.*[wW][aA][rR][eE][zZ].*/ ; - -redef always_hot_ids += { "warez", "hanzwarez", "zeraw", }; -redef hot_ids += { "warez", "hanzwarez", "zeraw", }; diff --git a/policy.old/frag.bro b/policy.old/frag.bro deleted file mode 100644 index fcced8cd9a..0000000000 --- a/policy.old/frag.bro +++ /dev/null @@ -1,6 +0,0 @@ -# Capture TCP fragments, but not UDP (or ICMP), since those are a lot more -# common due to high-volume, fragmenting protocols such as NFS :-(. - -redef capture_filters += { ["frag"] = "(ip[6:2] & 0x3fff != 0) and tcp" }; - -redef frag_timeout = 5 min; diff --git a/policy.old/ftp-reply-pattern.bro b/policy.old/ftp-reply-pattern.bro deleted file mode 100644 index 59c507978e..0000000000 --- a/policy.old/ftp-reply-pattern.bro +++ /dev/null @@ -1,1317 +0,0 @@ -# $Id: ftp-reply-pattern.bro 6 2004-04-30 00:31:26Z jason $ - -@load ftp-anonymizer - -redef process_ftp_reply_by_message_pattern = T; - - -# A line of reply message is split into fields with the following -# regular expression. The regular expression defines the pattern of -# field separators. Basically a field separator is blank space -# enclosed by optional punctuations. - -const ftp_msg_field_separator = - /@@BOL@@ [[:space:][:punct:]]*( @@EOL@@)?/ - | /[[:space:][:punct:]]+/ - | /[[:space:][:punct:]]* @@EOL@@/ - ; - -# Type *msg_format_info* defines a message format extracted from -# messages. - -type msg_format_info: record { - parts: string_array; - code: count; - msg: string; # one of the original messages - hit: count; # number of messages that match the pattern -}; - -type msg_format_group: table[string] of msg_format_info; -global msg_format_groups: table[string] of msg_format_group; - - -# A pattern string (derived from one or more message formats) contains -# fields enclosed by '|': e.g. -# -# "211 @@BOL@@ |connected| |to| |~ domain, ~ ip| @@EOL@@" -# -# Thus we the field separator can be defined by the following pattern: -# everything up to the first '|', after the last '|', or between two -# adjacent '|'s in the middle. - -const ftp_pattern_field_separator = - /@@BOL@@ @@EOL@@/ - | /@@BOL@@ [^|]*\|/ - | /\|[^|]+\|/ - | /\|[^|]* @@EOL@@/ - ; - -# A message pattern is very similar to a message format, except that -# the former is for message pattern matching and thus is used in a -# different phase than a message format, which is used in pattern -# extraction. - -type msg_pattern_info: record { - code: count; - str: string; - num_parts: count; - parts: string_array; - sep: string_array; - tok: string_array; - hit: count; -}; - -type msg_pattern_group: table[string] of msg_pattern_info; -global msg_pattern_groups: table[string] of msg_pattern_group; - - -# Here starts patterns of individual fields (numbers, ip address, domain -# name, etc.) in the reply message: - -# Numbers (including float numbers and negative numbers) -const ftp_number_pat = /[\-]?[0-9]+(\.[0-9]+)?/; - -# English words (including 's and 't) -# const ftp_word_pat = - /[[:alpha:]]*('m|'re|[[:alpha:]]'s|s'|n't|'d|'ve|'ll)|[[:alpha:]]+/ - ; - -# File modes in ls -l (seen in replies for STAT) -const ftp_file_mode_pat = /[ld\-]([r-][w-][xs-]){3}/; - -# FTP server version string -const ftp_server_version_pat = /[a-zA-Z0-9]+([\.\-_][a-zA-Z0-9]+)+/ &redef; - -# FTP path name -# -# As it is not clear how to define a pattern for path names, it is -# defined in two aspects: first, we define a pattern for strings that -# are path names *almost for sure*: - -const ftp_path_pat = /\/.+\/.*/ - | /README/ - | /.*\.(gz|tar|Z|ps|pdf)/ # TODO: add other extensions - | /[A-Z]:[\\\/].*/ # a path name almost for sure - ; - -# Second, we define a pattern for strings that can possibly be a path name: -# const ftp_file_name_pat = /[[:print:]]+/; -# -# Together, we assume that -# Set(ftp_path_pat) <= Set(path names) <= Set(ftp_file_name_pat) - -# DOS file names -const ftp_dos_path_pat = /[A-Z]:[\\\/].*/; - - -# Finally, a table of message field patterns -const ftp_msg_part_patterns = { - ["~ num"] = ftp_number_pat, - ["~ port"] = ftp_port_pat, - ["~ ip"] = ftp_ip_pat, - ["~ domain"] = ftp_domain_name_pat, - ["~ file_mode"] = ftp_file_mode_pat, - ["~ time"] = /[0-9]{2}:[0-9]{2}(:[0-9]{2})?(am|pm)?/, - ["~ day"] = /Mon|Tue|Wed|Thu|Fri|Sat|Sun/, - ["~ month"] = /Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec/, - ["~ ip,port"] = /[0-9]{1,3}(\.[0-9]{1,3}){3},[0-9]+/, - ["~ ip:port"] = /[0-9]{1,3}(\.[0-9]{1,3}){3}:[0-9]+/, - ["~ email"] = /[[:alnum:]\-\._]+@([\-0-9a-zA-Z]+\.)*[\-0-9a-zA-Z]+/, - ["~ path"] = ftp_path_pat, - ["~ url"] = /http:\/\/.+/, -} &redef; - - -# One critical issue in understanding an FTP reply message is to -# recognize the request arguments in messages. The argument of an FTP -# request may appear in various forms in the reply message, -# e.g. argument "/abc//def/" may appear as "/abc/def/" (eliminate -# duplicat /), "/abc/def" (w/o last /), or even "def" (base file name -# only). - -# Type *ftp_arg_variant* defines the set of variants of an argument, -# and function *expand_ftp_arg_variants* expands an argument to -# its variants. - -type ftp_arg_variants: record { - arg: string; # the argument - path: string; # after eliminating options - norm_path: string; # normalized path, after eliminating dup slashes - abs_path: string; # the absolute path - base_path: string; # the base file name only, without the directory part -}; - - -# Trace-specific anonymization of replies -# 1. Whether function anonymize_trace_specific_reply is defined: -const trace_specific_reply_anonymization = F &redef; - -# 2. Result of message anonymization -type ftp_reply_anon_result: record { - anonymized: bool; - msg: string; -}; - -# 3. The trace-specific function (to be defined externally) -global anonymize_trace_specific_reply: - function(session: ftp_session_info, code: count, msg: string, - cmd_arg: ftp_cmd_arg, - arg_var: ftp_arg_variants): ftp_reply_anon_result; - - -# Other global states: - -# Reply messages that are entirely stripped out (e.g. server banner message) -global msg_stripped_out: set[string]; - -# Remember wildcard matches to suppress the number of outputs -global all_wildcard_matches: set[string, string]; - - -# PART I. Message pattern extraction - -function init_msg_format_info(parts: string_array, code: count, msg: string, level: count): msg_format_info - { - return [$parts = parts, - $code = code, - $msg = msg, - $hit = 0]; - } - - -# Whether the pattern defined by *parts* is a sub-pattern of -# *fmt_parts*. - -function match_msg_format(fmt_parts: string_array, parts: string_array): bool - { - if ( length(fmt_parts) != length(parts) ) - return F; - - for ( i in fmt_parts ) - { - if ( i % 2 == 1 ) - { - local t1 = fmt_parts[i]; - local t2 = parts[i]; - - if ( t1 == t2 || t1 == "~ *" || - (t1 == "~ path" && - (t2 == ftp_file_name_pat || t2 == "~ num")) ) - ; # t2 matches t1 - else - return F; - } - } - - return T; - } - - -# Abstract msg_parts[k]. The whole msg_parts is passed because the -# function needs to look at the context to decide whether a pattern is -# applicable (in the case of version pattern). - -function abstract_msg_part(msg_parts: string_array, k: count, other_pat: table[string] of string): string - { - local part = msg_parts[k]; - local abs_part: string; - - if ( part in other_pat ) - abs_part = other_pat[part]; - else if ( k > 2 && - msg_parts[int_to_count(k-2)] == /[Vv]er(sion)?|[Rr]elease|.*ftpd.*|Server|Process/ && - part == ftp_server_version_pat && - part != ftp_domain_name_pat ) - abs_part = "~ version"; - else if ( part == ftp_msg_part_patterns["~ path"] && - part == ftp_file_name_pat ) - abs_part = "~ path"; - else - { - local known_pattern = 0; - - for ( pat_ty in ftp_msg_part_patterns ) - if ( part == ftp_msg_part_patterns[pat_ty] ) - { - ++known_pattern; - abs_part = pat_ty; - } - if ( known_pattern > 1 ) - print ftp_anon_log, - fmt("ERROR: ambiguous ftp msg part pattern: %s", part); - if ( known_pattern != 1 ) - abs_part = part; - } - - return abs_part; - } - - -# Transform a message format to a pattern string. - -function fmt_parts_to_string(parts: string_array): string - { - local p: string_array; - local num_parts = length(parts); - for ( i in parts ) - { - local s = parts[i]; - - if ( i == 1 || i == num_parts ) - p[i] = ""; - else if ( i % 2 == 1 ) - p[i] = string_cat("|", to_lower(s), "|"); - else - p[i] = " "; - } - return string_cat("@@BOL@@", cat_string_array(p), "@@EOL@@"); - } - - -# Extract the format of a message, if it does not match any known -# format. The message is already splitted into *msg_parts*, and the -# *act_msg* is only used for logging and debugging. Parameter -# *other_pat* defines an instance-specific mapping from strings to -# field types (e.g. "~ cmd", "~ arg"). For example, when "/fileA" is -# the argument of the corresponding FTP requests, other_pat["/fileA"] -# = "~ arg". - -function extract_ftp_reply_pattern(code: count, act_msg: string, msg_parts: string_array, - other_pat: table[string] of string, - session: ftp_session_info): bool - { - local num_parts = length(msg_parts); - - # Abstract each part of the message. - local abs_parts: string_array; - for ( i in msg_parts ) - { - if ( i % 2 == 1 ) - abs_parts[i] = abstract_msg_part(msg_parts, i, other_pat); - else - abs_parts[i] = msg_parts[i]; - } - - # Derive the abstract message format - local abs_msg = fmt_parts_to_string(abs_parts); - - # Locate the corresponding format group - local ind = fmt("%3d %3d", code, num_parts); - local fmt_group: msg_format_group; - - if ( ind in msg_format_groups ) - fmt_group = msg_format_groups[ind]; - else - msg_format_groups[ind] = fmt_group; - - # Check existing message formats - if ( abs_msg in fmt_group ) - { - ++fmt_group[abs_msg]$hit; - return F; - } - - local the_fmt = init_msg_format_info(abs_parts, code, - fmt("%s: %s", id_string(session$connection_id), act_msg), 1); - the_fmt$hit = 1; - - # Check whether it is a sub-format of a known format, or vice versa - - # Whether the_fmt is a sub-format of another format - local sub_format = F; - - # Which other formats are sub-formats of the_fmt - local sub_format_set: set[string]; - - for ( fm2 in fmt_group ) - { - local f2 = fmt_group[fm2]; - if ( match_msg_format(f2$parts, abs_parts) ) - { - sub_format = T; # abs_parts is a sub-format of f2 - ++f2$hit; - } - else if ( match_msg_format(abs_parts, f2$parts) ) - add sub_format_set[fm2]; - else - ; # do nothing - } - - # Do not add the format if it is a sub-format of another one. - if ( ! sub_format ) - { - fmt_group[abs_msg] = the_fmt; - - # remove sub-formats of this message - for ( fm3 in sub_format_set ) - { - the_fmt$hit = the_fmt$hit + fmt_group[fm3]$hit; - delete fmt_group[fm3]; - } - } - - return T; - } - -function print_msg_format(the_log: file, ind: string, m: string, f: msg_format_info) - { - local lm = to_string_literal(m); - if ( lm != m ) - print the_log, fmt("special_character_in_pattern: \"%s\"", lm); - local fm = fmt("%d %s", f$code, lm); - local pat_ind = fmt("%3d %3d", f$code, length(f$parts)); - - print the_log, fmt("reply_pattern: $%s$ \"%s\", # \"%s\"", - ind, fm, f$msg); - - if ( pat_ind in msg_pattern_groups && fm in msg_pattern_groups[pat_ind] ) - print the_log, fmt("ERROR: pattern_already_exists: \"%s\"", fm); - } - -event bro_done() - { - for ( ind in msg_format_groups ) - { - local fmt_group = msg_format_groups[ind]; - for ( m2 in fmt_group ) - print_msg_format(ftp_anon_log, ind, m2, fmt_group[m2]); - } - } - - -# PART II. Read and parse patterns - -type msg_pattern_result: record { - valid: bool, - msg_pat: msg_pattern_info, -}; - - -# Parse message pattern string -- put the separators in and -# tokens in . - -function parse_msg_format(fm: string): msg_pattern_result - { - local msg_pat: msg_pattern_info; - local ret = [$valid = F, $msg_pat = msg_pat]; - - # Separate the reply code from the rest of the pattern string - local code_fmt = split1(fm, / /); - local sep: string_array; - local tok: string_array; - - msg_pat$code = to_count(code_fmt[1]); - msg_pat$str = fm; - # print ftp_anon_log, fmt("msg_format: %d \"%s\"", msg_pat$code, msg_pat$str); - msg_pat$sep = sep; - msg_pat$tok = tok; - msg_pat$hit = 0; - - # Split the pattern string with the pattern field separator - local parts = split_all(code_fmt[2], ftp_pattern_field_separator); - local num_parts = length(parts); - msg_pat$parts = parts; - msg_pat$num_parts = num_parts; - - for ( i in parts ) - { - local s = parts[i]; - local j: count; - if ( i % 2 == 0 ) - { - j = int_to_count(i / 2); - sep[j] = s; - } - else if ( i > 1 && i < num_parts ) - { - j = int_to_count((i - 1) / 2); - tok[j] = s; - } - else - ; # do nothing - } - - ret$valid = T; - return ret; - } - - -# Parse the pattern string and insert the pattern into -# msg_pattern_groups. - -function process_predefined_msg_format(f: string): bool - { - local r: msg_pattern_result; - r = parse_msg_format(f); - if ( ! r$valid ) - return F; - local msg_pat = r$msg_pat; - - local pat_ind = fmt("%3d %3d", msg_pat$code, msg_pat$num_parts); - - local pat_group: msg_pattern_group; - if ( pat_ind !in msg_pattern_groups ) - msg_pattern_groups[pat_ind] = pat_group; - else - pat_group = msg_pattern_groups[pat_ind]; - - if ( msg_pat$str in pat_group ) - return F; # there should not be duplicates - pat_group[msg_pat$str] = msg_pat; - - return T; - } - -const ftp_msg_format_white_list: set[string] = {} &redef; - -event bro_init() - { - for ( f in ftp_msg_format_white_list ) - process_predefined_msg_format(f); - } - - -# PART III. Merge message patterns - -# moved to ftp-merge-pattern.bro - -# PART IV. Message pattern matching - -# Note that $parts is not redundant with $pat, because each field in -# $pat may contain multiple patterns, as in -# -# "211 @@BOL@@ |connected| |to| |~ domain, ~ ip| @@EOL@@" -# -# $parts tells whether "~ domain" or "~ ip" is matched. - -type msg_pattern_match_result: record { - valid: bool; - pat: msg_pattern_info; # the pattern matched - parts: string_array; # the matched pattern of each part -}; - - -# Return -1 if t1 is more specific than t2, 1 if vice versa, and 0 if -# t1 equals to t2 or if t1 and t2 are incomparable. - -function cmp_pattern_part(t1: string, t2: string): int - { - if ( t1 == t2 ) return 0; - - local ret: int = 0; - - if ( t1 != /~ .*/ || t2 != /~ .*/ ) - { - if ( t2 == /~ .*/ ) ret = -1; # t1 < t2 - if ( t1 == /~ .*/ ) ret = 1; # t2 < t1 - } - else if ( t1 == /~ (arg|cmd)/ || t2 == /~ (arg|cmd)/ ) - { - if ( t2 != /~ (arg|cmd)/ ) ret = -1; # t1 < t2 - if ( t1 != /~ (arg|cmd)/ ) ret = 1; # t2 < t1 - } - else if ( t1 == "~ ip" && t2 == "~ domain" ) - ret = -1; - else if ( t1 == "~ domain" && t2 == "~ ip" ) - ret = 1; - else if ( t1 == "~ *" || t2 == "~ *" ) - { - if ( t1 != "~ *" ) ret = -1; - if ( t2 != "~ *" ) ret = 1; - } - - # print ftp_anon_log, - # fmt("compare pattern part: \"%s\" vs. \"%s\" = %d", t1, t2, ret); - - if ( ret == 0 ) - print ftp_anon_log, - fmt("ERROR: cannot compare pattern part: \"%s\" vs. \"%s\"", t1, t2); - return ret; - } - - -# Which pattern is more specific, returns -1 if m1 < m2, ... - -function cmp_msg_pattern_match(m1: msg_pattern_match_result, m2: msg_pattern_match_result): int - { - local b1 = F; # whether part of m1 is more specific - local b2 = F; # whether part of m2 is more specific - - for ( i in m1$parts ) - { - local c = cmp_pattern_part(m1$parts[i], m2$parts[i]); - if ( c < 0 ) b1 = T; - if ( c > 0 ) b2 = T; - } - if ( b1 && ! b2 ) return -1; - if ( ! b1 && b2 ) return 1; - - print ftp_anon_log, - fmt("ERROR: cannot compare pattern match: \"%s\" vs. \"%s\"", m1$pat$str, m2$pat$str); - return 0; - } - - -# Whether data matches pat. Parameter aux_pat contains a set of (data, -# pat) pairs in addition to the predefined patterns and usually -# contains pairs such as "~ cmd : USER", "~ arg : anonymous". - -function do_match_pattern_part(pat: string, data: string, aux_pat: set[string]): bool - { - if ( pat == /~ .+[-+]/ ) # with a flag - pat = cut_tail(pat, 1); # ignore the flag - - if ( string_cat(pat, " : ", data) in aux_pat ) - return T; - else if ( pat != /~ .*/ ) # not an abstract pattern - { - return ( to_lower(data) == pat ); - } - else if ( pat == "~ *" ) - return T; # always match - else if ( pat == "~ path" ) - { - return ( data == ftp_file_name_pat || - /\// in data || /\\ / in data ); - } - else if ( pat == "~ domain" ) - { - return ( data == /([\-0-9a-zA-Z]+\.)*[\-0-9a-zA-Z]+/ ); - } - else if ( pat == "~ version" ) - { - return ( data == /[A-Za-z0-9\-\.\_]+/ ); - } - else if ( pat in ftp_msg_part_patterns ) - { - return ( data == ftp_msg_part_patterns[pat] ); - } - else - return F; - } - - -# Return the most promising part of that matches , where -# = ", [, ...]". - -function match_pattern_part(pat: string, data: string, aux_pat: set[string]): string - { - # print ftp_anon_log, fmt("part_match: \"%s\" ~? \"%s\"", data, pat); - - local best = "~ none"; - local pp = split(pat, /, /); - for ( i in pp ) - { - local p = pp[i]; - if ( do_match_pattern_part(p, data, aux_pat) ) - { - if ( best == "~ none" || cmp_pattern_part(best, p) > 0 ) - best = p; - } - } - - # if ( best != "~ none" ) - # print ftp_anon_log, fmt("part_match: \"%s\" ~ \"%s\"", data, best); - - return best; - } - - -# Return T if the message (act_msg) matches the pattern; otherwise -# return F. - -function do_msg_pattern_match(act_msg: string, msg_parts: string_array, - msg_pat: msg_pattern_info, aux_pat: set[string]): msg_pattern_match_result - { - local ret: msg_pattern_match_result; - ret$valid = F; - - local num_parts = length(msg_parts); - local pat = msg_pat$tok; - - local data: string_array; - for ( i2 in msg_parts ) - if ( i2 % 2 == 1 && i2 > 1 && i2 < num_parts ) - data[int_to_count((i2-1)/2)] = msg_parts[i2]; - - if ( length(pat) != length(data) ) - return ret; - - local matched: string_array; - - for ( i in pat ) - { - local m = match_pattern_part(pat[i], data[i], aux_pat); - if ( m == "~ none" ) - return ret; - matched[i] = m; - } - - ret$valid = T; - ret$parts = matched; - ret$pat = msg_pat; - return ret; - } - - -# Anonymize a data field according to its pattern type. - -function anonymize_msg_part(data: string, pat: string, - cmd_arg: ftp_cmd_arg, session: ftp_session_info): string - { - if ( pat == /~ .+[-+]/ ) - { - local pat_len = byte_len(pat); - local annotation = sub_bytes(pat, pat_len, 1); # the last character - if ( annotation == "+" ) # to expose the data - return data; - else if ( annotation == "-" ) # to hide the data - return "<->"; - pat = cut_tail(pat, 1); # otherwise ignore the annotation - } - - if ( pat == "~ cmd" ) - return cmd_arg$anonymized_cmd; - else if ( pat == "~ arg" ) - return cmd_arg$anonymized_arg; - else if ( pat == "~ num" ) - return ""; # hide the number by default - else if ( pat == "~ port" ) - return anonymize_port_arg(session, "", data); - else if ( pat == "~ ip" ) - { - local a = parse_dotted_addr(data); - return cat(anonymize_address(a, session$connection_id)); - } - else if ( pat == "~ domain" ) - return ""; - else if ( pat == "~ file_mode" ) - return ""; - else if ( pat == "~ time" || pat == "~ day" || pat == "~ month" ) - return data; - else if ( pat == "~ email" ) - return ""; - else if ( pat == "~ url" ) - return ""; - else if ( pat == "~ ip,port" || pat == "~ ip:port" ) - { - local b = split_all(data, /[:,]/); - b[1] = cat(anonymize_address(parse_dotted_addr(b[1]), session$connection_id)); - return cat_string_array(b); - } - else if ( pat == "~ path" || pat == "~ dir" ) - return anonymize_file_name_arg(session, "", data, - (session$reply_code >= 100 && session$reply_code < 300)); - else if ( pat == "~ version" ) - return data; # keep version of the server - else if ( pat == "~ *" ) - return "<*>"; - else - { - return ""; - print ftp_anon_log, fmt("ERROR: do not know how to anonymize pattern: %s", pat); - } - } - - -# Compute a unique id that does not appear in . - -function get_unique_subst_id(context: string, seed: string): string - { - local id = string_cat("X", md5_hmac(seed), "X"); - if ( strstr(context, id) > 0 ) - return get_unique_subst_id(context, string_cat(seed, ".")); - return id; - } - - -# Substitute all occurances of in with a unique id, if -# the occurrance of is followed by (context-sensitive -# substitution), and add to the mapping -> -# . It returns the message after substitution. - -function subst_part(msg1: string, part: string, suffix: string, subst_map: table[string] of string): string - { - local ps = string_cat(part, suffix); - if ( strstr(msg1, ps) <= 0 ) return msg1; - local subst_id = get_unique_subst_id(msg1, part); - subst_map[subst_id] = part; - return subst_string(msg1, ps, string_cat(subst_id, suffix)); - } - - -# Expand argument variants (see comments of ftp_arg_variants). - -function expand_ftp_arg_variants(session: ftp_session_info, cmd_arg: ftp_cmd_arg): ftp_arg_variants - { - local var: ftp_arg_variants; - - var$arg = cmd_arg$arg; - var$path = "~ none"; - var$norm_path = "~ none"; - var$abs_path = "~ none"; - var$base_path = "~ none"; - - if ( cmd_arg$cmd in ftp_cmds_with_file_arg ) - { - local opt_fn = separate_option_str(cmd_arg$arg); - var$path = opt_fn$file_name; - - # eliminate duplicate slashes - local norm_path = subst(var$path, /\/+|\\+/, "/"); - # eliminate '/./' (as '/') - norm_path = subst(norm_path, /\/(\.\/)+/, "/"); - if ( norm_path == /.*\/\./ ) # end with '/.' - norm_path = cut_tail(norm_path, 1); - - # compress .. - norm_path = compress_path(norm_path); - - if ( var$path == ftp_dos_path_pat ) - { - norm_path = subst(norm_path, /\//, "\\"); - # cut the last '\' off if it is not "C:\" - if ( norm_path == /.*\\/ && norm_path != /[[:alpha:]]:\\/ ) - norm_path = cut_tail(norm_path, 1); - } - else - { - if ( norm_path == /.*\// && norm_path != /\//) # if it is not '/' - norm_path = cut_tail(norm_path, 1); - } - - var$norm_path = norm_path; - - var$abs_path = absolute_path(session, norm_path); - - var$base_path = subst(norm_path, /.*(\/+|\\+)/, ""); - # But ignore base path names that only contain whitespace and/or punctuations - # if ( var$base_path == ftp_msg_field_separator ) - if ( var$base_path == "" ) - var$base_path = "~ none"; - - # print ftp_anon_log, fmt("path=\"%s\", norm_path=\"%s\", abs_path = \"%s\", base_path=\"%s\"", - # var$path, var$norm_path, var$abs_path, var$base_path); - } - - return var; - } - - -function strstr_clean(big: string, little: string, clean_match: bool): count - { - local i = strstr(big, little); - - if ( i == 0 ) return i; - - if ( clean_match ) - { - local prefix = sub_bytes(big, 1, i - 1); - local suffix = sub_bytes(big, i + byte_len(little), -1); - - # print ftp_anon_log, fmt("prefix = \"%s\", suffix = \"%s\"", prefix, suffix); - # if little is not surrounded by blanks or punctuations - if ( prefix != /|.*[[:blank:][:punct:]]/ || - suffix != /|[[:blank:][:punct:]].*/ ) - return 0; - } - - return i; - } - - -# Search s for an argument variant. Note that variants are searched in -# the order of priorities -- the more specific the varient is, the -# higher priority it gets. - -type arg_in_msg: record { - arg: string; - arg_ind: count; - arg_len: count; - prefix: string; - suffix: string; -}; - -function check_arg_variant(s: string, arg: string, v: arg_in_msg, clean_match: bool): bool - { - if ( arg == "" || arg == "~ none" ) - return F; - - local i = strstr_clean(s, arg, clean_match); - if ( i <= 0 ) return F; - - local len = byte_len(arg); - if ( len <= v$arg_len ) return F; - - v$arg = arg; - v$arg_ind = i; - v$arg_len = len; - v$prefix = sub_bytes(s, 1, i - 1); - v$suffix = sub_bytes(s, i + len, -1); - return T; - } - -function expand_path_arg(v: arg_in_msg): bool - { - if ( v$prefix != /.*\// ) return F; - - local parts = split_all(v$prefix, /([^[:blank:][:punct:]]*\/)+/); - local num_parts = length(parts); - if ( parts[num_parts] != "" ) return F; - local last_part = int_to_count(num_parts - 1); - local s = parts[last_part]; - local s_len = byte_len(s); - - print ftp_anon_log, fmt("expand_path_arg: \"%s\" + \"%s\"", s, v$arg); - v$arg_len = v$arg_len + s_len; - v$arg_ind = int_to_count(v$arg_ind - s_len); - v$arg = string_cat(s, v$arg); - - parts[last_part] = ""; - v$prefix = cat_string_array(parts); - return T; - } - -function search_arg_variant(s: string, var: ftp_arg_variants, clean_match: bool): string - { - local v = [$arg = "", $arg_ind = 0, $arg_len = 0, $prefix = "", $suffix = ""]; - - check_arg_variant(s, var$arg, v, clean_match); - check_arg_variant(s, var$path, v, clean_match); - check_arg_variant(s, var$norm_path, v, clean_match); - check_arg_variant(s, var$abs_path, v, clean_match); - check_arg_variant(s, var$base_path, v, clean_match); - - if ( var$path != "~ none" ) - expand_path_arg(v); - - return ( v$arg != "" ) ? v$arg : "~ none"; - } - - -# Substitute with a unique id in , store the mapping from -# the id to in , and update and -# about the argument. -# -# It returns the message after substituion. - -function process_arg_in_reply(arg_var: ftp_arg_variants, msg: string, - other_pat: table[string] of string, aux_pat: set[string], - subst_map: table[string] of string): string - { - add aux_pat[string_cat("~ arg", " : ", arg_var$arg)]; - add aux_pat[string_cat("~ arg", " : ", arg_var$path)]; - add aux_pat[string_cat("~ arg", " : ", arg_var$abs_path)]; - add aux_pat[string_cat("~ arg", " : ", arg_var$norm_path)]; - add aux_pat[string_cat("~ arg", " : ", arg_var$base_path)]; - - local arg = search_arg_variant(msg, arg_var, T); - if ( arg != "~ none" ) - { - print ftp_anon_log, fmt("arg_variant_found: \"%s\" in \"%s\"", arg, msg); - - if ( arg != "" ) - { - other_pat[arg] = "~ arg"; - if ( ftp_msg_field_separator in arg && arg != ftp_msg_field_separator ) - msg = subst_part(msg, arg, "", subst_map); - } - } - - return msg; - } - - -# Record the message being stripped out - -function strip_out_message(session: ftp_session_info, code: count, msg: string): string - { - local ind = fmt("%d %s", code, msg); - if ( ind !in msg_stripped_out ) - { - print ftp_anon_log, - fmt("message_stripped_out: %s", msg); - add msg_stripped_out[ind]; - } - return ""; - } - - -type msg_component: record { - msg: pattern; - part: pattern; - context: pattern; -}; - -global msg_components_not_to_split: table[string] of msg_component; - -event bro_init() -{ - # quoted string - msg_components_not_to_split["quoted"] = - [$msg = /.*/, - $part = /([^"]|\"\")*/, - $context = /@@BOL@@ *\"([^"]|\"\")*\"/]; - - # port numbers in reply to PASV - msg_components_not_to_split["port"] = - [$msg = /227 .*/, - $part = /[0-9]+([[:blank:]]*,[[:blank:]]*[0-9]+){5}/, - $context = /\([0-9]+([[:blank:]]*,[[:blank:]]*[0-9]+){5}\)/]; - - # dotted IP address - msg_components_not_to_split["ip"] = - [$msg = /.*/, # any reply code - $part = /[0-9]{1,3}(\.[0-9]{1,3}){3}/, - $context = /[[:space:]\(\[][0-9]{1,3}(\.[0-9]{1,3}){3}[[:space:][:punct:]]/]; - - # email - msg_components_not_to_split["email"] = - [$msg = /.*/, # any reply code - $part = /[[:alnum:]\-\._]+@([\-0-9a-zA-Z]+\.)*[\-0-9a-zA-Z]+/, - $context = /[[:space:]\(\[<][[:alnum:]\-\.\_]+@([\-[:alnum:]]+\.)*[\-[:alnum:]]+[[:space:][:punct:]]/]; - - # URL - msg_components_not_to_split["url"] = - [$msg = /.*/, # any reply code - $part = /(http|ftp):\/\/[[:alnum:][:punct:]]+/, - $context = /(http|ftp):\/\/[[:alnum:][:punct:]]+/]; - - # domain name - msg_components_not_to_split["domain-version-filename"] = - [$msg = /.*/, # any reply code - $part = /([[:alnum:]]+[\-\.\_])+[[:alnum:]]+/, - $context = /[^\@\.\-\_[:alnum:]]([[:alnum:]]+[\-\.\_])+[[:alnum:]]+[[:space:][:punct:]]/]; # not proceeded by '@' (as in email) - - # UNIX file mode string - msg_components_not_to_split["file_mode"] = - [$msg = /(211|213) .*/, - $part = /[ld\-]([r-][w-][xs-]){3}/, - $context = /@@BOL@@ [[:blank:]]*[ld\-]([r\-][w\-][xs\-]){3}/]; - - # file name in `ls -l` - msg_components_not_to_split["ls_l_file_name"] = - [$msg = /(211|213) @@BOL@@ [[:blank:]]*[ld\-]([r\-][w\-][xs\-]){3} .*/, - $part = /[^[:blank:]]+/, - $context = /[[:blank:]][^[:blank:]]+ @@EOL@@/]; - - # symbolic links in `ls -l` - msg_components_not_to_split["ls_l_symbolic_link"] = - [$msg = /(211|213) @@BOL@@ [[:blank:]]*[ld\-]([r-][w-][xs-]){3} .*/, - $part = /[^[:blank:]]+/, - $context = /[[:blank:]][^[:blank:]]+ -> /]; - - # time - msg_components_not_to_split["time"] = - [$msg = /.*/, # any reply code - $part = /[0-9]{2}:[0-9]{2}(:[0-9]{2})?(am|pm)?/, - $context = /[[:space:]\(\[][0-9]{2}:[0-9]{2}(:[0-9]{2})?(am|pm)?[[:space:][:punct:]]/]; -} - -function subst_in_context(msg: string, orig_msg: string, c: msg_component, subst_map: table[string] of string): string - { - # print ftp_anon_log, fmt("msg = \"%s\", context = %s", msg, c$context); - - if ( orig_msg != c$msg || c$context !in msg ) - return msg; - - local parts = split_all(msg, c$context); - local msg0 = msg; - - for ( i in parts ) - { - # print ftp_anon_log, fmt("part[%d] = \"%s\"", i, parts[i]); - if ( i % 2 == 0 ) - { - local s = parts[i]; - local t = split_all(s, c$part); - - if ( length(t) > 1 && /X[[:alnum:]]{32}X/ !in t[2] ) - { - # print ftp_anon_log, fmt("\"%s\" -> \"%s\" + \"%s\" + \"%s\"", - # to_string_literal(parts[i]), t[1], t[2], t[3]); - # print ftp_anon_log, fmt("subst_in_context: \"%s\" [%s].[%s]", - # to_string_literal(s), c$part, c$context); - - local id = get_unique_subst_id(msg0, msg0); - msg0 = string_cat(msg0, id); - subst_map[id] = t[2]; - t[2] = id; - parts[i] = cat_string_array(t); - # print ftp_anon_log, fmt("subst_in_context: \"%s\"->\"%s\" in \"%s\"", - # subst_map[id], id, to_string_literal(parts[i])); - } - } - } - - return cat_string_array(parts); - } - - -# The main function for FTP reply anonymization. cmd_arg is the -# corresponding FTP request. - -function anonymize_ftp_reply_by_msg_pattern(code: count, act_msg: string, - cmd_arg: ftp_cmd_arg, session: ftp_session_info): string - { - local cmd = cmd_arg$cmd; - local arg = cmd_arg$arg; - local arg_var = expand_ftp_arg_variants(session, cmd_arg); - - # First check if trace-specific anonymization applies to the message - if ( trace_specific_reply_anonymization ) - { - local ret = anonymize_trace_specific_reply(session, code, act_msg, cmd_arg, arg_var); - if ( ret$anonymized ) - { - print ftp_anon_log, fmt("trace_specific_reply: %d \"%s\" ->\"%s\"", - code, to_string_literal(act_msg), to_string_literal(ret$msg)); - return ret$msg; - } - } - - # Extract any prefix of form "-" - local prefix = ""; - local msg0 = act_msg; - - if ( code > 0 ) - { - prefix = fmt("%d-", code); - if ( strstr(msg0, prefix) == 1 ) # msg0 starts with prefix like '220-' - msg0 = sub_bytes(msg0, byte_len(prefix) + 1, -1); - else - prefix = ""; - } - - - # Below we will split the message into fields. However, before - # the split we will first substitute certain substrings of the - # message with unique ID's and switch the ID's back to the - # corresponding strings after the split. - - # This is necessary to keep some part of the message from - # being splitted, for instance, we'd like to split the - # message: - # - # "'CWD /My Document/music/' command successful." - # - # with "/My Document/music/" as a single field instead two - # fields: "/My" and "Document/music/". - - # Mark the two ends of the message - msg0 = string_cat("@@BOL@@ ", msg0, " @@EOL@@"); - - # For pattern extraction -- used by extract_ftp_reply_pattern - local other_pat: table[string] of string; - - # For pattern matching -- used by match_pattern_part - local aux_pat: set[string]; - - local subst_map: table[string] of string; - - local orig_msg = fmt("%d %s", code, msg0); - local msg1 = msg0; - - msg1 = subst_in_context(msg1, orig_msg, msg_components_not_to_split["file_mode"], subst_map); - msg1 = subst_in_context(msg1, orig_msg, msg_components_not_to_split["ls_l_file_name"], subst_map); - msg1 = subst_in_context(msg1, orig_msg, msg_components_not_to_split["ls_l_symbolic_link"], subst_map); - - # Process command in the reply message - if ( cmd != "" ) - { - other_pat[cmd] = "~ cmd"; - add aux_pat[string_cat("~ cmd", " : ", cmd)]; - add aux_pat[string_cat("~ cmd", " : ", to_lower(cmd))]; - if ( ftp_msg_field_separator in cmd ) - msg1 = subst_part(msg1, cmd, "", subst_map); - } - - # Process arguments in reply. Note that the order is - # critical: the argument variants are processed starting from - # the most specific one. - msg1 = process_arg_in_reply(arg_var, msg1, other_pat, aux_pat, subst_map); - - # Process directory in the reply - local dir = "~ none"; # any directory contained in the reply - if ( code == 257 || [cmd, code] in ftp_dir_operation ) - { - dir = extract_dir_from_reply(session, msg1, dir); - if ( dir != "~ none" ) - { - other_pat[dir] = "~ dir"; - add aux_pat[string_cat("~ dir", " : ", dir)]; - if ( ftp_msg_field_separator in dir ) - msg1 = subst_part(msg1, dir, "", subst_map); - } - } - - # msg1 = subst_in_context(msg1, orig_msg, msg_components_not_to_split["quoted"], subst_map); - msg1 = subst_in_context(msg1, orig_msg, msg_components_not_to_split["port"], subst_map); - msg1 = subst_in_context(msg1, orig_msg, msg_components_not_to_split["email"], subst_map); - msg1 = subst_in_context(msg1, orig_msg, msg_components_not_to_split["url"], subst_map); - msg1 = subst_in_context(msg1, orig_msg, msg_components_not_to_split["ip"], subst_map); - msg1 = subst_in_context(msg1, orig_msg, msg_components_not_to_split["domain-version-filename"], subst_map); - msg1 = subst_in_context(msg1, orig_msg, msg_components_not_to_split["time"], subst_map); - - # Summarize all the substitution for debugging and verification - local subst_str = ""; - if ( length(subst_map) > 0 ) - { - for ( xx in subst_map ) - { - if ( subst_str != "" ) - subst_str = string_cat(subst_str, ", "); - subst_str = string_cat(subst_str, fmt("(\"%s\"->\"%s\")", to_string_literal(subst_map[xx]), xx)); - } - print ftp_anon_log, fmt("substitute: \"%d %s\" with {%s}", - code, act_msg, subst_str); - } - - # Split the message to parts - local msg_parts = split_all(msg1, ftp_msg_field_separator); - local num_parts = length(msg_parts); - - # According to subst_map, change substitution ID's back to the - # corresponding parts. Note that here we only look at whole - # fields to look for substitution ID's. - for ( i in msg_parts ) - { - local this_part = msg_parts[i]; - if ( this_part in subst_map ) - { - msg_parts[i] = subst_map[this_part]; - # print ftp_anon_log, fmt("substitute_part: \"%s\"", to_string_literal(msg_parts[i])); - } - } - - # Sanity check for string substitution - local msg2 = cat_string_array(msg_parts); - # msg2 != msg0 suggests that there is an improper substitution - if ( msg2 != msg0 ) - { - print ftp_anon_log, fmt("ERROR: substitution: \"%s\" -> \"%s\" with {%s} in [%s]", - to_string_literal(msg0), to_string_literal(msg2), - subst_str, id_string(session$connection_id)); - return strip_out_message(session, code, act_msg); - } - - # So far the message is successfully splitted. Now we will try - # to find a matching pattern. - - # Look it up in message patterns. - local ind = fmt("%3d %3d", code, num_parts); - - if ( ind !in msg_pattern_groups ) - { - print ftp_anon_log, fmt("pattern_not_found: \"%d %s\" in [%s]", - code, act_msg, id_string(session$connection_id)); - extract_ftp_reply_pattern(code, act_msg, msg_parts, other_pat, session); - return strip_out_message(session, code, act_msg); - } - - local pat_group = msg_pattern_groups[ind]; - - # There can be more than one matches ... record all of them - # and pick the most promising one. - local matches: table[string] of msg_pattern_match_result; - local the_pat: msg_pattern_match_result; # the best match - the_pat$valid = F; - - for ( pat_str in pat_group ) - { - local msg_pat = pat_group[pat_str]; - local tok: string_array; - local r = do_msg_pattern_match(act_msg, msg_parts, msg_pat, aux_pat); - if ( r$valid ) - { - if ( length(matches) == 0 || cmp_msg_pattern_match(r, the_pat) < 0 ) - the_pat = r; - matches[pat_str] = r; - } - } - - if ( length(matches) == 0 ) - { - print ftp_anon_log, fmt("pattern_not_found: \"%d %s\" in [%s]", - code, act_msg, id_string(session$connection_id)); - - extract_ftp_reply_pattern(code, act_msg, msg_parts, other_pat, session); - - return strip_out_message(session, code, act_msg); - } - - if ( length(matches) > 1 ) - print ftp_anon_log, fmt("multiple_patterns: \"%d %s\"", code, act_msg); - - print ftp_anon_log, fmt("message_matched: (%d) \"%d %s\" ~ \"%s\"", - length(matches), code, act_msg, the_pat$pat$str); - - ++the_pat$pat$hit; - - # Now we anonymize the message according to the_pat. During - # the process we log two kinds of anonymization for manual - # inspection: - # 1) when a field matches the wild card pattern ('~ *'): this - # will help us find information that is over-conservatively - # anonymized; - # 2) when a field matches a pattern with a 'to expose' flag (a - # '+' at the end): this will help us to verify that the - # exposed data is privacy-safe. - - local anon_parts: string_array; - local match_wildcard = ""; - local match_exposure = ""; - - for ( i in msg_parts ) - { - local data = msg_parts[i]; - if ( i <= 2 || i >= num_parts - 1 ) - anon_parts[i] = subst(data, /@@BOL@@ | @@EOL@@/, ""); - else if ( i % 2 == 0 ) - anon_parts[i] = data; - else - { - local p = the_pat$parts[int_to_count((i-1)/2)]; - anon_parts[i] = ( p != /~ .*/ ) ? data : - anonymize_msg_part(data, p, - cmd_arg, session); - - if ( p == /~ .+[+]/ ) - { - if ( match_exposure != "" ) match_exposure = string_cat(match_exposure, "; "); - match_exposure = string_cat(match_exposure, data); - } - - if ( p == "~ *" ) - { - if ( match_wildcard != "" ) match_wildcard = string_cat(match_wildcard, "; "); - match_wildcard = string_cat(match_wildcard, data); - } - } - } - - if ( match_wildcard != "" && [match_wildcard, the_pat$pat$str] !in all_wildcard_matches ) - { - add all_wildcard_matches[match_wildcard, the_pat$pat$str]; - print ftp_anon_log, fmt("wildcard_match: in pattern: \"%s\" data: [%s] in [%s]", - the_pat$pat$str, - match_wildcard, - id_string(session$connection_id)); - } - - if ( match_exposure != "" ) - { - print ftp_anon_log, fmt("data_exposure: in pattern: \"%s\" data: [%s] in [%s]", - the_pat$pat$str, - match_exposure, - id_string(session$connection_id)); - } - - local result = cat_string_array(anon_parts); - - # Stick the prefix back to the message. - if ( prefix != "" ) - result = string_cat(prefix, result); - - return result; - } diff --git a/policy.old/gnutella.bro b/policy.old/gnutella.bro deleted file mode 100644 index 0fd4429f83..0000000000 --- a/policy.old/gnutella.bro +++ /dev/null @@ -1,61 +0,0 @@ -# $Id: gnutella.bro 4017 2007-02-28 07:11:54Z vern $ - -redef capture_filters += { ["gnutella"] = "port 6346 or port 8436" }; - -global gnutella_ports = { 6346/tcp, 8436/tcp } &redef; -redef dpd_config += { [ANALYZER_GNUTELLA] = [$ports = gnutella_ports] }; - -event gnutella_text_msg(c: connection, orig: bool, headers: string) - { - if ( orig ) - print fmt("gnu txt %s -> %s %s", c$id$orig_h, c$id$resp_h, headers); - else - print fmt("gnu txt %s -> %s %s", c$id$resp_h, c$id$orig_h, headers); - } - - -event gnutella_binary_msg(c: connection, orig: bool, msg_type: count, - ttl: count, hops: count, msg_len: count, - payload: string, payload_len: count, - trunc: bool, complete: bool) - { - local s = ""; - - if ( orig ) - s = fmt("gnu bin %s -> %s", c$id$orig_h, c$id$resp_h); - else - s = fmt("gnu bin %s -> %s", c$id$resp_h, c$id$orig_h); - - print fmt("%s %d %d %d %d %d %d %d %s", - s, msg_type, ttl, hops, msg_len, - trunc, complete, payload_len, payload); - } - - -event gnutella_partial_binary_msg(c: connection, orig: bool, - msg: string, len: count) - { - if ( orig ) - print fmt("gnu pbin %s -> %s", c$id$orig_h, c$id$resp_h); - else - print fmt("gnu pbin %s -> %s", c$id$resp_h, c$id$orig_h); - } - - -event gnutella_establish(c: connection) - { - print fmt("gnu est %s <-> %s", c$id$orig_h, c$id$resp_h); - } - - -event gnutella_not_establish(c: connection) - { - print fmt("gnu !est %s <-> %s", c$id$orig_h, c$id$resp_h); - } - - -event gnutella_http_notify(c: connection) - { - print fmt("gnu http %s/%s <-> %s/%s", c$id$orig_h, c$id$orig_p, - c$id$resp_h, c$id$resp_p); - } diff --git a/policy.old/hand-over.bro b/policy.old/hand-over.bro deleted file mode 100644 index 5c017c66b5..0000000000 --- a/policy.old/hand-over.bro +++ /dev/null @@ -1,144 +0,0 @@ -# $Id: hand-over.bro 617 2004-11-02 00:54:31Z scottc $ -# -# Hand-over between two instances of Bro. - -@load remote - -# The host from which we want to take over the state has to be -# added to remote_peers_{clear,ssl}, setting hand_over to T. -# -# The host which we want to allow to perform a hand-over with us -# has to be added to remote_peers with a port of 0/tcp and -# hand_over = T. - -function is_it_us(host: addr, p: port): bool - { -@ifdef ( listen_if_clear ) - if ( is_local_interface(host) && p == listen_port_clear ) - return T; -@endif - -@ifdef ( listen_if_ssl ) - if ( is_local_interface(host) && p == listen_port_ssl ) - return T; -@endif - return F; - } - -function is_handover_peer(p: event_peer): bool - { - local peer: Remote::Destination; - - if ( p$id in Remote::pending_peers ) - peer = Remote::pending_peers[p$id]; - else - return F; - - return peer$hand_over; - } - -function handover_start_processing() - { - uninstall_src_net_filter(0.0.0.0/0); - } - -event bro_init() - { - # Disable packet processing. - install_src_net_filter(0.0.0.0/0, 0, 100); - # Reporter::message("waiting for hand-over - packet processing disabled."); - } - -event remote_connection_error(p: event_peer, reason: string) - { - if ( is_remote_event() || ! ( p$id in Remote::connected_peers) ) - return; - - # Seems that the other side in not running. - # Reporter::error("can't connect for hand-over - starting processing ..."); - handover_start_processing(); - } - -event remote_connection_established(p: event_peer) - { - if ( is_remote_event() ) - return; - - # If [p$id] is defined in Remote::connected_peers and p != 0, we have connected - # to the host. - if ( p$p != 0/tcp && - ([p$id] in Remote::connected_peers ) ) - { - if ( ! is_handover_peer(p) ) - return; - - # Reporter::message(fmt("requesting hand-over from %s:%d", p$host, p$p)); - - request_remote_events(p, /handover_.*|finished_send_state/); - - # Give the remote side some time to register its handlers. - schedule 3 secs { handover_request(p$host, p$p) }; - return; - } - - # If the other side connected to us, we will allow the hand-over - # if the remote host is defined as a hand-over host in remote_peers. - if ( is_handover_peer(p) ) - { - # Reporter::message(fmt("allowing hand-over from %s:%d", p$host, p$p)); - request_remote_events(p, /handover_.*|finished_send_state/); - } - } - -event handover_send_state(p: event_peer) - { - if ( is_remote_event() ) - return; - - # There may be a serialization in progress in which case - # we will have to try again. - if ( ! send_state(p) ) - { - # Reporter::message("can't send state; serialization in progress"); - schedule 5 secs { handover_send_state(p$host, p$p) }; - } - } - -event handover_request(p: event_peer) - { - # Make sure the event is for us. - if ( ! (is_remote_event() && is_it_us(p$host, p$p)) ) - return; - - # Send state to other side. - schedule 1 sec { handover_send_state(p) }; - } - -event finished_send_state(p: event_peer) - { - # We will get this event from the remote side. - # Make sure it's indeed for us. - if ( ! is_remote_event() ) - return; - - if ( ! is_handover_peer(p) ) - return; - - #Reporter::message(fmt("full state received from %s:%d - starting processing ...", - # p$host, p$p)); - - event handover_got_state(p); - - # Start processing. - handover_start_processing(); - } - -event handover_got_state(p: event_peer) - { - # Make sure the event is for us. - if ( ! (is_remote_event() && is_it_us(p$host, p$p)) ) - return; - - # Reporter::message(fmt("%s:%d received our state - terminating", p$host, p$p)); - terminate(); - } diff --git a/policy.old/heavy-analysis.bro b/policy.old/heavy-analysis.bro deleted file mode 100644 index 6d3bf29a0c..0000000000 --- a/policy.old/heavy-analysis.bro +++ /dev/null @@ -1,26 +0,0 @@ -# $Id: heavy-analysis.bro 2771 2006-04-18 23:53:09Z vern $ -# -# Loading this files enables somewhat more accurate, yet also significantly -# more expensive, analysis (in terms of memory as well as CPU time). -# -# This script only sets core-level options. Script-level timeouts are -# adjusted in heavy.*.bro, loaded via Bro's prefix mechanism. To make this -# work, the prefix has to be set *before* reading other scripts, either by -# loading this script first of all, or by manually putting a @prefix -# at the start of Bro's configuration. - -@prefixes += heavy - -redef tcp_SYN_timeout = 120 secs; -redef tcp_session_timer = 30 secs; -redef tcp_connection_linger = 30 secs; -redef tcp_attempt_delay = 300 secs; -redef tcp_close_delay = 15 secs; -redef tcp_reset_delay = 15 secs; -redef tcp_partial_close_delay = 10 secs; - -redef max_timer_expires = 32; - -redef tcp_inactivity_timeout = 2 hrs; -redef udp_inactivity_timeout = 1 hrs; -redef icmp_inactivity_timeout = 1 hrs; diff --git a/policy.old/heavy.irc.bro b/policy.old/heavy.irc.bro deleted file mode 100644 index 0e2cdf0dbb..0000000000 --- a/policy.old/heavy.irc.bro +++ /dev/null @@ -1,4 +0,0 @@ -# $Id: heavy.irc.bro 4723 2007-08-07 18:14:35Z vern $ - -redef active_users &persistent &read_expire = 1 days; -redef active_channels &persistent &read_expire = 1 days; diff --git a/policy.old/heavy.scan.bro b/policy.old/heavy.scan.bro deleted file mode 100644 index 570e79bf6a..0000000000 --- a/policy.old/heavy.scan.bro +++ /dev/null @@ -1,6 +0,0 @@ -# $Id: heavy.scan.bro 4758 2007-08-10 06:49:23Z vern $ - -redef distinct_peers &create_expire = 10 hrs; -redef distinct_ports &create_expire = 10 hrs; -redef distinct_low_ports &create_expire = 10 hrs; -redef possible_scan_sources &create_expire = 10 hrs; diff --git a/policy.old/heavy.software.bro b/policy.old/heavy.software.bro deleted file mode 100644 index f9e8d0b694..0000000000 --- a/policy.old/heavy.software.bro +++ /dev/null @@ -1,3 +0,0 @@ -# $Id: heavy.software.bro 2771 2006-04-18 23:53:09Z vern $ - -redef only_report_local = F; diff --git a/policy.old/heavy.trw.bro b/policy.old/heavy.trw.bro deleted file mode 100644 index 1bfce8f6b4..0000000000 --- a/policy.old/heavy.trw.bro +++ /dev/null @@ -1,8 +0,0 @@ -# $Id: heavy.trw.bro 4723 2007-08-07 18:14:35Z vern $ - -redef TRW::scan_sources &write_expire = 1 day; -redef TRW::benign_sources &write_expire = 1 day; -redef TRW::failed_locals &write_expire = 12 hrs; -redef TRW::successful_locals &write_expire = 12 hrs; -redef TRW::lambda &write_expire = 12 hrs; -redef TRW::num_scanned_locals &write_expire = 12 hrs; diff --git a/policy.old/hot-ids.bro b/policy.old/hot-ids.bro deleted file mode 100644 index 64a6a7a71f..0000000000 --- a/policy.old/hot-ids.bro +++ /dev/null @@ -1,29 +0,0 @@ -# @(#) $Id: hot-ids.bro 785 2004-11-24 05:56:06Z rwinslow $ (LBL) - -# If these ids are seen, the corresponding connection is terminated. -const forbidden_ids = { - "uucp", "daemon", "rewt", "nuucp", - "EZsetup", "OutOfBox", "4Dgifts", - "ezsetup", "outofbox", "4dgifts", "sgiweb", - "r00t", "ruut", "bomb", "backdoor", - "bionic", "warhead", "check_mate", "checkmate", "check_made", - "themage", "darkmage", "y0uar3ownd", "netfrack", "netphrack", -} &redef; - -const forbidden_ids_if_no_password = { "lp" } &redef; - -const forbidden_id_patterns = /(y[o0]u)(r|ar[e3])([o0]wn.*)/ &redef; - -const always_hot_ids = { - "sync", "tutor", "tour", - "retro", "milk", "moof", "own", "gdm", "anacnd", - "lp", "demos", forbidden_ids, -} &redef; - -# The ones here that aren't in always_hot_ids are only hot upon -# success. -const hot_ids = { - "root", "system", "smtp", "sysadm", "diag", "sysdiag", "sundiag", - "operator", "sys", "toor", "issadmin", "msql", "sysop", "sysoper", - "wank", always_hot_ids, -} &redef; diff --git a/policy.old/hot.bro b/policy.old/hot.bro deleted file mode 100644 index 5c4fd6a395..0000000000 --- a/policy.old/hot.bro +++ /dev/null @@ -1,160 +0,0 @@ -# $Id: hot.bro 7057 2010-07-19 23:22:19Z vern $ - -@load site -@load port-name -@load notice -@load terminate-connection - -module Hot; - -export { - # True if it should be considered a spoofing attack if a connection has - # the same local net for source and destination. - const same_local_net_is_spoof = F &redef; - - const allow_spoof_services = { - 110/tcp, # pop-3 - 139/tcp, # netbios-ssn - } &redef; - - # Indexed by source address and destination address. - const allow_pairs: set[addr, addr] &redef; - - const hot_srcs: table[addr] of string = { - # [ph33r.the.eleet.com] = "kidz", - } &redef; - - const hot_dsts: table[addr] of string = { - [206.101.197.226] = "ILOVEYOU worm destination", - } &redef; - - const allow_services = { - ssh, http, gopher, ident, smtp, 20/tcp, - 53/udp, # DNS queries - 123/udp, # NTP - } &redef; - - const allow_services_to: set[addr, port] &redef; - const allow_services_from: set[addr, port] &redef; - const allow_service_pairs: set[addr, addr, port] &redef; - - const flag_successful_service: table[port] of string = { - [[31337/tcp]] = "popular backdoors", - } &redef; - - const flag_successful_inbound_service: table[port] of string = { - [1524/tcp] = "popular backdoor, but with false hits outbound", - } &redef; - - const terminate_successful_inbound_service: table[port] of string &redef; - - const flag_rejected_service: table[port] of string &redef; - - # Different values to hand to check_hot() at different stages in - # a connection's lifetime. - const CONN_ATTEMPTED = 1; - const CONN_ESTABLISHED = 2; - const APPL_ESTABLISHED = 3; - const CONN_FINISHED = 4; - const CONN_REJECTED = 5; - const CONN_TIMEOUT = 6; - const CONN_REUSED = 7; - - global check_hot: function(c: connection, state: count): bool; - global check_spoof: function(c: connection): bool; -} - -# An internal function used by check_hot. -function do_hot_check(c: connection, a: addr, t: table[addr] of string) - { - if ( a in t ) - { - ++c$hot; - local hot_msg = fmt("<%s>", t[a]); - append_addl(c, hot_msg); - } - } - -function check_spoof(c: connection): bool - { - local orig = c$id$orig_h; - local resp = c$id$resp_h; - local service = c$id$resp_p; - - if ( is_local_addr(orig) && is_local_addr(resp) && - service !in allow_spoof_services ) - { - if ( c$id$orig_p == service && orig == resp ) - event conn_weird("Land_attack", c, ""); - - if ( same_local_net_is_spoof ) - ++c$hot; - } - - return c$hot != 0; - } - -function check_hot(c: connection, state: count): bool - { - local id = c$id; - local service = id$resp_p; - - if ( service in allow_services || "ftp-data" in c$service ) - return F; - - if ( state == CONN_ATTEMPTED ) - check_spoof(c); - - else if ( state == CONN_REJECTED ) - { - check_spoof(c); - - if ( service in flag_rejected_service ) - ++c$hot; - } - - else if ( state == CONN_ESTABLISHED ) - { - check_spoof(c); - - local inbound = is_local_addr(id$resp_h); - - if ( (service in flag_successful_service || - (inbound && - service in flag_successful_inbound_service)) && - ([id$resp_h, id$resp_p] !in allow_services_to || - [id$orig_h, id$resp_p] !in allow_services_from) ) - { - if ( inbound && - service in terminate_successful_inbound_service ) - TerminateConnection::terminate_connection(c); - - ++c$hot; - if ( service in flag_successful_service ) - append_addl(c, flag_successful_service[service]); - else - append_addl(c, flag_successful_inbound_service[service]); - } - } - - else if ( state == APPL_ESTABLISHED || - ((state == CONN_FINISHED || state == CONN_TIMEOUT || - state == CONN_REUSED) && - service != telnet && c$orig$size > 0 && c$resp$size > 0) ) - { - # Connection established and has a non-trivial size. - local orig = c$id$orig_h; - local resp = c$id$resp_h; - - if ( [resp, service] in allow_services_to || - [orig, service] in allow_services_from || - [orig, resp, service] in allow_service_pairs || - [orig, resp] in allow_pairs ) - return F; - - do_hot_check(c, resp, hot_srcs); - do_hot_check(c, resp, hot_dsts); - } - - return c$hot != 0; - } diff --git a/policy.old/http-abstract.bro b/policy.old/http-abstract.bro deleted file mode 100644 index 3eaeb273f0..0000000000 --- a/policy.old/http-abstract.bro +++ /dev/null @@ -1,54 +0,0 @@ -# $Id: http-abstract.bro 47 2004-06-11 07:26:32Z vern $ - -@load http -@load http-entity - -module HTTP; - -export { - const abstract_max_length = 512 &redef; -} - -redef http_entity_data_delivery_size = 4096; -redef include_HTTP_abstract = T; - -function skip_abstract(c: connection, is_orig: bool, msg: http_message) - { - msg$skip_abstract = T; - if ( ! process_HTTP_data ) - skip_http_entity_data(c, is_orig); - } - -event http_content_type(c: connection, is_orig: bool, ty: string, subty: string) - { - local s = lookup_http_request_stream(c); - local msg = get_http_message(s, is_orig); - - if ( msg$entity_level == 1 && ty == "TEXT" ) - # Do not skip the body in this case. - return; - - skip_abstract(c, is_orig, msg); - } - -event http_entity_data(c: connection, is_orig: bool, length: count, data: string) - { - local s = lookup_http_request_stream(c); - local msg = get_http_message(s, is_orig); - - if ( msg$skip_abstract ) - return; - - local len = byte_len(data); - if ( len > abstract_max_length ) - msg$abstract = sub_bytes(data, 1, abstract_max_length); - else - msg$abstract = data; - - skip_abstract(c, is_orig, msg); - - # print http_log, fmt("%.6f %s %s %d bytes: \"%s\"", - # network_time(), s$id, - # is_orig ? "=>" : "<=", byte_len(msg$abstract), - # msg$abstract); - } diff --git a/policy.old/http-anon-server.bro b/policy.old/http-anon-server.bro deleted file mode 100644 index ecf755c39a..0000000000 --- a/policy.old/http-anon-server.bro +++ /dev/null @@ -1,209 +0,0 @@ -# $Id:$ - -# Anonymize values in Server: headers. -# -# TODO: -# -# - Zedo and IBM web servers can have Apache mods -- the parsing should -# be extended to support them -# - -@load anon -@load http-anon-utils - -# --------------------------------------------------------------------- -# Apache (and friends) -# - abandon all hope ye who enter here ..... -# --------------------------------------------------------------------- - -const apache_server = - /apache(-ish)?(\/([0-9]+\.)*[0-9]+)? *(\(?(red hat( linux)?|cobalt|suse\/linux|linux\/suse|darwin|gentoo\/linux|debian gnu\/linux|win32|fedora|freebsd|red-hat\/linux|unix)\)? *)*/; - -const apache_mod_pat = - /mod_fastcgi\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /openssl\/([0-9]+\.)*[0-9a-z]{1,4}(-beta[0-9]{0,2})?/ - | /dav\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /php-cgi\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /ben-ssl\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /embperl\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_ruby\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /nexadesic\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /postgresql\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_tsunami\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_auth_svn\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_auth_mda\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /rus\/pl(([0-9]+\.)*[0-9]{1,4})/ - | /authmysql\/(([0-9]+\.)*[0-9]{1,4})/ - | /mod_auth_pgsql\/(([0-9]+\.)*[0-9]{1,4})/ - | /mod_ssl\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /php\/(([0-9]+\.)*[0-9a-z]{1,4})(-[0-9]+)?/ - | /mod_perl\/(([0-9]+\.)*[0-9a-z]{1,4})(\_[0-9]+)?/ - | /mod_macro\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_auth_pam\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_oas\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_cap\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /powweb\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_gzip\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /resin\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_jk\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /python\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /perl\/(v)?(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_python\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_log_bytes\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_auth_passthrough\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_bwlimited\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_throttle\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /mod_webapp\/(([0-9]+\.)*[0-9a-z]{1,4})(-dev)?/ - | /frontpage\/(([0-9]+\.)*[0-9a-z]{1,5})/ - | /mod_pubcookie\/[0-9a-z]{2}\/[0-9]+\.[0-9]+\-[0-9]+/ - | /(-)?coyote\/(([0-9]+\.)*[0-9a-z]{1,4})/ - | /svn\/(([0-9]+\.)*[0-9a-z]{1,4})/ - ; - -# Various Apache variants (e.g., stronghold). -const apache_misc = - /stronghold\/(([0-9]+\.)*[0-9]+) apache(\/([0-9]+\.)*[0-9]+)? (c2neteu\/[0-9])? *(\(?(red hat( linux)?|cobalt|suse\/linux|linux\/suse|darwin|gentoo\/linux|debian gnu\/linux|win32|fedora|freebsd|red-hat\/linux|unix)\)? *)*/; - -const apache_basic = /apache?(\/([0-9]+\.)*[0-9]+)?/; -const apache_platforms = - /(\(?(red hat( linux)?|cobalt|suse\/linux|linux\/suse|darwin|gentoo\/linux|debian gnu\/linux|win32|fedora|freebsd|red-hat\/linux|unix)\)? *)*/; - -# ibm_http_server/1.3.26.2, apache/1.3.26 (unix). -const IBM_server = - /ibm_http_server(\/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)?( *apache\/[0-9]+\.[0-9]+\.[0-9]+ \(unix\))?/; - - -# --------------------------------------------------------------------- -# Servers values for which we don't retain all values. -# --------------------------------------------------------------------- - -const zope_server = - /zope\/\(zope ([0-9]+\.)*[0-9]+-[a-z0-9]{1,2}\, python ([0-9]+\.)*[0-9]+\, linux[0-9]\)/; - -const thttp_server = /thttpd\/[0-9]+\.[0-9]+(beta[0-9]+)?/; -const weblogic_server = /weblogic server [0-9]+\.[0-9]+/; -const zedo_server = /zedo 3g(\/([0-9]+\.)*[0-9]+)?/; -const jetty_server = /jetty\/[0-9]+\.[0-9]+/; - -# --------------------------------------------------------------------- -# Misc Servers -# --------------------------------------------------------------------- - -const misc_server = - /dclk creative/ - | /gws\/[0-9]+\.[0-9]+/ - | /nfe\/[0-9]+\.[0-9]+/ - | /gfe\/[0-9]+\.[0-9]+/ - | /dclk-adsvr/ - | /rsi/ - | /swcd\/([0-9]+\.)*[0-9]+/ - | /microsoft-iis\/[0-9]{1,2}\.[0-9]{1,2}/ - | /cafe\/[0-9]+\.[0-9]+/ - | /artblast\/([0-9]+\.)*[0-9]+/ - | /aolserver\/([0-9]+\.)*[0-9]+/ - | /resin\/([0-9]+\.)*s?[0-9]+/ - | /netscape-enterprise\/([0-9]+\.)*[0-9a-z]{1,2}+ *(aol)?/ - | /mapquest listener/ - | /miixpc\/[0-9]+\.[0-9]+/ - | /sun-one-web-server\/[0-9]+\.[0-9]+/ - | /appledotmacserver/ - | /cj\/[0-9]+\.[0-9]+/ - | /jigsaw\/([0-9]+\.)*[0-9]+/ - | /boa\/[0-9]+\.[0-9]+(\.[0-9]+(rc[0-9]+)?)?/ - | /tux\/[0-9]+\.[0-9]+ *\(linux\)/ - | /igfe/ - | /trafficmarketplace-jforce\/([0-9]+\.)*[0-9]+/ - | /lighttpd/ - | /hitbox gateway ([0-9]+\.)*[0-9]+ [a-z][0-9]/ - | /jbird\/[0-9]+\.[0-9a-z]{1,2}/ - | /perlbal/ - | /big-ip/ - | /konichiwa\/[0-9]+\.[0-9]+/ - | /footprint [0-9]+\.[0-9]+\/fpmc/ - | /iii [0-9]+/ - | /clickability web server\/([0-9]+\.)*[0-9]+ *\(unix\)/ - | /accipiter-directserver\/([0-9]+\.)*[0-9]+ \(nt; pentium\)/ - | /ibm-proxy-wte\/([0-9]+\.)*[0-9]+/ - | /netscape-commerce\/[0-9]+\.[0-9]+/ - | /nde/ - ; - -function do_apache_server(server: string): string - { - local apache_parts = split_all(server, apache_server); - if ( apache_parts[3] == "" ) - return apache_parts[2]; - - local apache_return_string = apache_parts[2]; - local mod_parts = split(apache_parts[3], / /); - - for ( part in mod_parts ) - { - if ( mod_parts[part] == apache_mod_pat ) - { - apache_return_string = - string_cat(apache_return_string, - " "); - apache_return_string = - string_cat(apache_return_string, - mod_parts[part]); - } - else - print http_anon_log, fmt("** unknown Apache mod: %s:%s", mod_parts[part], server); - } - - return apache_return_string; - } - -function check_server(server: string, server_pat: pattern): bool - { - return server_pat in server; - } - -function do_server(server: string, server_pat: pattern): string - { - return split_all(server, server_pat)[2]; - } - -function filter_in_http_server(server: string): string - { - # Vanilla Apache is a hard one and a special case. Let's get the - # nastiness over first. - - if ( apache_server in server ) - return do_apache_server(server); - - if ( check_server(server, apache_misc) ) - return do_server(server, apache_misc); - if ( check_server(server, IBM_server) ) - return do_server(server, IBM_server); - if ( check_server(server, zedo_server) ) - return do_server(server, zedo_server); - if ( check_server(server, zope_server) ) - return do_server(server, zope_server); - if ( check_server(server, jetty_server) ) - return do_server(server, jetty_server); - if ( check_server(server, thttp_server) ) - return do_server(server, thttp_server); - if ( check_server(server, weblogic_server) ) - return do_server(server, weblogic_server); - - # Grab bag. - if ( misc_server in server ) - return server; - - # Best guess - unknown Apache variant of some sort. - if ( apache_basic in server ) - { - print http_anon_log, - fmt("** unknown Apache variant: %s", server); - - return fmt("(bro: unknown) %s %s", - split_all(server, apache_basic)[2], - split_all(server, apache_platforms)[2]); - } - - print http_anon_log, fmt("** unknown server: %s", server); - - return fmt("(bro: unknown) %s", anonymize_arg("server", server)); - } diff --git a/policy.old/http-anon-useragent.bro b/policy.old/http-anon-useragent.bro deleted file mode 100644 index b8edd4a637..0000000000 --- a/policy.old/http-anon-useragent.bro +++ /dev/null @@ -1,111 +0,0 @@ -# $Id:$ - -# Filter-in known "USER-AGENT:" values. - -@load anon -@load http-anon-utils - -# --------------------------------------------------------------------- -# Mozilla (and friends) -# --------------------------------------------------------------------- - -const mozilla_full_pat = - /mozilla\/[0-9]\.[0-9] \(( *|;|iebar| freebsd i[0-9]{1,4}|fr|-|windows|windows 98|sunos sun4u|compatible|msie [0-9]\.[0-9]|windows nt [0-9]\.[0-9]|google-tr-1|sv1|\.net clr ([0-9]\.)*[0-9]+|x11|en|ppc mac os x|macintosh|u|linux i[0-9]{1,4}|en-us|rv\:([0-9]+\.)*[0-9]+|aol [0-9]\.[0-9]|gnotify ([0-9]+\.)*[0-9]+)*\) *(gecko\/[0-9]+)? *(firefox\/([0-9]+.)*[0-9]+)?/; - -const mozilla_head_pat = /mozilla\/[0-9]\.[0-9]/; - -const misc_user_pat = - /spiderman/ - | /w3m\/([0-9]+\.)*[0-9]+/ - | /java([0-9]+\.)*[0-9]+(_[0-9]+)?/ - | /java\/([0-9]+\.)*[0-9]+(_[0-9]+)?/ - | /freecorder/ - | /industry update control/ - | /microsoft-cryptoapi\/([0-9]+\.)*[0-9]+/ - | /ruriko\/([0-9]+\.)*[0-9]+/ - | /crawler[0-9]\.[0-9]/ - | /w3search/ - | /symantec liveupdate/ - | /davkit\/[0-9]\.[0-9]/ - | /windows-media-player\/([0-9]+\.)*[0-9]+/ - | /winamp\/([0-9]+\.)*[0-9]+/ - | /headdump/ - ; - -const misc_cmplx_user_pat = - /lynx\/([0-9]+\.)*[0-9]+.*/ - | /wget\/([0-9]+\.)*[0-9]+.*/ - | /yahooseeker\/([0-9]+\.)*[0-9]+.*/ - | /rma\/([0-9]+\.)*[0-9]+.*/ - | /aim\/[0-9]+.*/ - | /ichiro\/([0-9]+\.)*[0-9]+.*/ - | /unchaos.*/ - | /irlbot\/[0-9]\.[0-9]+.*/ - | /msnbot\/([0-9]+\.)*[0-9]+.*/ - | /opera\/([0-9]+\.)*[0-9]+.*/ - | /netnewswire\/([0-9]+\.)*[0-9]+.*/ - | /nsplayer\/([0-9]+\.)*[0-9]+.*/ - | /aipbot\/([0-9]+\.)*[0-9]+.*/ - | /mac os x; webservicescore\.framework.*/ - | /fast-webcrawler\/([0-9]+\.)*[0-9]+.*/ - | /skype.*/ - | /googlebot\/([0-9]+\.)*[0-9]+.*/ - ; - -const misc_cmplx_user_start = - /lynx\/([0-9]+\.)*[0-9]+/ - | /wget\/([0-9]+\.)*[0-9]+/ - | /yahooseeker\/([0-9]+\.)*[0-9]+/ - | /rma\/([0-9]+\.)*[0-9]+/ - | /aim\/[0-9]+/ - | /ichiro\/([0-9]+\.)*[0-9]+/ - | /unchaos/ - | /irlbot\/[0-9]\.[0-9]+/ - | /opera\/([0-9]+\.)*[0-9]+/ - | /msnbot\/([0-9]+\.)*[0-9]+/ - | /netnewswire\/([0-9]+\.)*[0-9]+/ - | /nsplayer\/([0-9]+\.)*[0-9]+/ - | /aipbot\/([0-9]+\.)*[0-9]+/ - | /mac os x; webservicescore\.framework/ - | /fast-webcrawler\/([0-9]+\.)*[0-9]+/ - | /skype/ - | /googlebot\/([0-9]+\.)*[0-9]+/ - ; - -function filter_in_http_useragent(user: string): string - { - # Check for an exact match for Mozilla. - if ( mozilla_full_pat in user ) - return split_all(user, mozilla_full_pat)[2]; - - # Look for popular Mozilla-compatible crawlers. - if ( mozilla_head_pat in user ) - { - local crawler = "(bro: unknown)"; - - if ( /.*yahoo\! slurp/ in user ) - crawler = "(yahoo! slurp)"; - - else if ( /.*ask jeeves/ in user ) - crawler = "(ask jeeves)"; - - else - print http_anon_log, - fmt("*** unknown Mozilla user-agent %s\n", user); - - return fmt("%s %s", split_all(user, mozilla_head_pat)[2], - crawler); - } - - # Some simple, common user names. - if ( misc_user_pat in user ) - return user; - - # Require some info removal. - if ( misc_cmplx_user_pat in user ) - return split_all(user, misc_cmplx_user_pat)[2]; - - print http_anon_log,fmt("*** unknown user agent %s\n", user); - - return fmt("(bro: unknown) %s", anonymize_arg("user-agent", user)); - } diff --git a/policy.old/http-anon-utils.bro b/policy.old/http-anon-utils.bro deleted file mode 100644 index 660452cc2f..0000000000 --- a/policy.old/http-anon-utils.bro +++ /dev/null @@ -1,164 +0,0 @@ -# $Id:$ - -@load anon - -global http_anon_log = open_log_file("http-anon") &redef; - -const URI_proto_pat = /^ *([a-zA-Z]+)\:\/\// ; -const known_URI_proto_pat = /^ *(http|https|ftp|ssh)\:\/\// ; - -const host_pat = / *^([\-0-9a-zA-Z]+\.)+([\_\-0-9a-zA-Z])*/ ; -const port_pat = /^ *(\:[0-9]+\.)/ ; - -const query_pat = /\?/ ; - -function anonymize_http_URI(URI: string): string - { - URI = to_lower(URI); - - # Strip off protocol. - local proto = ""; - if ( URI_proto_pat in URI ) - { - local proto_part = split(URI, /\:\/\//); - - # Check if we know the protocol. If not, flag it so we - # can update our protocol database. - - if ( known_URI_proto_pat !in URI ) - { - print http_anon_log, - fmt("*** protocol %s unknown ", proto_part[1]); - - proto_part[1] = - string_cat(" (bro: unknown) ", - anonymize_arg("proto", proto_part[1])); - } - - proto = string_cat(proto_part[1],"://"); - URI = proto_part[2]; - } - - # Strip off domain. - local host = ""; - if ( host_pat in URI ) - { - local base_parts = - split_all(URI, / *^([\-\_0-9a-z]+\.)+[\-\_0-9a-z]*/); - - if ( |base_parts| < 2 ) - { - print http_anon_log, - fmt (" XXXXXXXXXXXXXXXXXXXXXX BASE %s", URI); - return " XXXX processing error XXXX"; - } - - if ( |base_parts| == 2 ) - URI = ""; - - else if ( |base_parts| == 3) - URI = base_parts[3]; - - else if ( |base_parts| > 3) - { - local patch_me = ""; - local hack = base_parts[2]; - - local i = 1; - for ( part in base_parts ) - { - if ( i != 2 ) - patch_me = string_cat(patch_me, - base_parts[i]); - i += 1; - } - - URI = patch_me; - } - - if ( host == simple_filename ) - host = anonymize_path(host); - else - host = anonymize_host(base_parts[2]); - } - - # Strip off port (if it exists). - local pport = ""; - if ( port_pat in URI ) - { - print "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "; - print "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "; - print "XXXXX anon.bro doing nothing with port XXXXXXXXXXX "; - print "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "; - print "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "; - } - - # Handle query (if exists). - local tail = ""; - if ( URI == "/" ) - { - # -- pass - } - - else if ( query_pat in URI ) - { - local query_part = split(URI, /\?/); - - tail = fmt("%s?%s", - anonymize_path(query_part[1]), - anonymize_path(query_part[2])); - } - - else - tail = anonymize_path(URI); - - tail = string_cat("/", tail); - - return fmt("%s%s%s%s", proto, host, pport, tail); - } - - -const a_href_pat = /.*\< *a *href.*\>.*/ ; - #/.*\< *a *href *= *\"[[:print:]]+\" *\>.*/; - -# Doesn't get everything ... but works for most. -const a_href_split = - /\< *a *href *= *(\\)?(\"|\')?([0-9a-z\/._!\[\]():*;~&|$\\=+\-?%@])+(\\)?(\"|\')?/ ; - -# Elegant ... yeah ... really .. :-/ -const file_split = - /(\"|\')([0-9a-z\/._!\[\]():*;~&|$\\=+\-?%@])+(\"|\')/ ; -const file_strip_split = /([0-9a-z\/._!\[\]():*;~&|$\\=+\-?%@])+/ ; - -function http_doc_link_list(abstract: string): string - { - abstract = to_lower(abstract); - - if ( abstract == "" ) - return abstract; - - local concat_key = ""; - local href_parts = split_all(abstract, a_href_split); - - for ( part in href_parts ) - { - if ( href_parts[part] == a_href_split ) - { - local file_parts = - split_all(href_parts[part], file_split); - for ( a_part in file_parts ) - { - if ( file_parts[a_part] == file_split ) - { - local file_strip_parts = - split_all(file_parts[a_part], - file_strip_split); - concat_key = fmt("%s %s", concat_key, - anonymize_http_URI(file_strip_parts[2])); - } - } - } - } - - return concat_key; - } diff --git a/policy.old/http-body.bro b/policy.old/http-body.bro deleted file mode 100644 index 4990a37341..0000000000 --- a/policy.old/http-body.bro +++ /dev/null @@ -1,60 +0,0 @@ -# $Id: http-body.bro 5230 2008-01-14 01:38:18Z vern $ - -# Counts length of data. -# -# If log_HTTP_data = T, it also outputs an abstract of data. - -@load http - -module HTTP; - -redef process_HTTP_data = T; -redef log_HTTP_data = T; - -export { - # If the following is > 0, then when logging contents, they will be - # truncated beyond this many bytes. - global content_truncation_limit = 40 &redef; -} - -event http_entity_data(c: connection, is_orig: bool, length: count, data: string) - { - local s = lookup_http_request_stream(c); - local msg = get_http_message(s, is_orig); - local len = byte_len(data); - - msg$data_length = msg$data_length + length; - - if ( log_HTTP_data ) - { - local abstract: string; - if ( content_truncation_limit > 0 && - len > content_truncation_limit ) - abstract = cat(sub_bytes(data, 1, content_truncation_limit), "..."); - else - abstract = data; - - print http_log, fmt("%.6f %s %s %d bytes: \"%s\"", - network_time(), s$id, - is_orig ? "=>" : "<=", length, - abstract); - } - } - -event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) - { - local s = lookup_http_request_stream(c); - local msg = get_http_message(s, is_orig); - - # This is for debugging purpose only - if ( msg$data_length > 0 && - stat$body_length != msg$data_length + stat$content_gap_length) - { - # This can happen for multipart messages with a - # 'content-length' header, which is not required for multipart - # messages. - # Log::warning(fmt("length mismatch: %s %d %d %d", - # id_string(c$id), stat$body_length, msg$data_length, - # stat$content_gap_length)); - } - } diff --git a/policy.old/http-detect-passwd.bro b/policy.old/http-detect-passwd.bro deleted file mode 100644 index 8ad71168c2..0000000000 --- a/policy.old/http-detect-passwd.bro +++ /dev/null @@ -1,45 +0,0 @@ -@load http - -module HTTP; - -export { - redef enum Notice += { - PasswordFullFetch, # they got back the whole thing - PasswordShadowFetch, # they got back a shadowed version - }; - - # Pattern to search for in replies indicating that a full password - # file was returned. - const full_fetch = - /[[:alnum:]]+\:[[:alnum:]]+\:[[:digit:]]+\:[[:digit:]]+\:/ - &redef; - - # Same, but indicating a shadow password file was returned. - const shadow_fetch = - /[[:alnum:]]+\:\*\:[[:digit:]]+\:[[:digit:]]+\:/ - &redef; -} - -event http_entity_data(c: connection, is_orig: bool, length: count, data: string) - { - local s = lookup_http_request_stream(c); - local n = s$first_pending_request; - if ( n !in s$requests ) - return; - - local req = s$requests[n]; - local passwd_request = req$passwd_req; - if ( ! passwd_request ) - return; - - if ( full_fetch in data ) - NOTICE([$note=PasswordFullFetch, - $conn=c, $method=req$method, $URL=req$URI, - $msg=fmt("%s %s: %s %s", id_string(c$id), c$addl, - req$method, req$URI)]); - else if ( shadow_fetch in data ) - NOTICE([$note=PasswordShadowFetch, - $conn=c, $method=req$method, $URL=req$URI, - $msg=fmt("%s %s: %s %s", id_string(c$id), c$addl, - req$method, req$URI)]); - } diff --git a/policy.old/http-entity.bro b/policy.old/http-entity.bro deleted file mode 100644 index 9084b65661..0000000000 --- a/policy.old/http-entity.bro +++ /dev/null @@ -1,20 +0,0 @@ -# $Id: http-entity.bro 6 2004-04-30 00:31:26Z jason $ - -# Counts entity_level. - -module HTTP; - -event http_begin_entity(c: connection, is_orig: bool) - { - local s = lookup_http_request_stream(c); - local msg = get_http_message(s, is_orig); - ++msg$entity_level; - } - -event http_end_entity(c: connection, is_orig: bool) - { - local s = lookup_http_request_stream(c); - local msg = get_http_message(s, is_orig); - if ( msg$entity_level > 0 ) - --msg$entity_level; - } diff --git a/policy.old/http-event.bro b/policy.old/http-event.bro deleted file mode 100644 index 450be5cf1d..0000000000 --- a/policy.old/http-event.bro +++ /dev/null @@ -1,12 +0,0 @@ -# $Id: http-event.bro 6 2004-04-30 00:31:26Z jason $ - -@load http - -module HTTP; - -event http_event(c: connection, event_type: string, detail: string) - { - print http_log, fmt("%.6f %s HTTP event: [%s] \"%s\"", - network_time(), id_string(c$id), - event_type, detail); - } diff --git a/policy.old/http-extract-items.bro b/policy.old/http-extract-items.bro deleted file mode 100644 index 4c7b1a1c0d..0000000000 --- a/policy.old/http-extract-items.bro +++ /dev/null @@ -1,41 +0,0 @@ -# $Id:$ - -# Extracts the items from HTTP traffic, one per file. -# Files are named: -# -# .._._. -# -# where is a redef'able prefix (default: "http-item"), is -# a number uniquely identifying the item, the next four are describe -# the connection tuple, and is "orig" if the item was transferred -# from the originator to the responder, "resp" otherwise. - -@load http-reply - -module HTTP_extract_items; - -global prefix = "http-item" &redef; -global item_file: table[conn_id] of file; -global nitems = 0; - -event http_entity_data(c: connection, is_orig: bool, length: count, data: string) - { - local id = c$id; - if ( id !in item_file ) - { - # Create a new file for this one. - local fname = fmt("%s.%d.%s_%d.%s_%d.%s", - prefix, ++nitems, - id$orig_h, id$orig_p, - id$resp_h, id$resp_p, - is_orig ? "orig" : "resp"); - item_file[id] = open(fname); - } - - write_file(item_file[id], data); - } - -event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) - { - delete item_file[c$id]; - } diff --git a/policy.old/http-header.bro b/policy.old/http-header.bro deleted file mode 100644 index 259031b024..0000000000 --- a/policy.old/http-header.bro +++ /dev/null @@ -1,36 +0,0 @@ -# $Id: http-header.bro 7073 2010-09-13 00:45:02Z vern $ - -# Prints out detailed HTTP headers. - -@load http - -module HTTP; - -export { - # The following lets you specify headers that you don't want - # to print out. - global skip_header: set[string] &redef; - - # If you add anything to the following table, *only* the headers - # included will be recorded. - global include_header: set[string] &redef; - - # For example: - # redef skip_header += { "COOKIE", "SET-COOKIE" }; - # will refrain from printing cookies. -} - -event http_header(c: connection, is_orig: bool, name: string, value: string) - { - if ( name in skip_header ) - return; - - if ( |include_header| > 0 && name !in include_header ) - return; - - local s = lookup_http_request_stream(c); - - print http_log, fmt("%.6f %s %s %s: %s", - network_time(), s$id, - is_orig ? ">" : "<", name, value); - } diff --git a/policy.old/http-identified-files.bro b/policy.old/http-identified-files.bro deleted file mode 100644 index a4ecd2cf7f..0000000000 --- a/policy.old/http-identified-files.bro +++ /dev/null @@ -1,115 +0,0 @@ -# $Id:$ -# -# Analyze HTTP entities for sensitive types (e.g., executables). -# -# Contributed by Seth Hall. - -@load http-reply - -module HTTP; - -const http_identified_log = open_log_file("http-id"); - -export { - # Base the libmagic analysis on this many bytes. Currently, - # we will in fact use fewer (basically, just what's in the - # first data packet). - const magic_content_limit = 1024 &redef; - - # These MIME types are logged and generate a Notice. The patterns - # need to match the entire description as returned by libMagic. - # For example, for plain text it can return - # "text/plain charset=us-ascii", so you might want to use - # /text\/plain.*/. - const watched_mime_types = - /application\/x-dosexec/ # Windows and DOS executables - | /application\/x-executable/ # *NIX executable binary - &redef; - - const watched_descriptions = /PHP script text/ &redef; - - # URLs included here are not logged and notices are not generated. - # Take care when defining patterns to not be overly broad. - const ignored_urls = - /^http:\/\/www\.download\.windowsupdate\.com\// &redef; - - redef enum Notice += { - # Generated when we see a MIME type we flagged for watching. - HTTP_WatchedMIMEType, - - # Generated when the file extension doesn't match - # the file contents. - HTTP_IncorrectFileType, - }; - - # Create patterns that *should* be in the URLs for specific MIME types. - # Notices are generated if the pattern doesn't match. - const mime_types_extensions = { - ["application/x-dosexec"] = /\.([eE][xX][eE]|[dD][lL][lL])/, - } &redef; -} - -event http_entity_data(c: connection, is_orig: bool, length: count, data: string) - { - if ( is_orig ) - # For now we only inspect server responses. - return; - - local s = lookup_http_request_stream(c); - local msg = get_http_message(s, is_orig); - -@ifndef ( content_truncation_limit ) - # This is only done if http-body.bro is not loaded. - msg$data_length = msg$data_length + length; -@endif - - # For the time being, we'll just use the data from the first packet. - # Don't continue until we have enough data. - # if ( msg$data_length < magic_content_limit ) - # return; - - # Right now, only try this for the first chunk of data - if ( msg$data_length > length ) - return; - - local abstract = sub_bytes(data, 1, magic_content_limit); - local magic_mime = identify_data(abstract, T); - local magic_descr = identify_data(abstract, F); - - if ( (magic_mime == watched_mime_types || - watched_descriptions in magic_descr) && - s$first_pending_request in s$requests ) - { - local r = s$requests[s$first_pending_request]; - local host = (s$next_request$host=="") ? - fmt("%s", c$id$resp_h) : s$next_request$host; - - event file_transferred(c, abstract, magic_descr, magic_mime); - - local url = fmt("http://%s%s", host, r$URI); - if ( ignored_urls in url ) - return; - - local file_type = ""; - if ( magic_mime == watched_mime_types ) - file_type = magic_mime; - else - file_type = magic_descr; - - local message = fmt("%s %s %s %s", - id_string(c$id), file_type, r$method, url); - - NOTICE([$note=HTTP_WatchedMIMEType, $msg=message, $conn=c, - $method=r$method, $URL=url]); - - print http_identified_log, fmt("%.06f %s %s", - network_time(), s$id, message); - - if ( (magic_mime in mime_types_extensions && - mime_types_extensions[magic_mime] !in url) || - (magic_descr in mime_types_extensions && - mime_types_extensions[magic_descr] !in url) ) - NOTICE([$note=HTTP_IncorrectFileType, $msg=message, - $conn=c, $method=r$method, $URL=url]); - } - } diff --git a/policy.old/http-reply.bro b/policy.old/http-reply.bro deleted file mode 100644 index e410b1fc34..0000000000 --- a/policy.old/http-reply.bro +++ /dev/null @@ -1,117 +0,0 @@ -# $Id: http-reply.bro 2694 2006-04-02 22:50:00Z vern $ - -@load http-request - -module HTTP; - -redef capture_filters += { - ["http-reply"] = "tcp src port 80 or tcp src port 8080 or tcp src port 8000" -}; - -redef process_HTTP_replies = T; - -event http_reply(c: connection, version: string, code: count, reason: string) - { - local s = lookup_http_request_stream(c); - local msg = s$next_reply; - - init_http_message(msg); - - msg$initiated = T; - msg$code = code; - msg$reason = reason; - } - -function http_request_done(c: connection, stat: http_message_stat) - { - local s = lookup_http_request_stream(c); - local msg = s$next_request; - msg$initiated = F; - } - -function http_reply_done(c: connection, stat: http_message_stat) - { - local s = lookup_http_request_stream(c); - local req_msg = s$next_request; - local msg = s$next_reply; - local req: string; - local have_request = F; - local log_it: bool; - - if ( s$num_pending_requests == 0 ) - { - # Weird - reply w/o request - perhaps due to cold start? - req = ""; - log_it = F; - } - else - { - local r = s$requests[s$first_pending_request]; - have_request = T; - - # Remove pending request. - delete s$requests[s$first_pending_request]; - --s$num_pending_requests; - ++s$first_pending_request; - - req = fmt("%s %s", r$method, r$URI); - log_it = r$log_it; - } - - local req_rep = - fmt("%s (%d \"%s\" [%d%s]%s)", - req, msg$code, string_escape(msg$reason, "\""), - stat$body_length, - stat$interrupted ? " (interrupted)" : "", - have_request ? fmt(" %s", req_msg$host) : ""); - - # The following is a more verbose form: -# local req_rep = -# fmt("%s (%d \"%s\" [\"%s\", %d%s%s])", -# req, msg$code, msg$reason, -# msg$content_length, stat$body_length, -# stat$interrupted ? " (interrupted)" : "", -# stat$content_gap_length > 0 ? -# fmt(" (gap = %d bytes)", stat$content_gap_length) : ""); - - if ( log_it ) - NOTICE([$note=HTTP_SensitiveURI, $conn=c, - $method = r$method, $URL = r$URI, - $n = msg$code, - $msg = fmt("%s %s: %s", - id_string(c$id), c$addl, req_rep)]); - - print http_log, fmt("%.6f %s %s", network_time(), s$id, req_rep); - - msg$initiated = F; - } - -event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) - { - if ( is_orig ) - http_request_done(c, stat); - else - http_reply_done(c, stat); - } - -@load http-entity -event http_header(c: connection, is_orig: bool, name: string, value: string) - { - # Only rewrite top-level headers. - local s = lookup_http_request_stream(c); - local msg = get_http_message(s, is_orig); - - if ( msg$entity_level == 1 ) - { - if ( name == "CONTENT-LENGTH" ) - msg$content_length = value; - - else if ( is_orig && name == "HOST" ) - { # suppress leading blank - if ( /^ / in value ) - msg$host = sub_bytes(value, 2, -1); - else - msg$host = value; - } - } - } diff --git a/policy.old/http-request.bro b/policy.old/http-request.bro deleted file mode 100644 index d5d647c977..0000000000 --- a/policy.old/http-request.bro +++ /dev/null @@ -1,104 +0,0 @@ -# $Id: http-request.bro 6726 2009-06-07 22:09:55Z vern $ - -# Analysis of HTTP requests. - -@load http - -module HTTP; - -export { - const sensitive_URIs = - /etc\/(passwd|shadow|netconfig)/ - | /IFS[ \t]*=/ - | /nph-test-cgi\?/ - | /(%0a|\.\.)\/(bin|etc|usr|tmp)/ - | /\/Admin_files\/order\.log/ - | /\/carbo\.dll/ - | /\/cgi-bin\/(phf|php\.cgi|test-cgi)/ - | /\/cgi-dos\/args\.bat/ - | /\/cgi-win\/uploader\.exe/ - | /\/search97\.vts/ - | /tk\.tgz/ - | /ownz/ # somewhat prone to false positives - | /viewtopic\.php.*%.*\(.*\(/ # PHP attack, 26Nov04 - # a bunch of possible rootkits - | /sshd\.(tar|tgz).*/ - | /[aA][dD][oO][rR][eE][bB][sS][dD].*/ - # | /[tT][aA][gG][gG][eE][dD].*/ # prone to FPs - | /shv4\.(tar|tgz).*/ - | /lrk\.(tar|tgz).*/ - | /lyceum\.(tar|tgz).*/ - | /maxty\.(tar|tgz).*/ - | /rootII\.(tar|tgz).*/ - | /invader\.(tar|tgz).*/ - &redef; - - # Used to look for attempted password file fetches. - const passwd_URI = /passwd/ &redef; - - # URIs that match sensitive_URIs but can be generated by worms, - # and hence should not be flagged (because they're so common). - const worm_URIs = - /.*\/c\+dir/ - | /.*cool.dll.*/ - | /.*Admin.dll.*Admin.dll.*/ - &redef; - - # URIs that should not be considered sensitive if accessed by - # a local client. - const skip_remote_sensitive_URIs = - /\/cgi-bin\/(phf|php\.cgi|test-cgi)/ - &redef; - - const sensitive_post_URIs = /wwwroot|WWWROOT/ &redef; -} - -redef capture_filters += { - ["http-request"] = "tcp dst port 80 or tcp dst port 8080 or tcp dst port 8000" -}; - -event http_request(c: connection, method: string, original_URI: string, - unescaped_URI: string, version: string) - { - local log_it = F; - local URI = unescaped_URI; - - if ( (sensitive_URIs in URI && URI != worm_URIs) || - (method == "POST" && sensitive_post_URIs in URI) ) - { - if ( is_local_addr(c$id$orig_h) && - skip_remote_sensitive_URIs in URI ) - ; # don't flag it after all - else - log_it = T; - } - - local s = lookup_http_request_stream(c); - - if ( process_HTTP_replies ) - { - # To process HTTP replies, we need to record the corresponding - # requests. - local n = s$first_pending_request + s$num_pending_requests; - - s$requests[n] = [$method=method, $URI=URI, $log_it=log_it, - $passwd_req=passwd_URI in URI]; - ++s$num_pending_requests; - - # if process_HTTP_messages - local msg = s$next_request; - - init_http_message(msg); - msg$initiated = T; - } - else - { - if ( log_it ) - NOTICE([$note=HTTP_SensitiveURI, $conn=c, - $method = method, $URL = URI, - $msg=fmt("%s %s: %s %s", - id_string(c$id), c$addl, method, URI)]); - print http_log, - fmt("%.6f %s %s %s", network_time(), s$id, method, URI); - } - } diff --git a/policy.old/http.bro b/policy.old/http.bro deleted file mode 100644 index 5a774b6e97..0000000000 --- a/policy.old/http.bro +++ /dev/null @@ -1,203 +0,0 @@ -# $Id: http.bro 6726 2009-06-07 22:09:55Z vern $ - -@load notice -@load site -@load conn-id - -module HTTP; - -export { - redef enum Notice += { - HTTP_SensitiveURI, # sensitive URI in GET/POST/HEAD - }; -} - -# DPM configuration. -global http_ports = { - 80/tcp, 81/tcp, 631/tcp, 1080/tcp, 3138/tcp, - 8000/tcp, 8080/tcp, 8888/tcp, -}; -redef dpd_config += { [ANALYZER_HTTP] = [$ports = http_ports] }; -redef dpd_config += { [ANALYZER_HTTP_BINPAC] = [$ports = http_ports] }; - -# HTTP processing options. -export { - const process_HTTP_replies = F &redef; - const process_HTTP_data = F &redef; - const include_HTTP_abstract = F &redef; - const log_HTTP_data = F &redef; -} - -type http_pending_request: record { - method: string; - URI: string; - log_it: bool; - - # Whether we determined it's an attempted passwd file fetch. - passwd_req: bool; -}; - -# Eventually we will combine http_pending_request and http_message. - -type http_message: record { - initiated: bool; - code: count; # for HTTP reply message - reason: string; # for HTTP reply message - entity_level: count; # depth of enclosing MIME entities - data_length: count; # actual length of data delivered - content_length: string; # length specified in CONTENT-LENGTH header - header_slot: count; # rewrite slot at the end of headers - abstract: string; # data abstract - skip_abstract: bool; # to skip abstract for certain content types - host: string; # host indicated in Host header -}; - -type http_pending_request_stream: record { - # Number of first pending request. - first_pending_request: count &default = 0; - - # Total number of pending requests. - num_pending_requests: count &default = 0; - - # Indexed from [first_pending_request .. - # (first_pending_request + num_pending_requests - 1)] - requests: table[count] of http_pending_request; - - next_request: http_message; # the on-going request - next_reply: http_message; # the on-going reply - - # len_next_reply: count; # 0 means unspecified - # len_next_request: count; - - id: string; # repeated from http_session_info, for convenience -}; - -type http_session_info: record { - id: string; - request_stream: http_pending_request_stream; -}; - -const http_log = open_log_file("http") &redef; - -export { - global http_sessions: table[conn_id] of http_session_info; -} - -global http_session_id = 0; - -function init_http_message(msg: http_message) - { - msg$initiated = F; - msg$code = 0; - msg$reason = ""; - msg$entity_level = 0; - msg$data_length = 0; - msg$content_length = ""; - msg$header_slot = 0; - msg$abstract = ""; - msg$skip_abstract = F; - msg$host = ""; - } - -function new_http_message(): http_message - { - local msg: http_message; - init_http_message(msg); - return msg; - } - -function new_http_session(c: connection): http_session_info - { - local session = c$id; - local new_id = ++http_session_id; - - local info: http_session_info; - info$id = fmt("%%%s", prefixed_id(new_id)); - - local rs: http_pending_request_stream; - - rs$first_pending_request = 1; - rs$num_pending_requests = 0; - rs$id = info$id; - - rs$next_request = new_http_message(); - rs$next_reply = new_http_message(); - rs$requests = table(); - - info$request_stream = rs; - - http_sessions[session] = info; - - print http_log, fmt("%.6f %s start %s:%d > %s:%d", network_time(), - info$id, c$id$orig_h, - c$id$orig_p, c$id$resp_h, c$id$resp_p); - - return info; - } - -function lookup_http_session(c: connection): http_session_info - { - local s: http_session_info; - local id = c$id; - - s = id in http_sessions ? http_sessions[id] : new_http_session(c); - - append_addl(c, s$id); - - return s; - } - -function lookup_http_request_stream(c: connection): http_pending_request_stream - { - local s = lookup_http_session(c); - - return s$request_stream; - } - -function get_http_message(s: http_pending_request_stream, is_orig: bool): http_message - { - return is_orig ? s$next_request : s$next_reply; - } - -function finish_stream(session: conn_id, id: string, - rs: http_pending_request_stream) - { - ### We really want to do this in sequential order, not table order. - for ( i in rs$requests ) - { - local req = rs$requests[i]; - - if ( req$log_it ) - NOTICE([$note=HTTP_SensitiveURI, - $src=session$orig_h, $dst=session$resp_h, - $URL=req$URI, - $method=req$method, - $msg=fmt("%s:%d -> %s:%d %s: ", - session$orig_h, session$orig_p, - session$resp_h, session$resp_p, id)]); - - local msg = fmt("%s %s ", req$method, req$URI); - print http_log, fmt("%.6f %s %s", network_time(), rs$id, msg); - } - } - -event connection_state_remove(c: connection) - { - local id = c$id; - - if ( id !in http_sessions ) - return; - - local s = http_sessions[id]; - finish_stream(id, s$id, s$request_stream); - delete http_sessions[c$id]; - } - - -# event http_stats(c: connection, stats: http_stats_rec) -# { -# if ( stats$num_requests == 0 && stats$num_replies == 0 ) -# return; -# -# c$addl = fmt("%s (%d v%.1f v%.1f)", c$addl, stats$num_requests, stats$request_version, stats$reply_version); -# } diff --git a/policy.old/icmp.bro b/policy.old/icmp.bro deleted file mode 100644 index c6c3c87d44..0000000000 --- a/policy.old/icmp.bro +++ /dev/null @@ -1,306 +0,0 @@ -# $Id: icmp.bro 6883 2009-08-19 21:08:09Z vern $ - -@load hot -@load weird -@load conn -@load scan - -global icmp_file = open_log_file("icmp"); - -redef capture_filters += { ["icmp"] = "icmp" }; - -module ICMP; - -export { - - redef enum Notice += { - ICMPAsymPayload, # payload in echo req-resp not the same - ICMPConnectionPair, # too many ICMPs between hosts - ICMPAddressScan, - - # The following isn't presently sufficiently useful due - # to cold start and packet drops. - # ICMPUnpairedEchoReply, # no EchoRequest seen for EchoReply - }; - - # Whether to log detailed information icmp.log. - const log_details = T &redef; - - # ICMP scan detection. - const detect_scans = T &redef; - const scan_threshold = 25 &redef; - - # Analysis of connection pairs. - const detect_conn_pairs = F &redef; # switch for connection pair - const detect_payload_asym = F &redef; # switch for echo payload - const conn_pair_threshold = 200 &redef; -} - -global conn_pair:table[addr] of set[addr] &create_expire = 1 day; -global conn_pair_thresh_reached: table[addr] of bool &default=F; - - - -type flow_id: record { - orig_h: addr; - resp_h: addr; - id: count; -}; - -type flow_info: record { - start_time: time; - last_time: time; - orig_bytes: count; - resp_bytes: count; - payload: string; -}; - -const names: table[count] of string = { - [0] = "echo_reply", - [3] = "unreach", - [4] = "quench", - [5] = "redirect", - [8] = "echo_req", - [9] = "router_adv", - [10] = "router_sol", - [11] = "time_xcd", - [12] = "param_prob", - [13] = "tstamp_req", - [14] = "tstamp_reply", - [15] = "info_req", - [16] = "info_reply", - [17] = "mask_req", - [18] = "mask_reply", -} &default = function(n: count): string { return fmt("icmp-%d", n); }; - - -# Map IP protocol number to the protocol's name. -const IP_proto_name: table[count] of string = { - [1] = "ICMP", - [2] = "IGMP", - [6] = "TCP", - [17] = "UDP", - [41] = "IPV6", -} &default = function(n: count): string { return fmt("%s", n); } - &redef; - -# Print a report for the given ICMP flow. -function generate_flow_summary(flow: flow_id, fi: flow_info) - { - local local_init = is_local_addr(flow$orig_h); - local local_addr = local_init ? flow$orig_h : flow$resp_h; - local remote_addr = local_init ? flow$resp_h : flow$orig_h; - local flags = local_init ? "L" : ""; - - local state: string; - if ( fi$orig_bytes > 0 ) - { - if ( fi$resp_bytes > 0 ) - state = "SF"; - else - state = "SH"; - } - else if ( fi$resp_bytes > 0 ) - state = "SHR"; - else - state = "OTH"; - - print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s", - fi$start_time, fi$last_time - fi$start_time, - flow$orig_h, flow$resp_h, "icmp_echo", - fi$orig_bytes, fi$resp_bytes, state, flags); - } - -# Called when a flow is expired in order to generate a report for it. -function flush_flow(ft: table[flow_id] of flow_info, fi: flow_id): interval - { - generate_flow_summary(fi, ft[fi]); - return 0 sec; - } - -# Table to track each active flow. -global flows: table[flow_id] of flow_info - &read_expire = 45 sec - &expire_func = flush_flow; - -event icmp_sent(c: connection, icmp: icmp_conn) - { - print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s", - network_time(), 0.0, icmp$orig_h, icmp$resp_h, - names[icmp$itype], icmp$itype, icmp$icode, "icmp", - icmp$len, "0", "SH"); - } - -event flow_summary(flow: flow_id, last_time: time) - { - if ( flow !in flows ) - return; - - local fi = flows[flow]; - - if ( fi$last_time == last_time ) - { - generate_flow_summary(flow, fi); - delete flows[flow]; - } - } - -function update_flow(icmp: icmp_conn, id: count, is_orig: bool, payload: string) - { - local fid: flow_id; - fid$orig_h = is_orig ? icmp$orig_h : icmp$resp_h; - fid$resp_h = is_orig ? icmp$resp_h : icmp$orig_h; - fid$id = id; - - if ( fid !in flows ) - { - local info: flow_info; - info$start_time = network_time(); - info$orig_bytes = info$resp_bytes = 0; - info$payload = payload; # checked in icmp_echo_reply - flows[fid] = info; - } - - local fi = flows[fid]; - - fi$last_time = network_time(); - - if ( is_orig ) - fi$orig_bytes = fi$orig_bytes + byte_len(payload); - else - fi$resp_bytes = fi$resp_bytes + byte_len(payload); - - schedule +30sec { flow_summary(fid, fi$last_time) }; - } - -event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) - { - update_flow(icmp, id, T, payload); - - local orig = icmp$orig_h; - local resp = icmp$resp_h; - - # Simple ping scan detector. - if ( detect_scans && - (orig !in Scan::distinct_peers || - resp !in Scan::distinct_peers[orig]) ) - { - if ( orig !in Scan::distinct_peers ) - { - local empty_peer_set: set[addr] &mergeable; - Scan::distinct_peers[orig] = empty_peer_set; - } - - if ( resp !in Scan::distinct_peers[orig] ) - add Scan::distinct_peers[orig][resp]; - - if ( ! Scan::shut_down_thresh_reached[orig] && - orig !in Scan::skip_scan_sources && - orig !in Scan::skip_scan_nets && - |Scan::distinct_peers[orig]| >= scan_threshold ) - { - NOTICE([$note=ICMPAddressScan, $src=orig, - $n=scan_threshold, - $msg=fmt("%s has icmp echo scanned %s hosts", - orig, scan_threshold)]); - - Scan::shut_down_thresh_reached[orig] = T; - } - } - - if ( detect_conn_pairs ) - { - if ( orig !in conn_pair ) - { - local empty_peer_set2: set[addr] &mergeable; - conn_pair[orig] = empty_peer_set2; - } - - if ( resp !in conn_pair[orig] ) - add conn_pair[orig][resp]; - - if ( ! conn_pair_thresh_reached[orig] && - |conn_pair[orig]| >= conn_pair_threshold ) - { - NOTICE([$note=ICMPConnectionPair, - $msg=fmt("ICMP connection threshold exceeded : %s -> %s", - orig, resp)]); - conn_pair_thresh_reached[orig] = T; - } - } - } - -event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, - seq: count, payload: string) - { - # Check payload with the associated flow. - - local fid: flow_id; - fid$orig_h = icmp$resp_h; # We know the expected results since - fid$resp_h = icmp$orig_h; # it's an echo reply. - fid$id = id; - - if ( fid !in flows ) - { -# NOTICE([$note=ICMPUnpairedEchoReply, -# $msg=fmt("ICMP echo reply w/o request: %s -> %s", -# icmp$orig_h, icmp$resp_h)]); - } - else - { - if ( detect_payload_asym ) - { - local fi = flows[fid]; - local pl = fi$payload; - - if ( pl != payload ) - { - NOTICE([$note=ICMPAsymPayload, - $msg=fmt("ICMP payload inconsistancy: %s(%s) -> %s(%s)", - icmp$orig_h, byte_len(fi$payload), - icmp$resp_h, byte_len(payload))]); - } - } - } - - update_flow(icmp, id, F, payload); - } - -event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, - context: icmp_context) - { - if ( active_connection(context$id) ) - { - # This section allows Bro to act on ICMP-unreachable packets - # that happen in the context of an active connection. It is - # not currently used. - local c2 = connection_record(context$id); - local os = c2$orig$state; - local rs = c2$resp$state; - local is_attempt = - is_tcp_port(c2$id$orig_p) ? - (os == TCP_SYN_SENT && rs == TCP_INACTIVE) : - (os == UDP_ACTIVE && rs == UDP_INACTIVE); - - # Insert action here. - } - - if ( log_details ) - { - # ICMP unreachable packets are the only ones currently - # logged. Due to the connection data contained *within* - # them, each log line will contain two connections' worth - # of data. The initial ICMP connection info is the same - # as logged for connections. - print icmp_file, fmt("%.6f %.6f %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s %s", - network_time(), 0.0, icmp$orig_h, icmp$resp_h, - names[icmp$itype], icmp$itype, icmp$icode, "icmp", - icmp$len, "0", "EncapPkt:", - # This is the encapsulated packet: - context$id$orig_h, context$id$orig_p, - context$id$resp_h, context$id$resp_p, - context$len, IP_proto_name[context$proto], - context$len, context$bad_hdr_len, - context$bad_checksum); - } - } diff --git a/policy.old/ident.bro b/policy.old/ident.bro deleted file mode 100644 index d52265db65..0000000000 --- a/policy.old/ident.bro +++ /dev/null @@ -1,68 +0,0 @@ -# $Id: ident.bro 5948 2008-07-11 22:29:49Z vern $ - -@load notice -@load hot-ids - -module Ident; - -export { - redef enum Notice += { - IdentSensitiveID, # sensitive username in Ident lookup - }; - - const hot_ident_ids = { always_hot_ids, } &redef; - const hot_ident_exceptions = { "uucp", "nuucp", "daemon", } &redef; -} - -redef capture_filters += { ["ident"] = "tcp port 113" }; - -global ident_ports = { 113/tcp } &redef; -redef dpd_config += { [ANALYZER_IDENT] = [$ports = ident_ports] }; - -global pending_ident_requests: set[addr, port, addr, port, port, port]; - -event ident_request(c: connection, lport: port, rport: port) - { - local id = c$id; - add pending_ident_requests[id$orig_h, id$orig_p, id$resp_h, id$resp_p, lport, rport]; - } - -function add_ident_tag(c: connection, lport: port, rport: port, tag: string) -: connection - { - local id = c$id; - if ( [id$orig_h, id$orig_p, id$resp_h, id$resp_p, lport, rport] in - pending_ident_requests ) - delete pending_ident_requests[id$orig_h, id$orig_p, id$resp_h, id$resp_p, lport, rport]; - else - tag = fmt("orphan-%s", tag); - - local c_orig_id = [$orig_h = id$resp_h, $orig_p = rport, - $resp_h = id$orig_h, $resp_p = lport]; - - local c_orig = active_connection(c_orig_id) ? - connection_record(c_orig_id) : c; - - append_addl(c_orig, tag); - - return c_orig; - } - -event ident_reply(c: connection, lport: port, rport: port, - user_id: string, system: string) - { - local c_orig = add_ident_tag(c, lport, rport, fmt("ident/%s", user_id)); - - if ( user_id in hot_ident_ids && user_id !in hot_ident_exceptions ) - { - ++c_orig$hot; - NOTICE([$note=IdentSensitiveID, $conn=c, - $msg=fmt("%s hot ident: %s", - $user=c_orig$addl, id_string(c_orig$id))]); - } - } - -event ident_error(c: connection, lport: port, rport: port, line: string) - { - add_ident_tag(c, lport, rport, fmt("iderr/%s", line)); - } diff --git a/policy.old/inactivity.bro b/policy.old/inactivity.bro deleted file mode 100644 index ea984a2fc2..0000000000 --- a/policy.old/inactivity.bro +++ /dev/null @@ -1,31 +0,0 @@ -# $Id: inactivity.bro 7073 2010-09-13 00:45:02Z vern $ - -@load port-name - -const inactivity_timeouts: table[port] of interval = { - # For interactive services, allow longer periods of inactivity. - [[telnet, rlogin, ssh, ftp]] = 1 hrs, -} &redef; - -function determine_inactivity_timeout(c: connection) - { - local service = c$id$resp_p; - - # Determine service (adapted from hot.bro) - if ( c$orig$state == TCP_INACTIVE ) - { - # We're seeing a half-established connection. Use the - # service of the originator if it's well-known and the - # responder isn't. - if ( service !in port_names && c$id$orig_p in port_names ) - service = c$id$orig_p; - } - - if ( service in inactivity_timeouts ) - set_inactivity_timeout(c$id, inactivity_timeouts[service]); - } - -event connection_established(c: connection) - { - determine_inactivity_timeout(c); - } diff --git a/policy.old/interconn.bro b/policy.old/interconn.bro deleted file mode 100644 index ff545d4eef..0000000000 --- a/policy.old/interconn.bro +++ /dev/null @@ -1,318 +0,0 @@ -# $Id: interconn.bro 3997 2007-02-23 00:31:19Z vern $ -# -# interconn - generic detection of interactive connections. - -@load port-name -@load demux - -# The following must be defined for the event engine to generate -# interconn events. -redef interconn_min_interarrival = 0.01 sec; -redef interconn_max_interarrival = 2.0 sec; -redef interconn_max_keystroke_pkt_size = 20; -redef interconn_default_pkt_size = 512; -redef interconn_stat_period = 15.0 sec; -redef interconn_stat_backoff = 1.5; - -const interconn_min_num_pkts = 10 &redef; # min num of pkts sent -const interconn_min_duration = 2.0 sec &redef; # min duration for the connection - -const interconn_ssh_len_disabled = T &redef; -const interconn_min_ssh_pkts_ratio = 0.6 &redef; - -const interconn_min_bytes = 10 &redef; -const interconn_min_7bit_ascii_ratio = 0.75 &redef; - -const interconn_min_num_lines = 2 &redef; -const interconn_min_normal_line_ratio = 0.5 &redef; - -# alpha: portion of interarrival times within range -# [interconn_min_interarrival, interconn_max_interarrival] -# -# alpha should be >= interconn_min_alpha -# -# gamma: num_keystrokes_two_in_row / num_pkts -# gamma indicates the portion of keystrokes in the overall traffic -# -# gamma should be >= interconn_min_gamma - -const interconn_min_alpha = 0.2 &redef; # minimum required alpha -const interconn_min_gamma = 0.2 &redef; # minimum required gamma - -const interconn_standard_ports = { telnet, rlogin, ftp, ssh, smtp, 143/tcp, 110/tcp } &redef; -const interconn_ignore_standard_ports = F &redef; - -const interconn_demux_disabled = T &redef; - -const INTERCONN_UNKNOWN = 0; # direction/interactivity is unknown - -const INTERCONN_FORWARD = 1; # forward: a conn's orig is true originator -const INTERCONN_BACKWARD = 2; # backward: a conn's resp is true originator - -const INTERCONN_INTERACTIVE = 1; # a conn is interactive -const INTERCONN_STANDARD_PORT = 2; # conn involves a standard port to ignore - -type conn_info : record { - interactive: count; # interactivity: unknown/interactive/standard_port - dir: count; # direction: unknown/forward/backward -}; - -global interconn_conns: table [conn_id] of conn_info; # table for all connections - -# Table for resp_endp's of those established (non-partial) conn's. -# If a partial conn connects to one of such resp's, we can infer -# its direction. -global interconn_resps: table [addr, port] of count &default = 0; - -global interconn_log = open_log_file("interconn") &redef; - -global num_interconns = 0; - -function interconn_conn_string(c: connection): string - { - return fmt("%.6f %s.%d > %s.%d", - c$start_time, - c$id$orig_h, c$id$orig_p, - c$id$resp_h, c$id$resp_p); - } - -function interconn_weird(c: connection, s: string) - { - print fmt("%s interconn_weird: %s %s", network_time(), interconn_conn_string(c), s); - } - -function get_direction(c: connection): count - { - local id = c$id; - - if ( interconn_conns[id]$dir != INTERCONN_UNKNOWN ) - return interconn_conns[id]$dir; - - # The connection is not established yet, but one endpoint - # is a known resp_endp - if ( [id$resp_h, id$resp_p] in interconn_resps ) - { - interconn_conns[id]$dir = INTERCONN_FORWARD; - ++interconn_resps[id$resp_h, id$resp_p]; - - return INTERCONN_FORWARD; - } - - else if ( [id$orig_h, id$orig_p] in interconn_resps ) - { - interconn_conns[id]$dir = INTERCONN_BACKWARD; - ++interconn_resps[id$orig_h, id$orig_p]; - - return INTERCONN_BACKWARD; - } - - return INTERCONN_UNKNOWN; - } - -function comp_gamma(s: interconn_endp_stats): double - { - return s$num_pkts >= interconn_min_num_pkts ? - (1.0 * s$num_keystrokes_two_in_row) / s$num_pkts : 0.0; - } - -function comp_alpha(s: interconn_endp_stats) : double - { - return ( s$num_keystrokes_two_in_row > 0 ) ? - (1.0 * s$num_normal_interarrivals / s$num_keystrokes_two_in_row) : 0.0; - } - -function skip_further_interconn_processing(c: connection) - { - # This used to call skip_further_processing() - # (if active_connection(c$id) returned T). But that's - # clearly wrong *if* we're also doing additional analysis - # on the connection. So do nothing. - } - -function log_interconn(c: connection, tag: string) - { - print interconn_log, fmt("%s %s", interconn_conn_string(c), tag); - - local id = c$id; - - if ( interconn_demux_disabled ) - skip_further_interconn_processing(c); - else - demux_conn(id, tag, "orig", "resp"); - } - -function is_interactive_endp(s: interconn_endp_stats): bool - { - # Criteria 1: num_pkts >= interconn_min_num_pkts. - if ( s$num_pkts < interconn_min_num_pkts ) - return F; - - # Criteria 2: gamma >= interconn_min_gamma. - if ( comp_gamma(s) < interconn_min_gamma ) - return F; - - # Criteria 3: alpha >= interconn_min_alpha. - if ( comp_alpha(s) < interconn_min_alpha ) - return F; - - return T; - } - -event connection_established(c: connection) - { - local id = c$id; - local dir = interconn_conns[id]$dir; - - if ( dir == INTERCONN_FORWARD ) - return; - - if ( dir == INTERCONN_BACKWARD ) - { - interconn_weird(c, "inconsistent direction"); - return; - } - - interconn_conns[id]$dir = INTERCONN_FORWARD; - ++interconn_resps[id$resp_h, id$resp_p]; - } - -event new_connection(c: connection) - { - local id = c$id; - - local info: conn_info; - info$dir = INTERCONN_UNKNOWN; - - if ( interconn_ignore_standard_ports && - (id$orig_p in interconn_standard_ports || - id$resp_p in interconn_standard_ports) ) - { - info$interactive = INTERCONN_STANDARD_PORT; - skip_further_interconn_processing(c); - } - - else - info$interactive = INTERCONN_UNKNOWN; - - interconn_conns[id] = info; - } - -event interconn_remove_conn(c: connection) - { - local id = c$id; - - if ( id !in interconn_conns ) - # This can happen for weird connections such as those - # with an initial SYN+FIN packet. - return; - - local dir = interconn_conns[id]$dir; - - delete interconn_conns[id]; - delete demuxed_conn[c$id]; - - if ( dir == INTERCONN_FORWARD ) - { - if ( --interconn_resps[id$resp_h, id$resp_p] == 0 ) - delete interconn_resps[id$resp_h, id$resp_p]; - } - - else if ( dir == INTERCONN_BACKWARD ) - { - if ( --interconn_resps[id$orig_h, id$orig_p] == 0 ) - delete interconn_resps[id$orig_h, id$orig_p]; - } - } - -event interconn_stats(c: connection, - os: interconn_endp_stats, rs: interconn_endp_stats) - { - local id = c$id; - - if ( id !in interconn_conns ) - return; - - if ( interconn_conns[id]$interactive != INTERCONN_UNKNOWN ) - return; # already classified - - if ( c$duration < interconn_min_duration ) - # forget about excessively short connections - return; - - local dir = get_direction(c); - - # Criteria: - # - # if ( dir == FORWARD ) - # (os) is interactive - # else if ( dir == BACKWARD ) - # (rs) is interactive - # else - # either (os) or (rs) is interactive - if ( dir == INTERCONN_FORWARD ) - { - if ( ! is_interactive_endp(os) ) - return; - } - - else if ( dir == INTERCONN_BACKWARD ) - { - if ( ! is_interactive_endp(rs) ) - return; - } - - else - { - if ( ! is_interactive_endp(os) && ! is_interactive_endp(rs) ) - return; - } - - local tag: string; - - if ( ! interconn_ssh_len_disabled && (os$is_partial || rs$is_partial) ) - { - local num_pkts = os$num_pkts + rs$num_pkts; - local num_8k0_pkts = os$num_8k0_pkts + rs$num_8k0_pkts; - local num_8k4_pkts = os$num_8k4_pkts + rs$num_8k4_pkts; - - if ( num_8k0_pkts > num_pkts * interconn_min_ssh_pkts_ratio ) - { - # c now considered as interactive. - interconn_conns[id]$interactive = INTERCONN_INTERACTIVE; - tag = fmt("interconn.%d.ssh2", ++num_interconns); - } - else if ( num_8k4_pkts > num_pkts * interconn_min_ssh_pkts_ratio ) - { - # c now considered as interactive. - interconn_conns[id]$interactive = INTERCONN_INTERACTIVE; - tag = fmt("interconn.%d.ssh1", ++num_interconns); - } - } - - # Criteria 4: num_7bit_ascii / num_bytes is big enough; AND - # enough number of normal lines - if ( interconn_conns[id]$interactive != INTERCONN_INTERACTIVE ) - { - local num_bytes = os$num_bytes + rs$num_bytes; - local num_7bit_ascii = os$num_7bit_ascii + rs$num_7bit_ascii; - - if ( num_bytes < interconn_min_bytes || - num_7bit_ascii < num_bytes * interconn_min_7bit_ascii_ratio ) - return; - - local num_lines = os$num_lines + rs$num_lines; - local num_normal_lines = os$num_normal_lines + - rs$num_normal_lines; - - if ( num_lines < interconn_min_num_lines || - num_normal_lines < num_lines * interconn_min_normal_line_ratio ) - return; - - # c now considered as interactive. - interconn_conns[id]$interactive = INTERCONN_INTERACTIVE; - - tag = fmt("interconn.%d", ++num_interconns); - } - - log_interconn(c, tag); - } diff --git a/policy.old/irc-bot-syslog.bro b/policy.old/irc-bot-syslog.bro deleted file mode 100644 index 6ca1281db3..0000000000 --- a/policy.old/irc-bot-syslog.bro +++ /dev/null @@ -1,79 +0,0 @@ -# $Id: irc-bot-syslog.bro,v 1.1.4.2 2006/05/31 00:16:21 sommer Exp $ -# -# Passes current bot-state to syslog. -# -# - When a new server/client is found, we syslog it immediately. -# - Every IrcBot::summary_interval we dump the current set. - -@load irc-bot - -module IrcBotSyslog; - -export { - # Prefix for all messages for easy grepping. - const prefix = "irc-bots" &redef; -} - -# For debugging, everything which goes to syslog also goes here. -global syslog_file = open_log_file("irc-bots.syslog"); - -function fmt_time(t: time) : string - { - return strftime("%Y-%m-%d-%H-%M-%S", t); - } - -function log_server(ip: addr, new: bool) - { - local s = IrcBot::servers[ip]; - local ports = IrcBot::portset_to_str(s$p); - - local msg = fmt("%s ip=%s new=%d local=%d server=1 first_seen=%s last_seen=%s ports=%s", - prefix, ip, new, is_local_addr(ip), - fmt_time(s$first_seen), fmt_time(s$last_seen), ports); - - syslog(msg); - print syslog_file, fmt("%.6f %s", network_time(), msg); - } - -function log_client(ip: addr, new: bool) - { - local c = IrcBot::clients[ip]; - local servers = IrcBot::addrset_to_str(c$servers); - - local msg = fmt("%s ip=%s new=%d local=%d server=0 first_seen=%s last_seen=%s user=%s nick=%s realname=%s servers=%s", - prefix, ip, new, is_local_addr(ip), - fmt_time(c$first_seen), fmt_time(c$last_seen), - c$user, c$nick, c$realname, servers); - - syslog(msg); - print syslog_file, fmt("%.6f %s", network_time(), msg); - } - -event print_bot_state() - { - for ( s in IrcBot::confirmed_bot_servers ) - log_server(s, F); - - for ( c in IrcBot::confirmed_bot_clients ) - log_client(c, F); - } - -event bro_init() - { - set_buf(syslog_file, F); - } - -redef notice_policy += { - [$pred(a: notice_info) = - { - if ( a$note == IrcBot::IrcBotServerFound ) - log_server(a$src, T); - - if ( a$note == IrcBot::IrcBotClientFound ) - log_client(a$src, T); - - return F; - }, - $result = NOTICE_FILE, - $priority = 1] -}; diff --git a/policy.old/irc-bot.bro b/policy.old/irc-bot.bro deleted file mode 100644 index 4bbe072b7d..0000000000 --- a/policy.old/irc-bot.bro +++ /dev/null @@ -1,566 +0,0 @@ -# $Id:$ - -@load conn -@load notice -@load weird - -module IrcBot; - -export { - global detailed_log = open_log_file("irc.detailed") &redef; - global bot_log = open_log_file("irc-bots") &redef; - - global summary_interval = 1 min &redef; - - global detailed_logging = T &redef; - global content_dir = "irc-bots" &redef; - - global bot_nicks = - /^\[([^\]]+\|)+[0-9]{2,}]/ # [DEU|XP|L|00] - | /^\[[^ ]+\]([^ ]+\|)+([0-9a-zA-Z-]+)/ # [0]CHN|3436036 [DEU][1]3G-QE - | /^DCOM[0-9]+$/ # DCOM7845 - | /^\{[A-Z]+\}-[0-9]+/ # {XP}-5021040 - | /^\[[0-9]+-[A-Z0-9]+\][a-z]+/ # [0058-X2]wpbnlgwf - | /^\[[a-zA-Z0-9]\]-[a-zA-Z0-9]+$/ # [SD]-743056826 - | /^[a-z]+[A-Z]+-[0-9]{5,}$/ - | /^[A-Z]{3}-[0-9]{4}/ # ITD-1119 - ; - - global bot_cmds = - /(^| *)[.?#!][^ ]{0,5}(scan|ndcass|download|cvar\.|execute|update|dcom|asc|scanall) / - | /(^| +\]\[ +)\* (ipscan|wormride)/ - | /(^| *)asn1/ - ; - - global skip_msgs = - /.*AUTH .*/ - | /.*\*\*\* Your host is .*/ - | /.*\*\*\* If you are having problems connecting .*/ - ; - - redef enum Notice += { - IrcBotServerFound, - IrcBotClientFound, - }; - - type channel: record { - name: string; - passwords: set[string]; - topic: string &default=""; - topic_history: vector of string; - }; - - type bot_client: record { - host: addr; - p: port; - nick: string &default=""; - user: string &default=""; - realname: string &default=""; - channels: table[string] of channel; - servers: set[addr] &optional; - first_seen: time; - last_seen: time; - }; - - type bot_server: record { - host: addr; - p: set[port]; - clients: table[addr] of bot_client; - global_users: string &default=""; - passwords: set[string]; - channels: table[string] of channel; - first_seen: time; - last_seen: time; - }; - - type bot_conn: record { - client: bot_client; - server: bot_server; - conn: connection; - fd: file; - ircx: bool &default=F; - }; - - # We keep three sets of clients/servers: - # (1) tables containing all IRC clients/servers - # (2) sets containing potential bot hosts - # (3) sets containing confirmend bot hosts - # - # Hosts are confirmed when a connection is established between - # potential bot hosts. - # - # FIXME: (1) should really be moved into the general IRC script. - - global expire_server: - function(t: table[addr] of bot_server, idx: addr): interval; - global expire_client: - function(t: table[addr] of bot_client, idx: addr): interval; - - global servers: table[addr] of bot_server &write_expire=24 hrs - &expire_func=expire_server &persistent; - global clients: table[addr] of bot_client &write_expire=24 hrs - &expire_func=expire_client &persistent; - - global potential_bot_clients: set[addr] &persistent; - global potential_bot_servers: set[addr] &persistent; - global confirmed_bot_clients: set[addr] &persistent; - global confirmed_bot_servers: set[addr] &persistent; - - # All IRC connections. - global conns: table[conn_id] of bot_conn &persistent; - - # Connections between confirmed hosts. - global bot_conns: set[conn_id] &persistent; - - # Helper functions for readable output. - global strset_to_str: function(s: set[string]) : string; - global portset_to_str: function(s: set[port]) : string; - global addrset_to_str: function(s: set[addr]) : string; -} - -function strset_to_str(s: set[string]) : string - { - if ( |s| == 0 ) - return ""; - - local r = ""; - for ( i in s ) - { - if ( r != "" ) - r = cat(r, ","); - r = cat(r, fmt("\"%s\"", i)); - } - - return r; - } - -function portset_to_str(s: set[port]) : string - { - if ( |s| == 0 ) - return ""; - - local r = ""; - for ( i in s ) - { - if ( r != "" ) - r = cat(r, ","); - r = cat(r, fmt("%d", i)); - } - - return r; - } - -function addrset_to_str(s: set[addr]) : string - { - if ( |s| == 0 ) - return ""; - - local r = ""; - for ( i in s ) - { - if ( r != "" ) - r = cat(r, ","); - r = cat(r, fmt("%s", i)); - } - - return r; - } - -function fmt_time(t: time) : string - { - return strftime("%y-%m-%d-%H-%M-%S", t); - } - -event print_bot_state() - { - local bot_summary_log = open_log_file("irc-bots.summary"); - disable_print_hook(bot_summary_log); - - print bot_summary_log, "---------------------------"; - print bot_summary_log, strftime("%y-%m-%d-%H-%M-%S", network_time()); - print bot_summary_log, "---------------------------"; - print bot_summary_log; - print bot_summary_log, "Known servers"; - - for ( h in confirmed_bot_servers ) - { - local s = servers[h]; - - print bot_summary_log, - fmt(" %s %s - clients: %d ports %s password(s) %s last-seen %s first-seen %s global-users %s", - (is_local_addr(s$host) ? "L" : "R"), - s$host, length(s$clients), portset_to_str(s$p), - strset_to_str(s$passwords), - fmt_time(s$last_seen), fmt_time(s$first_seen), - s$global_users); - - for ( name in s$channels ) - { - local ch = s$channels[name]; - print bot_summary_log, - fmt(" channel %s: topic \"%s\", password(s) %s", - ch$name, ch$topic, - strset_to_str(ch$passwords)); - } - } - - print bot_summary_log, "\nKnown clients"; - - for ( h in confirmed_bot_clients ) - { - local c = clients[h]; - print bot_summary_log, - fmt(" %s %s - server(s) %s user %s nick %s realname %s last-seen %s first-seen %s", - (is_local_addr(h) ? "L" : "R"), h, - addrset_to_str(c$servers), - c$user, c$nick, c$realname, - fmt_time(c$last_seen), fmt_time(c$first_seen)); - } - - close(bot_summary_log); - - if ( summary_interval != 0 secs ) - schedule summary_interval { print_bot_state() }; - } - -event bro_init() - { - if ( summary_interval != 0 secs ) - schedule summary_interval { print_bot_state() }; - } - -function do_log_force(c: connection, msg: string) - { - local id = c$id; - print bot_log, fmt("%.6f %s:%d > %s:%d %s %s", - network_time(), id$orig_h, id$orig_p, - id$resp_h, id$resp_p, c$addl, msg); - } - -function do_log(c: connection, msg: string) - { - if ( c$id !in bot_conns ) - return; - - do_log_force(c, msg); - } - -function log_msg(c: connection, cmd: string, prefix: string, msg: string) - { - if ( skip_msgs in msg ) - return; - - do_log(c, fmt("MSG command=%s prefix=%s msg=\"%s\"", cmd, prefix, msg)); - } - -function update_timestamps(c: connection) : bot_conn - { - local conn = conns[c$id]; - - conn$client$last_seen = network_time(); - conn$server$last_seen = network_time(); - - # To prevent the set of entries from premature expiration, - # we need to make a write access (can't use read_expire as we - # iterate over the entries on a regular basis). - clients[c$id$orig_h] = conn$client; - servers[c$id$resp_h] = conn$server; - - return conn; - } - -function add_server(c: connection) : bot_server - { - local s_h = c$id$resp_h; - - if ( s_h in servers ) - return servers[s_h]; - - local empty_table1: table[addr] of bot_client; - local empty_table2: table[string] of channel; - local empty_set: set[string]; - local empty_set2: set[port]; - - local server = [$host=s_h, $p=empty_set2, $clients=empty_table1, - $channels=empty_table2, $passwords=empty_set, - $first_seen=network_time(), $last_seen=network_time()]; - servers[s_h] = server; - - return server; - } - -function add_client(c: connection) : bot_client - { - local c_h = c$id$orig_h; - - if ( c_h in clients ) - return clients[c_h]; - - local empty_table: table[string] of channel; - local empty_set: set[addr]; - local client = [$host=c_h, $p=c$id$resp_p, $servers=empty_set, - $channels=empty_table, $first_seen=network_time(), - $last_seen=network_time()]; - clients[c_h] = client; - - return client; - } - -function check_bot_conn(c: connection) - { - if ( c$id in bot_conns ) - return; - - local client = c$id$orig_h; - local server = c$id$resp_h; - - if ( client !in potential_bot_clients || server !in potential_bot_servers ) - return; - - # New confirmed bot_conn. - - add bot_conns[c$id]; - - if ( server !in confirmed_bot_servers ) - { - NOTICE([$note=IrcBotServerFound, $src=server, $p=c$id$resp_p, $conn=c, - $msg=fmt("ircbot server found: %s:%d", server, $p=c$id$resp_p)]); - add confirmed_bot_servers[server]; - } - - if ( client !in confirmed_bot_clients ) - { - NOTICE([$note=IrcBotClientFound, $src=client, $p=c$id$orig_p, $conn=c, - $msg=fmt("ircbot client found: %s:%d", client, $p=c$id$orig_p)]); - add confirmed_bot_clients[client]; - } - } - -function get_conn(c: connection) : bot_conn - { - local conn: bot_conn; - - if ( c$id in conns ) - { - check_bot_conn(c); - return update_timestamps(c); - } - - local c_h = c$id$orig_h; - local s_h = c$id$resp_h; - - local client : bot_client; - local server : bot_server; - - if ( c_h in clients ) - client = clients[c_h]; - else - client = add_client(c); - - if ( s_h in servers ) - server = servers[s_h]; - else - server = add_server(c); - - server$clients[c_h] = client; - add server$p[c$id$resp_p]; - add client$servers[s_h]; - - conn$server = server; - conn$client = client; - conn$conn = c; - conns[c$id] = conn; - update_timestamps(c); - - return conn; - } - -function expire_server(t: table[addr] of bot_server, idx: addr): interval - { - local server = t[idx]; - for ( c in server$clients ) - { - local client = server$clients[c]; - delete client$servers[idx]; - } - - delete potential_bot_servers[idx]; - delete confirmed_bot_servers[idx]; - return 0secs; - } - -function expire_client(t: table[addr] of bot_client, idx: addr): interval - { - local client = t[idx]; - for ( s in client$servers ) - if ( s in servers ) - delete servers[s]$clients[idx]; - delete potential_bot_clients[idx]; - delete confirmed_bot_clients[idx]; - return 0secs; - } - -function remove_connection(c: connection) - { - local conn = conns[c$id]; - delete conns[c$id]; - delete bot_conns[c$id]; - } - -event connection_state_remove(c: connection) - { - if ( c$id !in conns ) - return; - - remove_connection(c); - } - -event bro_init() - { - set_buf(detailed_log, F); - set_buf(bot_log, F); - } - -event irc_client(c: connection, prefix: string, data: string) - { - if ( detailed_logging ) - print detailed_log, fmt("%.6f %s > (%s) %s", network_time(), id_string(c$id), prefix, data); - - local conn = get_conn(c); - - if ( data == /^ *[iI][rR][cC][xX] *$/ ) - conn$ircx = T; - } - -event irc_server(c: connection, prefix: string, data: string) - { - if ( detailed_logging ) - print detailed_log, fmt("%.6f %s < (%s) %s", network_time(), id_string(c$id), prefix, data); - - local conn = get_conn(c); - } - -event irc_user_message(c: connection, user: string, host: string, server: string, real_name: string) - { - local conn = get_conn(c); - conn$client$user = user; - conn$client$realname = real_name; - - do_log(c, fmt("USER user=%s host=%s server=%s real_name=%s", user, host, server, real_name)); - } - -function get_channel(conn: bot_conn, channel: string) : channel - { - if ( channel in conn$server$channels ) - return conn$server$channels[channel]; - else - { - local empty_set: set[string]; - local empty_vec: vector of string; - local ch = [$name=channel, $passwords=empty_set, $topic_history=empty_vec]; - conn$server$channels[ch$name] = ch; - return ch; - } - } - -event irc_join_message(c: connection, info_list: irc_join_list) - { - local conn = get_conn(c); - - for ( i in info_list ) - { - local ch = get_channel(conn, i$channel); - - if ( i$password != "" ) - add ch$passwords[i$password]; - - conn$client$channels[ch$name] = ch; - - do_log(c, fmt("JOIN channel=%s password=%s", i$channel, i$password)); - } - } - -global urls: set[string] &read_expire = 7 days &persistent; - -event http_request(c: connection, method: string, original_URI: string, - unescaped_URI: string, version: string) - { - if ( original_URI in urls ) - do_log_force(c, fmt("Request for URL %s", original_URI)); - } - -event irc_channel_topic(c: connection, channel: string, topic: string) - { - if ( bot_cmds in topic ) - { - do_log_force(c, fmt("Matching TOPIC %s", topic)); - add potential_bot_servers[c$id$resp_h]; - } - - local conn = get_conn(c); - - local ch = get_channel(conn, channel); - ch$topic_history[|ch$topic_history|] = ch$topic; - ch$topic = topic; - - if ( c$id in bot_conns ) - { - do_log(c, fmt("TOPIC channel=%s topic=\"%s\"", channel, topic)); - - local s = split(topic, / /); - for ( i in s ) - { - local w = s[i]; - if ( w == /[a-zA-Z]+:\/\/.*/ ) - { - add urls[w]; - do_log(c, fmt("URL channel=%s url=\"%s\"", - channel, w)); - } - } - } - } - -event irc_nick_message(c: connection, who: string, newnick: string) - { - if ( bot_nicks in newnick ) - { - do_log_force(c, fmt("Matching NICK %s", newnick)); - add potential_bot_clients[c$id$orig_h]; - } - - local conn = get_conn(c); - conn$client$nick = newnick; - - do_log(c, fmt("NICK who=%s nick=%s", who, newnick)); - } - -event irc_password_message(c: connection, password: string) - { - local conn = get_conn(c); - add conn$server$passwords[password]; - - do_log(c, fmt("PASS password=%s", password)); - } - -event irc_privmsg_message(c: connection, source: string, target: string, - message: string) - { - log_msg(c, "privmsg", source, fmt("->%s %s", target, message)); - } - -event irc_notice_message(c: connection, source: string, target: string, - message: string) - { - log_msg(c, "notice", source, fmt("->%s %s", target, message)); - } - -event irc_global_users(c: connection, prefix: string, msg: string) - { - local conn = get_conn(c); - - # Better would be to parse the message to extract the counts. - conn$server$global_users = msg; - - log_msg(c, "globalusers", prefix, msg); - } diff --git a/policy.old/irc.bro b/policy.old/irc.bro deleted file mode 100644 index 27b905528a..0000000000 --- a/policy.old/irc.bro +++ /dev/null @@ -1,689 +0,0 @@ -# $Id: irc.bro 4758 2007-08-10 06:49:23Z vern $ - -@load conn-id -@load notice -@load weird - -@load signatures - -module IRC; - -export { - const log_file = open_log_file("irc") &redef; - - type irc_user: record { - u_nick: string; # nick name - u_real: string; # real name - u_host: string; # client host - u_channels: set[string]; # channels the user is member of - u_is_operator: bool; # user is server operator - u_conn: connection; # connection handle - }; - - type irc_channel: record { - c_name: string; # channel name - c_users: set[string]; # users in channel - c_ops: set[string]; # channel operators - c_type: string; # channel type - c_modes: string; # channel modes - c_topic: string; # channel topic - }; - - global expired_user: - function(t: table[string] of irc_user, idx: string): interval; - global expired_channel: - function(t: table[string] of irc_channel, idx: string): interval; - - # Commands to ignore in irc_request/irc_message. - const ignore_in_other_msgs = { "PING", "PONG", "ISON" } &redef; - - # Return codes to ignore in irc_response - const ignore_in_other_responses: set[count] = { - 303 # RPL_ISON - } &redef; - - # Active users, indexed by nick. - global active_users: table[string] of irc_user &read_expire = 6 hrs - &expire_func = expired_user &redef; - - # Active channels, indexed by channel name. - global active_channels: table[string] of irc_channel - &read_expire = 6 hrs - &expire_func = expired_channel &redef; - - # Strings that generate a notice if found in session dialog. - const hot_words = - /.*etc\/shadow.*/ - | /.*etc\/ldap.secret.*/ - | /.*phatbot.*/ - | /.*botnet.*/ - &redef; - - redef enum Notice += { - IRC_HotWord, - }; -} - - -# IRC ports. This could be widened to 6660-6669, say. -redef capture_filters += { ["irc-6666"] = "port 6666" }; -redef capture_filters += { ["irc-6667"] = "port 6667" }; - -# DPM configuration. -global irc_ports = { 6666/tcp, 6667/tcp } &redef; -redef dpd_config += { [ANALYZER_IRC] = [$ports = irc_ports] }; - -redef Weird::weird_action += { - ["irc_invalid_dcc_message_format"] = Weird::WEIRD_FILE, - ["irc_invalid_invite_message_format"] = Weird::WEIRD_FILE, - ["irc_invalid_kick_message_format"] = Weird::WEIRD_FILE, - ["irc_invalid_line"] = Weird::WEIRD_FILE, - ["irc_invalid_mode_message_format"] = Weird::WEIRD_FILE, - ["irc_invalid_names_line"] = Weird::WEIRD_FILE, - ["irc_invalid_njoin_line"] = Weird::WEIRD_FILE, - ["irc_invalid_notice_message_format"] = Weird::WEIRD_FILE, - ["irc_invalid_oper_message_format"] = Weird::WEIRD_FILE, - ["irc_invalid_privmsg_message_format"] = Weird::WEIRD_FILE, - ["irc_invalid_reply_number"] = Weird::WEIRD_FILE, - ["irc_invalid_squery_message_format"] = Weird::WEIRD_FILE, - ["irc_invalid_who_line"] = Weird::WEIRD_FILE, - ["irc_invalid_who_message_format"] = Weird::WEIRD_FILE, - ["irc_invalid_whois_channel_line"] = Weird::WEIRD_FILE, - ["irc_invalid_whois_message_format"] = Weird::WEIRD_FILE, - ["irc_invalid_whois_operator_line"] = Weird::WEIRD_FILE, - ["irc_invalid_whois_user_line"] = Weird::WEIRD_FILE, - ["irc_line_size_exceeded"] = Weird::WEIRD_FILE, - ["irc_line_too_short"] = Weird::WEIRD_FILE, - ["irc_partial_request"] = Weird::WEIRD_FILE, - ["irc_too_many_invalid"] = Weird::WEIRD_FILE, -}; - -# # IRC servers to identify server-to-server connections. -# redef irc_servers = { -# # German IRCnet servers -# irc.leo.org, -# irc.fu-berlin.de, -# irc.uni-erlangen.de, -# irc.belwue.de, -# irc.freenet.de, -# irc.tu-ilmenau.de, -# irc.rz.uni-karlsruhe.de, -# }; - -global conn_list: table[conn_id] of count; -global conn_ID = 0; -global check_connection: function(c: connection); - -function irc_check_hot(c: connection, s: string, context: string) - { - if ( s == hot_words ) - NOTICE([$note=IRC_HotWord, $conn=c, - $msg=fmt("IRC hot word in: %s", context)]); - } - -function log_activity(c: connection, msg: string) - { - print log_file, fmt("%.6f #%s %s", - network_time(), conn_list[c$id], msg); - } - -event connection_state_remove(c: connection) - { - delete conn_list[c$id]; - } - -event irc_request(c: connection, prefix: string, - command: string, arguments: string) - { - check_connection(c); - - local context = fmt("%s %s", command, arguments); - irc_check_hot(c, command, context); - irc_check_hot(c, arguments, context); - - if ( command !in ignore_in_other_msgs ) - log_activity(c, fmt("other request%s%s: %s", - prefix == "" ? "" : " ", - prefix, context)); - } - -event irc_reply(c: connection, prefix: string, code: count, params: string) - { - check_connection(c); - - local context = fmt("%s %s", code, params); - irc_check_hot(c, params, context); - - if ( code !in ignore_in_other_responses ) - log_activity(c, fmt("other response from %s: %s", - prefix, context)); - } - -event irc_message(c: connection, prefix: string, - command: string, message: string) - { - check_connection(c); - - # Sanity checks whether this is indeed IRC. - # - # If we happen to parse an HTTP connection, the server "commands" will - # end with ":". - if ( command == /.*:$/ ) - { - local aid = current_analyzer(); - event protocol_violation(c, ANALYZER_IRC, aid, "broken server response"); - return; - } - - local context = fmt("%s %s", command, message); - irc_check_hot(c, command, context); - irc_check_hot(c, message, context); - - if ( command !in ignore_in_other_msgs ) - log_activity(c, fmt("other server message from %s: %s", - prefix, context)); - } - -event irc_user_message(c: connection, user: string, host: string, - server: string, real_name: string) - { - check_connection(c); - - log_activity(c, fmt("new user, user='%s', host='%s', server='%s', real = '%s'", - user, host, server, real_name)); - - if ( user in active_users ) - active_users[user]$u_conn = c; - else - { - local u: irc_user; - u$u_nick = user; - u$u_real = real_name; - u$u_conn = c; - u$u_host = ""; - u$u_is_operator = F; - active_users[user] = u; - } - } - -event irc_quit_message(c: connection, nick: string, message: string) - { - check_connection(c); - - log_activity(c, fmt("user '%s' leaving%s", nick, - message == "" ? "" : fmt(", \"%s\"", message))); - - # Remove from lists. - if ( nick in active_users ) - { - delete active_users[nick]; - for ( my_channel in active_channels ) - delete active_channels[my_channel]$c_users[nick]; - } - } - -function check_message(c: connection, source: string, target: string, - msg: string, msg_type: string) - { - check_connection(c); - irc_check_hot(c, msg, msg); - log_activity(c, fmt("%s%s to '%s': %s", msg_type, - source != "" ? fmt(" from '%s'", source) : "", - target, msg)); - } - -event irc_privmsg_message(c: connection, source: string, target: string, - message: string) - { - check_message(c, source, target, message, "message"); - } - -event irc_notice_message(c: connection, source: string, target: string, - message: string) - { - check_message(c, source, target, message, "notice"); - } - -event irc_squery_message(c: connection, source: string, target: string, - message: string) - { - check_message(c, source, target, message, "squery"); - } - -event irc_join_message(c: connection, info_list: irc_join_list) - { - check_connection(c); - - for ( l in info_list ) - { - log_activity(c, fmt("user '%s' joined '%s'%s", - l$nick, l$channel, - l$password != "" ? - fmt("with password '%s'", - l$password) : "")); - - if ( l$nick == "" ) - next; - - if ( l$nick in active_users ) - add (active_users[l$nick]$u_channels)[l$channel]; - else - { - local user: irc_user; - user$u_nick = l$nick; - user$u_real = ""; - user$u_conn = c; - user$u_host = ""; - user$u_is_operator = F; - add user$u_channels[l$channel]; - - active_users[l$nick] = user; - } - - # Add channel to lists. - if ( l$channel in active_channels ) - add (active_channels[l$channel]$c_users)[l$nick]; - else - { - local my_c: irc_channel; - my_c$c_name = l$channel; - add my_c$c_users[l$nick]; - - my_c$c_type = my_c$c_modes = ""; - - active_channels[l$channel] = my_c; - } - } - } - -event irc_part_message(c: connection, nick: string, - chans: string_set, message: string) - { - check_connection(c); - - local channel_str = ""; - for ( ch in chans ) - channel_str = channel_str == "" ? - ch : fmt("%s, %s", channel_str, ch); - - log_activity(c, fmt("%s channel '%s'%s", - nick == "" ? "leaving" : - fmt("user '%s' leaving", nick), - channel_str, - message == "" ? - "" : fmt("with message '%s'", message))); - - # Remove user from channel. - if ( nick == "" ) - return; - - for ( ch in active_channels ) - { - delete (active_channels[ch]$c_users)[nick]; - delete (active_channels[ch]$c_ops)[nick]; - if ( nick in active_users ) - delete (active_users[nick]$u_channels)[ch]; - } - } - -event irc_nick_message(c: connection, who: string, newnick: string) - { - check_connection(c); - - log_activity(c, fmt("%s nick name to '%s'", - who == "" ? "changing" : - fmt("user '%s' changing", who), - newnick)); - } - -event irc_invalid_nick(c: connection) - { - check_connection(c); - log_activity(c, "changing nick name failed"); - } - -event irc_network_info(c: connection, users: count, services: count, - servers: count) - { - check_connection(c); - log_activity(c, fmt("network includes %d users, %d services, %d servers", - users, services, servers)); - } - -event irc_server_info(c: connection, users: count, services: count, - servers: count) - { - check_connection(c); - log_activity(c, fmt("server includes %d users, %d services, %d peers", - users, services, servers)); - } - -event irc_channel_info(c: connection, chans: count) - { - check_connection(c); - log_activity(c, fmt("network includes %d channels", chans)); - } - -event irc_who_line(c: connection, target_nick: string, channel: string, - user: string, host: string, server: string, - nick: string, params: string, hops: count, - real_name: string) - { - check_connection(c); - - log_activity(c, fmt("channel '%s' includes '%s' on %s connected to %s with nick '%s', real name '%s', params %s", - channel, user, host, server, - nick, real_name, params)); - - if ( nick == "" || channel == "" ) - return; - - if ( nick in active_users ) - active_users[nick]$u_conn = c; - - else - { - local myuser: irc_user; - myuser$u_nick = nick; - myuser$u_real = real_name; - myuser$u_conn = c; - myuser$u_host = host; - myuser$u_is_operator = F; - add myuser$u_channels[channel]; - - active_users[nick] = myuser; - - if ( channel in active_channels ) - add (active_channels[channel]$c_users)[nick]; - else - { - local my_c: irc_channel; - my_c$c_name = channel; - add my_c$c_users[nick]; - my_c$c_type = ""; - my_c$c_modes = ""; - - active_channels[channel] = my_c; - } - } - } - -event irc_who_message(c: connection, mask: string, oper: bool) - { - check_connection(c); - - log_activity(c, fmt("WHO with mask %s%s", mask, - oper ? ", only operators" : "")); - } - -event irc_whois_message(c: connection, server: string, users: string) - { - check_connection(c); - - log_activity(c, fmt("WHOIS%s for user(s) %s", - server == "" ? - server : fmt(" to server %s", server), - users)); - } - -event irc_whois_user_line(c: connection, nick: string, - user: string, host: string, real_name: string) - { - check_connection(c); - - log_activity(c, fmt("user '%s' with nick '%s' on host %s has real name '%s'", - user, nick, host, real_name)); - - if ( nick in active_users ) - { - active_users[nick]$u_real = real_name; - active_users[nick]$u_host = host; - } - else - { - local u: irc_user; - u$u_nick = nick; - u$u_real = real_name; - u$u_conn = c; - u$u_host = host; - u$u_is_operator = F; - - active_users[nick] = u; - } - } - -event irc_whois_operator_line(c: connection, nick: string) - { - check_connection(c); - log_activity(c, fmt("user '%s' is an IRC operator", nick)); - - if ( nick in active_users ) - active_users[nick]$u_is_operator = T; - else - { - local u: irc_user; - u$u_nick = nick; - u$u_real = ""; - u$u_conn = c; - u$u_host = ""; - u$u_is_operator = T; - - active_users[nick] = u; - } - } - -event irc_whois_channel_line(c: connection, nick: string, chans: string_set) - { - check_connection(c); - - local message = fmt("user '%s' is on channels:", nick); - for ( channel in chans ) - message = fmt("%s %s", message, channel); - - log_activity(c, message); - - if ( nick in active_users ) - { - for ( ch in chans ) - add active_users[nick]$u_channels[ch]; - } - else - { - local u: irc_user; - u$u_nick = nick; - u$u_real = ""; - u$u_conn = c; - u$u_host = ""; - u$u_is_operator = F; - u$u_channels = chans; - - active_users[nick] = u; - } - - for ( ch in chans ) - { - if ( ch in active_channels ) - add (active_channels[ch]$c_users)[nick]; - else - { - local my_c: irc_channel; - my_c$c_name = ch; - add my_c$c_users[nick]; - my_c$c_type = ""; - my_c$c_modes = ""; - - active_channels[ch] = my_c; - } - } - } - -event irc_oper_message(c: connection, user: string, password: string) - { - check_connection(c); - log_activity(c, fmt("user requests operator status with name '%s', password '%s'", - user, password)); - } - -event irc_oper_response(c: connection, got_oper: bool) - { - check_connection(c); - log_activity(c, fmt("user %s operator status", - got_oper ? "received" : "did not receive")); - } - -event irc_kick_message(c: connection, prefix: string, chans: string, - users: string, comment: string) - { - check_connection(c); - log_activity(c, fmt("user '%s' requested to kick '%s' from channel(s) %s with comment %s", - prefix, users, chans, comment)); - } - -event irc_error_message(c: connection, prefix: string, message: string) - { - check_connection(c); - log_activity(c, fmt("error message%s: %s", - prefix == "" ? "" : fmt("from '%s'", prefix), - message)); - } - -event irc_invite_message(c: connection, prefix: string, - nickname: string, channel: string) - { - check_connection(c); - log_activity(c, fmt("'%s' invited to channel %s%s", - nickname, channel, - prefix == "" ? "" : fmt(" by %s", prefix))); - } - -event irc_mode_message(c: connection, prefix: string, params: string) - { - check_connection(c); - log_activity(c, fmt("mode command%s: %s", - prefix == "" ? "" : fmt(" from '%s'", prefix), - params)); - } - -event irc_squit_message(c: connection, prefix: string, - server: string, message: string) - { - check_connection(c); - - log_activity(c, fmt("server disconnect attempt%s for %s with comment %s", - prefix == "" ? "" : fmt(" from '%s'", prefix), - server, message)); - } - -event irc_names_info(c: connection, c_type: string, channel: string, - users: string_set) - { - check_connection(c); - - local chan_type = - c_type == "@" ? "secret" : - (c_type == "*" ? "private" : "public"); - - local message = fmt("channel '%s' (%s) contains users:", - channel, chan_type); - - for ( user in users ) - message = fmt("%s %s", message, user); - - log_activity(c, message); - - if ( channel in active_channels ) - { - for ( u in users ) - add (active_channels[channel]$c_users)[u]; - } - else - { - local my_c: irc_channel; - my_c$c_name = channel; - my_c$c_users = users; - my_c$c_type = ""; - my_c$c_modes = ""; - - active_channels[channel] = my_c; - } - - for ( nick in users ) - { - if ( nick in active_users ) - add (active_users[nick]$u_channels)[channel]; - else - { - local usr: irc_user; - usr$u_nick = nick; - usr$u_real = ""; - usr$u_conn = c; - usr$u_host = ""; - usr$u_is_operator = F; - add usr$u_channels[channel]; - - active_users[nick] = usr; - } - } - } - -event irc_dcc_message(c: connection, prefix: string, target: string, - dcc_type: string, argument: string, - address: addr, dest_port: count, size: count) - { - check_connection(c); - - log_activity(c, fmt("DCC %s invitation for '%s' to host %s on port %s%s", - dcc_type, target, address, dest_port, - dcc_type == "SEND" ? - fmt(" (%s: %s bytes)", argument, size) : - "")); - } - -event irc_channel_topic(c: connection, channel: string, topic: string) - { - check_connection(c); - log_activity(c, fmt("topic for %s is '%s'", channel, topic)); - } - -event irc_password_message(c: connection, password: string) - { - check_connection(c); - log_activity(c, fmt("password %s", password)); - } - -function expired_user(t: table[string] of irc_user, idx: string): interval - { - for ( my_c in active_users[idx]$u_channels ) - { - suspend_state_updates(); - delete active_channels[my_c]$c_users[idx]; - delete active_channels[my_c]$c_ops[idx]; - resume_state_updates(); - } - - return 0 secs; - } - -function expired_channel(t:table[string] of irc_channel, idx: string): interval - { - for ( my_u in active_channels[idx]$c_users ) - if ( my_u in active_users ) - delete active_users[my_u]$u_channels[idx]; - # Else is there a possible state leak? How could it not - # be in active_users? Yet sometimes it isn't, which - # is why we needed to add the above test. - - return 0 secs; - } - -function check_connection(c: connection) - { - if ( c$id !in conn_list ) - { - ++conn_ID; - append_addl(c, fmt("#%d", conn_ID)); - conn_list[c$id] = conn_ID; - - log_activity(c, fmt("new connection %s", id_string(c$id))); - } - } diff --git a/policy.old/large-conns.bro b/policy.old/large-conns.bro deleted file mode 100644 index 7c55c8ff1c..0000000000 --- a/policy.old/large-conns.bro +++ /dev/null @@ -1,336 +0,0 @@ -# $Id: large-conns.bro 1332 2005-09-07 17:39:17Z vern $ - -# Written by Chema Gonzalez. - - -# Estimates the size of large "flows" (i.e., each direction of a TCP -# connection) by noting when their sequence numbers cross a set of regions -# in the sequence space. This can be done using a static packet filter, -# so is very efficient. It works for (TCP) traffic that Bro otherwise doesn't -# see. - -# Usage -# -# 1) Set the appropriate number_of_regions and region_size: -# -# Modify the number_of_regions and (perhaps) region_size global -# variables. You do this *prior* to loading this script, so -# for example: -# -# const number_of_regions = 32; -# @load large-conns -# -# You do *not* redef them like you would with other script variables -# (this is because they need to be used directly in the initializations -# of other variables used by this script). -# -# Note that number_of_regions affects the granularity -# and definition of the script (see below). -# -# 2) To get an estimate of the true size of a flow, call: -# -# function estimate_flow_size_and_remove(cid: conn_id, orig: bool): -# flow_size_est -# -# If orig=T, then an estimate of the size of the forward (originator) -# direction is returned. If orig=F, then the reverse (responder) -# direction is returned. In both cases, what's returned is a -# flow_size_est, which includes a flag indicating whether there was -# any estimate formed, and, if the flag is T, a lower bound, an upper bound, -# and an inconsistency-count (which, if > 0, means that the estimates -# came from sequence numbers that were inconsistent, and thus something -# is wrong - perhaps packet drops by the secondary filter). Finally, -# calling this function causes the flow's record to be deleted. Perhaps -# at some point we'll need to add a version that just retrieves the -# estimate. - -type flow_size_est: record { - have_est: bool; - lower: double &optional; - upper: double &optional; - num_inconsistent: count &optional; -}; - -global estimate_flow_size_and_remove: - function(cid: conn_id, orig: bool): flow_size_est; - -module LargeConn; - - -# Rationale -# -# One of the mechanisms that Bro uses to detect large TCP flows is -# to calculate the difference in the sequence number (seq) field contents -# between the last packet (FIN or RST) and the first packet (SYN). This -# method may be wrong if a) the seq number is busted (which can happen -# frequently with RST termination), or b) the seq number wraps around -# the 4GB sequence number space (note that this is OK for TCP while -# there is no ambiguity on what a packet's sequence number means, -# due to its use of a window <= 2 GB in size). -# -# The purpose of this script is to resolve these ambiguities. In other -# words, help with differentiating truly large flows from flows with -# a busted seq, and detecting very large flows that wrap around the -# 4GB seq space. -# -# To do so, large-flow listens to a small group of thin regions in -# the sequence space, located at equal distances from each other. The idea -# is that a truly large flow will pass through the regions in -# an orderly fashion, maybe several times. This script keeps track of -# all packets that pass through any of the regions, counting the number -# of times a packet from a given flow passes through consecutive regions. -# -# Note that the exact number of regions, and the size of each region, can -# be controlled by redefining the global variables number_of_regions -# and region_size, respectively. Both should be powers of two (if not, -# they are rounded to be such), and default to 4 and 16KB, respectively. -# The effect of varying these parameters is the following: -# -# - Increasing number_of_regions will increase the granularity of the -# script, at the cost of elevating its cost in both processing (more -# packets will be seen) and memory (more flows will be seen). -# The granularity of the script is defined as the minimum variation -# in size the script can see. Its value is: -# -# granularity = (4GB / number_of_regions) -# -# For example, if we're using 4 regions, the minimum flow size difference -# that the script can see is 1GB. -# -# number_of_regions also affects the script definition, defined as the -# smallest size of a flow which ensures that the flow will be seen by -# the script. The script definition is: -# -# definition = (2 * granularity) -# -# The script sees no flow smaller than the granularity, some flows with -# size between granularity and definition, and all flows larger than -# definition. In our example, the script definition is 2GB (it will see -# for sure only flows bigger than 2GB). -# -# - Increasing region_size will only increase the resilience of the script -# to lost packets, at the cost of augmenting the cost in both processing -# and memory (see above). The default value of 16 KB is chosen to work -# in the presence of largish packets without too much additional work. - -# Set up defaults, unless the user has already specified these. Note that -# these variables are *not* redef'able, since they are used in initializations -# later in this script (so a redef wouldn't be "seen" in time). -@ifndef ( number_of_regions ) - const number_of_regions = 4; -@endif -@ifndef ( region_size ) - const region_size = 16 * 1024; # 16 KB -@endif - - -# Track the regions visited for each flow. -type t_info: record { - last_region: count; # last region visited - num_regions: count; # number of regions visited - num_inconsistent: count; # num. inconsistent region crossings -}; - -# The state expiration for this table needs to be generous, as it's -# for tracking very large flows, which could be quite long-lived. -global flow_region_info: table[conn_id] of t_info &write_expire = 6 hr; - - -# Returns the integer logarithm in base b. -function logarithm(base: count, x: count): count - { - if ( x < base ) - return 0; - else - return 1 + logarithm(base, x / base); - } - - -# Function used to get around Bro's lack of real ordered loop. -function do_while(i: count, max: count, total: count, - f: function(i: count, total: count): count): count - { - if ( i >= max ) - return total; - else - return do_while(++i, max, f(--i, total), f); - } - -function fn_mask_location(i: count, total: count): count - { - return total * 2 + 1; - } - -function fn_filter_location(i: count, total: count): count - { - # The location pattern is 1010101010... - return total * 2 + (i % 2 == 0 ? 1 : 0); - } - -function fn_common_region_size(i: count, total: count): count - { - return total * 2; - } - - -function get_interregion_distance(number_of_regions: count, - region_size: count): count - { - local bits_number_of_regions = logarithm(2, number_of_regions); - local bits_other = int_to_count(32 - bits_number_of_regions); - - return do_while(0, bits_other, 1, fn_common_region_size); - } - - -global interregion_distance = - get_interregion_distance(number_of_regions, region_size); - - -# Returns an estiamte of size of the flow (one direction of a TCP connection) -# that this script has seen. This is based on the number of consecutive -# regions a flow has visited, weighted with the distance between regions. -# -# We know that the full sequence number space accounts for 4GB. This -# space comprises number_of_regions regions, separated from each other -# a (4GB / number_of_regions) distance. If a flow has been seen -# in X consecutive regions, it means that the size of the flow is -# greater than ((X - 1) * distance_between_regions) GB. -# -# Note that seeing a flow in just one region is no different from -# not seeing it at all. -function estimate_flow_size_and_remove(cid: conn_id, orig: bool): flow_size_est - { - local id = orig ? cid : - [$orig_h = cid$resp_h, $orig_p = cid$resp_p, - $resp_h = cid$orig_h, $resp_p = cid$orig_p]; - - if ( id !in flow_region_info ) - return [$have_est = F]; - - local regions_crossed = - int_to_count(flow_region_info[id]$num_regions - 1); - - local lower = regions_crossed * interregion_distance * 1.0; - local upper = lower + interregion_distance * 2.0; - local num_inconsis = flow_region_info[id]$num_inconsistent; - - delete flow_region_info[id]; - - return [$have_est = T, $lower = lower, $upper = upper, - $num_inconsistent = num_inconsis]; - } - - -# Returns a tcpdump filter corresponding to the number of regions and -# region size requested by the user. -# -# How to calculate the tcpdump filter used to hook packet_event to the -# secondary filter system? We are interested only in TCP packets whose -# seq number belongs to any of the test slices. Let's focus on the case -# of 4 regions, 16KB per region. -# -# The mask should be: [ x x L L L ... L L L x x ... x ] -# <---><---------------><---------> -# | | | -# | | +-> suffix: region size -# | +-> location: remaining bits -# +-> prefix: number of equidistant regions -# -# The 32-bit seq number is masked as follows: -# -# - suffix: defines size of the regions (16KB implies log_2(16KB) = 14 bits) -# -# - location: defines the exact location of the 4 regions. Note that, to -# minimize the amount of data we keep, the location will be distinct from -# zero, so segments with seq == 0 are not in a valid region -# -# - prefix: defines number of regions (4 implies log_2(4) = 2 bits) -# -# E.g., the mask will be seq_number & 0011...1100..00_2 = 00LL..LL00..00_2, -# which, by setting the location to 1010101010101010, will finally be -# seq_number & 0011...1100..00_2 = 00101010101010101000..00_2, i.e., -# seq_number & 0x3fffc000 = 0x2aaa8000. -# -# For that particular parameterization, we'd like to wind up with a -# packet event filter of "(tcp[4:4] & 0x3fffc000) == 0x2aaa8000". - -function get_event_filter(number_of_regions: count, region_size: count): string - { - local bits_number_of_regions = logarithm(2, number_of_regions); - local bits_region_size = logarithm(2, region_size); - local bits_remaining = - int_to_count(32 - bits_number_of_regions - bits_region_size); - - # Set the bits corresponding to the location: - # i = 0; - # while ( i < bits_remaining ) - # { - # mask = (mask * 2) + 1; - # filter = (filter * 2) + (((i % 2) == 0) ? 1 : 0); - # ++i; - # } - local mask = do_while(0, bits_remaining, 0, fn_mask_location); - local filter = do_while(0, bits_remaining, 0, fn_filter_location); - - # Set the bits corrsponding to the region size - # i = 0; - # while ( i < bits_region_size ) - # { - # mask = mask * 2; - # filter = filter * 2; - # ++i; - # } - mask = do_while(0, bits_region_size, mask, fn_common_region_size); - filter = do_while(0, bits_region_size, filter, fn_common_region_size); - - return fmt("(tcp[4:4] & 0x%x) == 0x%x", mask, filter); - } - - -# packet_event -- -# -# This event is raised once per (TCP) packet falling into any of the regions. -# It updates the flow_region_info table. -event packet_event(filter: string, pkt: pkt_hdr) - { - # Distill the region from the seq number. - local region = pkt$tcp$seq / interregion_distance; - - # Get packet info and update global counters. - local cid = [$orig_h = pkt$ip$src, $orig_p = pkt$tcp$sport, - $resp_h = pkt$ip$dst, $resp_p = pkt$tcp$dport]; - - if ( cid !in flow_region_info ) - { - flow_region_info[cid] = - [$last_region = region, $num_regions = 1, - $num_inconsistent = 0]; - return; - } - - local info = flow_region_info[cid]; - local next_region = (info$last_region + 1) % number_of_regions; - - if ( region == next_region ) - { # flow seen in the next region - info$last_region = region; - ++info$num_regions; - } - - else if ( region == info$last_region ) - { # flow seen in the same region, ignore - } - else - { - # Flow seen in another region (not the next one). - info$last_region = region; - info$num_regions = 1; # restart accounting - ++info$num_inconsistent; - } - } - - -# Glue the filter into the secondary filter hookup. -global packet_event_filter = get_event_filter(number_of_regions, region_size); -redef secondary_filters += { [packet_event_filter] = packet_event }; diff --git a/policy.old/listen-clear.bro b/policy.old/listen-clear.bro deleted file mode 100644 index 0922bc053e..0000000000 --- a/policy.old/listen-clear.bro +++ /dev/null @@ -1,16 +0,0 @@ -# $Id: listen-clear.bro 416 2004-09-17 03:52:28Z vern $ -# -# Listen for other Bros (non-SSL). - -@load remote - -# On which port to listen. -const listen_port_clear = Remote::default_port_clear &redef; - -# On which IP to bind (0.0.0.0 for any interface) -const listen_if_clear = 0.0.0.0 &redef; - -event bro_init() - { - listen(listen_if_clear, listen_port_clear, F); - } diff --git a/policy.old/listen-ssl.bro b/policy.old/listen-ssl.bro deleted file mode 100644 index fdf22a8e30..0000000000 --- a/policy.old/listen-ssl.bro +++ /dev/null @@ -1,16 +0,0 @@ -# $Id: listen-ssl.bro 1015 2005-01-31 13:46:50Z kreibich $ -# -# Listen for other Bros (SSL). - -@load remote - -# On which port to listen. -const listen_port_ssl = Remote::default_port_ssl &redef; - -# On which IP to bind (0.0.0.0 for any interface) -const listen_if_ssl = 0.0.0.0 &redef; - -event bro_init() - { - listen(listen_if_ssl, listen_port_ssl, T); - } diff --git a/policy.old/load-level.bro b/policy.old/load-level.bro deleted file mode 100644 index b8f9730bde..0000000000 --- a/policy.old/load-level.bro +++ /dev/null @@ -1,194 +0,0 @@ -# $Id: load-level.bro 1904 2005-12-14 03:27:15Z vern $ -# -# Support for shedding/reinstating load. - -@load notice - -# If no load_level is given, a filter is always activated. -# -# If a level is given for a filter (using the same ID than in -# {capture,restrict}_filter), then: -# -# - a capture_filter is activated if current load_level is <= -# - a restrict_filter is activated if current load_level is >= - -global capture_load_levels: table[string] of PcapFilterID &redef; -global restrict_load_levels: table[string] of PcapFilterID &redef; - -redef enum PcapFilterID += { - LoadLevel1, LoadLevel2, LoadLevel3, LoadLevel4, LoadLevel5, - LoadLevel6, LoadLevel7, LoadLevel8, LoadLevel9, LoadLevel10, -}; - -const Levels = { - LoadLevel1, LoadLevel2, LoadLevel3, LoadLevel4, LoadLevel5, - LoadLevel6, LoadLevel7, LoadLevel8, LoadLevel9, LoadLevel10 -}; - -# The load-level cannot not leave this interval. -const MinLoad = LoadLevel1; -const MaxLoad = LoadLevel10; - -# The initial load-level. -global default_load_level = LoadLevel10 &redef; - -# Set to 0 to turn off any changes of the filter. -global can_adjust_filter = T &redef; - -global current_load_level = DefaultPcapFilter; - -global ll_file = open_log_file("load-level"); - -# Interface functions for switching load levels. - -function set_load_level(level: PcapFilterID): bool - { - if ( level == current_load_level ) - return T; - - if ( ! can_adjust_filter ) - { - print ll_file, fmt("%.6f can't set %s (load-levels are turned off)", network_time(), level); - return F; - } - - if ( ! install_pcap_filter(level) ) - { - print ll_file, fmt("%.6f can't set %s (install failed)", network_time(), level); - - # Don't try again. - can_adjust_filter = F; - return F; - } - - current_load_level = level; - - print ll_file, fmt("%.6f switched to %s", network_time(), level); - - return T; - } - -# Too bad that we can't use enums like integers... -const IncreaseLoadLevelTab = { - [LoadLevel1] = LoadLevel2, - [LoadLevel2] = LoadLevel3, - [LoadLevel3] = LoadLevel4, - [LoadLevel4] = LoadLevel5, - [LoadLevel5] = LoadLevel6, - [LoadLevel6] = LoadLevel7, - [LoadLevel7] = LoadLevel8, - [LoadLevel8] = LoadLevel9, - [LoadLevel9] = LoadLevel10, - [LoadLevel10] = LoadLevel10, -}; - -const DecreaseLoadLevelTab = { - [LoadLevel1] = LoadLevel1, - [LoadLevel2] = LoadLevel1, - [LoadLevel3] = LoadLevel2, - [LoadLevel4] = LoadLevel3, - [LoadLevel5] = LoadLevel4, - [LoadLevel6] = LoadLevel5, - [LoadLevel7] = LoadLevel6, - [LoadLevel8] = LoadLevel7, - [LoadLevel9] = LoadLevel8, - [LoadLevel10] = LoadLevel9, -}; - -const LoadLevelToInt = { - [DefaultPcapFilter] = 0, - [LoadLevel1] = 1, - [LoadLevel2] = 2, - [LoadLevel3] = 3, - [LoadLevel4] = 4, - [LoadLevel5] = 5, - [LoadLevel6] = 6, - [LoadLevel7] = 7, - [LoadLevel8] = 8, - [LoadLevel9] = 9, - [LoadLevel10] = 10, -}; - -function increase_load_level() - { - set_load_level(IncreaseLoadLevelTab[current_load_level]); - } - -function decrease_load_level() - { - set_load_level(DecreaseLoadLevelTab[current_load_level]); - } - - -# Internal functions. - -function load_level_error() - { - print ll_file, fmt("%.6f Error, switching back to DefaultPcapFilter", - network_time()); - - install_default_pcap_filter(); - - # Don't try changing the load level any more. - can_adjust_filter = F; - } - -function build_load_level_filter(level: PcapFilterID): string - { - # Build up capture_filter. - local cfilter = ""; - - for ( id in capture_filters ) - { - if ( id !in capture_load_levels || - LoadLevelToInt[level] <= LoadLevelToInt[capture_load_levels[id]] ) - cfilter = add_to_pcap_filter(cfilter, capture_filters[id], "or"); - } - - # Build up restrict_filter. - local rfilter = ""; - for ( id in restrict_filters ) - { - if ( id !in restrict_load_levels || - LoadLevelToInt[level] >= LoadLevelToInt[restrict_load_levels[id]] ) - rfilter = add_to_pcap_filter(rfilter, restrict_filters[id], "and"); - } - - return join_filters(cfilter, rfilter); - } - -function precompile_load_level_filters(): bool - { - print ll_file, fmt("%.6f <<< Begin of precompilation", network_time() ); - - for ( i in Levels ) - { - local filter = build_load_level_filter(i); - - if ( ! precompile_pcap_filter(i, filter) ) - { - print ll_file, fmt("%.6f Level %d: %s", - network_time(), LoadLevelToInt[i], pcap_error()); - load_level_error(); - return F; - } - - print ll_file, fmt("%.6f Level %2d: %s", network_time(), LoadLevelToInt[i], filter); - } - - print ll_file, fmt("%.6f >>> End of precompilation", network_time() ); - - return T; - } - - -event bro_init() - { - set_buf(ll_file, F); - precompile_load_level_filters(); - set_load_level(default_load_level); - - # Don't adjust the filter when reading a trace. - if ( ! reading_live_traffic() ) - can_adjust_filter = F; - } diff --git a/policy.old/load-sample.bro b/policy.old/load-sample.bro deleted file mode 100644 index 16b26580ab..0000000000 --- a/policy.old/load-sample.bro +++ /dev/null @@ -1,43 +0,0 @@ -# $Id: load-sample.bro 1758 2005-11-22 00:58:10Z vern $ - -# A simple form of profiling based on sampling the work done per-packet. -# load_sample() is generated every load_sample_freq packets (roughly; -# it's randomized). For each sampled packet, "samples" contains a set -# of the functions, event handlers, and their source files that were accessed -# during the processing of that packet, along with an estimate of the -# CPU cost of processing the packet and (currently broken) memory allocated/ -# freed. - -global sampled_count: table[string] of count &default = 0; -global sampled_CPU: table[string] of interval &default = 0 sec; -global sampled_mem: table[string] of int &default = +0; - -global num_samples = 0; -global total_sampled_CPU = 0 sec; -global total_sampled_mem = +0; - -event load_sample(samples: load_sample_info, CPU: interval, dmem: int) - { - ++num_samples; - total_sampled_CPU += CPU; - total_sampled_mem += dmem; - - if ( |samples| == 0 ) - add samples[""]; - - for ( i in samples ) - { - ++sampled_count[i]; - sampled_CPU[i] += CPU; - sampled_mem[i] += dmem; - } - } - -event bro_done() - { - for ( i in sampled_CPU ) - print fmt("%s: %d%% pkts, %.1f%% CPU", - i, sampled_count[i] * 100 / num_samples, - sampled_CPU[i] * 100 / total_sampled_CPU); - # sampled_mem[i] / total_sampled_mem; - } diff --git a/policy.old/log-append.bro b/policy.old/log-append.bro deleted file mode 100644 index 440b78a894..0000000000 --- a/policy.old/log-append.bro +++ /dev/null @@ -1,10 +0,0 @@ -# $Id: log-append.bro 2797 2006-04-23 05:56:24Z vern $ - -# By default, logs are overwritten when opened, deleting the contents -# of any existing log of the same name. Loading this module changes the -# behavior to appending. - -function open_log_file(tag: string): file - { - return open_for_append(log_file_name(tag)); - } diff --git a/policy.old/login.bro b/policy.old/login.bro deleted file mode 100644 index 9d45249bb1..0000000000 --- a/policy.old/login.bro +++ /dev/null @@ -1,677 +0,0 @@ -# $Id: login.bro 6481 2008-12-15 00:47:57Z vern $ - -@load notice -@load weird -@load hot-ids -@load conn -# scan.bro is needed for "account_tried" event. -@load scan -@load demux -@load terminate-connection - -module Login; - -global telnet_ports = { 23/tcp } &redef; -redef dpd_config += { [ANALYZER_TELNET] = [$ports = telnet_ports] }; - -global rlogin_ports = { 513/tcp } &redef; -redef dpd_config += { [ANALYZER_RLOGIN] = [$ports = rlogin_ports] }; - -export { - redef enum Notice += { - SensitiveLogin, # interactive login using sensitive username - - # Interactive login seen using forbidden username, but the analyzer - # was confused in following the login dialog, so may be in error. - LoginForbiddenButConfused, - - # During a login dialog, a sensitive username (e.g., "rewt") was - # seen in the user's *password*. This is reported as a notice - # because it could be that the login analyzer didn't track the - # authentication dialog correctly, and in fact what it thinks is - # the user's password is instead the user's username. - SensitiveUsernameInPassword, - }; - - # If these patterns appear anywhere in the user's keystrokes, do a notice. - const input_trouble = - /rewt/ - | /eggdrop/ - | /\/bin\/eject/ - | /oir##t/ - | /ereeto/ - | /(shell|xploit)_?code/ - | /execshell/ - | /ff\.core/ - | /unset[ \t]+(histfile|history|HISTFILE|HISTORY)/ - | /neet\.tar/ - | /r0kk0/ - | /su[ \t]+(daemon|news|adm)/ - | /\.\/clean/ - | /rm[ \t]+-rf[ \t]+secure/ - | /cd[ \t]+\/dev\/[a-zA-Z]{3}/ - | /solsparc_lpset/ - | /\.\/[a-z]+[ \t]+passwd/ - | /\.\/bnc/ - | /bnc\.conf/ - | /\"\/bin\/ksh\"/ - | /LAST STAGE OF DELIRIUM/ - | /SNMPXDMID_PROG/ - | /snmpXdmid for solaris/ - | /\"\/bin\/uname/ - | /gcc[ \t]+1\.c/ - | />\/etc\/passwd/ - | /lynx[ \t]+-source[ \t]+.*(packetstorm|shellcode|linux|sparc)/ - | /gcc.*\/bin\/login/ - | /#define NOP.*0x/ - | /printf\(\"overflowing/ - | /exec[a-z]*\(\"\/usr\/openwin/ - | /perl[ \t]+.*x.*[0-9][0-9][0-9][0-9]/ - | /ping.*-s.*%d/ - &redef; - - # If this pattern appears anywhere in the user's input after applying - # / editing, do a notice ... - const edited_input_trouble = - /[ \t]*(cd|pushd|more|less|cat|vi|emacs|pine)[ \t]+((['"]?\.\.\.)|(["'](\.*)[ \t]))/ - &redef; - - # ... *unless* the corresponding output matches this: - const output_indicates_input_not_trouble = /No such file or directory/ &redef; - - # NOTICE on these, but only after waiting for the corresponding output, - # so it can be displayed at the same time. - const input_wait_for_output = edited_input_trouble &redef; - - # If the user's entire input matches this pattern, do a notice. Putting - # "loadmodule" here rather than in input_trouble is just to illustrate - # the idea, it could go in either. - const full_input_trouble = /.*loadmodule.*/ &redef; - - # If the following appears anywhere in the user's output, do a notice. - const output_trouble = - /^-r.s.*root.*\/bin\/(sh|csh|tcsh)/ - | /Jumping to address/ - | /Jumping Address/ - | /smashdu\.c/ - | /PATH_UTMP/ - | /Log started at =/ - | /www\.anticode\.com/ - | /www\.uberhax0r\.net/ - | /smurf\.c by TFreak/ - | /Super Linux Xploit/ - | /^# \[root@/ - | /^-r.s.*root.*\/bin\/(time|sh|csh|tcsh|bash|ksh)/ - | /invisibleX/ - | /PATH_(UTMP|WTMP|LASTLOG)/ - | /[0-9]{5,} bytes from/ - | /(PATH|STAT):\ .*=>/ - | /----- \[(FIN|RST|DATA LIMIT|Timed Out)\]/ - | /IDLE TIMEOUT/ - | /DATA LIMIT/ - | /-- TCP\/IP LOG --/ - | /STAT: (FIN|TIMED_OUT) / - | /(shell|xploit)_code/ - | /execshell/ - | /x86_bsd_compaexec/ - | /\\xbf\\xee\\xee\\xee\\x08\\xb8/ # from x.c worm - | /Coded by James Seter/ - | /Irc Proxy v/ - | /Daemon port\.\.\.\./ - | /BOT_VERSION/ - | /NICKCRYPT/ - | /\/etc\/\.core/ - | /exec.*\/bin\/newgrp/ - | /deadcafe/ - | /[ \/]snap\.sh/ - | /Secure atime,ctime,mtime/ - | /Can\'t fix checksum/ - | /Promisc Dectection/ - | /ADMsn0ofID/ - | /(cd \/; uname -a; pwd; id)/ - | /drw0rm/ - | /[Rr][Ee3][Ww][Tt][Ee3][Dd]/ - | /rpc\.sadmin/ - | /AbraxaS/ - | /\[target\]/ - | /ID_SENDSYN/ - | /ID_DISTROIT/ - | /by Mixter/ - | /rap(e?)ing.*using weapons/ - | /spsiod/ - | /[aA][dD][oO][rR][eE][bB][sS][dD]/ # rootkit - &redef; - - # Same, but must match entire output. - const full_output_trouble = /.*Trojaning in progress.*/ &redef; - - const backdoor_prompts = - /^[!-~]*( ?)[#%$] / - | /.*no job control/ - | /WinGate>/ - &redef; - - const non_backdoor_prompts = /^ *#.*#/ &redef; - const hot_terminal_types = /VT666|007/ &redef; - const hot_telnet_orig_ports = { 53982/tcp, } &redef; - const router_prompts: set[string] &redef; - const non_ASCII_hosts: set[addr] &redef; - const skip_logins_to = { non_ASCII_hosts, } &redef; - const always_hot_login_ids = { always_hot_ids } &redef; - const hot_login_ids = { hot_ids } &redef; - const rlogin_id_okay_if_no_password_exposed = { "root", } &redef; - - const BS = "\x08"; - const DEL = "\x7f"; - - global new_login_session: - function(c: connection, pid: peer_id, output_line: count); - global remove_login_session: function(c: connection, pid: peer_id); - global ext_set_login_state: - function(cid: conn_id, pid: peer_id, state: count); - global ext_get_login_state: - function(cid: conn_id, pid: peer_id): count; -} - -redef capture_filters += { ["login"] = "port telnet or tcp port 513" }; - -redef skip_authentication = { - "WELCOME TO THE BERKELEY PUBLIC LIBRARY", -}; - -redef direct_login_prompts = { "TERMINAL?", }; - -redef login_prompts = { - "Login:", "login:", "Name:", "Username:", "User:", "Member Name", - "User Access Verification", "Cisco Systems Console", - direct_login_prompts -}; - -redef login_non_failure_msgs = { - "Failures", "failures", # probably is " failures since last login" - "failure since last successful login", - "failures since last successful login", -}; - -redef login_non_failure_msgs = { - "Failures", "failures", # probably is " failures since last login" - "failure since last successful login", - "failures since last successful login", -} &redef; - -redef login_failure_msgs = { - "invalid", "Invalid", "incorrect", "Incorrect", "failure", "Failure", - # "Unable to authenticate", "unable to authenticate", - "User authorization failure", - "Login failed", - "INVALID", "Sorry.", "Sorry,", -}; - -redef login_success_msgs = { - "Last login", - "Last successful login", "Last successful login", - "checking for disk quotas", "unsuccessful login attempts", - "failure since last successful login", - "failures since last successful login", - router_prompts, -}; - -redef login_timeouts = { - "timeout", "timed out", "Timeout", "Timed out", - "Error reading command input", # VMS -}; - - -type check_info: record { - expanded_line: string; # line with all possible editing seqs - hot: bool; # whether any editing sequence was a hot user id - hot_id: string; # the ID considered hot - forbidden: bool; # same, but forbidden user id -}; - -type login_session_info: record { - user: string; - output_line: count; # number of lines seen - - # input string for which we want to match the output. - waiting_for_output: string; - waiting_for_output_line: count; # output line we want to match it to - state: count; # valid for external connections only -}; - -global login_sessions: table[peer_id, conn_id] of login_session_info; - - -# The next two functions are "external-to-the-event-engine", -# hence the ext_ prefix. They're used by the script to manage -# login state so that they can work with login sessions unknown -# to the event engine (such as those received from remote peers). - -function ext_get_login_state(cid: conn_id, pid: peer_id): count - { - if ( pid == PEER_ID_NONE ) - return get_login_state(cid); - - return login_sessions[pid, cid]$state; - } - -function ext_set_login_state(cid: conn_id, pid: peer_id, state: count) - { - if ( pid == PEER_ID_NONE ) - set_login_state(cid, state); - else - login_sessions[pid, cid]$state = state; - } - -function new_login_session(c: connection, pid: peer_id, output_line: count) - { - local s: login_session_info; - s$waiting_for_output = s$user = ""; - s$output_line = output_line; - s$state = LOGIN_STATE_AUTHENTICATE; - - login_sessions[pid, c$id] = s; - } - -function remove_login_session(c: connection, pid: peer_id) - { - delete login_sessions[pid, c$id]; - } - -function is_login_conn(c: connection): bool - { - return c$id$resp_p == telnet || c$id$resp_p == rlogin; - } - -function hot_login(c: connection, pid: peer_id, msg: string, tag: string) - { - if ( [pid, c$id] in login_sessions ) - NOTICE([$note=SensitiveLogin, $conn=c, - $user=login_sessions[pid, c$id]$user, $msg=msg]); - else - NOTICE([$note=SensitiveLogin, $conn=c, $msg=msg]); - - ++c$hot; - demux_conn(c$id, tag, "keys", service_name(c)); - } - -function is_hot_id(id: string, successful: bool, confused: bool): bool - { - return successful ? id in hot_login_ids : - (confused ? id in forbidden_ids : - id in always_hot_login_ids); - } - -function is_forbidden_id(id: string): bool - { - return id in forbidden_ids || id == forbidden_id_patterns; - } - -function edit_and_check_line(c: connection, pid: peer_id, line: string, - successful: bool): check_info - { - line = to_lower(line); - - local ctrl_H_edit = edit(line, BS); - local del_edit = edit(line, DEL); - - local confused = - (ext_get_login_state(c$id, pid) == LOGIN_STATE_CONFUSED); - local hot = is_hot_id(line, successful, confused); - local hot_id = hot ? line : ""; - local forbidden = is_forbidden_id(line); - - local eline = line; - - if ( ctrl_H_edit != line ) - { - eline = fmt("%s,%s", eline, ctrl_H_edit); - if ( ! hot && is_hot_id(ctrl_H_edit, successful, confused) ) - { - hot = T; - hot_id = ctrl_H_edit; - } - - forbidden = forbidden || is_forbidden_id(ctrl_H_edit); - } - - if ( del_edit != line ) - { - eline = fmt("%s,%s", eline, del_edit); - if ( ! hot && is_hot_id(del_edit, successful, confused) ) - { - hot = T; - hot_id = del_edit; - } - - forbidden = forbidden || is_forbidden_id(del_edit); - } - - local results: check_info; - results$expanded_line = eline; - results$hot = hot; - results$hot_id = hot_id; - results$forbidden = forbidden; - - return results; - } - -function edit_and_check_user(c: connection, pid: peer_id, user: string, - successful: bool, fmt_s: string): bool - { - local check = edit_and_check_line(c, pid, user, successful); - - if ( [pid, c$id] !in login_sessions ) - new_login_session(c, pid, 9999); - - login_sessions[pid, c$id]$user = check$expanded_line; - - c$addl = fmt(fmt_s, c$addl, check$expanded_line); - - if ( check$hot ) - { - ++c$hot; - demux_conn(c$id, check$hot_id, "keys", service_name(c)); - } - - if ( check$forbidden ) - { - if ( ext_get_login_state(c$id, pid) == LOGIN_STATE_CONFUSED ) - NOTICE([$note=LoginForbiddenButConfused, $conn=c, - $user = user, - $msg=fmt("not terminating %s because confused about state", full_id_string(c))]); - else - TerminateConnection::terminate_connection(c); - } - - return c$hot > 0; - } - -function edit_and_check_password(c: connection, pid: peer_id, password: string) - { - local check = edit_and_check_line(c, pid, password, T); - if ( check$hot ) - { - ++c$hot; - NOTICE([$note=SensitiveUsernameInPassword, $conn=c, - $user=password, - $msg=fmt("%s password: \"%s\"", - id_string(c$id), check$expanded_line)]); - } - } - -event login_failure(c: connection, user: string, client_user: string, - password: string, line: string) - { - local pid = get_event_peer()$id; - - event account_tried(c, user, password); - edit_and_check_password(c, pid, password); - - if ( c$hot == 0 && password == "" && - ! edit_and_check_line(c, pid, user, F)$hot ) - # Don't both reporting it, this was clearly a half-hearted - # attempt and it's not a sensitive username. - return; - - local user_hot = edit_and_check_user(c, pid, user, F, "%sfail/%s "); - if ( client_user != "" && client_user != user && - edit_and_check_user(c, pid, client_user, F, "%s(%s) ") ) - user_hot = T; - - if ( user_hot || c$hot > 0 ) - NOTICE([$note=SensitiveLogin, $conn=c, - $user=user, $sub=client_user, - $msg=fmt("%s %s", id_string(c$id), c$addl)]); - } - -event login_success(c: connection, user: string, client_user: string, - password: string, line: string) - { - local pid = get_event_peer()$id; - - Hot::check_hot(c, Hot::APPL_ESTABLISHED); - event account_tried(c, user, password); - edit_and_check_password(c, pid, password); - - # Look for whether the user name is sensitive; but allow for - # some ids being okay if no password was exposed accessing them. - local user_hot = F; - if ( c$id$resp_p == rlogin && password == "" && - user in rlogin_id_okay_if_no_password_exposed ) - append_addl(c, fmt("\"%s\"", user)); - - else - user_hot = edit_and_check_user(c, pid, user, T, "%s\"%s\" "); - - if ( c$id$resp_p == rlogin && client_user in always_hot_login_ids ) - { - append_addl(c, fmt("(%s)", client_user)); - demux_conn(c$id, client_user, "keys", service_name(c)); - user_hot = T; - } - - if ( user_hot || c$hot > 0 ) - NOTICE([$note=SensitiveLogin, $conn=c, - $user=user, $sub=client_user, - $msg=fmt("%s %s", id_string(c$id), c$addl)]); - - # else if ( password == "" ) - # alarm fmt("%s %s ", id_string(c$id), c$addl); - -### use the following if no login_input_line/login_output_line -# else -# { -# set_record_packets(c$id, F); -# skip_further_processing(c$id); -# } - } - -event login_input_line(c: connection, line: string) - { - local pid = get_event_peer()$id; - local BS_line = edit(line, BS); - local DEL_line = edit(line, DEL); - if ( input_trouble in line || - ### need to merge input_trouble and edited_input_trouble here - ### ideally, match on input_trouble would tell whether we need - ### to invoke the edit functions, as an attribute of a .*(^H|DEL) - ### rule. - input_trouble in BS_line || input_trouble in DEL_line || - (edited_input_trouble in BS_line && - # If one is in but the other not, then the one that's not - # is presumably the correct edit, and the one that is, isn't - # in fact edited at all - edited_input_trouble in DEL_line) || - line == full_input_trouble ) - { - if ( [pid, c$id] !in login_sessions ) - new_login_session(c, pid, 9999); - - if ( edited_input_trouble in BS_line && - edited_input_trouble in DEL_line ) - { - login_sessions[pid, c$id]$waiting_for_output = line; - login_sessions[pid, c$id]$waiting_for_output_line = - # We don't want the *next* line, that's just - # the echo of this input. - login_sessions[pid, c$id]$output_line + 2; - } - - else if ( ++c$hot <= 2 ) - hot_login(c, pid, fmt("%s input \"%s\"", id_string(c$id), line), "trb"); - } - } - -event login_output_line(c: connection, line: string) - { - local pid = get_event_peer()$id; - if ( [pid, c$id] !in login_sessions ) - new_login_session(c, pid, 9999); - - local s = login_sessions[pid, c$id]; - - if ( line != "" && ++s$output_line == 1 ) - { - if ( byte_len(line) < 40 && - backdoor_prompts in line && non_backdoor_prompts !in line ) - hot_login(c, pid, fmt("%s possible backdoor \"%s\"", id_string(c$id), line), "trb"); - } - - if ( s$waiting_for_output != "" && - s$output_line >= s$waiting_for_output_line ) - { - if ( output_indicates_input_not_trouble !in line ) - hot_login(c, pid, - fmt("%s input \"%s\" yielded output \"%s\"", - id_string(c$id), - s$waiting_for_output, - line), - "trb"); - - s$waiting_for_output = ""; - } - - if ( byte_len(line) < 256 && - (output_trouble in line || line == full_output_trouble) && - ++c$hot <= 2 ) - hot_login(c, pid, fmt("%s output \"%s\"", id_string(c$id), line), "trb"); - } - -event login_confused(c: connection, msg: string, line: string) - { - Hot::check_hot(c, Hot::APPL_ESTABLISHED); - - append_addl(c, ""); - - event conn_weird_addl(msg, c, line); - - set_record_packets(c$id, T); - } - -event login_confused_text(c: connection, line: string) - { - local pid = get_event_peer()$id; - if ( c$hot == 0 && edit_and_check_line(c, pid, line, F)$hot ) - { - local ignore = - edit_and_check_user(c, pid, line, F, "%sconfused/%s "); - NOTICE([$note=SensitiveLogin, $conn=c, - $user=line, - $msg=fmt("%s %s", id_string(c$id), c$addl)]); - set_record_packets(c$id, T); - } - } - -event login_terminal(c: connection, terminal: string) - { - local pid = get_event_peer()$id; - if ( hot_terminal_types in terminal ) - hot_login(c, pid, - fmt("%s term %s", id_string(c$id), terminal), "trb"); - } - -event login_prompt(c: connection, prompt: string) - { - # Could check length >= 6, per Solaris exploit ... - local pid = get_event_peer()$id; - hot_login(c, pid, - fmt("%s $TTYPROMPT %s", id_string(c$id), prompt), "trb"); - } - -event excessive_line(c: connection) - { - if ( is_login_conn(c) ) - { - local pid = get_event_peer()$id; - - if ( ! c$hot && c$id$resp_h in non_ASCII_hosts ) - { - ext_set_login_state(c$id, pid, LOGIN_STATE_SKIP); - set_record_packets(c$id, F); - } - else if ( ext_get_login_state(c$id, pid) == LOGIN_STATE_AUTHENTICATE ) - { - event login_confused(c, "excessive_line", ""); - ext_set_login_state(c$id, pid, LOGIN_STATE_CONFUSED); - } - } - } - -event inconsistent_option(c: connection) - { - print Weird::weird_file, fmt("%.6f %s inconsistent option", network_time(), id_string(c$id)); - } - -event bad_option(c: connection) - { - print Weird::weird_file, fmt("%.6f %s bad option", network_time(), id_string(c$id)); - } - -event bad_option_termination(c: connection) - { - print Weird::weird_file, fmt("%.6f %s bad option termination", network_time(), id_string(c$id)); - } - -event authentication_accepted(name: string, c: connection) - { - local addl_msg = fmt("auth/%s", name); - append_addl(c, addl_msg); - } - -event authentication_rejected(name: string, c: connection) - { - append_addl(c, fmt("auth-failed/%s", name)); - } - -event authentication_skipped(c: connection) - { - append_addl(c, "(skipped)"); - skip_further_processing(c$id); - - if ( ! c$hot ) - set_record_packets(c$id, F); - } - -event connection_established(c: connection) - { - if ( is_login_conn(c) ) - { - local pid = get_event_peer()$id; - - new_login_session(c, pid, 0); - - if ( c$id$resp_h in skip_logins_to ) - event authentication_skipped(c); - - if ( c$id$resp_p == telnet && - c$id$orig_p in hot_telnet_orig_ports ) - hot_login(c, pid, fmt("%s hot_orig_port", id_string(c$id)), "orig"); - } - } - -event partial_connection(c: connection) - { - if ( is_login_conn(c) ) - { - local pid = get_event_peer()$id; - new_login_session(c, pid, 9999); - ext_set_login_state(c$id, pid, LOGIN_STATE_CONFUSED); - - if ( c$id$resp_p == telnet && - c$id$orig_p in hot_telnet_orig_ports ) - hot_login(c, pid, fmt("%s hot_orig_port", id_string(c$id)), "orig"); - } - } - -event connection_finished(c: connection) - { - local pid = get_event_peer()$id; - remove_login_session(c, pid); - } - -event activating_encryption(c: connection) - { - if ( is_login_conn(c) ) - append_addl(c, "(encrypted)"); - } diff --git a/policy.old/mime-pop.bro b/policy.old/mime-pop.bro deleted file mode 100644 index eed2565036..0000000000 --- a/policy.old/mime-pop.bro +++ /dev/null @@ -1,180 +0,0 @@ -# $Id: mime-pop.bro 4758 2007-08-10 06:49:23Z vern $ -# -# A stripped-down version of mime.bro adapted to work on POP3 events. -# -# FIXME: What's the best way to merge mime.bro and mime-pop3.bro? - -@load pop3 - -module MIME_POP3; - -const mime_log = open_log_file("mime-pop") &redef; - -type mime_session_info: record { - id: count; - connection_id: conn_id; - level: count; - data_offset: count; -}; - -global mime_session_id = 0; -global mime_sessions: table[conn_id] of mime_session_info; - -function mime_session_string(session: mime_session_info): string - { - return fmt("#%s %s +%d", prefixed_id(session$id), - id_string(session$connection_id), session$level); - } - -function mime_log_warning(what: string) - { - print mime_log, fmt("%.6f warning: %s", network_time(), what); - } - -function mime_log_msg(session: mime_session_info, where: string, what: string) - { - print mime_log, fmt("%.6f %s: [%s] %s", - network_time(), - mime_session_string(session), - where, - what); - } - -function new_mime_session(c: connection) - { - local id = c$id; - local session_id = ++mime_session_id; - local info: mime_session_info; - - info$id = session_id; - info$connection_id = id; - info$level = 0; - info$data_offset = 0; - - mime_sessions[id] = info; - mime_log_msg(info, "start", ""); - } - -function get_mime_session(c: connection, new_session_ok: bool): mime_session_info - { - local id = c$id; - - if ( id !in mime_sessions ) - { - if ( ! new_session_ok ) - mime_log_warning(fmt("begin_entity missing for new MIME session %s", id_string(id))); - - new_mime_session(c); - } - - return mime_sessions[id]; - } - -function end_mime_session(session: mime_session_info) - { - mime_log_msg(session, "finish", ""); - delete mime_sessions[session$connection_id]; - } - -event connection_state_remove(c: connection) - { - if ( c$id$resp_p != 110/tcp ) - return; - - local id = c$id; - - if ( id in mime_sessions ) - { - mime_log_msg(mime_sessions[id], "state remove", ""); - delete mime_sessions[id]; - } - } - -function do_mime_begin_entity(c: connection) - { - local session = get_mime_session(c, T); - - ++session$level; - session$data_offset = 0; - mime_log_msg(session, "begin entity", ""); - } - -event mime_begin_entity(c: connection) - { - if ( c$id$resp_p != 110/tcp ) - return; - - do_mime_begin_entity(c); - } - -function do_mime_end_entity(c: connection) - { - local session = get_mime_session(c, T); - - mime_log_msg(session, "end entity", ""); - - if ( session$level > 0 ) - { - --session$level; - if ( session$level == 0 ) - end_mime_session(session); - } - else - mime_log_warning(fmt("unmatched end_entity for MIME session %s", - mime_session_string(session))); - } - -event mime_end_entity(c: connection) - { - if ( c$id$resp_p != 110/tcp ) - return; - - do_mime_end_entity(c); - } - -event mime_next_entity(c: connection) - { - if ( c$id$resp_p != 110/tcp ) - return; - - do_mime_end_entity(c); - do_mime_begin_entity(c); - } - -event mime_all_headers(c: connection, hlist: mime_header_list) - { - if ( c$id$resp_p != 110/tcp ) - return; - - local session = get_mime_session(c, T); - local i = 0; - - for ( i in hlist ) - { - local h = hlist[i]; - mime_log_msg(session, "header", - fmt("%s: \"%s\"", h$name, h$value)); - } - } - -event mime_segment_data(c: connection, length: count, data: string) - { - if ( c$id$resp_p != 110/tcp ) - return; - - local session = get_mime_session(c, T); - - if ( session$data_offset < 256 ) - mime_log_msg(session, "data", fmt("%d: %s", length, data)); - - session$data_offset = session$data_offset + length; - } - -event mime_event(c: connection, event_type: string, detail: string) - { - if ( c$id$resp_p != 110/tcp ) - return; - - local session = get_mime_session(c, T); - mime_log_msg(session, "event", fmt("%s: %s", event_type, detail)); - } diff --git a/policy.old/mt.bro b/policy.old/mt.bro deleted file mode 100644 index 1a39bc1025..0000000000 --- a/policy.old/mt.bro +++ /dev/null @@ -1,15 +0,0 @@ -# $Id: mt.bro 340 2004-09-09 06:38:27Z vern $ - -@load dns-lookup -@load hot -@load frag -@load tcp -@load scan -@load weird -@load finger -@load ident -@load ftp -@load login -@load portmapper -@load ntp -@load tftp diff --git a/policy.old/ncp.bro b/policy.old/ncp.bro deleted file mode 100644 index 53a798eec3..0000000000 --- a/policy.old/ncp.bro +++ /dev/null @@ -1,101 +0,0 @@ -# $Id:$ - -@load conn-id - -module NCP; - -global ncp_log = open_log_file("ncp") &redef; - -redef capture_filters += {["ncp"] = "tcp port 524"}; - -export { - -const ncp_frame_type_name = { - [ 0x1111 ] = "NCP_ALLOC_SLOT", - [ 0x2222 ] = "NCP_REQUEST", - [ 0x3333 ] = "NCP_REPLY", - [ 0x5555 ] = "NCP_DEALLOC_SLOT", - [ 0x7777 ] = "NCP_BURST", - [ 0x9999 ] = "NCP_ACK", -} &default = function(code: count): string - { - return fmt("NCP_UNKNOWN_FRAME_TYPE(%x)", code); - }; - -const ncp_function_name = { - [ 0x01 ] = "NCP_FILE_SET_LOCK", - [ 0x02 ] = "NCP_FILE_RELEASE_LOCK", - [ 0x03 ] = "NCP_LOG_FILE", - [ 0x04 ] = "NCP_LOCK_FILE_SET", - [ 0x05 ] = "NCP_RELEASE_FILE", - [ 0x06 ] = "NCP_RELEASE_FILE_SET", - [ 0x07 ] = "NCP_CLEAR_FILE", - [ 0x08 ] = "NCP_CLEAR_FILE_SET", - [ 0x09 ] = "NCP_LOG_LOGICAL_RECORD", - [ 0x0a ] = "NCP_LOCK_LOGICAL_RECORD_SET", - [ 0x0b ] = "NCP_CLEAR_LOGICAL_RECORD", - [ 0x0c ] = "NCP_RELEASE_LOGICAL_RECORD", - [ 0x0d ] = "NCP_RELEASE_LOGICAL_RECORD_SET", - [ 0x0e ] = "NCP_CLEAR_LOGICAL_RECORD_SET", - [ 0x0f ] = "NCP_ALLOC_RESOURCE", - [ 0x10 ] = "NCP_DEALLOC_RESOURCE", - [ 0x11 ] = "NCP_PRINT", - [ 0x15 ] = "NCP_MESSAGE", - [ 0x16 ] = "NCP_DIRECTORY", - [ 0x17 ] = "NCP_BINDARY_AND_MISC", - [ 0x18 ] = "NCP_END_OF_JOB", - [ 0x19 ] = "NCP_LOGOUT", - [ 0x1a ] = "NCP_LOG_PHYSICAL_RECORD", - [ 0x1b ] = "NCP_LOCK_PHYSICAL_RECORD_SET", - [ 0x1c ] = "NCP_RELEASE_PHYSICAL_RECORD", - [ 0x1d ] = "NCP_RELEASE_PHYSICAL_RECORD_SET", - [ 0x1e ] = "NCP_CLEAR_PHYSICAL_RECORD", - [ 0x1f ] = "NCP_CLEAR_PHYSICAL_RECORD_SET", - [ 0x20 ] = "NCP_SEMAPHORE", - [ 0x22 ] = "NCP_TRANSACTION_TRACKING", - [ 0x23 ] = "NCP_AFP", - [ 0x42 ] = "NCP_CLOSE_FILE", - [ 0x47 ] = "NCP_GET_FILE_SIZE", - [ 0x48 ] = "NCP_READ_FILE", - [ 0x49 ] = "NCP_WRITE_FILE", - [ 0x56 ] = "NCP_EXT_ATTR", - [ 0x57 ] = "NCP_FILE_DIR", - [ 0x58 ] = "NCP_AUDITING", - [ 0x5a ] = "NCP_MIGRATION", - [ 0x60 ] = "NCP_PNW", - [ 0x61 ] = "NCP_GET_MAX_PACKET_SIZE", - [ 0x68 ] = "NCP_NDS", - [ 0x6f ] = "NCP_SEMAPHORE_NEW", - [ 0x7b ] = "NCP_7B", - - [ 0x5701 ] = "NCP_CREATE_FILE_DIR", - [ 0x5702 ] = "NCP_INIT_SEARCH", - [ 0x5703 ] = "NCP_SEARCH_FILE_DIR", - [ 0x5704 ] = "NCP_RENAME_FILE_DIR", - [ 0x5706 ] = "NCP_OBTAIN_FILE_DIR_INFO", - [ 0x5707 ] = "NCP_MODIFY_FILE_DIR_DOS_INFO", - [ 0x5708 ] = "NCP_DELETE_FILE_DIR", - [ 0x5709 ] = "NCP_SET_SHORT_DIR_HANDLE", - [ 0x5714 ] = "NCP_SEARCH_FOR_FILE_DIR_SET", - [ 0x5718 ] = "NCP_GET_NAME_SPACE_LOADED_LIST", - [ 0x5742 ] = "NCP_GET_CURRENT_SIZE_OF_FILE", - -} &default = function(code: count): string - { - return fmt("NCP_UNKNOWN_FUNCTION(%x)", code); - }; - -} # export - -event ncp_request(c: connection, frame_type: count, length: count, func: count) - { - print ncp_log, fmt("%.6f %s NCP request type=%s function=%s", - network_time(), id_string(c$id), - ncp_frame_type_name[frame_type], - ncp_function_name[func]); - } - -event ncp_reply(c: connection, frame_type: count, length: count, - req_frame: count, req_func: count, completion_code: count) - { - } diff --git a/policy.old/netflow.bro b/policy.old/netflow.bro deleted file mode 100644 index 4fb1ac0fd0..0000000000 --- a/policy.old/netflow.bro +++ /dev/null @@ -1,106 +0,0 @@ -# $Id:$ -# -# Netflow data-dumper and proof-of-concept flow restitcher. -# Written by Bernhard Ager (2007). - -module NetFlow; - -export { - # Perform flow restitching? - global netflow_restitch = T &redef; - - # How long to wait for additional flow records after a RST or FIN, - # so we can compress multiple RST/FINs for the same flow rather than - # treating them as separate flows. It's not clear what's the best - # setting for this timer, but for now we use something larger - # than the NetFlow inactivity timeout (5 minutes). - global netflow_finished_conn_expire = 310 sec &redef; -} - -global netflow_log = open_log_file("netflow") &redef; - -# Should be larger than activity timeout. Setting only affects table -# declaration, therefore &redef useless. -const netflow_table_expire = 31 min; - -type flow: record { - cnt: count; - pkts: count; - octets: count; - syn: bool; - fin: bool; - first: time; - last: time; -}; - -function new_flow(r: nf_v5_record): flow - { - return [ $cnt = 1, - $pkts = r$pkts, - $octets = r$octets, - $syn = r$tcpflag_syn, - $fin = r$tcpflag_fin, - $first = r$first, - $last = r$last ]; - } - -function update_flow(f: flow, r: nf_v5_record) - { - f$pkts += r$pkts; - f$octets += r$octets; - ++f$cnt; - f$syn = f$syn || r$tcpflag_syn; - f$fin = f$fin || r$tcpflag_fin; - - if ( r$first < f$first ) - f$first = r$first; - if ( r$last > f$last ) - f$last = r$last; - } - -function print_flow(t: table[conn_id] of flow, idx: conn_id): interval - { - print netflow_log, fmt("%.6f flow %s: %s", network_time(), idx, t[idx]); - return -1 sec; - } - -event v5flow_finished(t: table[conn_id] of flow, idx: conn_id) - { - if ( idx in t ) - { - print_flow(t, idx); - delete t[idx]; - } - } - -global flows: table[conn_id] of flow &write_expire = netflow_table_expire - &expire_func = print_flow; - -event netflow_v5_header(h: nf_v5_header) - { - print netflow_log, fmt("%.6f header %s", network_time(), h); - } - -event netflow_v5_record (r: nf_v5_record) - { - if ( netflow_restitch ) - { - if ( r$id in flows ) - update_flow (flows[r$id], r); - else - flows[r$id] = new_flow (r); - - if ( r$tcpflag_fin || r$tcpflag_rst ) - schedule netflow_finished_conn_expire { - v5flow_finished (flows, r$id) - }; - } - - print netflow_log, fmt("%.6f record %s", network_time(), r); - } - -event bro_done () - { - for ( f_id in flows ) - print_flow(flows, f_id); - } diff --git a/policy.old/netstats.bro b/policy.old/netstats.bro deleted file mode 100644 index 606513bcd9..0000000000 --- a/policy.old/netstats.bro +++ /dev/null @@ -1,32 +0,0 @@ -# $Id: netstats.bro 564 2004-10-23 02:27:57Z vern $ - -@load notice - -redef enum Notice += { - DroppedPackets, # Bro reported packets dropped by the packet filter -}; - -const stats_collection_interval = 10secs; - -event net_stats_update(last_stat: NetStats) - { - local ns = net_stats(); - local new_dropped = ns$pkts_dropped - last_stat$pkts_dropped; - if ( new_dropped > 0 ) - { - local new_recvd = ns$pkts_recvd - last_stat$pkts_recvd; - local new_link = ns$pkts_link - last_stat$pkts_link; - NOTICE([$note=DroppedPackets, - $msg=fmt("%d packets dropped after filtering, %d received%s", - new_dropped, new_recvd + new_dropped, - new_link != 0 ? - fmt(", %d on link", new_link) : "")]); - } - - schedule stats_collection_interval { net_stats_update(ns) }; - } - -event bro_init() - { - schedule stats_collection_interval { net_stats_update(net_stats()) }; - } \ No newline at end of file diff --git a/policy.old/nfs.bro b/policy.old/nfs.bro deleted file mode 100644 index 0d572b52c7..0000000000 --- a/policy.old/nfs.bro +++ /dev/null @@ -1,408 +0,0 @@ - -@load udp - - -module NFS3; - -export { - global log_file = open_log_file("nfs") &redef; - global names_log_file = open_log_file("nfs-files") &redef; - global readdir_log = open_log_file("nfs-readdir") &redef; - - # We want to estimate how long it takes to lookup a chain of FH (directories) - # until we reach a FH that is used in a read or write operation. Whenever we - # get a new FH, we check how long ago we got the FH's parent. If this is less - # than fh_chain_maxtime, we assume that they belong to a lookup chain and set - # the dt value for the FH accordingly. - global fh_chain_maxtime = 100 msec; -} - - -redef capture_filters += { - ["nfs"] = "port 2049", - # NFS UDP packets are often fragmented. - ["nfs-frag"] = "(ip[6:2] & 0x3fff != 0) and udp", -}; - -global nfs_ports = { 2049/tcp, 2049/udp } &redef; -redef dpd_config += { [ANALYZER_NFS] = [$ports = nfs_ports] }; - -# Information about a filehandle -type fh_info : record { - id: count; # A unique ID (counter) for more readable representation of the FH - pathname: string &default="@"; # the path leading to this FH - basename: string &default=""; # the name of this FHs file or directory - mimetype: string &default=""; - t0: time &default=double_to_time(0); # time when we first saw this FH - dt: interval &default=0 sec; # time it took to get this FH (assuming a chain of - # procedures that ultimately yield the FH for the file - # a client is interested in - chainlen: count &default=0; - attr: fattr_t &optional; -}; - -# Maps opaque file handles to numbers for easier tracking. -global num_fhs = 0; -global fh_map: table[addr,string] of fh_info; - -# Maps connids to number for easier post processing -global num_nfs_conns = 0; -global nfs_conns: table[conn_id] of count; - - -# Get the FH info. Create a new info if it doesn't exists -function get_fh_info(c: connection, fh: string): fh_info - { - if ( [c$id$resp_h, fh] !in fh_map ) - { - # Don't have a mapping for this FH yet. E.g., a root FH - local newfhinfo: fh_info = [ $id=++num_fhs ]; - newfhinfo$pathname = fmt("@%d", newfhinfo$id); - newfhinfo$t0 = network_time(); - fh_map[c$id$resp_h, fh] = newfhinfo; - } - return fh_map[c$id$resp_h, fh]; - } - -function log_filename(proc: string, info: fh_info) - { - print names_log_file, fmt("%.6f %s path FH%d %s/%s", network_time(), proc, - info$id, info$pathname, info$basename); - ##print fmt("%.6f FH%d <%s> <%s>", network_time(), info$id, info$pathname, info$basename); - } - -function fmt_attr(a: fattr_t): string - { - local s = fmt("%s %s %d %d %d %d %d %d %d %d %d %.2f %.2f %.2f", - a$ftype, mode2string(a$mode), a$nlink, a$uid, a$gid, a$size, a$used, a$rdev1, a$rdev2, - a$fsid, a$fileid, a$atime, a$mtime, a$ctime); - return s; - } - -function log_attributes(c: connection, proc: string, fh: string, attr: fattr_t) - { - local info = get_fh_info(c,fh); - local did_change = F; - # check whether the attributes have changes - if (info?$attr) - { - # We can't compare records for equality :-(. So we use a hack. - # We add the two instance we want to compare to a set. If there - # are two elements in the set, the records are not equal... - local dummy: set[fattr_t]; - add dummy[info$attr]; - add dummy[attr]; - if (|dummy| > 1) - did_change = T; - } - else - did_change=T; - if (did_change) - { - info$attr = attr; - print names_log_file, fmt("%.6f %s attr FH%d %s", network_time(), proc, - info$id, fmt_attr(attr)); - } - } - -# Update (or add) a filehandle mapping. -# parentfh ... parent (directory) -# name ....... the name for this FH -# fh ......... the new FH -function add_update_fh(c: connection, proc: string, parentfh: string, name: string, fh: string) - { - local info = get_fh_info(c, fh); - - # TODO: we could/should check if we already have a pathname and/or basename - # for this FH and if so whether it matches the parent we just got! - if (name == ".") - return; - info$basename = name; - if (parentfh != "") - { - local parentinfo = get_fh_info(c, parentfh); - info$pathname = cat(parentinfo$pathname, "/", parentinfo$basename); - if ( (network_time() - parentinfo$t0) < fh_chain_maxtime - && info$dt < 0 sec ) - { - # The FH is part of lookup chain and it doesn't yet have a dt value - # TODO: this should probably be moved to get_fh_info(). But then get_fh_info() - # would need information about a FH's parent.... - # TODO: We are using network_time(), but we really should use request - # and reply time!!! - info$dt = parentinfo$dt + (network_time() - parentinfo$t0); - info$chainlen = parentinfo$chainlen + 1; - } - } - log_filename(proc, info); - } - -function set_fh_mimetype(c: connection, fh: string, proc:string, data: string) - { - local info = get_fh_info(c,fh); - local mimetype = identify_data(data, T); - if (info$mimetype != mimetype) - { - info$mimetype = mimetype; - print names_log_file, fmt("%.6f %s type FH%d %s/%s %s", network_time(), proc, - info$id, info$pathname, info$basename, (mimetype!="") ? mimetype : "X/X"); - } - } - -# Get the total time of the lookup chain for this FH to the -# current network time. Returns a negative interal if no -# lookup chain was found -function get_fh_chaintime_str(c:connection, fh:string): string - { - local info = get_fh_info(c, fh); - if ((network_time() - info$t0) < fh_chain_maxtime) - return fmt("%d %.6f", info$chainlen, info$dt + (network_time() - info$t0)); - else - return fmt("%d %.6f", 0, 0.0); - } - -# Get a FH ID -function get_fh_id(c:connection, fh: string): string - { - return cat("FH", get_fh_info(c, fh)$id); - } - -# Get the basename for the FH -function get_fh_basename(c:connection, fh: string): string - { - return get_fh_info(c, fh)$basename; - } - -# Get the fullname for the FH -function get_fh_fullname(c:connection, fh: string): string - { - local info = get_fh_info(c, fh); - return cat(info$pathname, "/", info$basename); - } - -function print_attr(attr: fattr_t): string - { - return fmt("%s", attr); - } - -function map_conn(cid: conn_id): count - { - if (cid !in nfs_conns) - nfs_conns[cid] = ++num_nfs_conns; - return nfs_conns[cid]; - } - - -function is_success(info: info_t): bool - { - return (info$rpc_stat == RPC_SUCCESS && info$nfs_stat == NFS3ERR_OK); - } - -function is_rpc_success(info: info_t): bool - { - return (info$rpc_stat == RPC_SUCCESS); - } - -function nfs_get_log_prefix(c: connection, info: info_t, proc: string): string - { - local nfs_stat_str = (info$rpc_stat == RPC_SUCCESS) ? fmt("%s", info$nfs_stat) : "X"; - return fmt("%.06f %.06f %d %.06f %.06f %d %s %s %d %s %s %s", - info$req_start, info$req_dur, info$req_len, - info$rep_start, info$rep_dur, info$rep_len, - id_string(c$id), get_port_transport_proto(c$id$orig_p), - map_conn(c$id), - proc, info$rpc_stat, nfs_stat_str); - } - - -event nfs_proc_not_implemented(c: connection, info: info_t, proc: proc_t) - { - local prefix = nfs_get_log_prefix(c, info, fmt("%s", proc)); - - print log_file, fmt("%s Not_implemented", prefix); - } - -event nfs_proc_null(c: connection, info: info_t) - { - local prefix = nfs_get_log_prefix(c, info, "null"); - - print log_file, prefix; - } - -event nfs_proc_getattr (c: connection, info: info_t, fh: string, attrs: fattr_t) - { - local prefix = nfs_get_log_prefix(c, info, "getattr"); - - if (is_success(info)) - log_attributes(c, "getattr", fh, attrs); - - print log_file, fmt("%s %s", prefix, get_fh_id(c,fh)); - } - -event nfs_proc_lookup(c: connection, info: info_t, req: diropargs_t, rep: lookup_reply_t) - { - local prefix = nfs_get_log_prefix(c, info, "lookup"); - - if (! is_success(info) ) - { - print log_file, fmt("%s %s + %s", prefix, get_fh_id(c, req$dirfh), req$fname); - # could print dir_attr, if they are set .... - return; - } - if (rep?$dir_attr) - log_attributes(c, "lookup", req$dirfh, rep$dir_attr); - if (is_rpc_success(info) && rep?$obj_attr) - log_attributes(c, "lookup", rep$fh, rep$obj_attr); - add_update_fh(c, "lookup", req$dirfh, req$fname, rep$fh); - print log_file, fmt("%s %s + %s => %s", prefix, get_fh_id(c, req$dirfh), req$fname, get_fh_id(c, rep$fh)); - - } - -event nfs_proc_read(c: connection, info: info_t, req: readargs_t, rep: read_reply_t) - { - local msg = nfs_get_log_prefix(c, info, "read"); - - msg = fmt("%s %s @%d: %d", msg, get_fh_id(c, req$fh), req$offset, req$size); - if (is_success(info)) - { - msg = fmt("%s got %d bytes %s %s", msg, rep$size, (rep$eof) ? "" : "x", - get_fh_chaintime_str(c, req$fh)); - if (rep?$data && req$offset==0 && rep$size>0) - set_fh_mimetype(c, req$fh, "read", rep$data); - if (is_rpc_success(info) && rep?$attr) - log_attributes(c, "read", req$fh, rep$attr); - } - - print log_file, msg; - } - -event nfs_proc_readlink(c: connection, info: info_t, fh: string, rep: readlink_reply_t) - { - local msg = nfs_get_log_prefix(c, info, "readlink"); - - msg = fmt("%s %s", msg, get_fh_id(c, fh)); - if (is_success(info)) - { - msg = fmt("%s : %s", msg, rep$nfspath); - if (rep?$attr) - log_attributes(c, "readlink", fh, rep$attr); - } - - print log_file, msg; - } - -event nfs_proc_write(c: connection, info: info_t, req: writeargs_t, rep: write_reply_t) - { - local msg = nfs_get_log_prefix(c, info, "write"); - - msg = fmt("%s %s @%d: %d %s", msg, get_fh_id(c, req$fh), req$offset, req$size, req$stable); - if (is_success(info)) - { - msg = fmt("%s wrote %d bytes %s %s", msg, rep$size, rep$commited, - get_fh_chaintime_str(c, req$fh)); - if (req?$data && req$offset==0 && rep$size>0) - set_fh_mimetype(c, req$fh, "write", req$data); - if (rep?$postattr) - log_attributes(c, "write", req$fh, rep$postattr); - } - - print log_file, msg; - } - -function nfs_newobj(c: connection, info: info_t, proc: string, req: diropargs_t, rep: newobj_reply_t) - { - local prefix = nfs_get_log_prefix(c, info, proc); - local newfh_str: string; - if (! is_success(info) ) - { - print log_file, fmt("%s %s + %s", prefix, get_fh_id(c, req$dirfh), req$fname); - # could print dir_attr, if they are set .... - return; - } - if (is_rpc_success(info) && rep?$dir_post_attr) - log_attributes(c, proc, req$dirfh, rep$dir_post_attr); - # TODO: could print dir_pre_attr - if (is_rpc_success(info) && rep?$obj_attr) - log_attributes(c, proc, rep$fh, rep$obj_attr); - add_update_fh(c, proc, req$dirfh, req$fname, rep$fh); - - newfh_str = (rep?$fh) ? get_fh_id(c, rep$fh) : "FH??"; - print log_file, fmt("%s %s + %s => %s", prefix, get_fh_id(c, req$dirfh), req$fname, get_fh_id(c, rep$fh)); - } - -event nfs_proc_create(c: connection, info: info_t, req: diropargs_t, rep: newobj_reply_t) - { - # TODO: create request attributes not implemented in core - nfs_newobj(c, info, "create", req, rep); - } - -event nfs_proc_mkdir(c: connection, info: info_t, req: diropargs_t, rep: newobj_reply_t) - { - # TODO: mkidir request attributes not implemented in core - nfs_newobj(c, info, "mkdir", req, rep); - } - -function nfs_delobj(c: connection, info: info_t, proc: string, req: diropargs_t, rep: delobj_reply_t) - { - local prefix = nfs_get_log_prefix(c, info, proc); - print log_file, fmt("%s %s - %s", prefix, get_fh_id(c, req$dirfh), req$fname); - if (is_rpc_success(info) && rep?$dir_post_attr) - log_attributes(c, proc, req$dirfh, rep$dir_post_attr); - # TODO: could print dir_pre_attr - } - -event nfs_proc_remove(c: connection, info: info_t, req: diropargs_t, rep: delobj_reply_t) - { - nfs_delobj(c, info, "remove", req, rep); - } - -event nfs_proc_rmdir(c: connection, info: info_t, req: diropargs_t, rep: delobj_reply_t) - { - nfs_delobj(c, info, "rmdir", req, rep); - } - -function fmt_direntry(c: connection, e: direntry_t): string - { - local rv = ""; - rv = fmt("%d %s %d", e$fileid, e$fname, e$cookie); - if (e?$fh) - rv = fmt("%s %s", rv, get_fh_id(c, e$fh)); - return rv; - - } - -event nfs_proc_readdir(c: connection, info: info_t, req: readdirargs_t, rep: readdir_reply_t) - { - local isplus = req$isplus; - local proc = (isplus) ? "readdirplus" : "readdir"; - local msg = nfs_get_log_prefix(c, info, proc); - msg = fmt("%s %s @%d (%x)", msg, get_fh_id(c, req$dirfh), req$cookie, req$cookieverf); - if (is_success(info)) - { - msg = fmt("%s %d entries %d", msg, |rep$entries|, rep$eof); - print readdir_log, msg; - for (i in rep$entries) - { - local curentry = rep$entries[i]; - if (curentry?$attr && curentry?$fh) - log_attributes(c, proc, curentry$fh, curentry$attr); - if (curentry?$fh) - add_update_fh(c, proc, req$dirfh, curentry$fname, curentry$fh); - print readdir_log,fmt(" %s", fmt_direntry(c, curentry)); - } - if (rep?$dir_attr) - log_attributes(c, proc, req$dirfh, rep$dir_attr); - } - else if (is_rpc_success(info) && rep?$dir_attr) - { - log_attributes(c, proc, req$dirfh, rep$dir_attr); - } - print log_file, msg; - } - -event connection_state_remove(c: connection) - { - if ( c$id !in nfs_conns ) - return; - delete nfs_conns[c$id]; - } diff --git a/policy.old/notice-policy.bro b/policy.old/notice-policy.bro deleted file mode 100644 index 78d26c26ed..0000000000 --- a/policy.old/notice-policy.bro +++ /dev/null @@ -1,72 +0,0 @@ -# $Id: notice-policy.bro 4758 2007-08-10 06:49:23Z vern $ - -# Examples of using notice_policy and other mechanisms to filter out -# alarms that are not interesting. - -# Note: this file is not self-contained, in that it refers to Notice -# names that will only be defined if you've loaded other files (e.g., -# print-resources for the ResourceSummary notice). The full list of -# policy files it needs is: -# -# blaster.bro -# conn.bro -# http-request.bro -# netstats.bro -# print-resources.bro -# trw.bro -# weird.bro - - -# Remove these notices from logging since they can be too noisy. -redef notice_action_filters += { - [[Weird::ContentGap, Weird::AckAboveHole]] = ignore_notice, -}; - -# Send these only to the notice log, not the alarm log. -redef notice_action_filters += { - [[Drop::AddressDropIgnored, DroppedPackets, - ResourceSummary, W32B_SourceRemote, - TRW::TRWScanSummary, Scan::BackscatterSeen, - Weird::WeirdActivity, - Weird::RetransmissionInconsistency]] = file_notice, -}; - -# Other example use of notice_action_filters: -# -# To just get a summary Notice when Bro is shutdown/checkpointed, use -# tally_notice_type, such as: -#redef notice_action_filters += { -# [[RetransmissionInconsistency, ContentGap, AckAboveHole]] = -# tally_notice_type, -#}; - -# To get a summary once every hour per originator, use notice_alarm_per_orig, -# such as: -#redef notice_action_filters += { -# [[ BackscatterSeen, RetransmissionInconsistency]] = -# notice_alarm_per_orig, -#}; - - -# Fine-grained filtering of specific alarms. -redef notice_policy += { - - # Connections to 2766/tcp ("Solaris listen service") appear - # nearly always actually due to P2P apps. - [$pred(n: notice_info) = - { - return n$note == SensitiveConnection && - /Solaris listen service/ in n$msg; - }, - $result = NOTICE_FILE, - $priority = 1], - - # Ignore sensitive URLs that end in .gif, .jpg, .png - [$pred(n: notice_info) = - { - return n$note == HTTP::HTTP_SensitiveURI && - n$URL == /.*\.(gif|GIF|png|PNG|jpg|JPG)/; - }, - $result = NOTICE_FILE, - $priority = 1], -}; diff --git a/policy.old/ntp.bro b/policy.old/ntp.bro deleted file mode 100644 index eb746bc830..0000000000 --- a/policy.old/ntp.bro +++ /dev/null @@ -1,53 +0,0 @@ -# $Id: ntp.bro 4758 2007-08-10 06:49:23Z vern $ - -@load udp-common - -redef capture_filters += { ["ntp"] = "udp port 123" }; - -module NTP; - -export { - const excessive_ntp_request = 48 &redef; - const allow_excessive_ntp_requests: set[addr] &redef; -} - -# DPM configuration. -global ntp_ports = { 123/udp } &redef; -redef dpd_config += { [ANALYZER_NTP] = [$ports = ntp_ports] }; - -const ntp_code: table[count] of string = { - [0] = "unspec", - [1] = "sym_act", - [2] = "sym_psv", - [3] = "client", - [4] = "server", - [5] = "bcast", - [6] = "rsv1", - [7] = "rsv2", -}; - -event ntp_message(u: connection, msg: ntp_msg, excess: string) - { - local id = u$id; - - if ( id !in udp_rep_count && id !in udp_req_count ) - { - Hot::check_hot(u, Hot::CONN_ATTEMPTED); - Scan::check_scan(u, F, F); - } - - if ( msg$code == 4 ) - # "server" - ++udp_rep_count[id]; - else - # anything else - ++udp_req_count[id]; - - local n_excess = byte_len(excess); - if ( n_excess > excessive_ntp_request && - id$orig_h !in allow_excessive_ntp_requests ) - { - append_addl_marker(u, fmt("%s", n_excess), ","); - ++u$hot; - } - } diff --git a/policy.old/passwords.bro b/policy.old/passwords.bro deleted file mode 100644 index 84e98ec3ff..0000000000 --- a/policy.old/passwords.bro +++ /dev/null @@ -1,29 +0,0 @@ -# $Id: passwords.bro 688 2004-11-02 23:59:55Z vern $ - -# Generates notices of exposed passwords. Currently just works -# on telnet/rlogin access. Should be extended to do FTP, HTTP, etc. - -@load login - -redef enum Notice += { - PasswordExposed, -}; - -# Usernames which we ignore. -global okay_usernames: set[string] &redef; - -# Passwords which we ignore. -global okay_passwords = { "", "" } &redef; - -event login_success(c:connection, user: string, client_user: string, - password: string, line: string) - { - if ( user in okay_usernames || password in okay_passwords ) - return; - - NOTICE([$note=PasswordExposed, - $conn=c, - $user=user, - $sub=password, - $msg="login exposed user's password"]); - } diff --git a/policy.old/peer-status.bro b/policy.old/peer-status.bro deleted file mode 100644 index 95189873fd..0000000000 --- a/policy.old/peer-status.bro +++ /dev/null @@ -1,84 +0,0 @@ -# $Id: peer-status.bro 5954 2008-07-15 00:07:50Z vern $ -# -# Emits process status "update" event periodically. - -module PeerStatus; - -export { - type peer_status: record { - res: bro_resources; - stats: net_stats; - current_time: time; - cpu: double; # average CPU load since last update - default_filter: string; # default capture filter - }; - - # Event sent periodically. - global update: event(status: peer_status); - - # Update interval. - const update_interval = 1 min; - - # This keeps track of all (local and remote) updates - # (indexed by peer ID). - global peers: table[peer_id] of peer_status; -} - -global start_time = 0; -global cpu_last_proc_time = 0 secs; -global cpu_last_wall_time: time = 0; -global stats: net_stats; -global default_filter : string; - -event net_stats_update(t: time, ns: net_stats) - { - stats = ns; - } - -event emit_update() - { - # Get CPU load. - local res = resource_usage(); - local proc_time = res$user_time + res$system_time; - local wall_time = current_time(); - local dproc = proc_time - cpu_last_proc_time; - local dwall = wall_time - cpu_last_wall_time; - local load = dproc / dwall * 100.0; - cpu_last_proc_time = proc_time; - cpu_last_wall_time = wall_time; - - local status: peer_status; - status$res = res; - status$stats = stats; - status$current_time = current_time(); - status$cpu = load; - status$default_filter = default_filter; - - event PeerStatus::update(status); - - schedule update_interval { emit_update() }; - } - -event bro_init() - { - default_filter = build_default_pcap_filter(); - - local res = resource_usage(); - cpu_last_proc_time = res$user_time + res$system_time; - cpu_last_wall_time = current_time(); - stats = [$pkts_recvd=0, $pkts_dropped=0, $pkts_link=0]; - - schedule update_interval { emit_update() }; - } - -event update(status: peer_status) - { - local peer = get_event_peer(); - peers[peer$id] = status; - } - -event remote_connection_closed(p: event_peer) - { - if ( p$id in peers ) - delete peers[p$id]; - } diff --git a/policy.old/pkt-profile.bro b/policy.old/pkt-profile.bro deleted file mode 100644 index a499ec2c6e..0000000000 --- a/policy.old/pkt-profile.bro +++ /dev/null @@ -1,5 +0,0 @@ -# $Id: pkt-profile.bro 325 2004-09-03 01:33:15Z vern $ - -redef pkt_profile_file = open_log_file("pkt-prof"); -redef pkt_profile_mode = PKT_PROFILE_MODE_SECS; -redef pkt_profile_freq = 1.0; diff --git a/policy.old/pop3.bro b/policy.old/pop3.bro deleted file mode 100644 index 40ae3920a9..0000000000 --- a/policy.old/pop3.bro +++ /dev/null @@ -1,155 +0,0 @@ -# $Id: pop3.bro 4758 2007-08-10 06:49:23Z vern $ -# -# Analyzer for Post Office Protocol, version 3. -# -# If you want to decode the mail itself, also load mime-pop.bro. - -@load login - -module POP3; - -export { - # Report if source triggers more ERR messages. - const error_threshold: count = 3 &redef; - # Don't log these commands. - const ignore_commands: set[string] = { "STAT" } &redef; -} - -redef capture_filters += { ["pop3"] = "port 110" }; - -global pop3_ports = { 110/tcp } &redef; -redef dpd_config += { [ANALYZER_POP3] = [$ports = pop3_ports] }; - -const log_file = open_log_file("pop3") &redef; - -type pop3_session_info: record { - id: count; # Unique session ID. - quit_sent: bool; # Client issued a QUIT. - last_command: string; # Last command of client. -}; - - -global pop_log: function(conn: pop3_session_info, - command: string, message: string); -global get_connection: function(id: conn_id): pop3_session_info; - - -global pop_connections: - table[conn_id] of pop3_session_info &read_expire = 60 mins; -global pop_connection_weirds: - table[addr] of count &default=0 &read_expire = 60 mins; -global pop_session_id = 0; - - -event pop3_request(c: connection, is_orig: bool, command: string, arg: string) - { - local conn = get_connection(c$id); - - pop_log(conn, command, fmt("%.6f #%s > %s %s", - network_time(), prefixed_id(conn$id), command, arg)); - - conn$last_command = command; - - if ( command == "QUIT" ) - conn$quit_sent = T; - } - -event pop3_reply(c: connection, is_orig: bool, cmd: string, msg: string) - { - local conn = get_connection(c$id); - - pop_log(conn, cmd, - fmt("%.6f #%s < %s %s", network_time(), prefixed_id(conn$id), cmd, msg)); - - if ( cmd == "OK" ) - { - if ( conn$quit_sent ) - delete pop_connections[c$id]; - } - - else if ( cmd == "ERR" ) - { - ++pop_connection_weirds[c$id$orig_h]; - if ( pop_connection_weirds[c$id$orig_h] > error_threshold ) - print log_file, fmt("%.6f #%s %s/%d > %s/%d WARNING: error count exceeds threshold", - network_time(), prefixed_id(conn$id), - c$id$orig_h, c$id$orig_p, - c$id$resp_h, c$id$resp_p); - } - } - -event pop3_login_success(c: connection, is_orig: bool, - user: string, password: string) - { - local conn = get_connection(c$id); - - local pw = byte_len(password) != 0 ? password : ""; - - print log_file, fmt("%.6f #%s > login successful: user %s password: %s", - network_time(), prefixed_id(conn$id), user, pw); - - event login_success(c, user, "", password, ""); - } - -event pop3_login_failure(c: connection, is_orig: bool, - user: string, password: string) - { - local conn = get_connection(c$id); - - print log_file, fmt("%.6f #%s > login failed: user %s password: %s", - network_time(), prefixed_id(conn$id), user, password); - - event login_failure(c, user, "", password, ""); - } - -# event pop3_data(c: connection, is_orig: bool, data: string) -# { -# # We could instantiate partial connections here if we wished, -# # but at considerable cost in terms of event counts. -# local conn = get_connection(c$id); -# } - -event pop3_unexpected(c: connection, is_orig: bool, msg: string, detail: string) - { - local conn = get_connection(c$id); - print log_file, fmt("%.6f #%s unexpected cmd: %s detail: %s", - network_time(), prefixed_id(conn$id), - msg, detail); - } - -event pop3_terminate(c: connection, is_orig: bool, msg: string) - { - delete pop_connections[c$id]; - } - - -function pop_log(conn: pop3_session_info, command: string, message: string) - { - if ( command !in ignore_commands ) - { - if ( (command == "OK" || command == "ERR") && - conn$last_command in ignore_commands ) - ; - else - print log_file, message; - } - } - -function get_connection(id: conn_id): pop3_session_info - { - if ( id in pop_connections ) - return pop_connections[id]; - - local conn: pop3_session_info; - - conn$id = ++pop_session_id; - conn$quit_sent = F; - conn$last_command = "INIT"; - pop_connections[id] = conn; - - print log_file, fmt("%.6f #%s %s/%d > %s/%d: new connection", - network_time(), prefixed_id(conn$id), - id$orig_h, id$orig_p, id$resp_h, id$resp_p); - - return conn; - } diff --git a/policy.old/port-name.bro b/policy.old/port-name.bro deleted file mode 100644 index c5b0f8c11f..0000000000 --- a/policy.old/port-name.bro +++ /dev/null @@ -1,63 +0,0 @@ -const port_names: table[port] of string = { - [0/icmp] = "icmp-echo", - [3/icmp] = "icmp-unreach", - [8/icmp] = "icmp-echo", - - [7/tcp] = "echo", - [9/tcp] = "discard", - [20/tcp] = "ftp-data", - [21/tcp] = "ftp", - [22/tcp] = "ssh", - [23/tcp] = "telnet", - [25/tcp] = "smtp", - [37/tcp] = "time", - [43/tcp] = "whois", - [53/tcp] = "dns", - [79/tcp] = "finger", - [80/tcp] = "http", - [109/tcp] = "pop-2", - [110/tcp] = "pop-3", - [111/tcp] = "portmap", - [113/tcp] = "ident", - [119/tcp] = "nntp", - [135/tcp] = "epmapper", - [139/tcp] = "netbios-ssn", - [143/tcp] = "imap4", - [179/tcp] = "bgp", - [389/tcp] = "ldap", - [443/tcp] = "https", - [445/tcp] = "smb", - [512/tcp] = "exec", - [513/tcp] = "rlogin", - [514/tcp] = "shell", - [515/tcp] = "printer", - [524/tcp] = "ncp", - [543/tcp] = "klogin", - [544/tcp] = "kshell", - [631/tcp] = "ipp", - [993/tcp] = "simap", - [995/tcp] = "spop", - [1521/tcp] = "oracle-sql", - [2049/tcp] = "nfs", - [6000/tcp] = "X11", - [6001/tcp] = "X11", - [6667/tcp] = "IRC", - - [53/udp] = "dns", - [69/udp] = "tftp", - [111/udp] = "portmap", - [123/udp] = "ntp", - [137/udp] = "netbios-ns", - [138/udp] = "netbios-dgm", - [161/udp] = "snmp", - [2049/udp] = "nfs", - -} &redef; - -function endpoint_id(h: addr, p: port): string - { - if ( p in port_names ) - return fmt("%s/%s", h, port_names[p]); - else - return fmt("%s/%d", h, p); - } diff --git a/policy.old/portmapper.bro b/policy.old/portmapper.bro deleted file mode 100644 index 4829812154..0000000000 --- a/policy.old/portmapper.bro +++ /dev/null @@ -1,468 +0,0 @@ -# $Id: portmapper.bro 4758 2007-08-10 06:49:23Z vern $ - -@load notice -@load hot -@load conn -@load weird -@load scan - -module Portmapper; - -export { - redef enum Notice += { - # Some combination of the service looked up, the host doing the - # request, and the server contacted is considered sensitive. - SensitivePortmapperAccess, - }; - - # Kudos to Job de Haas for a lot of these entries. - - const rpc_programs = { - [200] = "aarp", - - [100000] = "portmapper", [100001] = "rstatd", - [100002] = "rusersd", [100003] = "nfs", [100004] = "ypserv", - [100005] = "mountd", [100007] = "ypbind", [100008] = "walld", - [100009] = "yppasswdd", [100010] = "etherstatd", - [100011] = "rquotad", [100012] = "sprayd", - [100013] = "3270_mapper", [100014] = "rje_mapper", - [100015] = "selection_svc", [100016] = "database_svc", - [100017] = "rexd", [100018] = "alis", [100019] = "sched", - [100020] = "llockmgr", [100021] = "nlockmgr", - [100022] = "x25.inr", [100023] = "statmon", - [100024] = "status", [100026] = "bootparam", - [100028] = "ypupdate", [100029] = "keyserv", - [100033] = "sunlink_mapper", [100036] = "pwdauth", - [100037] = "tfsd", [100038] = "nsed", - [100039] = "nsemntd", [100041] = "pnpd", - [100042] = "ipalloc", [100043] = "filehandle", - [100055] = "ioadmd", [100062] = "NETlicense", - [100065] = "sunisamd", [100066] = "debug_svc", - [100068] = "cms", [100069] = "ypxfrd", - [100071] = "bugtraqd", [100078] = "kerbd", - [100083] = "tooltalkdb", [100087] = "admind", - [100099] = "autofsd", - - [100101] = "event", [100102] = "logger", [100104] = "sync", - [100105] = "diskinfo", [100106] = "iostat", - [100107] = "hostperf", [100109] = "activity", - [100111] = "lpstat", [100112] = "hostmem", - [100113] = "sample", [100114] = "x25", [100115] = "ping", - [100116] = "rpcnfs", [100117] = "hostif", [100118] = "etherif", - [100119] = "ippath", [100120] = "iproutes", - [100121] = "layers", [100122] = "snmp", [100123] = "traffic", - [100131] = "layers2", [100135] = "etherif2", - [100136] = "hostmem2", [100137] = "iostat2", - [100138] = "snmpv2", [100139] = "sender", - - [100221] = "kcms", [100227] = "nfs_acl", [100229] = "metad", - [100230] = "metamhd", [100232] = "sadmind", [100233] = "ufsd", - [100235] = "cachefsd", [100249] = "snmpXdmid", - - [100300] = "nisd", [100301] = "nis_cache", - [100302] = "nis_callback", [100303] = "nispasswd", - - [120126] = "nf_snmd", [120127] = "nf_snmd", - - [150001] = "pcnfsd", - - [300004] = "frameuser", [300009] = "stdfm", [300019] = "amd", - - [300433] = "bssd", [300434] = "drdd", - - [300598] = "dmispd", - - [390100] = "prestoctl_svc", - - [390600] = "arserverd", [390601] = "ntserverd", - [390604] = "arservtcd", - - [391000] = "SGI_snoopd", [391001] = "SGI_toolkitbus", - [391002] = "SGI_fam", [391003] = "SGI_notepad", - [391004] = "SGI_mountd", [391005] = "SGI_smtd", - [391006] = "SGI_pcsd", [391007] = "SGI_nfs", - [391008] = "SGI_rfind", [391009] = "SGI_pod", - [391010] = "SGI_iphone", [391011] = "SGI_videod", - [391012] = "SGI_testcd", [391013] = "SGI_ha_hb", - [391014] = "SGI_ha_nc", [391015] = "SGI_ha_appmon", - [391016] = "SGI_xfsmd", [391017] = "SGI_mediad", - - # 391018 - 391063 = "SGI_reserved" - - [545580417] = "bwnfsd", - - [555555554] = "inetray.start", [555555555] = "inetray", - [555555556] = "inetray", [555555557] = "inetray", - [555555558] = "inetray", [555555559] = "inetray", - [555555560] = "inetray", - - [600100069] = "fypxfrd", - - [1342177279] = "Solaris/CDE", # = 0x4fffffff - - # Some services that choose numbers but start often at these values. - [805306368] = "dmispd", - [824395111] = "cfsd", [1092830567] = "cfsd", - } &redef; - - const NFS_services = { - "mountd", "nfs", "pcnfsd", "nlockmgr", "rquotad", "status" - } &redef; - - # Indexed by the host providing the service, the host requesting it, - # and the service. - const RPC_okay: set[addr, addr, string] &redef; - const RPC_okay_nets: set[subnet] &redef; - const RPC_okay_services: set[string] &redef; - const NFS_world_servers: set[addr] &redef; - - # Indexed by the portmapper request and a boolean that's T if - # the request was answered, F it was attempted but not answered. - # If there's an entry in the set, then the access won't lead to a - # NOTICE (unless the connection is hot for some other reason). - const RPC_do_not_complain: set[string, bool] = { - ["pm_null", [T, F]], - } &redef; - - # Indexed by the host requesting the dump and the host from which it's - # requesting it. - const RPC_dump_okay: set[addr, addr] &redef; - - # Indexed by the host providing the service - any host can request it. - const any_RPC_okay = { - [NFS_world_servers, NFS_services], - [sun-rpc.mcast.net, "ypserv"], # sigh - } &redef; - - # Logs all portmapper activity as readable "messages" - # Format: timestamp orig_p resp_h resp_p proto localInit PortmapProcedure success details - const log_file = open_log_file("portmapper") &redef; - # Logs all portmapper mappings that we observe (i.e., getport and - # dump replies. Format: - # timestamp orig_h orig_p resp_h resp_p proto localInit PortmapProcedure RPCprogram version port proto - # the mapping is then: accepts with - # calls on . We learned this mapping via - const mapping_log_file = open_log_file("portmapper-maps") &redef; -} - -redef capture_filters += { ["portmapper"] = "port 111" }; - -const portmapper_ports = { 111/tcp, 111/udp } &redef; -redef dpd_config += { [ANALYZER_PORTMAPPER] = [$ports = portmapper_ports] }; - -# Indexed by source and destination addresses, plus the portmapper service. -# If the tuple is in the set, then we already created a NOTICE for it and -# shouldn't do so again. -global did_pm_notice: set[addr, addr, string]; - -# Indexed by source and portmapper service. If set, we already created -# a notice and shouldn't do so again. -global suppress_pm_notice: set[addr, string]; - - -function RPC_weird_action_filter(c: connection): Weird::WeirdAction - { - if ( c$id$orig_h in RPC_okay_nets ) - return Weird::WEIRD_FILE; - else - return Weird::WEIRD_UNSPECIFIED; - } - -redef Weird::weird_action_filters += { - [["bad_RPC", "excess_RPC", "multiple_RPCs", "partial_RPC"]] = - RPC_weird_action_filter, -}; - - -function rpc_prog(p: count): string - { - if ( p in rpc_programs ) - return rpc_programs[p]; - else - return fmt("unknown-%d", p); - } - - -function pm_get_conn_string(cid: conn_id) : string - { - return fmt("%s %d %s %d %s %s", - cid$orig_h, cid$orig_p, - cid$resp_h, cid$resp_p, - get_port_transport_proto(cid$resp_p), - is_local_addr(cid$orig_h) ? "L" : "X" - ); - } - -# Log a pm_request or pm_attempt to the log file -function pm_log(r: connection, proc: string, msg: string, success: bool) - { - print log_file, fmt("%f %s %s %s %s", network_time(), - pm_get_conn_string(r$id), - proc, success, msg); - } - -# Log portmapper mappings received from a dump procedure -function pm_log_mapping_dump(r: connection, m: pm_mappings) - { - # TODO: sort by program and version - for ( mp in m ) - { - local prog = rpc_prog(m[mp]$program); - local ver = m[mp]$version; - local p = m[mp]$p; - - print mapping_log_file, fmt("%f %s pm_dump %s %d %d %s", network_time(), - pm_get_conn_string(r$id), - prog, ver, p, get_port_transport_proto(p)); - } - } - -# Log portmapper mappings received from a getport procedure -# Unfortunately, pm_request_getport doesn't return pm_mapping, -# but returns the parameters separately .... -function pm_log_mapping_getport(r: connection, pr: pm_port_request, p: port) - { - local prog = rpc_prog(pr$program); - local ver = pr$version; - - print mapping_log_file, fmt("%f %s pm_getport %s %d %d %s", network_time(), - pm_get_conn_string(r$id), - prog, ver, p, get_port_transport_proto(p)); - } - - - -function pm_check_getport(r: connection, prog: string): bool - { - if ( prog in RPC_okay_services || - [r$id$resp_h, prog] in any_RPC_okay || - [r$id$resp_h, r$id$orig_h, prog] in RPC_okay ) - return F; - - if ( r$id$orig_h in RPC_okay_nets ) - return F; - - return T; - } - -function pm_activity(r: connection, do_notice: bool, proc: string) - { - local id = r$id; - - if ( do_notice && - [id$orig_h, id$resp_h, proc] !in did_pm_notice && - [id$orig_h, proc] !in suppress_pm_notice ) - { - NOTICE([$note=SensitivePortmapperAccess, $conn=r, - $msg=fmt("rpc: %s %s: %s", - id_string(r$id), proc, r$addl)]); - add did_pm_notice[id$orig_h, id$resp_h, proc]; - } - } - -function pm_request(r: connection, proc: string, addl: string, do_notice: bool) - { - if ( [proc, T] in RPC_do_not_complain ) - do_notice = F; - - if ( ! is_tcp_port(r$id$orig_p) ) - { - # It's UDP, so no connection_established event - check for - # scanning, hot access, here, instead. - Scan::check_scan(r, T, F); - Hot::check_hot(r, Hot::CONN_ESTABLISHED); - } - - if ( r$addl == "" ) - r$addl = addl; - - else - { - if ( byte_len(r$addl) > 80 ) - { - # r already has a lot of annotation. We can sometimes - # get *zillions* of successive pm_request's with the - # same connection ID, depending on how the RPC client - # behaves. For those, don't add any further, except - # add an ellipses if we don't already have one. - append_addl(r, "..."); - } - else - append_addl_marker(r, addl, ", "); - } - - add r$service[proc]; - Hot::check_hot(r, Hot::CONN_FINISHED); - pm_activity(r, do_notice || r$hot > 0, proc); - pm_log(r, proc, addl, T); - } - - -event pm_request_null(r: connection) - { - pm_request(r, "pm_null", "", F); - } - -event pm_request_set(r: connection, m: pm_mapping, success: bool) - { - pm_request(r, "pm_set", fmt("%s %d (%s)", - rpc_prog(m$program), m$p, success ? "ok" : "failed"), T); - } - -event pm_request_unset(r: connection, m: pm_mapping, success: bool) - { - pm_request(r, "pm_unset", fmt("%s %d (%s)", - rpc_prog(m$program), m$p, success ? "ok" : "failed"), T); - } - -function update_RPC_server_map(server: addr, p: port, prog: string) - { - if ( [server, p] in RPC_server_map ) - { - if ( prog !in RPC_server_map[server, p] ) - { - RPC_server_map[server, p] = - fmt("%s/%s", RPC_server_map[server, p], prog); - } - } - else - RPC_server_map[server, p] = prog; - } - -event pm_request_getport(r: connection, pr: pm_port_request, p: port) - { - local prog = rpc_prog(pr$program); - local do_notice = pm_check_getport(r, prog); - - update_RPC_server_map(r$id$resp_h, p, prog); - - pm_request(r, "pm_getport", fmt("%s -> %s", prog, p), do_notice); - pm_log_mapping_getport(r, pr, p); - } - -# Note, this function has the side effect of updating the -# RPC_server_map -function pm_mapping_to_text(server: addr, m: pm_mappings): string - { - # Used to suppress multiple entries for multiple versions. - local mapping_seen: set[count, port]; - local addls: vector of string; - local num_addls = 0; - - for ( mp in m ) - { - local prog = m[mp]$program; - local p = m[mp]$p; - - if ( [prog, p] !in mapping_seen ) - { - add mapping_seen[prog, p]; - addls[num_addls] = fmt("%s -> %s", rpc_prog(prog), p); - ++num_addls; - update_RPC_server_map(server, p, rpc_prog(prog)); - } - } - - local addl_str = fmt("%s", sort(addls, strcmp)); - - # Lop off surrounding []'s for compatibility with previous - # format. - addl_str = sub(addl_str, /^\[/, ""); - addl_str = sub(addl_str, /\]$/, ""); - - return addl_str; - } - -event pm_request_dump(r: connection, m: pm_mappings) - { - local do_notice = [r$id$orig_h, r$id$resp_h] !in RPC_dump_okay; - # pm_mapping_to_text has the side-effect of updating RPC_server_map - pm_request(r, "pm_dump", - length(m) == 0 ? "(nil)" : pm_mapping_to_text(r$id$resp_h, m), - do_notice); - pm_log_mapping_dump(r, m); - } - -event pm_request_callit(r: connection, call: pm_callit_request, p: port) - { - local orig_h = r$id$orig_h; - local prog = rpc_prog(call$program); - local do_notice = [orig_h, prog] !in suppress_pm_notice; - - pm_request(r, "pm_callit", fmt("%s/%d (%d bytes) -> %s", - prog, call$proc, call$arg_size, p), do_notice); - - if ( prog == "walld" ) - add suppress_pm_notice[orig_h, prog]; - } - - -function pm_attempt(r: connection, proc: string, status: rpc_status, - addl: string, do_notice: bool) - { - if ( [proc, F] in RPC_do_not_complain ) - do_notice = F; - - if ( ! is_tcp_port(r$id$orig_p) ) - { - # It's UDP, so no connection_attempt event - check for - # scanning here, instead. - Scan::check_scan(r, F, F); - Hot::check_hot(r, Hot::CONN_ATTEMPTED); - } - - add r$service[proc]; - append_addl(r, fmt("(%s)", RPC_status[status])); - - # Current policy is ignore any failed attempts. - pm_activity(r, F, proc); - pm_log(r, proc, addl, F); - } - -event pm_attempt_null(r: connection, status: rpc_status) - { - pm_attempt(r, "pm_null", status, "", T); - } - -event pm_attempt_set(r: connection, status: rpc_status, m: pm_mapping) - { - pm_attempt(r, "pm_set", status, fmt("%s %d", rpc_prog(m$program), m$p), T); - } - -event pm_attempt_unset(r: connection, status: rpc_status, m: pm_mapping) - { - pm_attempt(r, "pm_unset", status, fmt("%s %d", rpc_prog(m$program), m$p), T); - } - -event pm_attempt_getport(r: connection, status: rpc_status, pr: pm_port_request) - { - local prog = rpc_prog(pr$program); - local do_notice = pm_check_getport(r, prog); - pm_attempt(r, "pm_getport", status, prog, do_notice); - } - -event pm_attempt_dump(r: connection, status: rpc_status) - { - local do_notice = [r$id$orig_h, r$id$resp_h] !in RPC_dump_okay; - pm_attempt(r, "pm_dump", status, "", do_notice); - } - -event pm_attempt_callit(r: connection, status: rpc_status, - call: pm_callit_request) - { - local orig_h = r$id$orig_h; - local prog = rpc_prog(call$program); - local do_notice = [orig_h, prog] !in suppress_pm_notice; - - pm_attempt(r, "pm_callit", status, - fmt("%s/%d (%d bytes)", prog, call$proc, call$arg_size), - do_notice); - - if ( prog == "walld" ) - add suppress_pm_notice[orig_h, prog]; - } - -event pm_bad_port(r: connection, bad_p: count) - { - event conn_weird_addl("bad_pm_port", r, fmt("port %d", bad_p)); - } diff --git a/policy.old/print-filter.bro b/policy.old/print-filter.bro deleted file mode 100644 index 5d8d03b80a..0000000000 --- a/policy.old/print-filter.bro +++ /dev/null @@ -1,26 +0,0 @@ -# $Id: print-filter.bro 4506 2007-06-27 14:40:34Z vern $ - -module PrintFilter; - -export { - # If true, terminate Bro after printing the filter. - const terminate_bro = T &redef; - - # If true, write to log file instead of stdout. - const to_file = F &redef; - } - -event bro_init() - { - if ( to_file ) - { - local f = open_log_file("pcap_filter"); - print f, build_default_pcap_filter(); - close(f); - } - else - print build_default_pcap_filter(); - - if ( terminate_bro ) - exit(); - } diff --git a/policy.old/print-globals.bro b/policy.old/print-globals.bro deleted file mode 100644 index 994ea17eba..0000000000 --- a/policy.old/print-globals.bro +++ /dev/null @@ -1,4 +0,0 @@ -event bro_done() - { - print global_sizes(); - } diff --git a/policy.old/print-resources.bro b/policy.old/print-resources.bro deleted file mode 100644 index 7b069f9415..0000000000 --- a/policy.old/print-resources.bro +++ /dev/null @@ -1,21 +0,0 @@ -# $Id: print-resources.bro 6703 2009-05-13 22:27:44Z vern $ - -# Logs Bro resource usage information upon termination. - -@load notice - -redef enum Notice += { - ResourceSummary, # Notice type for this event -}; - -event bro_done() - { - local res = resource_usage(); - - NOTICE([$note=ResourceSummary, - $msg=fmt("elapsed time = %s, total CPU = %s, maximum memory = %d KB, peak connections = %d, peak timers = %d, peak fragments = %d", - res$real_time, res$user_time + res$system_time, - res$mem / 1024, - res$max_TCP_conns + res$max_UDP_conns + res$max_ICMP_conns, - res$max_timers, res$max_fragments)]); - } diff --git a/policy.old/print-sig-states.bro b/policy.old/print-sig-states.bro deleted file mode 100644 index c13677f6ca..0000000000 --- a/policy.old/print-sig-states.bro +++ /dev/null @@ -1,18 +0,0 @@ -# $Id: print-sig-states.bro 491 2004-10-05 05:44:59Z vern $ -# -# Simple profiling script for periodicaly dumping out signature-matching -# statistics. - -global sig_state_stats_interval = 5 mins; -global sig_state_file = open_log_file("sig-states"); - -event dump_sig_state_stats() - { - dump_rule_stats(sig_state_file); - schedule sig_state_stats_interval { dump_sig_state_stats() }; - } - -event bro_init() - { - schedule sig_state_stats_interval { dump_sig_state_stats() }; - } diff --git a/policy.old/profiling.bro b/policy.old/profiling.bro deleted file mode 100644 index a8aef46440..0000000000 --- a/policy.old/profiling.bro +++ /dev/null @@ -1,17 +0,0 @@ -# $Id: profiling.bro 1102 2005-03-17 09:17:46Z vern $ -# -# Turns on profiling of Bro resource consumption. - -redef profiling_file = open_log_file("prof"); - -# Cheap profiling every 15 seconds. -redef profiling_interval = 15 secs &redef; - -# Expensive profiling every 5 minutes. -redef expensive_profiling_multiple = 20; - -event bro_init() - { - set_buf(profiling_file, F); - } - diff --git a/policy.old/proxy.bro b/policy.old/proxy.bro deleted file mode 100644 index 1f43308f3a..0000000000 --- a/policy.old/proxy.bro +++ /dev/null @@ -1,99 +0,0 @@ -# $Id: proxy.bro,v 1.1.4.2 2006/05/31 00:16:22 sommer Exp $ -# -# Finds open proxies by matching incoming HTTP requests with outgoing ones. - -@load notice - -module Proxy; - -export { - const KnownProxies: set[addr] = { }; - - redef enum Notice += { - HTTPProxyFound, - }; -} - - -type request: record { - p: port; - paths: set[string]; -}; - -# Maps the address of the potential proxy to the paths that -# have been requested from it. -global requests: table[addr] of request; - -# A parsed URL. -type url: record { - host: string; - path: string; -}; - -global found_proxies: set[addr] &create_expire = 24 hrs; - -function parse_url(u: string) : url - { - # The URL parsing is imperfect, but should work sufficiently well. - local a = split1(u, /:\/\//); - if ( |a| == 1 ) - return [$host="", $path=a[1]]; - - local b = split1(a[2], /\//); - return [$host=b[1], $path=(|b| == 2 ? cat("/", b[2]) : "/")]; - } - -event http_request(c: connection, method: string, original_URI: string, - unescaped_URI: string, version: string) - { - if ( method != "GET" && method != "CONNECT" ) - return; - - local client = c$id$orig_h; - local server = c$id$resp_h; - - if ( server in KnownProxies ) - return; - - # FIXME: Which one? original_URI or unescaped_URI? - local u = parse_url(original_URI); - - if ( client in requests ) - { - # We have already seen requests to this host. Let's see - # any matches the one we're very currently seeing. - local r = requests[client]; - if ( u$path in r$paths ) - { - if ( client !in found_proxies ) - { - NOTICE([$note=HTTPProxyFound, - $conn=c, $src=client, - $p=r$p, $URL=original_URI, - $msg=fmt("HTTP proxy found %s:%d (%s)", - client, r$p, original_URI)]); - add found_proxies[client]; - } - - return; - } - } - - if ( u$host == "" ) - # A relative URL. That's fine. - return; - - # An absolute URL. Remember path for later. - # - # Note: using "when", could even lookup the destination - # host and remember that one, too! - - if ( server !in requests ) - { - local empty_set: set[string] &read_expire = 15 secs; - local req = [$p=c$id$resp_p, $paths=empty_set]; - requests[server] = req; - } - - add requests[server]$paths[u$path]; - } diff --git a/policy.old/remote-pcap.bro b/policy.old/remote-pcap.bro deleted file mode 100644 index 18b124707e..0000000000 --- a/policy.old/remote-pcap.bro +++ /dev/null @@ -1,52 +0,0 @@ -# $Id: remote-pcap.bro 2704 2006-04-04 07:35:46Z vern $ -# -# Allows remote peers to set our capture filter. - -@load remote - -# We install a filter which (hopefully) doesn't match anything to avoid Bro's -# default "tcp or udp" when no other script/peers adds a filter. - -## FIXME: We need non-blocking pacp for this to work. -## -## ##redef capture_filters["match-nothing"] = "ether src 0:0:0:0:0:0"; - -function build_capture_filter_index(p: event_peer): string - { - return fmt("remote-%d", p$id); - } - -event remote_capture_filter(p: event_peer, filter: string) - { - # If we send a capture filter to a peer and are subscribed to all - # of its events, we will get a remote_capture_filter event back. - if ( is_remote_event() ) - return; - - Remote::do_script_log(p, fmt("received capture filter: %s", filter)); - - capture_filters[build_capture_filter_index(p)] = filter; - - # This will recompile the filter, which may take some time. - # Thus, setting a new capture_filter may cost us some packets :-(. - update_default_pcap_filter(); - - Remote::do_script_log(p, fmt("new default pcap filter: %s", - default_pcap_filter)); - } - -event remote_connection_closed(p: event_peer) - { - local i = build_capture_filter_index(p); - - if ( i in capture_filters ) - { - Remote::do_script_log(p, fmt("removed capture filter: %s", - capture_filters[i])); - delete capture_filters[i]; - update_default_pcap_filter(); - } - - Remote::do_script_log(p, fmt("new default pcap filter: %s", - default_pcap_filter)); - } diff --git a/policy.old/remote-ping.bro b/policy.old/remote-ping.bro deleted file mode 100644 index c27c8884d2..0000000000 --- a/policy.old/remote-ping.bro +++ /dev/null @@ -1,49 +0,0 @@ -# $Id: remote-ping.bro 2704 2006-04-04 07:35:46Z vern $ -# -# Exchanges periodic pings between communicating Bro's to measure their -# processing times. - -@load remote - -module RemotePing; - -export { - const ping_interval = 1 secs; -} - -global pings: table[event_peer] of count; - -event remote_connection_established(p: event_peer) - { - pings[p] = 0; - } - -event remote_connection_closed(p: event_peer) - { - delete pings[p]; - } - -event ping() - { - for ( p in pings ) - send_ping(p, ++pings[p]); - - schedule ping_interval { ping() }; - } - -event remote_pong(p: event_peer, seq: count, - d1: interval, d2: interval, d3: interval) - { - # We log three times: "time= [/]" - # t1: round-trip between the two parent processes. - # t2: round-trip between the two child processes. - # t3: sum of time spent in client<->parent communication on - # either side - Remote::do_script_log(p, fmt("ping seq=%d time=%.3fs [%.3fs/%.3fs]", seq, - d1, d2 - d3, d1 - d2 + d3)); - } - -event bro_init() - { - schedule ping_interval { ping() }; - } diff --git a/policy.old/remote-print-id-reply.bro b/policy.old/remote-print-id-reply.bro deleted file mode 100644 index 81d0efe35e..0000000000 --- a/policy.old/remote-print-id-reply.bro +++ /dev/null @@ -1,17 +0,0 @@ -# $Id:$ -# -# Load this script to support remote printing of variables. The remote -# peer accesses these by loading remote-print-id.bro. - -module PrintID; - -global request_id_response: event(id: string, content: string); - -event request_id(id: string) - { - if ( ! is_remote_event() ) - return; - - local val = lookup_ID(id); - event request_id_response(id, fmt("%s", val)); - } diff --git a/policy.old/remote-print-id.bro b/policy.old/remote-print-id.bro deleted file mode 100644 index 550ff8b8b8..0000000000 --- a/policy.old/remote-print-id.bro +++ /dev/null @@ -1,53 +0,0 @@ -# $Id:$ -# -# Requests the current value of a variable (identifier) from a remote -# peer, prints it, and then terminates. The other side must load -# remote-print-id-reply.bro. -# -# Intended to be used from the command line as in: -# -# bro -e 'redef PrintID::dst="" PrintID::id=""' -# remote-print-id -# -# The other scripts must set up the connection. is an index into -# Remote::destinations corresponding to the destination. - -module PrintID; - -@load remote -@load remote-print-id-reply - -export { - const dst = "" &redef; - const id = "" &redef; -} - -event remote_connection_handshake_done(p: event_peer) - { - local peer = Remote::destinations[dst]; - - if ( peer$host == p$host ) - { - print fmt("Requesting %s from %s at %s:%d", - id, dst, p$host, p$p); - event request_id(id); - } - } - -event request_id_response(id: string, content: string) - { - print fmt("%s = %s", id, content); - terminate_communication(); - } - -event bro_init() - { - if ( dst !in Remote::destinations ) - { - print fmt("Unknown destination %s", dst); - terminate(); - return; - } - - Remote::connect_peer(dst); - } diff --git a/policy.old/remote-print.bro b/policy.old/remote-print.bro deleted file mode 100644 index e0d29259c6..0000000000 --- a/policy.old/remote-print.bro +++ /dev/null @@ -1,9 +0,0 @@ -# $Id: remote-print.bro 415 2004-09-17 03:25:12Z vern $ -# -# Write remote print messages into local files. - -event print_hook(f: file, s: string) - { - if ( is_remote_event() ) - print f, s; - } diff --git a/policy.old/remote-report-notices.bro b/policy.old/remote-report-notices.bro deleted file mode 100644 index b70baf59c4..0000000000 --- a/policy.old/remote-report-notices.bro +++ /dev/null @@ -1,14 +0,0 @@ -# $Id:$ -# -# Forward remote notices to our local system. - -event notice_action(n: notice_info, action: NoticeAction) - { - if ( is_remote_event() ) - { - # Don't raise this event recursively. - suppress_notice_action = T; - NOTICE(n); - suppress_notice_action = F; - } - } diff --git a/policy.old/remote-send-id.bro b/policy.old/remote-send-id.bro deleted file mode 100644 index 15c1df5f75..0000000000 --- a/policy.old/remote-send-id.bro +++ /dev/null @@ -1,45 +0,0 @@ -# $Id:$ -# -# Sends the current value of an ID to a remote Bro and then terminates -# processing. -# -# Intended to be used from the command line as in: -# -# bro -e "redef Send::dst="" Send::id="" -# remote-send-id -# -# The other scripts must set up the connection. is an index into -# Remote::destinations corresponding to the destination. - -module Send; - -@load remote - -export { - const dst = "" &redef; - const id = "" &redef; -} - -event remote_connection_handshake_done(p: event_peer) - { - local peer = Remote::destinations[dst]; - - if ( peer$host == p$host ) - { - print fmt("Sending %s to %s at %s:%d", id, dst, p$host, p$p); - send_id(p, id); - terminate_communication(); - } - } - -event bro_init() - { - if ( dst !in Remote::destinations ) - { - print fmt("Unknown destination %s", dst); - terminate(); - return; - } - - Remote::connect_peer(dst); - } diff --git a/policy.old/remote.bro b/policy.old/remote.bro deleted file mode 100644 index 294c8fcd1e..0000000000 --- a/policy.old/remote.bro +++ /dev/null @@ -1,272 +0,0 @@ -# $Id: remote.bro 5101 2007-11-29 07:02:27Z vern $ -# -# Connect to remote Bros and request some of their events. - -module Remote; - -export { - const default_port_ssl = 47756/tcp &redef; - const default_port_clear = 47757/tcp &redef; - - # Default compression level. - global default_compression = 0 &redef; - - # A remote peer to which we would like to talk. - # If there's no entry for a peer, it may still connect - # and request state, but not send us any. - type Destination : record { - # Destination endpoint. - host: addr; - p: port &optional; - - # When accepting a connection, the configuration only - # applies if the class matches the one transmitted by - # the peer. - # - # When initiating a connection, the class is sent to - # the other side. - class: string &optional; - - # Events requested from remote side. - events: pattern &optional; - - # Whether we are going to connect (rather than waiting - # for the other sie to connect to us). - connect: bool &default = F; - - # If disconnected, reconnect after this many seconds. - retry: interval &default = 0 secs; - - # Whether to accept remote events. - accept_input: bool &default = T; - - # Whether to perform state synchronization with peer. - sync: bool &default = T; - - # Whether to request logs from the peer. - request_logs: bool &default = F; - - # When performing state synchronization, whether we consider - # our state to be authoritative. If so, we will send the peer - # our current set when the connection is set up. - # (Only one side can be authoritative.) - auth: bool &default = F; - - # If not set, no capture filter is sent. - # If set to "", the default cature filter is sent. - capture_filter: string &optional; - - # Whether to use SSL-based communication. - ssl: bool &default = F; - - # Take-over state from this host - # (activated by loading hand-over.bro) - hand_over: bool &default = F; - - # Compression level is 0-9, with 0 = no compression. - compression: count &default = default_compression; - - # Set when connected. - peer: event_peer &optional; - connected: bool &default = F; - }; - - const destinations: table[string] of Destination &redef; - - # redef destinations += { - # ["foo"] = [$host = foo.bar.com, $events = /.*/, $connect=T, $retry = 60 secs, $ssl=T] - # }; - - # Write log message into remote.log - global do_script_log: function(p: event_peer, msg: string); - - global pending_peers: table[peer_id] of Destination; - global connected_peers: table[peer_id] of Destination; - - # Connect to destionations[dst], independent of its "connect" flag. - global connect_peer: function(peer: string); -} - -# Called rm_log rather than remote_log because there's an event by that name. -global rm_log = open_log_file("remote"); - -global src_names = { - [REMOTE_SRC_CHILD] = "[child] ", - [REMOTE_SRC_PARENT] = "[parent]", - [REMOTE_SRC_SCRIPT] = "[script]", -}; - -function do_script_log_common(level: count, src: count, msg: string) - { - print rm_log, - fmt("%.6f %s %s %s", current_time(), - (level == REMOTE_LOG_INFO ? "[info] " : "[error]"), - src_names[src], msg); - } - -event remote_log(level: count, src: count, msg: string) - { - do_script_log_common(level, src, msg); - } - -function do_script_log(p: event_peer, msg: string) - { - do_script_log_common(REMOTE_LOG_INFO, REMOTE_SRC_SCRIPT, - fmt("[#%d/%s:%d] %s", p$id, p$host, p$p, msg)); - } - -function connect_peer(peer: string) - { - local dst = destinations[peer]; - local p = dst$ssl ? default_port_ssl : default_port_clear; - - if ( dst?$p ) - p = dst$p; - - local class = dst?$class ? dst$class : ""; - local id = connect(dst$host, p, class ,dst$retry, dst$ssl); - - if ( id == PEER_ID_NONE ) - print rm_log, - fmt("%.6f %s/%d can't trigger connect", - current_time(), dst$host, p); - - pending_peers[id] = dst; - } - -event bro_init() &priority = -10 # let others modify destinations - { - set_buf(rm_log, F); - - for ( tag in destinations ) - { - if ( ! destinations[tag]$connect ) - next; - - connect_peer(tag); - } - } - -function setup_peer(p: event_peer, dst: Destination) - { - if ( dst?$events ) - { - do_script_log(p, fmt("requesting events matching %s", dst$events)); - request_remote_events(p, dst$events); - } - - if ( dst?$capture_filter ) - { - local filter = dst$capture_filter; - if ( filter == "" ) - filter = default_pcap_filter; - - do_script_log(p, fmt("sending capture_filter: %s", filter)); - send_capture_filter(p, filter); - } - - if ( dst$accept_input ) - { - do_script_log(p, "accepting state"); - set_accept_state(p, T); - } - - set_compression_level(p, dst$compression); - - if ( dst$sync ) - { - do_script_log(p, "requesting synchronized state"); - request_remote_sync(p, dst$auth); - } - - if ( dst$request_logs ) - { - do_script_log(p, "requesting logs"); - request_remote_logs(p); - } - - dst$peer = p; - dst$connected = T; - connected_peers[p$id] = dst; - } - -event remote_connection_established(p: event_peer) - { - if ( is_remote_event() ) - return; - - do_script_log(p, "connection established"); - - if ( p$id in pending_peers ) - { - # We issued the connect. - local dst = pending_peers[p$id]; - setup_peer(p, dst); - delete pending_peers[p$id]; - } - else - { # The other side connected to us. - local found = F; - for ( i in destinations ) - { - dst = destinations[i]; - if ( dst$host == p$host ) - { - local c = 0; - - # See if classes match = either both have - # the same class, or neither of them has - # a class. - if ( p?$class && p$class != "" ) - ++c; - - if ( dst?$class && dst$class != "" ) - ++c; - - if ( c == 1 || - (c == 2 && p$class != dst$class) ) - next; - - found = T; - setup_peer(p, dst); - break; - } - } - - if ( ! found ) - set_compression_level(p, default_compression); - } - - complete_handshake(p); - } - -event remote_connection_closed(p: event_peer) - { - if ( is_remote_event() ) - return; - - do_script_log(p, "connection closed"); - - if ( p$id in connected_peers ) - { - local dst = connected_peers[p$id]; - dst$connected = F; - - delete connected_peers[p$id]; - - if ( dst$retry != 0secs ) - # The core will retry. - pending_peers[p$id] = dst; - } - } - -event remote_state_inconsistency(operation: string, id: string, - expected_old: string, real_old: string) - { - if ( is_remote_event() ) - return; - - print rm_log, - fmt("%.6f state inconsistency: %s should be %s but is %s before %s", - network_time(), id, expected_old, real_old, operation); - } diff --git a/policy.old/rotate-logs.bro b/policy.old/rotate-logs.bro deleted file mode 100644 index 92ab4cf455..0000000000 --- a/policy.old/rotate-logs.bro +++ /dev/null @@ -1,160 +0,0 @@ -# $Id: rotate-logs.bro 4685 2007-07-30 23:50:26Z vern $ - -module RotateLogs; - -export { - # Maps file names to postprocessors. - global postprocessors: table[string] of string &redef; - - # Default postprocessor. - global default_postprocessor = "" &redef; - - # Files which are to be rotated according to log_rotate_interval - # and log_max_size, but aren't represented by a file object. - global aux_files: set[string] &redef; - - # For aux_files, the time interval in which we check the files' sizes. - global aux_check_size_interval = 30 secs &redef; - - # Callback to provide name for rotated file. - global build_name: function(info: rotate_info): string &redef; - - # Default naming suffix format. - global date_format = "%y-%m-%d_%H.%M.%S" &redef; - - # Whether to rotate files when shutting down. - global rotate_on_shutdown = T &redef; - - # If set, postprocessors get this tag as an additional argument. - global tag = "" &redef; -} - -# Default rotation is once per hour. -redef log_rotate_interval = 1 hr; - -# There are other variables that are defined in bro.init. Here are -# some example of how these might be redefined. -# redef log_rotate_base_time = "0:00"; -# redef log_max_size = 1e7; -# redef log_encryption_key = "mybigsecret"; - -# Given a rotate info record, returns new rotated filename. -function build_name(info: rotate_info): string - { - return fmt("%s-%s", info$old_name, strftime(date_format, info$open)); - } - -# Run post-processor on file. If there isn't any postprocessor defined, -# we move the file to a nicer name. -function run_pp(info: rotate_info) - { - local pp = default_postprocessor; - - if ( info$old_name in postprocessors ) - pp = postprocessors[info$old_name]; - - if ( pp != "" ) - # The date format is hard-coded here to provide a standardized - # script interface. - system(fmt("%s %s %s %s %s %s %s", - pp, info$new_name, info$old_name, - strftime("%y-%m-%d_%H.%M.%S", info$open), - strftime("%y-%m-%d_%H.%M.%S", info$close), - bro_is_terminating() ? "1" : "0", - tag)); - else - system(fmt("/bin/mv %s %s %s", - info$new_name, build_name(info), tag)); - } - -# Rotate file. -function rotate(f: file) - { - local info = rotate_file(f); - if ( info$old_name == "" ) - # Error. - return; - - run_pp(info); - } - -# Rotate file, but only if we know the name. -function rotate_by_name(f: string) - { - local info = rotate_file_by_name(f); - if ( info$old_name == "" ) - # Error. - return; - - run_pp(info); - } - -function make_nice_timestamp(i: interval) : time - { - # To get nice timestamps, we round the time up to - # the next multiple of the rotation interval. - - local nt = time_to_double(network_time()); - local ri = interval_to_double(i); - - return double_to_time(floor(nt / ri) * ri + ri); - } - -# Raised when a &rotate_interval expires. -event rotate_interval(f: file) - { - if ( bro_is_terminating() && ! rotate_on_shutdown ) - return; - - rotate(f); - } - -# Raised when a &rotate_size is reached. -event rotate_size(f: file) - { - rotate(f); - } - -# Raised for aux_files when log_rotate_inverval expires. - -global first_aux_rotate_interval = T; - -event aux_rotate_interval() - { - if ( bro_is_terminating() && ! rotate_on_shutdown ) - return; - - if ( ! first_aux_rotate_interval ) - for ( f in aux_files ) - rotate_by_name(f); - - first_aux_rotate_interval = F; - - if ( ! bro_is_terminating() ) - schedule calc_next_rotate(log_rotate_interval) - { aux_rotate_interval() }; - } - -# Regularly raised to check aux_files' sizes. -event aux_check_size() - { - for ( f in aux_files ) - if ( file_size(f) > log_max_size ) - rotate_by_name(f); - - if ( ! bro_is_terminating() ) - schedule aux_check_size_interval { aux_check_size() }; - } - -event bro_init() - { - if ( length(aux_files) != 0 ) - { - if ( log_rotate_interval != 0 secs ) - schedule calc_next_rotate(log_rotate_interval) - { aux_rotate_interval() }; - - if ( log_max_size != 0 ) - schedule aux_check_size_interval { aux_check_size() }; - } - } diff --git a/policy.old/rsh.bro b/policy.old/rsh.bro deleted file mode 100644 index 933d765dc7..0000000000 --- a/policy.old/rsh.bro +++ /dev/null @@ -1,105 +0,0 @@ -# $Id: rsh.bro 4758 2007-08-10 06:49:23Z vern $ - -@load conn -@load login - -module RSH; - -export { - redef enum Notice += { - # RSH client username and server username differ. - DifferentRSH_Usernames, - - # Attempt to authenticate via RSH failed. - FailedRSH_Authentication, - - # RSH session appears to be interactive - multiple lines of - # user commands. - InteractiveRSH, - - SensitiveRSH_Input, - SensitiveRSH_Output, - }; - - const failure_msgs = - /^Permission denied/ - | /Login failed/ - &redef; -} - -redef capture_filters += { ["rsh"] = "tcp port 514" }; - -global rsh_ports = { 514/tcp } &redef; -redef dpd_config += { [ANALYZER_RSH] = [$ports = rsh_ports] }; - -type rsh_session_info: record { - client_user: string; - server_user: string; - initial_cmd: string; - output_line: count; # number of lines seen -}; - -global rsh_sessions: table[conn_id] of rsh_session_info; - -function new_rsh_session(c: connection, client_user: string, - server_user: string, line: string) - { - if ( c$id in rsh_sessions ) - delete rsh_sessions[c$id]; - - local s: rsh_session_info; - s$client_user = client_user; - s$server_user = server_user; - s$initial_cmd = line; - s$output_line = 0; - - rsh_sessions[c$id] = s; - } - -event rsh_request(c: connection, client_user: string, server_user: string, - line: string, new_session: bool) - { - local id = c$id; - - local BS_line = edit(line, Login::BS); - local DEL_line = edit(line, Login::DEL); - - if ( new_session ) - { - new_rsh_session(c, client_user, server_user, line); - - if ( client_user != server_user ) - NOTICE([$note=DifferentRSH_Usernames, $conn=c, - $msg=fmt("differing client/server usernames (%s/%s)", - client_user, server_user), - $sub=client_user, $user=server_user]); - } - - local s = rsh_sessions[c$id]; - if ( s$output_line > 0 ) - NOTICE([$note=InteractiveRSH, $conn=c, - $msg="interactive RSH session, input following output", - $sub=s$client_user, $user=s$server_user]); - - if ( Login::input_trouble in line || - Login::input_trouble in BS_line || - Login::input_trouble in DEL_line || - line == Login::full_input_trouble ) - NOTICE([$note=SensitiveRSH_Input, $conn=c, - $msg=line, $sub=s$client_user, $user=s$server_user]); - } - -event rsh_reply(c: connection, client_user: string, server_user: string, - line: string) - { - local s = rsh_sessions[c$id]; - - if ( line != "" && ++s$output_line == 1 && failure_msgs in line ) - NOTICE([$note=FailedRSH_Authentication, $conn=c, - $msg=line, $sub=s$client_user, $user=s$server_user]); - - if ( Login::output_trouble in line || - line == Login::full_output_trouble ) - NOTICE([$note=SensitiveRSH_Output, $conn=c, - $msg=line, $sub=s$client_user, $user=s$server_user]); - } diff --git a/policy.old/save-peer-status.bro b/policy.old/save-peer-status.bro deleted file mode 100644 index 26481bc093..0000000000 --- a/policy.old/save-peer-status.bro +++ /dev/null @@ -1,53 +0,0 @@ -# $Id$ -# -# Writes a summary of our peer's status into a file. - -@load peer-status - -event PeerStatus::update(status: PeerStatus::peer_status) &priority = -5 - { - local f = open_log_file("peer_status"); - - for ( id in PeerStatus::peers ) - { - local stat = PeerStatus::peers[id]; - local host: string; - - if ( id != 0 ) - { - if ( id !in Remote::connected_peers ) - next; - - host = Remote::connected_peers[id]$peer$descr; - } - else - host = get_local_event_peer()$descr; - - print f, fmt("%18s %s%s %D %D %02.0f%% %4dM #%d %dK/%dK/%dK (%.1f%%)", - host, stat$res$version, stat$res$debug ? "-DEBUG" : "", - stat$res$start_time, stat$current_time, stat$cpu, - stat$res$mem / 1024 / 1024, - stat$res$num_TCP_conns + stat$res$num_UDP_conns + stat$res$num_ICMP_conns, - stat$stats$pkts_dropped / 1024, - stat$stats$pkts_recvd / 1024, - stat$stats$pkts_link / 1024, - 100.0 * stat$stats$pkts_dropped / (stat$stats$pkts_dropped + stat$stats$pkts_recvd)); - } - - print f, "###"; - -# for ( id in PeerStatus::peers ) -# { -# stat = PeerStatus::peers[id]; -# -# if ( id != 0 ) -# host = Remote::connected_peers[id]$peer$descr; -# else -# host = get_local_event_peer()$descr; -# -# print f, fmt("%10s %s", host, stat$default_filter); -# print f; -# } - - close(f); - } diff --git a/policy.old/scan.bro b/policy.old/scan.bro deleted file mode 100644 index d3ee0574c3..0000000000 --- a/policy.old/scan.bro +++ /dev/null @@ -1,706 +0,0 @@ -# $Id: scan.bro 7073 2010-09-13 00:45:02Z vern $ - -@load conn -@load notice -@load port-name -@load hot -@load drop -@load trw-impl - -module Scan; - -export { - redef enum Notice += { - PortScan, # the source has scanned a number of ports - AddressScan, # the source has scanned a number of addrs - BackscatterSeen, - # apparent flooding backscatter seen from source - - ScanSummary, # summary of scanning activity - PortScanSummary, # summary of distinct ports per scanner - LowPortScanSummary, # summary of distinct low ports per scanner - - PasswordGuessing, # source tried many user/password combinations - SuccessfulPasswordGuessing, # same, but a login succeeded - - Landmine, # source touched a landmine destination - ShutdownThresh, # source reached shut_down_thresh - LowPortTrolling, # source touched privileged ports - }; - - # If true, we suppress scan-checking (we still do account-tried - # accounting). This is provided because scan-checking can consume - # a lot of memory. - const suppress_scan_checks = F &redef; - - # Whether to consider UDP "connections" for scan detection. - # Can lead to false positives due to UDP fanout from some P2P apps. - const suppress_UDP_scan_checks = F &redef; - - const activate_priv_port_check = T &redef; - const activate_landmine_check = F &redef; - const landmine_thresh_trigger = 5 &redef; - - const landmine_address: set[addr] &redef; - - const scan_summary_trigger = 25 &redef; - const port_summary_trigger = 20 &redef; - const lowport_summary_trigger = 10 &redef; - - # Raise ShutdownThresh after this many failed attempts - const shut_down_thresh = 100 &redef; - - # Which services should be analyzed when detecting scanning - # (not consulted if analyze_all_services is set). - const analyze_services: set[port] &redef; - const analyze_all_services = T &redef; - - # Track address scaners only if at least these many hosts contacted. - const addr_scan_trigger = 0 &redef; - - # Ignore address scanners for further scan detection after - # scanning this many hosts. - # 0 disables. - const ignore_scanners_threshold = 0 &redef; - - # Report a scan of peers at each of these points. - const report_peer_scan: vector of count = { - 20, 100, 1000, 10000, 50000, 100000, 250000, 500000, 1000000, - } &redef; - - const report_outbound_peer_scan: vector of count = { - 100, 1000, 10000, - } &redef; - - # Report a scan of ports at each of these points. - const report_port_scan: vector of count = { - 50, 250, 1000, 5000, 10000, 25000, 65000, - } &redef; - - # Once a source has scanned this many different ports (to however many - # different remote hosts), start tracking its per-destination access. - const possible_port_scan_thresh = 20 &redef; - - # Threshold for scanning privileged ports. - const priv_scan_trigger = 5 &redef; - const troll_skip_service = { - smtp, ftp, ssh, 20/tcp, http, - } &redef; - - const report_accounts_tried: vector of count = { - 20, 100, 1000, 10000, 100000, 1000000, - } &redef; - - const report_remote_accounts_tried: vector of count = { - 100, 500, - } &redef; - - # Report a successful password guessing if the source attempted - # at least this many. - const password_guessing_success_threshhold = 20 &redef; - - const skip_accounts_tried: set[addr] &redef; - - const addl_web = { - 81/tcp, 443/tcp, 8000/tcp, 8001/tcp, 8080/tcp, } - &redef; - - const skip_services = { ident, } &redef; - const skip_outbound_services = { Hot::allow_services, ftp, addl_web, } - &redef; - - const skip_scan_sources = { - 255.255.255.255, # who knows why we see these, but we do - - # AltaVista. Here just as an example of what sort of things - # you might list. - test-scooter.av.pa-x.dec.com, - } &redef; - - const skip_scan_nets: set[subnet] = {} &redef; - - # List of well known local server/ports to exclude for scanning - # purposes. - const skip_dest_server_ports: set[addr, port] = {} &redef; - - # Reverse (SYN-ack) scans seen from these ports are considered - # to reflect possible SYN-flooding backscatter, and not true - # (stealth) scans. - const backscatter_ports = { - http, 53/tcp, 53/udp, bgp, 6666/tcp, 6667/tcp, - } &redef; - - const report_backscatter: vector of count = { - 20, - } &redef; - - global check_scan: - function(c: connection, established: bool, reverse: bool): bool; - - # The following tables are defined here so that we can redef - # the expire timeouts. - # FIXME: should we allow redef of attributes on IDs which - # are not exported? - - # How many different hosts connected to with a possible - # backscatter signature. - global distinct_backscatter_peers: table[addr] of table[addr] of count - &read_expire = 15 min; - - # Expire functions that trigger summaries. - global scan_summary: - function(t: table[addr] of set[addr], orig: addr): interval; - global port_summary: - function(t: table[addr] of set[port], orig: addr): interval; - global lowport_summary: - function(t: table[addr] of set[port], orig: addr): interval; - - # Indexed by scanner address, yields # distinct peers scanned. - # pre_distinct_peers tracks until addr_scan_trigger hosts first. - global pre_distinct_peers: table[addr] of set[addr] - &read_expire = 15 mins &redef; - - global distinct_peers: table[addr] of set[addr] - &read_expire = 15 mins &expire_func=scan_summary &redef; - global distinct_ports: table[addr] of set[port] - &read_expire = 15 mins &expire_func=port_summary &redef; - global distinct_low_ports: table[addr] of set[port] - &read_expire = 15 mins &expire_func=lowport_summary &redef; - - # Indexed by scanner address, yields a table with scanned hosts - # (and ports). - global scan_triples: table[addr] of table[addr] of set[port]; - - global remove_possible_source: - function(s: set[addr], idx: addr): interval; - global possible_scan_sources: set[addr] - &expire_func=remove_possible_source &read_expire = 15 mins; - - # Indexed by source address, yields user name & password tried. - global accounts_tried: table[addr] of set[string, string] - &read_expire = 1 days; - - global ignored_scanners: set[addr] &create_expire = 1 day &redef; - - # These tables track whether a threshold has been reached. - # More precisely, the counter is the next index of threshold vector. - global shut_down_thresh_reached: table[addr] of bool &default=F; - global rb_idx: table[addr] of count - &default=0 &read_expire = 1 days &redef; - global rps_idx: table[addr] of count - &default=0 &read_expire = 1 days &redef; - global rops_idx: table[addr] of count - &default=0 &read_expire = 1 days &redef; - global rpts_idx: table[addr,addr] of count - &default=0 &read_expire = 1 days &redef; - global rat_idx: table[addr] of count - &default=0 &read_expire = 1 days &redef; - global rrat_idx: table[addr] of count - &default=0 &read_expire = 1 days &redef; -} - -global thresh_check: function(v: vector of count, idx: table[addr] of count, - orig: addr, n: count): bool; -global thresh_check_2: function(v: vector of count, - idx: table[addr,addr] of count, orig: addr, - resp: addr, n: count): bool; - -function scan_summary(t: table[addr] of set[addr], orig: addr): interval - { - local num_distinct_peers = orig in t ? |t[orig]| : 0; - - if ( num_distinct_peers >= scan_summary_trigger ) - NOTICE([$note=ScanSummary, $src=orig, $n=num_distinct_peers, - $msg=fmt("%s scanned a total of %d hosts", - orig, num_distinct_peers)]); - - return 0 secs; - } - -function port_summary(t: table[addr] of set[port], orig: addr): interval - { - local num_distinct_ports = orig in t ? |t[orig]| : 0; - - if ( num_distinct_ports >= port_summary_trigger ) - NOTICE([$note=PortScanSummary, $src=orig, $n=num_distinct_ports, - $msg=fmt("%s scanned a total of %d ports", - orig, num_distinct_ports)]); - - return 0 secs; - } - -function lowport_summary(t: table[addr] of set[port], orig: addr): interval - { - local num_distinct_lowports = orig in t ? |t[orig]| : 0; - - if ( num_distinct_lowports >= lowport_summary_trigger ) - NOTICE([$note=LowPortScanSummary, $src=orig, - $n=num_distinct_lowports, - $msg=fmt("%s scanned a total of %d low ports", - orig, num_distinct_lowports)]); - - return 0 secs; - } - -function clear_addr(a: addr) - { - delete distinct_peers[a]; - delete distinct_ports[a]; - delete distinct_low_ports[a]; - delete scan_triples[a]; - delete possible_scan_sources[a]; - delete distinct_backscatter_peers[a]; - delete pre_distinct_peers[a]; - delete rb_idx[a]; - delete rps_idx[a]; - delete rops_idx[a]; - delete rat_idx[a]; - delete rrat_idx[a]; - delete shut_down_thresh_reached[a]; - delete ignored_scanners[a]; - } - -function ignore_addr(a: addr) - { - clear_addr(a); - add ignored_scanners[a]; - } - -function check_scan(c: connection, established: bool, reverse: bool): bool - { - if ( suppress_scan_checks ) - return F; - - local id = c$id; - - local service = "ftp-data" in c$service ? 20/tcp - : (reverse ? id$orig_p : id$resp_p); - local rev_service = reverse ? id$resp_p : id$orig_p; - local orig = reverse ? id$resp_h : id$orig_h; - local resp = reverse ? id$orig_h : id$resp_h; - local outbound = is_local_addr(orig); - - # The following works better than using get_conn_transport_proto() - # because c might not correspond to an active connection (which - # causes the function to fail). - if ( suppress_UDP_scan_checks && - service >= 0/udp && service <= 65535/udp ) - return F; - - if ( service in skip_services && ! outbound ) - return F; - - if ( outbound && service in skip_outbound_services ) - return F; - - if ( orig in skip_scan_sources ) - return F; - - if ( orig in skip_scan_nets ) - return F; - - # Don't include well known server/ports for scanning purposes. - if ( ! outbound && [resp, service] in skip_dest_server_ports ) - return F; - - if ( orig in ignored_scanners) - return F; - - if ( (! established || service !in Hot::allow_services) && - # not established, service not expressly allowed - - # not known peer set - (orig !in distinct_peers || resp !in distinct_peers[orig]) && - - # want to consider service for scan detection - (analyze_all_services || service in analyze_services) ) - { - if ( reverse && rev_service in backscatter_ports && - # reverse, non-priv backscatter port - service >= 1024/tcp ) - { - if ( orig !in distinct_backscatter_peers ) - { - local empty_bs_table: - table[addr] of count &default=0; - distinct_backscatter_peers[orig] = - empty_bs_table; - } - - if ( ++distinct_backscatter_peers[orig][resp] <= 2 && - # The test is <= 2 because we get two check_scan() - # calls, once on connection attempt and once on - # tear-down. - - distinct_backscatter_peers[orig][resp] == 1 && - - # Looks like backscatter, and it's not scanning - # a privileged port. - - thresh_check(report_backscatter, rb_idx, orig, - |distinct_backscatter_peers[orig]|) - ) - { - local rev_svc = rev_service in port_names ? - port_names[rev_service] : - fmt("%s", rev_service); - - NOTICE([$note=BackscatterSeen, $src=orig, - $p=rev_service, - $msg=fmt("backscatter seen from %s (%d hosts; %s)", - orig, |distinct_backscatter_peers[orig]|, rev_svc)]); - } - - if ( ignore_scanners_threshold > 0 && - |distinct_backscatter_peers[orig]| > - ignore_scanners_threshold ) - ignore_addr(orig); - } - - else - { # done with backscatter check - local ignore = F; - - local svc = service in port_names ? - port_names[service] : fmt("%s", service); - - if ( orig !in distinct_peers && addr_scan_trigger > 0 ) - { - if ( orig !in pre_distinct_peers ) - pre_distinct_peers[orig] = set(); - - add pre_distinct_peers[orig][resp]; - if ( |pre_distinct_peers[orig]| < addr_scan_trigger ) - ignore = T; - } - - if ( ! ignore ) - { # XXXXX - - if ( orig !in distinct_peers ) - distinct_peers[orig] = set() &mergeable; - - if ( resp !in distinct_peers[orig] ) - add distinct_peers[orig][resp]; - - local n = |distinct_peers[orig]|; - - if ( activate_landmine_check && - n >= landmine_thresh_trigger && - mask_addr(resp, 24) in landmine_address ) - { - local msg2 = fmt("landmine address trigger %s%s ", orig, svc); - NOTICE([$note=Landmine, $src=orig, - $p=service, $msg=msg2]); - } - - # Check for threshold if not outbound. - if ( ! shut_down_thresh_reached[orig] && - n >= shut_down_thresh && - ! outbound && orig !in neighbor_nets ) - { - shut_down_thresh_reached[orig] = T; - local msg = fmt("shutdown threshold reached for %s", orig); - NOTICE([$note=ShutdownThresh, $src=orig, - $p=service, $msg=msg]); - } - - else - { - local address_scan = F; - if ( outbound && - # inside host scanning out? - thresh_check(report_outbound_peer_scan, rops_idx, orig, n) ) - address_scan = T; - - if ( ! outbound && - thresh_check(report_peer_scan, rps_idx, orig, n) ) - address_scan = T; - - if ( address_scan ) - NOTICE([$note=AddressScan, - $src=orig, $p=service, - $n=n, - $msg=fmt("%s has scanned %d hosts (%s)", - orig, n, svc)]); - - if ( address_scan && - ignore_scanners_threshold > 0 && - n > ignore_scanners_threshold ) - ignore_addr(orig); - } - } - } # XXXX - } - - if ( established ) - # Don't consider established connections for port scanning, - # it's too easy to be mislead by FTP-like applications that - # legitimately gobble their way through the port space. - return F; - - # Coarse search for port-scanning candidates: those that have made - # connections (attempts) to possible_port_scan_thresh or more - # distinct ports. - if ( orig !in distinct_ports || service !in distinct_ports[orig] ) - { - if ( orig !in distinct_ports ) - distinct_ports[orig] = set() &mergeable; - - if ( service !in distinct_ports[orig] ) - add distinct_ports[orig][service]; - - if ( |distinct_ports[orig]| >= possible_port_scan_thresh && - orig !in scan_triples ) - { - scan_triples[orig] = table() &mergeable; - add possible_scan_sources[orig]; - } - } - - # Check for low ports. - if ( activate_priv_port_check && ! outbound && service < 1024/tcp && - service !in troll_skip_service ) - { - if ( orig !in distinct_low_ports || - service !in distinct_low_ports[orig] ) - { - if ( orig !in distinct_low_ports ) - distinct_low_ports[orig] = set() &mergeable; - - add distinct_low_ports[orig][service]; - - if ( |distinct_low_ports[orig]| == priv_scan_trigger && - orig !in neighbor_nets ) - { - local s = service in port_names ? port_names[service] : - fmt("%s", service); - local svrc_msg = fmt("low port trolling %s %s", orig, s); - NOTICE([$note=LowPortTrolling, $src=orig, - $p=service, $msg=svrc_msg]); - } - - if ( ignore_scanners_threshold > 0 && - |distinct_low_ports[orig]| > - ignore_scanners_threshold ) - ignore_addr(orig); - } - } - - # For sources that have been identified as possible scan sources, - # keep track of per-host scanning. - if ( orig in possible_scan_sources ) - { - if ( orig !in scan_triples ) - scan_triples[orig] = table() &mergeable; - - if ( resp !in scan_triples[orig] ) - scan_triples[orig][resp] = set() &mergeable; - - if ( service !in scan_triples[orig][resp] ) - { - add scan_triples[orig][resp][service]; - - if ( thresh_check_2(report_port_scan, rpts_idx, - orig, resp, - |scan_triples[orig][resp]|) ) - { - local m = |scan_triples[orig][resp]|; - NOTICE([$note=PortScan, $n=m, $src=orig, - $p=service, - $msg=fmt("%s has scanned %d ports of %s", - orig, m, resp)]); - } - } - } - - return T; - } - - -event account_tried(c: connection, user: string, passwd: string) - { - local src = c$id$orig_h; - - if ( src !in accounts_tried ) - accounts_tried[src] = set(); - - if ( [user, passwd] in accounts_tried[src] ) - return; - - local threshold_check = F; - - if ( is_local_addr(src) ) - { - if ( thresh_check(report_remote_accounts_tried, rrat_idx, src, - |accounts_tried[src]|) ) - threshold_check = T; - } - else - { - if ( thresh_check(report_accounts_tried, rat_idx, src, - |accounts_tried[src]|) ) - threshold_check = T; - } - - if ( threshold_check && src !in skip_accounts_tried ) - { - local m = |accounts_tried[src]|; - NOTICE([$note=PasswordGuessing, $src=src, $n=m, - $user=user, $sub=passwd, $p=c$id$resp_p, - $msg=fmt("%s has tried %d username/password combinations (latest: %s@%s)", - src, m, user, c$id$resp_h)]); - } - - add accounts_tried[src][user, passwd]; - } - -# Check for a successful login attempt from a scan. -event login_successful(c: connection, user: string) - { - local id = c$id; - local src = id$orig_h; - - if ( src in accounts_tried && - |accounts_tried[src]| >= password_guessing_success_threshhold ) - NOTICE([$note=SuccessfulPasswordGuessing, $src=src, $conn=c, - $msg=fmt("%s successfully logged in user '%s' after trying %d username/password combinations", - src, user, |accounts_tried[src]|)]); - } - - -# Hook into the catch&release dropping. When an address gets restored, we reset -# the source to allow dropping it again. -event Drop::address_restored(a: addr) - { - Drop::debug_log(fmt("received restored for %s (scan.bro)", a)); - clear_addr(a); - } - -event Drop::address_cleared(a: addr) - { - Drop::debug_log(fmt("received cleared for %s (scan.bro)", a)); - clear_addr(a); - } - -# When removing a possible scan source, we automatically delete its scanned -# hosts and ports. But we do not want the deletion propagated, because every -# peer calls the expire_function on its own (and thus applies the delete -# operation on its own table). -function remove_possible_source(s: set[addr], idx: addr): interval - { - suspend_state_updates(); - delete scan_triples[idx]; - resume_state_updates(); - - return 0 secs; - } - -# To recognize whether a certain threshhold vector (e.g. report_peer_scans) -# has been transgressed, a global variable containing the next vector index -# (idx) must be incremented. This cumbersome mechanism is necessary because -# values naturally don't increment by one (e.g. replayed table merges). -function thresh_check(v: vector of count, idx: table[addr] of count, - orig: addr, n: count): bool - { - if ( ignore_scanners_threshold > 0 && n > ignore_scanners_threshold ) - { - ignore_addr(orig); - return F; - } - - if ( idx[orig] < |v| && n >= v[idx[orig]] ) - { - ++idx[orig]; - return T; - } - else - return F; - } - -# Same as above, except the index has a different type signature. -function thresh_check_2(v: vector of count, idx: table[addr, addr] of count, - orig: addr, resp: addr, n: count): bool - { - if ( ignore_scanners_threshold > 0 && n > ignore_scanners_threshold ) - { - ignore_addr(orig); - return F; - } - - if ( idx[orig,resp] < |v| && n >= v[idx[orig, resp]] ) - { - ++idx[orig,resp]; - return T; - } - else - return F; - } - -event connection_established(c: connection) - { - local is_reverse_scan = (c$orig$state == TCP_INACTIVE); - Scan::check_scan(c, T, is_reverse_scan); - - local trans = get_port_transport_proto(c$id$orig_p); - if ( trans == tcp && ! is_reverse_scan && TRW::use_TRW_algorithm ) - TRW::check_TRW_scan(c, conn_state(c, trans), F); - } - -event partial_connection(c: connection) - { - Scan::check_scan(c, T, F); - } - -event connection_attempt(c: connection) - { - Scan::check_scan(c, F, c$orig$state == TCP_INACTIVE); - - local trans = get_port_transport_proto(c$id$orig_p); - if ( trans == tcp && TRW::use_TRW_algorithm ) - TRW::check_TRW_scan(c, conn_state(c, trans), F); - } - -event connection_half_finished(c: connection) - { - # Half connections never were "established", so do scan-checking here. - Scan::check_scan(c, F, F); - } - -event connection_rejected(c: connection) - { - local is_reverse_scan = c$orig$state == TCP_RESET; - - Scan::check_scan(c, F, is_reverse_scan); - - local trans = get_port_transport_proto(c$id$orig_p); - if ( trans == tcp && TRW::use_TRW_algorithm ) - TRW::check_TRW_scan(c, conn_state(c, trans), is_reverse_scan); - } - -event connection_reset(c: connection) - { - if ( c$orig$state == TCP_INACTIVE || c$resp$state == TCP_INACTIVE ) - # We never heard from one side - that looks like a scan. - Scan::check_scan(c, c$orig$size + c$resp$size > 0, - c$orig$state == TCP_INACTIVE); - } - -event connection_pending(c: connection) - { - if ( c$orig$state == TCP_PARTIAL && c$resp$state == TCP_INACTIVE ) - Scan::check_scan(c, F, F); - } - -# Report the remaining entries in the tables. -event bro_done() - { - for ( orig in distinct_peers ) - scan_summary(distinct_peers, orig); - - for ( orig in distinct_ports ) - port_summary(distinct_ports, orig); - - for ( orig in distinct_low_ports ) - lowport_summary(distinct_low_ports, orig); - } diff --git a/policy.old/secondary-filter.bro b/policy.old/secondary-filter.bro deleted file mode 100644 index 025e450225..0000000000 --- a/policy.old/secondary-filter.bro +++ /dev/null @@ -1,44 +0,0 @@ -# $Id: secondary-filter.bro 6022 2008-07-25 19:15:00Z vern $ - -# Examples of using the secondary-filter matching path. - -event rst_syn_fin_flag(filter: string, pkt: pkt_hdr) - { - print "rst_syn_fin_flag()"; - print fmt(" %s:%s -> %s:%s", pkt$ip$src, pkt$tcp$sport, - pkt$ip$dst, pkt$tcp$dport); - } - -event a_udp_event(filter: string, pkt: pkt_hdr) - { - print "a_udp_event()"; - print fmt(" %s:%s -> %s:%s", pkt$ip$src, pkt$udp$sport, - pkt$ip$dst, pkt$udp$dport); - } - -event a_tcp_event(filter: string, pkt: pkt_hdr) - { - print "a_tcp_event()"; - print fmt(" %s:%s -> %s:%s", pkt$ip$src, pkt$tcp$sport, - pkt$ip$dst, pkt$tcp$dport); - } - -event sampled_1_in_1024_packet(filter: string, pkt: pkt_hdr) - { - print "sampled packet:"; - print "ip", pkt$ip; - - if ( pkt?$tcp ) - print "tcp", pkt$tcp; - if ( pkt?$udp ) - print "udp", pkt$udp; - if ( pkt?$icmp ) - print "icmp", pkt$icmp; - } - -redef secondary_filters += { - ["tcp[13] & 7 != 0"] = rst_syn_fin_flag, - ["udp"] = a_udp_event, - ["tcp"] = a_tcp_event, - ["ip[10:2] & 0xffc == 0x398"] = sampled_1_in_1024_packet, -}; diff --git a/policy.old/sensor-sshd.bro b/policy.old/sensor-sshd.bro deleted file mode 100644 index 060f0cef68..0000000000 --- a/policy.old/sensor-sshd.bro +++ /dev/null @@ -1,276 +0,0 @@ -# $Id: sensor-sshd.bro 4758 2007-08-10 06:49:23Z vern $ -# -# sshd sensor input, i.e., events received from instrumented SSH servers -# that communicate with Bro via the Broccoli library. - -# We leverage the login analyzer: -@load login -@load remote - -# To prevent requesting sshd events from any peering Bro that connects, -# here is a list of our sshds. List the IP addresses of the hosts your -# sshds are running on here: -# -redef Remote::destinations += { - ["sshd1"] = [$host = 127.0.0.1, $events = /sensor_sshd.*/, $connect=F, $ssl=F] -}; - -# A big log file for all kinds of notes: -# -global sshd_log: file = open_log_file("sshd"); - -# A record gathering everything we need to know per connection -# from an ssh client to the sshd: -# -type sshd_conn: record { - - # Connection record we create for connections to sshd - conn: connection; - - # A table indexed by channel numbers, yielding files. - # For each channel that contains a shell session this - # table contains a file to which the session content is - # logged. - sessions: table[count] of file; -}; - -# To avoid reporting IP/port quadruples repeatedly, connections in -# sshd are identified through a globally unique identifier for the -# sshd server (a string) plus an numerical identifier for each -# connection to that sshd. -# -global sshd_conns: table[string, count] of sshd_conn; - - -function sshd_conn_new(src_ip: addr, src_p: port, - dst_ip: addr, dst_p: port, - ts: time): sshd_conn - { - local id: conn_id; - id$orig_h = src_ip; - id$orig_p = src_p; - id$resp_h = dst_ip; - id$resp_p = dst_p; - - local orig: endpoint; - local resp: endpoint; - orig$size = resp$size = 0; - orig$state = resp$state = 0; - - local c: connection; - c$id = id; - c$orig = orig; - c$resp = resp; - c$start_time = ts; - c$duration = 0 sec; - - # We mark this connection so the login analyzer can - # understand that it is a login session. - add c$service["ssh-login"]; - - c$addl = ""; - c$hot = 0; - - local sc: sshd_conn; - sc$conn = c; - - return sc; - } - - -event sensor_sshd_listen(ts: time, sid: string, - server_ip: addr, server_p: port) - { - print sshd_log, fmt("[%D][%s:%s] sshd listening at %s:%d", - ts, get_event_peer()$host, sid, server_ip, server_p); - } - - -event sensor_sshd_restart(ts: time, sid: string) - { - print sshd_log, fmt("[%D][%s:%s] sshd %s restarted", - ts, get_event_peer()$host, sid, sid); - } - - -event sensor_sshd_exit(ts: time, sid: string) - { - print sshd_log, fmt("[%D][%s:%s] sshd %s exiting", - ts, get_event_peer()$host, sid, sid); - } - - -event sensor_sshd_conn_new(ts: time, sid: string, cid: count, - src_ip: addr, src_p: port, - dst_ip: addr, dst_p: port) - { - local sc = sshd_conn_new(src_ip, src_p, dst_ip, dst_p, ts); - sshd_conns[sid, cid] = sc; - print sshd_log, fmt("[%D][%s:%s:%d] conn attempt from %s:%d to %s:%d", - ts, get_event_peer()$host, sid, cid, src_ip, sc$conn$id$orig_p, - dst_ip, sc$conn$id$resp_p); - - Login::new_login_session(sc$conn, get_event_peer()$id, 0); - } - - -event sensor_sshd_conn_end(ts: time, sid: string, cid: count) - { - local pid = get_event_peer()$id; - local sc = sshd_conns[sid, cid]; - - print sshd_log, fmt("[%D][%s:%s:%d] conn terminated", - ts, get_event_peer()$host, sid, cid); - - Login::remove_login_session(sc$conn, pid); - delete sshd_conns[sid, cid]; - } - - -event sensor_sshd_auth_ok(ts: time, sid: string, cid: count, - user: string, uid: int, gid: int) - { - local pid = get_event_peer()$id; - local sc = sshd_conns[sid, cid]; - print sshd_log, fmt("[%D][%s:%s:%d] auth ok: %s (%d/%d)", - ts, get_event_peer()$host, sid, cid, user, uid, gid); - - Login::ext_set_login_state(sc$conn$id, pid, LOGIN_STATE_LOGGED_IN); - event authentication_accepted(user, sc$conn); - } - - -event sensor_sshd_auth_failed(ts: time, sid: string, cid: count, user: string) - { - local sc = sshd_conns[sid, cid]; - print sshd_log, fmt("[%D][%s:%s:%d] auth reject: user %s from %s:%d", - ts, get_event_peer()$host, sid, cid, user, - sc$conn$id$orig_h, sc$conn$id$orig_p); - - event authentication_rejected(user, sc$conn); - } - - -event sensor_sshd_auth_timeout(ts: time, sid: string, cid: count) - { - local sc = sshd_conns[sid, cid]; - print sshd_log, fmt("[%D][%s:%s:%d] auth timeout", ts, - sid, get_event_peer()$host, cid); - } - - -event sensor_sshd_auth_password_attempt(ts: time, sid: string, cid: count, - user: string, password: string, - valid: bool) - { - local sc = sshd_conns[sid, cid]; - - if ( ! valid ) - { - print sshd_log, fmt("[%D][%s:%s:%d] password bad: user %s, password '%s'", - ts, get_event_peer()$host, sid, cid, user, password); - event login_failure(sc$conn, user, "", password, ""); - } - else - { - print sshd_log, fmt("[%D][%s:%s:%d] password ok: user %s, password '%s'", - ts, get_event_peer()$host, sid, cid, user, password); - event login_success(sc$conn, user, "", password, ""); - } - } - - -event sensor_sshd_channel_new_session(ts: time, sid: string, cid: count, - chan_id: count, stype: string) - { - local sc = sshd_conns[sid, cid]; - - print sshd_log, fmt("[%D][%s:%s:%d:%d] new session: type %s", - ts, get_event_peer()$host, sid, cid, chan_id, stype); - - if ( stype == "shell" ) - { - local filename = - fmt("sshd-%s-%s-%d-%d.log", - get_event_peer()$host, sid, cid, chan_id); - sc$sessions[chan_id] = open(filename); - } - } - - -event sensor_sshd_channel_new_forward(ts: time, sid: string, - cid: count, chan_id: count, - src_ip: addr, src_p: port, - dst_ip: addr, dst_p: port, - s2h: bool) - { - if ( s2h ) - print sshd_log, fmt("[%D][%s:%s:%d:%d] new port channel: %s:%d -> c -> s -> %s:%d", - ts, get_event_peer()$host, sid, cid, - chan_id, src_ip, src_p, dst_ip, dst_p); - else - print sshd_log, fmt("[%D][%s:%s:%d:%d] new port channel: %s:%d <- c <- s <- %s:%d", - ts, get_event_peer()$host, sid, cid, - chan_id, dst_ip, dst_p, src_ip, src_p); - } - - -event sensor_sshd_data_rx(ts: time, sid: string, cid: count, chan_id: count, - line: string) - { - local sc = sshd_conns[sid, cid]; - - if ( chan_id in sc$sessions ) - { - print sc$sessions[chan_id], - fmt("[%D][%s:%s:%d:%d] rx: %s", ts, - get_event_peer()$host, sid, cid, chan_id, line); - event login_output_line(sc$conn, line); - } - } - - -event sensor_sshd_data_tx(ts: time, sid: string, cid: count, - chan_id: count, line: string) - { - local sc: sshd_conn = sshd_conns[sid, cid]; - - if ( chan_id in sc$sessions ) - { - print sc$sessions[chan_id], - fmt("[%D][%s:%s:%d:%d] tx: %s", ts, - get_event_peer()$host, sid, cid, chan_id, line); - event login_input_line(sc$conn, line); - } - } - - -event sensor_sshd_exec(ts: time, sid: string, cid: count, - chan_id: count, command: string) - { - print sshd_log, - fmt("[%D][%s:%s:%d:%d] exec: '%s'", ts, get_event_peer()$host, - sid, cid, chan_id, command); - } - - -event sensor_sshd_channel_exit(ts: time, sid: string, cid: count, - chan_id: count, status: int) - { - print sshd_log, - fmt("[%D][%s:%s:%d:%d] channel exit, code %d", ts, - get_event_peer()$host, sid, cid, chan_id, status); - } - - -event sensor_sshd_channel_cleanup(ts: time, sid: string, cid: count, - chan_id: count) - { - local sc: sshd_conn = sshd_conns[sid, cid]; - - print sshd_log, fmt("[%D][%s:%s:%d:%d] channel cleanup", - ts, get_event_peer()$host, sid, cid, chan_id); - - if ( chan_id in sc$sessions ) - delete sc$sessions[chan_id]; - } diff --git a/policy.old/service-probe.bro b/policy.old/service-probe.bro deleted file mode 100644 index 2cb02a3463..0000000000 --- a/policy.old/service-probe.bro +++ /dev/null @@ -1,97 +0,0 @@ -# $Id: service-probe.bro 5892 2008-07-01 02:37:03Z vern $ -# -# Detects hosts that continually bang away at a particular service -# of a local host, for example for brute-forcing passwords. -# -# Written by Jim Mellander, LBNL. -# Updated by Robin Sommer, ICSI. - -@load conn - -module ServiceProbe; - -export { - redef enum Notice += { ServiceProbe }; - - # No work gets done unless this is set. - global detect_probes = F &redef; - - # By default, look for service probes targeting MySQL and SSH. - global probe_ports = { 1433/tcp, 22/tcp, } &redef; - - # They have to connect to this many to be flagged. - global connect_threshold: table[port] of count &default=100 &redef; - - # How many bytes the connection must have to be considered potentially - # a probe. If missing, then there's no lower/upper bound. - # - # Note, the attack that motivated including these was SSH password - # guessing, where it was empirically determined that connections - # with > 1KB and < 2KB bytes transferred appear to be unsuccessful - # password guesses. - # - global min_bytes: table[port] of int &default=-1 &redef; - global max_bytes: table[port] of int &default=-1 &redef; - - # How many tries a given originator host has made against a given - # port on a given responder host. - global tries: table[addr, addr, port] of count - &default=0 &read_expire = 10 min; -} - -global reported_hosts: set[addr] &read_expire = 1 day; - -function service_probe_check(c: connection) - { - if ( ! detect_probes ) - return; - - local id = c$id; - local orig = id$orig_h; - local resp = id$resp_h; - local service = (port_names[20/tcp] in c$service) ? 20/tcp : id$resp_p; - - if ( orig in reported_hosts ) - # We've already blocked them. - return; - - if ( is_local_addr(orig) ) - # We only analyze probes of local servers. - return; - - if ( service !in probe_ports ) - # Not a port we care about. - return; - - local enough_bytes = T; - local bytes_xferred = c$orig$size + c$resp$size; - - if ( service in min_bytes && bytes_xferred < min_bytes[service] ) - enough_bytes = F; - - if ( service in max_bytes && bytes_xferred > max_bytes[service] ) - enough_bytes = F; - - if ( ! enough_bytes ) - return; - - local cnt = ++tries[orig, resp, service]; - if ( cnt == connect_threshold[service] ) - { - local svc = service_name(c); - - NOTICE([$note=ServiceProbe, $src=orig, - $msg=fmt("service probing %s -> %s %s", - orig, resp, svc)]); - - # Since we've dropped this host, we can now release the space. - delete tries[orig, resp, service]; - add reported_hosts[orig]; - } - } - - -event connection_state_remove(c: connection) - { - service_probe_check(c); - } diff --git a/policy.old/sigs/http-bots.sig b/policy.old/sigs/http-bots.sig deleted file mode 100644 index 26f61c7d45..0000000000 --- a/policy.old/sigs/http-bots.sig +++ /dev/null @@ -1,93 +0,0 @@ -# $Id:$ -# -# Some signatures for detecting certain HTTP-based botnet activity. - -signature nethell { - http-request /.*php\?userid=/ - http-request-body /userid=[0-9]{8}_/ - event "Nethell request" -} - -signature bzub { - http-request /.*ver=.*&lg=.*&phid=.*&r=/ - http-request-body /phid=[A-F0-9]{64}/ - event "bzub request" -} - -signature iebho { - http-request /.*ver=.*&lg=.*&phid=/ - http-request-body /phid=[A-F0-9]{32}/ - event "IEBHO request" -} - -signature bebloh { - payload /^GET/ - http-request /.*get\.php\?type=slg&id=/ - event "Bebloh request" -} - -signature black_enery { - payload /^POST/ - http-request-header /Cache-Control: no-cache/ - http-request-body /.*id=.*&build_id=.*id=x.+_[0-9A-F]{8}&build_id=.+/ - event "Black energy request" -} - -signature waledec { - payload /^POST/ - http-request /\/[A-Za-z0-9]+\.[pP][nN][gG]/ - event "Waledec request" -} - -signature silentbanker { - payload /^POST/ - http-request /.*\/getcfg\.php/ - event "SilentBanker request" -} - -signature icepack { - payload /^GET/ - http-request /.*\/exe\.php/ - event "Icepack request" -} - -signature torpig { - payload /^POST/ - http-request /.*\/gate\.php/ - event "Torpig request" -} - -signature peed { - http-request /.*\/controller\.php\?action=/ - http-request /.*&entity/ - http-request /.*&rnd=/ - event "Peed request" -} - -signature gozi { - payload /^GET/ - http-request /.*\?user_id=/ - http-request /.*&version_id=/ - http-request /.*&crc=/ - event "Gozi request" -} - -signature wsnpoem { - payload /^GET/ - http-request /.*\/((cfg|config)[0-9]*)\.bin$/ - event "wsnpoem request" -} - -signature pinch { - payload /^POST/ - http-request /.*\?act=online&.*s4=.*&s5=.*&nickname=/ - http-request-body /.*msg_out=/ - event "pinch request" -} - -signature grum { - payload /^GET/ - http-request /.*s_alive\.php/ - event "Grum request" -} - diff --git a/policy.old/sigs/p0fsyn.osf b/policy.old/sigs/p0fsyn.osf deleted file mode 100644 index 8767265819..0000000000 --- a/policy.old/sigs/p0fsyn.osf +++ /dev/null @@ -1,773 +0,0 @@ -# -# p0f - SYN fingerprints -# ---------------------- -# -# .-------------------------------------------------------------------------. -# | The purpose of this file is to cover signatures for incoming TCP/IP | -# | connections (SYN packets). This is the default mode of operation for | -# | p0f. This is also the biggest and most up-to-date set of signatures | -# | shipped with this project. The file also contains a detailed discussion | -# | of all metrics examined by p0f, and some practical notes on how to | -# | add new signatures. | -# `-------------------------------------------------------------------------' -# -# (C) Copyright 2000-2003 by Michal Zalewski -# -# Each line in this file specifies a single fingerprint. Please read the -# information below carefully before attempting to append any signatures -# reported by p0f as UNKNOWN to this file to avoid mistakes. Note that -# this file is compatible only with the default operation mode, and not -# with -R or -A options (SYN+ACK and RST+ modes). -# -# We use the following set metrics for fingerprinting: -# -# - Window size (WSS) - a highly OS dependent setting used for TCP/IP -# performance control (max. amount of data to be sent without ACK). -# Some systems use a fixed value for initial packets. On other -# systems, it is a multiple of MSS or MTU (MSS+40). In some rare -# cases, the value is just arbitrary. -# -# NEW SIGNATURE: if p0f reported a special value of 'Snn', the number -# appears to be a multiple of MSS (MSS*nn); a special value of 'Tnn' -# means it is a multiple of MTU ((MSS+40)*nn). Unless you notice the -# value of nn is not fixed (unlikely), just copy the Snn or Tnn token -# literally. If you know this device has a simple stack and a fixed -# MTU, you can however multiply S value by MSS, or T value by MSS+40, -# and put it instead of Snn or Tnn. One system may exhibit several T -# or S values. In some situations, this might be a source of some -# additional information about the setup if you have some time to dig -# thru the kernel sources; in some other cases, like Windows, there seem -# to be a multitude of variants and WSS selection algorithms, but it's -# rather difficult to find a pattern without having the source. -# -# If WSS looks like a regular fixed value (for example is a power of two), -# or if you can confirm the value is fixed by looking at several -# fingerprints, please quote it literaly. If there's no apparent pattern -# in WSS chosen, you should consider wildcarding this value - but this -# should be the last option. -# -# NOTE: Some NAT devices, such as Linux iptables with --set-mss, will -# modify MSS, but not WSS. As a result, MSS is changed to reflect -# the MTU of the NAT device, but WSS remains a multiple of the original -# MSS. Fortunately for us, the source device would almost always be -# hooked up to Ethernet. P0f handles it automatically for the original -# MSS of 1460, by adding "NAT!" tag to the result. -# -# In certain configurations, Linux erratically (?) uses MTU from another -# interface on the default gw interface. This only happens on systems with -# two network interfaces. Thus, some Linux systems that do not go thru NAT, -# but have multiple interfaces instead, will be also tagged this way. -# -# P0f recognizes and automatically wildcards WSS of 12345, as generated -# by sendack and sendsyn utilities shipped with the program, when -# reporting a new signature. See test/sendack.c and test/sendsyn.c for more -# information about this. -# -# - Overall packet size - a function of all IP and TCP options and bugs. -# While this is partly redundant in the real world, we record this value -# to capture rare cases when there are IP options (which we do not currently -# examine) or packet data past the headers. Both situations are rare. -# -# Packet size MAY be wildcarded, but the meaning of the wildcard is -# very special, and means the packet must be larger than PACKET_BIG -# (defined in config.h as 100). This is usually not necessary, except -# for some really broken implementations in RST+ mode. For more information, -# see p0fr.fp. P0f automatically wildcards big packets when reporting -# new signatures. -# -# NEW SIGNATURE: Copy this value literally. -# -# - Initial TTL - We check the actual TTL of a received packet. It can't -# be higher than the initial TTL, and also shouldn't be dramatically -# lower (maximum distance is defined in config.h as 40 hops). -# -# NEW SIGNATURE: *Never* copy TTL from a p0f-reported signature literally. -# You need to determine the initial TTL. The best way to do it is to -# check the documentation for a remote system, or check its settings. -# A fairly good method is to simply round the observed TTL up to -# 32, 64, 128, or 255, but it should be noted that some obscure devices -# might not use round TTLs (in particular, some shoddy appliances and -# IRIX and Tru64 are known to use "original" initial TTL settings). If not -# sure, use traceroute or mtr to see how far you are from the host. -# -# Note that -F option overrides this check if no signature can be found. -# -# - Don't fragment flag (DF) - some modern OSes set this to implement PMTU -# discovery. Others do not bother. -# -# NEW SIGNATURE: Copy this value literally. Note: this setting is -# sometimes cleared by firewalls and/or certain connectivity clients. -# Try to find out what's the actual state for a given OS if you see both, -# and add the right one. P0f will automatically detect a case when a -# firewall removed the DF flag and will append "(firewall!)" suffix to -# the signature, so if the DF version is the right one, don't add no-DF -# variant, unless it has a different meaning. -# -# - Maximum segment size (MSS) - this setting is usually link-dependent. P0f -# uses it to determine link type of the remote host. -# -# NEW SIGNATURE: Always wildcard this value, except for rare cases when -# you have an appliance with a fixed value, know the system supports only -# a very limited number of network interface types, or know the system -# is using a value it pulled out of nowhere. I use specific unique MSS -# to tell Google crawlbots from the rest of Linux population, for example. -# -# If a specific MSS/MTU is unique to a certain link type, be sure to -# add it to mtu.h instead of creating several variants of each signature. -# -# - Window scaling (WSCALE) - this feature is used to scale WSS. -# It extends the size of a TCP/IP window to 32 bits, of sorts. Some modern -# systems implement this feature. -# -# NEW SIGNATURE: Observe several signatures. Initial WSCALE is often set -# to zero or other low value. There's usually no need to wildcard this -# parameter. -# -# - Timestamp - some systems that implement timestamps set them to -# zero in the initial SYN. This case is detected and handled appropriately. -# -# NEW SIGNATURE: Copy T or T0 option literally. -# -# - Selective ACK permitted - a flag set by systems that implement -# selective ACK functionality, -# -# NEW SIGNATURE: copy S option literally. -# -# - NOP option - its presence, count and sequence is a useful OS-dependent -# characteristic, -# -# NEW SIGNATURE: copy N options literally. -# -# - Other and unrecognized options (TTCP-related and such) - implemented by -# some eccentric or very buggy TCP/IP stacks ;-), -# -# NEW SIGNATURE: copy ? options literally. -# -# - EOL option. Contrary to the popular belief, the presence of EOL -# option is actually quite rare, most systems just NOP-pad to the -# packet boundary. -# -# NEW SIGNATURE: copy E option literally. -# -# - The sequence of TCP all options mentioned above - this is very -# specific to the implementation, -# -# NEW SIGNATURE: Copy the sequence literally. -# -# - Quirks. Some buggy stacks set certain values that should be zeroed in a -# TCP packet to non-zero values. This has no effect as of today, but is -# a valuable source of information. Some systems actually seem to leak -# memory there. Other systems just exhibit harmful but very specific -# behavior. This section captures all unusual yes-no properties not -# related to the main and expected header layout. We detect the following: -# -# - Data past the headers. Neither SYN nor SYN+ACK packets are supposed -# to carry any payload. If they do, we should take notice. The actual -# payload is not examined, but will be displayed if use the -X option. -# Note that payload is not unusual in RST+ mode (see p0fr.fp), very -# rare otherwise. -# -# - Options past EOL. Some systems have some trailing data past EOL -# in the options section of TCP/IP headers. P0f does not examine this -# data as of today, simply detects its presence. If there is a -# confirmed sizable population of systems that have data past EOL, it -# might be a good idea to look at it. Until then, you have to recompile -# p0f with DEBUG_EXTRAS set or use -x to display this data, -# -# - Zero IP ID. This again is a (mostly) harmless setting to use a fixed -# IP ID for packets with DF set. Some systems reportedly use zero ID, -# most OSes do not. There is a very slight probability of a false -# positive when IP ID is "naturally" chosen to be zero on a system -# that otherwise does set proper values, but the probability is -# neglible (if it becomes a problem, recompile p0f with IGNORE_ZEROID -# set in the sources). -# -# - IP options specified. Usually, packets do not have any IP options -# set, but there can be some. Until there is a confirmed sizable -# population of systems that do have IP options in a packet, p0f -# does not examine those in detail, but it might change (use -# DEBUG_EXTRAS or -x to display IP options if any found), -# -# - URG pointer value. SYN packets do not have URG flag set, so the -# value in URG pointer in TCP header is ignored. Most systems set it -# to zero, but some OSes (some versions of Windows, for example) do -# not zero this field or even simply leak memory; the actual value is -# not examined, because most cases seem to be just random garbage -# (you can use DEBUG_EXTRAS or -x to report this information though); -# see doc/win-memleak.txt for more information, -# -# - "Unused" field value. This should be always zero, but some systems -# forget to clear it. This might result in some funny issues in the -# future. P0f checks for non-zero value (and will display it if -# DEBUG_EXTRAS is set, or you can use -x), -# -# - ACK number non-zero. ACK value in SYN packets with no ACK flag -# is disregarded and is usually set to zero (just like with URG -# pointer), but some systems forget to do it. The exact value is -# not examined (but will be displayed with DEBUG_EXTRAS, or you can -# use -x). Note that this is not an anomaly in SYN+ACK and RST+ modes, -# -# - Non-zero second timestamp. The initial SYN packet should have the -# second timestamp always zeroed. SYN+ACK and RST+ may "legally" have -# this quirk though, -# -# - Unusual flags. If, in addition to SYN (or SYN+ACK), there are some -# auxilinary flags that do not modify the very meaning of a packet, -# p0f records this (this can be URG, PUSH, or something else). -# -# Note: ECN flags (ECE and CWR) are ignored and denoted in a separate -# way. ECN is never by default, because some systems can't handle it, -# and it probably does not make much sense to include it in signatures -# right now. -# -# - TCP option segment parsing problems. If p0f fails to decode options -# because of a badly broken packet, it records this fact. -# -# There are several other quirks valid only in RST+ mode, see p0fr.fp for -# more information. Those quirks are unheard of in SYN and SYN+ACK -# modes. -# -# NEW SIGNATURE: Copy "quirks" section literally. -# -# We DO NOT use ToS for fingerprinting. While the original TCP/IP -# fingerprinting research believed this value would be useful for this -# purpose, it is not. The setting is way too often tweaked by network -# devices. -# -# To wildcard MSS, WSS or WSCALE, replace it with '*'. You can also use a -# modulo operator to match any values that divide by nnn - '%nnn' (and, -# as stated above, WSS also supports special values Snn and Tnn). -# -# Fingerprint entry format: -# -# wwww:ttt:D:ss:OOO...:QQ:OS:Details -# -# wwww - window size (can be * or %nnn or Sxx or Txx) -# "Snn" (multiple of MSS) and "Tnn" (multiple of MTU) are allowed. -# ttt - initial TTL -# D - don't fragment bit (0 - not set, 1 - set) -# ss - overall SYN packet size (* has a special meaning) -# OOO - option value and order specification (see below) -# QQ - quirks list (see below) -# OS - OS genre (Linux, Solaris, Windows) -# details - OS description (2.0.27 on x86, etc) -# -# If OS genre starts with '*', p0f will not show distance, link type -# and timestamp data. It is useful for userland TCP/IP stacks of -# network scanners and so on, where many settings are randomized or -# bogus. -# -# If OS genre starts with @, it denotes an approximate hit for a group -# of operating systems (signature reporting still enabled in this case). -# Use this feature at the end of this file to catch cases for which -# you don't have a precise match, but can tell it's Windows or FreeBSD -# or whatnot by looking at, say, flag layout alone. -# -# If OS genre starts with - (which can prefix @ or *), the entry is -# not considered to be a real operating system (but userland stack -# instead). It is important to mark all scanners and so on with -, -# so that they are not used for masquerade detection (also add this -# prefix for signatures of application-induced behavior, such as -# increased window size with Opera browser). -# -# Option block description is a list of comma or space separated -# options in the order they appear in the packet: -# -# N - NOP option -# E - EOL option -# Wnnn - window scaling option, value nnn (or * or %nnn) -# Mnnn - maximum segment size option, value nnn (or * or %nnn) -# S - selective ACK OK -# T - timestamp -# T0 - timestamp with zero value -# ?n - unrecognized option number n. -# -# P0f can sometimes report ?nn among the options. This means it couldn't -# recognize this option (option number nn). It's either a bug in p0f, or -# a faulty TCP/IP stack, or, if the number is listed here: -# -# http://www.iana.org/assignments/tcp-parameters -# -# ...the stack might be simply quite exotic. -# -# To denote no TCP options, use a single '.'. -# -# Quirks section is usually an empty list ('.') of oddities or bugs of this -# particular stack. List items are not separated in any way. Possible values: -# -# P - options past EOL, -# Z - zero IP ID, -# I - IP options specified, -# U - urg pointer non-zero, -# X - unused (x2) field non-zero, -# A - ACK number non-zero, -# T - non-zero second timestamp, -# F - unusual flags (PUSH, URG, etc), -# D - data payload, -# ! - broken options segment. -# -# WARNING WARNING WARNING -# ----------------------- -# -# Do not add a system X as OS Y just because NMAP says so. It is often -# the case that X is a NAT firewall. While nmap is talking to the -# device itself, p0f is fingerprinting the guy behind the firewall -# instead. -# -# When in doubt, use common sense, don't add something that looks like -# a completely different system as Linux or FreeBSD or LinkSys router. -# Check DNS name, establish a connection to the remote host and look -# at SYN+ACK (p0f -A -S should do) - does it look similar? -# -# Some users tweak their TCP/IP settings - enable or disable RFC1323, -# RFC1644 or RFC2018 support, disable PMTU discovery, change MTU, initial -# TTL and so on. Always compare a new rule to other fingerprints for -# this system, and verify the system isn't "customized". It is OK to -# add signature variants caused by commonly used software (PFs, security -# packages, etc), but it makes no sense to try to add every single -# possible /proc/sys/net/ipv4/* tweak on Linux or so. -# -# KEEP IN MIND: Some packet firewalls configured to normalize outgoing -# traffic (OpenBSD pf with "scrub" enabled, for example) will, well, -# normalize packets. Signatures will not correspond to the originating -# system (and probably not quite to the firewall either). -# -# NOTE: Try to keep this file in some reasonable order, from most to -# least likely systems. This will speed up operation. Also keep most -# generic and broad rules near ehe end. -# -# Still decided to add signature? Let us know - mail a copy of your discovery -# to lcamtuf@coredump.cx. You can help make p0f better, and I can help you -# make your signature more accurate. -# - -########################## -# Standard OS signatures # -########################## - -# ----------------- AIX --------------------- - -# AIX is first because its signatures are close to NetBSD, MacOS X and -# Linux 2.0, but it uses a fairly rare MSSes, at least sometimes... -# This is a shoddy hack, though. - -45046:64:0:44:M*:.:AIX:4.3 - -16384:64:0:44:M512:.:AIX:4.3.2 and earlier - -16384:64:0:60:M512,N,W%2,N,N,T:.:AIX:4.3.3-5.2 (1) -32768:64:0:60:M512,N,W%2,N,N,T:.:AIX:4.3.3-5.2 (2) -65535:64:0:60:M512,N,W%2,N,N,T:.:AIX:4.3.3-5.2 (3) - -65535:64:0:64:M*,N,W1,N,N,T,N,N,S:.:AIX:5.3 ML1 - -# ----------------- Linux ------------------- - -512:64:0:44:M*:.:Linux:2.0.3x (1) -16384:64:0:44:M*:.:Linux:2.0.3x (2) - -# Endian snafu! Nelson says "ha-ha": -2:64:0:44:M*:.:Linux:2.0.3x (MkLinux) on Mac (1) -64:64:0:44:M*:.:Linux:2.0.3x (MkLinux) on Mac (2) - -S4:64:1:60:M1360,S,T,N,W0:.:Linux:2.4 (Google crawlbot) - -# Linux 2.6.0-test has an identical footprint as 2.4. I -# wouldn't put it here until 2.6 gets a bit more, err, -# mature (and perhaps starts to differ ;-), but many -# people keep submitting 2.6.0-tests. - -S2:64:1:60:M*,S,T,N,W0:.:Linux:2.4 (big boy) -S3:64:1:60:M*,S,T,N,W0:.:Linux:2.4.18 and newer -S4:64:1:60:M*,S,T,N,W0:.:Linux:2.4/2.6 - -S3:64:1:60:M*,S,T,N,W1:.:Linux:2.5 (sometimes 2.4) (1) -S4:64:1:60:M*,S,T,N,W1:.:Linux:2.5/2.6 (sometimes 2.4) (2) -S3:64:1:60:M*,S,T,N,W2:.:Linux:2.5 (sometimes 2.4) (3) -S4:64:1:60:M*,S,T,N,W2:.:Linux:2.5 (sometimes 2.4) (4) - -S20:64:1:60:M*,S,T,N,W0:.:Linux:2.2.20 and newer -S22:64:1:60:M*,S,T,N,W0:.:Linux:2.2 (1) -S11:64:1:60:M*,S,T,N,W0:.:Linux:2.2 (2) - -# Popular cluster config scripts disable timestamps and -# selective ACK: - -S4:64:1:48:M1460,N,W0:.:Linux:2.4 in cluster - -# This needs to be investigated. On some systems, WSS -# is selected as a multiple of MTU instead of MSS. I got -# many submissions for this for many late versions of 2.4: - -T4:64:1:60:M1412,S,T,N,W0:.:Linux:2.4 (late, uncommon) - -# This happens only over loopback, but let's make folks happy: -32767:64:1:60:M16396,S,T,N,W0:.:Linux:2.4 (local) -S8:64:1:60:M3884,S,T,N,W0:.:Linux:2.2 (local) - -# Opera visitors: -16384:64:1:60:M*,S,T,N,W0:.:-Linux:2.2 (Opera?) -32767:64:1:60:M*,S,T,N,W0:.:-Linux:2.4 (Opera?) - -# Some fairly common mods: -S4:64:1:52:M*,N,N,S,N,W0:.:Linux:2.4 w/o timestamps -S22:64:1:52:M*,N,N,S,N,W0:.:Linux:2.2 w/o timestamps - -# ----------------- FreeBSD ----------------- - -16384:64:1:44:M*:.:FreeBSD:2.0-4.1 -16384:64:1:60:M*,N,W0,N,N,T:.:FreeBSD:4.4 (1) - -1024:64:1:60:M*,N,W0,N,N,T:.:FreeBSD:4.4 (2) - -57344:64:1:44:M*:.:FreeBSD:4.6-4.8 (no RFC1323) -57344:64:1:60:M*,N,W0,N,N,T:.:FreeBSD:4.6-4.8 - -32768:64:1:60:M*,N,W0,N,N,T:.:FreeBSD:4.8-5.1 (or MacOS X 10.2-10.3) -65535:64:1:60:M*,N,W0,N,N,T:.:FreeBSD:4.7-5.1 (or MacOS X 10.2-10.3) (1) -65535:64:1:60:M*,N,W1,N,N,T:.:FreeBSD:4.7-5.1 (or MacOS X 10.2-10.3) (2) - -65535:64:1:60:M*,N,W0,N,N,T:Z:FreeBSD:5.1-current (1) -65535:64:1:60:M*,N,W1,N,N,T:Z:FreeBSD:5.1-current (2) -65535:64:1:60:M*,N,W2,N,N,T:Z:FreeBSD:5.1-current (3) - -# 16384:64:1:60:M*,N,N,N,N,N,N,T:.:FreeBSD:4.4 (w/o timestamps) - -# ----------------- NetBSD ------------------ - -16384:64:0:60:M*,N,W0,N,N,T:.:NetBSD:1.3 -65535:64:0:60:M*,N,W0,N,N,T0:.:-NetBSD:1.6 (Opera) -16384:64:1:60:M*,N,W0,N,N,T0:.:NetBSD:1.6 -65535:64:1:60:M*,N,W1,N,N,T0:.:NetBSD:1.6W-current (DF) -65535:64:1:60:M*,N,W0,N,N,T0:.:NetBSD:1.6X (DF) - -# ----------------- OpenBSD ----------------- - -16384:64:1:64:M*,N,N,S,N,W0,N,N,T:.:OpenBSD:3.0-3.4 -57344:64:1:64:M*,N,N,S,N,W0,N,N,T:.:OpenBSD:3.3-3.4 -16384:64:0:64:M*,N,N,S,N,W0,N,N,T:.:OpenBSD:3.0-3.4 (scrub) -65535:64:1:64:M*,N,N,S,N,W0,N,N,T:.:-OpenBSD:3.0-3.4 (Opera) - -# ----------------- Solaris ----------------- - -S17:64:1:64:N,W3,N,N,T0,N,N,S,M*:.:Solaris:8 (RFC1323 on) -S17:64:1:48:N,N,S,M*:.:Solaris:8 (1) -S17:255:1:44:M*:.:Solaris:2.5 to 7 - -# Sometimes, just sometimes, Solaris feels like coming up with -# rather arbitrary MSS values ;-) - -S6:255:1:44:M*:.:Solaris:2.5-7 -S23:64:1:48:N,N,S,M*:.:Solaris:8 (2) -S34:64:1:48:M*,N,N,S:.:Solaris:9 -S44:255:1:44:M*:.:Solaris:7 - -4096:64:0:44:M1460:.:SunOS:4.1.x - -S34:64:1:52:M*,N,W0,N,N,S:.:Solaris:10 (beta) - -# ----------------- IRIX -------------------- - -49152:60:0:44:M*:.:IRIX:6.2-6.4 -61440:60:0:44:M*:.:IRIX:6.2-6.5 -49152:60:0:52:M*,N,W2,N,N,S:.:IRIX:6.5 (RFC1323) (1) -49152:60:0:52:M*,N,W3,N,N,S:.:IRIX:6.5 (RFC1323) (2) - -61440:60:0:48:M*,N,N,S:.:IRIX:6.5.12-6.5.21 (1) -49152:60:0:48:M*,N,N,S:.:IRIX:6.5.12-6.5.21 (2) - -# ----------------- Tru64 ------------------- -# Tru64 and OpenVMS share the same stack on occassions. -# Relax. - -32768:60:1:48:M*,N,W0:.:Tru64:4.0 (or OS/2 Warp 4) -32768:60:0:48:M*,N,W0:.:Tru64:5.0 (or OpenVMS 7.x on Compaq 5.0 stack) -8192:60:0:44:M1460:.:Tru64:5.1 (no RFC1323) (or QNX 6) -61440:60:0:48:M*,N,W0:.:Tru64:v5.1a JP4 (or OpenVMS 7.x on Compaq 5.x stack) - -# ----------------- OpenVMS ----------------- - -6144:64:1:60:M*,N,W0,N,N,T:.:OpenVMS:7.2 (Multinet 4.3-4.4 stack) - -# ----------------- MacOS ------------------- - -S2:255:1:48:M*,W0,E:.:MacOS:8.6 classic - -16616:255:1:48:M*,W0,E:.:MacOS:7.3-8.6 (OTTCP) -16616:255:1:48:M*,N,N,N,E:.:MacOS:8.1-8.6 (OTTCP) -32768:255:1:48:M*,W0,N:.:MacOS:9.0-9.2 - -32768:255:1:48:M1380,N,N,N,N:.:MacOS:9.1 (1) (OT 2.7.4) -65535:255:1:48:M*,N,N,N,N:.:MacOS:9.1 (2) (OT 2.7.4) - -# ----------------- Windows ----------------- - -# Windows TCP/IP stack is a mess. For most recent XP, 2000 and -# even 98, the pathlevel, not the actual OS version, is more -# relevant to the signature. They share the same code, so it would -# seem. Luckily for us, almost all Windows 9x boxes have an -# awkward MSS of 536, which I use to tell one from another -# in most difficult cases. - -8192:32:1:44:M*:.:Windows:3.11 (Tucows) -S44:64:1:64:M*,N,W0,N,N,T0,N,N,S:.:Windows:95 -8192:128:1:64:M*,N,W0,N,N,T0,N,N,S:.:Windows:95b - -# There were so many tweaking tools and so many stack versions for -# Windows 98 it is no longer possible to tell them from each other -# without some very serious research. Until then, there's an insane -# number of signatures, for your amusement: - -S44:32:1:48:M*,N,N,S:.:Windows:98 (low TTL) (1) -8192:32:1:48:M*,N,N,S:.:Windows:98 (low TTL) (2) -%8192:64:1:48:M536,N,N,S:.:Windows:98 (13) -%8192:128:1:48:M536,N,N,S:.:Windows:98 (15) -S4:64:1:48:M*,N,N,S:.:Windows:98 (1) -S6:64:1:48:M*,N,N,S:.:Windows:98 (2) -S12:64:1:48:M*,N,N,S:.:Windows:98 (3 -T30:64:1:64:M1460,N,W0,N,N,T0,N,N,S:.:Windows:98 (16) -32767:64:1:48:M*,N,N,S:.:Windows:98 (4) -37300:64:1:48:M*,N,N,S:.:Windows:98 (5) -46080:64:1:52:M*,N,W3,N,N,S:.:Windows:98 (RFC1323) -65535:64:1:44:M*:.:Windows:98 (no sack) -S16:128:1:48:M*,N,N,S:.:Windows:98 (6) -S16:128:1:64:M*,N,W0,N,N,T0,N,N,S:.:Windows:98 (7) -S26:128:1:48:M*,N,N,S:.:Windows:98 (8) -T30:128:1:48:M*,N,N,S:.:Windows:98 (9) -32767:128:1:52:M*,N,W0,N,N,S:.:Windows:98 (10) -60352:128:1:48:M*,N,N,S:.:Windows:98 (11) -60352:128:1:64:M*,N,W2,N,N,T0,N,N,S:.:Windows:98 (12) - -# What's with 1414 on NT? -T31:128:1:44:M1414:.:Windows:NT 4.0 SP6a (1) -64512:128:1:44:M1414:.:Windows:NT 4.0 SP6a (2) -8192:128:1:44:M*:.:Windows:NT 4.0 (older) - -# Windows XP and 2000. Most of the signatures that were -# either dubious or non-specific (no service pack data) -# were deleted and replaced with generics at the end. - -65535:128:1:48:M*,N,N,S:.:Windows:2000 SP4, XP SP1 -%8192:128:1:48:M*,N,N,S:.:Windows:2000 SP2+, XP SP1 (seldom 98 4.10.2222) -S20:128:1:48:M*,N,N,S:.:Windows:SP3 -S45:128:1:48:M*,N,N,S:.:Windows:2000 SP4, XP SP 1 (2) -40320:128:1:48:M*,N,N,S:.:Windows:2000 SP4 - -S6:128:1:48:M*,N,N,S:.:Windows:XP, 2000 SP2+ -S12:128:1:48:M*,N,N,S:.:Windows:XP SP1 (1) -S44:128:1:48:M*,N,N,S:.:Windows:XP Pro SP1, 2000 SP3 -64512:128:1:48:M*,N,N,S:.:Windows:XP SP1, 2000 SP3 (2) -32767:128:1:48:M*,N,N,S:.:Windows:XP SP1, 2000 SP4 (3) - -# Odds, ends, mods: - -S52:128:1:48:M1260,N,N,S:.:Windows:XP/2000 via Cisco -65520:128:1:48:M*,N,N,S:.:Windows:XP bare-bone -16384:128:1:52:M536,N,W0,N,N,S:.:Windows:2000 w/ZoneAlarm? -2048:255:0:40:.:.:Windows:.NET Enterprise Server - -# No need to be more specific, it passes: -*:128:1:48:M*,N,N,S:U:-Windows:XP/2000 while downloading (leak!) - -# ----------------- HP/UX ------------------- - -32768:64:1:44:M*:.:HP-UX:B.10.20 -32768:64:1:48:M*,W0,N:.:HP-UX:11.00-11.11 - -# Whoa. Hardcore WSS. -0:64:0:48:M*,W0,N:.:HP-UX:B.11.00 A (RFC1323) - -# ----------------- RiscOS ------------------ - -16384:64:1:68:M1460,N,W0,N,N,T,N,N,?12:.:RISC OS:3.70-4.36 (inet 5.04) -12288:32:0:44:M536:.:RISC OS:3.70 inet 4.10 -4096:64:1:56:M1460,N,N,T:T:.:RISC OS:3.70 freenet 2.00 - -# ----------------- BSD/OS ------------------ - -8192:64:1:60:M1460,N,W0,N,N,T:.:BSD/OS:3.1-4.3 (or MacOS X 10.2) - -# ---------------- NetwonOS ----------------- - -4096:64:0:44:M1420:.:NewtonOS:2.1 - -# ---------------- NeXTSTEP ----------------- - -S8:64:0:44:M512:.:NeXTSTEP:3.3 - -# ------------------ BeOS ------------------- - -1024:255:0:48:M*,N,W0:.:BeOS:5.0-5.1 -12288:255:0:44:M*:.:BeOS:5.0.x - -# ------------------ OS/400 ----------------- - -8192:64:1:60:M1440,N,W0,N,N,T:.:OS/400:V4R4/R5 -8192:64:0:44:M536:.:OS/400:V4R3/M0 -4096:64:1:60:M1440,N,W0,N,N,T:.:OS/400:V4R5 + CF67032 - -28672:64:0:44:M1460:A:OS/390:? - -# ------------------ ULTRIX ----------------- - -16384:64:0:40:.:.:ULTRIX:4.5 - -# ------------------- QNX ------------------- - -S16:64:0:44:M512:.:QNX:demodisk - -# ------------------ Novell ----------------- - -16384:128:1:44:M1460:.:Novell:NetWare 5.0 -6144:128:1:44:M1460:.:Novell:IntranetWare 4.11 -6144:128:1:44:M1368:.:Novell:BorderManager ? - -# According to rfp: -6144:128:1:52:M*,W0,N,S,N,N:.:Novell:Netware 6 SP3 - -# -------------- SCO UnixWare --------------- - -S3:64:1:60:M1460,N,W0,N,N,T:.:SCO:UnixWare 7.1 -S23:64:1:44:M1380:.:SCO:OpenServer 5.0 - -# ------------------- DOS ------------------- - -2048:255:0:44:M536:.:DOS:Arachne via WATTCP/1.05 - -# ------------------ OS/2 ------------------- - -S56:64:0:44:M512:.:OS/2:4 - -# ----------------- TOPS-20 ----------------- - -# Another hardcore MSS, one of the ACK leakers hunted down. -0:64:0:44:M1460:A:TOPS-20:version 7 - -# ------------------ AMIGA ------------------ - -S32:64:1:56:M*,N,N,S,N,N,?12:.:AMIGA:3.9 BB2 with Miami stack - -# ------------------ Minix ------------------ - -# Not quite sure. -# 8192:210:0:44:M1460:X:@Minix:? - -# ------------------ Plan9 ------------------ - -65535:255:0:48:M1460,W0,N:.:Plan9:edition 4 - -# ----------------- AMIGAOS ----------------- - -16384:64:1:48:M1560,N,N,S:.:AMIGAOS:3.9 BB2 MiamiDX - -########################################### -# Appliance / embedded / other signatures # -########################################### - -# ---------- Firewalls / routers ------------ - -S12:64:1:44:M1460:.:@Checkpoint:(unknown 1) -S12:64:1:48:N,N,S,M1460:.:@Checkpoint:(unknown 2) -4096:32:0:44:M1460:.:ExtremeWare:4.x -60352:64:0:52:M1460,N,W2,N,N,S:.:Clavister:firewall 7.x - -S32:64:0:68:M512,N,W0,N,N,T,N,N,?12:.:Nokia:IPSO w/Checkpoint NG FP3 -S16:64:0:68:M1024,N,W0,N,N,T,N,N,?12:.:Nokia:IPSO 3.7 build 026 - -S4:64:1:60:W0,N,S,T,M1460:.:FortiNet:FortiGate 50 - -8192:64:1:44:M1460:.:@Eagle:Secure Gateway - -# ------- Switches and other stuff ---------- - -4128:255:0:44:M*:Z:Cisco:7200, Catalyst 3500, et -S8:255:0:44:M*:.:Cisco:12008 -60352:128:1:64:M1460,N,W2,N,N,T,N,N,S:.:Alteon:ACEswitch -64512:128:1:44:M1370:.:Nortel:Contivity Client - -# ---------- Caches and whatnots ------------ - -8192:64:1:64:M1460,N,N,S,N,W0,N,N,T:.:NetCache:5.2 -16384:64:1:64:M1460,N,N,S,N,W0,N:.:NetCache:5.3 -65535:64:1:64:M1460,N,N,S,N,W*,N,N,T:.:NetCache:5.3-5.5 -20480:64:1:64:M1460,N,N,S,N,W0,N,N,T:.:NetCache:4.1 - -32850:64:1:64:N,W1,N,N,T,N,N,S,M*:.:NetCache:Data OnTap 5.x - -65535:64:0:60:M1460,N,W0,N,N,T:.:CacheFlow:CacheOS 4.1 -8192:64:0:60:M1380,N,N,N,N,N,N,T:.:CacheFlow:CacheOS 1.1 - -S4:64:0:48:M1460,N,N,S:.:Cisco:Content Engine - -27085:128:0:40:.:.:Dell:PowerApp cache (Linux-based) - -65535:255:1:48:N,W1,M1460:.:Inktomi:crawler -S1:255:1:60:M1460,S,T,N,W0:.:LookSmart:ZyBorg - -16384:255:0:40:.:.:Proxyblocker:(what's this?) - -# ----------- Embedded systems -------------- - -S9:255:0:44:M536:.:PalmOS:Tungsten C -S5:255:0:44:M536:.:PalmOS:3/4 -S4:255:0:44:M536:.:PalmOS:3.5 -2948:255:0:44:M536:.:PalmOS:3.5.3 (Handera) -S29:255:0:44:M536:.:PalmOS:5.0 - -S23:64:1:64:N,W1,N,N,T,N,N,S,M1460:.:SymbianOS:7 -8192:255:0:44:M1460:.:SymbianOS:6048 (on Nokia 7650?) -8192:255:0:44:M536:.:SymbianOS:(on Nokia 9210?) - -32768:32:1:44:M1460:.:Windows:CE 3 - -# Perhaps S4? -5840:64:1:60:M1452,S,T,N,W1:.:Zaurus:3.10 - -32768:128:1:64:M1460,N,W0,N,N,T0,N,N,S:.:PocketPC:2002 - -S1:255:0:44:M346:.:Contiki:1.1-rc0 - -4096:128:0:44:M1460:.:Sega:Dreamcast Dreamkey 3.0 -T5:64:0:44:M536:.:Sega:Dreamcast HKT-3020 (browser disc 51027) -S22:64:1:44:M1460:.:Sony:Playstation 2 (SOCOM?) - -S12:64:0:44:M1452:.:AXIS:Printer Server 5600 v5.64 - -#################### -# Fancy signatures # -#################### - -1024:64:0:40:.:.:-*NMAP:syn scan (1) -2048:64:0:40:.:.:-*NMAP:syn scan (2) -3072:64:0:40:.:.:-*NMAP:syn scan (3) -4096:64:0:40:.:.:-*NMAP:syn scan (4) - -1024:64:0:60:W10,N,M265,T,E:P:-*NMAP:OS detection probe (1) -2048:64:0:60:W10,N,M265,T,E:P:-*NMAP:OS detection probe (2) -3072:64:0:60:W10,N,M265,T,E:P:-*NMAP:OS detection probe (3) -4096:64:0:60:W10,N,M265,T,E:P:-*NMAP:OS detection probe (4) - -1024:64:0:60:W10,N,M265,T,E:PF:-*NMAP:OS detection probe w/flags (1) -2048:64:0:60:W10,N,M265,T,E:PF:-*NMAP:OS detection probe w/flags (2) -3072:64:0:60:W10,N,M265,T,E:PF:-*NMAP:OS detection probe w/flags (3) -4096:64:0:60:W10,N,M265,T,E:PF:-*NMAP:OS detection probe w/flags (4) - -12345:255:0:40:.:A:-p0f:sendsyn utility - -# UFO - see tmp/*: -56922:128:0:40:.:A:-@Mysterious:port scanner (?) -5792:64:1:60:M1460,S,T,N,W0:T:-@Mysterious:NAT device (2nd tstamp) -S12:128:1:48:M1460,E:P:@Mysterious:Chello proxy (?) -S23:64:1:64:N,W1,N,N,T,N,N,S,M1380:.:@Mysterious:GPRS gateway (?) - -##################################### -# Generic signatures - just in case # -##################################### - -*:128:1:52:M*,N,W0,N,N,S:.:@Windows:XP/2000 (RFC1323 no tstamp) -*:128:1:64:M*,N,W0,N,N,T0,N,N,S:.:@Windows:XP/2000 (RFC1323) -*:128:1:64:M*,N,W*,N,N,T0,N,N,S:.:@Windows:XP (RFC1323, w+) -*:128:1:48:M536,N,N,S:.:@Windows:98 -*:128:1:48:M*,N,N,S:.:@Windows:XP/2000 - - diff --git a/policy.old/smb.bro b/policy.old/smb.bro deleted file mode 100644 index 4d31393a13..0000000000 --- a/policy.old/smb.bro +++ /dev/null @@ -1,8 +0,0 @@ -# $Id:$ - -redef capture_filters += { ["smb"] = "port 445" }; - -global smb_ports = { 445/tcp } &redef; -redef dpd_config += { [ANALYZER_SMB] = [$ports = smb_ports] }; - -# No default implementation for events. diff --git a/policy.old/smtp-relay.bro b/policy.old/smtp-relay.bro deleted file mode 100644 index 0a7f84e7ad..0000000000 --- a/policy.old/smtp-relay.bro +++ /dev/null @@ -1,192 +0,0 @@ -# $Id: smtp-relay.bro 5911 2008-07-03 22:59:01Z vern $ -# -# Tracks email relaying. - -@load smtp -@load mime - -module SMTP; - -redef process_smtp_relay = T; - -export { - const relay_log = open_log_file("relay") &redef; -} - -global print_smtp_relay: function(t: table[count] of smtp_session_info, - idx: count): interval; - -global smtp_relay_table: table[count] of smtp_session_info - &write_expire = 5 min &expire_func = print_smtp_relay; - -global smtp_session_by_recipient: table[string] of smtp_session_info - &write_expire = 5 min; -global smtp_session_by_message_id: table[string] of smtp_session_info - &write_expire = 5 min; -global smtp_session_by_content_hash: table[string] of smtp_session_info - &write_expire = 5 min; - - -function add_to_smtp_relay_table(session: smtp_session_info) - { - if ( session$id !in smtp_relay_table ) - smtp_relay_table[session$id] = session; - } - -function check_relay_1(session: smtp_session_info, rcpt: string) - { - if ( session$external_orig && rcpt != local_mail_addr ) - { - smtp_message(session, - fmt("relaying(1) message (from %s, to %s) to address %s", - session$connection_id$orig_h, - session$connection_id$resp_h, - rcpt)); - - if ( session$relay_1_rcpt != "" ) - session$relay_1_rcpt = cat(session$relay_1_rcpt, ","); - - session$relay_1_rcpt = cat(session$relay_1_rcpt, rcpt); - add_to_smtp_relay_table(session); - } - } - -function check_relay_2(session: smtp_session_info, rcpt: string) - { - if ( rcpt in smtp_session_by_recipient ) - { - local prev_session = smtp_session_by_recipient[rcpt]; - - # Should only check the first condition only (external - # followed by internal) but let's include the second one - # for testing purposes for now. - if ( (prev_session$external_orig && ! session$external_orig) || - (! prev_session$external_orig && session$external_orig) ) - { - smtp_message(session, - fmt("relaying(2) message (seen during #%d) to address %s (%s -> %s, %s -> %s)", - prev_session$id, rcpt, - prev_session$connection_id$orig_h, - prev_session$connection_id$resp_h, - session$connection_id$orig_h, - session$connection_id$resp_h)); - - session$relay_2_from = prev_session$id; - ++prev_session$relay_2_to; - - add_to_smtp_relay_table(session); - add_to_smtp_relay_table(prev_session); - } - } - - smtp_session_by_recipient[rcpt] = session; - } - -function check_relay_3(session: MIME::mime_session_info, msg_id: string) - { - local smtp_session = session$smtp_session; - - if ( msg_id in smtp_session_by_message_id ) - { - local prev_smtp_session = smtp_session_by_message_id[msg_id]; - - smtp_message(smtp_session, - fmt("relaying(3) message (seen during #%d) with id %s (%s -> %s, %s -> %s)", - prev_smtp_session$id, msg_id, - prev_smtp_session$connection_id$orig_h, - prev_smtp_session$connection_id$resp_h, - smtp_session$connection_id$orig_h, - smtp_session$connection_id$resp_h)); - - smtp_session$relay_3_from = prev_smtp_session$id; - ++prev_smtp_session$relay_3_to; - - add_to_smtp_relay_table(smtp_session); - add_to_smtp_relay_table(prev_smtp_session); - } - else - smtp_session_by_message_id[msg_id] = smtp_session; - } - -function check_relay_4(session: MIME::mime_session_info, content_hash: string) - { - local smtp_session = session$smtp_session; - smtp_session$content_hash = content_hash; - - if ( content_hash in smtp_session_by_content_hash ) - { - local prev_smtp_session = smtp_session_by_content_hash[content_hash]; - smtp_message(smtp_session, - fmt("relaying(4) message (seen during #%d) with hash %s (%s -> %s, %s -> %s)", - prev_smtp_session$id, - string_to_ascii_hex(content_hash), - prev_smtp_session$connection_id$orig_h, - prev_smtp_session$connection_id$resp_h, - smtp_session$connection_id$orig_h, - smtp_session$connection_id$resp_h)); - - smtp_session$relay_4_from = prev_smtp_session$id; - ++prev_smtp_session$relay_4_to; - - add_to_smtp_relay_table(smtp_session); - add_to_smtp_relay_table(prev_smtp_session); - } - else - smtp_session_by_content_hash[content_hash] = smtp_session; - } - -# event mime_all_data(c: connection, length: count, data: string) -# { -# local session = get_mime_session(c, T); -# session$content_hash = md5_hash(data); -# if ( process_smtp_relay ) -# check_relay_4(session, session$content_hash); -# # mime_log_msg(session, "all data", fmt("%s", data)); -# } - -event mime_content_hash(c: connection, content_len: count, hash_value: string) - { - local session = MIME::get_session(c, T); - session$content_hash = hash_value; - if ( process_smtp_relay && content_len > 0 ) - check_relay_4(session, session$content_hash); - } - -function relay_flow(from: count, to: count): string - { - if ( from > 0 ) - return fmt("<#%d", from); - - if ( to > 0 ) - return fmt(">%d", to); - - return "-"; - } - -function print_smtp_relay(t: table[count] of smtp_session_info, - idx: count): interval - { - local session = t[idx]; - - print relay_log, fmt("#%d: %s", - session$id, - directed_id_string(session$connection_id, T)); - - print relay_log, fmt("#%d: RCPT: <%s>, Subject: %s", - session$id, - session$recipients, session$subject); - - print relay_log, fmt("#%d: detected: [%s %s %s %s] %s", - session$id, - session$relay_1_rcpt == "" ? "-" : "1", - relay_flow(session$relay_2_from, session$relay_2_to), - relay_flow(session$relay_3_from, session$relay_3_to), - relay_flow(session$relay_4_from, session$relay_4_to), - session$content_gap ? "(content gap)" : ""); - - print relay_log, fmt("#%d: relay 1: <%s>", - session$id, - session$relay_1_rcpt); - - return 0 sec; - } diff --git a/policy.old/smtp.bro b/policy.old/smtp.bro deleted file mode 100644 index cddb926456..0000000000 --- a/policy.old/smtp.bro +++ /dev/null @@ -1,557 +0,0 @@ -# $Id: smtp.bro 5230 2008-01-14 01:38:18Z vern $ - -@load conn - -module SMTP; - -export { - redef enum Notice += { HotEmailRecipient, }; - - const process_smtp_relay = F &redef; - - const smtp_log = open_log_file("smtp") &redef; - - # Used to detect relaying. - const local_mail_addr = /.*@.*lbl.gov/ &redef; - - const hot_recipients = /@/ &redef; - - const smtp_legal_cmds: set[string] = { - ">", "EHLO", "HELO", "MAIL", - "RCPT", "DATA", ".", "QUIT", - "RSET", "VRFY", "EXPN", "HELP", "NOOP", - "SEND", "SOML", "SAML", "TURN", - "STARTTLS", - "BDAT", - "ETRN", - "AUTH", - "***", - } &redef; - - const smtp_hot_cmds: table[string] of pattern = { - ["MAIL"] = /.*<.*@.*:.*>.*/, # relay path - ["RCPT"] = /.*<.*@.*:.*>.*/, # relay path - ["VRFY"] = /.*/, - ["EXPN"] = /.*/, - ["TURN"] = /.*/, - } &redef; - - const smtp_sensitive_cmds: set[string] = { - "VRFY", "EXPN", "TURN", - } &redef; - - const smtp_expected_reply: set[string, count] = { - [">", 220], - ["EHLO", 250], - ["HELO", 250], - ["MAIL", 250], - ["RCPT", 250], - ["RCPT", 554], # transaction failed - ["QUIT", 221], - ["DATA", 354], - [".", 250], # end of data - ["RSET", 250], - ["VRFY", 250], - ["EXPN", 250], - ["HELP", 250], - ["HELP", 502], # help command not supported - ["NOOP", 250], - ["AUTH", 334], # two round authentication - ["AUTH", 235], # one round authentication - ["AUTH_ANSWER", 334], # multiple step authentication - ["AUTH_ANSWER", 235], # authentication successful - ["STARTTLS", 220], # Willing to do TLS - ["TURN", 502], # TURN is expected to be rejected - }; - - type smtp_cmd_info: record { - cmd: string; - cmd_arg: string; - reply: count; - reply_arg: string; - cont_reply: bool; - log_reply: bool; - }; - - type smtp_cmd_info_list: table[count] of smtp_cmd_info; - - type smtp_session_info: record { - id: count; - connection_id: conn_id; - external_orig: bool; - in_data: bool; - num_cmds: count; - num_replies: count; - cmds: smtp_cmd_info_list; - in_header: bool; - keep_current_header: bool; # hack till MIME rewriter ready - recipients: string; - subject: string; - content_hash: string; - num_lines_in_body: count; - # lines in RFC 822 body before MIME decoding - num_bytes_in_body: count; - # bytes in entity bodies after MIME decoding - content_gap: bool; # whether content gap in conversation - - relay_1_rcpt: string; # external recipients - relay_2_from: count; # session id of same recipient - relay_2_to: count; - relay_3_from: count; # session id of same msg id - relay_3_to: count; - relay_4_from: count; # session id of same content hash - relay_4_to: count; - }; - - global smtp_sessions: table[conn_id] of smtp_session_info; - global smtp_session_id = 0; - - global new_smtp_session: function(c: connection); -} - -redef capture_filters += { ["smtp"] = "tcp port smtp or tcp port 587" }; - -# DPM configuration. -global smtp_ports = { 25/tcp, 587/tcp } &redef; -redef dpd_config += { [ANALYZER_SMTP] = [$ports = smtp_ports] }; - -function is_smtp_connection(c: connection): bool - { - return c$id$resp_p == smtp; - } - -event bro_init() - { - have_SMTP = T; - } - -global add_to_smtp_relay_table: function(session: smtp_session_info); - -function new_smtp_command(session: smtp_session_info, cmd: string, arg: string) - { - ++session$num_cmds; - - local cmd_info: smtp_cmd_info; - cmd_info$cmd = cmd; - cmd_info$cmd_arg = arg; - cmd_info$reply = 0; - cmd_info$reply_arg = ""; - cmd_info$cont_reply = F; - cmd_info$log_reply = F; - - session$cmds[session$num_cmds] = cmd_info; - } - -function new_smtp_session(c: connection) - { - local session = c$id; - local new_id = ++smtp_session_id; - - local info: smtp_session_info; - local cmds: smtp_cmd_info_list; - - info$id = new_id; - info$connection_id = session; - info$in_data = F; - info$num_cmds = 0; - info$num_replies = 0; - info$cmds = cmds; - info$in_header = F; - info$keep_current_header = T; - info$external_orig = !is_local_addr(session$orig_h); - - info$subject = ""; - info$recipients = ""; - info$content_hash = ""; - info$num_lines_in_body = info$num_bytes_in_body = 0; - info$content_gap = F; - - info$relay_1_rcpt = ""; - info$relay_2_from = info$relay_2_to = info$relay_3_from = - info$relay_3_to = info$relay_4_from = info$relay_4_to = 0; - - new_smtp_command(info, ">", ""); - - smtp_sessions[session] = info; - append_addl(c, fmt("#%s", prefixed_id(new_id))); - - print smtp_log, fmt("%.6f #%s %s start %s", c$start_time, - prefixed_id(new_id), id_string(session), info$external_orig ? - "external" : "internal" ); - } - -function smtp_message(session: smtp_session_info, msg: string) - { - print smtp_log, fmt("%.6f #%s %s", - network_time(), prefixed_id(session$id), msg); - } - -function smtp_log_msg(session: smtp_session_info, is_orig: bool, msg: string) - { - print smtp_log, fmt("%.6f #%s %s: %s", - network_time(), - prefixed_id(session$id), - directed_id_string(session$connection_id, is_orig), - msg); - } - -function smtp_log_reject_recipient(session: smtp_session_info, rcpt: string) - { - if ( rcpt == "" ) - rcpt = ""; - - smtp_message(session, fmt("Recipient addresses rejected: %s", rcpt)); - } - -function smtp_log_command(session: smtp_session_info, is_orig: bool, - msg: string, cmd_info: smtp_cmd_info) - { - smtp_log_msg(session, is_orig, fmt("%s: %s(%s)", - msg, cmd_info$cmd, cmd_info$cmd_arg)); - } - -function smtp_log_reply(session: smtp_session_info, is_orig: bool, - msg: string, cmd_info: smtp_cmd_info) - { - smtp_log_msg(session, is_orig, fmt("%s: %s(%s) --> %d(%s)", - msg, - cmd_info$cmd, cmd_info$cmd_arg, - cmd_info$reply, cmd_info$reply_arg)); - } - -event smtp_request(c: connection, is_orig: bool, command: string, arg: string) - { - local id = c$id; - - if ( id !in smtp_sessions ) - new_smtp_session(c); - - local session = smtp_sessions[id]; - new_smtp_command(session, command, arg); - local cmd_info = session$cmds[session$num_cmds]; - - # Store the command in session record. - local log_this_cmd = F; - - if ( command in smtp_hot_cmds && arg == smtp_hot_cmds[command] ) - { - log_this_cmd = T; - cmd_info$log_reply = T; - } - - if ( command in smtp_sensitive_cmds ) - { - log_this_cmd = T; - cmd_info$log_reply = T; - } - - if ( log_this_cmd ) - smtp_log_command(session, is_orig, "unusual command", cmd_info); - - if ( command == "DATA" ) - { - session$in_data = T; - session$in_header = T; - } - - else if ( command == "." ) - session$in_data = F; - } - -function check_cmd_info(session: smtp_session_info): bool - { - if ( session$num_replies == 0 ) - return T; - - if ( session$num_replies <= session$num_cmds && - session$num_replies in session$cmds ) - return T; - - smtp_message(session, fmt("error: invalid num_replies: %d (num_cmds = %d)", - session$num_replies, session$num_cmds)); - return F; - } - -function smtp_command_mail(session: smtp_session_info, cmd_info: smtp_cmd_info) - { - local tokens = split(cmd_info$cmd_arg, /(<|:|>)*/); - - local i = 0; - for ( i in tokens ) - smtp_log_msg(session, T, fmt("%d: \"%s\"", i, tokens[i])); - } - -function extract_recipient(session: smtp_session_info, rcpt_cmd_arg: string): string - { - local pair: string_array; - local s: string; - - s = rcpt_cmd_arg; - - pair = split1(s, /<( |\t)*/); - if ( length(pair) != 2 ) - { - smtp_message(session, fmt("error: '<' not found in argument to RCPT: %s", - rcpt_cmd_arg)); - return ""; - } - - s = pair[2]; - # smtp_message(session, fmt("%s<%s", pair[1], pair[2])); - - pair = split1(s, /( |\t)*>/); - if ( length(pair) != 2 ) - { - smtp_message(session, fmt("error: '>' not found in argument to RCPT: %s", - rcpt_cmd_arg)); - return ""; - } - - s = pair[1]; - # smtp_message(session, fmt("%s>%s", pair[1], pair[2])); - - pair = split1(s, /:/); - if ( length(pair) == 2 ) - { - smtp_message(session, fmt("RCPT address is source route path: %s", - rcpt_cmd_arg)); - s = pair[2]; - } - - # Actually the local part of an address might be case-sensitive, - # but in most cases it is not. - - s = to_lower(s); - - return s; - } - -global check_relay_1: function(session: smtp_session_info, rcpt: string); -global check_relay_2: function(session: smtp_session_info, rcpt: string); - -function smtp_command_rcpt(c: connection, session: smtp_session_info, - cmd_info: smtp_cmd_info) - { - local rcpt = extract_recipient(session, cmd_info$cmd_arg); - - if ( cmd_info$reply == 554 ) - smtp_log_reject_recipient(session, rcpt); - - else if ( rcpt != "" ) - { - smtp_message(session, fmt("recipient: <%s>", rcpt)); - - if ( session$recipients != "" ) - session$recipients = cat(session$recipients, ","); - - session$recipients = cat(session$recipients, rcpt); - - if ( process_smtp_relay ) - { - check_relay_1(session, rcpt); - check_relay_2(session, rcpt); - } - - if ( rcpt == hot_recipients ) - { - local src = session$connection_id$orig_h; - local dst = session$connection_id$resp_h; - - NOTICE([$note=HotEmailRecipient, $src=src, $conn=c, - $user=rcpt, - $msg=fmt("hot email recipient %s -> %s@%s", - src, rcpt, dst)]); - } - } - } - -event smtp_reply(c: connection, is_orig: bool, code: count, cmd: string, - msg: string, cont_resp: bool) - { - local id = c$id; - - if ( id !in smtp_sessions ) - new_smtp_session(c); - - local session = smtp_sessions[id]; - local new_reply = F; - - # Check entry before indexing. - if ( ! check_cmd_info(session) ) - return; - - if ( session$num_replies == 0 || - ! session$cmds[session$num_replies]$cont_reply ) - { - ++session$num_replies; - if ( session$num_replies !in session$cmds ) - { - smtp_message(session, fmt("error: unmatched reply: %d %s (%s)", - code, msg, cmd)); - return; - } - - new_reply = T; - } - - if ( ! check_cmd_info(session) ) - return; - - local cmd_info = session$cmds[session$num_replies]; - - if ( cmd_info$cmd != cmd ) - { - smtp_message(session, - fmt("error: command mismatch: %s(%d) %s(%d), %s (%d %s)", - cmd_info$cmd, session$num_replies, - session$cmds[session$num_cmds], session$num_cmds, - cmd, code, msg)); - return; - } - - cmd_info$reply = code; - if ( new_reply ) - cmd_info$reply_arg = msg; - else - cmd_info$reply_arg = cat(cmd_info$reply_arg, "\r\n", msg); - - cmd_info$cont_reply = cont_resp; - - local log_this_reply = cmd_info$log_reply; - - if ( [cmd, code] !in smtp_expected_reply ) - log_this_reply = T; - - if ( log_this_reply && ! cont_resp ) - smtp_log_reply(session, is_orig, "unusual command/reply", cmd_info); - - # else if ( cmd == "MAIL" && code == 250 ) - # smtp_command_mail(session, cmd_info); - - else if ( cmd == "RCPT" ) - { - if ( code == 250 || code == 554 ) - smtp_command_rcpt(c, session, cmd_info); - } - - else if ( cmd == "STARTTLS" && code == 220 ) - { # it'll now go encrypted - no more we can do. - skip_further_processing(c$id); - smtp_message(session, cmd); - } - } - -function reset_on_gap(session: smtp_session_info) - { - local i: count; - - clear_table(session$cmds); - - session$num_cmds = session$num_replies = 0; - session$in_data = F; - } - -event smtp_unexpected(c: connection, is_orig: bool, msg: string, detail: string) - { - local id = c$id; - - if ( id !in smtp_sessions ) - new_smtp_session(c); - - local session = smtp_sessions[id]; - - smtp_log_msg(session, is_orig, fmt("unexpected: %s: %s", msg, detail)); - } - -function clear_smtp_session(session: smtp_session_info) - { - clear_table(session$cmds); - } - -event content_gap(c: connection, is_orig: bool, seq: count, length: count) - { - if ( is_smtp_connection(c) ) - { - local id = c$id; - if ( id !in smtp_sessions ) - new_smtp_session(c); - local session = smtp_sessions[id]; - session$content_gap = T; - reset_on_gap(session); - } - } - -event connection_finished(c: connection) - { - local id = c$id; - if ( id in smtp_sessions ) - { - local session = smtp_sessions[id]; - smtp_message(session, "finish"); - clear_smtp_session(session); - delete smtp_sessions[id]; - } - } - -event connection_state_remove(c: connection) - { - local id = c$id; - if ( id in smtp_sessions ) - { - local session = smtp_sessions[id]; - smtp_message(session, "state remove"); - clear_smtp_session(session); - delete smtp_sessions[id]; - } - } - -global rewrite_smtp_header_line: - function(c: connection, is_orig: bool, - session: smtp_session_info, line: string); - -function smtp_header_line(c: connection, is_orig: bool, - session: smtp_session_info, line: string) - { - if ( rewriting_smtp_trace ) - rewrite_smtp_header_line(c, is_orig, session, line); - } - -function smtp_body_line(c: connection, is_orig: bool, - session: smtp_session_info, line: string) - { - ++session$num_lines_in_body; - session$num_bytes_in_body = - session$num_bytes_in_body + byte_len(line) + 2; # including CRLF - } - -event smtp_data(c: connection, is_orig: bool, data: string) - { - local id = c$id; - if ( id in smtp_sessions ) - { - local session = smtp_sessions[id]; - # smtp_log_msg(session, is_orig, fmt("data: %s", data)); - if ( session$in_header ) - { - if ( data == "" ) - { - session$in_header = F; - skip_smtp_data(c); - } - else - { - smtp_header_line(c, is_orig, session, data); - # smtp_log_msg(session, T, fmt("header: %s", data)); - } - } - else - { - # smtp_body_line(c, is_orig, session, data); - } - } - } - -event bro_done() - { - clear_table(smtp_sessions); - } diff --git a/policy.old/snort.bro b/policy.old/snort.bro deleted file mode 100644 index 16a173de13..0000000000 --- a/policy.old/snort.bro +++ /dev/null @@ -1,21 +0,0 @@ -# $Id: snort.bro 720 2004-11-12 16:45:48Z rwinslow $ -# -# Definitions needed for signatures converted by snort2bro. - -# Servers for some services. -const dns_servers: set[subnet] = { local_nets } &redef; -const http_servers: set[subnet] = { local_nets } &redef; -const smtp_servers: set[subnet] = { local_nets } &redef; -const telnet_servers: set[subnet] = { local_nets } &redef; -const sql_servers: set[subnet] = { local_nets } &redef; - -const aim_servers: set[subnet] = { - 64.12.24.0/24, 64.12.25.0/24, 64.12.26.14/24, 64.12.28.0/24, - 64.12.29.0/24, 64.12.161.0/24, 64.12.163.0/24, 205.188.5.0/24, - 205.188.9.0/24 -} &redef; - -# Ports for some services. -const http_ports = { 80/tcp, 8000/tcp, 8001/tcp, 8080/tcp }; -const oracle_ports = { 1521/tcp }; -const non_shellcode_ports = { 80/tcp }; diff --git a/policy.old/ssh-stepping.bro b/policy.old/ssh-stepping.bro deleted file mode 100644 index 5658a56043..0000000000 --- a/policy.old/ssh-stepping.bro +++ /dev/null @@ -1,45 +0,0 @@ -@load stepping - -redef capture_filters += { ["ssh-stepping"] = "tcp port 22" }; - -module SSH_Stepping; - -# Keeps track of how many connections each source is responsible for. -global ssh_src_cnt: table[addr] of count &default=0 &write_expire=15sec; - -export { - # Threshold above which we stop analyzing a source. - # Use 0 to never stop. - global src_fanout_no_stp_analysis_thresh = 100 &redef; -} - -event connection_established(c: connection) - { - if ( c$id$resp_p == ssh ) - { - # No point recording these, and they're potentially huge - # due to use of ssh for file transfers. - set_record_packets(c$id, F); - - # Keep track of sources that create lots of connections - # so we can skip analyzing them - they're very likely - # uninteresting for stepping stones, and can present - # a large state burden. - local src = c$id$orig_h; - if ( ++ssh_src_cnt[src] == src_fanout_no_stp_analysis_thresh ) - add stp_skip_src[src]; - - if ( ssh_src_cnt[src] == 1 ) - # First entry. It's possible this entry was set - # before and has now expired. If so, stop skipping it. - delete stp_skip_src[src]; - } - } - -event partial_connection(c: connection) - { - if ( c$id$orig_p == ssh || c$id$resp_p == ssh ) - # No point recording these, and they're potentially huge - # due to use of ssh for file transfers. - set_record_packets(c$id, F); - } diff --git a/policy.old/ssl-alerts.bro b/policy.old/ssl-alerts.bro deleted file mode 100644 index 1a0d65dead..0000000000 --- a/policy.old/ssl-alerts.bro +++ /dev/null @@ -1,120 +0,0 @@ -# $Id: ssl-alerts.bro 416 2004-09-17 03:52:28Z vern $ -# -# Interface for SSL/TLS support. - -# --- constant definitions of the SSL/TLS alert/error records --- - -# --- Error descriptions for SSLv2. -const SSLv2_PE_NO_CIPHER = 0x0001; -const SSLv2_PE_NO_CERTIFICATE = 0x0002; -const SSLv2_PE_BAD_CERTIFICATE = 0x0004; -const SSLv2_PE_UNSUPPORTED_CERTIFICATE_TYPE = 0x0006; - -# --- Alert descriptions in SSLv3.0 and SSLv3.1. -const SSLv3x_ALERT_DESCR_CLOSE_NOTIFY = 0; -const SSLv3x_ALERT_DESCR_UNEXPECTED_MESSSAGE = 10; -const SSLv3x_ALERT_DESCR_BAD_RECORD_MAC = 20; -const SSLv3x_ALERT_DESCR_DECOMPRESSION_FAILURE = 30; -const SSLv3x_ALERT_DESCR_HANDSHAKE_FAILURE = 40; -const SSLv3x_ALERT_DESCR_BAD_CERTIFICATE = 42; -const SSLv3x_ALERT_DESCR_UNSUPPORTED_CERTIFICATE = 43; -const SSLv3x_ALERT_DESCR_CERTIFICATE_REVOKED = 44; -const SSLv3x_ALERT_DESCR_CERTIFICATE_EXPIRED = 45; -const SSLv3x_ALERT_DESCR_CERTIFICATE_UNKNOWN = 46; - -# --- Alert descriptions only in SSLv3.0. -const SSLv30_ALERT_DESCR_NO_CERTIFICATE = 41; - -# --- Alert descriptions only in SSLv3.1. -const SSLv31_ALERT_DESCR_DESCRYPTION_FAILED = 21; -const SSLv31_ALERT_DESCR_RECORD_OVERFLOW = 22; -const SSLv31_ALERT_DESCR_ILLEGAL_PARAMETER = 47; -const SSLv31_ALERT_DESCR_UNKNOWN_CA = 48; -const SSLv31_ALERT_DESCR_ACCESS_DENIED = 49; -const SSLv31_ALERT_DESCR_DECODE_ERROR = 50; -const SSLv31_ALERT_DESCR_DECRYPT_ERROR = 51; -const SSLv31_ALERT_DESCR_EXPORT_RESTRICTION = 60; -const SSLv31_ALERT_DESCR_PROTOCOL_VERSION = 70; -const SSLv31_ALERT_DESCR_INSUFFICIENT_SECURITY = 71; -const SSLv31_ALERT_DESCR_INTERNAL_ERROR = 80; -const SSLv31_ALERT_DESCR_USER_CANCELED = 90; -const SSLv31_ALERT_DESCR_NO_RENEGOTIATION = 100; - -# --- This is a table of all known alert descriptions. -# --- It can be used for detecting unknown alerts and for -# --- converting the alert descriptions constants into a human readable format. - -const ssl_alert_desc: table[count] of string = { - # --- SSLv2 - [SSLv2_PE_NO_CIPHER] = "SSLv2_PE_NO_CIPHER", - [SSLv2_PE_NO_CERTIFICATE] = "SSLv2_PE_NO_CERTIFICATE", - [SSLv2_PE_BAD_CERTIFICATE] = "SSLv2_PE_BAD_CERTIFICATE", - [SSLv2_PE_UNSUPPORTED_CERTIFICATE_TYPE] = - "SSLv2_PE_UNSUPPORTED_CERTIFICATE_TYPE", - - # --- sslv30 - [SSLv30_ALERT_DESCR_NO_CERTIFICATE] = - "SSLv30_ALERT_DESCR_NO_CERTIFICATE", - - # --- sslv31 - [SSLv31_ALERT_DESCR_DESCRYPTION_FAILED] = - "SSLv31_ALERT_DESCR_DESCRYPTION_FAILED", - [SSLv31_ALERT_DESCR_RECORD_OVERFLOW] = - "SSLv31_ALERT_DESCR_RECORD_OVERFLOW", - [SSLv31_ALERT_DESCR_ILLEGAL_PARAMETER] = - "SSLv31_ALERT_DESCR_ILLEGAL_PARAMETER", - [SSLv31_ALERT_DESCR_UNKNOWN_CA] = "SSLv31_ALERT_DESCR_UNKNOWN_CA", - [SSLv31_ALERT_DESCR_ACCESS_DENIED] = "SSLv31_ALERT_DESCR_ACCESS_DENIED", - [SSLv31_ALERT_DESCR_DECODE_ERROR] = "SSLv31_ALERT_DESCR_DECODE_ERROR", - [SSLv31_ALERT_DESCR_DECRYPT_ERROR] = "SSLv31_ALERT_DESCR_DECRYPT_ERROR", - [SSLv31_ALERT_DESCR_EXPORT_RESTRICTION] = - "SSLv31_ALERT_DESCR_EXPORT_RESTRICTION", - [SSLv31_ALERT_DESCR_PROTOCOL_VERSION] = - "SSLv31_ALERT_DESCR_PROTOCOL_VERSION", - [SSLv31_ALERT_DESCR_INSUFFICIENT_SECURITY] = - "SSLv31_ALERT_DESCR_INSUFFICIENT_SECURITY", - [SSLv31_ALERT_DESCR_INTERNAL_ERROR] = - "SSLv31_ALERT_DESCR_INTERNAL_ERROR", - [SSLv31_ALERT_DESCR_USER_CANCELED] = - "SSLv31_ALERT_DESCR_USER_CANCELED", - [SSLv31_ALERT_DESCR_NO_RENEGOTIATION] = - "SSLv31_ALERT_DESCR_NO_RENEGOTIATION", - - # -- sslv3.0 and sslv3.1 - [SSLv3x_ALERT_DESCR_CLOSE_NOTIFY] = "SSLv3x_ALERT_DESCR_CLOSE_NOTIFY", - [SSLv3x_ALERT_DESCR_UNEXPECTED_MESSSAGE] = - "SSLv3x_ALERT_DESCR_UNEXPECTED_MESSSAGE", - [SSLv3x_ALERT_DESCR_BAD_RECORD_MAC] = - "SSLv3x_ALERT_DESCR_BAD_RECORD_MAC", - [SSLv3x_ALERT_DESCR_DECOMPRESSION_FAILURE] = - "SSLv3x_ALERT_DESCR_DECOMPRESSION_FAILURE", - [SSLv3x_ALERT_DESCR_HANDSHAKE_FAILURE] = - "SSLv3x_ALERT_DESCR_HANDSHAKE_FAILURE", - [SSLv3x_ALERT_DESCR_BAD_CERTIFICATE] = - "SSLv3x_ALERT_DESCR_BAD_CERTIFICATE", - [SSLv3x_ALERT_DESCR_UNSUPPORTED_CERTIFICATE] = - "SSLv3x_ALERT_DESCR_UNSUPPORTED_CERTIFICATE", - [SSLv3x_ALERT_DESCR_CERTIFICATE_REVOKED] = - "SSLv3x_ALERT_DESCR_CERTIFICATE_REVOKED", - [SSLv3x_ALERT_DESCR_CERTIFICATE_EXPIRED] = - "SSLv3x_ALERT_DESCR_CERTIFICATE_EXPIRED", - [SSLv3x_ALERT_DESCR_CERTIFICATE_UNKNOWN] = - "SSLv3x_ALERT_DESCR_CERTIFICATE_UNKNOWN", -}; - -# --- definitions for SSLv2 error levels: -# NOTE: We currently use the SSLv3x alert levels "WARNING" and "FATAL" -# for SSLv2, since SSLv2 does not support an explicit error level. - -# --- definitions for SSLv3.0/SSLv3.1 alert levels -const SSLv3x_ALERT_LEVEL_WARNING = 1; -const SSLv3x_ALERT_LEVEL_FATAL = 2; - -# --- This is a table of all known alert levels. -# --- It can be used for detecting unknown alert levels and for -# --- converting the alert level constants into a human readable format. - -const ssl_alert_level: table[count] of string = { - [SSLv3x_ALERT_LEVEL_WARNING] = "SSLv3x_ALERT_LEVEL_WARNING", - [SSLv3x_ALERT_LEVEL_FATAL] = "SSLv3x_ALERT_LEVEL_FATAL", -}; diff --git a/policy.old/ssl-worm.bro b/policy.old/ssl-worm.bro deleted file mode 100644 index 40c9ce432e..0000000000 --- a/policy.old/ssl-worm.bro +++ /dev/null @@ -1,58 +0,0 @@ -# $Id: ssl-worm.bro 340 2004-09-09 06:38:27Z vern $ - -@load signatures -@load software - -redef signature_files += "ssl-worm.sig"; - -redef capture_filters += { - ["ssl-worm"] = "udp port 2002 and src net 134.96" -}; - -function sslworm_is_server_vulnerable(state: signature_state): bool - { - local ip = state$conn$id$resp_h; - - if ( ip !in software_table ) - return F; - - local softset = software_table[ip]; - - if ( "Apache" !in softset ) - return F; - - if ( "OpenSSL" !in softset ) - return F; - - local safe_version: software_version = - [$major = +0, $minor = +9, $minor2 = +6, $addl = "e"]; - - if ( software_cmp_version(softset["OpenSSL"]$version, safe_version) >= 0 ) - return F; - - return T; - } - -function sslworm_has_server_been_probed(state: signature_state): bool - { - # FIXME: Bro segfaults without the tmp variable - local result = - has_signature_matched("sslworm-probe", - state$conn$id$orig_h, state$conn$id$resp_h); - - return result; - } - -function sslworm_has_server_been_exploited(state: signature_state): bool - { - # FIXME: I don't know which side starts the UDP conversation - local result = - has_signature_matched("sslworm-exploit", - state$conn$id$orig_h, state$conn$id$resp_h); - - if ( ! result ) - result = has_signature_matched("sslworm-exploit", - state$conn$id$resp_h, state$conn$id$orig_h); - - return result; - } diff --git a/policy.old/stats.bro b/policy.old/stats.bro deleted file mode 100644 index a4a4d7a8ac..0000000000 --- a/policy.old/stats.bro +++ /dev/null @@ -1,80 +0,0 @@ -# $Id: stats.bro 4011 2007-02-28 07:01:12Z vern $ - -# Track memory/lag statistics. Differs from profiling.bro in that this -# is lighter-weight (much less info, and less load to generate). - -@load notice - -redef enum Notice += { - ResourceStats, # generated when running live packet capture - OfflineResourceStats, # generated when reading trace files -}; - -# ResourceStats should by default be sent to the notice file -redef notice_action_filters += { - [[ResourceStats, OfflineResourceStats]] = file_notice -}; - -# Interval in which the results are sent as a notice. If this is less -# than heartbeat_interval, then it is set to heartbeat_interval, since -# some of the reported statistics are only gathered via the heartbeat. -global stats_report_interval = 10 sec &redef; - -event check_stats(last_time: time, last_ns: NetStats, last_res: bro_resources) - { - local now = current_time(); - local lag = now - network_time(); - local report_delta = now - last_time; - - local res = resource_usage(); - local ns = net_stats(); - - local total_CPU_time = res$user_time + res$system_time; - local last_CPU_time = last_res$user_time + last_res$system_time; - local CPU_util = ((total_CPU_time - last_CPU_time) / report_delta) * 100.0; - - local pkts_recvd = ns$pkts_recvd - last_ns$pkts_recvd; - local pkts_dropped = ns$pkts_dropped - last_ns$pkts_dropped; - local pkts_link = ns$pkts_link - last_ns$pkts_link; - - if ( bro_is_terminating() ) - # No more stats will be written or scheduled when Bro is - # shutting down. - return; - - local delta_pkts_processed = res$num_packets - last_res$num_packets; - local delta_events = res$num_events_dispatched - last_res$num_events_dispatched; - local delta_queued = res$num_events_queued - last_res$num_events_queued; - - local stat_msg = - fmt("mem=%dMB pkts_proc=%d events_proc=%d events_queued=%d", - res$mem / 1000000, delta_pkts_processed, - delta_events, delta_queued); - - if ( reading_live_traffic() ) - { - stat_msg = fmt("%s et=%.2f lag=%fsec util=%.01f%% pkts_rcv=%d pkts_drp=%d pkts_link=%d", - stat_msg, report_delta, lag, CPU_util, - pkts_recvd, pkts_dropped, pkts_link); - NOTICE([$note=ResourceStats, $msg=stat_msg]); - } - - else if ( reading_traces() ) - NOTICE([$note=OfflineResourceStats, $msg=stat_msg]); - - else - { - # Remote communication only. - stat_msg = fmt("mem=%dMB events_proc=%d events_queued=%d lag=%fsec util=%.01f%%", - res$mem / 1000000, delta_events, delta_queued, - lag, CPU_util); - NOTICE([$note=ResourceStats, $msg=stat_msg]); - } - - schedule stats_report_interval { check_stats(now, ns, res) }; - } - -event bro_init() - { - schedule stats_report_interval { check_stats(current_time(), net_stats(), resource_usage()) }; - } diff --git a/policy.old/stepping.bro b/policy.old/stepping.bro deleted file mode 100644 index 9b7fe23031..0000000000 --- a/policy.old/stepping.bro +++ /dev/null @@ -1,484 +0,0 @@ -# $Id: stepping.bro 6481 2008-12-15 00:47:57Z vern $ - -@load notice -@load port-name -@load demux -@load login - -module Stepping; - -export { - redef enum Notice += { - # A stepping stone was seen in which the first part of - # the chain is a clear-text connection but the second part - # is encrypted. This often means that a password or - # passphrase has been exposed in the clear, and may also - # mean that the user has an incomplete notion that their - # connection is protected from eavesdropping. - ClearToEncrypted_SS, - }; -} - -global step_log = open_log_file("step") &redef; - -# The following must be defined for the event engine to generate -# stepping stone events. -redef stp_delta = 0.08 sec; -redef stp_idle_min = 0.5 sec; - -global stepping_stone: event(c1: connection, c2: connection, method: string); - -#### First, tag-based schemes - $DISPLAY, Last Login #### - -# If was a login to propagating a $DISPLAY of , -# then we make an entry of [, ] = . -global display_pairs: table[addr, string] of connection; - -# Maps login tags like "Last login ..." to connections. -global tag_to_conn_map: table[string] of connection; - -type tag_info: record { - display: string; # $DISPLAY, if any - tag: string; # login tag, e.g. "Last login ..." -}; - -global conn_tag_info: table[conn_id] of tag_info; - -const STONE_DISPLAY = 1; -const STONE_LOGIN_BANNER = 2; -const STONE_TIMING = 4; -### fixme -global detected_stones: table[addr, port, addr, port, addr, port, addr, port] - of count &default = 0; -global did_stone_summary: table[addr, port, addr, port, addr, port, addr, port] - of count &default = 0; - -function new_tag_info(c: connection) - { - local ti: tag_info; - ti$tag = ti$display = ""; - conn_tag_info[c$id] = ti; - } - -event login_display(c: connection, display: string) - { - local id = c$id; - if ( id !in conn_tag_info ) - new_tag_info(c); - - conn_tag_info[id]$display = display; - display_pairs[id$resp_h, display] = c; - - if ( [id$orig_h, display] in display_pairs ) - event Stepping::stepping_stone(display_pairs[id$orig_h, display], c, "display"); - } - -event login_output_line(c: connection, line: string) - { - if ( /^([Ll]ast +(successful)? *login)/ | /^Last interactive login/ - !in line || - # Some finger output includes "Last login ..." but luckily - # appears to be terminated by ctrl-A. - /\001/ in line ) - return; - - if ( c$id !in conn_tag_info ) - new_tag_info(c); - - local ti = conn_tag_info[c$id]; - local tag = line; - - if ( ti$tag == "" ) - ti$tag = tag; - - if ( tag in tag_to_conn_map ) - { - local c2 = tag_to_conn_map[tag]; - - ### Would really like this taken care of by having - # tag_to_conn_map[tag] deleted when c2 goes away. - if ( active_connection(c2$id) ) - event Stepping::stepping_stone(c2, c, "login-tag"); - } - else - tag_to_conn_map[tag] = c; - } - -event connection_finished(c: connection) - { - ### would really like some automatic destructors invoked - ### whenever a connection goes away - local id = c$id; - if ( id in conn_tag_info ) - { - local ti = conn_tag_info[id]; - delete display_pairs[id$resp_h, ti$display]; - delete tag_to_conn_map[ti$tag]; - delete conn_tag_info[id]; - } - } - - -#### Now, timing-based correlation #### - -const stp_ratio_thresh = 0.3 &redef; # prop. of idle times that must coincide - -# Time scale to which following thresholds apply. -const stp_scale = 100.0 &redef; - -const stp_common_host_thresh = 2 &redef; # must be <= stp_random_pair_thresh -const stp_random_pair_thresh = 4 &redef; - -const stp_demux_disabled = T &redef; - -# Indexed by the center host (or destination of the first connection, -# for ABCD stepping stones) and the $addl information associated with -# the connection (i.e., often username). If present in the set, then -# we shouldn't bother generating a report for a clear->ssh stepping stone. -const skip_clear_ssh_reports: set[addr, string] &redef; - -global num_stp_pairs = 0; - -type endp_info: record { - conn: connection; - id: conn_id; - resume_time: time; # time when resuming from most recent idle period - old_resume_time: time; # time when resuming from penultimate idle period - idle_cnt: count; # number of idle periods for this endpoint (flow) -}; - -type pair_info: record { - is_stp: bool; # true if flow pair considered a stepping stone pair - hit: count; # number of coincidences - hit_two_in_row: count; # number of coincidences two-in-row -}; - -# For connection k: -# stp_endps[2k] is the orig endpoint -# stp_endps[2k+1] is the resp endpoint -global stp_endps: table[int] of endp_info; - -# Some endpoint pairs are weird, e.g., when two endp's share a common port. -# Such weird endp pairs may be correlated, but are unlikely to be stepping -# stone pairs. -global stp_weird_pairs: set[int, int]; - -# Normal (i.e., not weird) endp pairs. -global stp_normal_pairs: table[int, int] of pair_info; - -function is_orig(e: int): bool - { - return (e % 2) == 0; - } - -function peer(e: int): int - { - return (e % 2) == 0 ? (e + 1): (e - 1); - } - -function orig_host(e: int): addr - { - return stp_endps[e]$id$orig_h; - } - -function resp_host(e: int): addr - { - return stp_endps[e]$id$resp_h; - } - -function orig_port(e: int): port - { - return stp_endps[e]$id$orig_p; - } - -function resp_port(e: int): port - { - return stp_endps[e]$id$resp_p; - } - -function build_conn(e: int): connection - { # return the id of the orig, not the resp - return stp_endps[e]$conn; - } - -function stp_id_string(id: conn_id): string - { - return fmt("%s.%d > %s.%d", id$orig_h, id$orig_p, id$resp_h, id$resp_p); - } - -function stp_create_weird_pair(e1: int, e2: int) - { - add stp_weird_pairs[e1, e2]; - } - -function stp_create_normal_pair(e1: int, e2: int) - { - local pair: pair_info; - - pair$is_stp = F; - pair$hit = pair$hit_two_in_row = 0; - - stp_normal_pairs[e1, e2] = pair; - } - -function stp_correlate_weird_pair(e1: int, e2: int) - { # do nothing right now - } - -global stp_check_normal_pair: function(e1: int, e2: int): bool; - -function stp_correlate_normal_pair(e1: int, e2: int) - { - if ( stp_normal_pairs[e1, e2]$is_stp ) - return; # already classified as stepping stone pair - - ++stp_normal_pairs[e1, e2]$hit; - - if ( stp_endps[e1]$old_resume_time != 0.0 && - stp_endps[e2]$old_resume_time != 0.0 ) - { - local dt = stp_endps[e2]$old_resume_time - - stp_endps[e1]$old_resume_time; - if ( dt >= 0.0 sec && dt <= stp_delta ) - ++stp_normal_pairs[e1, e2]$hit_two_in_row; - } - stp_check_normal_pair(e1, e2); - } - -function stp_check_weird_pair(e1: int, e2: int) - { # do nothing right now - } - -function stp_check_normal_pair(e1: int, e2: int): bool - { - if ( stp_normal_pairs[e1, e2]$is_stp ) - return T; # already classified as stepping stone pair - - local p1 = peer(e1); - local p2 = peer(e2); - local reverse_exists = [p2, p1] in stp_normal_pairs; - - if ( reverse_exists && stp_normal_pairs[p2, p1]$is_stp ) - { # already classified as stepping stone pair - stp_normal_pairs[e1, e2]$is_stp = T; - return T; - } - - local hit_two_in_row = stp_normal_pairs[e1, e2]$hit_two_in_row; - if ( reverse_exists ) - hit_two_in_row = hit_two_in_row + - stp_normal_pairs[p2, p1]$hit_two_in_row; - - # Criteria 1: - # if ( e1 and e2 share a common host ) - # hit_two_in_row >= stp_common_host_thresh - # else - # hit_two_in_row >= stp_random_pair_thresh - - local factor = max_double(1.0, - min_count(stp_endps[e1]$idle_cnt, - stp_endps[e2]$idle_cnt) / stp_scale); - - if ( hit_two_in_row < factor * stp_common_host_thresh ) - return F; - - if ( hit_two_in_row < factor * stp_random_pair_thresh && - orig_host(e1) != orig_host(e2) && orig_host(e1) != resp_host(e2) && - resp_host(e1) != orig_host(e2) && resp_host(e1) != resp_host(e2) ) - return F; - - # Criteria 2: - # hit_ratio >= stp_ratio_thresh - - local hit_ratio: double; - if ( reverse_exists && - stp_normal_pairs[p2, p1]$hit > stp_normal_pairs[e1, e2]$hit ) - hit_ratio = (1.0 * stp_normal_pairs[p2, p1]$hit) / - min_count(stp_endps[p1]$idle_cnt, - stp_endps[p2]$idle_cnt); - else - hit_ratio = (1.0 * stp_normal_pairs[e1, e2]$hit) / - min_count(stp_endps[e1]$idle_cnt, - stp_endps[e2]$idle_cnt); - - if ( hit_ratio < stp_ratio_thresh ) - return F; - - stp_normal_pairs[e1, e2]$is_stp = T; - event Stepping::stepping_stone(build_conn(e1), build_conn(e2), "timing"); - - return T; - } - -function reverse_id(id: conn_id): conn_id - { - local rid: conn_id; - - rid$orig_h = id$resp_h; - rid$orig_p = id$resp_p; - rid$resp_h = id$orig_h; - rid$resp_p = id$orig_p; - - return rid; - } - -event stp_create_endp(c: connection, e: int, is_orig: bool) - { - local end_i: endp_info; - - end_i$conn = c; - end_i$id = is_orig ? c$id : reverse_id(c$id); - end_i$resume_time = end_i$old_resume_time = 0.0; - end_i$idle_cnt = 0; - - stp_endps[e] = end_i; - } - -event stp_resume_endp(e: int) - { - stp_endps[e]$old_resume_time = stp_endps[e]$resume_time; - stp_endps[e]$resume_time = network_time(); - ++stp_endps[e]$idle_cnt; - } - -event stp_correlate_pair(e1: int, e2: int) - { - local normal = T; - - if ( [e1, e2] in stp_normal_pairs ) - ; - - else if ( [e1, e2] in stp_weird_pairs ) - normal = F; - - else - { - # An endpoint pair is considered weird, iff: - # the two flows both originated at same host, or - # both terminated at same host, or - # at least one flow is within a single host, or - # two flows share an endpoint (host, port) - - if ( orig_host(e1) == orig_host(e2) || resp_host(e1) == resp_host(e2) || - orig_host(e1) == resp_host(e1) || orig_host(e2) == resp_host(e2) || - (orig_host(e1) == resp_host(e2) && orig_port(e1) == resp_port(e2)) || - (resp_host(e1) == orig_host(e2) && resp_port(e1) == orig_port(e2)) ) - { - stp_create_weird_pair(e1, e2); - normal = F; - } - else - stp_create_normal_pair(e1, e2); - } - - if ( normal ) - stp_correlate_normal_pair(e1, e2); - else - stp_correlate_weird_pair(e1, e2); - } - -event stp_remove_pair(e1: int, e2: int) - { - delete stp_normal_pairs[e1, e2]; - delete stp_weird_pairs[e1, e2]; - } - -event stp_remove_endp(e: int) - { - delete stp_endps[e]; - } - - -function report_stone(id1: conn_id, addl1: string, id2: conn_id, addl2: string) -: string - { - if ( id1$resp_h == id2$orig_h ) - # A single-intermediary stepping stone. - return fmt("%s -> %s %s-> %s %s", - id1$orig_h, - endpoint_id(id1$resp_h, id1$resp_p), addl1, - endpoint_id(id2$resp_h, id2$resp_p), addl2); - else - # A multi-intermediary stepping stone. - return fmt("%s -> %s %s... %s -> %s %s", - id1$orig_h, - endpoint_id(id1$resp_h, id1$resp_p), addl1, - id2$orig_h, - endpoint_id(id2$resp_h, id2$resp_p), addl2); - } - -event stone_summary(id1: conn_id, id2: conn_id) - { - if ( ++did_stone_summary[id1$orig_h, id1$orig_p, id1$resp_h, id1$resp_p, id2$orig_h, id2$orig_p, id2$resp_h, id2$resp_p] > 1 ) - return; - - local detection_type = detected_stones[id1$orig_h, id1$orig_p, id1$resp_h, id1$resp_p, id2$orig_h, id2$orig_p, id2$resp_h, id2$resp_p]; - - local report: string; - - if ( detection_type == STONE_DISPLAY ) - report = "only-display"; - else if ( detection_type == STONE_LOGIN_BANNER ) - report = "only-banner"; - else if ( detection_type == STONE_TIMING ) - report = "only-timing"; - else if ( detection_type == STONE_LOGIN_BANNER + STONE_TIMING ) - report = "stone-both"; - else - report = fmt("stone-other-%d", detection_type); - - print step_log, fmt("%s detected %s %s %d %s %d %s %d %s %d", - network_time(), report, id1$orig_h, id1$orig_p, id1$resp_h, - id1$resp_p, id2$orig_h, id2$orig_p, id2$resp_h, id2$resp_p); - } - -event stepping_stone(c1: connection, c2: connection, method: string) - { - # Put into canonical form: make #1 be the earlier of the two - # connections. - local id1 = c1$start_time < c2$start_time ? c1$id : c2$id; - local id2 = c1$start_time < c2$start_time ? c2$id : c1$id; - - local addl1 = c1$start_time < c2$start_time ? c1$addl : c2$addl; - local addl2 = c1$start_time < c2$start_time ? c2$addl : c1$addl; - - if ( id1$orig_h == id2$orig_h || id1$resp_h == id2$resp_h ) - # of the form A->B, A->C ; or B->A, C->A ; uninteresting. - return; - - local tag = fmt("stp.%d", ++num_stp_pairs); - local prelude = fmt("%.6f step %s (%s)", network_time(), num_stp_pairs, method); - - local stone_type = (method == "display" ? STONE_DISPLAY : - (method == "login-tag" ? STONE_LOGIN_BANNER : - STONE_TIMING)); - - local current_stones = detected_stones[id1$orig_h, id1$orig_p, id1$resp_h, id1$resp_p, id2$orig_h, id2$orig_p, id2$resp_h, id2$resp_p]; - - if ( (current_stones / stone_type) % 2 == 0 ) - detected_stones[id1$orig_h, id1$orig_p, id1$resp_h, id1$resp_p, id2$orig_h, id2$orig_p, id2$resp_h, id2$resp_p] = current_stones + stone_type; - - schedule 1 day { stone_summary(id1, id2) }; - - print step_log, fmt("%s: %s", prelude, report_stone(id1, addl1, id2, addl2)); - - local is_ssh1 = id1$orig_p == ssh || id1$resp_p == ssh; - local is_ssh2 = id2$orig_p == ssh || id2$resp_p == ssh; - - if ( ! is_ssh1 && is_ssh2 ) - { # Inbound clear-text, outbound ssh. - if ( [id1$resp_h, addl1] !in skip_clear_ssh_reports ) - NOTICE([$note=ClearToEncrypted_SS, - # The following isn't sufficient for - # A->(B->C)->D stepping stones, only A->B->C. - $src=c1$id$orig_h, $conn=c2, - $user=addl1, $sub=addl2, - $msg=fmt("clear -> ssh: %s", report_stone(id1, addl1, id2, addl2))]); - } - - if ( ! stp_demux_disabled ) - { - demux_conn(id1, tag, "keys", "server"); - demux_conn(id2, tag, "keys", "server"); - } - } diff --git a/policy.old/summaries/app-summary.bro b/policy.old/summaries/app-summary.bro deleted file mode 100644 index 5be50f661a..0000000000 --- a/policy.old/summaries/app-summary.bro +++ /dev/null @@ -1,57 +0,0 @@ -@load conn-util -@load conn-app-reduced - -global conn_size_table: table[conn_id] of count; -global conn_size_log = open_log_file("conn-size") &redef; - -function add_to_conn_size(id: conn_id, size: count) - { - if ( id !in conn_size_table ) - conn_size_table[id] = 0; - local previous_size = conn_size_table[id]; - conn_size_table[id] = conn_size_table[id] + size; - if ( conn_size_table[id] < previous_size ) - { - print conn_size_log, fmt("ERROR: %.6f size wrapping around: %s, prev_size = %d, add = %d", - network_time(), conn_id_string(id), previous_size, size); - } - } - -event after_connections_state_remove(c: connection) - { - local id = c$id; - local app_size: count; - local transport_size: count; - if ( id !in conn_size_table ) - conn_size_table[id] = 0; - app_size = conn_size_table[id]; - transport_size = c$orig$size + c$resp$size; - local size_delta: int = transport_size - app_size; - local annotation: string = "none"; - if ( app_size > transport_size ) - annotation = "negative_transport_overhead"; - else if ( size_delta > 1000 && 1.0 * size_delta / transport_size > 0.3 ) - annotation = "suspicious_transport_overhead"; - - print conn_size_log, fmt("conn %s app_size %d conn_size %d annotation %s", conn_id_string(id), app_size, transport_size, annotation); - - delete conn_size_table[id]; - } - -event connection_state_remove(c: connection) - { - event after_connections_state_remove(c); - } - -function print_app_summary(log: file, - id: conn_id, conn_start: time, func: string, start: time, - num_req: count, req_size: count, num_resp: count, resp_size: count, - extra: string) - { - add_to_conn_size(id, req_size + resp_size); - print log, fmt("conn %s conn_start %.6f app %s app_func %s start %.6f req %d pyld_^ %d reply %d pyld_v %d%s", - conn_id_string(id), conn_start, conn_app[id], func, start, - num_req, req_size, - num_resp, resp_size, - byte_len(extra) > 0 ? cat(" ", extra) : ""); - } diff --git a/policy.old/summaries/conn-app-reduced.bro b/policy.old/summaries/conn-app-reduced.bro deleted file mode 100644 index 74cce70dee..0000000000 --- a/policy.old/summaries/conn-app-reduced.bro +++ /dev/null @@ -1,37 +0,0 @@ -@load port-name - -# Used to annotate apps for connections on ephemeral ports -global conn_app: table[conn_id] of string &default = - function(id: conn_id): string - { - local p = is_icmp_port(id$resp_p) ? id$orig_p : id$resp_p; - if ( p in port_names ) - return port_names[p]; - else - return fmt("%s", p); - }; - -redef port_names += { - [0/icmp] = "icmp-echo", - [8/icmp] = "icmp-echo", - [3/icmp] = "icmp-unreach", - - [497/tcp] = "dantz", - [554/tcp] = "rtsp", - [5730/tcp] = "steltor", # calendar - [[7501/tcp, 7502/tcp, 7503/tcp, 7504/tcp, 7505/tcp, - 7506/tcp, 7507/tcp, 7508/tcp, 7509/tcp, 7510/tcp]] - = "hpss", - [[3128/tcp, 8000/tcp, 8080/tcp, 8888/tcp]] = "http", - [8443/tcp] = "https", - [3396/tcp] = "printer-agent", - [13782/tcp] = "veritas-backup-ctrl", - [16384/tcp] = "connected-backup", - - [67/udp] = "dhcp-s", # bootstrap for diskless hosts - [68/udp] = "dhcp-c", # reply-port - [427/udp] = "srvloc", - [11001/udp] = "metasys", # cardkey - [38293/udp] = "nav-ping", # norton anti-virus host discovery -}; - diff --git a/policy.old/summaries/conn-app.bro b/policy.old/summaries/conn-app.bro deleted file mode 100644 index 243ad03f36..0000000000 --- a/policy.old/summaries/conn-app.bro +++ /dev/null @@ -1,21 +0,0 @@ -@load conn-app-reduced - -@load ftp -@load dce-rpc - -event new_connection(c: connection) - { - local id = c$id; - if ( [id$resp_h, id$resp_p] in DCE_RPC::dce_rpc_endpoint ) - { - # local uuid = DCE_RPC::dce_rpc_endpoint[id$resp_h, id$resp_p]; - # conn_app[id] = fmt("dce-rpc-%s", - # ( uuid in DCE_RPC::dce_rpc_uuid_name ) ? - # DCE_RPC::dce_rpc_uuid_name[uuid] : "unknown"); - conn_app[id] = "dce-rpc"; - } - else if ( FTP::is_ftp_data_connection(c) ) - { - conn_app[id] = "ftp-data"; - } - } diff --git a/policy.old/summaries/conn-size.bro b/policy.old/summaries/conn-size.bro deleted file mode 100644 index 8001911ed6..0000000000 --- a/policy.old/summaries/conn-size.bro +++ /dev/null @@ -1,83 +0,0 @@ -# const number_of_regions = 32; -const region_size = 1024 * 1024; # 1MB -@load large-conns - -global conn_size_log = open_log_file("conn-size") &redef; - -function conn_id_string(id: conn_id): string - { - return fmt("%s/%d=>%s/%s", - id$orig_h, id$orig_p, - id$resp_h, id$resp_p); - } - -function report_size_error(c: connection, msg: string) - { - print conn_size_log, fmt("conn %s start %.6f duration %.6f pkt_^ %d pyld_^ %d pkt_v %d pyld_v %d size_error [%s]", - conn_id_string(c$id), - c$start_time, - c$duration, - c$orig$num_pkts, c$orig$size, - c$resp$num_pkts, c$resp$size, - msg); - } - -function conn_size(c: connection, is_orig: bool): string - { - local endp = is_orig ? c$orig : c$resp; - local endp_name = is_orig ? "orig" : "resp"; - local size = endp$size; - - if ( is_tcp_port(c$id$resp_p) ) - # double check TCP sizes - { - local est = estimate_flow_size_and_remove(c$id, is_orig); - if ( est$have_est ) - { - print conn_size_log, - fmt("conn %s endpoint %s size %d low %.0fMB high %.0fMB inconsistent %d", - conn_id_string(c$id), endp_name, - endp$size, - est$lower / 1e6, - est$upper / 1e6, - est$num_inconsistent); - - if ( est$num_inconsistent > 0 ) - { - report_size_error(c, - fmt("%s size error inconsistent %d", - endp_name, - est$num_inconsistent)); - return "-"; - } - - if ( size < est$lower || size > est$upper ) - { - report_size_error(c, - fmt("%s size error estimates: %.0fMB - %.0fMB", - endp_name, - est$lower / 1e6, - est$upper / 1e6)); - return "-"; - } - } - } - else if ( is_udp_port(c$id$resp_p) ) - { - if ( endp$num_pkts > size && size != 0 ) - { - report_size_error(c, - fmt("%s size error: pkt > size", - endp_name)); - return "-"; - } - } - - return fmt("%d", size); - } - -event connection_state_remove(c: connection) - { - local orig_size = conn_size(c, T); - local resp_size = conn_size(c, F); - } diff --git a/policy.old/summaries/conn-summary.bro b/policy.old/summaries/conn-summary.bro deleted file mode 100644 index dc89e49acc..0000000000 --- a/policy.old/summaries/conn-summary.bro +++ /dev/null @@ -1,99 +0,0 @@ -@load conn-util -# @load conn-app -# @load smb-tag -# @load dce-rpc-tag - -module ConnSummary; - -# redef capture_filters += { ["TUI"] = "tcp or udp or icmp" }; -redef capture_filters = { ["ip"] = "ip" }; # to also capture IP fragments -# redef SMB_tag::log_smb_tags = F; -# redef DCE_RPC_tag::log_dce_rpc_tags = F; - -global conn_summary_log = open_log_file("conn-summary") &redef; - -global conn_annotation: table[conn_id] of string &default = ""; - -function add_to_conn_annotation(cid: conn_id, new_annotation: string) - { - local a: string; - if ( cid in conn_annotation ) - conn_annotation[cid] = - cat(conn_annotation[cid], ",", new_annotation); - else - conn_annotation[cid] = new_annotation; - } - -# II. Annotation events -event new_connection(c: connection) - { - if ( is_tcp_port(c$id$resp_p) ) - { - if ( c$orig$state != TCP_SYN_SENT ) - { - # add_to_conn_annotation(c$id, "partial"); - } - } - } - -event partial_connection(c: connection) - { - add_to_conn_annotation(c$id, "partial"); - } - -event connection_established(c: connection) - { - if ( c$orig$state == TCP_ESTABLISHED && c$resp$state == TCP_ESTABLISHED ) - { - add_to_conn_annotation(c$id, "established"); - } - } - -event connection_rejected(c: connection) - { - add_to_conn_annotation(c$id, "rejected"); - } - -event connection_reset(c: connection) - { - add_to_conn_annotation(c$id, "reset"); - } - -event connection_attempt(c: connection) - { - add_to_conn_annotation(c$id, "attempt"); - } - -event connection_finished(c: connection) - { - add_to_conn_annotation(c$id, "finished"); - } - -event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context) - { - add_to_conn_annotation(context$id, "unreach"); - } - -event icmp_time_exceeded(c: connection, icmp: icmp_conn, code: count, context: icmp_context) - { - add_to_conn_annotation(context$id, "time_exceeded"); - } - -event connection_state_remove(c: connection) - { - # local tag_smb = get_smb_tag(c$id); - # local tag_dce_rpc = get_dce_rpc_tag(c$id); - - print conn_summary_log, fmt("conn %s start %.6f duration %.6f app %s pkt_^ %d pyld_^ %d pkt_v %d pyld_v %d state %s notes [%s]", - conn_id_string(c$id), - c$start_time, - c$duration, - conn_app[c$id], - c$orig$num_pkts, c$orig$size, - c$resp$num_pkts, c$resp$size, - conn_state(c, get_port_transport_proto(c$id$resp_p)), - conn_annotation[c$id]); - - delete conn_annotation[c$id]; - delete conn_app[c$id]; - } diff --git a/policy.old/summaries/conn-util.bro b/policy.old/summaries/conn-util.bro deleted file mode 100644 index 623ca04955..0000000000 --- a/policy.old/summaries/conn-util.bro +++ /dev/null @@ -1,55 +0,0 @@ -function conn_id_string(id: conn_id): string - { - return fmt("%s/%d=>%s/%s", - id$orig_h, id$orig_p, - id$resp_h, id$resp_p); - } - -function connection_state(c: connection, trans: transport_proto): string - { - local os = c$orig$state; - local rs = c$resp$state; - - local o_inactive = os == TCP_INACTIVE || os == TCP_PARTIAL; - local r_inactive = rs == TCP_INACTIVE || rs == TCP_PARTIAL; - - if ( trans == tcp ) - { - if ( rs == TCP_RESET ) - { - if ( os == TCP_SYN_SENT || os == TCP_SYN_ACK_SENT || - (os == TCP_RESET && - c$orig$size == 0 && c$resp$size == 0) ) - return "REJ"; - else if ( o_inactive ) - return "RSTRH"; - else - return "RSTR"; - } - else if ( os == TCP_RESET ) - return r_inactive ? "RSTOS0" : "RSTO"; - else if ( rs == TCP_CLOSED && os == TCP_CLOSED ) - return "SF"; - else if ( os == TCP_CLOSED ) - return r_inactive ? "SH" : "S2"; - else if ( rs == TCP_CLOSED ) - return o_inactive ? "SHR" : "S3"; - else if ( os == TCP_SYN_SENT && rs == TCP_INACTIVE ) - return "S0"; - else if ( os == TCP_ESTABLISHED && rs == TCP_ESTABLISHED ) - return "S1"; - else - return "OTH"; - } - - else if ( trans == udp ) - { - if ( os == UDP_ACTIVE ) - return rs == UDP_ACTIVE ? "SF" : "S0"; - else - return rs == UDP_ACTIVE ? "SHR" : "OTH"; - } - - else - return "OTH"; - } diff --git a/policy.old/summaries/dce-rpc-summary.bro b/policy.old/summaries/dce-rpc-summary.bro deleted file mode 100644 index 0d6ffecf96..0000000000 --- a/policy.old/summaries/dce-rpc-summary.bro +++ /dev/null @@ -1,93 +0,0 @@ -@load conn-util -@load dce-rpc -@load app-summary - -module DCE_RPC_summary; - -global log = open_log_file("dce-rpc-summary") &redef; - -type dce_rpc_transaction: record { - connection_id: conn_id; - conn_start: time; - uuid: string; - opnum: count; - start: time; - num_req: count; - req_size: count; - num_resp: count; - resp_size: count; -}; - -global conn_uuid: table[conn_id] of string &default = DCE_RPC::null_uuid; -global dce_rpc_trans_table: table[conn_id] of dce_rpc_transaction; -# global msg_size: table[conn_id, bool] of count; - -function end_dce_rpc_transaction(id: conn_id) - { - if ( id !in dce_rpc_trans_table ) - return; - - local t = dce_rpc_trans_table[id]; - local ifname = DCE_RPC::dce_rpc_uuid_name[t$uuid]; - local func_name = DCE_RPC::dce_rpc_func_name[ifname, t$opnum]; - print_app_summary(log, - t$connection_id, - t$conn_start, - fmt("%s/%s", ifname, func_name), - t$start, - t$num_req, t$req_size, - t$num_resp, t$resp_size, - fmt("ifname %s", ifname)); - - delete dce_rpc_trans_table[id]; - } - -function new_dce_rpc_transaction(c: connection, uuid: string, opnum: count): dce_rpc_transaction - { - local id = c$id; - - # End any previous trans - end_dce_rpc_transaction(id); - - local t = [ - $connection_id = id, $conn_start = c$start_time, - $uuid = uuid, $opnum = opnum, - $start = network_time(), - $num_req = 0, $req_size = 0, - $num_resp = 0, $resp_size = 0]; - - dce_rpc_trans_table[id] = t; - return t; - } - -event dce_rpc_message(c: connection, is_orig: bool, ptype: dce_rpc_ptype, msg: string) - { - # msg_size[c$id, is_orig] = byte_len(msg); - } - -event dce_rpc_bind(c: connection, uuid: string) - { - conn_uuid[c$id] = uuid; - } - -event dce_rpc_request(c: connection, opnum: count, stub: string) - { - local t = new_dce_rpc_transaction(c, conn_uuid[c$id], opnum); - ++t$num_req; - t$req_size = t$req_size + byte_len(stub); - # t$req_size = t$req_size + msg_size[c$id, T]; - } - -event dce_rpc_response(c: connection, opnum: count, stub: string) - { - local t = dce_rpc_trans_table[c$id]; - ++t$num_resp; - t$resp_size = t$resp_size + byte_len(stub); - # t$resp_size = t$resp_size + msg_size[c$id, F]; - } - -event connection_state_remove(c: connection) - { - if ( c$id in dce_rpc_trans_table ) - end_dce_rpc_transaction(c$id); - } diff --git a/policy.old/summaries/dce-rpc-tag.bro b/policy.old/summaries/dce-rpc-tag.bro deleted file mode 100644 index b74aaa704b..0000000000 --- a/policy.old/summaries/dce-rpc-tag.bro +++ /dev/null @@ -1,68 +0,0 @@ -@load conn-util -@load dce-rpc - -redef capture_filters += { - ["dce-rpc"] = "tcp or udp", -}; - -global dce_rpc_tag: table[conn_id] of string &default = ""; - -const log_dce_rpc_tags = T &redef; -function get_dce_rpc_tag(id: conn_id): string - { - if ( id in dce_rpc_tag ) - return dce_rpc_tag[id]; - else - return ""; - } - -module DCE_RPC_tag; - -global log = open_log_file("dce_rpc-tag") &redef; - -function add_to_dce_rpc_tag(c: connection, name: string): bool - { - local id = c$id; - local orig_tag = dce_rpc_tag[id]; - - if ( orig_tag == "" ) - { - dce_rpc_tag[id] = name; - } - else if ( strstr(orig_tag, name) == 0 ) - { - dce_rpc_tag[id] = cat(orig_tag, ",", name); - } - - return T; - } - -# Deficiency: it only looks at the bind request, but not the reply, so we -# do not know if the bind is successful. - -event dce_rpc_bind(c: connection, uuid: string) - { - local if_name = DCE_RPC::dce_rpc_uuid_name[uuid]; - if ( log_dce_rpc_tags ) - print log, fmt("%.6f %s DCE_RPC_Bind: %s", - network_time(), id_string(c$id), if_name); - add_to_dce_rpc_tag(c, if_name); - } - -event delete_dce_rpc_tag(c: connection) - { - delete dce_rpc_tag[c$id]; - } - -event connection_state_remove(c: connection) - { - if ( c$id in dce_rpc_tag ) - { - if ( log_dce_rpc_tags ) - print log, fmt("conn %s start %.6f DCE/RPC [%s]", - conn_id_string(c$id), - c$start_time, - dce_rpc_tag[c$id]); - event delete_dce_rpc_tag(c); - } - } diff --git a/policy.old/summaries/dns-common-summary.bro b/policy.old/summaries/dns-common-summary.bro deleted file mode 100644 index 14d4187d3f..0000000000 --- a/policy.old/summaries/dns-common-summary.bro +++ /dev/null @@ -1,245 +0,0 @@ -@load conn-util -@load app-summary -@load dns-info - -module DNS_common_summary; - - -export { - - global dns_summary_log = open_log_file("dns-common-summary") &redef; - - const server_ports = { - 53/udp, 53/tcp, 137/udp, - } &redef; -} - -redef capture_filters += { - ["dns"] = "port 53", - ["netbios-ns"] = "udp port 137", -}; - -const dns_op_name = { - [0] = "QUERY", - [1] = "IQUERY", - [2] = "STATUS", - [5] = "NB_REGISTER", - [6] = "NB_RELEASE", - [7] = "NB_WACK", - [8] = "NB_REFRESH", -} &default = function(op: count): string - { - return fmt("op-%d", op); - }; - -function dns_qtype(qtype: int, server_port: port): string - { - if ( qtype < 0 ) - return "none"; - - if ( server_port == 137/udp ) - { - if ( qtype == 32 ) - return "NB"; - if ( qtype == 33 ) - return "NBSTAT"; - } - - return query_types[int_to_count(qtype)]; - } - -function dns_rcode(rcode: int): string - { - return ( rcode < 0 ) ? "none" : - base_error[int_to_count(rcode)]; - } - -const netbios_host_type = { - ["00"] = "workstation", - ["03"] = "messenger", - ["1b"] = "domain_master_browser", - ["20"] = "server", - ["1c"] = "domain_group", - ["1d"] = "master_browser_group", - ["1e"] = "group", -} &default = function(t: string): string { return t; }; - -const dns_transaction_timeout = 30 sec &redef; - -type dns_transaction: record { - connection_id: conn_id; - conn_start: time; - func: string; - start: time; - num_req: count; - req_size: count; - num_resp: count; - resp_size: count; - - num_q: count; - qtype: string; - query: string; - host_type: string; - rcode: string; - resp_time: time; # of the first resp -}; - -# Use only the client addr and transaction id for index, because -# Netbios/NS clients sometimes send to broadcast address -type dns_trans_index: record { - client: addr; - client_port: port; - id: count; - server: addr; - server_port: port; -}; -global dns_trans_table: table[dns_trans_index] of dns_transaction; - -function fmt_list(x: string): string - { - if ( strstr(x, ",") > 0 ) - return cat("[", x, "]"); - else - return x; - } - -event expire_DNS_transaction(ind: dns_trans_index) - { - if ( ind !in dns_trans_table ) - return; - - local t = dns_trans_table[ind]; - if ( ind$server_port in server_ports ) - { - print_app_summary(dns_summary_log, - t$connection_id, - t$conn_start, - t$func, t$start, - t$num_req, t$req_size, - t$num_resp, t$resp_size, - fmt("qtype %s return %s query '%s' host_type %s latency %.6f", - fmt_list(t$qtype), fmt_list(t$rcode), - fmt_list(gsub(t$query, / /, "_")), - fmt_list(t$host_type), - t$resp_time >= t$start ? t$resp_time - t$start : -1 sec)); - } - delete dns_trans_table[ind]; - } - -function lookup_dns_transaction(c: connection, msg: dns_msg, is_orig: bool): dns_transaction - { - local id = c$id; - local client: addr; - local server: addr; - local client_port: port; - local server_port: port; - - if ( ( ! msg$QR && is_orig ) || ( msg$QR && ! is_orig ) ) - { - client = id$orig_h; - client_port = id$orig_p; - server = id$resp_h; - server_port = id$resp_p; - } - else - { - client = id$resp_h; - client_port = id$resp_p; - server = id$orig_h; - server_port = id$orig_p; - } - - # print fmt("%.6f client %s server %s", network_time(), client, server); - - # Netbios queries are sometimes sent to broadcast addresses, - # so we ignore the server part - if ( server_port == 137/udp ) - server = 0.0.0.0; - - local ind = [$client = client, $client_port = client_port, - $id = msg$id, - $server = server, $server_port = server_port]; - - if ( ind !in dns_trans_table ) - { - local t = [ - $connection_id = id, - $conn_start = c$start_time, - $func = dns_op_name[msg$opcode], - $start = network_time(), - $num_req = 0, $req_size = 0, - $num_resp = 0, $resp_size = 0, - $num_q = 0, - $qtype = "none", - $query = "none", $host_type = "none", - $rcode = "none", - $resp_time = network_time() - 1 sec]; - dns_trans_table[ind] = t; - } - - schedule dns_transaction_timeout { - expire_DNS_transaction(ind) - }; - - return dns_trans_table[ind]; - } - -event dns_message(c: connection, is_orig: bool, msg: dns_msg, len: count) - { - local t = lookup_dns_transaction(c, msg, is_orig); - if ( ! msg$QR ) - { - ++t$num_req; - t$req_size = t$req_size + len; - } - else - { - local rcode = dns_rcode(msg$rcode); - if ( t$rcode == "none" ) - t$rcode = rcode; - else if ( t$rcode != rcode ) - t$rcode = cat(t$rcode, ",", rcode); - ++t$num_resp; - t$resp_size = t$resp_size + len; - if ( t$num_resp == 1 ) - t$resp_time = network_time(); - } - } - -function append_query(t: dns_transaction, query: string, host_type: string, qtype: string) - { - ++t$num_q; - if ( t$num_q == 1 ) - { - t$qtype = qtype; - t$query = query; - t$host_type = host_type; - } - else - { - if ( qtype != t$qtype ) - t$qtype = cat(t$qtype, ",", qtype); - if ( query != t$query ) - t$query = cat(t$query, ",", query); - if ( host_type != t$host_type ) - t$host_type = cat(t$host_type, ",", host_type); - } - } - -event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) - { - local host_type = "n/a"; - if ( c$id$resp_p == 137/udp ) - { - query = decode_netbios_name(query); - local last_byte = sub_bytes(query, byte_len(query) - 2, 2); - host_type = netbios_host_type[last_byte]; - } - - # print log, fmt("conn %s start %.6f op %d qtype 0x%x name [%s]", - # conn_id_string(c$id), network_time(), - # msg$opcode, qtype, query); - - local t = lookup_dns_transaction(c, msg, T); - append_query(t, query, host_type, dns_qtype(qtype, c$id$resp_p)); - } diff --git a/policy.old/summaries/dns-summary.bro b/policy.old/summaries/dns-summary.bro deleted file mode 100644 index 327f2f5032..0000000000 --- a/policy.old/summaries/dns-summary.bro +++ /dev/null @@ -1,8 +0,0 @@ -@load dns-common-summary - -redef DNS_common_summary::log = open_log_file("dns-summary"); -redef DNS_common_summary::server_ports = { 53/udp, 53/tcp }; - -redef capture_filters = { - ["dns"] = "port 53", -}; diff --git a/policy.old/summaries/http-rps-summary.bro b/policy.old/summaries/http-rps-summary.bro deleted file mode 100644 index 0241a886b7..0000000000 --- a/policy.old/summaries/http-rps-summary.bro +++ /dev/null @@ -1,171 +0,0 @@ -# $Id:$ - -@load http -@load app-summary - -redef capture_filters = { - ["http"] = "tcp port 80 or tcp port 8080 or tcp port 8000 or tcp port 8888 or tcp port 3128", -}; - -module HTTP_req_per_session; - -export { - global log = open_log_file("http-rps-summary") &redef; - const http_session_idle_timeout = 1 sec &redef; -} - -type http_session: record { - # standard stuff - connection_id: conn_id; # of the first conn - conn_start: time; - func: string; - start: time; - num_req: count; - req_size: count; - num_resp: count; - resp_size: count; - - # for timeout - unfinished_req: count; - unfinished_resp: count; - last_time: time; -}; - -global expire_http_session: function( - tbl: table[addr] of http_session, index: addr): interval; - -global http_ssn_table: table[addr] of http_session - &read_expire = http_session_idle_timeout - &expire_func = expire_http_session; - -function new_http_session(c: connection): http_session - { - local t = [ - $connection_id = c$id, - $conn_start = c$start_time, - $func = "unknown", - $start = network_time(), - $num_req = 0, $req_size = 0, - $num_resp = 0, $resp_size = 0, - $unfinished_req = 0, $unfinished_resp = 0, - $last_time = network_time()]; - - return t; - } - -function lookup_http_session(c: connection, is_orig: bool): http_session - { - local id = c$id; - local index = id$orig_h; - - if ( index !in http_ssn_table ) - { - if ( ! is_orig ) - print fmt("%.6f HTTP session not found for a resposne", - network_time(), conn_id_string(id)); - - http_ssn_table[index] = new_http_session(c); - } - - return http_ssn_table[index]; - } - -function end_http_session(t: http_session) - { - print_app_summary(log, t$connection_id, t$conn_start, t$func, t$start, - t$num_req, t$req_size, - t$num_resp, t$resp_size, - fmt("duration %.6f", t$last_time - t$start)); - } - -function check_expiration(t: http_session): bool - { - print fmt("%.6f check expiration http_session %s: %.6f %d,%d %d,%d", - network_time(), conn_id_string(t$connection_id), - t$last_time, - t$num_req, t$num_resp, - t$unfinished_req, t$unfinished_resp); - - if ( network_time() - t$last_time < http_session_idle_timeout - || ( t$unfinished_req + t$unfinished_resp > 0 && - network_time() - t$last_time < 15 min && - ! done_with_network ) ) - { - print fmt("do not expire"); - return F; - } - - end_http_session(t); - return T; - } - -function expire_http_session(tbl: table[addr] of http_session, - index: addr): interval - { - local t = tbl[index]; - if ( ! check_expiration(t) ) - { - print fmt("... no, wait one more second: %d, %d", - t$unfinished_req, t$unfinished_resp); - return 1 sec; - } - return 0 sec; - } - -event http_request(c: connection, method: string, original_URI: string, unescaped_URI: string, version: string) - { - local t = lookup_http_session(c, T); - if ( check_expiration(t) ) - { - delete http_ssn_table[c$id$orig_h]; - t = lookup_http_session(c, T); - } - t$func = method; - ++t$num_req; - ++t$unfinished_req; - t$last_time = network_time(); - } - -event http_reply(c: connection, version: string, code: count, reason: string) - { - # print fmt("http reply"); - local t = lookup_http_session(c, F); - ++t$num_resp; - ++t$unfinished_resp; - t$last_time = network_time(); - } - -function http_request_done(c: connection, stat: http_message_stat) - { - # print fmt("http request done"); - local t = lookup_http_session(c, T); - t$req_size = t$req_size + stat$body_length; - if ( t$unfinished_req > 0 ) - --t$unfinished_req; - t$last_time = network_time(); - } - -function http_reply_done(c: connection, stat: http_message_stat) - { - local t = lookup_http_session(c, F); - t$resp_size = t$resp_size + stat$body_length; - if ( t$unfinished_resp > 0 ) - --t$unfinished_resp; - t$last_time = network_time(); - } - -event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) - { - if ( is_orig ) - http_request_done(c, stat); - else - http_reply_done(c, stat); - } - -event bro_done() - { - for ( index in http_ssn_table ) - { - end_http_session(http_ssn_table[index]); - } - } diff --git a/policy.old/summaries/http-summary.bro b/policy.old/summaries/http-summary.bro deleted file mode 100644 index 1f6c1219e4..0000000000 --- a/policy.old/summaries/http-summary.bro +++ /dev/null @@ -1,281 +0,0 @@ -@load http -@load app-summary - -redef capture_filters = { - ["http"] = "tcp port 80 or tcp port 8080 or tcp port 8000 or tcp port 8888 or tcp port 3128", - ["ipp"] = "tcp port 631", -}; - -module HTTP_summary; - -global log = open_log_file("http-summary") &redef; - -type http_transaction: record { - # standard stuff - connection_id: conn_id; - conn_start: time; - func: string; - start: time; - num_req: count; - req_size: count; - num_resp: count; - resp_size: count; - - # for tracking the state - req_done: bool; - resp_done: bool; - done: bool; - - # http-specific stuff - code: count; - req_content_type: string; - resp_content_type: string; - conditional_get: string; - user_agent: string; - cache_control: string; - last_modified: string; - etag: string; -}; - -type http_trans_group: record { - trans: table[count] of http_transaction; - first_req: count; - last_req: count; -}; - -global http_trans_table: table[conn_id] of http_trans_group; - -function lookup_http_trans_group(id: conn_id, create: bool): http_trans_group - { - if ( id !in http_trans_table ) - { - if ( create ) - { - local trans: table[count] of http_transaction; - http_trans_table[id] = [ - $trans = trans, $first_req = 1, $last_req = 0]; - } - else - print fmt("HTTP trans_group not found: %s", conn_id_string(id)); - } - - return http_trans_table[id]; - } - -function new_http_transaction(c: connection, func: string): http_transaction - { - # print fmt("new http trans: %.6f %s", network_time(), func); - local g = lookup_http_trans_group(c$id, T); - - local t = [ - $connection_id = c$id, - $conn_start = c$start_time, - $func = func, - $start = network_time(), - $num_req = 0, $req_size = 0, - $num_resp = 0, $resp_size = 0, - $req_done = F, $resp_done = F, $done = F, - $code = 0, - $req_content_type = "none", - $resp_content_type = "none", - $conditional_get = "no", - $user_agent = "none", - $cache_control = "none", - $last_modified = "none", - $etag = "none"]; - - ++g$last_req; - g$trans[g$last_req] = t; - - return t; - } - -function lookup_http_transaction(id: conn_id, is_orig: bool): http_transaction - { - local g = lookup_http_trans_group(id, F); - local index = is_orig ? g$last_req : g$first_req; - - if ( index !in g$trans ) - { - print fmt("HTTP transaction not found: %s : %d-%d", - conn_id_string(id), g$first_req, g$last_req); - } - - return g$trans[index]; - } - -function end_http_transaction(t: http_transaction) - { - if ( t$req_done && t$resp_done ) - { - if ( t$done ) - return; - t$done = T; - print_app_summary(log, t$connection_id, t$conn_start, t$func, t$start, - t$num_req, t$req_size, - t$num_resp, t$resp_size, - fmt("code %d content_type_^ %s content_type_v %s conditional_get %s user_agent %s cache_control %s last_modified %s etag %s", - t$code, - t$req_content_type, t$resp_content_type, - t$conditional_get, - subst_string(t$user_agent, " ", "_"), - subst_string(t$cache_control, " ", ""), - t$last_modified == "none" ? "none" : "present", - t$etag == "none" ? "none" : "present" - )); - } - } - -event http_request(c: connection, method: string, original_URI: string, unescaped_URI: string, version: string) - { - # print fmt("http request"); - local t = new_http_transaction(c, method); - ++t$num_req; - t$req_done = F; - } - -event http_reply(c: connection, version: string, code: count, reason: string) - { - # print fmt("http reply"); - local id = c$id; - local g = lookup_http_trans_group(id, T); - local t: http_transaction; - if ( g$first_req in g$trans ) - t = g$trans[g$first_req]; - else - t = new_http_transaction(c, "none"); - - ++t$num_resp; - t$code = code; - t$resp_done = F; - } - -function http_request_done(c: connection, stat: http_message_stat) - { - # print fmt("http request done"); - local t = lookup_http_transaction(c$id, T); - t$req_size = t$req_size + stat$body_length; - t$req_done = T; - end_http_transaction(t); - } - -function http_reply_done(c: connection, stat: http_message_stat) - { - # print fmt("http reply done"); - local t = lookup_http_transaction(c$id, F); - t$resp_size = t$resp_size + stat$body_length; - if ( t$code >= 200 ) - { - t$resp_done = T; - end_http_transaction(t); - local g = lookup_http_trans_group(t$connection_id, F); - ++g$first_req; - } - } - -event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) - { - if ( is_orig ) - http_request_done(c, stat); - else - http_reply_done(c, stat); - } - -event http_content_type(c: connection, is_orig: bool, ty: string, subty: string) - { - local t = lookup_http_transaction(c$id, is_orig); - local type_str = fmt("%s/%s", ty, subty); - if ( is_orig ) - t$req_content_type = type_str; - else - t$resp_content_type = type_str; - } - -function http_conditional_get(c: connection, is_orig: bool, h: mime_header_rec) - { - local t = lookup_http_transaction(c$id, is_orig); - t$conditional_get = h$name; - } - -function http_user_agent(c: connection, is_orig: bool, h: mime_header_rec) - { - local t = lookup_http_transaction(c$id, is_orig); - t$user_agent = h$value; - } - -function http_cache_control(c: connection, is_orig: bool, h: mime_header_rec) - { - local t = lookup_http_transaction(c$id, is_orig); - t$cache_control = h$value; - } - -function http_last_modified(c: connection, is_orig: bool, h: mime_header_rec) - { - local t = lookup_http_transaction(c$id, is_orig); - t$last_modified = h$value; - } - -function http_etag(c: connection, is_orig: bool, h: mime_header_rec) - { - local t = lookup_http_transaction(c$id, is_orig); - t$etag = h$value; - } - -# type mime_header_rec: record { -# name: string; -# value: string; -# }; -# type mime_header_list: table[count] of mime_header_rec; - -const conditional_get_headers = { - "IF-MODIFIED-SINCE", - "IF-UNMODIFIED-SINCE", - "IF-MATCH", - "IF-NONE-MATCH", - "IF-RANGE", -}; - -event http_all_headers(c: connection, is_orig: bool, hlist: mime_header_list) - { - if ( ! is_orig ) - return; - - for ( i in hlist ) - { - local h = hlist[i]; - if ( h$name in conditional_get_headers ) - http_conditional_get(c, is_orig, h); - if ( h$name == "USER-AGENT" ) - http_user_agent(c, is_orig, h); - if ( h$name == "CACHE-CONTROL" ) - http_cache_control(c, is_orig, h); - if ( h$name == "LAST-MODIFIED" ) - http_last_modified(c, is_orig, h); - if ( h$name == "ETAG" ) - http_etag(c, is_orig, h); - } - } - -function end_http_trans_group(g: http_trans_group, index: count) - { - if ( index !in g$trans ) - return; - local t = g$trans[index]; - - t$req_done = T; - t$resp_done = T; - end_http_transaction(t); - - delete g$trans[index]; - end_http_trans_group(g, index + 1); - } - -event connection_state_remove(c: connection) - { - local id = c$id; - if ( id in http_trans_table ) - { - end_http_trans_group(http_trans_table[id], 1); - delete http_trans_table[id]; - } - } diff --git a/policy.old/summaries/ipp-summary.bro b/policy.old/summaries/ipp-summary.bro deleted file mode 100644 index 5bc4c3df86..0000000000 --- a/policy.old/summaries/ipp-summary.bro +++ /dev/null @@ -1,3 +0,0 @@ -@load http-summary - -redef HTTP_summary::log = open_log_file("ipp-summary") &redef; diff --git a/policy.old/summaries/ncp-summary.bro b/policy.old/summaries/ncp-summary.bro deleted file mode 100644 index 89c19c6713..0000000000 --- a/policy.old/summaries/ncp-summary.bro +++ /dev/null @@ -1,78 +0,0 @@ -@load ncp -@load app-summary - -module NCP_summary; - -global ncp_summary_log = open_log_file("ncp-summary") &redef; - -type ncp_transaction: record { - connection_id: conn_id; - conn_start: time; - func: string; - start: time; - num_req: count; - req_size: count; - num_resp: count; - resp_size: count; - completion_code: int; # ... of the first reply -}; - -global ncp_trans_table: table[conn_id] of ncp_transaction; - -function end_ncp_transaction(id: conn_id) - { - if ( id !in ncp_trans_table ) - return; - - local t = ncp_trans_table[id]; - print_app_summary(ncp_summary_log, t$connection_id, t$conn_start, t$func, t$start, - t$num_req, t$req_size, - t$num_resp, t$resp_size, - fmt("completion_code %d", t$completion_code)); - } - -function new_ncp_transaction(c: connection, func: string): ncp_transaction - { - local id = c$id; - - # End any previous trans - end_ncp_transaction(id); - - local t = [ - $connection_id = id, - $conn_start = c$start_time, - $func = func, - $start = network_time(), - $num_req = 0, $req_size = 0, - $num_resp = 0, $resp_size = 0, - $completion_code = -1]; - - ncp_trans_table[id] = t; - return t; - } - -event ncp_request(c: connection, frame_type: count, length: count, func: count) - { - local f = ( frame_type == 0x2222 ) ? - NCP::ncp_function_name[func] : - NCP::ncp_frame_type_name[frame_type]; - - local t = new_ncp_transaction(c, f); - ++t$num_req; - t$req_size = t$req_size + length; - } - -event ncp_reply(c: connection, frame_type: count, length: count, req_frame: count, req_func: count, completion_code: count) - { - local t = ncp_trans_table[c$id]; - ++t$num_resp; - if ( t$num_resp == 1 ) - t$completion_code = completion_code; - t$resp_size = t$resp_size + length; - } - -event connection_state_remove(c: connection) - { - if ( c$id in ncp_trans_table ) - end_ncp_transaction(c$id); - } diff --git a/policy.old/summaries/ncp-tag.bro b/policy.old/summaries/ncp-tag.bro deleted file mode 100644 index 61c63a2f3f..0000000000 --- a/policy.old/summaries/ncp-tag.bro +++ /dev/null @@ -1,26 +0,0 @@ -@load conn-id -@load ncp - -module NCP_tag; - -global log = open_log_file("ncp-tag") &redef; - -const ncp_request_type = { -[ 0x11 ] = "print", -[ 0x16, 0x68 ] = "directory", -} &default = function(code: count): string - { - return fmt("unknown(%x)", code); - }; - -event ncp_request(c: connection, frame_type: count, length: count, func: count) - { - print log, fmt("%.6f %s NCP request type=%s function=%s", - network_time(), id_string(c$id), - NCP::ncp_frame_type_name[frame_type], - NCP::ncp_function_name[func]); - } - -event ncp_reply(c: connection, frame_type: count, length: count, completion_code: count) - { - } diff --git a/policy.old/summaries/netbios-ns-summary.bro b/policy.old/summaries/netbios-ns-summary.bro deleted file mode 100644 index 3587b9a954..0000000000 --- a/policy.old/summaries/netbios-ns-summary.bro +++ /dev/null @@ -1,9 +0,0 @@ -@load dns-common-summary - -redef DNS_common_summary::dns_summary_log = open_log_file("netbios-ns-summary"); -redef DNS_common_summary::server_ports = { 137/udp }; - -redef capture_filters += { - ["netbios-ns"] = "udp port 137", -}; - diff --git a/policy.old/summaries/netbios-ssn-summary.bro b/policy.old/summaries/netbios-ssn-summary.bro deleted file mode 100644 index 5166e56baa..0000000000 --- a/policy.old/summaries/netbios-ssn-summary.bro +++ /dev/null @@ -1,112 +0,0 @@ -@load app-summary - -redef capture_filters = { - ["netbios-ssn"] = "tcp port 139", -}; - -module NetbiosSSN_summary; - -global netbios_log = open_log_file("netbios-ssn-summary") &redef; - -const netbios_msg_types = { - [0x0] = "ssn_message", - [0x81] = "ssn_request", - [0x82] = "positive_resp", - [0x83] = "negative_resp", - [0x84] = "retarget_resp", - [0x85] = "keep_alive", -} &default = function(msg_type: count): string - { - return fmt("unknown-0x%x", msg_type); - }; - -type netbios_ssn_transaction: record { - connection_id: conn_id; - conn_start: time; - start: time; - num_req: count; - req_size: count; - num_resp: count; - resp_size: count; - req_type: string; - resp_type: string; # ... of the first reply - raw_ssn_msg: count; -}; - -global netbios_ssn_trans_table: table[conn_id] of netbios_ssn_transaction; - -function end_netbios_ssn_transaction(id: conn_id) - { - if ( id !in netbios_ssn_trans_table ) - return; - - local t = netbios_ssn_trans_table[id]; - print_app_summary(netbios_log, t$connection_id, t$conn_start, - t$req_type, t$start, - t$num_req, t$req_size, - t$num_resp, t$resp_size, - fmt("req_type %s resp_type %s raw %d", - t$req_type, t$resp_type, t$raw_ssn_msg)); - - delete netbios_ssn_trans_table[id]; - } - -function lookup_netbios_ssn_transaction(c: connection, new_trans: bool): netbios_ssn_transaction - { - local id = c$id; - - if ( new_trans ) - { - # End any previous trans - end_netbios_ssn_transaction(id); - } - - if ( id !in netbios_ssn_trans_table ) - { - local t = [ - $connection_id = id, - $conn_start = c$start_time, - $start = network_time(), - $num_req = 0, $req_size = 0, - $num_resp = 0, $resp_size = 0, - $req_type = "none", $resp_type = "none", - $raw_ssn_msg = 0]; - netbios_ssn_trans_table[c$id] = t; - } - - return netbios_ssn_trans_table[c$id]; - } - -event netbios_ssn_message(c: connection, is_orig: bool, msg_type: count, data_len: count) - { - local msg_type_name = netbios_msg_types[msg_type]; - local t: netbios_ssn_transaction; - if ( is_orig ) - { - t = lookup_netbios_ssn_transaction(c, T); - ++t$num_req; - if ( t$num_req == 1 ) - t$req_type = msg_type_name; - t$req_size = t$req_size + data_len; - } - else - { - t = lookup_netbios_ssn_transaction(c, F); - ++t$num_resp; - if ( t$num_resp == 1 ) - t$resp_type = msg_type_name; - t$resp_size = t$resp_size + data_len; - } - } - -event netbios_session_raw_message(c: connection, is_orig: bool, msg: string) - { - local t = lookup_netbios_ssn_transaction(c, F); - ++t$raw_ssn_msg; - } - -event connection_state_remove(c: connection) - { - if ( c$id in netbios_ssn_trans_table ) - end_netbios_ssn_transaction(c$id); - } diff --git a/policy.old/summaries/nfs-summary.bro b/policy.old/summaries/nfs-summary.bro deleted file mode 100644 index ad1979b33b..0000000000 --- a/policy.old/summaries/nfs-summary.bro +++ /dev/null @@ -1,9 +0,0 @@ -@load sun-rpc-summary - -redef SUN_RPC_summary::log = open_log_file("nfs-summary"); - -redef capture_filters = { - ["nfs"] = "port 2049", - # UDP packets are often fragmented - ["nfs-frag"] = "ip[6:2] & 0x1fff != 0", -}; diff --git a/policy.old/summaries/rexmit-summary.bro b/policy.old/summaries/rexmit-summary.bro deleted file mode 100644 index 9f5c1ef0c9..0000000000 --- a/policy.old/summaries/rexmit-summary.bro +++ /dev/null @@ -1,26 +0,0 @@ -# Statistical analysis of TCP connection in terms of the packet streams -# in each direction. - -@load conn-util - -redef capture_filters = { ["tcp"] = "tcp" }; -redef ignore_keep_alive_rexmit = T; - -global log = open_log_file("rexmit-summary") &redef; - -const min_num_pkts = 0; - -event conn_stats(c: connection, os: endpoint_stats, rs: endpoint_stats) - { - if ( os$num_pkts < min_num_pkts && rs$num_pkts < min_num_pkts ) - return; - - print log, fmt("conn %s start %.6f duration %.6f pkt_^ %d rexmit_pkt_^ %d pyld_^ %d rexmit_pyld_^ %d pkt_v %d rexmit_pkt_v %d pyld_v %d rexmit_pyld_v %d", - conn_id_string(c$id), c$start_time, c$duration, - os$num_pkts, os$num_rxmit, - # os$num_pkts == 0 ? 0.0 : 1.0 * os$num_rxmit / os$num_pkts, - c$orig$size, os$num_rxmit_bytes, - rs$num_pkts, rs$num_rxmit, - # rs$num_pkts == 0 ? 0.0 : 1.0 * rs$num_rxmit / rs$num_pkts, - c$resp$size, rs$num_rxmit_bytes); - } diff --git a/policy.old/summaries/smb-summary.bro b/policy.old/summaries/smb-summary.bro deleted file mode 100644 index 4ba9c575a0..0000000000 --- a/policy.old/summaries/smb-summary.bro +++ /dev/null @@ -1,251 +0,0 @@ -@load app-summary - -redef capture_filters += { - ["netbios-dgm"] = "udp port 138", - ["netbios-ssn"] = "tcp port 139", - ["microsft-ds"] = "tcp port 445", -}; - -module SMB_summary; - -global smb_log = open_log_file("smb-summary") &redef; -global chris_log = open_log_file("chris-summary") &redef; - -#const smb_transaction_func = { -# ["SMB_COM_TRANSACTION", 0x0 ] = "\\PIPE\\LANMAN\\", -# ["SMB_COM_TRANSACTION", 0x1 ] = "\\MAILSLOT\\", -# ["SMB_COM_TRANSACTION", 0x54] = "CallNamedPipe", -# ["SMB_COM_TRANSACTION", 0x53] = "WaitNamedPipe", -# ["SMB_COM_TRANSACTION", 0x26] = "TransactNmPipe", -# -# ["SMB_COM_TRANSACTION2", 0x0] = "TRANS2_OPEN2", -# ["SMB_COM_TRANSACTION2", 0x1] = "TRANS2_FIND_FIRST2", -# ["SMB_COM_TRANSACTION2", 0x2] = "TRANS2_FIND_NEXT2", -# ["SMB_COM_TRANSACTION2", 0x3] = "TRANS2_QUERY_FS_INFORMATION", -# ["SMB_COM_TRANSACTION2", 0x5] = "TRANS2_QUERY_PATH_INFORMATION", -# ["SMB_COM_TRANSACTION2", 0x6] = "TRANS2_SET_PATH_INFORMATION", -# ["SMB_COM_TRANSACTION2", 0x7] = "TRANS2_QUERY_FILE_INFORMATION", -# ["SMB_COM_TRANSACTION2", 0x8] = "TRANS2_SET_FILE_INFORMATION", -# ["SMB_COM_TRANSACTION2", 0x0d] = "TRANS2_CREATE_DIRECTORY", -# ["SMB_COM_TRANSACTION2", 0x0e] = "TRANS2_SESSION_SETUP", -# ["SMB_COM_TRANSACTION2", 0x10] = "TRANS2_GET_DFS_REFERRAL", -#} &default = function(cmd: string, subcmd: count): string -# { -# return fmt("%s/%d", cmd, subcmd); -# }; - -type smb_req_resp: record { - connection_id: conn_id; - conn_start: time; - func: string; - cmd: string; - start: time; - num_req: count; - req_size: count; - num_resp: count; - resp_size: count; -}; - -type smb_req_reply_group: record { - trans: table[count] of smb_req_resp; - first_req: count; - last_req: count; -}; - -global smb_trans_table: table[conn_id] of smb_req_reply_group; - -function lookup_smb_req_reply_group(id: conn_id, create: bool): smb_req_reply_group - { - if ( id !in smb_trans_table ) - { - if ( create ) - { - local trans: table[count] of smb_req_resp; - smb_trans_table[id] = [ - $trans = trans, $first_req = 1, $last_req = 0]; - } - else - print fmt("SMB req_reply_group not found: %s", - conn_id_string(id)); - } - - return smb_trans_table[id]; - } - -function new_smb_req_resp(c: connection, cmd: string): smb_req_resp - { - local id = c$id; - local g = lookup_smb_req_reply_group(id, T); - - if( is_udp_port(id$orig_p) || is_udp_port(id$resp_p) ) - print fmt("%.6f %s a new req_resp was triggered on a UDP connection!: %s", - network_time(), conn_id_string(id), cmd); - - local t = [ - $connection_id = id, $conn_start = c$start_time, - $cmd = cmd, $func = cmd, - $start = network_time(), - $num_req = 0, $req_size = 0, - $num_resp = 0, $resp_size = 0 - ]; - - ++g$last_req; - g$trans[g$last_req] = t; - - return g$trans[g$last_req]; - } - -function end_smb_req_resp(t: smb_req_resp) - { - print_app_summary(smb_log, t$connection_id, t$conn_start, - t$func, t$start, - t$num_req, t$req_size, - t$num_resp, t$resp_size, - fmt("cmd %s", t$cmd)); - } - -function lookup_smb_req_resp(c: connection, is_orig: bool, cmd: string): smb_req_resp - { - local id = c$id; - local g = lookup_smb_req_reply_group(id, T); - - if( is_udp_port(id$orig_p) || is_udp_port(id$resp_p) ) - print fmt("%.6f %s a lookup was triggered on a UDP connection!: %s", - network_time(), conn_id_string(id), cmd); - - if ( g$first_req > g$last_req ) - { - print fmt("%.6f %s request missing: %s", - network_time(), conn_id_string(id), cmd); - return new_smb_req_resp(c, cmd); - } - - if ( is_orig ) - { - return g$trans[g$last_req]; - } - else if ( cmd == "(current)" ) - { - return g$trans[g$first_req]; - } - else - { - local t = g$trans[g$first_req]; - if ( g$first_req < g$last_req ) - { - end_smb_req_resp(t); - ++g$first_req; - t = g$trans[g$first_req]; - } - if ( t$cmd != cmd ) - { - if ( g$first_req < g$last_req ) - return lookup_smb_req_resp(c, is_orig, cmd); - print fmt("%.6f %s SMB command-reply mismatch", - network_time(), conn_id_string(id)); - } - return t; - } - } - -event smb_message(c: connection, hdr: smb_hdr, is_orig: bool, cmd: - string, body_length: count, body : string) - { - print chris_log, fmt("%.6f %s %s", network_time(), conn_id_string(c$id), cmd); - - local t: smb_req_resp; - - if ( is_udp_port( c$id$orig_p ) || is_udp_port ( c$id$resp_p ) ) - { - # dont need to keep track of UDP smb commands - print_app_summary(smb_log, c$id, network_time(), - cmd, network_time(), - 0, 0, 0, 0, - fmt("cmd %s", cmd)); - } - else if ( is_orig ) - { - t = new_smb_req_resp(c, cmd); - ++t$num_req; - t$req_size = t$req_size + body_length; - } - else - { - t = lookup_smb_req_resp(c, is_orig, cmd); - ++t$num_resp; - t$resp_size = t$resp_size + body_length; - } - } - -event smb_error(c: connection, hdr: smb_hdr, cmd: count, cmd_str: string, data: string) - { - print chris_log, fmt("%.6f %s SMB_ERROR:%s", network_time(), conn_id_string(c$id), cmd_str); - } - -event dce_rpc_bind(c: connection, uuid: string) - { - local id = c$id; - if ( id !in smb_trans_table ) - return; - local t = lookup_smb_req_resp(c, T, "(current)"); - t$func = "DCE_RPC_BIND"; - } - -event dce_rpc_request(c: connection, opnum: count, stub: string) - { - local id = c$id; - if ( id !in smb_trans_table ) - return; - local t = lookup_smb_req_resp(c, T, "(current)"); - t$func = "DCE_RPC_CALL"; - } - -event dce_rpc_response(c: connection, opnum: count, stub: string) - { - local id = c$id; - if ( id !in smb_trans_table ) - return; - local t = lookup_smb_req_resp(c, F, "(current)"); - t$func = "DCE_RPC_CALL"; - } - -event smb_com_transaction(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool) - { - if ( is_orig && !is_udp_port( c$id$orig_p ) ) - { - local t = lookup_smb_req_resp(c, T, "(current)"); - } - } - -event smb_com_transaction2(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool) - { - if ( is_orig && !is_udp_port( c$id$orig_p ) ) - { - local t = lookup_smb_req_resp(c, T, "(current)"); - } - } - -function end_smb_req_reply_group(g: smb_req_reply_group, index: count) - { - if ( index > g$last_req ) - return; - - if ( index >= g$first_req && index in g$trans ) - end_smb_req_resp(g$trans[index]); - - if( index in g$trans ) - { - delete g$trans[index]; - end_smb_req_reply_group(g, index + 1); - } - } - -event connection_state_remove(c: connection) - { - local id = c$id; - if ( !is_udp_port( id$orig_p ) && id in smb_trans_table ) - { - local g = smb_trans_table[id]; - end_smb_req_reply_group(g, 1); - } - } diff --git a/policy.old/summaries/smb-tag.bro b/policy.old/summaries/smb-tag.bro deleted file mode 100644 index 82813b5284..0000000000 --- a/policy.old/summaries/smb-tag.bro +++ /dev/null @@ -1,160 +0,0 @@ -@load conn-util - -redef capture_filters += { - ["smb"] = "tcp port 445", - ["netbios-ss"] = "tcp port 139", -}; - -global smb_filename_tag: table[conn_id] of string &default = ""; - -const log_smb_tags = T &redef; -function get_smb_tag(id: conn_id): string - { - if ( id in smb_filename_tag ) - return smb_filename_tag[id]; - else - return ""; - } - -module SMB_tag; - -global log = open_log_file("smb-tag") &redef; - -const well_known_files = { - "\\IPC$", - "\\print$", - "\\LANMAN", - "\\atsvc", - "\\AudioSrv", - "\\browser", - "\\cert", - "\\Ctx_Winstation_API_Service", - "\\DAV", - "\\dnsserver", - "\\epmapper", - "\\eventlog", - "\\HydraLsPipe", - "\\InitShutdown", - "\\keysvc", - "\\locator", - "\\llsrpc", - "\\lsarpc", - "\\msgsvc", - "\\netdfs", - "\\netlogon", - "\\ntsvcs", - "\\policyagent", - "\\ipsec", - "\\ProfMapApi", - "\\protected_storage", - "\\ROUTER", - "\\samr", - "\\scerpc", - "\\SECLOGON", - "\\SfcApi", - "\\spoolss", - "\\srvsvc", - "\\ssdpsrv", - "\\svcctl", - "\\tapsrv", - "\\trkwks", - "\\W32TIME", - "\\W32TIME_ALT", - "\\winlogonrpc", - "\\winreg", - "\\winspipe", - "\\wkssvc", - "\\lbl.gov", - "\\LBL" -}; - -function well_known_file(n: string): string - { - n = to_lower(n); - local a = ""; - for ( p in well_known_files ) - { - if ( strstr(n, to_lower(p)) > 0 ) - if ( byte_len(p) > byte_len(a) ) - a = p; - } - return a; - } - -function add_to_smb_filename_tag(c: connection, name: string): bool - { - if ( name == "\\PIPE\\" || name == "" ) - return F; - - local id = c$id; - local orig_tag = smb_filename_tag[id]; - - local n = well_known_file(name); - if ( n == "" ) - { - if ( log_smb_tags ) - print log, fmt("%.6f %s regular file: \"%s\"", - network_time(), conn_id_string(c$id), name); - n = ""; - } - - n = fmt("\"%s\"", n); - - if ( orig_tag == "" ) - { - smb_filename_tag[id] = n; - } - else if ( strstr(orig_tag, n) == 0 ) - { - smb_filename_tag[id] = cat(orig_tag, ",", n); - } - - return T; - } - -event smb_com_nt_create_andx(c: connection, name: string) - { - add_to_smb_filename_tag(c, name); - } - -event smb_com_transaction(c: connection, is_orig: bool, subcmd: count, - name: string, data: string) - { - add_to_smb_filename_tag(c, name); - } - -event smb_com_transaction2(c: connection, is_orig: bool, subcmd: count, - name: string, data: string) - { - add_to_smb_filename_tag(c, name); - } - -event smb_get_dfs_referral(c: connection, max_referral_level: count, file_name: string) - { - add_to_smb_filename_tag(c, file_name); - } - -event smb_com_tree_connect_andx(c: connection, path: string, service: string) - { - local basic = sub(path, /.*\\/, "\\"); - if ( /\$$/ in basic ) - add_to_smb_filename_tag(c, basic); - } - -event delete_smb_tag(c: connection) - { - delete smb_filename_tag[c$id]; - } - -event connection_state_remove(c: connection) - { - if ( c$id in smb_filename_tag ) - { - if ( log_smb_tags ) - print log, fmt("conn %s start %.6f SMB [%s]", - conn_id_string(c$id), - c$start_time, - smb_filename_tag[c$id]); - event delete_smb_tag(c); - } - } diff --git a/policy.old/summaries/sun-rpc-summary.bro b/policy.old/summaries/sun-rpc-summary.bro deleted file mode 100644 index 9f0f376cfd..0000000000 --- a/policy.old/summaries/sun-rpc-summary.bro +++ /dev/null @@ -1,46 +0,0 @@ -@load app-summary -@load rpc - -redef capture_filters += { - ["port-map"] = "port 111", - ["nfs"] = "port 2049", - # UDP packets are often fragmented - ["nfs-frag"] = "ip[6:2] & 0x1fff != 0", -}; - -module SUN_RPC_summary; - -export { - global log = open_log_file("sun-rpc-summary") &redef; -} - -global nfs_status: table[conn_id] of count; - -event nfs_reply_status(n: connection, status: count) - { - # print fmt("%.6f status = %d", network_time(), status); - nfs_status[n$id] = status; - } - -event rpc_call(c: connection, prog: count, ver: count, proc: count, status: count, - start_time: time, call_len: count, reply_len: count) - { - # print fmt("%.6f rpc_call", network_time()); - local prog_name = RPC::program_name(prog); - local nfs_st = "n/a"; - if ( c$id in nfs_status ) - { - nfs_st = fmt("%d", nfs_status[c$id]); - # print fmt("%.6f get_status = %s", network_time(), nfs_st); - delete nfs_status[c$id]; - } - - print_app_summary(log, c$id, c$start_time, - fmt("%sv%d/%s", - prog_name, - ver, - RPC::procedure_name(prog, ver, proc)), - start_time, - 1, call_len, status == RPC_TIMEOUT ? 0 : 1, reply_len, - fmt("rpc_status %s nfs_status %s", status, nfs_st)); - } diff --git a/policy.old/synflood.bro b/policy.old/synflood.bro deleted file mode 100644 index 3c2ecde4b7..0000000000 --- a/policy.old/synflood.bro +++ /dev/null @@ -1,131 +0,0 @@ -# $Id: synflood.bro 4054 2007-03-05 21:45:58Z vern $ - -@load notice - -redef enum Notice += { - SynFloodStart, # start of syn-flood against a certain victim - SynFloodEnd, # end of syn-flood against a certain victim - SynFloodStatus, # report of ongoing syn-flood -}; - -# We report a syn-flood if more than SYNFLOOD_THRESHOLD new connections -# have been reported within the last SYNFLOOD_INTERVAL for a certain IP. -# (We sample the conns by one out of SYNFLOOD_SAMPLE_RATE, so the attempt -# counter is an estimated value.). If a victim is identified, we install a -# filter via install_dst_filter and sample the packets targeting it by -# SYNFLOOD_VICTIM_SAMPLE_RATE. -# -# Ongoing syn-floods are reported every SYNFLOOD_REPORT_INTERVAL. - -global SYNFLOOD_THRESHOLD = 15000 &redef; -global SYNFLOOD_INTERVAL = 60 secs &redef; -global SYNFLOOD_REPORT_INTERVAL = 1 mins &redef; - -# Sample connections by one out of x. -global SYNFLOOD_SAMPLE_RATE = 100 &redef; - -# Sample packets to known victims with probability x. -global SYNFLOOD_VICTIM_SAMPLE_RATE = 0.01 &redef; - -global conn_attempts: table[addr] of count &default = 0; -global victim_attempts: table[addr,addr] of count - &default = 0 &read_expire = 5mins; - -# We remember up to this many number of sources per victim. -global max_sources = 100; -global current_victims: table[addr] of set[addr] &read_expire = 60mins; -global accumulated_conn_attempts: table[addr] of count &default = 0; - -global sample_count = 0; -global interval_start: time = 0; - -# Using new_connection() can be quite expensive but connection_attempt() has -# a rather large lag that may lead to detecting flood too late. Additionally, -# it does not cover UDP/ICMP traffic. -event new_connection(c: connection) - { - if ( c$id$resp_h in current_victims ) - { - ++conn_attempts[c$id$resp_h]; - - local srcs = current_victims[c$id$resp_h]; - if ( length(srcs) < max_sources ) - add srcs[c$id$orig_h]; - return; - } - - if ( ++sample_count % SYNFLOOD_SAMPLE_RATE == 0 ) - { - local ip = c$id$resp_h; - - if ( ++conn_attempts[ip] * SYNFLOOD_SAMPLE_RATE > - SYNFLOOD_THRESHOLD ) - { - NOTICE([$note=SynFloodStart, $src=ip, - $msg=fmt("start of syn-flood against %s; sampling packets now", ip)]); - - add current_victims[ip][c$id$orig_h]; - - # Drop most packets to victim. - install_dst_addr_filter(ip, 0, - 1 - SYNFLOOD_VICTIM_SAMPLE_RATE); - # Drop all packets from victim. - install_src_addr_filter(ip, 0, 1.0); - } - } - } - -event check_synflood() - { - for ( ip in current_victims ) - { - accumulated_conn_attempts[ip] = - accumulated_conn_attempts[ip] + conn_attempts[ip]; - - if ( conn_attempts[ip] * (1 / SYNFLOOD_VICTIM_SAMPLE_RATE) < - SYNFLOOD_THRESHOLD ) - { - NOTICE([$note=SynFloodEnd, $src=ip, $n=length(current_victims[ip]), - $msg=fmt("end of syn-flood against %s; stopping sampling", - ip)]); - - delete current_victims[ip]; - uninstall_dst_addr_filter(ip); - uninstall_src_addr_filter(ip); - } - } - - clear_table(conn_attempts); - schedule SYNFLOOD_INTERVAL { check_synflood() }; - } - -event report_synflood() - { - for ( ip in current_victims ) - { - local est_num_conn = accumulated_conn_attempts[ip] * - (1 / SYNFLOOD_VICTIM_SAMPLE_RATE); - - local interv: interval; - - if ( interval_start != 0 ) - interv = network_time() - interval_start; - else - interv = SYNFLOOD_INTERVAL; - - NOTICE([$note=SynFloodStatus, $src=ip, $n=length(current_victims[ip]), - $msg=fmt("syn-flood against %s; estimated %.0f connections in last %s", - ip, est_num_conn, interv)]); - } - - clear_table(accumulated_conn_attempts); - - schedule SYNFLOOD_REPORT_INTERVAL { report_synflood() }; - interval_start = network_time(); - } - -event bro_init() - { - schedule SYNFLOOD_INTERVAL { check_synflood() }; - schedule SYNFLOOD_REPORT_INTERVAL { report_synflood() }; - } diff --git a/policy.old/targeted-scan.bro b/policy.old/targeted-scan.bro deleted file mode 100644 index 09922644ba..0000000000 --- a/policy.old/targeted-scan.bro +++ /dev/null @@ -1,114 +0,0 @@ -# $Id:$ -# -# Drop external hosts that continually bang away on a particular open port. -# -# Note that we time out identified scanners to avoid excessive memory -# utilitization in the event of a wide scan across address space. - -@load notice -@load site - -module TargetedScan; - -export { - redef enum Notice += { TargetedScan, }; - - # If true, then only consider traffic from external sources. - global external_only = T &redef; - - # Which ports to consider. - const ports = { 1433/tcp, } &redef; - - # If set, at least/most this many bytes need to be transferred for - # a connection using the given port. These are useful for example - # for inferring that SSH connections reflect password-guessing - # attempts. - const min_bytes: table[port] of count &redef; - const max_bytes: table[port] of count &redef; - - # If set, then this is the threshold for reportin accessing - # for a given service. - const port_threshold: table[port] of count &redef; - - # Otherwise, this is the threshold. - const general_threshold = 1000 &redef; - - # The data structure we use to track targeted probing. - # It's exported to enable redef'ing the &write_expire value. - global targeted_tries: table[addr, addr, port] of count - &default=0 &write_expire=10 min &redef; -} - -function delete_targeted_data(orig: addr, resp: addr, service: port) - { - delete targeted_tries[orig, resp, service]; - } - -function targeted_check(c: connection) - { - local id = c$id; - local orig = id$orig_h; - local resp = id$resp_h; - local service = ("ftp-data" in c$service) ? 20/tcp : id$resp_p; - - if ( service !in ports || (external_only && is_local_addr(orig)) ) - return; - - local bytes_xferred = c$orig$size + c$resp$size; - - if ( service in min_bytes && bytes_xferred < min_bytes[service] ) - return; - if ( service in max_bytes && bytes_xferred > max_bytes[service] ) - return; - - local cnt = ++targeted_tries[orig, resp, service]; - - if ( service in port_threshold ) - { - if ( cnt != port_threshold[service] ) - return; - } - - else if ( cnt != general_threshold ) - return; - - local svc = service in port_names ? - port_names[service] : fmt("%s", service); - - NOTICE([$note=TargetedScan, $src=orig, $dst=resp, $p=service, - $msg=fmt("targeted attack on service %s, count = %d", svc, cnt)]); - - # Since we've reported this host, we can stop tracking it. - delete targeted_tries[orig, resp, service]; - } - - -event connection_finished(c: connection) - { - targeted_check(c); - } - -event connection_rejected(c: connection) - { - targeted_check(c); - } - -event connection_half_finished(c: connection) - { - targeted_check(c); - } - -event connection_reset(c: connection) - { - targeted_check(c); - } - -event connection_partial_close(c: connection) - { - targeted_check(c); - } - -event connection_state_remove(c: connection) - { - targeted_check(c); - } diff --git a/policy.old/tcp.bro b/policy.old/tcp.bro deleted file mode 100644 index fd561180bb..0000000000 --- a/policy.old/tcp.bro +++ /dev/null @@ -1,6 +0,0 @@ -# Generic TCP connection processing. - -@load conn - -redef capture_filters += { ["tcp"] = "tcp[13] & 7 != 0" }; -# redef capture_filters += { ["tcp"] = "(tcp[13] & 7 != 0) or (ip6[53] & 7 != 0)" }; diff --git a/policy.old/terminate-connection.bro b/policy.old/terminate-connection.bro deleted file mode 100644 index 5242afaf6d..0000000000 --- a/policy.old/terminate-connection.bro +++ /dev/null @@ -1,77 +0,0 @@ -# $Id$ - -@load site -@load notice - -# Ugly: we need the following from conn.bro, but we can't soundly load -# it because it in turn loads us. -global full_id_string: function(c: connection): string; - -# TODO: this is a notice action filter but it shouldn't cause this -# script to be come a dependency on notice-action-filters.bro -# Figure out where to put this! -function drop_source_and_terminate(n: Notice::Info, a: Notice::Action): Notice::Action - { - if ( n?$conn ) - TerminateConnection::terminate_connection(n$conn); - - return NOTICE_DROP; - } - - -module TerminateConnection; - -export { - redef enum Notice += { - TerminatingConnection, # connection will be terminated - TerminatingConnectionIgnored, # connection terminated disabled - }; - - # Whether we're allowed (and/or are capable) to terminate connections - # using "rst". - const activate_terminate_connection = F &redef; - - # Terminate the given connection. - global terminate_connection: function(c: connection); - -} - -function terminate_connection(c: connection) - { - local id = c$id; - - if ( activate_terminate_connection ) - { - local local_init = is_local_addr(id$orig_h); - - local term_cmd = fmt("rst %s -n 32 -d 20 %s %d %d %s %d %d", - local_init ? "-R" : "", - id$orig_h, id$orig_p, get_orig_seq(id), - id$resp_h, id$resp_p, get_resp_seq(id)); - - if ( reading_live_traffic() ) - system(term_cmd); - else - NOTICE([$note=TerminatingConnection, $conn=c, - $msg=term_cmd, $sub="first termination command"]); - - term_cmd = fmt("rst %s -r 2 -n 4 -s 512 -d 20 %s %d %d %s %d %d", - local_init ? "-R" : "", - id$orig_h, id$orig_p, get_orig_seq(id), - id$resp_h, id$resp_p, get_resp_seq(id)); - - if ( reading_live_traffic() ) - system(term_cmd); - else - NOTICE([$note=TerminatingConnection, $conn=c, - $msg=term_cmd, $sub="second termination command"]); - - NOTICE([$note=TerminatingConnection, $conn=c, - $msg=fmt("terminating %s", full_id_string(c))]); - } - - else - NOTICE([$note=TerminatingConnectionIgnored, $conn=c, - $msg=fmt("ignoring request to terminate %s", - full_id_string(c))]); - } diff --git a/policy.old/tftp.bro b/policy.old/tftp.bro deleted file mode 100644 index d1f3e43746..0000000000 --- a/policy.old/tftp.bro +++ /dev/null @@ -1,33 +0,0 @@ -# $Id: tftp.bro 4758 2007-08-10 06:49:23Z vern $ - -# Very simplistic - doesn't pick up the replies. - -@load notice -@load udp-common -@load site - -module TFTP; - -export { - redef enum Notice += { - OutboundTFTP, # outbound TFTP seen - }; -} - -redef capture_filters += { ["tftp"] = "udp port 69" }; - -global tftp_notice_count: table[addr] of count &default = 0 &read_expire = 7 days; - -event udp_request(u: connection) - { - if ( u$id$resp_p == 69/udp && u$id$orig_p >= 1024/udp ) - { - local src = u$id$orig_h; - local dst = u$id$resp_h; - - if ( is_local_addr(src) && ! is_local_addr(dst) && - ++tftp_notice_count[src] == 1 ) - NOTICE([$note=OutboundTFTP, $conn=u, - $msg=fmt("outbound TFTP: %s -> %s", src, dst)]); - } - } diff --git a/policy.old/time-machine/time-machine.bro b/policy.old/time-machine/time-machine.bro deleted file mode 100644 index 98e37437ae..0000000000 --- a/policy.old/time-machine/time-machine.bro +++ /dev/null @@ -1,278 +0,0 @@ -# $Id: time-machine.bro,v 1.1.2.8 2006/01/06 01:51:37 sommer Exp $ -# -# Low-level time-machine interface. - -@load notice - -module TimeMachine; - -export { - # Request to send us a connection. Automatically subscribes - # and suspends cut-off. - # - # start : time where to start searching (0 for as early as possible). - # in_mem: only scan TM's memory-buffer but not any on-disk data. - # descr: description to be written to log file to identify the query - # - # Returns tag of this query. - global request_connection: - function(c: connection, in_mem: bool, descr: string) : string; - - # id$orig_p = 0/tcp acts as wildcard. - global request_connection_id: - function(id: conn_id, start: time, in_mem: bool, descr: string) - : string; - - # Request to save connection to file in TM host. Automatically - # suspends cut-off. - # - # filename: destination file on TM host. - # start : time where to start searching (0 = as early as possible). - # in_mem : only scan TM's memory-buffer, but not any on-disk data. - global capture_connection: - function(filename: string, c: connection, in_mem: bool, - descr: string); - - # id$orig_p = 0/tcp acts as wildcard. - global capture_connection_id: - function(filename: string, id: conn_id, start: time, - in_mem: bool, descr: string); - - # Request to send everything involving a certain host to us. - # Always searches mem and disk buffers. - # - # host : address of host - # start: time where to start searching (0 for as early as possible). - # - # Returns tag of this query. - global request_addr: function(host: addr, start: time, - in_mem: bool, descr: string) : string; - - # Don't issue duplicate queries. Should be on for normal use; - # only need to turn off for benchmarking. - global filter_duplicates = T &redef; - - # Automatically issue suspend_cutoff as specified above. - # Should be on for normal use; off only used for benchmarking. - global auto_suspend_cutoff = T &redef; - - # Automatically subscribe as specified above. - # Should be on for normal use; off only used for benchmarking. - global auto_subscribe = F &redef; - - # Automatically set start time for query. - # Should be on for normal use; off only used for benchmarking. - global auto_set_start = T &redef; - - # Request to save everything involving a certain host. - # Always searches mem and disk buffers. - # - # filename: destination file on TM host. - # host : address of host - # start: time where to start searching (0 for as early as possible). - # - global capture_addr: function(filename: string, host: addr, - start: time, in_mem: bool, - descr: string); - - # Prevent the TM from cutting the connection off. - global suspend_cut_off: function(c: connection, descr: string); - - # id$orig_p = 0/tcp acts as wildcard. - global suspend_cut_off_id: function(id: conn_id, descr: string); - - type Direction: enum { - ORIG, # connections originating from host - RESP, # connections responded to by host - BOTH # independent of direction - }; - - # Change the TM class for given IP. - global set_class: function(host: addr, class: string, dir: Direction, - descr: string); - - # Revoke class assignment for IP. - global unset_class: function(host: addr, descr: string); - - # ID of this Bro instance for TM queries. Automatically set. - global feed_id = ""; -} - -global tag = 0; - -global cmds: table[string] of string &read_expire = 1 day; - -global command: event(cmd: string); -global descrs: table[string] of string; - -global profile: file; -global logfile = open_log_file("tm"); - -function id2str(id: conn_id, include_index: bool) : string - { - local index = ""; - if ( include_index ) - index = id$orig_p != 0/tcp ? "connection4 " : "connection3 "; - - if ( id$orig_p != 0/tcp) - return fmt("%s\"%s %s:%d %s:%d\"", index, - get_port_transport_proto(id$resp_p), - id$orig_h, id$orig_p, - id$resp_h, id$resp_p); - else - return fmt("%s\"%s %s %s:%d\"", index, - get_port_transport_proto(id$resp_p), - id$orig_h, - id$resp_h, id$resp_p); - } - -function issue_query(result: string, add_tag: bool, cmd: string, - start: time, in_mem: bool, sub: bool, descr: string) : string - { - local key = fmt("%s %s", result, cmd); - local qtag = ""; - - if ( key in cmds && filter_duplicates ) - return cmds[key]; - - if ( add_tag ) - { - qtag = fmt("t%x", ++tag); - result = fmt("%s tag %s", result, qtag); - } - - local range = ""; - - if ( time_to_double(start) > 0.0 && auto_set_start ) - { # We subtract a few seconds to allow for clock skew. - start = start - 2 secs; - range += fmt("start %.6f end 9876543210 ", start); - } - - if ( in_mem ) - range += "mem_only "; - - if ( sub ) - range += "subscribe "; - - local c = fmt("query %s %s %s", result, cmd, range); - descrs[c] = descr; - - if ( time_machine_profiling ) - print profile, fmt("%.6f %s %s", current_time(), - (qtag != "" ? qtag : "-"), c); - - event TimeMachine::command(c); - - cmds[key] = qtag; - - return qtag; - } - -function issue_command(cmd: string, descr: string) - { - if ( cmd in cmds && filter_duplicates ) - return; - - descrs[cmd] = descr; - event TimeMachine::command(cmd); - - cmds[cmd] = ""; - } - -function request_connection(c: connection, in_mem: bool, descr: string) : string - { - return request_connection_id(c$id, c$start_time, in_mem, descr); - } - -function request_connection_id(id: conn_id, start: time, in_mem: bool, - descr: string) : string - { - if ( auto_suspend_cutoff ) - suspend_cut_off_id(id, descr); - return issue_query(fmt("feed %s", feed_id), T, - fmt("index %s", id2str(id, T)), start, in_mem, - auto_subscribe, descr); - } - -function capture_connection(filename: string, c: connection, - in_mem: bool, descr: string) - { - capture_connection_id(filename, c$id, c$start_time, in_mem, descr); - } - -function capture_connection_id(filename: string, id: conn_id, start: time, - in_mem: bool, descr: string) - { - if ( auto_suspend_cutoff ) - suspend_cut_off_id(id, descr); - - issue_query(fmt("to_file \"%s\"", filename), F, - fmt("index %s", id2str(id, T)), - start, in_mem, auto_subscribe, descr); - } - -function request_addr(host: addr, start: time, in_mem: bool, descr: string) -: string - { - return issue_query(fmt("feed %s", feed_id), T, - fmt("index ip \"%s\"", host), start, in_mem, F, descr); - } - -function capture_addr(filename: string, host: addr, start: time, - in_mem: bool, descr: string) - { - issue_query(fmt("to_file \"%s\"", filename), F, - fmt("index ip \"%s\"", host), start, in_mem, F, descr); - } - -function suspend_cut_off(c: connection, descr: string) - { - suspend_cut_off_id(c$id, descr); - } - -function suspend_cut_off_id(id: conn_id, descr: string) - { - issue_command(fmt("suspend_cutoff %s", id2str(id, F)), descr); - } - -function set_class(host: addr, class: string, dir: Direction, descr: string) - { - local d = ""; - - if ( dir == ORIG ) - d = " orig"; - else if ( dir == RESP ) - d = " resp"; - - issue_command(fmt("set_dyn_class %s %s%s", host, class, d), descr); - } - -function unset_class(host: addr, descr: string) - { - issue_command(fmt("unset_dyn_class %s", host), descr); - } - -event command(cmd: string) - { - # We might not know the command if we're just relaying the event - # from external. - if ( cmd in descrs ) - { - local descr = descrs[cmd]; - delete descrs[cmd]; - - print logfile, fmt("%.6f %.6f [%s] %s", network_time(), current_time(), descr, cmd); - } - } - -event bro_init() - { - set_buf(logfile, F); - - # Create a feed ID that's unique across restarts w/ high probability. - feed_id = fmt("%s-%d-%d", gethostname(), getpid(), rand(100)); - - if ( time_machine_profiling ) - profile = open_log_file("tm-prof.queries"); - } diff --git a/policy.old/time-machine/tm-capture.bro b/policy.old/time-machine/tm-capture.bro deleted file mode 100644 index a322f25263..0000000000 --- a/policy.old/time-machine/tm-capture.bro +++ /dev/null @@ -1,91 +0,0 @@ -# $Id: tm-capture.bro,v 1.1.2.1 2006/01/04 03:52:02 sommer Exp $ -# -# For each non-scan alert, we can -# (a) tell the time-machine to permanently store the connection's packets -# (b) request the connection, to store the (reassembled) payload ourselves -# (c) request all other traffic from that IP within the last X hours -# (d) store all other traffic from that IP within the last X hours - -@load time-machine -@load tm-contents -@load notice -@load scan - -module TimeMachineCapture; - -export { - # Request past traffic. Set to 0 to disable. - # This does on-disk queries, potentially expensive. - const history_interval = 0 hrs &redef; - - # Capture past traffic. Set to 0 to disable. - # This does on-disk queries, potentially expensive. - const history_capture_interval = 0 hrs &redef; - - const ignore_notices: set[Notice] = { - Scan::AddressScan, - Scan::PortScan, - } &redef; -} - -@ifdef ( TimeMachineGap::ContentGapTmAndLink ) -redef ignore_notices += { - TimeMachineGap::ContentGapTmAndLink, - TimeMachineGap::ContentGapSolved, -}; -@endif - -global hosts: set[addr] &create_expire = history_capture_interval; - -global dbg = open_log_file("tm-capture"); - -event notice_alarm(n: notice_info, action: NoticeAction) - { - if ( n$note in ignore_notices ) - return; - - if ( ! n?$id ) - return; - - if ( n?$conn && is_external_connection(n$conn) ) - return; - - local id = n$id; - local start: time; - - if ( n?$conn ) - start = n$conn$start_time; - else if ( connection_exists(id) ) - start = lookup_connection(id)$start_time; - else - start = network_time() - 5 min; # shouldn't usually get here - - local tag = fmt("conn.%s", n$tag); - n$captured = tag; - - # It should be in the TM's memory. - TimeMachine::capture_connection_id(fmt("%s.pcap", tag), id, start, - T, "tm-capture"); - - if ( get_port_transport_proto(id$resp_p) == tcp ) - { - n$captured += " (contents)"; - TimeMachine::save_contents_id(tag, id, start, T, "tm-capture"); - } - - if ( n$src !in hosts ) - { - if ( history_interval != 0 sec ) - TimeMachine::request_addr(n$src, - network_time() - history_interval, F, - "tm-capture"); - - if ( history_capture_interval != 0secs ) - TimeMachine::capture_addr(fmt("host.%s.%s.pcap", - n$src, n$tag), n$src, - network_time() - history_capture_interval, F, - "tm-capture"); - - add hosts[n$src]; - } - } diff --git a/policy.old/time-machine/tm-class.bro b/policy.old/time-machine/tm-class.bro deleted file mode 100644 index 4d69308517..0000000000 --- a/policy.old/time-machine/tm-class.bro +++ /dev/null @@ -1,22 +0,0 @@ -# $Id:$ -# -# Changes the class for addresses that have generated alerts. - -@load time-machine -@load notice -@load scan - -event notice_alarm(n: notice_info, action: NoticeAction) - { - if ( ! n?$src ) - return; - - if ( n?$conn && is_external_connection(n$conn) ) - return; - - local class = "alarm"; - if ( n$note == Scan::AddressScan || n$note == Scan::PortScan ) - class = "scanner"; - - TimeMachine::set_class(n$src, class, TimeMachine::BOTH, "tm-class"); - } diff --git a/policy.old/time-machine/tm-contents.bro b/policy.old/time-machine/tm-contents.bro deleted file mode 100644 index ea921342ae..0000000000 --- a/policy.old/time-machine/tm-contents.bro +++ /dev/null @@ -1,111 +0,0 @@ -# $Id:$ -# -# Provides a function that requests a particular connection from the -# Time Machine and stores the subsequent reassembled payload into a -# local file. - -@load time-machine - -module TimeMachine; - -export { - global save_contents: - function(filename_prefix: string, c: connection, - in_mem: bool, descr: string); - - global save_contents_id: - function(filename_prefix: string, id: conn_id, start: time, - in_mem: bool, descr: string); - - # Raised when contents have been fully saved. - global contents_saved: - event(c: connection, orig_file: string, resp_file: string); - - const contents_dir = "tm-contents" &redef; - } - -# Table associating TM tag with filename. -global requested_conns: table[string] of string; - -type fnames: record { - orig: string; - resp: string; - orig_f: file; - resp_f: file; - }; - -global external_conns: table[conn_id] of fnames; - -function save_contents(filename_prefix: string, c: connection, - in_mem: bool, descr: string) - { - if ( is_external_connection(c) ) - return; - - save_contents_id(filename_prefix, c$id, c$start_time, in_mem, descr); - } - -function save_contents_id(filename_prefix: string, id: conn_id, start: time, - in_mem: bool, descr: string) - { - TimeMachine::suspend_cut_off_id(id, descr); - local qtag = TimeMachine::request_connection_id(id, start, in_mem, descr); - if ( qtag == "" ) - return; - - requested_conns[qtag] = filename_prefix; - } - -event connection_external(c: connection, tag: string) - { - if ( tag !in requested_conns ) - return; - - local fn = requested_conns[tag]; - local id = c$id; - local idstr = fmt("%s.%d-%s.%d", id$orig_h, id$orig_p, id$resp_h, id$resp_p); - - local orig_fn = fmt("%s/%s.%s.orig.dat", contents_dir, fn, idstr); - local resp_fn = fmt("%s/%s.%s.resp.dat", contents_dir, fn, idstr); - local orig_f = open(orig_fn); - local resp_f = open(resp_fn); - - set_contents_file(c$id, CONTENTS_ORIG, orig_f); - set_contents_file(c$id, CONTENTS_RESP, resp_f); - - delete requested_conns[tag]; - external_conns[c$id] = - [$orig=orig_fn, $resp=resp_fn, $orig_f=orig_f, $resp_f=resp_f]; - } - -event delayed_contents_saved(c: connection, orig_file: string, resp_file: string) - { - schedule 2 min { TimeMachine::contents_saved(c, orig_file, resp_file) }; - } - -event connection_state_remove(c: connection) - { - if ( ! is_external_connection(c) ) - return; - - if ( c$id !in external_conns ) - return; - - local fn = external_conns[c$id]; - - close(fn$orig_f); - close(fn$resp_f); - - # FIXME: We delay this a bit as there seems to be some race-condition - # with the file's data being flushed to disk. Not sure why, though. - # However, we need to delay indirectly through another event to - # install it into the global timer manager. - event delayed_contents_saved(c, fn$orig, fn$resp); - - delete external_conns[c$id]; - } - -event bro_init() - { - mkdir(contents_dir); - } diff --git a/policy.old/time-machine/tm-ftp.bro b/policy.old/time-machine/tm-ftp.bro deleted file mode 100644 index cc09fc8328..0000000000 --- a/policy.old/time-machine/tm-ftp.bro +++ /dev/null @@ -1,42 +0,0 @@ -# $Id: tm-ftp.bro,v 1.1.2.1 2006/01/04 03:55:48 sommer Exp $ -# -# For sensitive FTP connections, request the data connection from the TM. -# When we get it, we store the reassembled payload and run the file-analyzer -# (the latter is automatically done by ftp.bro). - -@load time-machine -@load tm-contents -@load ftp - -module TimeMachineFTP; - -global data_conns: table[count] of conn_id; - -event ftp_sensitive_file(c: connection, session: FTP::ftp_session_info, - filename: string) - { - if ( is_external_connection(c) ) - return; - - if ( session$id !in data_conns ) - # Should not happen, as transfer parameters need to be - # negotiated first. We let ftp.bro deal with this, though. - return; - - local id = data_conns[session$id]; - TimeMachine::save_contents(fmt("ftp.%s", session$id), c, T, "tm-ftp"); - } - -event ftp_connection_expected(c: connection, orig_h: addr, resp_h: addr, - resp_p: port, session: FTP::ftp_session_info) - { - data_conns[session$id] = - [$orig_h=orig_h, $orig_p=0/tcp, $resp_h=resp_h, $resp_p=resp_p]; - } - -event connection_state_remove(c: connection) - &priority = 5 # to be called before FTP's handler - { - if ( c$id in FTP::ftp_sessions ) - delete data_conns[FTP::ftp_sessions[c$id]$id]; - } diff --git a/policy.old/time-machine/tm-gap.bro b/policy.old/time-machine/tm-gap.bro deleted file mode 100644 index e97d6a848a..0000000000 --- a/policy.old/time-machine/tm-gap.bro +++ /dev/null @@ -1,127 +0,0 @@ -# $Id: tm-gap.bro,v 1.1.2.1 2006/01/05 22:38:37 sommer Exp $ -# -# When we see a content gap, we request the same connection from the TM. -# If we get it from there completely, fine. If not, we check whether the -# gap is at the same place as before, which would indicate that the packet -# was indeed missing on the link. - -@load conn-id -@load time-machine - -module TimeMachineGap; - -export { - # If true, we assume a BPF filter that includes *all* data packets. - const seeing_all_packets = F &redef; - - # Exclude these ports. - const ignore_ports = { 80/tcp, 22/tcp, 443/tcp }; - - redef enum Notice += { - # A connection has at least one gap that matches a gap - # on the link. - ContentGapTmAndLink, - - # A connection that had a gap on the link has been fully - # received from the TM. - ContentGapSolved, - }; -} - -type gap : record { - is_orig: bool; - seq: count; - length: count; -}; - -# Remembers the first gap per connection. -# (FIXME: Would it make sense to remember all gaps?) -global conns: table[conn_id] of gap; - -global f = open_log_file("gap"); - -event content_gap(c: connection, is_orig: bool, seq: count, length: count) - { - if ( ! is_external_connection(c) ) - { - if ( c$id in conns ) - # We already requested the conn. - return; - - if ( c$id$resp_p in ignore_ports ) - return; - - # It only makes sense to request the connection if we are - # not just analyzing TCP control packets for it. There's - # no perfect way to determine whether we do so but, as a - # heuristic, we assume that we are supposed to see data - # packets if: - # - # (1) the service port is well-known for one of our analyzers - # (because then the analyzer script is loaded which extends - # the capture filter accordingly; or - # (2) the user explicitly tells us they are using a filter that - # includes all packets (e.g., DPD); or - # (3) (special case) it's an HTTP reply, but we only - # load http-request. - - if ( ! seeing_all_packets ) - { - if ( c$id$resp_p !in dpd_analyzer_ports ) - return; - - if ( c$id$resp_p in dpd_analyzer_ports && ! is_orig && - ANALYZER_HTTP in dpd_analyzer_ports[c$id$resp_p]) - { -@ifdef ( process_HTTP_replies ) - if ( ! process_HTTP_replies ) -@endif - return; - } - } - - local g: gap = [$is_orig=is_orig, $seq=seq, $length=length]; - conns[c$id] = g; - - # Should be in TM's memory. - TimeMachine::request_connection(c, T, "tm-gap"); - - print f, "ask", id_string(c$id); - } - - else - { # a gap in a connection from the TM - if ( c$id !in conns ) - # Will be reported as ContentGap by weird.bro. - return; - - local h = conns[c$id]; - - if ( h$is_orig == is_orig && h$seq == seq && h$length == length ) - { - NOTICE([$note=ContentGapTmAndLink, $conn=c, - $msg=fmt("%s same content gap on link and from time-machine (%s %d/%d)", - id_string(c$id), - is_orig ? ">" : "<", seq, length)]); - } - - delete conns[c$id]; - } - } - -event connection_external(c: connection, tag: string) - { - if ( c$id in conns ) - print f, "got", id_string(c$id); - } - -event connection_state_remove(c: connection) - { - if ( c$id in conns && is_external_connection(c) ) - { # It's still in the table, so we got it completely. Yippie! - NOTICE([$note=ContentGapSolved, $conn=c, - $msg=fmt("%s content gap(s) solved by time-machine", - id_string(c$id))]); - delete conns[c$id]; - } - } diff --git a/policy.old/time-machine/tm-http.bro b/policy.old/time-machine/tm-http.bro deleted file mode 100644 index ad9d997ffc..0000000000 --- a/policy.old/time-machine/tm-http.bro +++ /dev/null @@ -1,18 +0,0 @@ -# $Id: tm-http.bro,v 1.1.2.1 2005/11/29 21:39:05 sommer Exp $ -# -# Requests connections from time-machine for which we have seen a sensitive URI. - -@load http -@load time-machine - -redef notice_policy += { - [$pred(a: notice_info) = - { - if ( a$note == HTTP::HTTP_SensitiveURI && - a?$conn && ! is_external_connection(a$conn) ) - TimeMachine::request_connection(a$conn, T, "tm-http"); - return F; - }, - $result = NOTICE_FILE, # irrelevant, since we always return F - $priority = 1] -}; diff --git a/policy.old/trw-impl.bro b/policy.old/trw-impl.bro deleted file mode 100644 index a93782d11c..0000000000 --- a/policy.old/trw-impl.bro +++ /dev/null @@ -1,191 +0,0 @@ -# $Id: trw.bro 2911 2006-05-06 17:58:43Z vern $ - -@load notice -@load port-name -@load hot - -module TRW; - -export { - redef enum Notice += { - TRWAddressScan, # source flagged as scanner by TRW algorithm - TRWScanSummary, # summary of scanning activities reported by TRW - }; - - # Activate TRW if T. - global use_TRW_algorithm = F &redef; - - # Tell TRW not to flag a friendly remote. - global do_not_flag_friendly_remotes = T &redef; - - # Set of services for outbound connections that are possibly triggered - # by incoming connections. - const triggered_outbound_services = { ident, finger, 20/tcp, } &redef; - - # The following correspond to P_D and P_F in the TRW paper, i.e., the - # desired detection and false positive probabilities. - global target_detection_prob = 0.99 &redef; - global target_false_positive_prob = 0.01 &redef; - - # Given a legitimate remote, the probability that its connection - # attempt will succeed. - global theta_zero = 0.8 &redef; - - # Given a scanner, the probability that its connection attempt - # will succeed. - global theta_one = 0.2 &redef; - - - # These variables the user usually won't alter, except they - # might want to adjust the expiration times, which is why - # they're exported here. - global scan_sources: set[addr] &write_expire = 1 hr; - global benign_sources: set[addr] &write_expire = 1 hr; - - global failed_locals: set[addr, addr] &write_expire = 30 mins; - global successful_locals: set[addr, addr] &write_expire = 30 mins; - - global lambda: table[addr] of double - &default = 1.0 &write_expire = 30 mins; - global num_scanned_locals: - table[addr] of count &default = 0 &write_expire = 30 mins; - - # Function called to perform TRW analysis. - global check_TRW_scan: function(c: connection, state: string, - reverse: bool): bool; -} - -# Set of remote hosts that have been successfully accessed by local hosts. -global friendly_remotes: set[addr] &read_expire = 30 mins; - -# Set of local honeypot hosts - for internal use at LBL. -global honeypot: set[addr]; - -# Approximate solutions for upper and lower thresholds. -global eta_zero: double; # initialized when Bro starts -global eta_one: double; - -event bro_init() - { - eta_zero = - (1 - target_detection_prob) / (1 - target_false_positive_prob); - eta_one = target_detection_prob / target_false_positive_prob; - } - - -event TRW_scan_summary(orig: addr) - { - NOTICE([$note=TRWScanSummary, $src=orig, - $msg=fmt("%s scanned a total of %d hosts", - orig, num_scanned_locals[orig])]); - } - -function check_TRW_scan(c: connection, state: string, reverse: bool): bool - { - local id = c$id; - - local service = "ftp-data" in c$service ? 20/tcp - : (reverse ? id$orig_p : id$resp_p); - local orig = reverse ? id$resp_h : id$orig_h; - local resp = reverse ? id$orig_h : id$resp_h; - local outbound = is_local_addr(orig); - - # Mark a remote as friendly if it is successfully accessed by - # a local with protocols other than triggered_outbound_services. - # XXX There is an ambiguity to determine who initiated a - # connection when the status is "OTH". - if ( outbound ) - { - if ( resp !in scan_sources && - service !in triggered_outbound_services && - orig !in honeypot && state != "OTH" ) - add friendly_remotes[resp]; - - return F; - } - - if ( orig in scan_sources ) - return T; - - if ( orig in benign_sources ) - return F; - - if ( do_not_flag_friendly_remotes && orig in friendly_remotes ) - return F; - - # Start TRW evaluation. - local flag = +0; - local resp_byte = reverse ? c$orig$size : c$resp$size; - local established = T; - - if ( state == "S0" || state == "REJ" || state == "OTH" || - (state == "RSTOS0" && resp_byte <= 0) ) - established = F; - - if ( ! established || resp in honeypot ) - { - if ( [orig, resp] !in failed_locals ) - { - flag = 1; - add failed_locals[orig, resp]; - } - } - - else if ( [orig, resp] !in successful_locals ) - { - flag = -1; - add successful_locals[orig, resp]; - } - - if ( flag == 0 ) - return F; - - local ratio = 1.0; - - # Update the corresponding likelihood ratio of orig. - if ( theta_zero <= 0 || theta_zero >= 1 || theta_one <= 0 || - theta_one >= 1 || theta_one >= theta_zero ) - { - # Error: theta_zero should be between 0 and 1. - # Log::error("bad theta_zero/theta_one in check_TRW_scan"); - use_TRW_algorithm = F; - return F; - } - - if ( flag == 1 ) - ratio = (1 - theta_one) / (1 - theta_zero); - - if ( flag == -1 ) - ratio = theta_one / theta_zero; - - ++num_scanned_locals[orig]; - - lambda[orig] = lambda[orig] * ratio; - local updated_lambda = lambda[orig]; - - if ( target_detection_prob <= 0 || - target_detection_prob >= 1 || - target_false_positive_prob <= 0 || - target_false_positive_prob >= 1 ) - { - # Error: target probabilities should be between 0 and 1 - # Log::error("bad target probabilities in check_TRW_scan"); - use_TRW_algorithm = F; - return F; - } - - if ( updated_lambda > eta_one ) - { - add scan_sources[orig]; - NOTICE([$note=TRWAddressScan, $src=orig, - $msg=fmt("%s scanned a total of %d hosts", - orig, num_scanned_locals[orig])]); - schedule 1 day { TRW_scan_summary(orig) }; - return T; - } - - if ( updated_lambda < eta_zero ) - add benign_sources[orig]; - - return F; - } diff --git a/policy.old/trw.bro b/policy.old/trw.bro deleted file mode 100644 index 0ffe6246f7..0000000000 --- a/policy.old/trw.bro +++ /dev/null @@ -1,7 +0,0 @@ -# $Id: trw.bro 3297 2006-06-18 00:56:58Z vern $ -# -# Load this file to actiate TRW analysis. - -@load trw-impl - -redef TRW::use_TRW_algorithm = T; diff --git a/policy.old/udp-common.bro b/policy.old/udp-common.bro deleted file mode 100644 index a6ca5a647b..0000000000 --- a/policy.old/udp-common.bro +++ /dev/null @@ -1,46 +0,0 @@ -# $Id: udp-common.bro 4758 2007-08-10 06:49:23Z vern $ -# -# Performs generic UDP request/reply processing, but doesn't set -# the packet filter to capture all UDP traffic (use udp.bro for that). - -@load hot -@load conn -@load scan - -global udp_req_count: table[conn_id] of count &default = 0; -global udp_rep_count: table[conn_id] of count &default = 0; - -event udp_request(u: connection) - { - Scan::check_scan(u, F, F); -# if ( TRW::use_TRW_algorithm ) -# TRW::check_TRW_scan(u, conn_state(u, udp), F); - - Hot::check_hot(u, Hot::CONN_ATTEMPTED); - } - -event udp_reply(u: connection) - { - Scan::check_scan(u, T, F); -# if ( TRW::use_TRW_algorithm ) -# TRW::check_TRW_scan(u, conn_state(u, udp), F); - - Hot::check_hot(u, Hot::CONN_ESTABLISHED); - Hot::check_hot(u, Hot::CONN_FINISHED); - } - -function add_req_rep_addl(u: connection) - { - local id = u$id; - if ( udp_req_count[id] > 1 || udp_rep_count[id] > 1 ) - append_addl(u, fmt("[%d/%d]", udp_req_count[id], udp_rep_count[id])); - - delete udp_req_count[id]; - delete udp_rep_count[id]; - } - -event udp_session_done(u: connection) - { - add_req_rep_addl(u); - Hot::check_hot(u, Hot::CONN_FINISHED); - } diff --git a/policy.old/udp.bro b/policy.old/udp.bro deleted file mode 100644 index ae5f1834ad..0000000000 --- a/policy.old/udp.bro +++ /dev/null @@ -1,5 +0,0 @@ -# $Id: udp.bro 1103 2005-03-17 09:18:28Z vern $ - -@load udp-common - -redef capture_filters += { ["udp"] = "udp" }; diff --git a/policy.old/weird.bro b/policy.old/weird.bro deleted file mode 100644 index 245f6b79ac..0000000000 --- a/policy.old/weird.bro +++ /dev/null @@ -1,424 +0,0 @@ -# $Id: weird.bro 6452 2008-12-07 01:19:13Z vern $ - -@load notice -@load port-name - -module Weird; - -export { - redef enum Notice += { - WeirdActivity, # generic unusual, alarm-worthy activity - RetransmissionInconsistency, - # possible evasion; usually just chud - AckAboveHole, - # could mean packet drop; could also be chud - ContentGap, - # data has sequence hole; perhaps due to filtering - }; - - const weird_file = open_log_file("weird") &redef; - - type WeirdAction: enum { - WEIRD_UNSPECIFIED, WEIRD_IGNORE, WEIRD_FILE, - WEIRD_NOTICE_ALWAYS, WEIRD_NOTICE_PER_CONN, - WEIRD_NOTICE_PER_ORIG, WEIRD_NOTICE_ONCE, - }; - - # Which of the above actions lead to logging. For internal use. - const notice_actions = { - WEIRD_NOTICE_ALWAYS, WEIRD_NOTICE_PER_CONN, - WEIRD_NOTICE_PER_ORIG, WEIRD_NOTICE_ONCE, - }; - - const weird_action: table[string] of WeirdAction = { - # tcp_weird - ["above_hole_data_without_any_acks"] = WEIRD_FILE, - ["active_connection_reuse"] = WEIRD_FILE, - ["bad_HTTP_reply"] = WEIRD_FILE, - ["bad_HTTP_version"] = WEIRD_FILE, - ["bad_ICMP_checksum"] = WEIRD_FILE, - ["bad_ident_port"] = WEIRD_FILE, - ["bad_ident_reply"] = WEIRD_FILE, - ["bad_ident_request"] = WEIRD_FILE, - ["bad_rlogin_prolog"] = WEIRD_FILE, - ["bad_rsh_prolog"] = WEIRD_FILE, - ["rsh_text_after_rejected"] = WEIRD_FILE, - ["bad_RPC"] = WEIRD_NOTICE_PER_ORIG, - ["bad_RPC_program"] = WEIRD_FILE, - ["bad_SYN_ack"] = WEIRD_FILE, - ["bad_TCP_checksum"] = WEIRD_FILE, - ["bad_UDP_checksum"] = WEIRD_FILE, - ["baroque_SYN"] = WEIRD_FILE, - ["base64_illegal_encoding"] = WEIRD_FILE, - ["connection_originator_SYN_ack"] = WEIRD_FILE, - ["corrupt_tcp_options"] = WEIRD_FILE, - ["crud_trailing_HTTP_request"] = WEIRD_FILE, - ["data_after_reset"] = WEIRD_FILE, - ["data_before_established"] = WEIRD_FILE, - ["data_without_SYN_ACK"] = WEIRD_FILE, - ["DHCP_no_type_option"] = WEIRD_FILE, - ["DHCP_wrong_msg_type"] = WEIRD_FILE, - ["DHCP_wrong_op_type"] = WEIRD_FILE, - ["DNS_AAAA_neg_length"] = WEIRD_FILE, - ["DNS_Conn_count_too_large"] = WEIRD_FILE, - ["DNS_NAME_too_long"] = WEIRD_FILE, - ["DNS_RR_bad_length"] = WEIRD_FILE, - ["DNS_RR_length_mismatch"] = WEIRD_FILE, - ["DNS_RR_unknown_type"] = WEIRD_FILE, - ["DNS_label_forward_compress_offset"] = WEIRD_NOTICE_PER_ORIG, - ["DNS_label_len_gt_name_len"] = WEIRD_NOTICE_PER_ORIG, - ["DNS_label_len_gt_pkt"] = WEIRD_NOTICE_PER_ORIG, - ["DNS_label_too_long"] = WEIRD_NOTICE_PER_ORIG, - ["DNS_truncated_RR_rdlength_lt_len"] = WEIRD_FILE, - ["DNS_truncated_ans_too_short"] = WEIRD_FILE, - ["DNS_truncated_len_lt_hdr_len"] = WEIRD_FILE, - ["DNS_truncated_quest_too_short"] = WEIRD_FILE, - ["excessive_data_without_further_acks"] = WEIRD_FILE, - ["excess_RPC"] = WEIRD_NOTICE_PER_ORIG, - ["excessive_RPC_len"] = WEIRD_NOTICE_PER_ORIG, - ["FIN_advanced_last_seq"] = WEIRD_FILE, - ["FIN_after_reset"] = WEIRD_IGNORE, - ["FIN_storm"] = WEIRD_NOTICE_ALWAYS, - ["HTTP_bad_chunk_size"] = WEIRD_FILE, - ["HTTP_chunked_transfer_for_multipart_message"] = WEIRD_FILE, - ["HTTP_overlapping_messages"] = WEIRD_FILE, - ["HTTP_unknown_method"] = WEIRD_FILE, - ["HTTP_version_mismatch"] = WEIRD_FILE, - ["ident_request_addendum"] = WEIRD_FILE, - ["inappropriate_FIN"] = WEIRD_FILE, - ["inflate_data_failed"] = WEIRD_FILE, - ["inflate_failed"] = WEIRD_FILE, - ["invalid_irc_global_users_reply"] = WEIRD_FILE, - ["irc_invalid_command"] = WEIRD_FILE, - ["irc_invalid_dcc_message_format"] = WEIRD_FILE, - ["irc_invalid_invite_message_format"] = WEIRD_FILE, - ["irc_invalid_join_line"] = WEIRD_FILE, - ["irc_invalid_kick_message_format"] = WEIRD_FILE, - ["irc_invalid_line"] = WEIRD_FILE, - ["irc_invalid_mode_message_format"] = WEIRD_FILE, - ["irc_invalid_names_line"] = WEIRD_FILE, - ["irc_invalid_njoin_line"] = WEIRD_FILE, - ["irc_invalid_notice_message_format"] = WEIRD_FILE, - ["irc_invalid_oper_message_format"] = WEIRD_FILE, - ["irc_invalid_privmsg_message_format"] = WEIRD_FILE, - ["irc_invalid_reply_number"] = WEIRD_FILE, - ["irc_invalid_squery_message_format"] = WEIRD_FILE, - ["irc_invalid_topic_reply"] = WEIRD_FILE, - ["irc_invalid_who_line"] = WEIRD_FILE, - ["irc_invalid_who_message_format"] = WEIRD_FILE, - ["irc_invalid_whois_channel_line"] = WEIRD_FILE, - ["irc_invalid_whois_message_format"] = WEIRD_FILE, - ["irc_invalid_whois_operator_line"] = WEIRD_FILE, - ["irc_invalid_whois_user_line"] = WEIRD_FILE, - ["irc_line_size_exceeded"] = WEIRD_FILE, - ["irc_line_too_short"] = WEIRD_FILE, - ["irc_too_many_invalid"] = WEIRD_FILE, - ["line_terminated_with_single_CR"] = WEIRD_FILE, - ["line_terminated_with_single_LF"] = WEIRD_FILE, - ["malformed_ssh_identification"] = WEIRD_FILE, - ["malformed_ssh_version"] = WEIRD_FILE, - ["matching_undelivered_data"] = WEIRD_FILE, - ["multiple_HTTP_request_elements"] = WEIRD_FILE, - ["multiple_RPCs"] = WEIRD_NOTICE_PER_ORIG, - ["non_IPv4_packet"] = WEIRD_NOTICE_ONCE, - ["NUL_in_line"] = WEIRD_FILE, - ["originator_RPC_reply"] = WEIRD_NOTICE_PER_ORIG, - ["partial_finger_request"] = WEIRD_FILE, - ["partial_ftp_request"] = WEIRD_FILE, - ["partial_ident_request"] = WEIRD_FILE, - ["partial_RPC"] = WEIRD_NOTICE_PER_ORIG, - ["partial_RPC_request"] = WEIRD_FILE, - ["pending_data_when_closed"] = WEIRD_FILE, - ["pop3_bad_base64_encoding"] = WEIRD_FILE, - ["pop3_client_command_unknown"] = WEIRD_FILE, - ["pop3_client_sending_server_commands"] = WEIRD_FILE, - ["pop3_malformed_auth_plain"] = WEIRD_FILE, - ["pop3_server_command_unknown"] = WEIRD_FILE, - ["pop3_server_sending_client_commands"] = WEIRD_FILE, - ["possible_split_routing"] = WEIRD_FILE, - ["premature_connection_reuse"] = WEIRD_FILE, - ["repeated_SYN_reply_wo_ack"] = WEIRD_FILE, - ["repeated_SYN_with_ack"] = WEIRD_FILE, - ["responder_RPC_call"] = WEIRD_NOTICE_PER_ORIG, - ["rlogin_text_after_rejected"] = WEIRD_FILE, - ["RPC_rexmit_inconsistency"] = WEIRD_FILE, - ["RPC_underflow"] = WEIRD_FILE, - ["RST_storm"] = WEIRD_NOTICE_ALWAYS, - ["RST_with_data"] = WEIRD_FILE, # PC's do this - ["simultaneous_open"] = WEIRD_NOTICE_PER_CONN, - ["spontaneous_FIN"] = WEIRD_IGNORE, - ["spontaneous_RST"] = WEIRD_IGNORE, - ["SMB_parsing_error"] = WEIRD_FILE, - ["no_smb_session_using_parsesambamsg"] = WEIRD_FILE, - ["smb_andx_command_failed_to_parse"] = WEIRD_FILE, - ["transaction_subcmd_missing"] = WEIRD_FILE, - ["SSLv3_data_without_full_handshake"] = WEIRD_FILE, - ["unexpected_SSLv3_record"] = WEIRD_FILE, - ["successful_RPC_reply_to_invalid_request"] = WEIRD_NOTICE_PER_ORIG, - ["SYN_after_close"] = WEIRD_FILE, - ["SYN_after_partial"] = WEIRD_NOTICE_PER_ORIG, - ["SYN_after_reset"] = WEIRD_FILE, - ["SYN_inside_connection"] = WEIRD_FILE, - ["SYN_seq_jump"] = WEIRD_FILE, - ["SYN_with_data"] = WEIRD_FILE, - ["TCP_christmas"] = WEIRD_FILE, - ["truncated_ARP"] = WEIRD_FILE, - ["truncated_NTP"] = WEIRD_FILE, - ["UDP_datagram_length_mismatch"] = WEIRD_NOTICE_PER_ORIG, - ["unexpected_client_HTTP_data"] = WEIRD_FILE, - ["unexpected_multiple_HTTP_requests"] = WEIRD_FILE, - ["unexpected_server_HTTP_data"] = WEIRD_FILE, - ["unmatched_HTTP_reply"] = WEIRD_FILE, - ["unpaired_RPC_response"] = WEIRD_FILE, - ["unsolicited_SYN_response"] = WEIRD_IGNORE, - ["window_recision"] = WEIRD_FILE, - ["double_%_in_URI"] = WEIRD_FILE, - ["illegal_%_at_end_of_URI"] = WEIRD_FILE, - ["unescaped_%_in_URI"] = WEIRD_FILE, - ["unescaped_special_URI_char"] = WEIRD_FILE, - - ["UDP_zone_transfer"] = WEIRD_NOTICE_ONCE, - - ["deficit_netbios_hdr_len"] = WEIRD_FILE, - ["excess_netbios_hdr_len"] = WEIRD_FILE, - ["netbios_client_session_reply"] = WEIRD_FILE, - ["netbios_raw_session_msg"] = WEIRD_FILE, - ["netbios_server_session_request"] = WEIRD_FILE, - ["unknown_netbios_type"] = WEIRD_FILE, - - # flow_weird - ["excessively_large_fragment"] = WEIRD_NOTICE_ALWAYS, - - # Code Red generates slews ... - ["excessively_small_fragment"] = WEIRD_NOTICE_PER_ORIG, - - ["fragment_inconsistency"] = WEIRD_NOTICE_ALWAYS, - ["fragment_overlap"] = WEIRD_NOTICE_ALWAYS, - ["fragment_protocol_inconsistency"] = WEIRD_NOTICE_ALWAYS, - ["fragment_size_inconsistency"] = WEIRD_NOTICE_ALWAYS, - ["fragment_with_DF"] = WEIRD_FILE, # these do indeed happen! - ["incompletely_captured_fragment"] = WEIRD_NOTICE_ALWAYS, - - # net_weird - ["bad_IP_checksum"] = WEIRD_FILE, - ["bad_TCP_header_len"] = WEIRD_FILE, - ["internally_truncated_header"] = WEIRD_NOTICE_ALWAYS, - ["truncated_IP"] = WEIRD_FILE, - ["truncated_header"] = WEIRD_FILE, - - # generated by policy script - ["Land_attack"] = WEIRD_NOTICE_PER_ORIG, - ["bad_pm_port"] = WEIRD_NOTICE_PER_ORIG, - } &redef; - - # table that maps weird types into a function that should be called - # to determine the action. - const weird_action_filters: - table[string] of function(c: connection): WeirdAction &redef; - - const weird_ignore_host: set[addr, string] &redef; - - # But don't ignore these (for the weird file), it's handy keeping - # track of clustered checksum errors. - const weird_do_not_ignore_repeats = { - "bad_IP_checksum", "bad_TCP_checksum", "bad_UDP_checksum", - "bad_ICMP_checksum", - } &redef; -} - -# id/msg pairs that should be ignored (because the problem has already -# been reported). -global weird_ignore: table[string] of set[string] &write_expire = 10 min; - -# For WEIRD_NOTICE_PER_CONN. -global did_notice_conn: set[addr, port, addr, port, string] - &read_expire = 1 day; - -# For WEIRD_NOTICE_PER_ORIG. -global did_notice_orig: set[addr, string] &read_expire = 1 day; - -# For WEIRD_NOTICE_ONCE. -global did_weird_log: set[string] &read_expire = 1 day; - -global did_inconsistency_msg: set[conn_id]; - -function weird_id_string(id: conn_id): string - { - return fmt("%s > %s", - endpoint_id(id$orig_h, id$orig_p), - endpoint_id(id$resp_h, id$resp_p)); - } - -# Used to pass the optional connection into report_weird(). -global current_conn: connection; - -function report_weird(t: time, name: string, id: string, have_conn: bool, - addl: string, action: WeirdAction, no_log: bool) - { - if ( action == WEIRD_IGNORE || - (id in weird_ignore && name in weird_ignore[id]) ) - return; - - local msg = id; - - if ( action == WEIRD_UNSPECIFIED ) - { - if ( name in weird_action ) - { - action = weird_action[name]; - if ( action == WEIRD_IGNORE ) - return; - - msg = fmt("%s: %s", msg, name); - } - else - { - action = WEIRD_NOTICE_ALWAYS; - msg = fmt("** %s: %s", msg, name); - } - } - else - msg = fmt("%s: %s", msg, name); - - if ( addl != "" ) - msg = fmt("%s (%s)", msg, addl); - - if ( action in notice_actions && ! no_log ) - { - if ( have_conn ) - NOTICE([$note=WeirdActivity, $conn=current_conn, - $msg=msg]); - else - NOTICE([$note=WeirdActivity, $msg=msg]); - } - - else if ( id != "" && name !in weird_do_not_ignore_repeats ) - { - if ( id !in weird_ignore ) - weird_ignore[id] = set() &mergeable; - - add weird_ignore[id][name]; - } - - print weird_file, fmt("%.6f %s", t, msg); - } - -function report_weird_conn(t: time, name: string, id: string, addl: string, - c: connection) - { - if ( [c$id$orig_h, name] in weird_ignore_host || - [c$id$resp_h, name] in weird_ignore_host ) - return; - - local no_log = F; - local action = WEIRD_UNSPECIFIED; - - if ( name in weird_action ) - { - if ( name in weird_action_filters ) - action = weird_action_filters[name](c); - - if ( action == WEIRD_UNSPECIFIED ) - action = weird_action[name]; - - local cid = c$id; - - if ( action == WEIRD_NOTICE_PER_CONN ) - { - if ( [cid$orig_h, cid$orig_p, cid$resp_h, cid$resp_p, name] in did_notice_conn ) - no_log = T; - else - add did_notice_conn[cid$orig_h, cid$orig_p, cid$resp_h, cid$resp_p, name]; - } - - else if ( action == WEIRD_NOTICE_PER_ORIG ) - { - if ( [c$id$orig_h, name] in did_notice_orig ) - no_log = T; - else - add did_notice_orig[c$id$orig_h, name]; - } - - else if ( action == WEIRD_NOTICE_ONCE ) - { - if ( name in did_weird_log ) - no_log = T; - else - add did_weird_log[name]; - } - } - - current_conn = c; - report_weird(t, name, id, T, addl, action, no_log); - } - -function report_weird_orig(t: time, name: string, id: string, orig: addr) - { - local no_log = F; - local action = WEIRD_UNSPECIFIED; - - if ( name in weird_action ) - { - action = weird_action[name]; - if ( action == WEIRD_NOTICE_PER_ORIG ) - { - if ( [orig, name] in did_notice_orig ) - no_log = T; - else - add did_notice_orig[orig, name]; - } - } - - report_weird(t, name, id, F, "", action, no_log); - } - -event conn_weird(name: string, c: connection) - { - report_weird_conn(network_time(), name, weird_id_string(c$id), "", c); - } - -event conn_weird_addl(name: string, c: connection, addl: string) - { - report_weird_conn(network_time(), name, weird_id_string(c$id), addl, c); - } - -event flow_weird(name: string, src: addr, dst: addr) - { - report_weird_orig(network_time(), name, fmt("%s -> %s", src, dst), src); - } - -event net_weird(name: string) - { - report_weird(network_time(), name, "", F, "", WEIRD_UNSPECIFIED, F); - } - -event rexmit_inconsistency(c: connection, t1: string, t2: string) - { - if ( c$id !in did_inconsistency_msg ) - { - NOTICE([$note=RetransmissionInconsistency, $conn=c, - $msg=fmt("%s rexmit inconsistency (%s) (%s)", - weird_id_string(c$id), t1, t2)]); - add did_inconsistency_msg[c$id]; - } - } - -event ack_above_hole(c: connection) - { - NOTICE([$note=AckAboveHole, $conn=c, - $msg=fmt("%s ack above a hole", weird_id_string(c$id))]); - } - -event content_gap(c: connection, is_orig: bool, seq: count, length: count) - { - NOTICE([$note=ContentGap, $conn=c, - $msg=fmt("%s content gap (%s %d/%d)%s", - weird_id_string(c$id), is_orig ? ">" : "<", seq, length, - is_external_connection(c) ? " [external]" : "")]); - } - -event connection_state_remove(c: connection) - { - delete weird_ignore[weird_id_string(c$id)]; - delete did_inconsistency_msg[c$id]; - } diff --git a/policy.old/worm.bro b/policy.old/worm.bro deleted file mode 100644 index 18e9649096..0000000000 --- a/policy.old/worm.bro +++ /dev/null @@ -1,117 +0,0 @@ -# $Id: worm.bro 4758 2007-08-10 06:49:23Z vern $ - -@load notice -@load site - -# signatures.bro needs this. -global is_worm_infectee: function(ip: addr) : bool; - -@load signatures - -redef enum Notice += { - LocalWorm, # worm seen in local host - RemoteWorm, # worm seen in remote host -}; - -# redef capture_filters += { ["worm"] = "tcp dst port 80" }; - -const worm_log = open_log_file("worm") &redef; - -# Maps types of worms to URI patterns. -const worm_types: table[string] of pattern = { - ["Code Red 1"] = /\.id[aq]\?.*NNNNNNNNNNNNN/, - ["Code Red 2"] = /\.id[aq]\?.*XXXXXXXXXXXXX/, - ["Nimda"] = /\/scripts\/root\.exe\?\/c\+tftp/ | - /\/MSADC\/root.exe\?\/c\+dir/ | - /cool\.dll.*httpodbc\.dll/, # 29Oct01 Nimda variant -} &redef; - -# Maps signatures to worm types. -const worm_sigs: table[string] of string = { - ["slammer"] = "Slammer", - ["nimda"] = "Nimda", - ["bagle-bc"] = "Bagle.bc" -}; - -# We handle these ourselves. -redef signature_actions += { - ["codered1"] = SIG_IGNORE, - ["codered2"] = SIG_IGNORE, - ["slammer"] = SIG_IGNORE, - ["nimda"] = SIG_IGNORE, - ["bagle-bc"] = SIG_IGNORE -}; - -# Indexed by infectee. -global worm_list: table[addr] of count &default=0 &read_expire = 2 days; - -# Indexed by infectee and type of worm. -global worm_type_list: table[addr, string] of count - &default=0 &read_expire = 2 days; - -# Invoked each time a new infectee (or a new type of worm for an existing -# infectee) is seen. For the first instance of any type for a new infectee, -# two events will be generated, one with worm_type of "first instance", -# and another with the particular worm type. -global worm_infectee_seen: event(c: connection, is_local: bool, worm_type: string); - -# Invoked whenever connection c has included a URI of worm type "worm_type". -event worm_instance(c: connection, worm_type: string) - { - local id = c$id; - local src = id$orig_h; - local is_local = is_local_addr(src); - - if ( ++worm_list[src] == 1 ) - event worm_infectee_seen(c, is_local, "first instance"); - - if ( ++worm_type_list[src, worm_type] == 1 ) - event worm_infectee_seen(c, is_local, worm_type); - } - -event worm_infectee_seen(c: connection, is_local: bool, worm_type: string) - { - if ( worm_type == "first instance" ) - return; # just do the reporting for the specific type - - local infectee = c$id$orig_h; - local where = is_local ? "local" : "remote"; - local msg = fmt("%s %s worm source: %s", where, worm_type, infectee); - - if ( is_local ) - NOTICE([$note=LocalWorm, $conn=c, $src=infectee, - $msg=msg, $sub=worm_type]); - else - NOTICE([$note=RemoteWorm, $conn=c, $src=infectee, - $msg=msg, $sub=worm_type]); - - print worm_log, fmt("%.6f %s", network_time(), msg); - } - -event http_request(c: connection, method: string, - original_URI: string, unescaped_URI: string, version: string) - { - # It's a pity to do this as a loop. Better would be if Bro could - # search the patterns as one large RE and note which matched. - - for ( wt in worm_types ) - if ( worm_types[wt] in unescaped_URI ) - event worm_instance(c, wt); - } - -event signature_match(state: signature_state, msg: string, data: string) - { - if ( state$id in worm_sigs ) - event worm_instance(state$conn, worm_sigs[state$id]); - } - -# Ignore "weird" events, we get some due to the capture_filter above that -# only captures the client side of an HTTP session. -event conn_weird(name: string, c: connection) - { - } - -function is_worm_infectee(ip: addr): bool - { - return ip in worm_list; - } diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index d834c08053..6d6faf7b4a 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -2,6 +2,7 @@ include(InstallPackageConfigFile) install(DIRECTORY ./ DESTINATION ${BRO_SCRIPT_INSTALL_PATH} FILES_MATCHING PATTERN "site/local*" EXCLUDE + PATTERN "test-all-policy.bro" EXCLUDE PATTERN "*.bro" PATTERN "*.sig" PATTERN "*.fp" diff --git a/scripts/base/frameworks/cluster/__load__.bro b/scripts/base/frameworks/cluster/__load__.bro index 03262d3d75..0f9003514d 100644 --- a/scripts/base/frameworks/cluster/__load__.bro +++ b/scripts/base/frameworks/cluster/__load__.bro @@ -1,7 +1,7 @@ # Load the core cluster support. @load ./main -@if ( Cluster::node != "" ) +@if ( Cluster::is_enabled() ) # Give the node being started up it's peer name. redef peer_description = Cluster::node; @@ -9,10 +9,10 @@ redef peer_description = Cluster::node; # Add a cluster prefix. @prefixes += cluster -## If this script isn't found anywhere, the cluster bombs out. -## Loading the cluster framework requires that a script by this name exists -## somewhere in the BROPATH. The only thing in the file should be the -## cluster definition in the :bro:id:`Cluster::nodes` variable. +# If this script isn't found anywhere, the cluster bombs out. +# Loading the cluster framework requires that a script by this name exists +# somewhere in the BROPATH. The only thing in the file should be the +# cluster definition in the :bro:id:`Cluster::nodes` variable. @load cluster-layout @if ( Cluster::node in Cluster::nodes ) @@ -21,22 +21,22 @@ redef peer_description = Cluster::node; # Don't load the listening script until we're a bit more sure that the # cluster framework is actually being enabled. -@load frameworks/communication/listen-clear +@load frameworks/communication/listen ## Set the port that this node is supposed to listen on. -redef Communication::listen_port_clear = Cluster::nodes[Cluster::node]$p; +redef Communication::listen_port = Cluster::nodes[Cluster::node]$p; -@if ( Cluster::nodes[Cluster::node]$node_type == Cluster::MANAGER ) +@if ( Cluster::local_node_type() == Cluster::MANAGER ) @load ./nodes/manager @endif -@if ( Cluster::nodes[Cluster::node]$node_type == Cluster::PROXY ) +@if ( Cluster::local_node_type() == Cluster::PROXY ) @load ./nodes/proxy @endif -@if ( Cluster::nodes[Cluster::node]$node_type == Cluster::WORKER ) +@if ( Cluster::local_node_type() == Cluster::WORKER ) @load ./nodes/worker @endif @endif -@endif \ No newline at end of file +@endif diff --git a/scripts/base/frameworks/cluster/main.bro b/scripts/base/frameworks/cluster/main.bro index f6066e5800..1e89e9b2a7 100644 --- a/scripts/base/frameworks/cluster/main.bro +++ b/scripts/base/frameworks/cluster/main.bro @@ -1,29 +1,71 @@ +##! A framework for establishing and controlling a cluster of Bro instances. +##! In order to use the cluster framework, a script named +##! ``cluster-layout.bro`` must exist somewhere in Bro's script search path +##! which has a cluster definition of the :bro:id:`Cluster::nodes` variable. +##! The ``CLUSTER_NODE`` environment variable or :bro:id:`Cluster::node` +##! must also be sent and the cluster framework loaded as a package like +##! ``@load base/frameworks/cluster``. + +@load base/frameworks/control module Cluster; export { - redef enum Log::ID += { CLUSTER }; + ## The cluster logging stream identifier. + redef enum Log::ID += { LOG }; + + ## The record type which contains the column fields of the cluster log. type Info: record { + ## The time at which a cluster message was generated. ts: time; + ## A message indicating information about the cluster's operation. message: string; } &log; - + + ## Types of nodes that are allowed to participate in the cluster + ## configuration. type NodeType: enum { + ## A dummy node type indicating the local node is not operating + ## within a cluster. + NONE, + ## A node type which is allowed to view/manipulate the configuration + ## of other nodes in the cluster. CONTROL, + ## A node type responsible for log and policy management. MANAGER, + ## A node type for relaying worker node communication and synchronizing + ## worker node state. PROXY, + ## The node type doing all the actual traffic analysis. WORKER, + ## A node acting as a traffic recorder using the + ## `Time Machine `_ software. TIME_MACHINE, }; - ## Events raised by the manager and handled by the workers. - const manager_events = /Drop::.*/ &redef; + ## Events raised by a manager and handled by the workers. + const manager2worker_events = /Drop::.*/ &redef; - ## Events raised by the proxies and handled by the manager. - const proxy_events = /Notice::notice/ &redef; + ## Events raised by a manager and handled by proxies. + const manager2proxy_events = /EMPTY/ &redef; - ## Events raised by workers and handled by the manager. - const worker_events = /(Notice::notice|TimeMachine::command|Drop::.*)/ &redef; + ## Events raised by proxies and handled by a manager. + const proxy2manager_events = /EMPTY/ &redef; + + ## Events raised by proxies and handled by workers. + const proxy2worker_events = /EMPTY/ &redef; + + ## Events raised by workers and handled by a manager. + const worker2manager_events = /(TimeMachine::command|Drop::.*)/ &redef; + + ## Events raised by workers and handled by proxies.. + const worker2proxy_events = /EMPTY/ &redef; + + ## Events raised by TimeMachine instances and handled by a manager. + const tm2manager_events = /EMPTY/ &redef; + + ## Events raised by TimeMachine instances and handled by workers. + const tm2worker_events = /EMPTY/ &redef; ## Events sent by the control host (i.e. BroControl) when dynamically ## connecting to a running instance to update settings or request data. @@ -31,30 +73,38 @@ export { ## Record type to indicate a node in a cluster. type Node: record { + ## Identifies the type of cluster node in this node's configuration. node_type: NodeType; + ## The IP address of the cluster node. ip: addr; + ## The port to which the this local node can connect when + ## establishing communication. p: port; - ## Identifier for the interface a worker is sniffing. interface: string &optional; - - ## Manager node this node uses. For workers and proxies. + ## Name of the manager node this node uses. For workers and proxies. manager: string &optional; - ## Proxy node this node uses. For workers and managers. + ## Name of the proxy node this node uses. For workers and managers. proxy: string &optional; - ## Worker nodes that this node connects with. For managers and proxies. + ## Names of worker nodes that this node connects with. + ## For managers and proxies. workers: set[string] &optional; + ## Name of a time machine node with which this node connects. time_machine: string &optional; }; ## This function can be called at any time to determine if the cluster ## framework is being enabled for this run. + ## + ## Returns: True if :bro:id:`Cluster::node` has been set. global is_enabled: function(): bool; ## This function can be called at any time to determine what type of ## cluster node the current Bro instance is going to be acting as. - ## :bro:id:`is_enabled` should be called first to find out if this is - ## actually going to be a cluster node. + ## If :bro:id:`Cluster::is_enabled` returns false, then + ## :bro:enum:`Cluster::NONE` is returned. + ## + ## Returns: The :bro:type:`Cluster::NodeType` the calling node acts as. global local_node_type: function(): NodeType; ## This gives the value for the number of workers currently connected to, @@ -80,18 +130,18 @@ function is_enabled(): bool function local_node_type(): NodeType { - return nodes[node]$node_type; + return is_enabled() ? nodes[node]$node_type : NONE; } - -event remote_connection_handshake_done(p: event_peer) +event remote_connection_handshake_done(p: event_peer) &priority=5 { - if ( nodes[p$descr]$node_type == WORKER ) + if ( p$descr in nodes && nodes[p$descr]$node_type == WORKER ) ++worker_count; } -event remote_connection_closed(p: event_peer) + +event remote_connection_closed(p: event_peer) &priority=5 { - if ( nodes[p$descr]$node_type == WORKER ) + if ( p$descr in nodes && nodes[p$descr]$node_type == WORKER ) --worker_count; } @@ -100,10 +150,9 @@ event bro_init() &priority=5 # If a node is given, but it's an unknown name we need to fail. if ( node != "" && node !in nodes ) { - local msg = "You didn't supply a valid node in the Cluster::nodes configuration."; - event reporter_error(current_time(), msg, ""); + Reporter::error(fmt("'%s' is not a valid node in the Cluster::nodes configuration", node)); terminate(); } - Log::create_stream(CLUSTER, [$columns=Info]); - } \ No newline at end of file + Log::create_stream(Cluster::LOG, [$columns=Info]); + } diff --git a/scripts/base/frameworks/cluster/nodes/manager.bro b/scripts/base/frameworks/cluster/nodes/manager.bro index 78b9fb7788..22d9d539ca 100644 --- a/scripts/base/frameworks/cluster/nodes/manager.bro +++ b/scripts/base/frameworks/cluster/nodes/manager.bro @@ -10,21 +10,13 @@ @prefixes += cluster-manager -# Load the script for local site configuration for the manager node. -@load site/local-manager - ## Turn off remote logging since this is the manager and should only log here. redef Log::enable_remote_logging = F; +redef Log::default_rotation_interval = 1 hrs; + ## Use the cluster's archive logging script. redef Log::default_rotation_postprocessor_cmd = "archive-log"; ## We're processing essentially *only* remote events. redef max_remote_events_processed = 10000; - -# Reraise remote notices locally. -event Notice::notice(n: Notice::Info) - { - if ( is_remote_event() ) - NOTICE(n); - } diff --git a/scripts/base/frameworks/cluster/nodes/proxy.bro b/scripts/base/frameworks/cluster/nodes/proxy.bro index 8340bf1be8..e38a5e9109 100644 --- a/scripts/base/frameworks/cluster/nodes/proxy.bro +++ b/scripts/base/frameworks/cluster/nodes/proxy.bro @@ -1,9 +1,10 @@ +##! Redefines the options common to all proxy nodes within a Bro cluster. +##! In particular, proxies are not meant to produce logs locally and they +##! do not forward events anywhere, they mainly synchronize state between +##! worker nodes. @prefixes += cluster-proxy -# Load the script for local site configuration for proxy nodes. -@load site/local-proxy - ## The proxy only syncs state; does not forward events. redef forward_remote_events = F; redef forward_remote_state_changes = T; @@ -14,6 +15,8 @@ redef Log::enable_local_logging = F; ## Make sure that remote logging is enabled. redef Log::enable_remote_logging = T; +redef Log::default_rotation_interval = 24hrs; + ## Use the cluster's delete-log script. redef Log::default_rotation_postprocessor_cmd = "delete-log"; diff --git a/scripts/base/frameworks/cluster/nodes/worker.bro b/scripts/base/frameworks/cluster/nodes/worker.bro index f534e0aecc..61d5228c88 100644 --- a/scripts/base/frameworks/cluster/nodes/worker.bro +++ b/scripts/base/frameworks/cluster/nodes/worker.bro @@ -1,30 +1,24 @@ +##! Redefines some options common to all worker nodes within a Bro cluster. +##! In particular, worker nodes do not produce logs locally, instead they +##! send them off to a manager node for processing. @prefixes += cluster-worker -# Load the script for local site configuration for the worker nodes. -@load site/local-worker - ## Don't do any local logging. redef Log::enable_local_logging = F; ## Make sure that remote logging is enabled. redef Log::enable_remote_logging = T; +redef Log::default_rotation_interval = 24hrs; + ## Use the cluster's delete-log script. redef Log::default_rotation_postprocessor_cmd = "delete-log"; +@load misc/trim-trace-file ## Record all packets into trace file. -# TODO: should we really be setting this to T? +## +## Note that this only indicates that *if* we are recording packets, we want all +## of them (rather than just those the core deems sufficiently important). Setting +## this does not turn recording on. Use '-w ' for that. redef record_all_packets = T; - -# Workers need to have a filter for the notice log which doesn't -# do remote logging since we forward the notice event directly. -event bro_init() - { - Log::add_filter(Notice::NOTICE, - [ - $name="cluster-worker", - $pred=function(rec: Notice::Info): bool { return F; } - ] - ); - } diff --git a/scripts/base/frameworks/cluster/setup-connections.bro b/scripts/base/frameworks/cluster/setup-connections.bro index 7928d0c6ec..b5a0d25e1f 100644 --- a/scripts/base/frameworks/cluster/setup-connections.bro +++ b/scripts/base/frameworks/cluster/setup-connections.bro @@ -1,5 +1,10 @@ +##! This script establishes communication among all nodes in a cluster +##! as defined by :bro:id:`Cluster::nodes`. + @load ./main -@load base/frameworks/communication/main +@load base/frameworks/communication + +@if ( Cluster::node in Cluster::nodes ) module Cluster; @@ -22,23 +27,24 @@ event bro_init() &priority=9 if ( n$node_type == WORKER && n$manager == node ) Communication::nodes[i] = [$host=n$ip, $connect=F, - $class=i, $events=worker_events, $request_logs=T]; + $class=i, $events=worker2manager_events, $request_logs=T]; if ( n$node_type == PROXY && n$manager == node ) Communication::nodes[i] = [$host=n$ip, $connect=F, - $class=i, $events=proxy_events, $request_logs=T]; + $class=i, $events=proxy2manager_events, $request_logs=T]; if ( n$node_type == TIME_MACHINE && me?$time_machine && me$time_machine == i ) Communication::nodes["time-machine"] = [$host=nodes[i]$ip, $p=nodes[i]$p, - $connect=T, $retry=1min]; + $connect=T, $retry=1min, + $events=tm2manager_events]; } else if ( me$node_type == PROXY ) { if ( n$node_type == WORKER && n$proxy == node ) Communication::nodes[i] = - [$host=n$ip, $connect=F, $class=i, $events=worker_events]; + [$host=n$ip, $connect=F, $class=i, $sync=T, $auth=T, $events=worker2proxy_events]; # accepts connections from the previous one. # (This is not ideal for setups with many proxies) @@ -56,26 +62,38 @@ event bro_init() &priority=9 # Finally the manager, to send it status updates. if ( n$node_type == MANAGER && me$manager == i ) - Communication::nodes["manager"] = [$host=nodes[i]$ip, $p=nodes[i]$p, + Communication::nodes["manager"] = [$host=nodes[i]$ip, + $p=nodes[i]$p, $connect=T, $retry=1mins, - $class=node]; + $class=node, + $events=manager2proxy_events]; } else if ( me$node_type == WORKER ) { if ( n$node_type == MANAGER && me$manager == i ) - Communication::nodes["manager"] = [$host=nodes[i]$ip, $p=nodes[i]$p, + Communication::nodes["manager"] = [$host=nodes[i]$ip, + $p=nodes[i]$p, $connect=T, $retry=1mins, - $class=node, $events=manager_events]; + $class=node, + $events=manager2worker_events]; if ( n$node_type == PROXY && me$proxy == i ) - Communication::nodes["proxy"] = [$host=nodes[i]$ip, $p=nodes[i]$p, - $connect=T, $retry=1mins, $sync=T, - $class=node]; + Communication::nodes["proxy"] = [$host=nodes[i]$ip, + $p=nodes[i]$p, + $connect=T, $retry=1mins, + $sync=T, $class=node, + $events=proxy2worker_events]; - if ( n$node_type == TIME_MACHINE && me?$time_machine && me$time_machine == i ) - Communication::nodes["time-machine"] = [$host=nodes[i]$ip, $p=nodes[i]$p, - $connect=T, $retry=1min]; + if ( n$node_type == TIME_MACHINE && + me?$time_machine && me$time_machine == i ) + Communication::nodes["time-machine"] = [$host=nodes[i]$ip, + $p=nodes[i]$p, + $connect=T, + $retry=1min, + $events=tm2worker_events]; } } } + +@endif diff --git a/scripts/base/frameworks/communication/main.bro b/scripts/base/frameworks/communication/main.bro index 73e6086f97..04772f57aa 100644 --- a/scripts/base/frameworks/communication/main.bro +++ b/scripts/base/frameworks/communication/main.bro @@ -1,26 +1,47 @@ -##! Connect to remote Bro or Broccoli instances to share state and/or transfer -##! events. +##! Facilitates connecting to remote Bro or Broccoli instances to share state +##! and/or transfer events. + +@load base/frameworks/packet-filter module Communication; export { - redef enum Log::ID += { COMMUNICATION }; + + ## The communication logging stream identifier. + redef enum Log::ID += { LOG }; - const default_port_ssl = 47756/tcp &redef; - const default_port_clear = 47757/tcp &redef; + ## Which interface to listen on (0.0.0.0 for any interface). + const listen_interface = 0.0.0.0 &redef; + + ## Which port to listen on. + const listen_port = 47757/tcp &redef; + + ## This defines if a listening socket should use SSL. + const listen_ssl = F &redef; ## Default compression level. Compression level is 0-9, with 0 = no ## compression. - global default_compression = 0 &redef; + global compression_level = 0 &redef; + ## A record type containing the column fields of the communication log. type Info: record { + ## The network time at which a communication event occurred. ts: time &log; + ## The peer name (if any) for which a communication event is concerned. peer: string &log &optional; + ## Where the communication event message originated from, that is, + ## either from the scripting layer or inside the Bro process. src_name: string &log &optional; + ## .. todo:: currently unused. connected_peer_desc: string &log &optional; + ## .. todo:: currently unused. connected_peer_addr: addr &log &optional; + ## .. todo:: currently unused. connected_peer_port: port &log &optional; + ## The severity of the communication event message. level: string &log &optional; + ## A message describing the communication event between Bro or + ## Broccoli instances. message: string &log; }; @@ -69,17 +90,14 @@ export { auth: bool &default = F; ## If not set, no capture filter is sent. - ## If set to "", the default cature filter is sent. + ## If set to "", the default capture filter is sent. capture_filter: string &optional; ## Whether to use SSL-based communication. ssl: bool &default = F; - ## Take-over state from this host (activated by loading hand-over.bro) - hand_over: bool &default = F; - ## Compression level is 0-9, with 0 = no compression. - compression: count &default = default_compression; + compression: count &default = compression_level; ## The remote peer. peer: event_peer &optional; @@ -91,11 +109,25 @@ export { ## The table of Bro or Broccoli nodes that Bro will initiate connections ## to or respond to connections from. global nodes: table[string] of Node &redef; - + + ## A table of peer nodes for which this node issued a + ## :bro:id:`Communication::connect_peer` call but with which a connection + ## has not yet been established or with which a connection has been + ## closed and is currently in the process of retrying to establish. + ## When a connection is successfully established, the peer is removed + ## from the table. global pending_peers: table[peer_id] of Node; + + ## A table of peer nodes for which this node has an established connection. + ## Peers are automatically removed if their connection is closed and + ## automatically added back if a connection is re-established later. global connected_peers: table[peer_id] of Node; - ## Connect to nodes[node], independent of its "connect" flag. + ## Connect to a node in :bro:id:`Communication::nodes` independent + ## of its "connect" flag. + ## + ## peer: the string used to index a particular node within the + ## :bro:id:`Communication::nodes` table. global connect_peer: function(peer: string); } @@ -105,21 +137,18 @@ const src_names = { [REMOTE_SRC_SCRIPT] = "script", }; -event bro_init() +event bro_init() &priority=5 { - Log::create_stream(COMMUNICATION, [$columns=Info]); - - if ( |nodes| > 0 ) - enable_communication(); + Log::create_stream(Communication::LOG, [$columns=Info]); } function do_script_log_common(level: count, src: count, msg: string) { - Log::write(COMMUNICATION, [$ts = network_time(), - $level = (level == REMOTE_LOG_INFO ? "info" : "error"), - $src_name = src_names[src], - $peer = get_event_peer()$descr, - $message = msg]); + Log::write(Communication::LOG, [$ts = network_time(), + $level = (level == REMOTE_LOG_INFO ? "info" : "error"), + $src_name = src_names[src], + $peer = get_event_peer()$descr, + $message = msg]); } # This is a core generated event. @@ -128,6 +157,13 @@ event remote_log(level: count, src: count, msg: string) do_script_log_common(level, src, msg); } +# This is a core generated event. +event remote_log_peer(p: event_peer, level: count, src: count, msg: string) + { + local rmsg = fmt("[#%d/%s:%d] %s", p$id, p$host, p$p, msg); + do_script_log_common(level, src, rmsg); + } + function do_script_log(p: event_peer, msg: string) { do_script_log_common(REMOTE_LOG_INFO, REMOTE_SRC_SCRIPT, msg); @@ -136,7 +172,7 @@ function do_script_log(p: event_peer, msg: string) function connect_peer(peer: string) { local node = nodes[peer]; - local p = node$ssl ? default_port_ssl : default_port_clear; + local p = listen_port; if ( node?$p ) p = node$p; @@ -145,9 +181,9 @@ function connect_peer(peer: string) local id = connect(node$host, p, class, node$retry, node$ssl); if ( id == PEER_ID_NONE ) - Log::write(COMMUNICATION, [$ts = network_time(), - $peer = get_event_peer()$descr, - $message = "can't trigger connect"]); + Log::write(Communication::LOG, [$ts = network_time(), + $peer = get_event_peer()$descr, + $message = "can't trigger connect"]); pending_peers[id] = node; } @@ -239,7 +275,7 @@ event remote_connection_established(p: event_peer) } if ( ! found ) - set_compression_level(p, default_compression); + set_compression_level(p, compression_level); } complete_handshake(p); @@ -273,15 +309,18 @@ event remote_state_inconsistency(operation: string, id: string, local msg = fmt("state inconsistency: %s should be %s but is %s before %s", id, expected_old, real_old, operation); - Log::write(COMMUNICATION, [$ts = network_time(), - $peer = get_event_peer()$descr, - $message = msg]); + Log::write(Communication::LOG, [$ts = network_time(), + $peer = get_event_peer()$descr, + $message = msg]); } # Actually initiate the connections that need to be established. event bro_init() &priority = -10 # let others modify nodes { + if ( |nodes| > 0 ) + enable_communication(); + for ( tag in nodes ) { if ( ! nodes[tag]$connect ) diff --git a/scripts/base/frameworks/control/main.bro b/scripts/base/frameworks/control/main.bro index 22422eb51d..4fe8872801 100644 --- a/scripts/base/frameworks/control/main.bro +++ b/scripts/base/frameworks/control/main.bro @@ -1,81 +1,67 @@ -##! This is a utility script that sends the current values of all &redef'able -##! consts to a remote Bro then sends the :bro:id:`configuration_update` event -##! and terminates processing. -##! -##! Intended to be used from the command line like this when starting a controller:: -##! -##! bro frameworks/control/controller Control::host= Control::port= Control::cmd= [Control::arg=] -##! -##! A controllee only needs to load the controllee script in addition -##! to the specific analysis scripts desired. It may also need a node -##! configured as a controller node in the communications nodes configuration:: -##! -##! bro frameworks/control/controllee -##! -##! To use the framework as a controllee, it only needs to be loaded and -##! the controlled node need to accept all events in the "Control::" namespace -##! from the host where the control actions will be performed from along with -##! using the "control" class. +##! The control framework provides the foundation for providing "commands" +##! that can be taken remotely at runtime to modify a running Bro instance +##! or collect information from the running instance. module Control; export { - ## This is the address of the host that will be controlled. + ## The address of the host that will be controlled. const host = 0.0.0.0 &redef; - - ## This is the port of the host that will be controlled. + + ## The port of the host that will be controlled. const host_port = 0/tcp &redef; - ## This is the command that is being done. It's typically set on the - ## command line and influences whether this instance starts up as a - ## controller or controllee. + ## The command that is being done. It's typically set on the + ## command line. const cmd = "" &redef; - + ## This can be used by commands that take an argument. const arg = "" &redef; - + + ## Events that need to be handled by controllers. const controller_events = /Control::.*_request/ &redef; + + ## Events that need to be handled by controllees. const controllee_events = /Control::.*_response/ &redef; - ## These are the commands that can be given on the command line for + ## The commands that can currently be given on the command line for ## remote control. - const commands: set[string] = { + const commands: set[string] = { "id_value", "peer_status", "net_stats", "configuration_update", "shutdown", - }; - + } &redef; + ## Variable IDs that are to be ignored by the update process. - const ignore_ids: set[string] = { - # FIXME: Bro crashes if it tries to send this ID. - "Log::rotation_control", - }; - + const ignore_ids: set[string] = { }; + ## Event for requesting the value of an ID (a variable). global id_value_request: event(id: string); - ## Event for returning the value of an ID after an :bro:id:`id_request` event. + ## Event for returning the value of an ID after an + ## :bro:id:`Control::id_value_request` event. global id_value_response: event(id: string, val: string); - + ## Requests the current communication status. global peer_status_request: event(); ## Returns the current communication status. global peer_status_response: event(s: string); - + ## Requests the current net_stats. global net_stats_request: event(); ## Returns the current net_stats. global net_stats_response: event(s: string); - + ## Inform the remote Bro instance that it's configuration may have been updated. global configuration_update_request: event(); - ## This event is a wrapper and alias for the :bro:id:`configuration_update_request` event. + ## This event is a wrapper and alias for the + ## :bro:id:`Control::configuration_update_request` event. ## This event is also a primary hooking point for the control framework. global configuration_update: event(); ## Message in response to a configuration update request. global configuration_update_response: event(); - + ## Requests that the Bro instance begins shutting down. global shutdown_request: event(); ## Message in response to a shutdown request. diff --git a/scripts/base/frameworks/dpd/dpd.sig b/scripts/base/frameworks/dpd/dpd.sig index 8e07095b41..adda0ce54e 100644 --- a/scripts/base/frameworks/dpd/dpd.sig +++ b/scripts/base/frameworks/dpd/dpd.sig @@ -80,15 +80,15 @@ signature irc_server_reply { tcp-state responder } -signature irc_sig3 { +signature irc_server_to_server1 { ip-proto == tcp - payload /(.*\x0a)*(\x20)*[Ss][Ee][Rr][Vv][Ee][Rr](\x20)+.+\x0a/ + payload /(|.*[\r\n]) *[Ss][Ee][Rr][Vv][Ee][Rr] +[^ ]+ +[0-9]+ +:.+[\r\n]/ } -signature irc_sig4 { +signature irc_server_to_server2 { ip-proto == tcp - payload /(.*\x0a)*(\x20)*[Ss][Ee][Rr][Vv][Ee][Rr](\x20)+.+\x0a/ - requires-reverse-signature irc_sig3 + payload /(|.*[\r\n]) *[Ss][Ee][Rr][Vv][Ee][Rr] +[^ ]+ +[0-9]+ +:.+[\r\n]/ + requires-reverse-signature irc_server_to_server1 enable "irc" } diff --git a/scripts/base/frameworks/dpd/main.bro b/scripts/base/frameworks/dpd/main.bro index 9bfd7f615b..e8488c3ec1 100644 --- a/scripts/base/frameworks/dpd/main.bro +++ b/scripts/base/frameworks/dpd/main.bro @@ -7,14 +7,16 @@ module DPD; redef signature_files += "base/frameworks/dpd/dpd.sig"; export { - redef enum Log::ID += { DPD }; + ## Add the DPD logging stream identifier. + redef enum Log::ID += { LOG }; + ## The record type defining the columns to log in the DPD logging stream. type Info: record { ## Timestamp for when protocol analysis failed. ts: time &log; ## Connection unique ID. uid: string &log; - ## Connection ID. + ## Connection ID containing the 4-tuple which identifies endpoints. id: conn_id &log; ## Transport protocol for the violation. proto: transport_proto &log; @@ -25,8 +27,7 @@ export { ## Disabled analyzer IDs. This is only for internal tracking ## so as to not attempt to disable analyzers multiple times. - # TODO: This is waiting on ticket #460 to remove the '0'. - disabled_aids: set[count] &default=set(0); + disabled_aids: set[count]; }; ## Ignore violations which go this many bytes into the connection. @@ -38,9 +39,9 @@ redef record connection += { dpd: Info &optional; }; -event bro_init() +event bro_init() &priority=5 { - Log::create_stream(DPD, [$columns=Info]); + Log::create_stream(DPD::LOG, [$columns=Info]); # Populate the internal DPD analysis variable. for ( a in dpd_config ) @@ -104,5 +105,5 @@ event protocol_violation(c: connection, atype: count, aid: count, reason: string) &priority=-5 { if ( c?$dpd ) - Log::write(DPD, c$dpd); + Log::write(DPD::LOG, c$dpd); } diff --git a/scripts/base/frameworks/intel/main.bro b/scripts/base/frameworks/intel/main.bro index 9849d4df42..9ee1c75100 100644 --- a/scripts/base/frameworks/intel/main.bro +++ b/scripts/base/frameworks/intel/main.bro @@ -11,7 +11,7 @@ # user_name # file_name # file_md5 -# x509_cert - DER encoded, not PEM (ascii armored) +# x509_md5 # Example tags: # infrastructure @@ -20,10 +20,13 @@ # canary # friend +@load base/frameworks/notice + module Intel; export { - redef enum Log::ID += { INTEL }; + ## The intel logging stream identifier. + redef enum Log::ID += { LOG }; redef enum Notice::Type += { ## This notice should be used in all detector scripts to indicate @@ -31,75 +34,120 @@ export { Detection, }; + ## Record type used for logging information from the intelligence framework. + ## Primarily for problems or oddities with inserting and querying data. + ## This is important since the content of the intelligence framework can + ## change quite dramatically during runtime and problems may be introduced + ## into the data. type Info: record { + ## The current network time. ts: time &log; + ## Represents the severity of the message. ## This value should be one of: "info", "warn", "error" level: string &log; + ## The message. message: string &log; }; + ## Record to represent metadata associated with a single piece of + ## intelligence. type MetaData: record { + ## A description for the data. desc: string &optional; + ## A URL where more information may be found about the intelligence. url: string &optional; + ## The time at which the data was first declared to be intelligence. first_seen: time &optional; + ## When this data was most recent inserted into the framework. latest_seen: time &optional; + ## Arbitrary text tags for the data. tags: set[string]; }; + ## Record to represent a singular piece of intelligence. type Item: record { + ## If the data is an IP address, this hold the address. ip: addr &optional; + ## If the data is textual, this holds the text. str: string &optional; + ## If the data is numeric, this holds the number. num: int &optional; + ## The subtype of the data for when either the $str or $num fields are + ## given. If one of those fields are given, this field must be present. subtype: string &optional; + ## The next five fields are temporary until a better model for + ## attaching metadata to an intelligence item is created. desc: string &optional; url: string &optional; first_seen: time &optional; latest_seen: time &optional; tags: set[string]; - ## These single string tags are throw away until pybroccoli supports sets + ## These single string tags are throw away until pybroccoli supports sets. tag1: string &optional; tag2: string &optional; tag3: string &optional; }; + ## Record model used for constructing queries against the intelligence + ## framework. type QueryItem: record { - ip: addr &optional; - str: string &optional; - num: int &optional; - subtype: string &optional; + ## If an IP address is being queried for, this field should be given. + ip: addr &optional; + ## If a string is being queried for, this field should be given. + str: string &optional; + ## If numeric data is being queried for, this field should be given. + num: int &optional; + ## If either a string or number is being queried for, this field should + ## indicate the subtype of the data. + subtype: string &optional; - or_tags: set[string] &optional; - and_tags: set[string] &optional; + ## A set of tags where if a single metadata record attached to an item + ## has any one of the tags defined in this field, it will match. + or_tags: set[string] &optional; + ## A set of tags where a single metadata record attached to an item + ## must have all of the tags defined in this field. + and_tags: set[string] &optional; ## The predicate can be given when searching for a match. It will - ## be tested against every :bro:type:`MetaData` item associated with - ## the data being matched on. If it returns T a single time, the - ## matcher will consider that the item has matched. - pred: function(meta: Intel::MetaData): bool &optional; + ## be tested against every :bro:type:`Intel::MetaData` item associated + ## with the data being matched on. If it returns T a single time, the + ## matcher will consider that the item has matched. This field can + ## be used for constructing arbitrarily complex queries that may not + ## be possible with the $or_tags or $and_tags fields. + pred: function(meta: Intel::MetaData): bool &optional; }; - + ## Function to insert data into the intelligence framework. + ## + ## item: The data item. + ## + ## Returns: T if the data was successfully inserted into the framework, + ## otherwise it returns F. global insert: function(item: Item): bool; + + ## A wrapper for the :bro:id:`Intel::insert` function. This is primarily + ## used as the external API for inserting data into the intelligence + ## using Broccoli. global insert_event: event(item: Item); + + ## Function for matching data within the intelligence framework. global matcher: function(item: QueryItem): bool; - - type MetaDataStore: table[count] of MetaData; - type DataStore: record { - ip_data: table[addr] of MetaDataStore; - ## The first string is the actual value and the second string is the subtype. - string_data: table[string, string] of MetaDataStore; - int_data: table[int, string] of MetaDataStore; - }; - global data_store: DataStore; - - } +type MetaDataStore: table[count] of MetaData; +type DataStore: record { + ip_data: table[addr] of MetaDataStore; + # The first string is the actual value and the second string is the subtype. + string_data: table[string, string] of MetaDataStore; + int_data: table[int, string] of MetaDataStore; +}; +global data_store: DataStore; + event bro_init() { - Log::create_stream(INTEL, [$columns=Info]); + Log::create_stream(Intel::LOG, [$columns=Info]); } @@ -161,7 +209,7 @@ function insert(item: Item): bool } if ( err_msg != "" ) - Log::write(INTEL, [$ts=network_time(), $level="warn", $message=fmt(err_msg)]); + Log::write(Intel::LOG, [$ts=network_time(), $level="warn", $message=fmt(err_msg)]); return F; } @@ -270,6 +318,6 @@ function matcher(item: QueryItem): bool } if ( err_msg != "" ) - Log::write(INTEL, [$ts=network_time(), $level="error", $message=fmt(err_msg)]); + Log::write(Intel::LOG, [$ts=network_time(), $level="error", $message=fmt(err_msg)]); return F; } diff --git a/scripts/base/frameworks/logging/__load__.bro b/scripts/base/frameworks/logging/__load__.bro index 3021aed706..42b2d7c564 100644 --- a/scripts/base/frameworks/logging/__load__.bro +++ b/scripts/base/frameworks/logging/__load__.bro @@ -1,3 +1,3 @@ @load ./main - +@load ./postprocessors @load ./writers/ascii diff --git a/scripts/base/frameworks/logging/main.bro b/scripts/base/frameworks/logging/main.bro index a90dd21984..2c36b3001e 100644 --- a/scripts/base/frameworks/logging/main.bro +++ b/scripts/base/frameworks/logging/main.bro @@ -1,16 +1,16 @@ ##! The Bro logging interface. ##! -##! See XXX for a introduction to Bro's logging framework. +##! See :doc:`/logging` for a introduction to Bro's logging framework. module Log; -# Log::ID and Log::Writer are defined in bro.init due to circular dependencies. +# Log::ID and Log::Writer are defined in types.bif due to circular dependencies. export { - ## If true, is local logging is by default enabled for all filters. + ## If true, local logging is by default enabled for all filters. const enable_local_logging = T &redef; - ## If true, is remote logging is by default enabled for all filters. + ## If true, remote logging is by default enabled for all filters. const enable_remote_logging = T &redef; ## Default writer to use if a filter does not specify @@ -23,36 +23,67 @@ export { columns: any; ## Event that will be raised once for each log entry. - ## The event receives a single same parameter, an instance of type ``columns``. + ## The event receives a single same parameter, an instance of type + ## ``columns``. ev: any &optional; }; - ## Default function for building the path values for log filters if not - ## speficied otherwise by a filter. The default implementation uses ``id`` + ## Builds the default path values for log filters if not otherwise + ## specified by a filter. The default implementation uses *id* ## to derive a name. ## - ## id: The log stream. - ## path: A suggested path value, which may be either the filter's ``path`` - ## if defined or a fall-back generated internally. + ## id: The ID associated with the log stream. + ## + ## path: A suggested path value, which may be either the filter's + ## ``path`` if defined, else a previous result from the function. + ## If no ``path`` is defined for the filter, then the first call + ## to the function will contain an empty string. + ## ## rec: An instance of the streams's ``columns`` type with its - ## fields set to the values to logged. + ## fields set to the values to be logged. ## ## Returns: The path to be used for the filter. global default_path_func: function(id: ID, path: string, rec: any) : string &redef; - ## Filter customizing logging. + # Log rotation support. + + ## Information passed into rotation callback functions. + type RotationInfo: record { + writer: Writer; ##< The :bro:type:`Log::Writer` being used. + fname: string; ##< Full name of the rotated file. + path: string; ##< Original path value. + open: time; ##< Time when opened. + close: time; ##< Time when closed. + terminating: bool; ##< True if rotation occured due to Bro shutting down. + }; + + ## Default rotation interval. Zero disables rotation. + const default_rotation_interval = 0secs &redef; + + ## Default naming format for timestamps embedded into filenames. + ## Uses a ``strftime()`` style. + const default_rotation_date_format = "%Y-%m-%d-%H-%M-%S" &redef; + + ## Default shell command to run on rotated files. Empty for none. + const default_rotation_postprocessor_cmd = "" &redef; + + ## Specifies the default postprocessor function per writer type. + ## Entries in this table are initialized by each writer type. + const default_rotation_postprocessors: table[Writer] of function(info: RotationInfo) : bool &redef; + + ## A filter type describes how to customize logging streams. type Filter: record { ## Descriptive name to reference this filter. name: string; - ## The writer to use. + ## The logging writer implementation to use. writer: Writer &default=default_writer; - ## Predicate indicating whether a log entry should be recorded. + ## Indicates whether a log entry should be recorded. ## If not given, all entries are recorded. ## ## rec: An instance of the streams's ``columns`` type with its - ## fields set to the values to logged. + ## fields set to the values to logged. ## ## Returns: True if the entry is to be recorded. pred: function(rec: any): bool &optional; @@ -74,11 +105,15 @@ export { ## easy to flood the disk by returning a new string for each ## connection ... ## - ## id: The log stream. - ## path: A suggested path value, which may be either the filter's ``path`` - ## if defined or a fall-back generated internally. + ## id: The ID associated with the log stream. + ## + ## path: A suggested path value, which may be either the filter's + ## ``path`` if defined, else a previous result from the function. + ## If no ``path`` is defined for the filter, then the first call + ## to the function will contain an empty string. + ## ## rec: An instance of the streams's ``columns`` type with its - ## fields set to the values to logged. + ## fields set to the values to be logged. ## ## Returns: The path to be used for the filter. path_func: function(id: ID, path: string, rec: any): string &optional; @@ -96,70 +131,194 @@ export { ## If true, entries are passed on to remote peers. log_remote: bool &default=enable_remote_logging; - }; - # Log rotation support. - - ## Information passed into rotation callback functions. - type RotationInfo: record { - writer: Writer; ##< Writer. - fname: string; ##< Full name of the rotated file. - path: string; ##< Original path value. - open: time; ##< Time when opened. - close: time; ##< Time when closed. - terminating: bool; ##< True if rotation occured due to Bro shutting down. - }; - - ## Default rotation interval. Zero disables rotation. - const default_rotation_interval = 0secs &redef; - - ## Default naming format for timestamps embedded into filenames. Uses a strftime() style. - const default_rotation_date_format = "%Y-%m-%d-%H-%M-%S" &redef; - - ## Default shell command to run on rotated files. Empty for none. - const default_rotation_postprocessor_cmd = "" &redef; - - ## Specifies the default postprocessor function per writer type. Entries in this - ## table are initialized by each writer type. - const default_rotation_postprocessors: table[Writer] of function(info: RotationInfo) : bool &redef; - - ## Type for controlling file rotation. - type RotationControl: record { ## Rotation interval. interv: interval &default=default_rotation_interval; - ## Callback function to trigger for rotated files. If not set, the default - ## comes out of default_rotation_postprocessors. + + ## Callback function to trigger for rotated files. If not set, the + ## default comes out of :bro:id:`Log::default_rotation_postprocessors`. postprocessor: function(info: RotationInfo) : bool &optional; }; - ## Specifies rotation parameters per ``(id, path)`` tuple. - ## If a pair is not found in this table, default values defined in - ## ``RotationControl`` are used. - const rotation_control: table[Writer, string] of RotationControl &default=[] &redef; - ## Sentinel value for indicating that a filter was not found when looked up. - const no_filter: Filter = [$name=""]; # Sentinel. + const no_filter: Filter = [$name=""]; - # TODO: Document. + ## Creates a new logging stream with the default filter. + ## + ## id: The ID enum to be associated with the new logging stream. + ## + ## stream: A record defining the content that the new stream will log. + ## + ## Returns: True if a new logging stream was successfully created and + ## a default filter added to it. + ## + ## .. bro:see:: Log::add_default_filter Log::remove_default_filter global create_stream: function(id: ID, stream: Stream) : bool; + + ## Enables a previously disabled logging stream. Disabled streams + ## will not be written to until they are enabled again. New streams + ## are enabled by default. + ## + ## id: The ID associated with the logging stream to enable. + ## + ## Returns: True if the stream is re-enabled or was not previously disabled. + ## + ## .. bro:see:: Log::disable_stream global enable_stream: function(id: ID) : bool; + + ## Disables a currently enabled logging stream. Disabled streams + ## will not be written to until they are enabled again. New streams + ## are enabled by default. + ## + ## id: The ID associated with the logging stream to disable. + ## + ## Returns: True if the stream is now disabled or was already disabled. + ## + ## .. bro:see:: Log::enable_stream global disable_stream: function(id: ID) : bool; + + ## Adds a custom filter to an existing logging stream. If a filter + ## with a matching ``name`` field already exists for the stream, it + ## is removed when the new filter is successfully added. + ## + ## id: The ID associated with the logging stream to filter. + ## + ## filter: A record describing the desired logging parameters. + ## + ## Returns: True if the filter was sucessfully added, false if + ## the filter was not added or the *filter* argument was not + ## the correct type. + ## + ## .. bro:see:: Log::remove_filter Log::add_default_filter + ## Log::remove_default_filter global add_filter: function(id: ID, filter: Filter) : bool; + + ## Removes a filter from an existing logging stream. + ## + ## id: The ID associated with the logging stream from which to + ## remove a filter. + ## + ## name: A string to match against the ``name`` field of a + ## :bro:type:`Log::Filter` for identification purposes. + ## + ## Returns: True if the logging stream's filter was removed or + ## if no filter associated with *name* was found. + ## + ## .. bro:see:: Log::remove_filter Log::add_default_filter + ## Log::remove_default_filter global remove_filter: function(id: ID, name: string) : bool; - global get_filter: function(id: ID, name: string) : Filter; # Returns no_filter if not found. + + ## Gets a filter associated with an existing logging stream. + ## + ## id: The ID associated with a logging stream from which to + ## obtain one of its filters. + ## + ## name: A string to match against the ``name`` field of a + ## :bro:type:`Log::Filter` for identification purposes. + ## + ## Returns: A filter attached to the logging stream *id* matching + ## *name* or, if no matches are found returns the + ## :bro:id:`Log::no_filter` sentinel value. + ## + ## .. bro:see:: Log::add_filter Log::remove_filter Log::add_default_filter + ## Log::remove_default_filter + global get_filter: function(id: ID, name: string) : Filter; + + ## Writes a new log line/entry to a logging stream. + ## + ## id: The ID associated with a logging stream to be written to. + ## + ## columns: A record value describing the values of each field/column + ## to write to the log stream. + ## + ## Returns: True if the stream was found and no error occurred in writing + ## to it or if the stream was disabled and nothing was written. + ## False if the stream was was not found, or the *columns* + ## argument did not match what the stream was initially defined + ## to handle, or one of the stream's filters has an invalid + ## ``path_func``. + ## + ## .. bro:see: Log::enable_stream Log::disable_stream global write: function(id: ID, columns: any) : bool; + + ## Sets the buffering status for all the writers of a given logging stream. + ## A given writer implementation may or may not support buffering and if it + ## doesn't then toggling buffering with this function has no effect. + ## + ## id: The ID associated with a logging stream for which to + ## enable/disable buffering. + ## + ## buffered: Whether to enable or disable log buffering. + ## + ## Returns: True if buffering status was set, false if the logging stream + ## does not exist. + ## + ## .. bro:see:: Log::flush global set_buf: function(id: ID, buffered: bool): bool; + + ## Flushes any currently buffered output for all the writers of a given + ## logging stream. + ## + ## id: The ID associated with a logging stream for which to flush buffered + ## data. + ## + ## Returns: True if all writers of a log stream were signalled to flush + ## buffered data or if the logging stream is disabled, + ## false if the logging stream does not exist. + ## + ## .. bro:see:: Log::set_buf Log::enable_stream Log::disable_stream global flush: function(id: ID): bool; + + ## Adds a default :bro:type:`Log::Filter` record with ``name`` field + ## set as "default" to a given logging stream. + ## + ## id: The ID associated with a logging stream for which to add a default + ## filter. + ## + ## Returns: The status of a call to :bro:id:`Log::add_filter` using a + ## default :bro:type:`Log::Filter` argument with ``name`` field + ## set to "default". + ## + ## .. bro:see:: Log::add_filter Log::remove_filter + ## Log::remove_default_filter global add_default_filter: function(id: ID) : bool; + + ## Removes the :bro:type:`Log::Filter` with ``name`` field equal to + ## "default". + ## + ## id: The ID associated with a logging stream from which to remove the + ## default filter. + ## + ## Returns: The status of a call to :bro:id:`Log::remove_filter` using + ## "default" as the argument. + ## + ## .. bro:see:: Log::add_filter Log::remove_filter Log::add_default_filter global remove_default_filter: function(id: ID) : bool; + ## Runs a command given by :bro:id:`Log::default_rotation_postprocessor_cmd` + ## on a rotated file. Meant to be called from postprocessor functions + ## that are added to :bro:id:`Log::default_rotation_postprocessors`. + ## + ## info: A record holding meta-information about the log being rotated. + ## + ## npath: The new path of the file (after already being rotated/processed + ## by writer-specific postprocessor as defined in + ## :bro:id:`Log::default_rotation_postprocessors`. + ## + ## Returns: True when :bro:id:`Log::default_rotation_postprocessor_cmd` + ## is empty or the system command given by it has been invoked + ## to postprocess a rotated log file. + ## + ## .. bro:see:: Log::default_rotation_date_format + ## Log::default_rotation_postprocessor_cmd + ## Log::default_rotation_postprocessors global run_rotation_postprocessor_cmd: function(info: RotationInfo, npath: string) : bool; } # We keep a script-level copy of all filters so that we can manipulate them. global filters: table[ID, string] of Filter; -@load logging.bif.bro # Needs Filter and Stream defined. +@load base/logging.bif # Needs Filter and Stream defined. module Log; @@ -172,8 +331,40 @@ function __default_rotation_postprocessor(info: RotationInfo) : bool function default_path_func(id: ID, path: string, rec: any) : string { - # TODO for Seth: Do what you want. :) - return path; + local id_str = fmt("%s", id); + + local parts = split1(id_str, /::/); + if ( |parts| == 2 ) + { + # The suggested path value is a previous result of this function + # or a filter path explicitly set by the user, so continue using it. + if ( path != "" ) + return path; + + # Example: Notice::LOG -> "notice" + if ( parts[2] == "LOG" ) + { + local module_parts = split_n(parts[1], /[^A-Z][A-Z][a-z]*/, T, 4); + local output = ""; + if ( 1 in module_parts ) + output = module_parts[1]; + if ( 2 in module_parts && module_parts[2] != "" ) + output = cat(output, sub_bytes(module_parts[2],1,1), "_", sub_bytes(module_parts[2], 2, |module_parts[2]|)); + if ( 3 in module_parts && module_parts[3] != "" ) + output = cat(output, "_", module_parts[3]); + if ( 4 in module_parts && module_parts[4] != "" ) + output = cat(output, sub_bytes(module_parts[4],1,1), "_", sub_bytes(module_parts[4], 2, |module_parts[4]|)); + return to_lower(output); + } + + # Example: Notice::POLICY_LOG -> "notice_policy" + if ( /_LOG$/ in parts[2] ) + parts[2] = sub(parts[2], /_LOG$/, ""); + + return cat(to_lower(parts[1]),"_",to_lower(parts[2])); + } + else + return to_lower(id_str); } # Run post-processor on file. If there isn't any postprocessor defined, @@ -206,8 +397,7 @@ function create_stream(id: ID, stream: Stream) : bool function disable_stream(id: ID) : bool { - if ( ! __disable_stream(id) ) - return F; + return __disable_stream(id); } function add_filter(id: ID, filter: Filter) : bool @@ -217,7 +407,7 @@ function add_filter(id: ID, filter: Filter) : bool # definition. if ( ! filter?$path_func ) filter$path_func = default_path_func; - + filters[id, filter$name] = filter; return __add_filter(id, filter); } diff --git a/scripts/base/frameworks/logging/postprocessors/__load__.bro b/scripts/base/frameworks/logging/postprocessors/__load__.bro new file mode 100644 index 0000000000..830a69aa75 --- /dev/null +++ b/scripts/base/frameworks/logging/postprocessors/__load__.bro @@ -0,0 +1,2 @@ +@load ./scp +@load ./sftp diff --git a/scripts/base/frameworks/logging/postprocessors/scp.bro b/scripts/base/frameworks/logging/postprocessors/scp.bro new file mode 100644 index 0000000000..3aadc5bbf3 --- /dev/null +++ b/scripts/base/frameworks/logging/postprocessors/scp.bro @@ -0,0 +1,72 @@ +##! This script defines a postprocessing function that can be applied +##! to a logging filter in order to automatically SCP (secure copy) +##! a log stream (or a subset of it) to a remote host at configurable +##! rotation time intervals. Generally, to use this functionality +##! you must handle the :bro:id:`bro_init` event and do the following +##! in your handler: +##! +##! 1) Create a new :bro:type:`Log::Filter` record that defines a name/path, +##! rotation interval, and set the ``postprocessor`` to +##! :bro:id:`Log::scp_postprocessor`. +##! 2) Add the filter to a logging stream using :bro:id:`Log::add_filter`. +##! 3) Add a table entry to :bro:id:`Log::scp_destinations` for the filter's +##! writer/path pair which defines a set of :bro:type:`Log::SCPDestination` +##! records. + +module Log; + +export { + ## Secure-copies the rotated-log to all the remote hosts + ## defined in :bro:id:`Log::scp_destinations` and then deletes + ## the local copy of the rotated-log. It's not active when + ## reading from trace files. + ## + ## info: A record holding meta-information about the log file to be + ## postprocessed. + ## + ## Returns: True if secure-copy system command was initiated or + ## if no destination was configured for the log as described + ## by *info*. + global scp_postprocessor: function(info: Log::RotationInfo): bool; + + ## A container that describes the remote destination for the SCP command + ## argument as ``user@host:path``. + type SCPDestination: record { + ## The remote user to log in as. A trust mechanism should be + ## pre-established. + user: string; + ## The remote host to which to transfer logs. + host: string; + ## The path/directory on the remote host to send logs. + path: string; + }; + + ## A table indexed by a particular log writer and filter path, that yields + ## a set remote destinations. The :bro:id:`Log::scp_postprocessor` + ## function queries this table upon log rotation and performs a secure + ## copy of the rotated-log to each destination in the set. This + ## table can be modified at run-time. + global scp_destinations: table[Writer, string] of set[SCPDestination]; + + ## Default naming format for timestamps embedded into log filenames + ## that use the SCP rotator. + const scp_rotation_date_format = "%Y-%m-%d-%H-%M-%S" &redef; +} + +function scp_postprocessor(info: Log::RotationInfo): bool + { + if ( reading_traces() || [info$writer, info$path] !in scp_destinations ) + return T; + + local command = ""; + for ( d in scp_destinations[info$writer, info$path] ) + { + local dst = fmt("%s/%s.%s.log", d$path, info$path, + strftime(Log::scp_rotation_date_format, info$open)); + command += fmt("scp %s %s@%s:%s;", info$fname, d$user, d$host, dst); + } + + command += fmt("/bin/rm %s", info$fname); + system(command); + return T; + } diff --git a/scripts/base/frameworks/logging/postprocessors/sftp.bro b/scripts/base/frameworks/logging/postprocessors/sftp.bro new file mode 100644 index 0000000000..5a31853063 --- /dev/null +++ b/scripts/base/frameworks/logging/postprocessors/sftp.bro @@ -0,0 +1,73 @@ +##! This script defines a postprocessing function that can be applied +##! to a logging filter in order to automatically SFTP +##! a log stream (or a subset of it) to a remote host at configurable +##! rotation time intervals. Generally, to use this functionality +##! you must handle the :bro:id:`bro_init` event and do the following +##! in your handler: +##! +##! 1) Create a new :bro:type:`Log::Filter` record that defines a name/path, +##! rotation interval, and set the ``postprocessor`` to +##! :bro:id:`Log::sftp_postprocessor`. +##! 2) Add the filter to a logging stream using :bro:id:`Log::add_filter`. +##! 3) Add a table entry to :bro:id:`Log::sftp_destinations` for the filter's +##! writer/path pair which defines a set of :bro:type:`Log::SFTPDestination` +##! records. + +module Log; + +export { + ## Securely transfers the rotated-log to all the remote hosts + ## defined in :bro:id:`Log::sftp_destinations` and then deletes + ## the local copy of the rotated-log. It's not active when + ## reading from trace files. + ## + ## info: A record holding meta-information about the log file to be + ## postprocessed. + ## + ## Returns: True if sftp system command was initiated or + ## if no destination was configured for the log as described + ## by *info*. + global sftp_postprocessor: function(info: Log::RotationInfo): bool; + + ## A container that describes the remote destination for the SFTP command, + ## comprised of the username, host, and path at which to upload the file. + type SFTPDestination: record { + ## The remote user to log in as. A trust mechanism should be + ## pre-established. + user: string; + ## The remote host to which to transfer logs. + host: string; + ## The path/directory on the remote host to send logs. + path: string; + }; + + ## A table indexed by a particular log writer and filter path, that yields + ## a set remote destinations. The :bro:id:`Log::sftp_postprocessor` + ## function queries this table upon log rotation and performs a secure + ## transfer of the rotated-log to each destination in the set. This + ## table can be modified at run-time. + global sftp_destinations: table[Writer, string] of set[SFTPDestination]; + + ## Default naming format for timestamps embedded into log filenames + ## that use the SFTP rotator. + const sftp_rotation_date_format = "%Y-%m-%d-%H-%M-%S" &redef; +} + +function sftp_postprocessor(info: Log::RotationInfo): bool + { + if ( reading_traces() || [info$writer, info$path] !in sftp_destinations ) + return T; + + local command = ""; + for ( d in sftp_destinations[info$writer, info$path] ) + { + local dst = fmt("%s/%s.%s.log", d$path, info$path, + strftime(Log::sftp_rotation_date_format, info$open)); + command += fmt("echo put %s %s | sftp -b - %s@%s;", info$fname, dst, + d$user, d$host); + } + + command += fmt("/bin/rm %s", info$fname); + system(command); + return T; + } diff --git a/scripts/base/frameworks/logging/writers/ascii.bro b/scripts/base/frameworks/logging/writers/ascii.bro index 1b5b1be33d..fa1fcd6797 100644 --- a/scripts/base/frameworks/logging/writers/ascii.bro +++ b/scripts/base/frameworks/logging/writers/ascii.bro @@ -1,4 +1,5 @@ -##! Interface for the ascii log writer. +##! Interface for the ASCII log writer. Redefinable options are available +##! to tweak the output format of ASCII logs. module LogAscii; @@ -7,11 +8,12 @@ export { ## into files. This is primarily for debugging purposes. const output_to_stdout = F &redef; - ## If true, include a header line with column names. + ## If true, include a header line with column names and description + ## of the other ASCII logging options that were used. const include_header = T &redef; ## Prefix for the header line if included. - const header_prefix = "# " &redef; + const header_prefix = "#" &redef; ## Separator between fields. const separator = "\t" &redef; @@ -19,8 +21,9 @@ export { ## Separator between set elements. const set_separator = "," &redef; - ## String to use for empty fields. - const empty_field = "-" &redef; + ## String to use for empty fields. This should be different from + ## *unset_field* to make the output non-ambigious. + const empty_field = "(empty)" &redef; ## String to use for an unset &optional field. const unset_field = "-" &redef; diff --git a/scripts/base/frameworks/metrics/cluster.bro b/scripts/base/frameworks/metrics/cluster.bro index 91efa98996..4804bc5005 100644 --- a/scripts/base/frameworks/metrics/cluster.bro +++ b/scripts/base/frameworks/metrics/cluster.bro @@ -8,48 +8,51 @@ ##! to be an internal implementation detail. @load base/frameworks/cluster +@load ./main module Metrics; export { - ## This value allows a user to decide how large of result groups the - ## workers should transmit values. + ## Allows a user to decide how large of result groups the + ## workers should transmit values for cluster metric aggregation. const cluster_send_in_groups_of = 50 &redef; - ## This is the percent of the full threshold value that needs to be met + ## The percent of the full threshold value that needs to be met ## on a single worker for that worker to send the value to its manager in ## order for it to request a global view for that value. There is no ## requirement that the manager requests a global view for the index ## since it may opt not to if it requested a global view for the index ## recently. const cluster_request_global_view_percent = 0.1 &redef; + + ## Event sent by the manager in a cluster to initiate the + ## collection of metrics values for a filter. + global cluster_filter_request: event(uid: string, id: ID, filter_name: string); + + ## Event sent by nodes that are collecting metrics after receiving + ## a request for the metric filter from the manager. + global cluster_filter_response: event(uid: string, id: ID, filter_name: string, data: MetricTable, done: bool); + + ## This event is sent by the manager in a cluster to initiate the + ## collection of a single index value from a filter. It's typically + ## used to get intermediate updates before the break interval triggers + ## to speed detection of a value crossing a threshold. + global cluster_index_request: event(uid: string, id: ID, filter_name: string, index: Index); + + ## This event is sent by nodes in response to a + ## :bro:id:`Metrics::cluster_index_request` event. + global cluster_index_response: event(uid: string, id: ID, filter_name: string, index: Index, val: count); + + ## This is sent by workers to indicate that they crossed the percent of the + ## current threshold by the percentage defined globally in + ## :bro:id:`Metrics::cluster_request_global_view_percent` + global cluster_index_intermediate_response: event(id: Metrics::ID, filter_name: string, index: Metrics::Index, val: count); + + ## This event is scheduled internally on workers to send result chunks. + global send_data: event(uid: string, id: ID, filter_name: string, data: MetricTable); + } -## This event is sent by the manager in a cluster to initiate the -## collection of metrics values for a filter. -global cluster_filter_request: event(uid: string, id: ID, filter_name: string); - -## This event is sent by nodes that are collecting metrics after receiving -## a request for the metric filter from the manager. -global cluster_filter_response: event(uid: string, id: ID, filter_name: string, data: MetricTable, done: bool); - -## This event is sent by the manager in a cluster to initiate the -## collection of a single index value from a filter. It's typically -## used to get intermediate updates before the break interval triggers -## to speed detection of a value crossing a threshold. -global cluster_index_request: event(uid: string, id: ID, filter_name: string, index: Index); - -## This event is sent by nodes in response to a -## :bro:id:`cluster_index_request` event. -global cluster_index_response: event(uid: string, id: ID, filter_name: string, index: Index, val: count); - -## This is sent by workers to indicate that they crossed the percent of the -## current threshold by the percentage defined globally in -## :bro:id:`cluster_request_global_view_percent` -global cluster_index_intermediate_response: event(id: Metrics::ID, filter_name: string, index: Metrics::Index, val: count); - -## This event is scheduled internally on workers to send result chunks. -global send_data: event(uid: string, id: ID, filter_name: string, data: MetricTable); # This is maintained by managers so they can know what data they requested and # when they requested it. @@ -86,8 +89,8 @@ global index_requests: table[string, ID, string, Index] of count &create_expire= global recent_global_view_indexes: table[ID, string, Index] of count &create_expire=5mins &default=0; # Add events to the cluster framework to make this work. -redef Cluster::manager_events += /Metrics::cluster_(filter_request|index_request)/; -redef Cluster::worker_events += /Metrics::cluster_(filter_response|index_response|index_intermediate_response)/; +redef Cluster::manager2worker_events += /Metrics::cluster_(filter_request|index_request)/; +redef Cluster::worker2manager_events += /Metrics::cluster_(filter_response|index_response|index_intermediate_response)/; @if ( Cluster::local_node_type() != Cluster::MANAGER ) # This is done on all non-manager node types in the event that a metric is @@ -258,4 +261,4 @@ event Metrics::cluster_filter_response(uid: string, id: ID, filter_name: string, } } -@endif \ No newline at end of file +@endif diff --git a/scripts/base/frameworks/metrics/main.bro b/scripts/base/frameworks/metrics/main.bro index 2dd9e19b03..d322d128fe 100644 --- a/scripts/base/frameworks/metrics/main.bro +++ b/scripts/base/frameworks/metrics/main.bro @@ -1,13 +1,16 @@ -##! This is the implementation of the metrics framework. +##! The metrics framework provides a way to count and measure data. @load base/frameworks/notice module Metrics; export { - redef enum Log::ID += { METRICS }; + ## The metrics logging stream identifier. + redef enum Log::ID += { LOG }; + ## Identifiers for metrics to collect. type ID: enum { + ## Blank placeholder value. NOTHING, }; @@ -15,10 +18,13 @@ export { ## current value to the logging stream. const default_break_interval = 15mins &redef; - ## This is the interval for how often notices will happen after they have - ## already fired. + ## This is the interval for how often threshold based notices will happen + ## after they have already fired. const renotice_interval = 1hr &redef; + ## Represents a thing which is having metrics collected for it. An instance + ## of this record type and a :bro:type:`Metrics::ID` together represent a + ## single measurement. type Index: record { ## Host is the value to which this metric applies. host: addr &optional; @@ -37,17 +43,30 @@ export { network: subnet &optional; } &log; + ## The record type that is used for logging metrics. type Info: record { + ## Timestamp at which the metric was "broken". ts: time &log; + ## What measurement the metric represents. metric_id: ID &log; + ## The name of the filter being logged. :bro:type:`Metrics::ID` values + ## can have multiple filters which represent different perspectives on + ## the data so this is necessary to understand the value. filter_name: string &log; + ## What the metric value applies to. index: Index &log; + ## The simple numeric value of the metric. value: count &log; }; - # TODO: configure a metrics filter logging stream to log the current + # TODO: configure a metrics filter logging stream to log the current # metrics configuration in case someone is looking through # old logs and the configuration has changed since then. + + ## Filters define how the data from a metric is aggregated and handled. + ## Filters can be used to set how often the measurements are cut or "broken" + ## and logged or how the data within them is aggregated. It's also + ## possible to disable logging and use filters for thresholding. type Filter: record { ## The :bro:type:`Metrics::ID` that this filter applies to. id: ID &optional; @@ -62,7 +81,7 @@ export { aggregation_mask: count &optional; ## This is essentially a mapping table between addresses and subnets. aggregation_table: table[subnet] of subnet &optional; - ## The interval at which the metric should be "broken" and written + ## The interval at which this filter should be "broken" and written ## to the logging stream. The counters are also reset to zero at ## this time so any threshold based detection needs to be set to a ## number that should be expected to happen within this period. @@ -79,7 +98,7 @@ export { notice_threshold: count &optional; ## A series of thresholds at which to generate notices. notice_thresholds: vector of count &optional; - ## How often this notice should be raised for this metric index. It + ## How often this notice should be raised for this filter. It ## will be generated everytime it crosses a threshold, but if the ## $break_interval is set to 5mins and this is set to 1hr the notice ## only be generated once per hour even if something crosses the @@ -87,15 +106,43 @@ export { notice_freq: interval &optional; }; + ## Function to associate a metric filter with a metric ID. + ## + ## id: The metric ID that the filter should be associated with. + ## + ## filter: The record representing the filter configuration. global add_filter: function(id: ID, filter: Filter); + + ## Add data into a :bro:type:`Metrics::ID`. This should be called when + ## a script has measured some point value and is ready to increment the + ## counters. + ## + ## id: The metric ID that the data represents. + ## + ## index: The metric index that the value is to be added to. + ## + ## increment: How much to increment the counter by. global add_data: function(id: ID, index: Index, increment: count); + + ## Helper function to represent a :bro:type:`Metrics::Index` value as + ## a simple string + ## + ## index: The metric index that is to be converted into a string. + ## + ## Returns: A string reprentation of the metric index. global index2str: function(index: Index): string; - # This is the event that is used to "finish" metrics and adapt the metrics - # framework for clustered or non-clustered usage. + ## Event that is used to "finish" metrics and adapt the metrics + ## framework for clustered or non-clustered usage. + ## + ## ..note: This is primarily intended for internal use. global log_it: event(filter: Filter); + ## Event to access metrics records as they are passed to the logging framework. global log_metrics: event(rec: Info); + + ## Type to store a table of metrics values. Interal use only! + type MetricTable: table[Index] of count &default=0; } redef record Notice::Info += { @@ -105,7 +152,6 @@ redef record Notice::Info += { global metric_filters: table[ID] of vector of Filter = table(); global filter_store: table[ID, string] of Filter = table(); -type MetricTable: table[Index] of count &default=0; # This is indexed by metric ID and stream filter name. global store: table[ID, string] of MetricTable = table() &default=table(); @@ -124,7 +170,7 @@ global thresholds: table[ID, string, Index] of count = {} &create_expire=renotic event bro_init() &priority=5 { - Log::create_stream(METRICS, [$columns=Info, $ev=log_metrics]); + Log::create_stream(Metrics::LOG, [$columns=Info, $ev=log_metrics]); } function index2str(index: Index): string @@ -151,7 +197,7 @@ function write_log(ts: time, filter: Filter, data: MetricTable) $value=val]; if ( filter$log ) - Log::write(METRICS, m); + Log::write(Metrics::LOG, m); } } @@ -218,6 +264,10 @@ function add_data(id: ID, index: Index, increment: count) } else if ( filter?$aggregation_table ) { + # Don't add the data if the aggregation table doesn't include + # the given host address. + if ( index$host !in filter$aggregation_table ) + return; index$network = filter$aggregation_table[index$host]; delete index$host; } diff --git a/scripts/base/frameworks/metrics/non-cluster.bro b/scripts/base/frameworks/metrics/non-cluster.bro index a467ebf714..85c050fb25 100644 --- a/scripts/base/frameworks/metrics/non-cluster.bro +++ b/scripts/base/frameworks/metrics/non-cluster.bro @@ -1,3 +1,4 @@ +@load ./main module Metrics; @@ -17,4 +18,4 @@ function data_added(filter: Filter, index: Index, val: count) { if ( check_notice(filter, index, val) ) do_notice(filter, index, val); - } \ No newline at end of file + } diff --git a/scripts/base/frameworks/notice/__load__.bro b/scripts/base/frameworks/notice/__load__.bro index 2cc93ee933..4548e98dc2 100644 --- a/scripts/base/frameworks/notice/__load__.bro +++ b/scripts/base/frameworks/notice/__load__.bro @@ -8,6 +8,16 @@ @load ./actions/page @load ./actions/add-geodata -# There shouldn't be any defaul toverhead from loading these since they +# There shouldn't be any default overhead from loading these since they # *should* only do anything when notices have the ACTION_EMAIL action applied. @load ./extend-email/hostnames + +# The cluster framework must be loaded first. +@load base/frameworks/cluster + +@if ( Cluster::is_enabled() ) +@load ./cluster +@endif + +# Load here so that it can check whether clustering is enabled. +@load ./actions/pp-alarms diff --git a/scripts/base/frameworks/notice/actions/add-geodata.bro b/scripts/base/frameworks/notice/actions/add-geodata.bro index 71e9c6b490..9f6909595c 100644 --- a/scripts/base/frameworks/notice/actions/add-geodata.bro +++ b/scripts/base/frameworks/notice/actions/add-geodata.bro @@ -4,6 +4,10 @@ ##! probably a safe assumption to make in most cases. If both addresses ##! are remote, it will use the $src address. +@load ../main +@load base/frameworks/notice +@load base/utils/site + module Notice; export { @@ -27,6 +31,7 @@ export { ## Add a helper to the notice policy for looking up GeoIP data. redef Notice::policy += { [$pred(n: Notice::Info) = { return (n$note in Notice::lookup_location_types); }, + $action = ACTION_ADD_GEODATA, $priority = 10], }; } @@ -44,4 +49,4 @@ event notice(n: Notice::Info) &priority=10 else if ( n?$dst && ! Site::is_local_addr(n$dst) ) n$remote_location = lookup_location(n$dst); } - } \ No newline at end of file + } diff --git a/scripts/base/frameworks/notice/actions/drop.bro b/scripts/base/frameworks/notice/actions/drop.bro index fc1f608f9f..0116dd4ed4 100644 --- a/scripts/base/frameworks/notice/actions/drop.bro +++ b/scripts/base/frameworks/notice/actions/drop.bro @@ -1,6 +1,8 @@ ##! This script extends the built in notice code to implement the IP address ##! dropping functionality. +@load ../main + module Notice; export { @@ -31,4 +33,4 @@ event bro_init() }; add Notice::sync_functions[drop_func]; - } \ No newline at end of file + } diff --git a/scripts/base/frameworks/notice/actions/email_admin.bro b/scripts/base/frameworks/notice/actions/email_admin.bro index c03629d885..7484a1c606 100644 --- a/scripts/base/frameworks/notice/actions/email_admin.bro +++ b/scripts/base/frameworks/notice/actions/email_admin.bro @@ -1,10 +1,18 @@ +##! Adds a new notice action type which can be used to email notices +##! to the administrators of a particular address space as set by +##! :bro:id:`Site::local_admins` if the notice contains a source +##! or destination address that lies within their space. + +@load ../main +@load base/utils/site + module Notice; export { redef enum Action += { ## Indicate that the generated email should be addressed to the - ## appropriate email addresses as found in the - ## :bro:id:`Site::addr_to_emails` variable based on the relevant + ## appropriate email addresses as found by the + ## :bro:id:`Site::get_emails` function based on the relevant ## address or addresses indicated in the notice. ACTION_EMAIL_ADMIN }; diff --git a/scripts/base/frameworks/notice/actions/page.bro b/scripts/base/frameworks/notice/actions/page.bro index 059a92c0c9..16a3463126 100644 --- a/scripts/base/frameworks/notice/actions/page.bro +++ b/scripts/base/frameworks/notice/actions/page.bro @@ -1,10 +1,13 @@ +##! Allows configuration of a pager email address to which notices can be sent. + +@load ../main module Notice; export { redef enum Action += { ## Indicates that the notice should be sent to the pager email address - ## configured in the :bro:id:`mail_page_dest` variable. + ## configured in the :bro:id:`Notice::mail_page_dest` variable. ACTION_PAGE }; @@ -16,4 +19,4 @@ event notice(n: Notice::Info) &priority=-5 { if ( ACTION_PAGE in n$actions ) email_notice_to(n, mail_page_dest, F); - } \ No newline at end of file + } diff --git a/scripts/base/frameworks/notice/actions/pp-alarms.bro b/scripts/base/frameworks/notice/actions/pp-alarms.bro new file mode 100644 index 0000000000..82fda6db6c --- /dev/null +++ b/scripts/base/frameworks/notice/actions/pp-alarms.bro @@ -0,0 +1,250 @@ +##! Notice extension that mails out a pretty-printed version of alarm.log +##! in regular intervals, formatted for better human readability. If activated, +##! that replaces the default summary mail having the raw log output. + +@load base/frameworks/cluster +@load ../main + +module Notice; + +export { + ## Activate pretty-printed alarm summaries. + const pretty_print_alarms = T &redef; + + ## Address to send the pretty-printed reports to. Default if not set is + ## :bro:id:`Notice::mail_dest`. + const mail_dest_pretty_printed = "" &redef; + ## If an address from one of these networks is reported, we mark + ## the entry with an additional quote symbol (i.e., ">"). Many MUAs + ## then highlight such lines differently. + global flag_nets: set[subnet] &redef; + + ## Function that renders a single alarm. Can be overidden. + global pretty_print_alarm: function(out: file, n: Info) &redef; + + ## Force generating mail file, even if reading from traces or no mail + ## destination is defined. This is mainly for testing. + global force_email_summaries = F &redef; +} + +# We maintain an old-style file recording the pretty-printed alarms. +const pp_alarms_name = "alarm-mail.txt"; +global pp_alarms: file; +global pp_alarms_open: bool = F; + +# Returns True if pretty-printed alarm summaries are activated. +function want_pp() : bool + { + if ( force_email_summaries ) + return T; + + return (pretty_print_alarms && ! reading_traces() + && (mail_dest != "" || mail_dest_pretty_printed != "")); + } + +# Opens and intializes the output file. +function pp_open() + { + if ( pp_alarms_open ) + return; + + pp_alarms_open = T; + pp_alarms = open(pp_alarms_name); + } + +# Closes and mails out the current output file. +function pp_send(rinfo: Log::RotationInfo) + { + if ( ! pp_alarms_open ) + return; + + write_file(pp_alarms, "\n\n--\n[Automatically generated]\n\n"); + close(pp_alarms); + pp_alarms_open = F; + + local from = strftime("%H:%M:%S", rinfo$open); + local to = strftime("%H:%M:%S", rinfo$close); + local subject = fmt("Alarm summary from %s-%s", from, to); + local dest = mail_dest_pretty_printed != "" ? mail_dest_pretty_printed + : mail_dest; + + if ( dest == "" ) + # No mail destination configured, just leave the file alone. This is mainly for + # testing. + return; + + local headers = email_headers(subject, dest); + + local header_name = pp_alarms_name + ".tmp"; + local header = open(header_name); + write_file(header, headers + "\n"); + close(header); + + system(fmt("/bin/cat %s %s | %s -t -oi && /bin/rm -f %s %s", + header_name, pp_alarms_name, sendmail, header_name, pp_alarms_name)); + } + +# Postprocessor function that triggers the email. +function pp_postprocessor(info: Log::RotationInfo): bool + { + if ( want_pp() ) + pp_send(info); + + return T; + } + +event bro_init() + { + if ( ! want_pp() ) + return; + + # This replaces the standard non-pretty-printing filter. + Log::add_filter(Notice::ALARM_LOG, + [$name="alarm-mail", $writer=Log::WRITER_NONE, + $interv=Log::default_rotation_interval, + $postprocessor=pp_postprocessor]); + } + +event notice(n: Notice::Info) &priority=-5 + { + if ( ! want_pp() ) + return; + + if ( ACTION_ALARM !in n$actions ) + return; + + if ( ! pp_alarms_open ) + pp_open(); + + pretty_print_alarm(pp_alarms, n); + } + +function do_msg(out: file, n: Info, line1: string, line2: string, line3: string, host1: addr, name1: string, host2: addr, name2: string) + { + local country = ""; +@ifdef ( Notice::ACTION_ADD_GEODATA ) # Make tests happy, cyclic dependency. + if ( n?$remote_location && n$remote_location?$country_code ) + country = fmt(" (remote location %s)", n$remote_location$country_code); +@endif + + line1 = cat(line1, country); + + local resolved = ""; + + if ( host1 != 0.0.0.0 ) + resolved = fmt("%s # %s = %s", resolved, host1, name1); + + if ( host2 != 0.0.0.0 ) + resolved = fmt("%s %s = %s", resolved, host2, name2); + + print out, line1; + print out, line2; + if ( line3 != "" ) + print out, line3; + if ( resolved != "" ) + print out, resolved; + print out, ""; + } + +# Default pretty-printer. +function pretty_print_alarm(out: file, n: Info) + { + local pdescr = ""; + +@if ( Cluster::is_enabled() ) + pdescr = "local"; + + if ( n?$src_peer ) + pdescr = n$src_peer?$descr ? n$src_peer$descr : fmt("%s", n$src_peer$host); + + pdescr = fmt("<%s> ", pdescr); +@endif + + local msg = fmt( "%s%s", pdescr, n$msg); + + local who = ""; + local h1 = 0.0.0.0; + local h2 = 0.0.0.0; + + local orig_p = ""; + local resp_p = ""; + + if ( n?$id ) + { + h1 = n$id$orig_h; + h2 = n$id$resp_h; + who = fmt("%s:%s -> %s:%s", h1, n$id$orig_p, h2, n$id$resp_p); + } + else if ( n?$src && n?$dst ) + { + h1 = n$src; + h2 = n$dst; + who = fmt("%s -> %s", h1, h2); + } + else if ( n?$src ) + { + h1 = n$src; + who = fmt("%s%s", h1, (n?$p ? fmt(":%s", n$p) : "")); + } + + if ( n?$uid ) + who = fmt("%s (uid %s)", who, n$uid ); + + local flag = (h1 in flag_nets || h2 in flag_nets); + + local line1 = fmt(">%s %D %s %s", (flag ? ">" : " "), network_time(), n$note, who); + local line2 = fmt(" %s", msg); + local line3 = n?$sub ? fmt(" %s", n$sub) : ""; + + if ( h1 == 0.0.0.0 ) + { + do_msg(out, n, line1, line2, line3, h1, "", h2, ""); + return; + } + + if ( reading_traces() ) + { + do_msg(out, n, line1, line2, line3, h1, "", h2, ""); + return; + } + + when ( local h1name = lookup_addr(h1) ) + { + if ( h2 == 0.0.0.0 ) + { + do_msg(out, n, line1, line2, line3, h1, h1name, h2, ""); + return; + } + + when ( local h2name = lookup_addr(h2) ) + { + do_msg(out, n, line1, line2, line3, h1, h1name, h2, h2name); + return; + } + timeout 5secs + { + do_msg(out, n, line1, line2, line3, h1, h1name, h2, "(dns timeout)"); + return; + } + } + + timeout 5secs + { + if ( h2 == 0.0.0.0 ) + { + do_msg(out, n, line1, line2, line3, h1, "(dns timeout)", h2, ""); + return; + } + + when ( local h2name_ = lookup_addr(h2) ) + { + do_msg(out, n, line1, line2, line3, h1, "(dns timeout)", h2, h2name_); + return; + } + timeout 5secs + { + do_msg(out, n, line1, line2, line3, h1, "(dns timeout)", h2, "(dns timeout)"); + return; + } + } + } diff --git a/scripts/base/frameworks/notice/cluster.bro b/scripts/base/frameworks/notice/cluster.bro new file mode 100644 index 0000000000..281901cf31 --- /dev/null +++ b/scripts/base/frameworks/notice/cluster.bro @@ -0,0 +1,55 @@ +##! Implements notice functionality across clusters. Worker nodes +##! will disable notice/alarm logging streams and forward notice +##! events to the manager node for logging/processing. + +@load ./main +@load base/frameworks/cluster + +module Notice; + +export { + ## This is the event used to transport notices on the cluster. + ## + ## n: The notice information to be sent to the cluster manager for + ## further processing. + global cluster_notice: event(n: Notice::Info); +} + +## Manager can communicate notice suppression to workers. +redef Cluster::manager2worker_events += /Notice::begin_suppression/; +## Workers needs need ability to forward notices to manager. +redef Cluster::worker2manager_events += /Notice::cluster_notice/; + +@if ( Cluster::local_node_type() != Cluster::MANAGER ) +# The notice policy is completely handled by the manager and shouldn't be +# done by workers or proxies to save time for packet processing. +redef policy = {}; + +event Notice::begin_suppression(n: Notice::Info) + { + suppressing[n$note, n$identifier] = n; + } + +event Notice::notice(n: Notice::Info) + { + # Send the locally generated notice on to the manager. + event Notice::cluster_notice(n); + } + +event bro_init() &priority=-3 + { + # Workers and proxies need to disable the notice streams because notice + # events are forwarded directly instead of being logged remotely. + Log::disable_stream(Notice::LOG); + Log::disable_stream(Notice::POLICY_LOG); + Log::disable_stream(Notice::ALARM_LOG); + } +@endif + +@if ( Cluster::local_node_type() == Cluster::MANAGER ) +event Notice::cluster_notice(n: Notice::Info) + { + # Raise remotely received notices on the manager + NOTICE(n); + } +@endif diff --git a/scripts/base/frameworks/notice/extend-email/hostnames.bro b/scripts/base/frameworks/notice/extend-email/hostnames.bro index da2d0d5d0f..2ec6dbb23f 100644 --- a/scripts/base/frameworks/notice/extend-email/hostnames.bro +++ b/scripts/base/frameworks/notice/extend-email/hostnames.bro @@ -1,40 +1,52 @@ +##! Loading this script extends the :bro:enum:`Notice::ACTION_EMAIL` action +##! by appending to the email the hostnames associated with +##! :bro:type:`Notice::Info`'s *src* and *dst* fields as determined by a +##! DNS lookup. + +@load ../main module Notice; -# This probably doesn't actually work due to the async lookup_addr. +# We have to store references to the notices here because the when statement +# clones the frame which doesn't give us access to modify values outside +# of it's execution scope. (we get a clone of the notice instead of a +# reference to the original notice) +global tmp_notice_storage: table[string] of Notice::Info &create_expire=max_email_delay+10secs; + event Notice::notice(n: Notice::Info) &priority=10 { if ( ! n?$src && ! n?$dst ) return; - + # This should only be done for notices that are being sent to email. if ( ACTION_EMAIL !in n$actions ) return; - + + # I'm not recovering gracefully from the when statements because I want + # the notice framework to detect that something has exceeded the maximum + # allowed email delay and tell the user. + local uid = unique_id(""); + tmp_notice_storage[uid] = n; + local output = ""; if ( n?$src ) { + add n$email_delay_tokens["hostnames-src"]; when ( local src_name = lookup_addr(n$src) ) { - output = cat(output, "orig_h/src: ", src_name, "\n"); - } - timeout 5secs - { - output = cat(output, "orig_h/src: \n"); + output = string_cat("orig/src hostname: ", src_name, "\n"); + tmp_notice_storage[uid]$email_body_sections[|tmp_notice_storage[uid]$email_body_sections|] = output; + delete tmp_notice_storage[uid]$email_delay_tokens["hostnames-src"]; } } if ( n?$dst ) { + add n$email_delay_tokens["hostnames-dst"]; when ( local dst_name = lookup_addr(n$dst) ) { - output = cat(output, "resp_h/dst: ", dst_name, "\n"); - } - timeout 5secs - { - output = cat(output, "resp_h/dst: \n"); + output = string_cat("resp/dst hostname: ", dst_name, "\n"); + tmp_notice_storage[uid]$email_body_sections[|tmp_notice_storage[uid]$email_body_sections|] = output; + delete tmp_notice_storage[uid]$email_delay_tokens["hostnames-dst"]; } } - - if ( output != "" ) - n$email_body_sections[|n$email_body_sections|] = output; } diff --git a/scripts/base/frameworks/notice/main.bro b/scripts/base/frameworks/notice/main.bro index ea7a472031..e9b29e7392 100644 --- a/scripts/base/frameworks/notice/main.bro +++ b/scripts/base/frameworks/notice/main.bro @@ -2,67 +2,89 @@ ##! are odd or potentially bad. Decisions of the meaning of various notices ##! need to be done per site because Bro does not ship with assumptions about ##! what is bad activity for sites. More extensive documetation about using -##! the notice framework can be found in the documentation section of the -##! http://www.bro-ids.org/ website. +##! the notice framework can be found in :doc:`/notice`. module Notice; export { - redef enum Log::ID += { - ## This is the primary logging stream for notices. It must always be - ## referenced with the module name included because the name is - ## also used by the global function :bro:id:`NOTICE`. - NOTICE, + redef enum Log::ID += { + ## This is the primary logging stream for notices. + LOG, ## This is the notice policy auditing log. It records what the current ## notice policy is at Bro init time. - NOTICE_POLICY, + POLICY_LOG, ## This is the alarm stream. - ALARM, + ALARM_LOG, }; - ## Scripts creating new notices need to redef this enum to add their own + ## Scripts creating new notices need to redef this enum to add their own ## specific notice types which would then get used when they call the ## :bro:id:`NOTICE` function. The convention is to give a general category - ## along with the specific notice separating words with underscores and using - ## leading capitals on each word except for abbreviations which are kept in - ## all capitals. For example, SSH::Login is for heuristically guessed - ## successful SSH logins. + ## along with the specific notice separating words with underscores and + ## using leading capitals on each word except for abbreviations which are + ## kept in all capitals. For example, SSH::Login is for heuristically + ## guessed successful SSH logins. type Type: enum { ## Notice reporting a count of how often a notice occurred. Tally, }; - + ## These are values representing actions that can be taken with notices. type Action: enum { ## Indicates that there is no action to be taken. ACTION_NONE, ## Indicates that the notice should be sent to the notice logging stream. ACTION_LOG, - ## Indicates that the notice should be sent to the email address(es) + ## Indicates that the notice should be sent to the email address(es) ## configured in the :bro:id:`Notice::mail_dest` variable. ACTION_EMAIL, - ## Indicates that the notice should be alarmed. + ## Indicates that the notice should be alarmed. A readable ASCII + ## version of the alarm log is emailed in bulk to the address(es) + ## configured in :bro:id:`Notice::mail_dest`. ACTION_ALARM, + ## Indicates that the notice should not be supressed by the normal + ## duplicate notice suppression that the notice framework does. + ACTION_NO_SUPPRESS, }; - + + ## The notice framework is able to do automatic notice supression by + ## utilizing the $identifier field in :bro:type:`Notice::Info` records. + ## Set this to "0secs" to completely disable automated notice suppression. + const default_suppression_interval = 1hrs &redef; + type Info: record { + ## An absolute time indicating when the notice occurred, defaults + ## to the current network time. ts: time &log &optional; + + ## A connection UID which uniquely identifies the endpoints + ## concerned with the notice. uid: string &log &optional; + + ## A connection 4-tuple identifying the endpoints concerned with the + ## notice. id: conn_id &log &optional; - ## These are shorthand ways of giving the uid and id to a notice. The + ## A shorthand way of giving the uid and id to a notice. The ## reference to the actual connection will be deleted after applying ## the notice policy. conn: connection &optional; + ## A shorthand way of giving the uid and id to a notice. The + ## reference to the actual connection will be deleted after applying + ## the notice policy. iconn: icmp_conn &optional; - - ## The :bro:enum:`Notice::Type` of the notice. + + ## The transport protocol. Filled automatically when either conn, iconn + ## or p is specified. + proto: transport_proto &log &optional; + + ## The :bro:type:`Notice::Type` of the notice. note: Type &log; ## The human readable message for the notice. msg: string &log &optional; ## The human readable sub-message. sub: string &log &optional; - + ## Source address, if we don't have a :bro:type:`conn_id`. src: addr &log &optional; ## Destination address. @@ -71,136 +93,284 @@ export { p: port &log &optional; ## Associated count, or perhaps a status code. n: count &log &optional; - + ## Peer that raised this notice. src_peer: event_peer &optional; ## Textual description for the peer that raised this notice. peer_descr: string &log &optional; - + ## The actions which have been applied to this notice. actions: set[Notice::Action] &log &optional; - + ## These are policy items that returned T and applied their action ## to the notice. - ## TODO: this can't take set() as a default. (bug) policy_items: set[count] &log &optional; - + ## By adding chunks of text into this element, other scripts can ## expand on notices that are being emailed. The normal way to add text ## is to extend the vector by handling the :bro:id:`Notice::notice` ## event and modifying the notice in place. - email_body_sections: vector of string &default=vector(); + email_body_sections: vector of string &optional; + + ## Adding a string "token" to this set will cause the notice framework's + ## built-in emailing functionality to delay sending the email until + ## either the token has been removed or the email has been delayed + ## for :bro:id:`Notice::max_email_delay`. + email_delay_tokens: set[string] &optional; + + ## This field is to be provided when a notice is generated for the + ## purpose of deduplicating notices. The identifier string should + ## be unique for a single instance of the notice. This field should be + ## filled out in almost all cases when generating notices to define + ## when a notice is conceptually a duplicate of a previous notice. + ## + ## For example, an SSL certificate that is going to expire soon should + ## always have the same identifier no matter the client IP address + ## that connected and resulted in the certificate being exposed. In + ## this case, the resp_h, resp_p, and hash of the certificate would be + ## used to create this value. The hash of the cert is included + ## because servers can return multiple certificates on the same port. + ## + ## Another example might be a host downloading a file which triggered + ## a notice because the MD5 sum of the file it downloaded was known + ## by some set of intelligence. In that case, the orig_h (client) + ## and MD5 sum would be used in this field to dedup because if the + ## same file is downloaded over and over again you really only want to + ## know about it a single time. This makes it possible to send those + ## notices to email without worrying so much about sending thousands + ## of emails. + identifier: string &optional; + + ## This field indicates the length of time that this + ## unique notice should be suppressed. This field is automatically + ## filled out and should not be written to by any other script. + suppress_for: interval &log &optional; }; - + ## Ignored notice types. const ignored_types: set[Notice::Type] = {} &redef; ## Emailed notice types. const emailed_types: set[Notice::Type] = {} &redef; ## Alarmed notice types. const alarmed_types: set[Notice::Type] = {} &redef; - + ## Types that should be suppressed for the default suppression interval. + const not_suppressed_types: set[Notice::Type] = {} &redef; + ## This table can be used as a shorthand way to modify suppression + ## intervals for entire notice types. + const type_suppression_intervals: table[Notice::Type] of interval = {} &redef; + ## This is the record that defines the items that make up the notice policy. type PolicyItem: record { - ## This is the exact positional order in which the :bro:type:`PolicyItem` - ## records are checked. This is set internally by the notice framework. + ## This is the exact positional order in which the + ## :bro:type:`Notice::PolicyItem` records are checked. + ## This is set internally by the notice framework. position: count &log &optional; ## Define the priority for this check. Items are checked in ordered ## from highest value (10) to lowest value (0). priority: count &log &default=5; ## An action given to the notice if the predicate return true. - result: Notice::Action &log &default=ACTION_NONE; - ## The pred (predicate) field is a function that returns a boolean T - ## or F value. If the predicate function return true, the action in - ## this record is applied to the notice that is given as an argument - ## to the predicate function. - pred: function(n: Notice::Info): bool; - ## Indicates this item should terminate policy processing if the + action: Notice::Action &log &default=ACTION_NONE; + ## The pred (predicate) field is a function that returns a boolean T + ## or F value. If the predicate function return true, the action in + ## this record is applied to the notice that is given as an argument + ## to the predicate function. If no predicate is supplied, it's + ## assumed that the PolicyItem always applies. + pred: function(n: Notice::Info): bool &log &optional; + ## Indicates this item should terminate policy processing if the ## predicate returns T. halt: bool &log &default=F; + ## This defines the length of time that this particular notice should + ## be supressed. + suppress_for: interval &log &optional; }; - ## This is the where the :bro:id:`Notice::policy` is defined. All notice - ## processing is done through this variable. + ## Defines a notice policy that is extensible on a per-site basis. + ## All notice processing is done through this variable. const policy: set[PolicyItem] = { [$pred(n: Notice::Info) = { return (n$note in Notice::ignored_types); }, $halt=T, $priority = 9], + [$pred(n: Notice::Info) = { return (n$note in Notice::not_suppressed_types); }, + $action = ACTION_NO_SUPPRESS, + $priority = 9], [$pred(n: Notice::Info) = { return (n$note in Notice::alarmed_types); }, + $action = ACTION_ALARM, $priority = 8], [$pred(n: Notice::Info) = { return (n$note in Notice::emailed_types); }, - $result = ACTION_EMAIL, + $action = ACTION_EMAIL, $priority = 8], - [$pred(n: Notice::Info) = { return T; }, - $result = ACTION_LOG, + [$pred(n: Notice::Info) = { + if (n$note in Notice::type_suppression_intervals) + { + n$suppress_for=Notice::type_suppression_intervals[n$note]; + return T; + } + return F; + }, + $action = ACTION_NONE, + $priority = 8], + [$action = ACTION_LOG, $priority = 0], } &redef; - + ## Local system sendmail program. const sendmail = "/usr/sbin/sendmail" &redef; - ## Email address to send notices with the :bro:enum:`ACTION_EMAIL` action. + ## Email address to send notices with the :bro:enum:`Notice::ACTION_EMAIL` + ## action or to send bulk alarm logs on rotation with + ## :bro:enum:`Notice::ACTION_ALARM`. const mail_dest = "" &redef; - + ## Address that emails will be from. const mail_from = "Big Brother " &redef; ## Reply-to address used in outbound email. const reply_to = "" &redef; ## Text string prefixed to the subject of all emails sent out. const mail_subject_prefix = "[Bro]" &redef; + ## The maximum amount of time a plugin can delay email from being sent. + const max_email_delay = 15secs &redef; - ## This is the event that is called as the entry point to the - ## notice framework by the global :bro:id:`NOTICE` function. By the time + ## A log postprocessing function that implements emailing the contents + ## of a log upon rotation to any configured :bro:id:`Notice::mail_dest`. + ## The rotated log is removed upon being sent. + ## + ## info: A record containing the rotated log file information. + ## + ## Returns: True. + global log_mailing_postprocessor: function(info: Log::RotationInfo): bool; + + ## This is the event that is called as the entry point to the + ## notice framework by the global :bro:id:`NOTICE` function. By the time ## this event is generated, default values have already been filled out in ## the :bro:type:`Notice::Info` record and synchronous functions in the - ## :bro:id:`Notice:sync_functions` have already been called. The notice + ## :bro:id:`Notice::sync_functions` have already been called. The notice ## policy has also been applied. + ## + ## n: The record containing notice data. global notice: event(n: Info); - ## This is a set of functions that provide a synchronous way for scripts + ## This is a set of functions that provide a synchronous way for scripts ## extending the notice framework to run before the normal event based ## notice pathway that most of the notice framework takes. This is helpful ## in cases where an action against a notice needs to happen immediately ## and can't wait the short time for the event to bubble up to the top of - ## the event queue. An example is the IP address dropping script that - ## can block IP addresses that have notices generated because it + ## the event queue. An example is the IP address dropping script that + ## can block IP addresses that have notices generated because it ## needs to operate closer to real time than the event queue allows it to. - ## Normally the event based extension model using the + ## Normally the event based extension model using the ## :bro:id:`Notice::notice` event will work fine if there aren't harder ## real time constraints. const sync_functions: set[function(n: Notice::Info)] = set() &redef; - + + ## This event is generated when a notice begins to be suppressed. + ## + ## n: The record containing notice data regarding the notice type + ## about to be suppressed. + global begin_suppression: event(n: Notice::Info); + + ## This event is generated on each occurence of an event being suppressed. + ## + ## n: The record containing notice data regarding the notice type + ## being suppressed. + global suppressed: event(n: Notice::Info); + + ## This event is generated when a notice stops being suppressed. + ## + ## n: The record containing notice data regarding the notice type + ## that was being suppressed. + global end_suppression: event(n: Notice::Info); + ## Call this function to send a notice in an email. It is already used - ## by default with the built in :bro:enum:`ACTION_EMAIL` and - ## :bro:enum:`ACTION_PAGE` actions. + ## by default with the built in :bro:enum:`Notice::ACTION_EMAIL` and + ## :bro:enum:`Notice::ACTION_PAGE` actions. + ## + ## n: The record of notice data to email. + ## + ## dest: The intended recipient of the notice email. + ## + ## extend: Whether to extend the email using the ``email_body_sections`` + ## field of *n*. global email_notice_to: function(n: Info, dest: string, extend: bool); + + ## Constructs mail headers to which an email body can be appended for + ## sending with sendmail. + ## + ## subject_desc: a subject string to use for the mail + ## + ## dest: recipient string to use for the mail + ## + ## Returns: a string of mail headers to which an email body can be appended + global email_headers: function(subject_desc: string, dest: string): string; - ## This is an internally used function, please ignore it. It's only used - ## for filling out missing details of :bro:type:`Notice:Info` records - ## before the synchronous and asynchronous event pathways have begun. - global apply_policy: function(n: Notice::Info); - - ## This event can be handled to access the :bro:type:`Info` + ## This event can be handled to access the :bro:type:`Notice::Info` ## record as it is sent on to the logging framework. + ## + ## rec: The record containing notice data before it is logged. global log_notice: event(rec: Info); + + ## This is an internal wrapper for the global :bro:id:`NOTICE` function; + ## disregard. + ## + ## n: The record of notice data. + global internal_NOTICE: function(n: Notice::Info); } +# This is used as a hack to implement per-item expiration intervals. +function per_notice_suppression_interval(t: table[Notice::Type, string] of Notice::Info, idx: any): interval + { + local n: Notice::Type; + local s: string; + [n,s] = idx; + + local suppress_time = t[n,s]$suppress_for - (network_time() - t[n,s]$ts); + if ( suppress_time < 0secs ) + suppress_time = 0secs; + + # If there is no more suppression time left, the notice needs to be sent + # to the end_suppression event. + if ( suppress_time == 0secs ) + event Notice::end_suppression(t[n,s]); + + return suppress_time; + } + +# This is the internally maintained notice suppression table. It's +# indexed on the Notice::Type and the $identifier field from the notice. +global suppressing: table[Type, string] of Notice::Info = {} + &create_expire=0secs + &expire_func=per_notice_suppression_interval; + # This is an internal variable used to store the notice policy ordered by # priority. global ordered_policy: vector of PolicyItem = vector(); -event bro_init() +function log_mailing_postprocessor(info: Log::RotationInfo): bool { - Log::create_stream(NOTICE_POLICY, [$columns=PolicyItem]); - Log::create_stream(Notice::NOTICE, [$columns=Info, $ev=log_notice]); - - Log::create_stream(ALARM, [$columns=Notice::Info]); - # Make sure that this log is output as text so that it can be packaged - # up and emailed later. - Log::add_filter(ALARM, [$name="default", $writer=Log::WRITER_ASCII]); + if ( ! reading_traces() && mail_dest != "" ) + { + local headers = email_headers(fmt("Log Contents: %s", info$fname), + mail_dest); + local tmpfilename = fmt("%s.mailheaders.tmp", info$fname); + local tmpfile = open(tmpfilename); + write_file(tmpfile, headers); + close(tmpfile); + system(fmt("/bin/cat %s %s | %s -t -oi && /bin/rm %s %s", + tmpfilename, info$fname, sendmail, tmpfilename, info$fname)); + } + return T; + } + +event bro_init() &priority=5 + { + Log::create_stream(Notice::LOG, [$columns=Info, $ev=log_notice]); + + Log::create_stream(Notice::ALARM_LOG, [$columns=Notice::Info]); + # If Bro is configured for mailing notices, set up mailing for alarms. + # Make sure that this alarm log is also output as text so that it can + # be packaged up and emailed later. + if ( ! reading_traces() && mail_dest != "" ) + Log::add_filter(Notice::ALARM_LOG, + [$name="alarm-mail", $path="alarm-mail", $writer=Log::WRITER_ASCII, + $interv=24hrs, $postprocessor=log_mailing_postprocessor]); } - # TODO: need a way to call a Bro script level callback during file rotation. - # we need more than a just $postprocessor. - #redef Log::rotation_control += { - # [Log::WRITER_ASCII, "alarm"] = [$postprocessor="mail-alarms"]; - #}; # TODO: fix this. #function notice_tags(n: Notice::Info) : table[string] of string @@ -220,34 +390,80 @@ event bro_init() # return tgs; # } +function email_headers(subject_desc: string, dest: string): string + { + local header_text = string_cat( + "From: ", mail_from, "\n", + "Subject: ", mail_subject_prefix, " ", subject_desc, "\n", + "To: ", dest, "\n", + "User-Agent: Bro-IDS/", bro_version(), "\n"); + if ( reply_to != "" ) + header_text = string_cat(header_text, "Reply-To: ", reply_to, "\n"); + return header_text; + } + +event delay_sending_email(n: Notice::Info, dest: string, extend: bool) + { + email_notice_to(n, dest, extend); + } + function email_notice_to(n: Notice::Info, dest: string, extend: bool) { if ( reading_traces() || dest == "" ) return; - - local email_text = string_cat( - "From: ", mail_from, "\n", - "Subject: ", mail_subject_prefix, " ", fmt("%s", n$note), "\n", - "To: ", dest, "\n", - # TODO: BiF to get version (the resource_usage Bif seems like overkill). - "User-Agent: Bro-IDS/?.?.?\n"); - - if ( reply_to != "" ) - email_text = string_cat(email_text, "Reply-To: ", reply_to, "\n"); - - # The notice emails always start off with the human readable message. - email_text = string_cat(email_text, "\n", n$msg, "\n"); - + + if ( extend ) + { + if ( |n$email_delay_tokens| > 0 ) + { + # If we still are within the max_email_delay, keep delaying. + if ( n$ts + max_email_delay > network_time() ) + { + schedule 1sec { delay_sending_email(n, dest, extend) }; + return; + } + else + { + event reporter_info(network_time(), + fmt("Notice email delay tokens weren't released in time (%s).", n$email_delay_tokens), + ""); + } + } + } + + local email_text = email_headers(fmt("%s", n$note), dest); + + # First off, finish the headers and include the human readable messages + # then leave a blank line after the message. + email_text = string_cat(email_text, "\nMessage: ", n$msg); + if ( n?$sub ) + email_text = string_cat(email_text, "\nSub-message: ", n$sub); + + email_text = string_cat(email_text, "\n\n"); + + # Next, add information about the connection if it exists. + if ( n?$id ) + { + email_text = string_cat(email_text, "Connection: ", + fmt("%s", n$id$orig_h), ":", fmt("%d", n$id$orig_p), " -> ", + fmt("%s", n$id$resp_h), ":", fmt("%d", n$id$resp_p), "\n"); + if ( n?$uid ) + email_text = string_cat(email_text, "Connection uid: ", n$uid, "\n"); + } + else if ( n?$src ) + email_text = string_cat(email_text, "Address: ", fmt("%s", n$src), "\n"); + # Add the extended information if it's requested. if ( extend ) { + email_text = string_cat(email_text, "\nEmail Extensions\n"); + email_text = string_cat(email_text, "----------------\n"); for ( i in n$email_body_sections ) { - email_text = string_cat(email_text, "******************\n"); email_text = string_cat(email_text, n$email_body_sections[i], "\n"); } } - + email_text = string_cat(email_text, "\n\n--\n[Automatically generated]\n\n"); piped_exec(fmt("%s -t -oi", sendmail), email_text); } @@ -257,9 +473,34 @@ event notice(n: Notice::Info) &priority=-5 if ( ACTION_EMAIL in n$actions ) email_notice_to(n, mail_dest, T); if ( ACTION_LOG in n$actions ) - Log::write(Notice::NOTICE, n); + Log::write(Notice::LOG, n); if ( ACTION_ALARM in n$actions ) - Log::write(ALARM, n); + Log::write(Notice::ALARM_LOG, n); + + # Normally suppress further notices like this one unless directed not to. + # n$identifier *must* be specified for suppression to function at all. + if ( n?$identifier && + ACTION_NO_SUPPRESS !in n$actions && + [n$note, n$identifier] !in suppressing && + n$suppress_for != 0secs ) + { + suppressing[n$note, n$identifier] = n; + event Notice::begin_suppression(n); + } + } + +## This determines if a notice is being suppressed. It is only used +## internally as part of the mechanics for the global :bro:id:`NOTICE` +## function. +function is_being_suppressed(n: Notice::Info): bool + { + if ( n?$identifier && [n$note, n$identifier] in suppressing ) + { + event Notice::suppressed(n); + return T; + } + else + return F; } # Executes a script with all of the notice fields put into the @@ -270,9 +511,9 @@ function execute_with_notice(cmd: string, n: Notice::Info) #local tgs = tags(n); #system_env(cmd, tags); } - -# This is run synchronously as a function before all of the other -# notice related functions and events. It also modifies the + +# This is run synchronously as a function before all of the other +# notice related functions and events. It also modifies the # :bro:type:`Notice::Info` record in place. function apply_policy(n: Notice::Info) { @@ -287,7 +528,7 @@ function apply_policy(n: Notice::Info) if ( ! n?$uid ) n$uid = n$conn$uid; } - + if ( n?$id ) { if ( ! n?$src ) @@ -298,8 +539,12 @@ function apply_policy(n: Notice::Info) n$p = n$id$resp_p; } + if ( n?$p ) + n$proto = get_port_transport_proto(n$p); + if ( n?$iconn ) { + n$proto = icmp; if ( ! n?$src ) n$src = n$iconn$orig_h; if ( ! n?$dst ) @@ -309,55 +554,72 @@ function apply_policy(n: Notice::Info) if ( ! n?$src_peer ) n$src_peer = get_event_peer(); if ( ! n?$peer_descr ) - n$peer_descr = n$src_peer?$descr ? + n$peer_descr = n$src_peer?$descr ? n$src_peer$descr : fmt("%s", n$src_peer$host); - + if ( ! n?$actions ) n$actions = set(); - + + if ( ! n?$email_body_sections ) + n$email_body_sections = vector(); + if ( ! n?$email_delay_tokens ) + n$email_delay_tokens = set(); + if ( ! n?$policy_items ) n$policy_items = set(); - + for ( i in ordered_policy ) { - if ( ordered_policy[i]$pred(n) ) + # If there's no predicate or the predicate returns F. + if ( ! ordered_policy[i]?$pred || ordered_policy[i]$pred(n) ) { - add n$actions[ordered_policy[i]$result]; + add n$actions[ordered_policy[i]$action]; add n$policy_items[int_to_count(i)]; - + + # If the predicate matched and there was a suppression interval, + # apply it to the notice now. + if ( ordered_policy[i]?$suppress_for ) + n$suppress_for = ordered_policy[i]$suppress_for; + # If the policy item wants to halt policy processing, do it now! if ( ordered_policy[i]$halt ) break; } } - + + # Apply the suppression time after applying the policy so that policy + # items can give custom suppression intervals. If there is no + # suppression interval given yet, the default is applied. + if ( ! n?$suppress_for ) + n$suppress_for = default_suppression_interval; + # Delete the connection record if it's there so we aren't sending that - # to remote machines. It can cause problems due to the size of the + # to remote machines. It can cause problems due to the size of the # connection record. if ( n?$conn ) delete n$conn; if ( n?$iconn ) delete n$iconn; } - -# Create the ordered notice policy automatically which will be used at runtime + +# Create the ordered notice policy automatically which will be used at runtime # for prioritized matching of the notice policy. event bro_init() &priority=10 { + # Create the policy log here because it's only written to in this handler. + Log::create_stream(Notice::POLICY_LOG, [$columns=PolicyItem]); + local tmp: table[count] of set[PolicyItem] = table(); for ( pi in policy ) { if ( pi$priority < 0 || pi$priority > 10 ) - { - print "All Notice::PolicyItem priorities must be within 0 and 10"; - exit(); - } - + Reporter::fatal("All Notice::PolicyItem priorities must be within 0 and 10"); + if ( pi$priority !in tmp ) tmp[pi$priority] = set(); add tmp[pi$priority][pi]; } - + local rev_count = vector(10,9,8,7,6,5,4,3,2,1,0); for ( i in rev_count ) { @@ -368,24 +630,33 @@ event bro_init() &priority=10 { pi$position = |ordered_policy|; ordered_policy[|ordered_policy|] = pi; - Log::write(NOTICE_POLICY, pi); + Log::write(Notice::POLICY_LOG, pi); } } } } +function internal_NOTICE(n: Notice::Info) + { + # Suppress this notice if necessary. + if ( is_being_suppressed(n) ) + return; + + # Fill out fields that might be empty and do the policy processing. + apply_policy(n); + + # Run the synchronous functions with the notice. + for ( func in sync_functions ) + func(n); + + # Generate the notice event with the notice. + event Notice::notice(n); + } + module GLOBAL; ## This is the entry point in the global namespace for notice framework. function NOTICE(n: Notice::Info) { - # Fill out fields that might be empty and do the policy processing. - Notice::apply_policy(n); - - # Run the synchronous functions with the notice. - for ( func in Notice::sync_functions ) - func(n); - - # Generate the notice event with the notice. - event Notice::notice(n); + Notice::internal_NOTICE(n); } diff --git a/scripts/base/frameworks/notice/weird.bro b/scripts/base/frameworks/notice/weird.bro index 31ecd484e9..f894a42464 100644 --- a/scripts/base/frameworks/notice/weird.bro +++ b/scripts/base/frameworks/notice/weird.bro @@ -1,271 +1,349 @@ +##! This script provides a default set of actions to take for "weird activity" +##! events generated from Bro's event engine. Weird activity is defined as +##! unusual or exceptional activity that can indicate malformed connections, +##! traffic that doesn't conform to a particular protocol, malfunctioning +##! or misconfigured hardware, or even an attacker attempting to avoid/confuse +##! a sensor. Without context, it's hard to judge whether a particular +##! category of weird activity is interesting, but this script provides +##! a starting point for the user. + +@load base/utils/conn-ids +@load base/utils/site +@load ./main + module Weird; export { - redef enum Log::ID += { WEIRD }; + ## The weird logging stream identifier. + redef enum Log::ID += { LOG }; redef enum Notice::Type += { - ## Generic unusual but alarm-worthy activity. - Weird_Activity, - ## Possible evasion; usually just chud. - Retransmission_Inconsistency, - ## Could mean packet drop; could also be chud. - Ack_Above_Hole, - ## Data has sequence hole; perhaps due to filtering. - Content_Gap, + ## Generic unusual but notice-worthy weird activity. + Activity, }; + ## The record type which contains the column fields of the weird log. type Info: record { + ## The time when the weird occurred. ts: time &log; + ## If a connection is associated with this weird, this will be the + ## connection's unique ID. uid: string &log &optional; + ## conn_id for the optional connection. id: conn_id &log &optional; - msg: string &log; + ## The name of the weird that occurred. + name: string &log; + ## Additional information accompanying the weird if any. addl: string &log &optional; + ## Indicate if this weird was also turned into a notice. notice: bool &log &default=F; + ## The peer that originated this weird. This is helpful in cluster + ## deployments if a particular cluster node is having trouble to help + ## identify which node is having trouble. + peer: string &log &optional; }; - type WeirdAction: enum { - WEIRD_UNSPECIFIED, WEIRD_IGNORE, WEIRD_FILE, - WEIRD_NOTICE_ALWAYS, WEIRD_NOTICE_PER_CONN, - WEIRD_NOTICE_PER_ORIG, WEIRD_NOTICE_ONCE, + ## Types of actions that may be taken when handling weird activity events. + type Action: enum { + ## A dummy action indicating the user does not care what internal + ## decision is made regarding a given type of weird. + ACTION_UNSPECIFIED, + ## No action is to be taken. + ACTION_IGNORE, + ## Log the weird event every time it occurs. + ACTION_LOG, + ## Log the weird event only once. + ACTION_LOG_ONCE, + ## Log the weird event once per connection. + ACTION_LOG_PER_CONN, + ## Log the weird event once per originator host. + ACTION_LOG_PER_ORIG, + ## Always generate a notice associated with the weird event. + ACTION_NOTICE, + ## Generate a notice associated with the weird event only once. + ACTION_NOTICE_ONCE, + ## Generate a notice for the weird event once per connection. + ACTION_NOTICE_PER_CONN, + ## Generate a notice for the weird event once per originator host. + ACTION_NOTICE_PER_ORIG, }; - # Which of the above actions lead to logging. For internal use. - const notice_actions = { - WEIRD_NOTICE_ALWAYS, WEIRD_NOTICE_PER_CONN, - WEIRD_NOTICE_PER_ORIG, WEIRD_NOTICE_ONCE, - }; + ## A table specifying default/recommended actions per weird type. + const actions: table[string] of Action = { + ["unsolicited_SYN_response"] = ACTION_IGNORE, + ["above_hole_data_without_any_acks"] = ACTION_LOG, + ["active_connection_reuse"] = ACTION_LOG, + ["bad_HTTP_reply"] = ACTION_LOG, + ["bad_HTTP_version"] = ACTION_LOG, + ["bad_ICMP_checksum"] = ACTION_LOG_PER_ORIG, + ["bad_ident_port"] = ACTION_LOG, + ["bad_ident_reply"] = ACTION_LOG, + ["bad_ident_request"] = ACTION_LOG, + ["bad_rlogin_prolog"] = ACTION_LOG, + ["bad_rsh_prolog"] = ACTION_LOG, + ["rsh_text_after_rejected"] = ACTION_LOG, + ["bad_RPC"] = ACTION_LOG_PER_ORIG, + ["bad_RPC_program"] = ACTION_LOG, + ["bad_SYN_ack"] = ACTION_LOG, + ["bad_TCP_checksum"] = ACTION_LOG_PER_ORIG, + ["bad_UDP_checksum"] = ACTION_LOG_PER_ORIG, + ["baroque_SYN"] = ACTION_LOG, + ["base64_illegal_encoding"] = ACTION_LOG, + ["connection_originator_SYN_ack"] = ACTION_LOG_PER_ORIG, + ["corrupt_tcp_options"] = ACTION_LOG_PER_ORIG, + ["crud_trailing_HTTP_request"] = ACTION_LOG, + ["data_after_reset"] = ACTION_LOG, + ["data_before_established"] = ACTION_LOG, + ["data_without_SYN_ACK"] = ACTION_LOG, + ["DHCP_no_type_option"] = ACTION_LOG, + ["DHCP_wrong_msg_type"] = ACTION_LOG, + ["DHCP_wrong_op_type"] = ACTION_LOG, + ["DNS_AAAA_neg_length"] = ACTION_LOG, + ["DNS_Conn_count_too_large"] = ACTION_LOG, + ["DNS_NAME_too_long"] = ACTION_LOG, + ["DNS_RR_bad_length"] = ACTION_LOG, + ["DNS_RR_length_mismatch"] = ACTION_LOG, + ["DNS_RR_unknown_type"] = ACTION_LOG, + ["DNS_label_forward_compress_offset"] = ACTION_LOG_PER_ORIG, + ["DNS_label_len_gt_name_len"] = ACTION_LOG_PER_ORIG, + ["DNS_label_len_gt_pkt"] = ACTION_LOG_PER_ORIG, + ["DNS_label_too_long"] = ACTION_LOG_PER_ORIG, + ["DNS_truncated_RR_rdlength_lt_len"] = ACTION_LOG, + ["DNS_truncated_ans_too_short"] = ACTION_LOG, + ["DNS_truncated_len_lt_hdr_len"] = ACTION_LOG, + ["DNS_truncated_quest_too_short"] = ACTION_LOG, + ["dns_changed_number_of_responses"] = ACTION_LOG_PER_ORIG, + ["dns_reply_seen_after_done"] = ACTION_LOG_PER_ORIG, + ["excessive_data_without_further_acks"] = ACTION_LOG, + ["excess_RPC"] = ACTION_LOG_PER_ORIG, + ["excessive_RPC_len"] = ACTION_LOG_PER_ORIG, + ["FIN_advanced_last_seq"] = ACTION_LOG, + ["FIN_after_reset"] = ACTION_IGNORE, + ["FIN_storm"] = ACTION_NOTICE_PER_ORIG, + ["HTTP_bad_chunk_size"] = ACTION_LOG, + ["HTTP_chunked_transfer_for_multipart_message"] = ACTION_LOG, + ["HTTP_overlapping_messages"] = ACTION_LOG, + ["HTTP_unknown_method"] = ACTION_LOG, + ["HTTP_version_mismatch"] = ACTION_LOG, + ["ident_request_addendum"] = ACTION_LOG, + ["inappropriate_FIN"] = ACTION_LOG, + ["inflate_failed"] = ACTION_LOG, + ["invalid_irc_global_users_reply"] = ACTION_LOG, + ["irc_invalid_command"] = ACTION_LOG, + ["irc_invalid_dcc_message_format"] = ACTION_LOG, + ["irc_invalid_invite_message_format"] = ACTION_LOG, + ["irc_invalid_join_line"] = ACTION_LOG, + ["irc_invalid_kick_message_format"] = ACTION_LOG, + ["irc_invalid_line"] = ACTION_LOG, + ["irc_invalid_mode_message_format"] = ACTION_LOG, + ["irc_invalid_names_line"] = ACTION_LOG, + ["irc_invalid_njoin_line"] = ACTION_LOG, + ["irc_invalid_notice_message_format"] = ACTION_LOG, + ["irc_invalid_oper_message_format"] = ACTION_LOG, + ["irc_invalid_privmsg_message_format"] = ACTION_LOG, + ["irc_invalid_reply_number"] = ACTION_LOG, + ["irc_invalid_squery_message_format"] = ACTION_LOG, + ["irc_invalid_topic_reply"] = ACTION_LOG, + ["irc_invalid_who_line"] = ACTION_LOG, + ["irc_invalid_who_message_format"] = ACTION_LOG, + ["irc_invalid_whois_channel_line"] = ACTION_LOG, + ["irc_invalid_whois_message_format"] = ACTION_LOG, + ["irc_invalid_whois_operator_line"] = ACTION_LOG, + ["irc_invalid_whois_user_line"] = ACTION_LOG, + ["irc_line_size_exceeded"] = ACTION_LOG, + ["irc_line_too_short"] = ACTION_LOG, + ["irc_too_many_invalid"] = ACTION_LOG, + ["line_terminated_with_single_CR"] = ACTION_LOG, + ["line_terminated_with_single_LF"] = ACTION_LOG, + ["malformed_ssh_identification"] = ACTION_LOG, + ["malformed_ssh_version"] = ACTION_LOG, + ["matching_undelivered_data"] = ACTION_LOG, + ["multiple_HTTP_request_elements"] = ACTION_LOG, + ["multiple_RPCs"] = ACTION_LOG_PER_ORIG, + ["non_IPv4_packet"] = ACTION_LOG_ONCE, + ["NUL_in_line"] = ACTION_LOG, + ["originator_RPC_reply"] = ACTION_LOG_PER_ORIG, + ["partial_finger_request"] = ACTION_LOG, + ["partial_ftp_request"] = ACTION_LOG, + ["partial_ident_request"] = ACTION_LOG, + ["partial_RPC"] = ACTION_LOG_PER_ORIG, + ["partial_RPC_request"] = ACTION_LOG, + ["pending_data_when_closed"] = ACTION_LOG, + ["pop3_bad_base64_encoding"] = ACTION_LOG, + ["pop3_client_command_unknown"] = ACTION_LOG, + ["pop3_client_sending_server_commands"] = ACTION_LOG, + ["pop3_malformed_auth_plain"] = ACTION_LOG, + ["pop3_server_command_unknown"] = ACTION_LOG, + ["pop3_server_sending_client_commands"] = ACTION_LOG, + ["possible_split_routing"] = ACTION_LOG, + ["premature_connection_reuse"] = ACTION_LOG, + ["repeated_SYN_reply_wo_ack"] = ACTION_LOG, + ["repeated_SYN_with_ack"] = ACTION_LOG, + ["responder_RPC_call"] = ACTION_LOG_PER_ORIG, + ["rlogin_text_after_rejected"] = ACTION_LOG, + ["RPC_rexmit_inconsistency"] = ACTION_LOG, + ["RPC_underflow"] = ACTION_LOG, + ["RST_storm"] = ACTION_LOG, + ["RST_with_data"] = ACTION_LOG, + ["simultaneous_open"] = ACTION_LOG_PER_CONN, + ["spontaneous_FIN"] = ACTION_IGNORE, + ["spontaneous_RST"] = ACTION_IGNORE, + ["SMB_parsing_error"] = ACTION_LOG, + ["no_smb_session_using_parsesambamsg"] = ACTION_LOG, + ["smb_andx_command_failed_to_parse"] = ACTION_LOG, + ["transaction_subcmd_missing"] = ACTION_LOG, + ["successful_RPC_reply_to_invalid_request"] = ACTION_NOTICE_PER_ORIG, + ["SYN_after_close"] = ACTION_LOG, + ["SYN_after_partial"] = ACTION_NOTICE_PER_ORIG, + ["SYN_after_reset"] = ACTION_LOG, + ["SYN_inside_connection"] = ACTION_LOG, + ["SYN_seq_jump"] = ACTION_LOG, + ["SYN_with_data"] = ACTION_LOG_PER_ORIG, + ["TCP_christmas"] = ACTION_LOG, + ["truncated_ARP"] = ACTION_LOG, + ["truncated_NTP"] = ACTION_LOG, + ["UDP_datagram_length_mismatch"] = ACTION_LOG_PER_ORIG, + ["unexpected_client_HTTP_data"] = ACTION_LOG, + ["unexpected_multiple_HTTP_requests"] = ACTION_LOG, + ["unexpected_server_HTTP_data"] = ACTION_LOG, + ["unmatched_HTTP_reply"] = ACTION_LOG, + ["unpaired_RPC_response"] = ACTION_LOG, + ["window_recision"] = ACTION_LOG, + ["double_%_in_URI"] = ACTION_LOG, + ["illegal_%_at_end_of_URI"] = ACTION_LOG, + ["unescaped_%_in_URI"] = ACTION_LOG, + ["unescaped_special_URI_char"] = ACTION_LOG, + ["deficit_netbios_hdr_len"] = ACTION_LOG, + ["excess_netbios_hdr_len"] = ACTION_LOG, + ["netbios_client_session_reply"] = ACTION_LOG, + ["netbios_raw_session_msg"] = ACTION_LOG, + ["netbios_server_session_request"] = ACTION_LOG, + ["unknown_netbios_type"] = ACTION_LOG, + ["excessively_large_fragment"] = ACTION_LOG, + ["excessively_small_fragment"] = ACTION_LOG_PER_ORIG, + ["fragment_inconsistency"] = ACTION_LOG_PER_ORIG, + ["fragment_overlap"] = ACTION_LOG_PER_ORIG, + ["fragment_protocol_inconsistency"] = ACTION_LOG, + ["fragment_size_inconsistency"] = ACTION_LOG_PER_ORIG, + # These do indeed happen! + ["fragment_with_DF"] = ACTION_LOG, + ["incompletely_captured_fragment"] = ACTION_LOG, + ["bad_IP_checksum"] = ACTION_LOG_PER_ORIG, + ["bad_TCP_header_len"] = ACTION_LOG, + ["internally_truncated_header"] = ACTION_LOG, + ["truncated_IP"] = ACTION_LOG, + ["truncated_header"] = ACTION_LOG, + } &default=ACTION_LOG &redef; - const weird_action: table[string] of WeirdAction = { - # tcp_weird - ["above_hole_data_without_any_acks"] = WEIRD_FILE, - ["active_connection_reuse"] = WEIRD_FILE, - ["bad_HTTP_reply"] = WEIRD_FILE, - ["bad_HTTP_version"] = WEIRD_FILE, - ["bad_ICMP_checksum"] = WEIRD_FILE, - ["bad_ident_port"] = WEIRD_FILE, - ["bad_ident_reply"] = WEIRD_FILE, - ["bad_ident_request"] = WEIRD_FILE, - ["bad_rlogin_prolog"] = WEIRD_FILE, - ["bad_rsh_prolog"] = WEIRD_FILE, - ["rsh_text_after_rejected"] = WEIRD_FILE, - ["bad_RPC"] = WEIRD_NOTICE_PER_ORIG, - ["bad_RPC_program"] = WEIRD_FILE, - ["bad_SYN_ack"] = WEIRD_FILE, - ["bad_TCP_checksum"] = WEIRD_FILE, - ["bad_UDP_checksum"] = WEIRD_FILE, - ["baroque_SYN"] = WEIRD_FILE, - ["base64_illegal_encoding"] = WEIRD_FILE, - ["connection_originator_SYN_ack"] = WEIRD_FILE, - ["corrupt_tcp_options"] = WEIRD_NOTICE_PER_ORIG, - ["crud_trailing_HTTP_request"] = WEIRD_FILE, - ["data_after_reset"] = WEIRD_FILE, - ["data_before_established"] = WEIRD_FILE, - ["data_without_SYN_ACK"] = WEIRD_FILE, - ["DHCP_no_type_option"] = WEIRD_FILE, - ["DHCP_wrong_msg_type"] = WEIRD_FILE, - ["DHCP_wrong_op_type"] = WEIRD_FILE, - ["DNS_AAAA_neg_length"] = WEIRD_FILE, - ["DNS_Conn_count_too_large"] = WEIRD_FILE, - ["DNS_NAME_too_long"] = WEIRD_FILE, - ["DNS_RR_bad_length"] = WEIRD_FILE, - ["DNS_RR_length_mismatch"] = WEIRD_FILE, - ["DNS_RR_unknown_type"] = WEIRD_FILE, - ["DNS_label_forward_compress_offset"] = WEIRD_NOTICE_PER_ORIG, - ["DNS_label_len_gt_name_len"] = WEIRD_NOTICE_PER_ORIG, - ["DNS_label_len_gt_pkt"] = WEIRD_NOTICE_PER_ORIG, - ["DNS_label_too_long"] = WEIRD_NOTICE_PER_ORIG, - ["DNS_truncated_RR_rdlength_lt_len"] = WEIRD_FILE, - ["DNS_truncated_ans_too_short"] = WEIRD_FILE, - ["DNS_truncated_len_lt_hdr_len"] = WEIRD_FILE, - ["DNS_truncated_quest_too_short"] = WEIRD_FILE, - ["excessive_data_without_further_acks"] = WEIRD_FILE, - ["excess_RPC"] = WEIRD_NOTICE_PER_ORIG, - ["excessive_RPC_len"] = WEIRD_NOTICE_PER_ORIG, - ["FIN_advanced_last_seq"] = WEIRD_FILE, - ["FIN_after_reset"] = WEIRD_IGNORE, - ["FIN_storm"] = WEIRD_NOTICE_ALWAYS, - ["HTTP_bad_chunk_size"] = WEIRD_FILE, - ["HTTP_chunked_transfer_for_multipart_message"] = WEIRD_FILE, - ["HTTP_overlapping_messages"] = WEIRD_FILE, - ["HTTP_unknown_method"] = WEIRD_FILE, - ["HTTP_version_mismatch"] = WEIRD_FILE, - ["ident_request_addendum"] = WEIRD_FILE, - ["inappropriate_FIN"] = WEIRD_FILE, - ["inflate_data_failed"] = WEIRD_FILE, - ["inflate_failed"] = WEIRD_FILE, - ["invalid_irc_global_users_reply"] = WEIRD_FILE, - ["irc_invalid_command"] = WEIRD_FILE, - ["irc_invalid_dcc_message_format"] = WEIRD_FILE, - ["irc_invalid_invite_message_format"] = WEIRD_FILE, - ["irc_invalid_join_line"] = WEIRD_FILE, - ["irc_invalid_kick_message_format"] = WEIRD_FILE, - ["irc_invalid_line"] = WEIRD_FILE, - ["irc_invalid_mode_message_format"] = WEIRD_FILE, - ["irc_invalid_names_line"] = WEIRD_FILE, - ["irc_invalid_njoin_line"] = WEIRD_FILE, - ["irc_invalid_notice_message_format"] = WEIRD_FILE, - ["irc_invalid_oper_message_format"] = WEIRD_FILE, - ["irc_invalid_privmsg_message_format"] = WEIRD_FILE, - ["irc_invalid_reply_number"] = WEIRD_FILE, - ["irc_invalid_squery_message_format"] = WEIRD_FILE, - ["irc_invalid_topic_reply"] = WEIRD_FILE, - ["irc_invalid_who_line"] = WEIRD_FILE, - ["irc_invalid_who_message_format"] = WEIRD_FILE, - ["irc_invalid_whois_channel_line"] = WEIRD_FILE, - ["irc_invalid_whois_message_format"] = WEIRD_FILE, - ["irc_invalid_whois_operator_line"] = WEIRD_FILE, - ["irc_invalid_whois_user_line"] = WEIRD_FILE, - ["irc_line_size_exceeded"] = WEIRD_FILE, - ["irc_line_too_short"] = WEIRD_FILE, - ["irc_too_many_invalid"] = WEIRD_FILE, - ["line_terminated_with_single_CR"] = WEIRD_FILE, - ["line_terminated_with_single_LF"] = WEIRD_FILE, - ["malformed_ssh_identification"] = WEIRD_FILE, - ["malformed_ssh_version"] = WEIRD_FILE, - ["matching_undelivered_data"] = WEIRD_FILE, - ["multiple_HTTP_request_elements"] = WEIRD_FILE, - ["multiple_RPCs"] = WEIRD_NOTICE_PER_ORIG, - ["non_IPv4_packet"] = WEIRD_NOTICE_ONCE, - ["NUL_in_line"] = WEIRD_FILE, - ["originator_RPC_reply"] = WEIRD_NOTICE_PER_ORIG, - ["partial_finger_request"] = WEIRD_FILE, - ["partial_ftp_request"] = WEIRD_FILE, - ["partial_ident_request"] = WEIRD_FILE, - ["partial_RPC"] = WEIRD_NOTICE_PER_ORIG, - ["partial_RPC_request"] = WEIRD_FILE, - ["pending_data_when_closed"] = WEIRD_FILE, - ["pop3_bad_base64_encoding"] = WEIRD_FILE, - ["pop3_client_command_unknown"] = WEIRD_FILE, - ["pop3_client_sending_server_commands"] = WEIRD_FILE, - ["pop3_malformed_auth_plain"] = WEIRD_FILE, - ["pop3_server_command_unknown"] = WEIRD_FILE, - ["pop3_server_sending_client_commands"] = WEIRD_FILE, - ["possible_split_routing"] = WEIRD_FILE, - ["premature_connection_reuse"] = WEIRD_FILE, - ["repeated_SYN_reply_wo_ack"] = WEIRD_FILE, - ["repeated_SYN_with_ack"] = WEIRD_FILE, - ["responder_RPC_call"] = WEIRD_NOTICE_PER_ORIG, - ["rlogin_text_after_rejected"] = WEIRD_FILE, - ["RPC_rexmit_inconsistency"] = WEIRD_FILE, - ["RPC_underflow"] = WEIRD_FILE, - ["RST_storm"] = WEIRD_NOTICE_ALWAYS, - ["RST_with_data"] = WEIRD_FILE, # PC's do this - ["simultaneous_open"] = WEIRD_NOTICE_PER_CONN, - ["spontaneous_FIN"] = WEIRD_IGNORE, - ["spontaneous_RST"] = WEIRD_IGNORE, - ["SMB_parsing_error"] = WEIRD_FILE, - ["no_smb_session_using_parsesambamsg"] = WEIRD_FILE, - ["smb_andx_command_failed_to_parse"] = WEIRD_FILE, - ["transaction_subcmd_missing"] = WEIRD_FILE, - ["SSLv3_data_without_full_handshake"] = WEIRD_FILE, - ["unexpected_SSLv3_record"] = WEIRD_FILE, - ["successful_RPC_reply_to_invalid_request"] = WEIRD_NOTICE_PER_ORIG, - ["SYN_after_close"] = WEIRD_FILE, - ["SYN_after_partial"] = WEIRD_NOTICE_PER_ORIG, - ["SYN_after_reset"] = WEIRD_FILE, - ["SYN_inside_connection"] = WEIRD_FILE, - ["SYN_seq_jump"] = WEIRD_FILE, - ["SYN_with_data"] = WEIRD_FILE, - ["TCP_christmas"] = WEIRD_FILE, - ["truncated_ARP"] = WEIRD_FILE, - ["truncated_NTP"] = WEIRD_FILE, - ["UDP_datagram_length_mismatch"] = WEIRD_NOTICE_PER_ORIG, - ["unexpected_client_HTTP_data"] = WEIRD_FILE, - ["unexpected_multiple_HTTP_requests"] = WEIRD_FILE, - ["unexpected_server_HTTP_data"] = WEIRD_FILE, - ["unmatched_HTTP_reply"] = WEIRD_FILE, - ["unpaired_RPC_response"] = WEIRD_FILE, - ["unsolicited_SYN_response"] = WEIRD_IGNORE, - ["window_recision"] = WEIRD_FILE, - ["double_%_in_URI"] = WEIRD_FILE, - ["illegal_%_at_end_of_URI"] = WEIRD_FILE, - ["unescaped_%_in_URI"] = WEIRD_FILE, - ["unescaped_special_URI_char"] = WEIRD_FILE, + ## To completely ignore a specific weird for a host, add the host + ## and weird name into this set. + const ignore_hosts: set[addr, string] &redef; - ["UDP_zone_transfer"] = WEIRD_NOTICE_ONCE, - - ["deficit_netbios_hdr_len"] = WEIRD_FILE, - ["excess_netbios_hdr_len"] = WEIRD_FILE, - ["netbios_client_session_reply"] = WEIRD_FILE, - ["netbios_raw_session_msg"] = WEIRD_FILE, - ["netbios_server_session_request"] = WEIRD_FILE, - ["unknown_netbios_type"] = WEIRD_FILE, - - # flow_weird - ["excessively_large_fragment"] = WEIRD_NOTICE_ALWAYS, - - # Code Red generates slews ... - ["excessively_small_fragment"] = WEIRD_NOTICE_PER_ORIG, - - ["fragment_inconsistency"] = WEIRD_NOTICE_PER_ORIG, - ["fragment_overlap"] = WEIRD_NOTICE_PER_ORIG, - ["fragment_protocol_inconsistency"] = WEIRD_NOTICE_ALWAYS, - ["fragment_size_inconsistency"] = WEIRD_NOTICE_PER_ORIG, - ["fragment_with_DF"] = WEIRD_FILE, # these do indeed happen! - ["incompletely_captured_fragment"] = WEIRD_NOTICE_ALWAYS, - - # net_weird - ["bad_IP_checksum"] = WEIRD_FILE, - ["bad_TCP_header_len"] = WEIRD_FILE, - ["internally_truncated_header"] = WEIRD_NOTICE_ALWAYS, - ["truncated_IP"] = WEIRD_FILE, - ["truncated_header"] = WEIRD_FILE, - - # generated by policy script - ["Land_attack"] = WEIRD_NOTICE_PER_ORIG, - ["bad_pm_port"] = WEIRD_NOTICE_PER_ORIG, - - ["ICMP-unreachable for wrong state"] = WEIRD_NOTICE_PER_ORIG, - - } &redef; - - # table that maps weird types into a function that should be called - # to determine the action. - const weird_action_filters: - table[string] of function(c: connection): WeirdAction &redef; - - const weird_ignore_host: set[addr, string] &redef; - - # But don't ignore these (for the weird file), it's handy keeping - # track of clustered checksum errors. + ## Don't ignore repeats for weirds in this set. For example, + ## it's handy keeping track of clustered checksum errors. const weird_do_not_ignore_repeats = { "bad_IP_checksum", "bad_TCP_checksum", "bad_UDP_checksum", "bad_ICMP_checksum", } &redef; + ## This table is used to track identifier and name pairs that should be + ## temporarily ignored because the problem has already been reported. + ## This helps reduce the volume of high volume weirds by only allowing + ## a unique weird every ``create_expire`` interval. + global weird_ignore: set[string, string] &create_expire=10min &redef; + + ## A state set which tracks unique weirds solely by the name to reduce + ## duplicate logging. This is not synchronized deliberately because it + ## could cause overload during storms + global did_log: set[string, string] &create_expire=1day &redef; + + ## A state set which tracks unique weirds solely by the name to reduce + ## duplicate notices from being raised. + global did_notice: set[string, string] &create_expire=1day &redef; + + ## Handlers of this event are invoked one per write to the weird + ## logging stream before the data is actually written. + ## + ## rec: The weird columns about to be logged to the weird stream. global log_weird: event(rec: Info); } -# id/msg pairs that should be ignored (because the problem has already -# been reported). -global weird_ignore: table[string] of set[string] &write_expire = 10 min; +# These actions result in the output being limited and further redundant +# weirds not progressing to being logged or noticed. +const limiting_actions = { + ACTION_LOG_ONCE, + ACTION_LOG_PER_CONN, + ACTION_LOG_PER_ORIG, + ACTION_NOTICE_ONCE, + ACTION_NOTICE_PER_CONN, + ACTION_NOTICE_PER_ORIG, +}; -# For WEIRD_NOTICE_PER_CONN. -global did_notice_conn: set[addr, port, addr, port, string] - &read_expire = 1 day; +# This is an internal set to track which Weird::Action values lead to notice +# creation. +const notice_actions = { + ACTION_NOTICE, + ACTION_NOTICE_PER_CONN, + ACTION_NOTICE_PER_ORIG, + ACTION_NOTICE_ONCE, +}; -# For WEIRD_NOTICE_PER_ORIG. -global did_notice_orig: set[addr, string] &read_expire = 1 day; - -# For WEIRD_NOTICE_ONCE. -global did_weird_log: set[string] &read_expire = 1 day; - -global did_inconsistency_msg: set[conn_id]; - -# Used to pass the optional connection into report_weird(). +# Used to pass the optional connection into report(). global current_conn: connection; -event bro_init() +event bro_init() &priority=5 { - Log::create_stream(WEIRD, [$columns=Info, $ev=log_weird]); + Log::create_stream(Weird::LOG, [$columns=Info, $ev=log_weird]); } -function report_weird(t: time, name: string, id: string, have_conn: bool, - addl: string, action: WeirdAction, no_log: bool) +function flow_id_string(src: addr, dst: addr): string { + return fmt("%s -> %s", src, dst); + } + +function report(t: time, name: string, identifier: string, have_conn: bool, addl: string) + { + local action = actions[name]; + + # If this weird is to be ignored let's drop out of here very early. + if ( action == ACTION_IGNORE || [name, identifier] in weird_ignore ) + return; + + if ( action in limiting_actions ) + { + if ( action in notice_actions ) + { + # Handle notices + if ( have_conn && action == ACTION_NOTICE_PER_ORIG ) + identifier = fmt("%s", current_conn$id$orig_h); + else if ( action == ACTION_NOTICE_ONCE ) + identifier = ""; + + # If this weird was already noticed then we're done. + if ( [name, identifier] in did_notice ) + return; + add did_notice[name, identifier]; + } + else + { + # Handle logging. + if ( have_conn && action == ACTION_LOG_PER_ORIG ) + identifier = fmt("%s", current_conn$id$orig_h); + else if ( action == ACTION_LOG_ONCE ) + identifier = ""; + + # If this weird was already logged then we're done. + if ( [name, identifier] in did_log ) + return; + add did_log[name, identifier]; + } + } + + # Create the Weird::Info record. local info: Info; info$ts = t; - info$msg = name; + info$name = name; + info$peer = peer_description; if ( addl != "" ) info$addl = addl; if ( have_conn ) @@ -274,154 +352,59 @@ function report_weird(t: time, name: string, id: string, have_conn: bool, info$id = current_conn$id; } - if ( action == WEIRD_IGNORE || - (id in weird_ignore && name in weird_ignore[id]) ) - return; - - if ( action == WEIRD_UNSPECIFIED ) - { - if ( name in weird_action && weird_action[name] == WEIRD_IGNORE ) - return; - else - { - action = WEIRD_NOTICE_ALWAYS; - info$notice = T; - } - } - - if ( action in notice_actions && ! no_log ) + if ( action in notice_actions ) { + info$notice = T; + local n: Notice::Info; - n$note = Weird_Activity; - n$msg = info$msg; + n$note = Activity; + n$msg = info$name; if ( have_conn ) n$conn = current_conn; if ( info?$addl ) n$sub = info$addl; NOTICE(n); } - else if ( id != "" && name !in weird_do_not_ignore_repeats ) - { - if ( id !in weird_ignore ) - weird_ignore[id] = set() &mergeable; - add weird_ignore[id][name]; - } - - Log::write(WEIRD, info); + + # This is for the temporary ignoring to reduce volume for identical weirds. + if ( name !in weird_do_not_ignore_repeats ) + add weird_ignore[name, identifier]; + + Log::write(Weird::LOG, info); } -function report_weird_conn(t: time, name: string, id: string, addl: string, - c: connection) +function report_conn(t: time, name: string, identifier: string, addl: string, c: connection) { - if ( [c$id$orig_h, name] in weird_ignore_host || - [c$id$resp_h, name] in weird_ignore_host ) + local cid = c$id; + if ( [cid$orig_h, name] in ignore_hosts || + [cid$resp_h, name] in ignore_hosts ) return; - local no_log = F; - local action = WEIRD_UNSPECIFIED; - - if ( name in weird_action ) - { - if ( name in weird_action_filters ) - action = weird_action_filters[name](c); - - if ( action == WEIRD_UNSPECIFIED ) - action = weird_action[name]; - - local cid = c$id; - - if ( action == WEIRD_NOTICE_PER_CONN ) - { - if ( [cid$orig_h, cid$orig_p, cid$resp_h, cid$resp_p, name] in did_notice_conn ) - no_log = T; - else - add did_notice_conn[cid$orig_h, cid$orig_p, cid$resp_h, cid$resp_p, name]; - } - - else if ( action == WEIRD_NOTICE_PER_ORIG ) - { - if ( [c$id$orig_h, name] in did_notice_orig ) - no_log = T; - else - add did_notice_orig[c$id$orig_h, name]; - } - - else if ( action == WEIRD_NOTICE_ONCE ) - { - if ( name in did_weird_log ) - no_log = T; - else - add did_weird_log[name]; - } - } - current_conn = c; - report_weird(t, name, id, T, addl, action, no_log); + report(t, name, identifier, T, addl); } -function report_weird_orig(t: time, name: string, id: string, orig: addr) +function report_orig(t: time, name: string, identifier: string, orig: addr) { - local no_log = F; - local action = WEIRD_UNSPECIFIED; - - if ( name in weird_action ) - { - action = weird_action[name]; - if ( action == WEIRD_NOTICE_PER_ORIG ) - { - if ( [orig, name] in did_notice_orig ) - no_log = T; - else - add did_notice_orig[orig, name]; - } - } - - report_weird(t, name, id, F, "", action, no_log); + if ( [orig, name] in ignore_hosts ) + return; + + report(t, name, identifier, F, ""); } + +# The following events come from core generated weirds typically. event conn_weird(name: string, c: connection, addl: string) { - report_weird_conn(network_time(), name, id_string(c$id), addl, c); + report_conn(network_time(), name, id_string(c$id), addl, c); } event flow_weird(name: string, src: addr, dst: addr) { - report_weird_orig(network_time(), name, fmt("%s -> %s", src, dst), src); + report_orig(network_time(), name, flow_id_string(src, dst), src); } event net_weird(name: string) { - report_weird(network_time(), name, "", F, "", WEIRD_UNSPECIFIED, F); - } - -event rexmit_inconsistency(c: connection, t1: string, t2: string) - { - if ( c$id !in did_inconsistency_msg ) - { - NOTICE([$note=Retransmission_Inconsistency, - $conn=c, - $msg=fmt("%s rexmit inconsistency (%s) (%s)", - id_string(c$id), t1, t2)]); - add did_inconsistency_msg[c$id]; - } - } - -event ack_above_hole(c: connection) - { - NOTICE([$note=Ack_Above_Hole, $conn=c, - $msg=fmt("%s ack above a hole", id_string(c$id))]); - } - -event content_gap(c: connection, is_orig: bool, seq: count, length: count) - { - NOTICE([$note=Content_Gap, $conn=c, - $msg=fmt("%s content gap (%s %d/%d)%s", - id_string(c$id), is_orig ? ">" : "<", seq, length, - is_external_connection(c) ? " [external]" : "")]); - } - -event connection_state_remove(c: connection) - { - delete weird_ignore[id_string(c$id)]; - delete did_inconsistency_msg[c$id]; + report(network_time(), name, "", F, ""); } diff --git a/scripts/base/frameworks/packet-filter/main.bro b/scripts/base/frameworks/packet-filter/main.bro index b030e763f0..afcb5bd700 100644 --- a/scripts/base/frameworks/packet-filter/main.bro +++ b/scripts/base/frameworks/packet-filter/main.bro @@ -4,33 +4,40 @@ ##! open filter and all filters defined in Bro scripts with the ##! :bro:id:`capture_filters` and :bro:id:`restrict_filters` variables. +@load base/frameworks/notice + module PacketFilter; export { - redef enum Log::ID += { PACKET_FILTER }; - + ## Add the packet filter logging stream. + redef enum Log::ID += { LOG }; + + ## Add notice types related to packet filter errors. redef enum Notice::Type += { ## This notice is generated if a packet filter is unable to be compiled. Compile_Failure, - - ## This notice is generated if a packet filter is unable to be installed. + + ## This notice is generated if a packet filter is fails to install. Install_Failure, }; - + + ## The record type defining columns to be logged in the packet filter + ## logging stream. type Info: record { + ## The time at which the packet filter installation attempt was made. ts: time &log; - + ## This is a string representation of the node that applied this ## packet filter. It's mostly useful in the context of dynamically ## changing filters on clusters. node: string &log &optional; - + ## The packet filter that is being set. filter: string &log; - + ## Indicate if this is the filter set during initialization. init: bool &log &default=F; - + ## Indicate if the filter was applied successfully. success: bool &log &default=T; }; @@ -38,19 +45,19 @@ export { ## By default, Bro will examine all packets. If this is set to false, ## it will dynamically build a BPF filter that only select protocols ## for which the user has loaded a corresponding analysis script. - ## The latter used to be default for Bro versions < 1.6. That has now + ## The latter used to be default for Bro versions < 2.0. That has now ## changed however to enable port-independent protocol analysis. const all_packets = T &redef; - - ## Filter string which is unconditionally or'ed to the beginning of every + + ## Filter string which is unconditionally or'ed to the beginning of every ## dynamically built filter. const unrestricted_filter = "" &redef; - + ## Call this function to build and install a new dynamically built ## packet filter. global install: function(); - - ## This is where the default packet filter is stored and it should not + + ## This is where the default packet filter is stored and it should not ## normally be modified by users. global default_filter = ""; } @@ -78,35 +85,26 @@ function build_default_filter(): string return cmd_line_bpf_filter; if ( all_packets ) - { # Return an "always true" filter. - if ( bro_has_ipv6() ) - return "ip or not ip"; - else - return "not ip6"; - } + return "ip or not ip"; # Build filter dynamically. - + # First the capture_filter. local cfilter = ""; for ( id in capture_filters ) cfilter = combine_filters(cfilter, capture_filters[id], "or"); - + # Then the restrict_filter. local rfilter = ""; for ( id in restrict_filters ) rfilter = combine_filters(rfilter, restrict_filters[id], "and"); - + # Finally, join them into one filter. local filter = combine_filters(rfilter, cfilter, "and"); if ( unrestricted_filter != "" ) filter = combine_filters(unrestricted_filter, filter, "or"); - - # Exclude IPv6 if we don't support it. - if ( ! bro_has_ipv6() ) - filter = combine_filters(filter, "not ip6", "and"); - + return filter; } @@ -116,37 +114,38 @@ function install() if ( ! precompile_pcap_filter(DefaultPcapFilter, default_filter) ) { - NOTICE([$note=Compile_Failure, + NOTICE([$note=Compile_Failure, $msg=fmt("Compiling packet filter failed"), $sub=default_filter]); - exit(); + Reporter::fatal(fmt("Bad pcap filter '%s'", default_filter)); } - + # Do an audit log for the packet filter. local info: Info; info$ts = network_time(); # If network_time() is 0.0 we're at init time so use the wall clock. - if ( info$ts == 0.0 ) + if ( info$ts == 0.0 ) { info$ts = current_time(); info$init = T; } info$filter = default_filter; - + if ( ! install_pcap_filter(DefaultPcapFilter) ) { # Installing the filter failed for some reason. info$success = F; - NOTICE([$note=Install_Failure, + NOTICE([$note=Install_Failure, $msg=fmt("Installing packet filter failed"), $sub=default_filter]); } - - Log::write(PACKET_FILTER, info); + + if ( reading_live_traffic() || reading_traces() ) + Log::write(PacketFilter::LOG, info); } event bro_init() &priority=10 { - Log::create_stream(PACKET_FILTER, [$columns=Info]); + Log::create_stream(PacketFilter::LOG, [$columns=Info]); PacketFilter::install(); } diff --git a/scripts/base/frameworks/packet-filter/netstats.bro b/scripts/base/frameworks/packet-filter/netstats.bro index 887c7222e0..9fbaa5cd1d 100644 --- a/scripts/base/frameworks/packet-filter/netstats.bro +++ b/scripts/base/frameworks/packet-filter/netstats.bro @@ -1,10 +1,14 @@ ##! This script reports on packet loss from the various packet sources. +##! When Bro is reading input from trace files, this script will not +##! report any packet loss statistics. + +@load base/frameworks/notice module PacketFilter; export { redef enum Notice::Type += { - ## Bro reported packets dropped by the packet filter. + ## Indicates packets were dropped by the packet filter. Dropped_Packets, }; diff --git a/scripts/base/frameworks/reporter/main.bro b/scripts/base/frameworks/reporter/main.bro index ee9def9121..3c19005364 100644 --- a/scripts/base/frameworks/reporter/main.bro +++ b/scripts/base/frameworks/reporter/main.bro @@ -1,17 +1,36 @@ ##! This framework is intended to create an output and filtering path for ##! internal messages/warnings/errors. It should typically be loaded to -##! avoid Bro spewing internal messages to standard error. +##! avoid Bro spewing internal messages to standard error and instead log +##! them to a file in a standard way. Note that this framework deals with +##! the handling of internally-generated reporter messages, for the +##! interface into actually creating reporter messages from the scripting +##! layer, use the built-in functions in :doc:`/scripts/base/reporter.bif`. module Reporter; export { - redef enum Log::ID += { REPORTER }; - - type Level: enum { INFO, WARNING, ERROR }; - + ## The reporter logging stream identifier. + redef enum Log::ID += { LOG }; + + ## An indicator of reporter message severity. + type Level: enum { + ## Informational, not needing specific attention. + INFO, + ## Warning of a potential problem. + WARNING, + ## A non-fatal error that should be addressed, but doesn't + ## terminate program execution. + ERROR + }; + + ## The record type which contains the column fields of the reporter log. type Info: record { + ## The network time at which the reporter event was generated. ts: time &log; + ## The severity of the reporter message. level: Level &log; + ## An info/warning/error message that could have either been + ## generated from the internal Bro core or at the scripting-layer. message: string &log; ## This is the location in a Bro script where the message originated. ## Not all reporter messages will have locations in them though. @@ -19,22 +38,22 @@ export { }; } -event bro_init() +event bro_init() &priority=5 { - Log::create_stream(REPORTER, [$columns=Info]); + Log::create_stream(Reporter::LOG, [$columns=Info]); } event reporter_info(t: time, msg: string, location: string) { - Log::write(REPORTER, [$ts=t, $level=INFO, $message=msg, $location=location]); + Log::write(Reporter::LOG, [$ts=t, $level=INFO, $message=msg, $location=location]); } event reporter_warning(t: time, msg: string, location: string) { - Log::write(REPORTER, [$ts=t, $level=WARNING, $message=msg, $location=location]); + Log::write(Reporter::LOG, [$ts=t, $level=WARNING, $message=msg, $location=location]); } event reporter_error(t: time, msg: string, location: string) { - Log::write(REPORTER, [$ts=t, $level=ERROR, $message=msg, $location=location]); + Log::write(Reporter::LOG, [$ts=t, $level=ERROR, $message=msg, $location=location]); } diff --git a/scripts/base/frameworks/signatures/main.bro b/scripts/base/frameworks/signatures/main.bro index 9f218ab144..26f78a68d1 100644 --- a/scripts/base/frameworks/signatures/main.bro +++ b/scripts/base/frameworks/signatures/main.bro @@ -1,29 +1,37 @@ -##! Script level signature support. +##! Script level signature support. See the +##! :doc:`signature documentation ` for more information about +##! Bro's signature engine. + +@load base/frameworks/notice module Signatures; export { + ## Add various signature-related notice types. redef enum Notice::Type += { - ## Generic for alarm-worthy + ## Generic notice type for notice-worthy signature matches. Sensitive_Signature, ## Host has triggered many signatures on the same host. The number of - ## signatures is defined by the :bro:id:`vert_scan_thresholds` variable. + ## signatures is defined by the + ## :bro:id:`Signatures::vert_scan_thresholds` variable. Multiple_Signatures, - ## Host has triggered the same signature on multiple hosts as defined by the - ## :bro:id:`horiz_scan_thresholds` variable. + ## Host has triggered the same signature on multiple hosts as defined + ## by the :bro:id:`Signatures::horiz_scan_thresholds` variable. Multiple_Sig_Responders, - ## The same signature has triggered multiple times for a host. The number - ## of times the signature has be trigger is defined by the - ## :bro:id:`count_thresholds` variable. To generate this notice, the - ## :bro:enum:`SIG_COUNT_PER_RESP` action must be set for the signature. + ## The same signature has triggered multiple times for a host. The + ## number of times the signature has been triggered is defined by the + ## :bro:id:`Signatures::count_thresholds` variable. To generate this + ## notice, the :bro:enum:`Signatures::SIG_COUNT_PER_RESP` action must + ## bet set for the signature. Count_Signature, ## Summarize the number of times a host triggered a signature. The - ## interval between summaries is defined by the :bro:id:`summary_interval` - ## variable. + ## interval between summaries is defined by the + ## :bro:id:`Signatures::summary_interval` variable. Signature_Summary, }; - redef enum Log::ID += { SIGNATURES }; + ## The signature logging stream identifier. + redef enum Log::ID += { LOG }; ## These are the default actions you can apply to signature matches. ## All of them write the signature record to the logging stream unless @@ -37,8 +45,8 @@ export { SIG_QUIET, ## Generate a notice. SIG_LOG, - ## The same as :bro:enum:`SIG_FILE`, but ignore for aggregate/scan - ## processing. + ## The same as :bro:enum:`Signatures::SIG_LOG`, but ignore for + ## aggregate/scan processing. SIG_FILE_BUT_NO_SCAN, ## Generate a notice and set it to be alarmed upon. SIG_ALARM, @@ -47,22 +55,33 @@ export { ## Alarm once and then never again. SIG_ALARM_ONCE, ## Count signatures per responder host and alarm with the - ## :bro:enum:`Count_Signature` notice if a threshold defined by - ## :bro:id:`count_thresholds` is reached. + ## :bro:enum:`Signatures::Count_Signature` notice if a threshold + ## defined by :bro:id:`Signatures::count_thresholds` is reached. SIG_COUNT_PER_RESP, ## Don't alarm, but generate per-orig summary. SIG_SUMMARY, }; - + + ## The record type which contains the column fields of the signature log. type Info: record { + ## The network time at which a signature matching type of event to + ## be logged has occurred. ts: time &log; + ## The host which triggered the signature match event. src_addr: addr &log &optional; + ## The host port on which the signature-matching activity occurred. src_port: port &log &optional; + ## The destination host which was sent the payload that triggered the + ## signature match. dst_addr: addr &log &optional; + ## The destination host port which was sent the payload that triggered + ## the signature match. dst_port: port &log &optional; ## Notice associated with signature event note: Notice::Type &log; + ## The name of the signature that matched. sig_id: string &log &optional; + ## A more descriptive message of the signature-matching event. event_msg: string &log &optional; ## Extracted payload data or extra message. sub_msg: string &log &optional; @@ -80,22 +99,26 @@ export { ## Signature IDs that should always be ignored. const ignored_ids = /NO_DEFAULT_MATCHES/ &redef; - ## Alarm if, for a pair [orig, signature], the number of different - ## responders has reached one of the thresholds. + ## Generate a notice if, for a pair [orig, signature], the number of + ## different responders has reached one of the thresholds. const horiz_scan_thresholds = { 5, 10, 50, 100, 500, 1000 } &redef; - ## Alarm if, for a pair [orig, resp], the number of different signature - ## matches has reached one of the thresholds. + ## Generate a notice if, for a pair [orig, resp], the number of different + ## signature matches has reached one of the thresholds. const vert_scan_thresholds = { 5, 10, 50, 100, 500, 1000 } &redef; - ## Alarm if a :bro:enum:`SIG_COUNT_PER_RESP` signature is triggered as - ## often as given by one of these thresholds. + ## Generate a notice if a :bro:enum:`Signatures::SIG_COUNT_PER_RESP` + ## signature is triggered as often as given by one of these thresholds. const count_thresholds = { 5, 10, 50, 100, 500, 1000, 10000, 1000000, } &redef; - ## The interval between when :bro:id:`Signature_Summary` notices are - ## generated. + ## The interval between when :bro:enum:`Signatures::Signature_Summary` + ## notice are generated. const summary_interval = 1 day &redef; - + + ## This event can be handled to access/alter data about to be logged + ## to the signature logging stream. + ## + ## rec: The record of signature data about to be logged. global log_signature: event(rec: Info); } @@ -112,7 +135,7 @@ global did_sig_log: set[string] &read_expire = 1 hr; event bro_init() { - Log::create_stream(SIGNATURES, [$columns=Info, $ev=log_signature]); + Log::create_stream(Signatures::LOG, [$columns=Info, $ev=log_signature]); } # Returns true if the given signature has already been triggered for the given @@ -172,7 +195,7 @@ event signature_match(state: signature_state, msg: string, data: string) $event_msg=fmt("%s: %s", src_addr, msg), $sig_id=sig_id, $sub_msg=data]; - Log::write(SIGNATURES, info); + Log::write(Signatures::LOG, info); } local notice = F; @@ -246,7 +269,7 @@ event signature_match(state: signature_state, msg: string, data: string) fmt("%s has triggered signature %s on %d hosts", orig, sig_id, hcount); - Log::write(SIGNATURES, + Log::write(Signatures::LOG, [$note=Multiple_Sig_Responders, $src_addr=orig, $sig_id=sig_id, $event_msg=msg, $host_count=hcount, $sub_msg=horz_scan_msg]); @@ -263,7 +286,7 @@ event signature_match(state: signature_state, msg: string, data: string) fmt("%s has triggered %d different signatures on host %s", orig, vcount, resp); - Log::write(SIGNATURES, + Log::write(Signatures::LOG, [$ts=network_time(), $note=Multiple_Signatures, $src_addr=orig, diff --git a/scripts/base/frameworks/software/main.bro b/scripts/base/frameworks/software/main.bro index e35902aff1..7471076335 100644 --- a/scripts/base/frameworks/software/main.bro +++ b/scripts/base/frameworks/software/main.bro @@ -1,45 +1,55 @@ ##! This script provides the framework for software version detection and -##! parsing, but doesn't actually do any detection on it's own. It relys on +##! parsing but doesn't actually do any detection on it's own. It relys on ##! other protocol specific scripts to parse out software from the protocols ##! that they analyze. The entry point for providing new software detections ##! to this framework is through the :bro:id:`Software::found` function. +@load base/utils/directions-and-hosts +@load base/utils/numbers + module Software; export { - - redef enum Log::ID += { SOFTWARE }; - + ## The software logging stream identifier. + redef enum Log::ID += { LOG }; + + ## Scripts detecting new types of software need to redef this enum to add + ## their own specific software types which would then be used when they + ## create :bro:type:`Software::Info` records. type Type: enum { + ## A placeholder type for when the type of software is not known. UNKNOWN, - OPERATING_SYSTEM, - DATABASE_SERVER, - # There are a number of ways to detect printers on the - # network, we just need to codify them in a script and move - # this out of here. It isn't currently used for anything. - PRINTER, }; - + + ## A structure to represent the numeric version of software. type Version: record { - major: count &optional; ##< Major version number - minor: count &optional; ##< Minor version number - minor2: count &optional; ##< Minor subversion number - addl: string &optional; ##< Additional version string (e.g. "beta42") + ## Major version number + major: count &optional; + ## Minor version number + minor: count &optional; + ## Minor subversion number + minor2: count &optional; + ## Additional version string (e.g. "beta42") + addl: string &optional; } &log; - + + ## The record type that is used for representing and logging software. type Info: record { - ## The time at which the software was first detected. - ts: time &log; + ## The time at which the software was detected. + ts: time &log &optional; ## The IP address detected running the software. host: addr &log; - ## The type of software detected (e.g. WEB_SERVER) + ## The Port on which the software is running. Only sensible for server software. + host_p: port &log &optional; + ## The type of software detected (e.g. :bro:enum:`HTTP::SERVER`). software_type: Type &log &default=UNKNOWN; - ## Name of the software (e.g. Apache) - name: string &log; - ## Version of the software - version: Version &log; + ## Name of the software (e.g. Apache). + name: string &log &optional; + ## Version of the software. + version: Version &log &optional; ## The full unparsed version string found because the version parsing - ## doesn't work 100% reliably and this acts as a fall back in the logs. + ## doesn't always work reliably in all cases and this acts as a + ## fallback in the logs. unparsed_version: string &log &optional; ## This can indicate that this software being detected should @@ -52,37 +62,29 @@ export { force_log: bool &default=F; }; - ## The hosts whose software should be detected and tracked. + ## Hosts whose software should be detected and tracked. ## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS const asset_tracking = LOCAL_HOSTS &redef; - ## Other scripts should call this function when they detect software. - ## unparsed_version: This is the full string from which the - ## :bro:type:`Software::Info` was extracted. + ## id: The connection id where the software was discovered. + ## + ## info: A record representing the software discovered. + ## ## Returns: T if the software was logged, F otherwise. - global found: function(id: conn_id, info: Software::Info): bool; + global found: function(id: conn_id, info: Info): bool; - ## This function can take many software version strings and parse them - ## into a sensible :bro:type:`Software::Version` record. There are - ## still many cases where scripts may have to have their own specific - ## version parsing though. - global parse: function(unparsed_version: string, - host: addr, - software_type: Type): Info; - - ## Compare two versions. + ## Compare two version records. + ## ## Returns: -1 for v1 < v2, 0 for v1 == v2, 1 for v1 > v2. ## If the numerical version numbers match, the addl string ## is compared lexicographically. global cmp_versions: function(v1: Version, v2: Version): int; - ## This type represents a set of software. It's used by the - ## :bro:id:`tracked` variable to store all known pieces of software - ## for a particular host. It's indexed with the name of a piece of - ## software such as "Firefox" and it yields a - ## :bro:type:`Software::Info` record with more information about the - ## software. + ## Type to represent a collection of :bro:type:`Software::Info` records. + ## It's indexed with the name of a piece of software such as "Firefox" + ## and it yields a :bro:type:`Software::Info` record with more information + ## about the software. type SoftwareSet: table[string] of Info; ## The set of software associated with an address. Data expires from @@ -98,108 +100,23 @@ export { global log_software: event(rec: Info); } -event bro_init() +event bro_init() &priority=5 { - Log::create_stream(SOFTWARE, [$columns=Info, $ev=log_software]); + Log::create_stream(Software::LOG, [$columns=Info, $ev=log_software]); } - -function parse_mozilla(unparsed_version: string, - host: addr, - software_type: Type): Info - { - local software_name = ""; - local v: Version; - local parts: table[count] of string; - if ( /Opera [0-9\.]*$/ in unparsed_version ) - { - software_name = "Opera"; - parts = split_all(unparsed_version, /Opera [0-9\.]*$/); - if ( 2 in parts ) - v = parse(parts[2], host, software_type)$version; - } - else if ( /MSIE 7.*Trident\/4\.0/ in unparsed_version ) - { - software_name = "MSIE"; - v = [$major=8,$minor=0]; - } - else if ( / MSIE [0-9\.]*b?[0-9]*;/ in unparsed_version ) - { - software_name = "MSIE"; - parts = split_all(unparsed_version, /MSIE [0-9\.]*b?[0-9]*/); - if ( 2 in parts ) - v = parse(parts[2], host, software_type)$version; - } - else if ( /Version\/.*Safari\// in unparsed_version ) - { - software_name = "Safari"; - parts = split_all(unparsed_version, /Version\/[0-9\.]*/); - if ( 2 in parts ) - { - v = parse(parts[2], host, software_type)$version; - if ( / Mobile\/?.* Safari/ in unparsed_version ) - v$addl = "Mobile"; - } - } - else if ( /(Firefox|Netscape|Thunderbird)\/[0-9\.]*/ in unparsed_version ) - { - parts = split_all(unparsed_version, /(Firefox|Netscape|Thunderbird)\/[0-9\.]*/); - if ( 2 in parts ) - { - local tmp_s = parse(parts[2], host, software_type); - software_name = tmp_s$name; - v = tmp_s$version; - } - } - else if ( /Chrome\/.*Safari\// in unparsed_version ) - { - software_name = "Chrome"; - parts = split_all(unparsed_version, /Chrome\/[0-9\.]*/); - if ( 2 in parts ) - v = parse(parts[2], host, software_type)$version; - } - else if ( /^Opera\// in unparsed_version ) - { - if ( /Opera M(ini|obi)\// in unparsed_version ) - { - parts = split_all(unparsed_version, /Opera M(ini|obi)/); - if ( 2 in parts ) - software_name = parts[2]; - parts = split_all(unparsed_version, /Version\/[0-9\.]*/); - if ( 2 in parts ) - v = parse(parts[2], host, software_type)$version; - else - { - parts = split_all(unparsed_version, /Opera Mini\/[0-9\.]*/); - if ( 2 in parts ) - v = parse(parts[2], host, software_type)$version; - } - } - else - { - software_name = "Opera"; - parts = split_all(unparsed_version, /Version\/[0-9\.]*/); - if ( 2 in parts ) - v = parse(parts[2], host, software_type)$version; - } - } - else if ( /AppleWebKit\/[0-9\.]*/ in unparsed_version ) - { - software_name = "Unspecified WebKit"; - parts = split_all(unparsed_version, /AppleWebKit\/[0-9\.]*/); - if ( 2 in parts ) - v = parse(parts[2], host, software_type)$version; - } +type Description: record { + name: string; + version: Version; + unparsed_version: string; +}; - return [$ts=network_time(), $host=host, $name=software_name, $version=v, - $software_type=software_type, $unparsed_version=unparsed_version]; - } +# Defining this here because of a circular dependency between two functions. +global parse_mozilla: function(unparsed_version: string): Description; # Don't even try to understand this now, just make sure the tests are # working. -function parse(unparsed_version: string, - host: addr, - software_type: Type): Info +function parse(unparsed_version: string): Description { local software_name = ""; local v: Version; @@ -207,7 +124,7 @@ function parse(unparsed_version: string, # Parse browser-alike versions separately if ( /^(Mozilla|Opera)\/[0-9]\./ in unparsed_version ) { - return parse_mozilla(unparsed_version, host, software_type); + return parse_mozilla(unparsed_version); } else { @@ -232,7 +149,7 @@ function parse(unparsed_version: string, if ( 4 in version_numbers && version_numbers[4] != "" ) v$addl = strip(version_numbers[4]); else if ( 3 in version_parts && version_parts[3] != "" && - version_parts[3] != ")" ) + version_parts[3] != ")" ) { if ( /^[[:blank:]]*\([a-zA-Z0-9\-\._[:blank:]]*\)/ in version_parts[3] ) { @@ -269,9 +186,102 @@ function parse(unparsed_version: string, v$major = extract_count(version_numbers[1]); } } - return [$ts=network_time(), $host=host, $name=software_name, - $version=v, $unparsed_version=unparsed_version, - $software_type=software_type]; + + return [$version=v, $unparsed_version=unparsed_version, $name=software_name]; + } + + +function parse_mozilla(unparsed_version: string): Description + { + local software_name = ""; + local v: Version; + local parts: table[count] of string; + + if ( /Opera [0-9\.]*$/ in unparsed_version ) + { + software_name = "Opera"; + parts = split_all(unparsed_version, /Opera [0-9\.]*$/); + if ( 2 in parts ) + v = parse(parts[2])$version; + } + else if ( / MSIE / in unparsed_version ) + { + software_name = "MSIE"; + if ( /Trident\/4\.0/ in unparsed_version ) + v = [$major=8,$minor=0]; + else if ( /Trident\/5\.0/ in unparsed_version ) + v = [$major=9,$minor=0]; + else if ( /Trident\/6\.0/ in unparsed_version ) + v = [$major=10,$minor=0]; + else + { + parts = split_all(unparsed_version, /MSIE [0-9]{1,2}\.*[0-9]*b?[0-9]*/); + if ( 2 in parts ) + v = parse(parts[2])$version; + } + } + else if ( /Version\/.*Safari\// in unparsed_version ) + { + software_name = "Safari"; + parts = split_all(unparsed_version, /Version\/[0-9\.]*/); + if ( 2 in parts ) + { + v = parse(parts[2])$version; + if ( / Mobile\/?.* Safari/ in unparsed_version ) + v$addl = "Mobile"; + } + } + else if ( /(Firefox|Netscape|Thunderbird)\/[0-9\.]*/ in unparsed_version ) + { + parts = split_all(unparsed_version, /(Firefox|Netscape|Thunderbird)\/[0-9\.]*/); + if ( 2 in parts ) + { + local tmp_s = parse(parts[2]); + software_name = tmp_s$name; + v = tmp_s$version; + } + } + else if ( /Chrome\/.*Safari\// in unparsed_version ) + { + software_name = "Chrome"; + parts = split_all(unparsed_version, /Chrome\/[0-9\.]*/); + if ( 2 in parts ) + v = parse(parts[2])$version; + } + else if ( /^Opera\// in unparsed_version ) + { + if ( /Opera M(ini|obi)\// in unparsed_version ) + { + parts = split_all(unparsed_version, /Opera M(ini|obi)/); + if ( 2 in parts ) + software_name = parts[2]; + parts = split_all(unparsed_version, /Version\/[0-9\.]*/); + if ( 2 in parts ) + v = parse(parts[2])$version; + else + { + parts = split_all(unparsed_version, /Opera Mini\/[0-9\.]*/); + if ( 2 in parts ) + v = parse(parts[2])$version; + } + } + else + { + software_name = "Opera"; + parts = split_all(unparsed_version, /Version\/[0-9\.]*/); + if ( 2 in parts ) + v = parse(parts[2])$version; + } + } + else if ( /AppleWebKit\/[0-9\.]*/ in unparsed_version ) + { + software_name = "Unspecified WebKit"; + parts = split_all(unparsed_version, /AppleWebKit\/[0-9\.]*/); + if ( 2 in parts ) + v = parse(parts[2])$version; + } + + return [$version=v, $unparsed_version=unparsed_version, $name=software_name]; } @@ -356,7 +366,7 @@ function software_fmt(i: Info): string # Insert a mapping into the table # Overides old entries for the same software and generates events if needed. -event software_register(id: conn_id, info: Info) +event register(id: conn_id, info: Info) { # Host already known? if ( info$host !in tracked ) @@ -375,16 +385,40 @@ event software_register(id: conn_id, info: Info) if ( ! info$force_log && cmp_versions(old$version, info$version) == 0 ) return; } - - Log::write(SOFTWARE, info); ts[info$name] = info; + + Log::write(Software::LOG, info); } function found(id: conn_id, info: Info): bool { if ( info$force_log || addr_matches_host(info$host, asset_tracking) ) { - event software_register(id, info); + if ( !info?$ts ) + info$ts=network_time(); + + if ( info?$version ) # we have a version number and don't have to parse. check if the name is also set... + { + if ( ! info?$name ) + { + Reporter::error("Required field name not present in Software::found"); + return F; + } + } + else # no version present, we have to parse... + { + if ( !info?$unparsed_version ) + { + Reporter::error("No unparsed version string present in Info record with version in Software::found"); + return F; + } + local sw = parse(info$unparsed_version); + info$unparsed_version = sw$unparsed_version; + info$name = sw$name; + info$version = sw$version; + } + + event register(id, info); return T; } else diff --git a/scripts/base/frameworks/time-machine/notice.bro b/scripts/base/frameworks/time-machine/notice.bro deleted file mode 100644 index f012de8ee9..0000000000 --- a/scripts/base/frameworks/time-machine/notice.bro +++ /dev/null @@ -1,3 +0,0 @@ -# If we asked the Time Machine to capture, the filename prefix. -# TODO: implement this as a timemachine/notice.bro script? -#captured: string &optional; diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index 7fe403fe08..7129d8eb68 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -1,84 +1,180 @@ -@load const.bif.bro -@load types.bif.bro +@load base/const.bif +@load base/types.bif # Type declarations + +## An ordered array of strings. The entries are indexed by succesive numbers. Note +## that it depends on the usage whether the first index is zero or one. +## +## .. 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 string_array: table[count] of string; + +## A set of strings. +## +## .. 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 string_set: set[string]; + +## A set of addresses. +## +## .. 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 addr_set: set[addr]; + +## A set of counts. +## +## .. 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 count_set: set[count]; + +## A vector of counts, used by some builtin functions to store a list of indices. +## +## .. 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 index_vec: vector of count; + +## A vector of strings. +## +## .. 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 string_vec: vector of string; +## A vector of addresses. +## +## .. 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 addr_vec: vector of addr; + +## A table of strings indexed by strings. +## +## .. 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 table_string_of_string: table[string] of string; -type transport_proto: enum { unknown_transport, tcp, udp, icmp }; +## A connection's transport-layer protocol. Note that Bro uses the term +## "connection" broadly, using flow semantics for ICMP and UDP. +type transport_proto: enum { + unknown_transport, ##< An unknown transport-layer protocol. + tcp, ##< TCP. + udp, ##< UDP. + icmp ##< ICMP. +}; +## A connection's identifying 4-tuple of endpoints and ports. +## +## .. note:: It's actually a 5-tuple: the transport-layer protocol is stored as +## part of the port values, `orig_p` and `resp_p`, and can be extracted from them +## with :bro:id:`get_port_transport_proto`. type conn_id: record { - orig_h: addr; - orig_p: port; - resp_h: addr; - resp_p: port; + orig_h: addr; ##< The originator's IP address. + orig_p: port; ##< The originator's port number. + resp_h: addr; ##< The responder's IP address. + resp_p: port; ##< The responder's port number. } &log; +## Specifics about an ICMP conversation. ICMP events typically pass this in +## addition to :bro:type:`conn_id`. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect icmp_sent +## icmp_time_exceeded icmp_unreachable type icmp_conn: record { - orig_h: addr; - resp_h: addr; - itype: count; - icode: count; - len: count; -}; - -type icmp_hdr: record { - icmp_type: count; # type of message + orig_h: addr; ##< The originator's IP address. + resp_h: addr; ##< The responder's IP address. + itype: count; ##< The ICMP type of the packet that triggered the instantiation of the record. + icode: count; ##< The ICMP code of the packet that triggered the instantiation of the record. + len: count; ##< The length of the ICMP payload of the packet that triggered the instantiation of the record. + v6: bool; ##< True if it's an ICMPv6 packet. }; +## Packet context part of an ICMP message. The fields of this record reflect the +## packet that is described by the context. +## +## .. bro:see:: icmp_time_exceeded icmp_unreachable type icmp_context: record { - id: conn_id; - len: count; - proto: count; - frag_offset: count; + id: conn_id; ##< The packet's 4-tuple. + len: count; ##< The length of the IP packet (headers + payload). + proto: count; ##< The packet's transport-layer protocol. + frag_offset: count; ##< The packet's fragementation offset. + ## True if the packet's IP header is not fully included in the context + ## or if there is not enough of the transport header to determine source + ## and destination ports. If that is the cast, the appropriate fields + ## of this record will be set to null values. bad_hdr_len: bool; - bad_checksum: bool; - MF: bool; - DF: bool; + bad_checksum: bool; ##< True if the packet's IP checksum is not correct. + MF: bool; ##< True if the packets *more fragements* flag is set. + DF: bool; ##< True if the packets *don't fragment* flag is set. }; +# A DNS mapping between IP address and hostname resolved by Bro's internal +# resolver. +# +# .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +# dns_mapping_unverified dns_mapping_valid type dns_mapping: record { + ## The time when the mapping was created, which corresponds to the when the DNS + ## query was sent out. creation_time: time; - + ## If the mapping is the result of a name lookup, the queried host name; otherwise + ## empty. req_host: string; + ## If the mapping is the result of a pointer lookup, the queried address; otherwise + ## null. req_addr: addr; - + ## True if the lookup returned success. Only then, the result ields are valid. valid: bool; + ## If the mapping is the result of a pointer lookup, the resolved hostname; + ## otherwise empty. hostname: string; + ## If the mapping is the result of an address lookup, the resolved address(es); + ## otherwise empty. addrs: addr_set; }; +## A parsed host/port combination describing server endpoint for an upcoming +## data transfert. +## +## .. bro:see:: fmt_ftp_port parse_eftp_port parse_ftp_epsv parse_ftp_pasv +## parse_ftp_port type ftp_port: record { - h: addr; - p: port; - valid: bool; # true if format was right -}; - -type endpoint: record { - size: count; # logical size (for TCP: from seq numbers) - state: count; - - # The following are set if use_conn_size_analyzer is T. - num_pkts: count &optional; # number of packets on the wire - num_bytes_ip: count &optional; # actual number of IP-level bytes on the wire + h: addr; ##< The host's address. + p: port; ##< The host's port. + valid: bool; ##< True if format was right. Only then, *h* and *p* are valid. }; +## Statistics about what a TCP endpoint sent. +## +## .. bro:see:: conn_stats type endpoint_stats: record { - num_pkts: count; - num_rxmit: count; - num_rxmit_bytes: count; - num_in_order: count; - num_OO: count; - num_repl: count; + num_pkts: count; ##< Number of packets. + num_rxmit: count; ##< Number of retransmission. + num_rxmit_bytes: count; ##< Number of retransmitted bytes. + num_in_order: count; ##< Number of in-order packets. + num_OO: count; ##< Number out-of-order packets. + num_repl: count; ##< Number of replicated packets (last packet was sent again). + ## Endian type used by the endpoint, if it it could be determined from the sequence + ## numbers used. This is one of :bro:see:`ENDIAN_UNKNOWN`, :bro:see:`ENDIAN_BIG`, + ## :bro:see:`ENDIAN_LITTLE`, and :bro:see:`ENDIAN_CONFUSED`. endian_type: count; }; +## A unique analyzer instance ID. Each time instantiates a protocol analyzers +## for a connection, it assigns it a unique ID that can be used to reference +## that instance. +## +## .. bro:see:: analyzer_name disable_analyzer protocol_confirmation +## protocol_violation +## +## .. todo::While we declare an alias for the type here, the events/functions still +## use ``count``. That should be changed. type AnalyzerID: count; module Tunnel; @@ -96,130 +192,242 @@ export { } # end export module GLOBAL; +## Statistics about an endpoint. +## +## todo::Where is this used? +type endpoint: record { + size: count; ##< Logical size of data sent (for TCP: derived from sequence numbers). + ## Endpoint state. For TCP connection, one of the constants: + ## :bro:see:`TCP_INACTIVE` :bro:see:`TCP_SYN_SENT` :bro:see:`TCP_SYN_ACK_SENT` + ## :bro:see:`TCP_PARTIAL` :bro:see:`TCP_ESTABLISHED` :bro:see:`TCP_CLOSED` + ## :bro:see:`TCP_RESET`. For UDP, one of :bro:see:`UDP_ACTIVE` and + ## :bro:see:`UDP_INACTIVE`. + state: count; + ## Number of packets sent. Only set if :bro:id:`use_conn_size_analyzer` is true. + num_pkts: count &optional; + ## Number of IP-level bytes sent. Only set if :bro:id:`use_conn_size_analyzer` is + ## true. + num_bytes_ip: count &optional; +}; + +## A connection. This is Bro's basic connection type describing IP- and +## transport-layer information about the conversation. Note that Bro uses a +## liberal interpreation of "connection" and associates instances of this type +## also with UDP and ICMP flows. type connection: record { - id: conn_id; - orig: endpoint; - resp: endpoint; - start_time: time; + id: conn_id; ##< The connection's identifying 4-tuple. + orig: endpoint; ##< Statistics about originator side. + resp: endpoint; ##< Statistics about responder side. + start_time: time; ##< The timestamp of the connection's first packet. + ## The duration of the conversation. Roughly speaking, this is the interval between + ## first and last data packet (low-level TCP details may adjust it somewhat in + ## ambigious cases). duration: interval; - service: string_set; # if empty, service hasn't been determined - addl: string; - hot: count; # how hot; 0 = don't know or not hot - history: string; + ## The set of services the connection is using as determined by Bro's dynamic + ## protocol detection. Each entry is the label of an analyzer that confirmed that + ## it could parse the connection payload. While typically, there will be at + ## most one entry for each connection, in principle it is possible that more than + ## one protocol analyzer is able to parse the same data. If so, all will + ## be recorded. Also note that the recorced services are independent of any + ## transport-level protocols. + service: set[string]; + addl: string; ##< Deprecated. + hot: count; ##< Deprecated. + history: string; ##< State history of TCP connections. See *history* in :bro:see:`Conn::Info`. + ## A globally unique connection identifier. For each connection, Bro creates an ID + ## that is very likely unique across independent Bro runs. These IDs can thus be + ## used to tag and locate information associated with that connection. uid: string; + ## If the connection is tunneled, this field contains information about + ## the encapsulating "connection". tunnel_parent: Tunnel::Parent &optional; }; +## Fields of a SYN packet. +## +## .. bro:see:: connection_SYN_packet type SYN_packet: record { - is_orig: bool; - DF: bool; - ttl: count; - size: count; - win_size: count; - win_scale: int; - MSS: count; - SACK_OK: bool; + is_orig: bool; ##< True if the packet was sent the connection's originator. + DF: bool; ##< True if the *don't fragment* is set in the IP header. + ttl: count; ##< The IP header's time-to-live. + size: count; ##< The size of the packet's payload as specified in the IP header. + win_size: count; ##< The window size from the TCP header. + win_scale: int; ##< The window scale option if present, or -1 if not. + MSS: count; ##< The maximum segement size if present, or 0 if not. + SACK_OK: bool; ##< True if the *SACK* option is present. }; -## This record is used for grabbing packet capturing information from -## the core with the :bro:id:`net_stats` BiF. All counts are cumulative. +## Packet capture statistics. All counts are cumulative. +## +## .. bro:see:: net_stats type NetStats: record { - pkts_recvd: count &default=0; ##< Packets received by Bro. - pkts_dropped: count &default=0; ##< Packets dropped. - pkts_link: count &default=0; ##< Packets seen on the link (not always available). + pkts_recvd: count &default=0; ##< Packets received by Bro. + pkts_dropped: count &default=0; ##< Packets reported dropped by the system. + ## Packets seen on the link. Note that this may differ + ## from *pkts_recvd* because of a potential capture_filter. See + ## :doc:`/scripts/base/frameworks/packet-filter/main`. Depending on the packet + ## capture system, this value may not be available and will then be always set to + ## zero. + pkts_link: count &default=0; }; +## Statistics about Bro's resource consumption. +## +## .. bro:see:: resource_usage +## +## .. note:: All process-level values refer to Bro's main process only, not to +## the child process it spawns for doing communication. type bro_resources: record { - version: string; # Bro version string - debug: bool; # true if compiled with --enable-debug - start_time: time; # start time of process - real_time: interval; # elapsed real time since Bro started running - user_time: interval; # user CPU seconds - system_time: interval; # system CPU seconds - mem: count; # maximum memory consumed, in KB - minor_faults: count; # page faults not requiring actual I/O - major_faults: count; # page faults requiring actual I/O - num_swap: count; # times swapped out - blocking_input: count; # blocking input operations - blocking_output: count; # blocking output operations - num_context: count; # number of involuntary context switches + version: string; ##< Bro version string. + debug: bool; ##< True if compiled with --enable-debug. + start_time: time; ##< Start time of process. + real_time: interval; ##< Elapsed real time since Bro started running. + user_time: interval; ##< User CPU seconds. + system_time: interval; ##< System CPU seconds. + mem: count; ##< Maximum memory consumed, in KB. + minor_faults: count; ##< Page faults not requiring actual I/O. + major_faults: count; ##< Page faults requiring actual I/O. + num_swap: count; ##< Times swapped out. + blocking_input: count; ##< Blocking input operations. + blocking_output: count; ##< Blocking output operations. + num_context: count; ##< Number of involuntary context switches. - num_TCP_conns: count; # current number of TCP connections - num_UDP_conns: count; - num_ICMP_conns: count; - num_fragments: count; # current number of fragments pending reassembly - num_packets: count; # total number packets processed to date - num_timers: count; # current number of pending timers - num_events_queued: count; # total number of events queued so far - num_events_dispatched: count; # same for events dispatched + num_TCP_conns: count; ##< Current number of TCP connections in memory. + num_UDP_conns: count; ##< Current number of UDP flows in memory. + num_ICMP_conns: count; ##< Current number of ICMP flows in memory. + num_fragments: count; ##< Current number of fragments pending reassembly. + num_packets: count; ##< Total number packets processed to date. + num_timers: count; ##< Current number of pending timers. + num_events_queued: count; ##< Total number of events queued so far. + num_events_dispatched: count; ##< Total number of events dispatched so far. - max_TCP_conns: count; # maximum number of TCP connections, etc. - max_UDP_conns: count; - max_ICMP_conns: count; - max_fragments: count; - max_timers: count; + max_TCP_conns: count; ##< Maximum number of concurrent TCP connections so far. + max_UDP_conns: count; ##< Maximum number of concurrent UDP connections so far. + max_ICMP_conns: count; ##< Maximum number of concurrent ICMP connections so far. + max_fragments: count; ##< Maximum number of concurrently buffered fragements so far. + max_timers: count; ##< Maximum number of concurrent timers pending so far. }; - -# Summary statistics of all DFA_State_Caches. +## Summary statistics of all regular expression matchers. +## +## .. bro:see:: get_matcher_stats type matcher_stats: record { - matchers: count; # number of distinct RE matchers - dfa_states: count; # number of DFA states across all matchers - computed: count; # number of computed DFA state transitions - mem: count; # number of bytes used by DFA states - hits: count; # number of cache hits - misses: count; # number of cache misses - avg_nfa_states: count; # average # NFA states across all matchers + matchers: count; ##< Number of distinct RE matchers. + dfa_states: count; ##< Number of DFA states across all matchers. + computed: count; ##< Number of computed DFA state transitions. + mem: count; ##< Number of bytes used by DFA states. + hits: count; ##< Number of cache hits. + misses: count; ##< Number of cache misses. + avg_nfa_states: count; ##< Average number of NFA states across all matchers. }; -# Info provided to gap_report, and also available by get_gap_summary(). +## Statistics about number of gaps in TCP connections. +## +## .. bro:see:: gap_report get_gap_summary type gap_info: record { - ack_events: count; # how many ack events *could* have had gaps - ack_bytes: count; # how many bytes those covered - gap_events: count; # how many *did* have gaps - gap_bytes: count; # how many bytes were missing in the gaps: + ack_events: count; ##< How many ack events *could* have had gaps. + ack_bytes: count; ##< How many bytes those covered. + gap_events: count; ##< How many *did* have gaps. + gap_bytes: count; ##< How many bytes were missing in the gaps. }; -# This record should be read-only. +## Deprecated. +## +## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere +## else. type packet: record { conn: connection; is_orig: bool; - seq: count; # seq=k => it is the kth *packet* of the connection + seq: count; ##< seq=k => it is the kth *packet* of the connection timestamp: time; }; -type var_sizes: table[string] of count; # indexed by var's name, returns size +## Table type used to map variable names to their memory allocation. +## +## .. bro:see:: global_sizes +## +## .. 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 var_sizes: table[string] of count; +## Meta-information about a script-level identifier. +## +## .. bro:see:: global_ids id_table type script_id: record { - type_name: string; - exported: bool; - constant: bool; - enum_constant: bool; - redefinable: bool; - value: any &optional; + type_name: string; ##< The name of the identifier's type. + exported: bool; ##< True if the identifier is exported. + constant: bool; ##< True if the identifier is a constant. + enum_constant: bool; ##< True if the identifier is an enum value. + redefinable: bool; ##< True if the identifier is declared with the :bro:attr:`&redef` attribute. + value: any &optional; ##< The current value of the identifier. }; +## Table type used to map script-level identifiers to meta-information +## describing them. +## +## .. bro:see:: global_ids script_id +## +## .. 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 id_table: table[string] of script_id; +## Meta-information about a record-field. +## +## .. bro:see:: record_fields record_field_table type record_field: record { - type_name: string; - log: bool; + type_name: string; ##< The name of the field's type. + log: bool; ##< True of the field is declared with :bro:attr:`&log` attribute. + ## The current value of the field in the record instance passed into + ## :bro:see:`record_fields` (if it has one). value: any &optional; - default_val: any &optional; + default_val: any &optional; ##< The value of the :bro:attr:`&default` attribute if defined. }; +## Table type used to map record field declarations to meta-information describing +## them. +## +## .. bro:see:: record_fields record_field +## +## .. 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 record_field_table: table[string] of record_field; +# todo::Do we still needs these here? Can they move into the packet filter +# framework? +# # The following two variables are defined here until the core is not # dependent on the names remaining as they are now. -## This is the list of capture filters indexed by some user-definable ID. + +## Set of BPF capture filters to use for capturing, indexed by a user-definable +## ID (which must be unique). If Bro is *not* configured to examine +## :bro:id:`PacketFilter::all_packets`, all packets matching at least +## one of the filters in this table (and all in :bro:id:`restrict_filters`) +## will be analyzed. +## +## .. bro:see:: PacketFilter PacketFilter::all_packets +## PacketFilter::unrestricted_filter restrict_filters global capture_filters: table[string] of string &redef; -## This is the list of restriction filters indexed by some user-definable ID. + +## Set of BPF filters to restrict capturing, indexed by a user-definable ID (which +## must be unique). If Bro is *not* configured to examine +## :bro:id:`PacketFilter::all_packets`, only packets matching *all* of the +## filters in this table (and any in :bro:id:`capture_filters`) will be +## analyzed. +## +## .. bro:see:: PacketFilter PacketFilter::all_packets +## PacketFilter::unrestricted_filter capture_filters global restrict_filters: table[string] of string &redef; -# {precompile,install}_pcap_filter identify the filter by IDs +## Enum type identifying dynamic BPF filters. These are used by +## :bro:see:`precompile_pcap_filter` and :bro:see:`precompile_pcap_filter`. type PcapFilterID: enum { None }; +## Deprecated. +## +## .. bro:see:: anonymize_addr type IPAddrAnonymization: enum { KEEP_ORIG_ADDR, SEQUENTIALLY_NUMBERED, @@ -228,34 +436,54 @@ type IPAddrAnonymization: enum { PREFIX_PRESERVING_MD5, }; +## Deprecated. +## +## .. bro:see:: anonymize_addr type IPAddrAnonymizationClass: enum { - ORIG_ADDR, # client address - RESP_ADDR, # server address + ORIG_ADDR, + RESP_ADDR, OTHER_ADDR, }; - -# Events are generated by event_peer's (which may be either ourselves, or -# some remote process). +## A locally unique ID identifying a communication peer. The ID is returned by +## :bro:id:`connect`. +## +## .. bro:see:: connect Communication type peer_id: count; +## A communication peer. +## +## .. bro:see:: complete_handshake disconnect finished_send_state +## get_event_peer get_local_event_peer remote_capture_filter +## remote_connection_closed remote_connection_error +## remote_connection_established remote_connection_handshake_done +## remote_event_registered remote_log_peer remote_pong +## request_remote_events request_remote_logs request_remote_sync +## send_capture_filter send_current_packet send_id send_ping send_state +## set_accept_state set_compression_level +## +## .. todo::The type's name is to narrow these days, should rename. type event_peer: record { - id: peer_id; # locally unique ID of peer (returned by connect()) - host: addr; + id: peer_id; ##< Locally unique ID of peer (returned by :bro:id:`connect`). + host: addr; ##< The IP address of the peer. + ## Either the port we connected to at the peer; or our port the peer + ## connected to if the session is remotely initiated. p: port; - is_local: bool; # true if this peer describes the current process. - descr: string; # source's external_source_description - class: string &optional; # self-assigned class of the peer + is_local: bool; ##< True if this record describes the local process. + descr: string; ##< The peer's :bro:see:`peer_description`. + class: string &optional; ##< The self-assigned *class* of the peer. See :bro:see:`Communication::Node`. }; +## Deprecated. +## +## .. bro:see:: rotate_file rotate_file_by_name rotate_interval type rotate_info: record { - old_name: string; # original filename - new_name: string; # file name after rotation - open: time; # time when opened - close: time; # time when closed + old_name: string; ##< Original filename. + new_name: string; ##< File name after rotation. + open: time; ##< Time when opened. + close: time; ##< Time when closed. }; - ### The following aren't presently used, though they should be. # # Structures needed for subsequence computations (str_smith_waterman): # # @@ -264,67 +492,104 @@ type rotate_info: record { # SW_MULTIPLE, # }; +## Paramerts for the Smith-Waterman algorithm. +## +## .. bro:see:: str_smith_waterman type sw_params: record { - # Minimum size of a substring, minimum "granularity". + ## Minimum size of a substring, minimum "granularity". min_strlen: count &default = 3; - # Smith-Waterman flavor to use. + ## Smith-Waterman flavor to use. sw_variant: count &default = 0; }; +## Helper type for return value of Smith-Waterman algorithm. +## +## .. bro:see:: str_smith_waterman sw_substring_vec sw_substring sw_align_vec sw_params type sw_align: record { - str: string; # string a substring is part of - index: count; # at which offset + str: string; ##< String a substring is part of. + index: count; ##< Offset substring is located. }; +## Helper type for return value of Smith-Waterman algorithm. +## +## .. bro:see:: str_smith_waterman sw_substring_vec sw_substring sw_align sw_params type sw_align_vec: vector of sw_align; +## Helper type for return value of Smith-Waterman algorithm. +## +## .. bro:see:: str_smith_waterman sw_substring_vec sw_align_vec sw_align sw_params +## type sw_substring: record { - str: string; # a substring - aligns: sw_align_vec; # all strings of which it's a substring - new: bool; # true if start of new alignment + str: string; ##< A substring. + aligns: sw_align_vec; ##< All strings of which it's a substring. + new: bool; ##< True if start of new alignment. }; +## Return type for Smith-Waterman algorithm. +## +## .. bro:see:: str_smith_waterman sw_substring sw_align_vec sw_align sw_params +## +## .. 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 sw_substring_vec: vector of sw_substring; -# Policy-level handling of pcap packets. +## Policy-level representation of a packet passed on by libpcap. The data includes +## the complete packet as returned by libpcap, including the link-layer header. +## +## .. bro:see:: dump_packet get_current_packet type pcap_packet: record { - ts_sec: count; - ts_usec: count; - caplen: count; - len: count; - data: string; + ts_sec: count; ##< The non-fractional part of the packet's timestamp (i.e., full seconds since the epoch). + ts_usec: count; ##< The fractional part of the packet's timestamp. + caplen: count; ##< The number of bytes captured (<= *len*). + len: count; ##< The length of the packet in bytes, including `_ for more information, Bro uses the same +## code. +## +## .. bro:see:: entropy_test_add entropy_test_finish entropy_test_init find_entropy type entropy_test_result: record { - entropy: double; - chi_square: double; - mean: double; - monte_carlo_pi: double; - serial_correlation: double; + entropy: double; ##< Information density. + chi_square: double; ##< Chi-Square value. + mean: double; ##< Arithmetic Mean. + monte_carlo_pi: double; ##< Monte-carlo value for pi. + serial_correlation: double; ##< Serial correlation coefficient. }; # Prototypes of Bro built-in functions. -@load strings.bif.bro -@load bro.bif.bro -@load reporter.bif.bro +@load base/strings.bif +@load base/bro.bif +@load base/reporter.bif +## Deprecated. This is superseded by the new logging framework. global log_file_name: function(tag: string): string &redef; + +## Deprecated. This is superseded by the new logging framework. global open_log_file: function(tag: string): file &redef; -# Where to store the persistent state. +## Specifies a directory for Bro store its persistent state. All globals can +## be declared persistent via the :bro:attr:`&persistent` attribute. const state_dir = ".state" &redef; -# Length of the delays added when storing state incrementally. +## Length of the delays inserted when storing state incrementally. To avoid +## dropping packets when serializing larger volumes of persistent state to +## disk, Bro interleaves the operation with continued packet processing. const state_write_delay = 0.01 secs &redef; global done_with_network = F; @@ -341,6 +606,7 @@ function open_log_file(tag: string): file return open(log_file_name(tag)); } +## Internal function. function add_interface(iold: string, inew: string): string { if ( iold == "" ) @@ -348,8 +614,12 @@ function add_interface(iold: string, inew: string): string else return fmt("%s %s", iold, inew); } + +## Network interfaces to listen on. Use ``redef interfaces += "eth0"`` to +## extend. global interfaces = "" &add_func = add_interface; +## Internal function. function add_signature_file(sold: string, snew: string): string { if ( sold == "" ) @@ -357,11 +627,15 @@ function add_signature_file(sold: string, snew: string): string else return cat(sold, " ", snew); } + +## Signature files to read. Use ``redef signature_files += "foo.sig"`` to +## extend. Signature files will be searched relative to ``BROPATH``. global signature_files = "" &add_func = add_signature_file; +## ``p0f`` fingerprint file to use. Will be searched relative to ``BROPATH``. const passive_fingerprint_file = "base/misc/p0f.fp" &redef; -# TODO: testing to see if I can remove these without causing problems. +# todo::testing to see if I can remove these without causing problems. #const ftp = 21/tcp; #const ssh = 22/tcp; #const telnet = 23/tcp; @@ -374,161 +648,265 @@ const passive_fingerprint_file = "base/misc/p0f.fp" &redef; #const bgp = 179/tcp; #const rlogin = 513/tcp; -const TCP_INACTIVE = 0; -const TCP_SYN_SENT = 1; -const TCP_SYN_ACK_SENT = 2; -const TCP_PARTIAL = 3; -const TCP_ESTABLISHED = 4; -const TCP_CLOSED = 5; -const TCP_RESET = 6; +# TCP values for :bro:see:`endpoint` *state* field. +# todo::these should go into an enum to make them autodoc'able. +const TCP_INACTIVE = 0; ##< Endpoint is still inactive. +const TCP_SYN_SENT = 1; ##< Endpoint has sent SYN. +const TCP_SYN_ACK_SENT = 2; ##< Endpoint has sent SYN/ACK. +const TCP_PARTIAL = 3; ##< Endpoint has sent data but no initial SYN. +const TCP_ESTABLISHED = 4; ##< Endpoint has finished initial handshake regularly. +const TCP_CLOSED = 5; ##< Endpoint has closed connection. +const TCP_RESET = 6; ##< Endpoint has sent RST. -# If true, don't verify checksums. Useful for running on altered trace -# files, and for saving a few cycles, but of course dangerous, too ... -# Note that the -C command-line option overrides the setting of this -# variable. +# UDP values for :bro:see:`endpoint` *state* field. +# todo::these should go into an enum to make them autodoc'able. +const UDP_INACTIVE = 0; ##< Endpoint is still inactive. +const UDP_ACTIVE = 1; ##< Endpoint has sent something. + +## If true, don't verify checksums. Useful for running on altered trace +## files, and for saving a few cycles, but at the risk of analyzing invalid +## data. Note that the ``-C`` command-line option overrides the setting of this +## variable. const ignore_checksums = F &redef; -# If true, instantiate connection state when a partial connection -# (one missing its initial establishment negotiation) is seen. +## If true, instantiate connection state when a partial connection +## (one missing its initial establishment negotiation) is seen. const partial_connection_ok = T &redef; -# If true, instantiate connection state when a SYN ack is seen -# but not the initial SYN (even if partial_connection_ok is false). +## If true, instantiate connection state when a SYN/ACK is seen but not the initial +## SYN (even if :bro:see:`partial_connection_ok` is false). const tcp_SYN_ack_ok = T &redef; -# If a connection state is removed there may still be some undelivered -# data waiting in the reassembler. If true, pass this to the signature -# engine before flushing the state. +## If true, pass any undelivered to the signature engine before flushing the state. +## If a connection state is removed, there may still be some data waiting in the +## reassembler. const tcp_match_undelivered = T &redef; -# Check up on the result of an initial SYN after this much time. +## Check up on the result of an initial SYN after this much time. const tcp_SYN_timeout = 5 secs &redef; -# After a connection has closed, wait this long for further activity -# before checking whether to time out its state. +## After a connection has closed, wait this long for further activity +## before checking whether to time out its state. const tcp_session_timer = 6 secs &redef; -# When checking a closed connection for further activity, consider it -# inactive if there hasn't been any for this long. Complain if the -# connection is reused before this much time has elapsed. +## When checking a closed connection for further activity, consider it +## inactive if there hasn't been any for this long. Complain if the +## connection is reused before this much time has elapsed. const tcp_connection_linger = 5 secs &redef; -# Wait this long upon seeing an initial SYN before timing out the -# connection attempt. +## Wait this long upon seeing an initial SYN before timing out the +## connection attempt. const tcp_attempt_delay = 5 secs &redef; -# Upon seeing a normal connection close, flush state after this much time. +## Upon seeing a normal connection close, flush state after this much time. const tcp_close_delay = 5 secs &redef; -# Upon seeing a RST, flush state after this much time. +## Upon seeing a RST, flush state after this much time. const tcp_reset_delay = 5 secs &redef; -# Generate a connection_partial_close event this much time after one half -# of a partial connection closes, assuming there has been no subsequent -# activity. +## Generate a :bro:id:`connection_partial_close` event this much time after one half +## of a partial connection closes, assuming there has been no subsequent +## activity. const tcp_partial_close_delay = 3 secs &redef; -# If a connection belongs to an application that we don't analyze, -# time it out after this interval. If 0 secs, then don't time it out. +## If a connection belongs to an application that we don't analyze, +## time it out after this interval. If 0 secs, then don't time it out (but +## :bro:see:`tcp_inactivity_timeout`/:bro:see:`udp_inactivity_timeout`/:bro:see:`icmp_inactivity_timeout` +## still apply). const non_analyzed_lifetime = 0 secs &redef; -# If a connection is inactive, time it out after this interval. -# If 0 secs, then don't time it out. +## If a TCP connection is inactive, time it out after this interval. If 0 secs, +## then don't time it out. +## +## .. bro:see:: udp_inactivity_timeout icmp_inactivity_timeout set_inactivity_timeout const tcp_inactivity_timeout = 5 min &redef; + +## If a UDP flow is inactive, time it out after this interval. If 0 secs, then +## don't time it out. +## +## .. bro:see:: tcp_inactivity_timeout icmp_inactivity_timeout set_inactivity_timeout const udp_inactivity_timeout = 1 min &redef; + +## If an ICMP flow is inactive, time it out after this interval. If 0 secs, then +## don't time it out. +## +## .. bro:see:: tcp_inactivity_timeout udp_inactivity_timeout set_inactivity_timeout const icmp_inactivity_timeout = 1 min &redef; -# This many FINs/RSTs in a row constitutes a "storm". +## Number of FINs/RSTs in a row that constitute a "storm". Storms are reported via +## as ``weird`` via the notice framework, and they must also come within +## intervals of at most :bro:see:`tcp_storm_interarrival_thresh`. +## +## .. bro:see:: tcp_storm_interarrival_thresh const tcp_storm_thresh = 1000 &redef; -# The FINs/RSTs must come with this much time or less between them. +## FINs/RSTs must come with this much time or less between them to be +## considered a "storm". +## +## .. bro:see:: tcp_storm_thresh const tcp_storm_interarrival_thresh = 1 sec &redef; -# Maximum amount of data that might plausibly be sent in an initial -# flight (prior to receiving any acks). Used to determine whether we -# must not be seeing our peer's acks. Set to zero to turn off this -# determination. +## Maximum amount of data that might plausibly be sent in an initial flight (prior +## to receiving any acks). Used to determine whether we must not be seeing our +## peer's ACKs. Set to zero to turn off this determination. +## +## .. bro:see:: tcp_max_above_hole_without_any_acks tcp_excessive_data_without_further_acks const tcp_max_initial_window = 4096; -# If we're not seeing our peer's acks, the maximum volume of data above -# a sequence hole that we'll tolerate before assuming that there's -# been a packet drop and we should give up on tracking a connection. -# If set to zero, then we don't ever give up. +## If we're not seeing our peer's ACKs, the maximum volume of data above a sequence +## hole that we'll tolerate before assuming that there's been a packet drop and we +## should give up on tracking a connection. If set to zero, then we don't ever give +## up. +## +## .. bro:see:: tcp_max_initial_window tcp_excessive_data_without_further_acks const tcp_max_above_hole_without_any_acks = 4096; -# If we've seen this much data without any of it being acked, we give up -# on that connection to avoid memory exhaustion due to buffering all that -# stuff. If set to zero, then we don't ever give up. Ideally, Bro would -# track the current window on a connection and use it to infer that data -# has in fact gone too far, but for now we just make this quite beefy. +## If we've seen this much data without any of it being acked, we give up +## on that connection to avoid memory exhaustion due to buffering all that +## stuff. If set to zero, then we don't ever give up. Ideally, Bro would +## track the current window on a connection and use it to infer that data +## has in fact gone too far, but for now we just make this quite beefy. +## +## .. bro:see:: tcp_max_initial_window tcp_max_above_hole_without_any_acks const tcp_excessive_data_without_further_acks = 10 * 1024 * 1024; -# For services without a handler, these sets define which -# side of a connection is to be reassembled. +## For services without an a handler, these sets define originator-side ports that +## still trigger reassembly. +## +## .. :bro:see:: tcp_reassembler_ports_resp const tcp_reassembler_ports_orig: set[port] = {} &redef; + +## For services without an a handler, these sets define responder-side ports that +## still trigger reassembly. +## +## .. :bro:see:: tcp_reassembler_ports_orig const tcp_reassembler_ports_resp: set[port] = {} &redef; -# These sets define destination ports for which the contents -# of the originator (responder, respectively) stream should -# be delivered via tcp_contents. +## Defines destination TCP ports for which the contents of the originator stream +## should be delivered via :bro:see:`tcp_contents`. +## +## .. bro:see:: tcp_content_delivery_ports_resp tcp_content_deliver_all_orig +## tcp_content_deliver_all_resp udp_content_delivery_ports_orig +## udp_content_delivery_ports_resp udp_content_deliver_all_orig +## udp_content_deliver_all_resp tcp_contents const tcp_content_delivery_ports_orig: table[port] of bool = {} &redef; + +## Defines destination TCP ports for which the contents of the responder stream should +## be delivered via :bro:see:`tcp_contents`. +## +## .. bro:see:: tcp_content_delivery_ports_orig tcp_content_deliver_all_orig +## tcp_content_deliver_all_resp udp_content_delivery_ports_orig +## udp_content_delivery_ports_resp udp_content_deliver_all_orig +## udp_content_deliver_all_resp tcp_contents const tcp_content_delivery_ports_resp: table[port] of bool = {} &redef; -# To have all TCP orig->resp/resp->orig traffic reported via tcp_contents, -# redef these to T. +## If true, all TCP originator-side traffic is reported via +## :bro:see:`tcp_contents`. +## +## .. bro:see:: tcp_content_delivery_ports_orig tcp_content_delivery_ports_resp +## tcp_content_deliver_all_resp udp_content_delivery_ports_orig +## udp_content_delivery_ports_resp udp_content_deliver_all_orig +## udp_content_deliver_all_resp tcp_contents const tcp_content_deliver_all_orig = F &redef; + +## If true, all TCP responder-side traffic is reported via +## :bro:see:`tcp_contents`. +## +## .. bro:see:: tcp_content_delivery_ports_orig +## tcp_content_delivery_ports_resp +## tcp_content_deliver_all_orig udp_content_delivery_ports_orig +## udp_content_delivery_ports_resp udp_content_deliver_all_orig +## udp_content_deliver_all_resp tcp_contents const tcp_content_deliver_all_resp = F &redef; -# These sets define destination ports for which the contents -# of the originator (responder, respectively) stream should -# be delivered via udp_contents. +## Defines UDP destination ports for which the contents of the originator stream +## should be delivered via :bro:see:`udp_contents`. +## +## .. bro:see:: tcp_content_delivery_ports_orig +## tcp_content_delivery_ports_resp +## tcp_content_deliver_all_orig tcp_content_deliver_all_resp +## udp_content_delivery_ports_resp udp_content_deliver_all_orig +## udp_content_deliver_all_resp udp_contents const udp_content_delivery_ports_orig: table[port] of bool = {} &redef; + +## Defines UDP destination ports for which the contents of the originator stream +## should be delivered via :bro:see:`udp_contents`. +## +## .. bro:see:: tcp_content_delivery_ports_orig +## tcp_content_delivery_ports_resp tcp_content_deliver_all_orig +## tcp_content_deliver_all_resp udp_content_delivery_ports_orig +## udp_content_deliver_all_orig udp_content_deliver_all_resp udp_contents const udp_content_delivery_ports_resp: table[port] of bool = {} &redef; -# To have all UDP orig->resp/resp->orig traffic reported via udp_contents, -# redef these to T. +## If true, all UDP originator-side traffic is reported via +## :bro:see:`tcp_contents`. +## +## .. bro:see:: tcp_content_delivery_ports_orig +## tcp_content_delivery_ports_resp tcp_content_deliver_all_resp +## tcp_content_delivery_ports_orig udp_content_delivery_ports_orig +## udp_content_delivery_ports_resp udp_content_deliver_all_resp +## udp_contents const udp_content_deliver_all_orig = F &redef; + +## If true, all UDP responder-side traffic is reported via +## :bro:see:`tcp_contents`. +## +## .. bro:see:: tcp_content_delivery_ports_orig +## tcp_content_delivery_ports_resp tcp_content_deliver_all_resp +## tcp_content_delivery_ports_orig udp_content_delivery_ports_orig +## udp_content_delivery_ports_resp udp_content_deliver_all_orig +## udp_contents const udp_content_deliver_all_resp = F &redef; -# Check for expired table entries after this amount of time +## Check for expired table entries after this amount of time. +## +## .. bro:see:: table_incremental_step table_expire_delay const table_expire_interval = 10 secs &redef; -# When expiring/serializing, don't work on more than this many table -# entries at a time. +## When expiring/serializing table entries, don't work on more than this many table +## at a time. +## +## .. bro:see:: table_expire_interval table_expire_delay const table_incremental_step = 5000 &redef; -# When expiring, wait this amount of time before checking the next chunk -# of entries. +## When expiring table entries, wait this amount of time before checking the next +## chunk of entries. +## +## .. :bro:see:: table_expire_interval table_incremental_step const table_expire_delay = 0.01 secs &redef; -# Time to wait before timing out a DNS/NTP/RPC request. +## Time to wait before timing out a DNS request. const dns_session_timeout = 10 sec &redef; + +## Time to wait before timing out an NTP request. const ntp_session_timeout = 300 sec &redef; + +## Time to wait before timing out an RPC request. const rpc_timeout = 24 sec &redef; -# Time window for reordering packets (to deal with timestamp -# discrepency between multiple packet sources). -const packet_sort_window = 0 usecs &redef; - -# How long to hold onto fragments for possible reassembly. A value -# of 0.0 means "forever", which resists evasion, but can lead to -# state accrual. +## How long to hold onto fragments for possible reassembly. A value of 0.0 means +## "forever", which resists evasion, but can lead to state accrual. const frag_timeout = 0.0 sec &redef; -# Whether to use the ConnSize analyzer to count the number of -# packets and IP-level bytes transfered by each endpoint. If -# true, these values are returned in the connection's endpoint -# record val. +## Time window for reordering packets. This is used for dealing with timestamp +## discrepency between multiple packet sources. +## +## .. note:: Setting this can have a major performance impact as now packets need +## to be potentially copied and buffered. +const packet_sort_window = 0 usecs &redef; + +## Whether to use the ``ConnSize`` analyzer to count the number of packets and +## IP-level bytes transfered by each endpoint. If true, these values are returned +## in the connection's :bro:see:`endpoint` record value. const use_conn_size_analyzer = T &redef; -const UDP_INACTIVE = 0; -const UDP_ACTIVE = 1; # means we've seen something from this endpoint - -const ENDIAN_UNKNOWN = 0; -const ENDIAN_LITTLE = 1; -const ENDIAN_BIG = 2; -const ENDIAN_CONFUSED = 3; +# todo::these should go into an enum to make them autodoc'able. +const ENDIAN_UNKNOWN = 0; ##< Endian not yet determined. +const ENDIAN_LITTLE = 1; ##< Little endian. +const ENDIAN_BIG = 2; ##< Big endian. +const ENDIAN_CONFUSED = 3; ##< Tried to determine endian, but failed. +## Deprecated. function append_addl(c: connection, addl: string) { if ( c$addl == "" ) @@ -538,6 +916,7 @@ function append_addl(c: connection, addl: string) c$addl = fmt("%s %s", c$addl, addl); } +## Deprecated. function append_addl_marker(c: connection, addl: string, marker: string) { if ( c$addl == "" ) @@ -548,154 +927,637 @@ function append_addl_marker(c: connection, addl: string, marker: string) } -# Values for set_contents_file's "direction" argument. -const CONTENTS_NONE = 0; # turn off recording of contents -const CONTENTS_ORIG = 1; # record originator contents -const CONTENTS_RESP = 2; # record responder contents -const CONTENTS_BOTH = 3; # record both originator and responder contents - -const ICMP_UNREACH_NET = 0; -const ICMP_UNREACH_HOST = 1; -const ICMP_UNREACH_PROTOCOL = 2; -const ICMP_UNREACH_PORT = 3; -const ICMP_UNREACH_NEEDFRAG = 4; -const ICMP_UNREACH_ADMIN_PROHIB = 13; -# The above list isn't exhaustive ... +# Values for :bro:see:`set_contents_file` *direction* argument. +# todo::these should go into an enum to make them autodoc'able +const CONTENTS_NONE = 0; ##< Turn off recording of contents. +const CONTENTS_ORIG = 1; ##< Record originator contents. +const CONTENTS_RESP = 2; ##< Record responder contents. +const CONTENTS_BOTH = 3; ##< Record both originator and responder contents. +# Values for code of ICMP *unreachable* messages. The list is not exhaustive. +# todo::these should go into an enum to make them autodoc'able +# +# .. bro:see:: :bro:see:`icmp_unreachable ` +const ICMP_UNREACH_NET = 0; ##< Network unreachable. +const ICMP_UNREACH_HOST = 1; ##< Host unreachable. +const ICMP_UNREACH_PROTOCOL = 2; ##< Protocol unreachable. +const ICMP_UNREACH_PORT = 3; ##< Port unreachable. +const ICMP_UNREACH_NEEDFRAG = 4; ##< Fragement needed. +const ICMP_UNREACH_ADMIN_PROHIB = 13; ##< Adminstratively prohibited. # Definitions for access to packet headers. Currently only used for # discarders. -const IPPROTO_IP = 0; # dummy for IP -const IPPROTO_ICMP = 1; # control message protocol -const IPPROTO_IGMP = 2; # group mgmt protocol -const IPPROTO_IPIP = 4; # IP encapsulation in IP -const IPPROTO_TCP = 6; # TCP -const IPPROTO_UDP = 17; # user datagram protocol -const IPPROTO_RAW = 255; # raw IP packet +# todo::these should go into an enum to make them autodoc'able +const IPPROTO_IP = 0; ##< Dummy for IP. +const IPPROTO_ICMP = 1; ##< Control message protocol. +const IPPROTO_IGMP = 2; ##< Group management protocol. +const IPPROTO_IPIP = 4; ##< IP encapsulation in IP. +const IPPROTO_TCP = 6; ##< TCP. +const IPPROTO_UDP = 17; ##< User datagram protocol. +const IPPROTO_IPV6 = 41; ##< IPv6 header. +const IPPROTO_ICMPV6 = 58; ##< ICMP for IPv6. +const IPPROTO_RAW = 255; ##< Raw IP packet. -type ip_hdr: record { - hl: count; # header length (in bytes) - tos: count; # type of service - len: count; # total length - id: count; # identification - ttl: count; # time to live - p: count; # protocol - src: addr; # source address - dst: addr; # dest address +# Definitions for IPv6 extension headers. +const IPPROTO_HOPOPTS = 0; ##< IPv6 hop-by-hop-options header. +const IPPROTO_ROUTING = 43; ##< IPv6 routing header. +const IPPROTO_FRAGMENT = 44; ##< IPv6 fragment header. +const IPPROTO_ESP = 50; ##< IPv6 encapsulating security payload header. +const IPPROTO_AH = 51; ##< IPv6 authentication header. +const IPPROTO_NONE = 59; ##< IPv6 no next header. +const IPPROTO_DSTOPTS = 60; ##< IPv6 destination options header. +const IPPROTO_MOBILITY = 135; ##< IPv6 mobility header. + +## Values extracted from an IPv6 extension header's (e.g. hop-by-hop or +## destination option headers) option field. +## +## .. bro:see:: ip6_hdr ip6_hdr_chain ip6_hopopts ip6_dstopts +type ip6_option: record { + otype: count; ##< Option type. + len: count; ##< Option data length. + data: string; ##< Option data. +}; + +## Values extracted from an IPv6 Hop-by-Hop options extension header. +## +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain ip6_option +type ip6_hopopts: record { + ## Protocol number of the next header (RFC 1700 et seq., IANA assigned + ## number), e.g. :bro:id:`IPPROTO_ICMP`. + nxt: count; + ## Length of header in 8-octet units, excluding first unit. + len: count; + ## The TLV encoded options; + options: vector of ip6_option; +}; + +## Values extracted from an IPv6 Destination options extension header. +## +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain ip6_option +type ip6_dstopts: record { + ## Protocol number of the next header (RFC 1700 et seq., IANA assigned + ## number), e.g. :bro:id:`IPPROTO_ICMP`. + nxt: count; + ## Length of header in 8-octet units, excluding first unit. + len: count; + ## The TLV encoded options; + options: vector of ip6_option; +}; + +## Values extracted from an IPv6 Routing extension header. +## +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain +type ip6_routing: record { + ## Protocol number of the next header (RFC 1700 et seq., IANA assigned + ## number), e.g. :bro:id:`IPPROTO_ICMP`. + nxt: count; + ## Length of header in 8-octet units, excluding first unit. + len: count; + ## Routing type. + rtype: count; + ## Segments left. + segleft: count; + ## Type-specific data. + data: string; +}; + +## Values extracted from an IPv6 Fragment extension header. +## +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain +type ip6_fragment: record { + ## Protocol number of the next header (RFC 1700 et seq., IANA assigned + ## number), e.g. :bro:id:`IPPROTO_ICMP`. + nxt: count; + ## 8-bit reserved field. + rsv1: count; + ## Fragmentation offset. + offset: count; + ## 2-bit reserved field. + rsv2: count; + ## More fragments. + more: bool; + ## Fragment identification. + id: count; +}; + +## Values extracted from an IPv6 Authentication extension header. +## +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain +type ip6_ah: record { + ## Protocol number of the next header (RFC 1700 et seq., IANA assigned + ## number), e.g. :bro:id:`IPPROTO_ICMP`. + nxt: count; + ## Length of header in 4-octet units, excluding first two units. + len: count; + ## Reserved field. + rsv: count; + ## Security Parameter Index. + spi: count; + ## Sequence number. + seq: count; + ## Authentication data. + data: string; +}; + +## Values extracted from an IPv6 ESP extension header. +## +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain +type ip6_esp: record { + ## Security Parameters Index. + spi: count; + ## Sequence number. + seq: count; +}; + +## Values extracted from an IPv6 Mobility Binding Refresh Request message. +## +## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg +type ip6_mobility_brr: record { + ## Reserved. + rsv: count; + ## Mobility Options. + options: vector of ip6_option; +}; + +## Values extracted from an IPv6 Mobility Home Test Init message. +## +## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg +type ip6_mobility_hoti: record { + ## Reserved. + rsv: count; + ## Home Init Cookie. + cookie: count; + ## Mobility Options. + options: vector of ip6_option; +}; + +## Values extracted from an IPv6 Mobility Care-of Test Init message. +## +## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg +type ip6_mobility_coti: record { + ## Reserved. + rsv: count; + ## Care-of Init Cookie. + cookie: count; + ## Mobility Options. + options: vector of ip6_option; +}; + +## Values extracted from an IPv6 Mobility Home Test message. +## +## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg +type ip6_mobility_hot: record { + ## Home Nonce Index. + nonce_idx: count; + ## Home Init Cookie. + cookie: count; + ## Home Keygen Token. + token: count; + ## Mobility Options. + options: vector of ip6_option; +}; + +## Values extracted from an IPv6 Mobility Care-of Test message. +## +## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg +type ip6_mobility_cot: record { + ## Care-of Nonce Index. + nonce_idx: count; + ## Care-of Init Cookie. + cookie: count; + ## Care-of Keygen Token. + token: count; + ## Mobility Options. + options: vector of ip6_option; +}; + +## Values extracted from an IPv6 Mobility Binding Update message. +## +## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg +type ip6_mobility_bu: record { + ## Sequence number. + seq: count; + ## Acknowledge bit. + a: bool; + ## Home Registration bit. + h: bool; + ## Link-Local Address Compatibility bit. + l: bool; + ## Key Management Mobility Capability bit. + k: bool; + ## Lifetime. + life: count; + ## Mobility Options. + options: vector of ip6_option; +}; + +## Values extracted from an IPv6 Mobility Binding Acknowledgement message. +## +## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg +type ip6_mobility_back: record { + ## Status. + status: count; + ## Key Management Mobility Capability. + k: bool; + ## Sequence number. + seq: count; + ## Lifetime. + life: count; + ## Mobility Options. + options: vector of ip6_option; +}; + +## Values extracted from an IPv6 Mobility Binding Error message. +## +## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain ip6_mobility_msg +type ip6_mobility_be: record { + ## Status. + status: count; + ## Home Address. + hoa: addr; + ## Mobility Options. + options: vector of ip6_option; +}; + +## Values extracted from an IPv6 Mobility header's message data. +## +## .. bro:see:: ip6_mobility_hdr ip6_hdr ip6_hdr_chain +type ip6_mobility_msg: record { + ## The type of message from the header's MH Type field. + id: count; + ## Binding Refresh Request. + brr: ip6_mobility_brr &optional; + ## Home Test Init. + hoti: ip6_mobility_hoti &optional; + ## Care-of Test Init. + coti: ip6_mobility_coti &optional; + ## Home Test. + hot: ip6_mobility_hot &optional; + ## Care-of Test. + cot: ip6_mobility_cot &optional; + ## Binding Update. + bu: ip6_mobility_bu &optional; + ## Binding Acknowledgement. + back: ip6_mobility_back &optional; + ## Binding Error. + be: ip6_mobility_be &optional; +}; + +## Values extracted from an IPv6 Mobility header. +## +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr ip6_hdr_chain +type ip6_mobility_hdr: record { + ## Protocol number of the next header (RFC 1700 et seq., IANA assigned + ## number), e.g. :bro:id:`IPPROTO_ICMP`. + nxt: count; + ## Length of header in 8-octet units, excluding first unit. + len: count; + ## Mobility header type used to identify header's the message. + mh_type: count; + ## Reserved field. + rsv: count; + ## Mobility header checksum. + chksum: count; + ## Mobility header message + msg: ip6_mobility_msg; +}; + +## A general container for a more specific IPv6 extension header. +## +## .. bro:see:: pkt_hdr ip4_hdr ip6_hopopts ip6_dstopts ip6_routing ip6_fragment +## ip6_ah ip6_esp +type ip6_ext_hdr: record { + ## The RFC 1700 et seq. IANA assigned number identifying the type of + ## the extension header. + id: count; + ## Hop-by-hop option extension header. + hopopts: ip6_hopopts &optional; + ## Destination option extension header. + dstopts: ip6_dstopts &optional; + ## Routing extension header. + routing: ip6_routing &optional; + ## Fragment header. + fragment: ip6_fragment &optional; + ## Authentication extension header. + ah: ip6_ah &optional; + ## Encapsulating security payload header. + esp: ip6_esp &optional; + ## Mobility header. + mobility: ip6_mobility_hdr &optional; +}; + +## Values extracted from an IPv6 header. +## +## .. bro:see:: pkt_hdr ip4_hdr ip6_hdr_chain ip6_hopopts ip6_dstopts +## ip6_routing ip6_fragment ip6_ah ip6_esp +type ip6_hdr: record { + class: count; ##< Traffic class. + flow: count; ##< Flow label. + len: count; ##< Payload length. + nxt: count; ##< Protocol number of the next header + ##< (RFC 1700 et seq., IANA assigned number) + ##< e.g. :bro:id:`IPPROTO_ICMP`. + hlim: count; ##< Hop limit. + src: addr; ##< Source address. + dst: addr; ##< Destination address. + exts: vector of ip6_ext_hdr; ##< Extension header chain. +}; + +## Values extracted from an IPv4 header. +## +## .. bro:see:: pkt_hdr ip6_hdr discarder_check_ip +type ip4_hdr: record { + hl: count; ##< Header length in bytes. + tos: count; ##< Type of service. + len: count; ##< Total length. + id: count; ##< Identification. + ttl: count; ##< Time to live. + p: count; ##< Protocol. + src: addr; ##< Source address. + dst: addr; ##< Destination address. }; # TCP flags. -const TH_FIN = 1; -const TH_SYN = 2; -const TH_RST = 4; -const TH_PUSH = 8; -const TH_ACK = 16; -const TH_URG = 32; -const TH_FLAGS = 63; # (TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG) +# +# todo::these should go into an enum to make them autodoc'able +const TH_FIN = 1; ##< FIN. +const TH_SYN = 2; ##< SYN. +const TH_RST = 4; ##< RST. +const TH_PUSH = 8; ##< PUSH. +const TH_ACK = 16; ##< ACK. +const TH_URG = 32; ##< URG. +const TH_FLAGS = 63; ##< Mask combining all flags. +## Values extracted from a TCP header. +## +## .. bro:see:: pkt_hdr discarder_check_tcp type tcp_hdr: record { - sport: port; # source port - dport: port; # destination port - seq: count; # sequence number - ack: count; # acknowledgement number - hl: count; # header length (in bytes) - dl: count; # data length (xxx: not in original tcphdr!) - flags: count; # flags - win: count; # window + sport: port; ##< source port. + dport: port; ##< destination port + seq: count; ##< sequence number + ack: count; ##< acknowledgement number + hl: count; ##< header length (in bytes) + dl: count; ##< data length (xxx: not in original tcphdr!) + flags: count; ##< flags + win: count; ##< window }; +## Values extracted from a UDP header. +## +## .. bro:see:: pkt_hdr discarder_check_udp type udp_hdr: record { - sport: port; # source port - dport: port; # destination port - ulen: count; # udp length + sport: port; ##< source port + dport: port; ##< destination port + ulen: count; ##< udp length }; +## Values extracted from an ICMP header. +## +## .. bro:see:: pkt_hdr discarder_check_icmp +type icmp_hdr: record { + icmp_type: count; ##< type of message +}; -# Holds an ip_hdr and one of tcp_hdr, udp_hdr, or icmp_hdr. +## A packet header, consisting of an IP header and transport-layer header. +## +## .. bro:see:: new_packet type pkt_hdr: record { - ip: ip_hdr; - tcp: tcp_hdr &optional; - udp: udp_hdr &optional; - icmp: icmp_hdr &optional; + ip: ip4_hdr &optional; ##< The IPv4 header if an IPv4 packet. + ip6: ip6_hdr &optional; ##< The IPv6 header if an IPv6 packet. + tcp: tcp_hdr &optional; ##< The TCP header if a TCP packet. + udp: udp_hdr &optional; ##< The UDP header if a UDP packet. + icmp: icmp_hdr &optional; ##< The ICMP header if an ICMP packet. }; - -# If you add elements here, then for a given BPF filter as index, when -# a packet matching that filter is captured, the corresponding event handler -# will be invoked. +## Definition of "secondary filters". A secondary filter is a BPF filter given as +## index in this table. For each such filter, the corresponding event is raised for +## all matching packets. global secondary_filters: table[string] of event(filter: string, pkt: pkt_hdr) &redef; -global discarder_maxlen = 128 &redef; # maximum amount of data passed to fnc +## Maximum length of payload passed to discarder functions. +## +## .. :bro:see:: discarder_check_tcp discarder_check_udp discarder_check_icmp +## discarder_check_ip +global discarder_maxlen = 128 &redef; -global discarder_check_ip: function(i: ip_hdr): bool; -global discarder_check_tcp: function(i: ip_hdr, t: tcp_hdr, d: string): bool; -global discarder_check_udp: function(i: ip_hdr, u: udp_hdr, d: string): bool; -global discarder_check_icmp: function(i: ip_hdr, ih: icmp_hdr): bool; -# End of definition of access to packet headers, discarders. +## Function for skipping packets based on their IP header. If defined, this +## function will be called for all IP packets before Bro performs any further +## analysis. If the function signals to discard a packet, no further processing +## will be performed on it. +## +## p: The IP header of the considered packet. +## +## Returns: True if the packet should not be analyzed any further. +## +## .. :bro:see:: discarder_check_tcp discarder_check_udp discarder_check_icmp +## discarder_maxlen +## +## .. note:: This is very low-level functionality and potentially expensive. +## Avoid using it. +global discarder_check_ip: function(p: pkt_hdr): bool; +## Function for skipping packets based on their TCP header. If defined, this +## function will be called for all TCP packets before Bro performs any further +## analysis. If the function signals to discard a packet, no further processing +## will be performed on it. +## +## p: The IP and TCP headers of the considered packet. +## +## d: Up to :bro:see:`discarder_maxlen` bytes of the TCP payload. +## +## Returns: True if the packet should not be analyzed any further. +## +## .. :bro:see:: discarder_check_ip discarder_check_udp discarder_check_icmp +## discarder_maxlen +## +## .. note:: This is very low-level functionality and potentially expensive. +## Avoid using it. +global discarder_check_tcp: function(p: pkt_hdr, d: string): bool; + +## Function for skipping packets based on their UDP header. If defined, this +## function will be called for all UDP packets before Bro performs any further +## analysis. If the function signals to discard a packet, no further processing +## will be performed on it. +## +## p: The IP and UDP headers of the considered packet. +## +## d: Up to :bro:see:`discarder_maxlen` bytes of the UDP payload. +## +## Returns: True if the packet should not be analyzed any further. +## +## .. :bro:see:: discarder_check_ip discarder_check_tcp discarder_check_icmp +## discarder_maxlen +## +## .. note:: This is very low-level functionality and potentially expensive. +## Avoid using it. +global discarder_check_udp: function(p: pkt_hdr, d: string): bool; + +## Function for skipping packets based on their ICMP header. If defined, this +## function will be called for all ICMP packets before Bro performs any further +## analysis. If the function signals to discard a packet, no further processing +## will be performed on it. +## +## p: The IP and ICMP headers of the considered packet. +## +## Returns: True if the packet should not be analyzed any further. +## +## .. :bro:see:: discarder_check_ip discarder_check_tcp discarder_check_udp +## discarder_maxlen +## +## .. note:: This is very low-level functionality and potentially expensive. +## Avoid using it. +global discarder_check_icmp: function(p: pkt_hdr): bool; + +## Bro's watchdog interval. const watchdog_interval = 10 sec &redef; -# The maximum number of timers to expire after processing each new -# packet. The value trades off spreading out the timer expiration load -# with possibly having to hold state longer. A value of 0 means -# "process all expired timers with each new packet". +## The maximum number of timers to expire after processing each new +## packet. The value trades off spreading out the timer expiration load +## with possibly having to hold state longer. A value of 0 means +## "process all expired timers with each new packet". const max_timer_expires = 300 &redef; -# With a similar trade-off, this gives the number of remote events -# to process in a batch before interleaving other activity. +## With a similar trade-off, this gives the number of remote events +## to process in a batch before interleaving other activity. const max_remote_events_processed = 10 &redef; # These need to match the definitions in Login.h. -const LOGIN_STATE_AUTHENTICATE = 0; # trying to authenticate -const LOGIN_STATE_LOGGED_IN = 1; # successful authentication -const LOGIN_STATE_SKIP = 2; # skip any further processing -const LOGIN_STATE_CONFUSED = 3; # we're confused +# +# .. bro:see:: get_login_state +# +# todo::use enum to make them autodoc'able +const LOGIN_STATE_AUTHENTICATE = 0; # Trying to authenticate. +const LOGIN_STATE_LOGGED_IN = 1; # Successful authentication. +const LOGIN_STATE_SKIP = 2; # Skip any further processing. +const LOGIN_STATE_CONFUSED = 3; # We're confused. # It would be nice to replace these function definitions with some # form of parameterized types. + +## Returns minimum of two ``double`` values. +## +## a: First value. +## b: Second value. +## +## Returns: The minimum of *a* and *b*. function min_double(a: double, b: double): double { return a < b ? a : b; } + +## Returns maximum of two ``double`` values. +## +## a: First value. +## b: Second value. +## +## Returns: The maximum of *a* and *b*. function max_double(a: double, b: double): double { return a > b ? a : b; } + +## Returns minimum of two ``interval`` values. +## +## a: First value. +## b: Second value. +## +## Returns: The minimum of *a* and *b*. function min_interval(a: interval, b: interval): interval { return a < b ? a : b; } + +## Returns maximum of two ``interval`` values. +## +## a: First value. +## b: Second value. +## +## Returns: The maximum of *a* and *b*. function max_interval(a: interval, b: interval): interval { return a > b ? a : b; } + +## Returns minimum of two ``count`` values. +## +## a: First value. +## b: Second value. +## +## Returns: The minimum of *a* and *b*. function min_count(a: count, b: count): count { return a < b ? a : b; } + +## Returns maximum of two ``count`` values. +## +## a: First value. +## b: Second value. +## +## Returns: The maximum of *a* and *b*. function max_count(a: count, b: count): count { return a > b ? a : b; } +## TODO. global skip_authentication: set[string] &redef; + +## TODO. global direct_login_prompts: set[string] &redef; + +## TODO. global login_prompts: set[string] &redef; + +## TODO. global login_non_failure_msgs: set[string] &redef; + +## TODO. global login_failure_msgs: set[string] &redef; + +## TODO. global login_success_msgs: set[string] &redef; + +## TODO. global login_timeouts: set[string] &redef; +## A MIME header key/value pair. +## +## .. bro:see:: mime_header_list http_all_headers mime_all_headers mime_one_header type mime_header_rec: record { - name: string; - value: string; + name: string; ##< The header name. + value: string; ##< The header value. }; + +## A list of MIME headers. +## +## .. bro:see:: mime_header_rec http_all_headers mime_all_headers type mime_header_list: table[count] of mime_header_rec; + +## The length of MIME data segments delivered to handlers of +## :bro:see:`mime_segment_data`. +## +## .. bro:see:: mime_segment_data mime_segment_overlap_length global mime_segment_length = 1024 &redef; + +## The number of bytes of overlap between successive segments passed to +## :bro:see:`mime_segment_data`. global mime_segment_overlap_length = 0 &redef; +## An RPC portmapper mapping. +## +## .. bro:see:: pm_mappings type pm_mapping: record { - program: count; - version: count; - p: port; + program: count; ##< The RPC program. + version: count; ##< The program version. + p: port; ##< The port. }; +## Table of RPC portmapper mappings. +## +## .. bro:see:: pm_request_dump type pm_mappings: table[count] of pm_mapping; +## An RPC portmapper request. +## +## .. bro:see:: pm_attempt_getport pm_request_getport type pm_port_request: record { - program: count; - version: count; - is_tcp: bool; + program: count; ##< The RPC program. + version: count; ##< The program version. + is_tcp: bool; ##< True if using TCP. }; +## An RPC portmapper *callit* request. +## +## .. bro:see:: pm_attempt_callit pm_request_callit type pm_callit_request: record { - program: count; - version: count; - proc: count; - arg_size: count; + program: count; ##< The RPC program. + version: count; ##< The program version. + proc: count; ##< The procedure being called. + arg_size: count; ##< The size of the argument. }; # See const.bif @@ -709,6 +1571,10 @@ type pm_callit_request: record { # const RPC_AUTH_ERROR = 7; # const RPC_UNKNOWN_ERROR = 8; +## Mapping of numerical RPC status codes to readable messages. +## +## .. bro:see:: pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset rpc_dialogue rpc_reply const RPC_status = { [RPC_SUCCESS] = "ok", [RPC_PROG_UNAVAIL] = "prog unavail", @@ -724,242 +1590,307 @@ const RPC_status = { module NFS3; export { - # Should the read and write events return the file data that has been - # read/written? + ## If true, :bro:see:`nfs_proc_read` and :bro:see:`nfs_proc_write` events return + ## the file data that has been read/written. + ## + ## .. .. bro:see:: return_data_max return_data_first_only const return_data = F &redef; - # If nfs_return_data is true, how much data should be returned at most. + ## If bro:id:`NFS3::return_data` is true, how much data should be returned at + ## most. const return_data_max = 512 &redef; - # If nfs_return_data is true, whether to *only* return data if the read or write - # offset is 0, i.e., only return data for the beginning of the file. + ## If bro:id:`NFS3::return_data` is true, whether to *only* return data if the read + ## or write offset is 0, i.e., only return data for the beginning of the file. const return_data_first_only = T &redef; - # This record summarizes the general results and status of NFSv3 request/reply - # pairs. It's part of every NFSv3 event. + ## Record summarizing the general results and status of NFSv3 request/reply pairs. + ## + ## Note that when *rpc_stats* or *nfs_stats* indicates not successful, the reply + ## record passed to the correpsonding event will be empty and contain uninitialized + ## fields, so don't use it. Also note that time and duration values might not be + ## fully accurate. For TCP, we record times when the corresponding chunk of data + ## is delivered to the analyzer. Depending on the reassembler, this might be well + ## after the first packet of the request was received. + ## + ## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup + ## nfs_proc_mkdir nfs_proc_not_implemented nfs_proc_null + ## nfs_proc_read nfs_proc_readdir nfs_proc_readlink nfs_proc_remove + ## nfs_proc_rmdir nfs_proc_write nfs_reply_status type info_t: record { - rpc_stat: rpc_status; # If this indicates not successful, the reply record in the - # events will be empty and contain uninitialized fields, so - # don't use it. + ## The RPC status. + rpc_stat: rpc_status; + ## The NFS status. nfs_stat: status_t; - - # The start time, duration, and length in bytes of the request (call). Note that - # the start and end time might not be accurate. For TCP, we record the - # time when a chunk of data is delivered to the analyzer. Depending on the - # Reassembler, this might be well after the first packet of the request - # was received. + ## The start time of the request. req_start: time; + ## The duration of the request. req_dur: interval; + ## The length in bytes of the request. req_len: count; - - # Same for the reply. + ## The start time of the reply. rep_start: time; + ## The duration of the reply. rep_dur: interval; + ## The length in bytes of the reply. rep_len: count; }; - # NFSv3 types. Type names are based on RFC 1813. + ## NFS file attributes. Field names are based on RFC 1813. + ## + ## .. bro:see:: nfs_proc_getattr type fattr_t: record { - ftype: file_type_t; - mode: count; - nlink: count; - uid: count; - gid: count; - size: count; - used: count; - rdev1: count; - rdev2: count; - fsid: count; - fileid: count; - atime: time; - mtime: time; - ctime: time; + ftype: file_type_t; ##< File type. + mode: count; ##< Mode + nlink: count; ##< Number of links. + uid: count; ##< User ID. + gid: count; ##< Group ID. + size: count; ##< Size. + used: count; ##< TODO. + rdev1: count; ##< TODO. + rdev2: count; ##< TODO. + fsid: count; ##< TODO. + fileid: count; ##< TODO. + atime: time; ##< Time of last access. + mtime: time; ##< Time of last modification. + ctime: time; ##< Time of creation. }; + ## NFS *readdir* arguments. + ## + ## .. bro:see:: nfs_proc_readdir type diropargs_t : record { - dirfh: string; # the file handle of the directory - fname: string; # the name of the file we are interested in + dirfh: string; ##< The file handle of the directory. + fname: string; ##< The name of the file we are interested in. }; - # Note, we don't need a "post_op_attr" type. We use an "fattr_t &optional" - # instead. - + ## NFS lookup reply. If the lookup failed, *dir_attr* may be set. If the lookup + ## succeeded, *fh* is always set and *obj_attr* and *dir_attr* may be set. + ## + ## .. bro:see:: nfs_proc_lookup type lookup_reply_t: record { - # If the lookup failed, dir_attr may be set. - # If the lookup succeeded, fh is always set and obj_attr and dir_attr may be set. - fh: string &optional; # file handle of object looked up - obj_attr: fattr_t &optional; # optional attributes associated w/ file - dir_attr: fattr_t &optional; # optional attributes associated w/ dir. + fh: string &optional; ##< File handle of object looked up. + obj_attr: fattr_t &optional; ##< Optional attributes associated w/ file + dir_attr: fattr_t &optional; ##< Optional attributes associated w/ dir. }; + ## NFS *read* arguments. + ## + ## .. bro:see:: nfs_proc_read type readargs_t: record { - fh: string; # file handle to read from - offset: count; # offset in file - size: count; # number of bytes to read + fh: string; ##< File handle to read from. + offset: count; ##< Offset in file. + size: count; ##< Number of bytes to read. }; + ## NFS *read* reply. If the lookup fails, *attr* may be set. If the lookup succeeds, + ## *attr* may be set and all other fields are set. type read_reply_t: record { - # If the lookup fails, attr may be set. If the lookup succeeds, attr may be set - # and all other fields are set. - attr: fattr_t &optional; # attributes - size: count &optional; # number of bytes read - eof: bool &optional; # did the read end at EOF - data: string &optional; # the actual data; not yet implemented. + attr: fattr_t &optional; ##< Attributes. + size: count &optional; ##< Number of bytes read. + eof: bool &optional; ##< Sid the read end at EOF. + data: string &optional; ##< The actual data; not yet implemented. }; + ## NFS *readline* reply. If the request fails, *attr* may be set. If the request + ## succeeds, *attr* may be set and all other fields are set. + ## + ## .. bro:see:: nfs_proc_readlink type readlink_reply_t: record { - # If the request fails, attr may be set. If the request succeeds, attr may be - # set and all other fields are set. - attr: fattr_t &optional; # attributes - nfspath: string &optional; # the contents of the symlink; in general a pathname as text + attr: fattr_t &optional; ##< Attributes. + nfspath: string &optional; ##< Contents of the symlink; in general a pathname as text. }; + ## NFS *write* arguments. + ## + ## .. bro:see:: nfs_proc_write type writeargs_t: record { - fh: string; # file handle to write to - offset: count; # offset in file - size: count; # number of bytes to write - stable: stable_how_t; # how and when data is commited - data: string &optional; # the actual data; not implemented yet + fh: string; ##< File handle to write to. + offset: count; ##< Offset in file. + size: count; ##< Number of bytes to write. + stable: stable_how_t; ##< How and when data is commited. + data: string &optional; ##< The actual data; not implemented yet. }; + ## NFS *wcc* attributes. + ## + ## .. bro:see:: NFS3::write_reply_t type wcc_attr_t: record { - size: count; - atime: time; - mtime: time; + size: count; ##< The dize. + atime: time; ##< Access time. + mtime: time; ##< Modification time. }; + ## NFS *write* reply. If the request fails, *pre|post* attr may be set. If the + ## request succeeds, *pre|post* attr may be set and all other fields are set. + ## + ## .. bro:see:: nfs_proc_write type write_reply_t: record { - # If the request fails, pre|post attr may be set. If the request succeeds, - # pre|post attr may be set and all other fields are set. - preattr: wcc_attr_t &optional; # pre operation attributes - postattr: fattr_t &optional; # post operation attributes - size: count &optional; - commited: stable_how_t &optional; - verf: count &optional; # write verifier cookue + preattr: wcc_attr_t &optional; ##< Pre operation attributes. + postattr: fattr_t &optional; ##< Post operation attributes. + size: count &optional; ##< Size. + commited: stable_how_t &optional; ##< TODO. + verf: count &optional; ##< Write verifier cookie. }; - # reply for create, mkdir, symlink + ## NFS reply for *create*, *mkdir*, and *symlink*. If the proc + ## failed, *dir_\*_attr* may be set. If the proc succeeded, *fh* and the *attr*'s + ## may be set. Note: no guarantee that *fh* is set after success. + ## + ## .. bro:see:: nfs_proc_create nfs_proc_mkdir type newobj_reply_t: record { - # If the proc failed, dir_*_attr may be set. If the proc succeeded, fh and - # the attr's may be set. Note: no guarantee that fh is set after - # success. - fh: string &optional; # file handle of object created - obj_attr: fattr_t &optional; # optional attributes associated w/ new object - dir_pre_attr: wcc_attr_t &optional; # optional attributes associated w/ dir - dir_post_attr: fattr_t &optional; # optional attributes associated w/ dir + fh: string &optional; ##< File handle of object created. + obj_attr: fattr_t &optional; ##< Optional attributes associated w/ new object. + dir_pre_attr: wcc_attr_t &optional; ##< Optional attributes associated w/ dir. + dir_post_attr: fattr_t &optional; ##< Optional attributes associated w/ dir. }; - # reply for remove, rmdir - # Corresponds to "wcc_data" in the spec. + ## NFS reply for *remove*, *rmdir*. Corresponds to *wcc_data* in the spec. + ## + ## .. bro:see:: nfs_proc_remove nfs_proc_rmdir type delobj_reply_t: record { - dir_pre_attr: wcc_attr_t &optional; # optional attributes associated w/ dir - dir_post_attr: fattr_t &optional; # optional attributes associated w/ dir + dir_pre_attr: wcc_attr_t &optional; ##< Optional attributes associated w/ dir. + dir_post_attr: fattr_t &optional; ##< Optional attributes associated w/ dir. }; - # This record is used for both readdir and readdirplus. + ## NFS *readdir* arguments. Used for both *readdir* and *readdirplus*. + ## + ## .. bro:see:: nfs_proc_readdir type readdirargs_t: record { - isplus: bool; # is this a readdirplus request? - dirfh: string; # the directory filehandle - cookie: count; # cookie / pos in dir; 0 for first call - cookieverf: count; # the cookie verifier - dircount: count; # "count" field for readdir; maxcount otherwise (in bytes) - maxcount: count &optional; # only used for readdirplus. in bytes + isplus: bool; ##< Is this a readdirplus request? + dirfh: string; ##< The directory filehandle. + cookie: count; ##< Cookie / pos in dir; 0 for first call. + cookieverf: count; ##< The cookie verifier. + dircount: count; ##< "count" field for readdir; maxcount otherwise (in bytes). + maxcount: count &optional; ##< Only used for readdirplus. in bytes. }; + ## NFS *direntry*. *fh* and *attr* are used for *readdirplus*. However, even + ## for *readdirplus* they may not be filled out. + ## + ## .. bro:see:: NFS3::direntry_vec_t NFS3::readdir_reply_t type direntry_t: record { - # fh and attr are used for readdirplus. However, even for readdirplus they may - # not be filled out. - fileid: count; # e.g., inode number - fname: string; # filename - cookie: count; - attr: fattr_t &optional; # readdirplus: the FH attributes for the entry - fh: string &optional; # readdirplus: the FH for the entry + fileid: count; ##< E.g., inode number. + fname: string; ##< Filename. + cookie: count; ##< Cookie value. + attr: fattr_t &optional; ##< *readdirplus*: the *fh* attributes for the entry. + fh: string &optional; ##< *readdirplus*: the *fh* for the entry }; + ## Vector of NFS *direntry*. + ## + ## .. bro:see:: NFS3::readdir_reply_t type direntry_vec_t: vector of direntry_t; - # Used for readdir and readdirplus. + ## NFS *readdir* reply. Used for *readdir* and *readdirplus*. If an is + ## returned, *dir_attr* might be set. On success, *dir_attr* may be set, all others + ## must be set. type readdir_reply_t: record { - # If error: dir_attr might be set. If success: dir_attr may be set, all others - # must be set. - isplus: bool; # is the reply for a readdirplus request - dir_attr: fattr_t &optional; - cookieverf: count &optional; - entries: direntry_vec_t &optional; - eof: bool; # if true, no more entries in dir. + isplus: bool; ##< True if the reply for a *readdirplus* request. + dir_attr: fattr_t &optional; ##< Directory attributes. + cookieverf: count &optional; ##< TODO. + entries: direntry_vec_t &optional; ##< Returned directory entries. + eof: bool; ##< If true, no more entries in directory. }; + ## NFS *fsstat*. type fsstat_t: record { - attrs: fattr_t &optional; - tbytes: double; - fbytes: double; - abytes: double; - tfiles: double; - ffiles: double; - afiles: double; - invarsec: interval; + attrs: fattr_t &optional; ##< Attributes. + tbytes: double; ##< TODO. + fbytes: double; ##< TODO. + abytes: double; ##< TODO. + tfiles: double; ##< TODO. + ffiles: double; ##< TODO. + afiles: double; ##< TODO. + invarsec: interval; ##< TODO. }; } # end export module GLOBAL; +## An NTP message. +## +## .. bro:see:: ntp_message type ntp_msg: record { - id: count; - code: count; - stratum: count; - poll: count; - precision: int; - distance: interval; - dispersion: interval; - ref_t: time; - originate_t: time; - receive_t: time; - xmit_t: time; + id: count; ##< Message ID. + code: count; ##< Message code. + stratum: count; ##< Stratum. + poll: count; ##< Poll. + precision: int; ##< Precision. + distance: interval; ##< Distance. + dispersion: interval; ##< Dispersion. + ref_t: time; ##< Reference time. + originate_t: time; ##< Originating time. + receive_t: time; ##< Receive time. + xmit_t: time; ##< Send time. }; -# Maps Samba command numbers to descriptive names. +## Maps SMB command numbers to descriptive names. global samba_cmds: table[count] of string &redef &default = function(c: count): string { return fmt("samba-unknown-%d", c); }; +## An SMB command header. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction +## smb_com_transaction2 smb_com_tree_connect_andx smb_com_tree_disconnect +## smb_com_write_andx smb_error smb_get_dfs_referral smb_message type smb_hdr : record { - command: count; - status: count; - flags: count; - flags2: count; - tid: count; - pid: count; - uid: count; - mid: count; + command: count; ##< The command number (see :bro:see:`samba_cmds` ). + status: count; ##< The status code. + flags: count; ##< Flag set 1. + flags2: count; ##< Flag set 2. + tid: count; ##< TODO. + pid: count; ##< Process ID. + uid: count; ##< User ID. + mid: count; ##< TODO. }; +## An SMB transaction. +## +## .. bro:see:: smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 type smb_trans : record { - word_count: count; - total_param_count: count; - total_data_count: count; - max_param_count: count; - max_data_count: count; - max_setup_count: count; + word_count: count; ##< TODO. + total_param_count: count; ##< TODO. + total_data_count: count; ##< TODO. + max_param_count: count; ##< TODO. + max_data_count: count; ##< TODO. + max_setup_count: count; ##< TODO. # flags: count; # timeout: count; - param_count: count; - param_offset: count; - data_count: count; - data_offset: count; - setup_count: count; - setup0: count; - setup1: count; - setup2: count; - setup3: count; - byte_count: count; - parameters: string; + param_count: count; ##< TODO. + param_offset: count; ##< TODO. + data_count: count; ##< TODO. + data_offset: count; ##< TODO. + setup_count: count; ##< TODO. + setup0: count; ##< TODO. + setup1: count; ##< TODO. + setup2: count; ##< TODO. + setup3: count; ##< TODO. + byte_count: count; ##< TODO. + parameters: string; ##< TODO. }; + +## SMB transaction data. +## +## .. bro:see:: smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 +## +## .. todo:: Should this really be a record type? type smb_trans_data : record { - data : string; + data : string; ##< The transaction's data. }; +## Deprecated. +## +## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere +## else. type smb_tree_connect : record { flags: count; password: string; @@ -967,170 +1898,257 @@ type smb_tree_connect : record { service: string; }; +## Deprecated. +## +## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere +## else. type smb_negotiate : table[count] of string; -# A list of router addresses offered by the server. +## A list of router addresses offered by a DHCP server. +## +## .. bro:see:: dhcp_ack dhcp_offer type dhcp_router_list: table[count] of addr; +## A DHCP message. +## +## .. bro:see:: dhcp_ack dhcp_decline dhcp_discover dhcp_inform dhcp_nak +## dhcp_offer dhcp_release dhcp_request type dhcp_msg: record { - op: count; # message OP code. 1 = BOOTREQUEST, 2 = BOOTREPLY - m_type: count; # the type of DHCP message - xid: count; # transaction ID of a DHCP session - h_addr: string; # hardware address of the client - ciaddr: addr; # original IP address of the client - yiaddr: addr; # IP address assigned to the client + op: count; ##< Message OP code. 1 = BOOTREQUEST, 2 = BOOTREPLY + m_type: count; ##< The type of DHCP message. + xid: count; ##< Transaction ID of a DHCP session. + h_addr: string; ##< Hardware address of the client. + ciaddr: addr; ##< Original IP address of the client. + yiaddr: addr; ##< IP address assigned to the client. }; +## A DNS message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_message +## dns_query_reply dns_rejected dns_request type dns_msg: record { - id: count; + id: count; ##< Transaction ID. - opcode: count; - rcode: count; + opcode: count; ##< Operation code. + rcode: count; ##< Return code. - QR: bool; - AA: bool; - TC: bool; - RD: bool; - RA: bool; - Z: count; + QR: bool; ##< Query response flag. + AA: bool; ##< Authoritative answer flag. + TC: bool; ##< Truncated packet flag. + RD: bool; ##< Recursion desired flag. + RA: bool; ##< Recursion available flag. + Z: count; ##< TODO. - num_queries: count; - num_answers: count; - num_auth: count; - num_addl: count; + num_queries: count; ##< Number of query records. + num_answers: count; ##< Number of answer records. + num_auth: count; ##< Number of authoritative records. + num_addl: count; ##< Number of additional records. }; +## A DNS SOA record. +## +## .. bro:see:: dns_SOA_reply type dns_soa: record { - mname: string; # primary source of data for zone - rname: string; # mailbox for responsible person - serial: count; # version number of zone - refresh: interval; # seconds before refreshing - retry: interval; # how long before retrying failed refresh - expire: interval; # when zone no longer authoritative - minimum: interval; # minimum TTL to use when exporting + mname: string; ##< Primary source of data for zone. + rname: string; ##< Mailbox for responsible person. + serial: count; ##< Version number of zone. + refresh: interval; ##< Seconds before refreshing. + retry: interval; ##< How long before retrying failed refresh. + expire: interval; ##< When zone no longer authoritative. + minimum: interval; ##< Minimum TTL to use when exporting. }; +## An additional DNS EDNS record. +## +## .. bro:see:: dns_EDNS_addl type dns_edns_additional: record { - query: string; - qtype: count; - t: count; - payload_size: count; - extended_rcode: count; - version: count; - z_field: count; - TTL: interval; - is_query: count; + query: string; ##< Query. + qtype: count; ##< Query type. + t: count; ##< TODO. + payload_size: count; ##< TODO. + extended_rcode: count; ##< Extended return code. + version: count; ##< Version. + z_field: count; ##< TODO. + TTL: interval; ##< Time-to-live. + is_query: count; ##< TODO. }; +## An additional DNS TSIG record. +## +## bro:see:: dns_TSIG_addl type dns_tsig_additional: record { - query: string; - qtype: count; - alg_name: string; - sig: string; - time_signed: time; - fudge: time; - orig_id: count; - rr_error: count; - is_query: count; + query: string; ##< Query. + qtype: count; ##< Query type. + alg_name: string; ##< Algorithm name. + sig: string; ##< Signature. + time_signed: time; ##< Time when signed. + fudge: time; ##< TODO. + orig_id: count; ##< TODO. + rr_error: count; ##< TODO. + is_query: count; ##< TODO. }; -# Different values for "answer_type" in the following. DNS_QUERY -# shouldn't occur, it's just for completeness. -const DNS_QUERY = 0; -const DNS_ANS = 1; -const DNS_AUTH = 2; -const DNS_ADDL = 3; +# DNS answer types. +# +# .. .. bro:see:: dns_answerr +# +# todo::use enum to make them autodoc'able +const DNS_QUERY = 0; ##< A query. This shouldn't occur, just for completeness. +const DNS_ANS = 1; ##< An answer record. +const DNS_AUTH = 2; ##< An authorative record. +const DNS_ADDL = 3; ##< An additional record. +## The general part of a DNS reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_HINFO_reply +## dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply +## dns_TXT_reply dns_WKS_reply type dns_answer: record { + ## Answer type. One of :bro:see:`DNS_QUERY`, :bro:see:`DNS_ANS`, + ## :bro:see:`DNS_AUTH` and :bro:see:`DNS_ADDL`. answer_type: count; - query: string; - qtype: count; - qclass: count; - TTL: interval; + query: string; ##< Query. + qtype: count; ##< Query type. + qclass: count; ##< Query class. + TTL: interval; ##< Time-to-live. }; -# For servers in these sets, omit processing the AUTH or ADDL records -# they include in their replies. +## For DNS servers in these sets, omit processing the AUTH records they include in +## their replies. +## +## .. bro:see:: dns_skip_all_auth dns_skip_addl global dns_skip_auth: set[addr] &redef; + +## For DNS servers in these sets, omit processing the ADDL records they include in +## their replies. +## +## .. bro:see:: dns_skip_all_addl dns_skip_auth global dns_skip_addl: set[addr] &redef; -# If the following are true, then all AUTH or ADDL records are skipped. +## If true, all DNS AUTH records are skipped. +## +## .. bro:see:: dns_skip_all_addl dns_skip_auth global dns_skip_all_auth = T &redef; + +## If true, all DNS ADDL records are skipped. +## +## .. bro:see:: dns_skip_all_auth dns_skip_addl global dns_skip_all_addl = T &redef; -# If a DNS request includes more than this many queries, assume it's -# non-DNS traffic and do not process it. Set to 0 to turn off this -# functionality. +## If a DNS request includes more than this many queries, assume it's non-DNS +## traffic and do not process it. Set to 0 to turn off this functionality. global dns_max_queries = 5; -# The maxiumum size in bytes for an SSL cipherspec. If we see a packet that -# has bigger cipherspecs, we won't do a comparisons of cipherspecs. -const ssl_max_cipherspec_size = 68 &redef; - -type X509_extensions: table[count] of string; - +## An X509 certificate. +## +## .. bro:see:: x509_certificate type X509: record { - version: count; - serial: string; - subject: string; - issuer: string; - not_valid_before: time; - not_valid_after: time; + version: count; ##< Version number. + serial: string; ##< Serial number. + subject: string; ##< Subject. + issuer: string; ##< Issuer. + not_valid_before: time; ##< Timestamp before when certificate is not valid. + not_valid_after: time; ##< Timestamp after when certificate is not valid. }; -# This is indexed with the CA's name and yields a DER (binary) encoded certificate. -const root_ca_certs: table[string] of string = {} &redef; - +## HTTP session statistics. +## +## .. bro:see:: http_stats type http_stats_rec: record { - num_requests: count; - num_replies: count; - request_version: double; - reply_version: double; + num_requests: count; ##< Number of requests. + num_replies: count; ##< Number of replies. + request_version: double; ##< HTTP version of the requests. + reply_version: double; ##< HTTP Version of the replies. }; +## HTTP message statistics. +## +## .. bro:see:: http_message_done type http_message_stat: record { - start: time; # when the request/reply line was complete - interrupted: bool; # whether the message is interrupted - finish_msg: string; # reason phrase if interrupted - body_length: count; # length of body processed - # (before finished/interrupted) - content_gap_length: count; # total len of gaps within body_length - header_length: count; # length of headers - # (including the req/reply line, - # but not CR/LF's) + ## When the request/reply line was complete. + start: time; + ## Whether the message was interrupted. + interrupted: bool; + ## Reason phrase if interrupted. + finish_msg: string; + ## Length of body processed (before finished/interrupted). + body_length: count; + ## Total length of gaps within body_length. + content_gap_length: count; + ## Length of headers (including the req/reply line, but not CR/LF's). + header_length: count; }; +## Maximum number of HTTP entity data delivered to events. The amount of data +## can be limited for better performance, zero disables truncation. +## +## .. bro:see:: http_entity_data skip_http_entity_data skip_http_data global http_entity_data_delivery_size = 1500 &redef; -# Truncate URIs longer than this to prevent over-long URIs (usually sent -# by worms) from slowing down event processing. A value of -1 means "do -# not truncate". +## Skip HTTP data for performance considerations. The skipped +## portion will not go through TCP reassembly. +## +## .. bro:see:: http_entity_data skip_http_entity_data http_entity_data_delivery_size +const skip_http_data = F &redef; + +## Maximum length of HTTP URIs passed to events. Longer ones will be truncated +## to prevent over-long URIs (usually sent by worms) from slowing down event +## processing. A value of -1 means "do not truncate". +## +## .. bro:see:: http_request const truncate_http_URI = -1 &redef; -# IRC-related globals to which the event engine is sensitive. +## IRC join information. +## +## .. bro:see:: irc_join_list type irc_join_info: record { nick: string; channel: string; password: string; usermode: string; }; + +## Set of IRC join information. +## +## .. bro:see:: irc_join_message type irc_join_list: set[irc_join_info]; + +## Deprecated. +## +## .. todo:: Remove. It's still declared internally but doesn't seem used anywhere +## else. global irc_servers : set[addr] &redef; -# Stepping-stone globals. +## Internal to the stepping stone detector. const stp_delta: interval &redef; + +## Internal to the stepping stone detector. const stp_idle_min: interval &redef; -# Don't do analysis on these sources. Used to avoid overload from scanners. +## Internal to the stepping stone detector. global stp_skip_src: set[addr] &redef; +## Deprecated. const interconn_min_interarrival: interval &redef; + +## Deprecated. const interconn_max_interarrival: interval &redef; + +## Deprecated. const interconn_max_keystroke_pkt_size: count &redef; + +## Deprecated. const interconn_default_pkt_size: count &redef; + +## Deprecated. const interconn_stat_period: interval &redef; + +## Deprecated. const interconn_stat_backoff: double &redef; +## Deprecated. type interconn_endp_stats: record { num_pkts: count; num_keystrokes_two_in_row: count; @@ -1144,9 +2162,13 @@ type interconn_endp_stats: record { num_normal_lines: count; }; +## Deprecated. const backdoor_stat_period: interval &redef; + +## Deprecated. const backdoor_stat_backoff: double &redef; +## Deprecated. type backdoor_endp_stats: record { is_partial: bool; num_pkts: count; @@ -1158,339 +2180,446 @@ type backdoor_endp_stats: record { num_7bit_ascii: count; }; +## Description of a signature match. +## +## .. bro:see:: signature_match type signature_state: record { - sig_id: string; # ID of the signature - conn: connection; # Current connection - is_orig: bool; # True if current endpoint is originator - payload_size: count; # Payload size of the first pkt of curr. endpoint - + sig_id: string; ##< ID of the matching signature. + conn: connection; ##< Matching connection. + is_orig: bool; ##< True if matching endpoint is originator. + payload_size: count; ##< Payload size of the first matching packet of current endpoint. }; -# This type is no longer used -# TODO: remove any use of this from the core. +# Deprecated. +# +# .. todo:: This type is no longer used. Remove any reference of this from the +# core. type software_version: record { - major: int; # Major version number - minor: int; # Minor version number - minor2: int; # Minor subversion number - addl: string; # Additional version string (e.g. "beta42") + major: int; + minor: int; + minor2: int; + addl: string; }; -# This type is no longer used -# TODO: remove any use of this from the core. +# Deprecated. +# +# .. todo:: This type is no longer used. Remove any reference of this from the +# core. type software: record { - name: string; # Unique name of a software, e.g., "OS" + name: string; version: software_version; }; -# The following describe the quality of signature matches used -# for passive fingerprinting. +## Quality of passive fingerprinting matches. +## +## .. .. bro:see:: OS_version type OS_version_inference: enum { - direct_inference, generic_inference, fuzzy_inference, + direct_inference, ##< TODO. + generic_inference, ##< TODO. + fuzzy_inference, ##< TODO. }; +## Passive fingerprinting match. +## +## .. bro:see:: OS_version_found type OS_version: record { - genre: string; # Linux, Windows, AIX, ... - detail: string; # kernel version or such - dist: count; # how far is the host away from the sensor (TTL)? - match_type: OS_version_inference; + genre: string; ##< Linux, Windows, AIX, ... + detail: string; ##< Lernel version or such. + dist: count; ##< How far is the host away from the sensor (TTL)?. + match_type: OS_version_inference; ##< Quality of the match. }; -# Defines for which subnets we should do passive fingerprinting. +## Defines for which subnets we should do passive fingerprinting. +## +## .. bro:see:: OS_version_found global generate_OS_version_event: set[subnet] &redef; -# Type used to report load samples via load_sample(). For now, -# it's a set of names (event names, source file names, and perhaps -# 's, which were seen during the sample. +# Type used to report load samples via :bro:see:`load_sample`. For now, it's a +# set of names (event names, source file names, and perhaps ````, which were seen during the sample. type load_sample_info: set[string]; -# NetFlow-related data structures. - -# The following provides a mean to sort together flow headers and flow -# records at the script level. rcvr_id equals the name of the file -# (e.g., netflow.dat) or the socket address (e.g., 127.0.0.1:5555), -# or an explicit name if specified to -y or -Y; pdu_id is just a serial -# number, ignoring any overflows. +## ID for NetFlow header. This is primarily a means to sort together NetFlow +## headers and flow records at the script level. type nfheader_id: record { + ## Name of the NetFlow file (e.g., ``netflow.dat``) or the receiving socket address + ## (e.g., ``127.0.0.1:5555``), or an explicit name if specified to + ## ``-y`` or ``-Y``. rcvr_id: string; + ## A serial number, ignoring any overflows. pdu_id: count; }; +## A NetFlow v5 header. +## +## .. bro:see:: netflow_v5_header type nf_v5_header: record { - h_id: nfheader_id; # ID for sorting, per the above - cnt: count; - sysuptime: interval; # router's uptime - exporttime: time; # when the data was exported - flow_seq: count; - eng_type: count; - eng_id: count; - sample_int: count; - exporter: addr; + h_id: nfheader_id; ##< ID for sorting. + cnt: count; ##< TODO. + sysuptime: interval; ##< Router's uptime. + exporttime: time; ##< When the data was exported. + flow_seq: count; ##< Sequence number. + eng_type: count; ##< Engine type. + eng_id: count; ##< Engine ID. + sample_int: count; ##< Sampling interval. + exporter: addr; ##< Exporter address. }; +## A NetFlow v5 record. +## +## .. bro:see:: netflow_v5_record type nf_v5_record: record { - h_id: nfheader_id; - id: conn_id; - nexthop: addr; - input: count; - output: count; - pkts: count; - octets: count; - first: time; - last: time; - tcpflag_fin: bool; # Taken from tcpflags in NF V5; or directly. - tcpflag_syn: bool; - tcpflag_rst: bool; - tcpflag_psh: bool; - tcpflag_ack: bool; - tcpflag_urg: bool; - proto: count; - tos: count; - src_as: count; - dst_as: count; - src_mask: count; - dst_mask: count; + h_id: nfheader_id; ##< ID for sorting. + id: conn_id; ##< Connection ID. + nexthop: addr; ##< Address of next hop. + input: count; ##< Input interface. + output: count; ##< Output interface. + pkts: count; ##< Number of packets. + octets: count; ##< Number of bytes. + first: time; ##< Timestamp of first packet. + last: time; ##< Timestamp of last packet. + tcpflag_fin: bool; ##< FIN flag for TCP flows. + tcpflag_syn: bool; ##< SYN flag for TCP flows. + tcpflag_rst: bool; ##< RST flag for TCP flows. + tcpflag_psh: bool; ##< PSH flag for TCP flows. + tcpflag_ack: bool; ##< ACK flag for TCP flows. + tcpflag_urg: bool; ##< URG flag for TCP flows. + proto: count; ##< IP protocol. + tos: count; ##< Type of service. + src_as: count; ##< Source AS. + dst_as: count; ##< Destination AS. + src_mask: count; ##< Source mask. + dst_mask: count; ##< Destination mask. }; -# The peer record and the corresponding set type used by the -# BitTorrent analyzer. +## A BitTorrent peer. +## +## .. bro:see:: bittorrent_peer_set type bittorrent_peer: record { - h: addr; - p: port; + h: addr; ##< The peer's address. + p: port; ##< The peer's port. }; + +## A set of BitTorrent peers. +## +## .. bro:see:: bt_tracker_response type bittorrent_peer_set: set[bittorrent_peer]; -# The benc value record and the corresponding table type used by the -# BitTorrenttracker analyzer. Note that "benc" = Bencode ("Bee-Encode"), -# per http://en.wikipedia.org/wiki/Bencode. +## BitTorrent "benc" value. Note that "benc" = Bencode ("Bee-Encode"), per +## http://en.wikipedia.org/wiki/Bencode. +## +## .. bro:see:: bittorrent_benc_dir type bittorrent_benc_value: record { - i: int &optional; - s: string &optional; - d: string &optional; - l: string &optional; + i: int &optional; ##< TODO. + s: string &optional; ##< TODO. + d: string &optional; ##< TODO. + l: string &optional; ##< TODO. }; + +## A table of BitTorrent "benc" values. +## +## .. bro:see:: bt_tracker_response type bittorrent_benc_dir: table[string] of bittorrent_benc_value; -# The header table type used by the bittorrenttracker analyzer. +## Header table type used by BitTorrent analyzer. +## +## .. bro:see:: bt_tracker_request bt_tracker_response +## bt_tracker_response_not_ok type bt_tracker_headers: table[string] of string; -@load event.bif.bro +@load base/event.bif -# The filter the user has set via the -f command line options, or -# empty if none. +## BPF filter the user has set via the -f command line options. Empty if none. const cmd_line_bpf_filter = "" &redef; -# Rotate logs every x interval. +## Deprecated. const log_rotate_interval = 0 sec &redef; -# If set, rotate logs at given time + i * log_rotate_interval. -# (string is time in 24h format, e.g., "18:00"). +## Deprecated. const log_rotate_base_time = "0:00" &redef; -# Rotate logs when they reach this size (in bytes). Note, the -# parameter is a double rather than a count to enable easy expression -# of large values such as 1e7 or exceeding 2^32. +## Deprecated. const log_max_size = 0.0 &redef; -# Default public key for encrypting log files. +## Deprecated. const log_encryption_key = "" &redef; -# Write profiling info into this file. +## Write profiling info into this file in regular intervals. The easiest way to +## activate profiling is loading :doc:`/scripts/policy/misc/profiling`. +## +## .. bro:see:: profiling_interval expensive_profiling_multiple segment_profiling global profiling_file: file &redef; -# Update interval for profiling (0 disables). +## Update interval for profiling (0 disables). The easiest way to activate +## profiling is loading :doc:`/scripts/policy/misc/profiling`. +## +## .. bro:see:: profiling_file expensive_profiling_multiple segment_profiling const profiling_interval = 0 secs &redef; -# Multiples of profiling_interval at which (expensive) memory -# profiling is done (0 disables). +## Multiples of profiling_interval at which (more expensive) memory profiling is +## done (0 disables). +## +## .. bro:see:: profiling_interval profiling_file segment_profiling const expensive_profiling_multiple = 0 &redef; -# If true, then write segment profiling information (very high volume!) -# in addition to statistics. +## If true, then write segment profiling information (very high volume!) +## in addition to profiling statistics. +## +## .. bro:see:: profiling_interval expensive_profiling_multiple profiling_file const segment_profiling = F &redef; -# Output packet profiling information every secs (mode 1), -# every packets (mode 2), or every bytes (mode 3). -# Mode 0 disables. +## Output modes for packet profiling information. +## +## .. bro:see:: pkt_profile_mode pkt_profile_freq pkt_profile_mode pkt_profile_file type pkt_profile_modes: enum { - PKT_PROFILE_MODE_NONE, - PKT_PROFILE_MODE_SECS, - PKT_PROFILE_MODE_PKTS, - PKT_PROFILE_MODE_BYTES, + PKT_PROFILE_MODE_NONE, ##< No output. + PKT_PROFILE_MODE_SECS, ##< Output every :bro:see:`pkt_profile_freq` seconds. + PKT_PROFILE_MODE_PKTS, ##< Output every :bro:see:`pkt_profile_freq` packets. + PKT_PROFILE_MODE_BYTES, ##< Output every :bro:see:`pkt_profile_freq` bytes. }; + +## Output modes for packet profiling information. +## +## .. bro:see:: pkt_profile_modes pkt_profile_freq pkt_profile_mode pkt_profile_file const pkt_profile_mode = PKT_PROFILE_MODE_NONE &redef; -# Frequency associated with packet profiling. +## Frequency associated with packet profiling. +## +## .. bro:see:: pkt_profile_modes pkt_profile_mode pkt_profile_mode pkt_profile_file const pkt_profile_freq = 0.0 &redef; -# File where packet profiles are logged. +## File where packet profiles are logged. +## +## .. bro:see:: pkt_profile_modes pkt_profile_freq pkt_profile_mode pkt_profile_mode global pkt_profile_file: file &redef; -# Rate at which to generate load_sample events, *if* you've also -# defined a load_sample handler. Units are inverse number of packets; -# e.g., a value of 20 means "roughly one in every 20 packets". +## Rate at which to generate :bro:see:`load_sample` events. As all +## events, the event is only generated if you've also defined a +## :bro:see:`load_sample` handler. Units are inverse number of packets; e.g., a +## value of 20 means "roughly one in every 20 packets". +## +## .. bro:see:: load_sample global load_sample_freq = 20 &redef; -# Rate at which to generate gap_report events assessing to what -# degree the measurement process appears to exhibit loss. +## Rate at which to generate :bro:see:`gap_report` events assessing to what degree +## the measurement process appears to exhibit loss. +## +## .. bro:see:: gap_report const gap_report_freq = 1.0 sec &redef; -# Whether we want content_gap and drop reports for partial connections -# (a connection is partial if it is missing a full handshake). Note that -# gap reports for partial connections might not be reliable. +## Whether we want :bro:see:`content_gap` and :bro:see:`gap_report` for partial +## connections. A connection is partial if it is missing a full handshake. Note +## that gap reports for partial connections might not be reliable. +## +## .. bro:see:: content_gap gap_report partial_connection const report_gaps_for_partial = F &redef; -# Globals associated with entire-run statistics on gaps (useful -# for final summaries). - -# The CA certificate file to authorize remote Bros. +## The CA certificate file to authorize remote Bros/Broccolis. +## +## .. bro:see:: ssl_private_key ssl_passphrase const ssl_ca_certificate = "" &redef; -# File containing our private key and our certificate. +## File containing our private key and our certificate. +## +## .. bro:see:: ssl_ca_certificate ssl_passphrase const ssl_private_key = "" &redef; -# The passphrase for our private key. Keeping this undefined -# causes Bro to prompt for the passphrase. +## The passphrase for our private key. Keeping this undefined +## causes Bro to prompt for the passphrase. +## +## .. bro:see:: ssl_private_key ssl_ca_certificate const ssl_passphrase = "" &redef; -# Whether the Bro-level packet filter drops packets per default or not. +## Default mode for Bro's user-space dynamic packet filter. If true, packets that +## aren't explicitly allowed through, are dropped from any further processing. +## +## .. note:: This is not the BPF packet filter but an additional dynamic filter +## that Bro optionally applies just before normal processing starts. +## +## .. bro:see:: install_dst_addr_filter install_dst_net_filter +## install_src_addr_filter install_src_net_filter uninstall_dst_addr_filter +## uninstall_dst_net_filter uninstall_src_addr_filter uninstall_src_net_filter const packet_filter_default = F &redef; -# Maximum size of regular expression groups for signature matching. +## Maximum size of regular expression groups for signature matching. const sig_max_group_size = 50 &redef; -# If true, send logger messages to syslog. +## Deprecated. No longer functional. const enable_syslog = F &redef; -# This is transmitted to peers receiving our events. +## Description transmitted to remote communication peers for identification. const peer_description = "bro" &redef; -# If true, broadcast events/state received from one peer to other peers. -# NOTE: These options are only temporary. They will disappear when we get a -# more sophisticated script-level communication framework. +## If true, broadcast events received from one peer to all other peers. +## +## .. bro:see:: forward_remote_state_changes +## +## .. note:: This option is only temporary and will disappear once we get a more +## sophisticated script-level communication framework. const forward_remote_events = F &redef; + +## If true, broadcast state updates received from one peer to all other peers. +## +## .. bro:see:: forward_remote_events +## +## .. note:: This option is only temporary and will disappear once we get a more +## sophisticated script-level communication framework. const forward_remote_state_changes = F &redef; +## Place-holder constant indicating "no peer". const PEER_ID_NONE = 0; -# Whether to use the connection tracker. -const use_connection_compressor = T &redef; +# Signature payload pattern types. +# todo::use enum to help autodoc +# todo::Still used? +#const SIG_PATTERN_PAYLOAD = 0; +#const SIG_PATTERN_HTTP = 1; +#const SIG_PATTERN_FTP = 2; +#const SIG_PATTERN_FINGER = 3; -# Whether compressor should handle refused connections itself. -const cc_handle_resets = F &redef; +# Deprecated. +# todo::Should use the new logging framework directly. +const REMOTE_LOG_INFO = 1; ##< Deprecated. +const REMOTE_LOG_ERROR = 2; ##< Deprecated. -# Whether compressor should only take care of initial SYNs. -# (By default on, this is basically "connection compressor lite".) -const cc_handle_only_syns = T &redef; +# Source of logging messages from the communication framework. +# todo::these should go into an enum to make them autodoc'able. +const REMOTE_SRC_CHILD = 1; ##< Message from the child process. +const REMOTE_SRC_PARENT = 2; ##< Message from the parent process. +const REMOTE_SRC_SCRIPT = 3; ##< Message from a policy script. -# Whether compressor instantiates full state when originator sends a -# non-control packet. -const cc_instantiate_on_data = F &redef; - -# Signature payload pattern types -const SIG_PATTERN_PAYLOAD = 0; -const SIG_PATTERN_HTTP = 1; -const SIG_PATTERN_FTP = 2; -const SIG_PATTERN_FINGER = 3; - -# Log-levels for remote_log. -# Eventually we should create a general logging framework and merge these in. -const REMOTE_LOG_INFO = 1; -const REMOTE_LOG_ERROR = 2; - -# Sources for remote_log. -const REMOTE_SRC_CHILD = 1; -const REMOTE_SRC_PARENT = 2; -const REMOTE_SRC_SCRIPT = 3; - -# Synchronize trace processing at a regular basis in pseudo-realtime mode. +## Synchronize trace processing at a regular basis in pseudo-realtime mode. +## +## .. bro:see:: remote_trace_sync_peers const remote_trace_sync_interval = 0 secs &redef; -# Number of peers across which to synchronize trace processing. +## Number of peers across which to synchronize trace processing in +## pseudo-realtime mode. +## +## .. bro:see:: remote_trace_sync_interval const remote_trace_sync_peers = 0 &redef; -# Whether for &synchronized state to send the old value as a consistency check. +## Whether for :bro:attr:`&synchronized` state to send the old value as a +## consistency check. const remote_check_sync_consistency = F &redef; -# Prepend the peer description, if set. -function prefixed_id(id: count): string - { - if ( peer_description == "" ) - return fmt("%s", id); - else - return cat(peer_description, "-", id); - } - -# Analyzer tags. The core automatically defines constants -# ANALYZER_*, e.g., ANALYZER_HTTP. +## Analyzer tags. The core automatically defines constants +## ``ANALYZER_*``, e.g., ``ANALYZER_HTTP``. +## +## .. bro:see:: dpd_config +## +## .. todo::We should autodoc these automaticallty generated constants. type AnalyzerTag: count; -# DPD configuration. - +## Set of ports activating a particular protocol analysis. +## +## .. bro:see:: dpd_config type dpd_protocol_config: record { - ports: set[port] &optional; + ports: set[port] &optional; ##< Set of ports. }; +## Port configuration for Bro's "dynamic protocol detection". Protocol +## analyzers can be activated via either well-known ports or content analysis. +## This table defines the ports. +## +## .. bro:see:: dpd_reassemble_first_packets dpd_buffer_size +## dpd_match_only_beginning dpd_ignore_ports const dpd_config: table[AnalyzerTag] of dpd_protocol_config = {} &redef; -# Reassemble the beginning of all TCP connections before doing -# signature-matching for protocol detection. +## Reassemble the beginning of all TCP connections before doing +## signature-matching. Enabling this provides more accurate matching at the +## expensive of CPU cycles. +## +## .. bro:see:: dpd_config dpd_buffer_size +## dpd_match_only_beginning dpd_ignore_ports +## +## .. note:: Despite the name, this option affects *all* signature matching, not +## only signatures used for dynamic protocol detection. const dpd_reassemble_first_packets = T &redef; -# Size of per-connection buffer in bytes. If the buffer is full, data is -# deleted and lost to analyzers that are activated afterwards. +## Size of per-connection buffer used for dynamic protocol detection. For each +## connection, Bro buffers this initial amount of payload 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. +## +## .. bro:see:: dpd_reassemble_first_packets dpd_config dpd_match_only_beginning +## dpd_ignore_ports const dpd_buffer_size = 1024 &redef; -# If true, stops signature matching if dpd_buffer_size has been reached. +## If true, stops signature matching if dpd_buffer_size has been reached. +## +## .. bro:see:: dpd_reassemble_first_packets dpd_buffer_size +## dpd_config dpd_ignore_ports +## +## .. note:: Despite the name, this option affects *all* signature matching, not +## only signatures used for dynamic protocol detection. const dpd_match_only_beginning = T &redef; -# If true, don't consider any ports for deciding which analyzer to use. +## If true, don't consider any ports for deciding which protocol analyzer to +## use. If so, the value of :bro:see:`dpd_config` is ignored. +## +## .. bro:see:: dpd_reassemble_first_packets dpd_buffer_size +## dpd_match_only_beginning dpd_config const dpd_ignore_ports = F &redef; -# Ports which the core considers being likely used by servers. +## Ports which the core considers being likely used by servers. For ports in +## this set, is may heuristically decide to flip the direction of the +## connection if it misses the initial handshake. const likely_server_ports: set[port] &redef; -# Set of all ports for which we know an analyzer. +## Deprated. Set of all ports for which we know an analyzer, built by +## :doc:`/scripts/base/frameworks/dpd/main`. +## +## .. todo::This should be defined by :doc:`/scripts/base/frameworks/dpd/main` +## itself we still need it. global dpd_analyzer_ports: table[port] of set[AnalyzerTag]; -# Per-incident timer managers are drained after this amount of inactivity. +## Per-incident timer managers are drained after this amount of inactivity. const timer_mgr_inactivity_timeout = 1 min &redef; -# If true, output profiling for time-machine queries. +## If true, output profiling for time-machine queries. const time_machine_profiling = F &redef; -# If true, warns about unused event handlers at startup. +## If true, warns about unused event handlers at startup. const check_for_unused_event_handlers = F &redef; # If true, dumps all invoked event handlers at startup. -const dump_used_event_handlers = F &redef; +# todo::Still used? +# const dump_used_event_handlers = F &redef; -# If true, we suppress prints to local files if we have a receiver for -# print_hook events. Ignored for files with a &disable_print_hook attribute. +## Deprecated. const suppress_local_output = F &redef; -# Holds the filename of the trace file given with -w (empty if none). +## Holds the filename of the trace file given with -w (empty if none). +## +## .. bro:see:: record_all_packets const trace_output_file = ""; -# If a trace file is given, dump *all* packets seen by Bro into it. -# By default, Bro applies (very few) heuristics to reduce the volume. -# A side effect of setting this to true is that we can write the -# packets out before we actually process them, which can be helpful -# for debugging in case the analysis triggers a crash. +## If a trace file is given with ``-w``, dump *all* packets seen by Bro into it. By +## default, Bro applies (very few) heuristics to reduce the volume. A side effect +## of setting this to true is that we can write the packets out before we actually +## process them, which can be helpful for debugging in case the analysis triggers a +## crash. +## +## .. bro:see:: trace_output_file const record_all_packets = F &redef; -# Some connections (e.g., SSH) retransmit the acknowledged last -# byte to keep the connection alive. If ignore_keep_alive_rexmit -# is set to T, such retransmissions will be excluded in the rexmit -# counter in conn_stats. +## Ignore certain TCP retransmissions for :bro:see:`conn_stats`. Some connections +## (e.g., SSH) retransmit the acknowledged last byte to keep the connection alive. +## If *ignore_keep_alive_rexmit* is set to true, such retransmissions will be +## excluded in the rexmit counter in :bro:see:`conn_stats`. +## +## .. bro:see:: conn_stats const ignore_keep_alive_rexmit = F &redef; -# Skip HTTP data portions for performance considerations (the skipped -# portion will not go through TCP reassembly). -const skip_http_data = F &redef; - -# Whether the analysis engine parses IP packets encapsulated in -# UDP tunnels. See also: udp_tunnel_port, policy/udp-tunnel.bro. +## Whether the analysis engine parses IP packets encapsulated in +## UDP tunnels. +## +## .. bro:see:: tunnel_port const parse_udp_tunnels = F &redef; module Tunnel; @@ -1498,7 +2627,7 @@ export { ## Whether to decapsulate IP tunnels (IPinIP, 6in4, 6to4) const decapsulate_ip = F &redef; - ## Whether to decapsulate URDP tunnels (e.g., Teredo, IPv4 in UDP) + ## Whether to decapsulate UDP tunnels (e.g., Teredo, IPv4 in UDP) const decapsulate_udp = F &redef; ## If decapsulating UDP: the set of ports for which to do so. @@ -1514,7 +2643,9 @@ export { } # end export module GLOBAL; +## Number of bytes per packet to capture from live interfaces. +const snaplen = 8192 &redef; -# Load the logging framework here because it uses fairly deep integration with +# Load the logging framework here because it uses fairly deep integration with # BiFs and script-land defined types. @load base/frameworks/logging diff --git a/scripts/base/protocols/conn/contents.bro b/scripts/base/protocols/conn/contents.bro index 21945beed5..2e6b547ab1 100644 --- a/scripts/base/protocols/conn/contents.bro +++ b/scripts/base/protocols/conn/contents.bro @@ -1,21 +1,27 @@ ##! This script can be used to extract either the originator's data or the ##! responders data or both. By default nothing is extracted, and in order ##! to actually extract data the ``c$extract_orig`` and/or the -##! ``c$extract_resp`` variable must be set to T. One way to achieve this -##! would be to handle the connection_established event elsewhere and set the -##! extract_orig and extract_resp options there. However, there may be trouble -##! with the timing due the event queue delay. -##! This script does not work well in a cluster context unless it has a -##! remotely mounted disk to write the content files to. +##! ``c$extract_resp`` variable must be set to ``T``. One way to achieve this +##! would be to handle the :bro:id:`connection_established` event elsewhere +##! and set the ``extract_orig`` and ``extract_resp`` options there. +##! However, there may be trouble with the timing due to event queue delay. +##! +##! .. note:: +##! +##! This script does not work well in a cluster context unless it has a +##! remotely mounted disk to write the content files to. + +@load base/utils/files module Conn; export { - ## The prefix given to files as they are opened on disk. + ## The prefix given to files containing extracted connections as they are + ## opened on disk. const extraction_prefix = "contents" &redef; - ## If this variable is set to T, then all contents of all files will be - ## extracted. + ## If this variable is set to ``T``, then all contents of all connections + ## will be extracted. const default_extract = F &redef; } diff --git a/scripts/base/protocols/conn/inactivity.bro b/scripts/base/protocols/conn/inactivity.bro index 04dab62470..28df192de3 100644 --- a/scripts/base/protocols/conn/inactivity.bro +++ b/scripts/base/protocols/conn/inactivity.bro @@ -4,7 +4,7 @@ module Conn; export { - ## Define inactivty timeouts by the service detected being used over + ## Define inactivity timeouts by the service detected being used over ## the connection. const analyzer_inactivity_timeouts: table[AnalyzerTag] of interval = { # For interactive services, allow longer periods of inactivity. diff --git a/scripts/base/protocols/conn/main.bro b/scripts/base/protocols/conn/main.bro index 69c4cde64b..34ec12fa56 100644 --- a/scripts/base/protocols/conn/main.bro +++ b/scripts/base/protocols/conn/main.bro @@ -1,18 +1,39 @@ +##! This script manages the tracking/logging of general information regarding +##! TCP, UDP, and ICMP traffic. For UDP and ICMP, "connections" are to +##! be interpreted using flow semantics (sequence of packets from a source +##! host/post to a destination host/port). Further, ICMP "ports" are to +##! be interpreted as the source port meaning the ICMP message type and +##! the destination port being the ICMP message code. + +@load base/utils/site module Conn; export { - redef enum Log::ID += { CONN }; + ## The connection logging stream identifier. + redef enum Log::ID += { LOG }; + ## The record type which contains column fields of the connection log. type Info: record { ## This is the time of the first packet. ts: time &log; + ## A unique identifier of a connection. uid: string &log; + ## The connection's 4-tuple of endpoint addresses/ports. id: conn_id &log; + ## The transport layer protocol of the connection. proto: transport_proto &log; + ## An identification of an application protocol being sent over the + ## the connection. service: string &log &optional; + ## How long the connection lasted. For 3-way or 4-way connection + ## tear-downs, this will not include the final ACK. duration: interval &log &optional; + ## The number of payload bytes the originator sent. For TCP + ## this is taken from sequence numbers and might be inaccurate + ## (e.g., due to large connections) orig_bytes: count &log &optional; + ## The number of payload bytes the responder sent. See ``orig_bytes``. resp_bytes: count &log &optional; ## ========== =============================================== @@ -46,8 +67,8 @@ export { ## have been completed prior to the packet loss. missed_bytes: count &log &default=0; - ## Records the state history of (TCP) connections as - ## a string of letters. + ## Records the state history of connections as a string of letters. + ## For TCP connections the meaning of those letters is: ## ## ====== ==================================================== ## Letter Meaning @@ -66,10 +87,24 @@ export { ## originator and lower case then means the responder. ## Also, there is compression. We only record one "d" in each direction, ## for instance. I.e., we just record that data went in that direction. - ## This history is not meant to encode how much data that happened to be. + ## This history is not meant to encode how much data that happened to + ## be. history: string &log &optional; + ## Number of packets the originator sent. + ## Only set if :bro:id:`use_conn_size_analyzer` = T + orig_pkts: count &log &optional; + ## Number IP level bytes the originator sent (as seen on the wire, + ## taken from IP total_length header field). + ## Only set if :bro:id:`use_conn_size_analyzer` = T + orig_ip_bytes: count &log &optional; + ## Number of packets the responder sent. See ``orig_pkts``. + resp_pkts: count &log &optional; + ## Number IP level bytes the responder sent. See ``orig_pkts``. + resp_ip_bytes: count &log &optional; }; - + + ## Event that can be handled to access the :bro:type:`Conn::Info` + ## record as it is sent on to the logging framework. global log_conn: event(rec: Info); } @@ -79,7 +114,7 @@ redef record connection += { event bro_init() &priority=5 { - Log::create_stream(CONN, [$columns=Info, $ev=log_conn]); + Log::create_stream(Conn::LOG, [$columns=Info, $ev=log_conn]); } function conn_state(c: connection, trans: transport_proto): string @@ -143,31 +178,39 @@ function determine_service(c: connection): string return to_lower(service); } +## Fill out the c$conn record for logging function set_conn(c: connection, eoc: bool) { if ( ! c?$conn ) { - local id = c$id; local tmp: Info; - tmp$ts=c$start_time; - tmp$uid=c$uid; - tmp$id=id; - tmp$proto=get_port_transport_proto(id$resp_p); - if( |Site::local_nets| > 0 ) - tmp$local_orig=Site::is_local_addr(id$orig_h); c$conn = tmp; } + + c$conn$ts=c$start_time; + c$conn$uid=c$uid; + c$conn$id=c$id; + c$conn$proto=get_port_transport_proto(c$id$resp_p); + if( |Site::local_nets| > 0 ) + c$conn$local_orig=Site::is_local_addr(c$id$orig_h); if ( eoc ) { if ( c$duration > 0secs ) { c$conn$duration=c$duration; - # TODO: these should optionally use Gregor's new - # actual byte counting code if it's enabled. c$conn$orig_bytes=c$orig$size; c$conn$resp_bytes=c$resp$size; } + if ( c$orig?$num_pkts ) + { + # these are set if use_conn_size_analyzer=T + # we can have counts in here even without duration>0 + c$conn$orig_pkts = c$orig$num_pkts; + c$conn$orig_ip_bytes = c$orig$num_bytes_ip; + c$conn$resp_pkts = c$resp$num_pkts; + c$conn$resp_ip_bytes = c$resp$num_bytes_ip; + } local service = determine_service(c); if ( service != "" ) c$conn$service=service; @@ -178,11 +221,6 @@ function set_conn(c: connection, eoc: bool) } } -event connection_established(c: connection) &priority=5 - { - set_conn(c, F); - } - event content_gap(c: connection, is_orig: bool, seq: count, length: count) &priority=5 { set_conn(c, F); @@ -190,9 +228,13 @@ event content_gap(c: connection, is_orig: bool, seq: count, length: count) &prio c$conn$missed_bytes = c$conn$missed_bytes + length; } -event connection_state_remove(c: connection) &priority=-5 +event connection_state_remove(c: connection) &priority=5 { set_conn(c, T); - Log::write(CONN, c$conn); + } + +event connection_state_remove(c: connection) &priority=-5 + { + Log::write(Conn::LOG, c$conn); } diff --git a/scripts/base/protocols/dns/consts.bro b/scripts/base/protocols/dns/consts.bro index b57170dded..fbf4aba008 100644 --- a/scripts/base/protocols/dns/consts.bro +++ b/scripts/base/protocols/dns/consts.bro @@ -4,9 +4,9 @@ module DNS; export { - const PTR = 12; - const EDNS = 41; - const ANY = 255; + const PTR = 12; ##< RR TYPE value for a domain name pointer. + const EDNS = 41; ##< An OPT RR TYPE value described by EDNS. + const ANY = 255; ##< A QTYPE value describing a request for all records. ## Mapping of DNS query type codes to human readable string representation. const query_types = { @@ -29,50 +29,43 @@ export { [ANY] = "*", } &default = function(n: count): string { return fmt("query-%d", n); }; - const code_types = { - [0] = "X0", - [1] = "Xfmt", - [2] = "Xsrv", - [3] = "Xnam", - [4] = "Ximp", - [5] = "X[", - } &default="?"; - ## Errors used for non-TSIG/EDNS types. const base_errors = { - [0] = "NOERROR", ##< No Error - [1] = "FORMERR", ##< Format Error - [2] = "SERVFAIL", ##< Server Failure - [3] = "NXDOMAIN", ##< Non-Existent Domain - [4] = "NOTIMP", ##< Not Implemented - [5] = "REFUSED", ##< Query Refused - [6] = "YXDOMAIN", ##< Name Exists when it should not - [7] = "YXRRSET", ##< RR Set Exists when it should not - [8] = "NXRRSet", ##< RR Set that should exist does not - [9] = "NOTAUTH", ##< Server Not Authoritative for zone - [10] = "NOTZONE", ##< Name not contained in zone - [11] = "unassigned-11", ##< available for assignment - [12] = "unassigned-12", ##< available for assignment - [13] = "unassigned-13", ##< available for assignment - [14] = "unassigned-14", ##< available for assignment - [15] = "unassigned-15", ##< available for assignment - [16] = "BADVERS", ##< for EDNS, collision w/ TSIG - [17] = "BADKEY", ##< Key not recognized - [18] = "BADTIME", ##< Signature out of time window - [19] = "BADMODE", ##< Bad TKEY Mode - [20] = "BADNAME", ##< Duplicate key name - [21] = "BADALG", ##< Algorithm not supported - [22] = "BADTRUNC", ##< draft-ietf-dnsext-tsig-sha-05.txt - [3842] = "BADSIG", ##< 16 <= number collision with EDNS(16); - ##< this is a translation from TSIG(16) + [0] = "NOERROR", # No Error + [1] = "FORMERR", # Format Error + [2] = "SERVFAIL", # Server Failure + [3] = "NXDOMAIN", # Non-Existent Domain + [4] = "NOTIMP", # Not Implemented + [5] = "REFUSED", # Query Refused + [6] = "YXDOMAIN", # Name Exists when it should not + [7] = "YXRRSET", # RR Set Exists when it should not + [8] = "NXRRSet", # RR Set that should exist does not + [9] = "NOTAUTH", # Server Not Authoritative for zone + [10] = "NOTZONE", # Name not contained in zone + [11] = "unassigned-11", # available for assignment + [12] = "unassigned-12", # available for assignment + [13] = "unassigned-13", # available for assignment + [14] = "unassigned-14", # available for assignment + [15] = "unassigned-15", # available for assignment + [16] = "BADVERS", # for EDNS, collision w/ TSIG + [17] = "BADKEY", # Key not recognized + [18] = "BADTIME", # Signature out of time window + [19] = "BADMODE", # Bad TKEY Mode + [20] = "BADNAME", # Duplicate key name + [21] = "BADALG", # Algorithm not supported + [22] = "BADTRUNC", # draft-ietf-dnsext-tsig-sha-05.txt + [3842] = "BADSIG", # 16 <= number collision with EDNS(16); + # this is a translation from TSIG(16) } &default = function(n: count): string { return fmt("rcode-%d", n); }; - # This deciphers EDNS Z field values. + ## This deciphers EDNS Z field values. const edns_zfield = { [0] = "NOVALUE", # regular entry [32768] = "DNS_SEC_OK", # accepts DNS Sec RRs } &default="?"; + ## Possible values of the CLASS field in resource records or QCLASS field + ## in query messages. const classes = { [1] = "C_INTERNET", [2] = "C_CSNET", @@ -81,4 +74,4 @@ export { [254] = "C_NONE", [255] = "C_ANY", } &default = function(n: count): string { return fmt("qclass-%d", n); }; -} \ No newline at end of file +} diff --git a/scripts/base/protocols/dns/main.bro b/scripts/base/protocols/dns/main.bro index 59ade654d4..c50a8bdc54 100644 --- a/scripts/base/protocols/dns/main.bro +++ b/scripts/base/protocols/dns/main.bro @@ -1,56 +1,105 @@ +##! Base DNS analysis script which tracks and logs DNS queries along with +##! their responses. + +@load ./consts module DNS; export { - redef enum Log::ID += { DNS }; - + ## The DNS logging stream identifier. + redef enum Log::ID += { LOG }; + + ## The record type which contains the column fields of the DNS log. type Info: record { - ts: time &log; - uid: string &log; - id: conn_id &log; - proto: transport_proto &log; - trans_id: count &log &optional; - query: string &log &optional; - qclass: count &log &optional; - qclass_name: string &log &optional; - qtype: count &log &optional; - qtype_name: string &log &optional; - rcode: count &log &optional; - rcode_name: string &log &optional; - QR: bool &log &default=F; - AA: bool &log &default=F; - TC: bool &log &default=F; - RD: bool &log &default=F; - RA: bool &log &default=F; - Z: count &log &default=0; - TTL: interval &log &optional; - answers: set[string] &log &optional; - - ## This value indicates if this request/response pair is ready to be logged. + ## The earliest time at which a DNS protocol message over the + ## associated connection is observed. + ts: time &log; + ## A unique identifier of the connection over which DNS messages + ## are being transferred. + uid: string &log; + ## The connection's 4-tuple of endpoint addresses/ports. + id: conn_id &log; + ## The transport layer protocol of the connection. + proto: transport_proto &log; + ## A 16 bit identifier assigned by the program that generated the + ## DNS query. Also used in responses to match up replies to + ## outstanding queries. + trans_id: count &log &optional; + ## The domain name that is the subject of the DNS query. + query: string &log &optional; + ## The QCLASS value specifying the class of the query. + qclass: count &log &optional; + ## A descriptive name for the class of the query. + qclass_name: string &log &optional; + ## A QTYPE value specifying the type of the query. + qtype: count &log &optional; + ## A descriptive name for the type of the query. + qtype_name: string &log &optional; + ## The response code value in DNS response messages. + rcode: count &log &optional; + ## A descriptive name for the response code value. + rcode_name: string &log &optional; + ## The Authoritative Answer bit for response messages specifies that + ## the responding name server is an authority for the domain name + ## in the question section. + AA: bool &log &default=F; + ## The Truncation bit specifies that the message was truncated. + TC: bool &log &default=F; + ## The Recursion Desired bit indicates to a name server to recursively + ## purse the query. + RD: bool &log &default=F; + ## The Recursion Available bit in a response message indicates if + ## the name server supports recursive queries. + RA: bool &log &default=F; + ## A reserved field that is currently supposed to be zero in all + ## queries and responses. + Z: count &log &default=0; + ## The set of resource descriptions in answer of the query. + answers: vector of string &log &optional; + ## The caching intervals of the associated RRs described by the + ## ``answers`` field. + TTLs: vector of interval &log &optional; + + ## This value indicates if this request/response pair is ready to be + ## logged. ready: bool &default=F; + ## The total number of resource records in a reply message's answer + ## section. total_answers: count &optional; + ## The total number of resource records in a reply message's answer, + ## authority, and additional sections. total_replies: count &optional; }; - + + ## A record type which tracks the status of DNS queries for a given + ## :bro:type:`connection`. type State: record { ## Indexed by query id, returns Info record corresponding to ## query/response which haven't completed yet. pending: table[count] of Info &optional; - + ## This is the list of DNS responses that have completed based on the ## number of responses declared and the number received. The contents ## of the set are transaction IDs. finished_answers: set[count] &optional; }; - + + ## An event that can be handled to access the :bro:type:`DNS::Info` + ## record as it is sent to the logging framework. global log_dns: event(rec: Info); - + ## This is called by the specific dns_*_reply events with a "reply" which - ## may not represent the full data available from the resource record, but + ## may not represent the full data available from the resource record, but ## it's generally considered a summarization of the response(s). - # TODO: Weirdly enough, if I define this, the locally defined script layer - # event won't trigger any of it's handlers. - #global do_reply: event(c: connection, msg: dns_msg, ans: dns_answer, reply: string); + ## + ## c: The connection record for which to fill in DNS reply data. + ## + ## msg: The DNS message header information for the response. + ## + ## ans: The general information of a RR response. + ## + ## reply: The specific response information according to RR type/class. + global do_reply: event(c: connection, msg: dns_msg, ans: dns_answer, reply: string); } redef record connection += { @@ -59,24 +108,26 @@ redef record connection += { }; # DPD configuration. -redef capture_filters += { +redef capture_filters += { ["dns"] = "port 53", ["mdns"] = "udp and port 5353", ["llmns"] = "udp and port 5355", - ["netbios-ns"] = "udp port 137", + ["netbios-ns"] = "udp port 137", }; -global dns_ports = { 53/udp, 53/tcp, 137/udp, 5353/udp, 5355/udp } &redef; +const dns_ports = { 53/udp, 53/tcp, 137/udp, 5353/udp, 5355/udp }; redef dpd_config += { [ANALYZER_DNS] = [$ports = dns_ports] }; -global dns_udp_ports = { 53/udp, 137/udp, 5353/udp, 5355/udp } &redef; -global dns_tcp_ports = { 53/tcp } &redef; +const dns_udp_ports = { 53/udp, 137/udp, 5353/udp, 5355/udp }; +const dns_tcp_ports = { 53/tcp }; redef dpd_config += { [ANALYZER_DNS_UDP_BINPAC] = [$ports = dns_udp_ports] }; redef dpd_config += { [ANALYZER_DNS_TCP_BINPAC] = [$ports = dns_tcp_ports] }; +redef likely_server_ports += { 53/udp, 53/tcp, 137/udp, 5353/udp, 5355/udp }; + event bro_init() &priority=5 { - Log::create_stream(DNS, [$columns=Info, $ev=log_dns]); + Log::create_stream(DNS::LOG, [$columns=Info, $ev=log_dns]); } function new_session(c: connection, trans_id: count): Info @@ -88,7 +139,7 @@ function new_session(c: connection, trans_id: count): Info state$finished_answers=set(); c$dns_state = state; } - + local info: Info; info$ts = network_time(); info$id = c$id; @@ -101,23 +152,29 @@ function new_session(c: connection, trans_id: count): Info function set_session(c: connection, msg: dns_msg, is_query: bool) { if ( ! c?$dns_state || msg$id !in c$dns_state$pending ) + { c$dns_state$pending[msg$id] = new_session(c, msg$id); - + # Try deleting this transaction id from the set of finished answers. + # Sometimes hosts will reuse ports and transaction ids and this should + # be considered to be a legit scenario (although bad practice). + delete c$dns_state$finished_answers[msg$id]; + } + c$dns = c$dns_state$pending[msg$id]; c$dns$rcode = msg$rcode; c$dns$rcode_name = base_errors[msg$rcode]; - + if ( ! is_query ) { if ( ! c$dns?$total_answers ) c$dns$total_answers = msg$num_answers; - - if ( c$dns?$total_replies && + + if ( c$dns?$total_replies && c$dns$total_replies != msg$num_answers + msg$num_addl + msg$num_auth ) { - event conn_weird("dns_changed_number_of_responses", c, - fmt("The declared number of responses changed from %d to %d", + event conn_weird("dns_changed_number_of_responses", c, + fmt("The declared number of responses changed from %d to %d", c$dns$total_replies, msg$num_answers + msg$num_addl + msg$num_auth)); } @@ -128,27 +185,30 @@ function set_session(c: connection, msg: dns_msg, is_query: bool) } } } - -event do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=5 + +event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=5 { set_session(c, msg, F); - c$dns$AA = msg$AA; - c$dns$RA = msg$RA; - c$dns$TTL = ans$TTL; - if ( ans$answer_type == DNS_ANS ) { + c$dns$AA = msg$AA; + c$dns$RA = msg$RA; + if ( msg$id in c$dns_state$finished_answers ) event conn_weird("dns_reply_seen_after_done", c, ""); - + if ( reply != "" ) { if ( ! c$dns?$answers ) - c$dns$answers = set(); - add c$dns$answers[reply]; + c$dns$answers = vector(); + c$dns$answers[|c$dns$answers|] = reply; + + if ( ! c$dns?$TTLs ) + c$dns$TTLs = vector(); + c$dns$TTLs[|c$dns$TTLs|] = ans$TTL; } - + if ( c$dns?$answers && |c$dns$answers| == c$dns$total_answers ) { add c$dns_state$finished_answers[c$dns$trans_id]; @@ -157,13 +217,12 @@ event do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &pri } } } - -event do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=-5 + +event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=-5 { if ( c$dns$ready ) { - Log::write(DNS, c$dns); - add c$dns_state$finished_answers[c$dns$trans_id]; + Log::write(DNS::LOG, c$dns); # This record is logged and no longer pending. delete c$dns_state$pending[c$dns$trans_id]; } @@ -172,91 +231,94 @@ event do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &pri event dns_request(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count) &priority=5 { set_session(c, msg, T); - + c$dns$RD = msg$RD; c$dns$TC = msg$TC; c$dns$qclass = qclass; c$dns$qclass_name = classes[qclass]; c$dns$qtype = qtype; c$dns$qtype_name = query_types[qtype]; - + # Decode netbios name queries - # Note: I'm ignoring the name type for now. Not sure if this should be + # Note: I'm ignoring the name type for now. Not sure if this should be # worked into the query/response in some fashion. if ( c$id$resp_p == 137/udp ) query = decode_netbios_name(query); c$dns$query = query; - + c$dns$Z = msg$Z; } - + event dns_A_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priority=5 { - event do_reply(c, msg, ans, fmt("%s", a)); + event DNS::do_reply(c, msg, ans, fmt("%s", a)); } - + event dns_TXT_reply(c: connection, msg: dns_msg, ans: dns_answer, str: string) &priority=5 { - event do_reply(c, msg, ans, str); + event DNS::do_reply(c, msg, ans, str); } - -event dns_AAAA_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr, - astr: string) &priority=5 + +event dns_AAAA_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priority=5 { - # TODO: What should we do with astr? - event do_reply(c, msg, ans, fmt("%s", a)); + event DNS::do_reply(c, msg, ans, fmt("%s", a)); } - + +event dns_A6_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priority=5 + { + event DNS::do_reply(c, msg, ans, fmt("%s", a)); + } + event dns_NS_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string) &priority=5 { - event do_reply(c, msg, ans, name); + event DNS::do_reply(c, msg, ans, name); } event dns_CNAME_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string) &priority=5 { - event do_reply(c, msg, ans, name); + event DNS::do_reply(c, msg, ans, name); } event dns_MX_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string, preference: count) &priority=5 { - event do_reply(c, msg, ans, name); + event DNS::do_reply(c, msg, ans, name); } - + event dns_PTR_reply(c: connection, msg: dns_msg, ans: dns_answer, name: string) &priority=5 { - event do_reply(c, msg, ans, name); + event DNS::do_reply(c, msg, ans, name); } - + event dns_SOA_reply(c: connection, msg: dns_msg, ans: dns_answer, soa: dns_soa) &priority=5 { - event do_reply(c, msg, ans, soa$mname); + event DNS::do_reply(c, msg, ans, soa$mname); } event dns_WKS_reply(c: connection, msg: dns_msg, ans: dns_answer) &priority=5 { - event do_reply(c, msg, ans, ""); + event DNS::do_reply(c, msg, ans, ""); } - + event dns_SRV_reply(c: connection, msg: dns_msg, ans: dns_answer) &priority=5 { - event do_reply(c, msg, ans, ""); + event DNS::do_reply(c, msg, ans, ""); } # TODO: figure out how to handle these #event dns_EDNS(c: connection, msg: dns_msg, ans: dns_answer) # { -# +# # } # #event dns_EDNS_addl(c: connection, msg: dns_msg, ans: dns_edns_additional) # { -# +# # } # #event dns_TSIG_addl(c: connection, msg: dns_msg, ans: dns_tsig_additional) # { -# +# # } @@ -270,10 +332,10 @@ event connection_state_remove(c: connection) &priority=-5 { if ( ! c?$dns_state ) return; - - # If Bro is expiring state, we should go ahead and log all unlogged + + # If Bro is expiring state, we should go ahead and log all unlogged # request/response pairs now. for ( trans_id in c$dns_state$pending ) - Log::write(DNS, c$dns_state$pending[trans_id]); + Log::write(DNS::LOG, c$dns_state$pending[trans_id]); } - + diff --git a/scripts/base/protocols/ftp/file-extract.bro b/scripts/base/protocols/ftp/file-extract.bro index 5ebe0ec63c..7cee4995ba 100644 --- a/scripts/base/protocols/ftp/file-extract.bro +++ b/scripts/base/protocols/ftp/file-extract.bro @@ -1,9 +1,12 @@ -##! File extraction for FTP. +##! File extraction support for FTP. + +@load ./main +@load base/utils/files module FTP; export { - ## Pattern of file mime types to extract from FTP entity bodies. + ## Pattern of file mime types to extract from FTP transfers. const extract_file_types = /NO_DEFAULT/ &redef; ## The on-disk prefix for files to be extracted from FTP-data transfers. @@ -11,10 +14,15 @@ export { } redef record Info += { - ## The file handle for the file to be extracted + ## On disk file where it was extracted to. extraction_file: file &log &optional; + ## Indicates if the current command/response pair should attempt to + ## extract the file if a file was transferred. extract_file: bool &default=F; + + ## Internal tracking of the total number of files extracted during this + ## session. num_extracted_files: count &default=0; }; @@ -25,13 +33,11 @@ event file_transferred(c: connection, prefix: string, descr: string, if ( [id$resp_h, id$resp_p] !in ftp_data_expected ) return; - local expected = ftp_data_expected[id$resp_h, id$resp_p]; - local s = expected$state; + local s = ftp_data_expected[id$resp_h, id$resp_p]; if ( extract_file_types in s$mime_type ) { s$extract_file = T; - add s$tags["extracted_file"]; ++s$num_extracted_files; } } @@ -43,8 +49,7 @@ event file_transferred(c: connection, prefix: string, descr: string, if ( [id$resp_h, id$resp_p] !in ftp_data_expected ) return; - local expected = ftp_data_expected[id$resp_h, id$resp_p]; - local s = expected$state; + local s = ftp_data_expected[id$resp_h, id$resp_p]; if ( s$extract_file ) { @@ -62,4 +67,4 @@ event log_ftp(rec: Info) &priority=-10 { delete rec$extraction_file; delete rec$extract_file; - } \ No newline at end of file + } diff --git a/scripts/base/protocols/ftp/main.bro b/scripts/base/protocols/ftp/main.bro index bf32ba3114..e6c0131337 100644 --- a/scripts/base/protocols/ftp/main.bro +++ b/scripts/base/protocols/ftp/main.bro @@ -1,55 +1,76 @@ ##! The logging this script does is primarily focused on logging FTP commands ##! along with metadata. For example, if files are transferred, the argument ##! will take on the full path that the client is at along with the requested -##! file name. -##! -##! TODO: -##! -##! * Handle encrypted sessions correctly (get an example?) +##! file name. + +@load ./utils-commands +@load base/utils/paths +@load base/utils/numbers module FTP; export { - redef enum Log::ID += { FTP }; - + ## The FTP protocol logging stream identifier. + redef enum Log::ID += { LOG }; + + ## List of commands that should have their command/response pairs logged. + const logged_commands = { + "APPE", "DELE", "RETR", "STOR", "STOU", "ACCT" + } &redef; + ## This setting changes if passwords used in FTP sessions are captured or not. const default_capture_password = F &redef; + ## User IDs that can be considered "anonymous". + const guest_ids = { "anonymous", "ftp", "guest" } &redef; + type Info: record { + ## Time when the command was sent. ts: time &log; uid: string &log; id: conn_id &log; + ## User name for the current FTP session. user: string &log &default=""; + ## Password for the current FTP session if captured. password: string &log &optional; + ## Command given by the client. command: string &log &optional; + ## Argument for the command if one is given. arg: string &log &optional; - + + ## Libmagic "sniffed" file type if the command indicates a file transfer. mime_type: string &log &optional; + ## Libmagic "sniffed" file description if the command indicates a file transfer. mime_desc: string &log &optional; + ## Size of the file if the command indicates a file transfer. file_size: count &log &optional; + + ## Reply code from the server in response to the command. reply_code: count &log &optional; + ## Reply message from the server in response to the command. reply_msg: string &log &optional; + ## Arbitrary tags that may indicate a particular attribute of this command. tags: set[string] &log &default=set(); - ## By setting the CWD to '/.', we can indicate that unless something + ## Current working directory that this session is in. By making + ## the default value '/.', we can indicate that unless something ## more concrete is discovered that the existing but unknown ## directory is ok to use. cwd: string &default="/."; + + ## Command that is currently waiting for a response. cmdarg: CmdArg &optional; + ## Queue for commands that have been sent but not yet responded to + ## are tracked here. pending_commands: PendingCmds; - ## This indicates if the session is in active or passive mode. + ## Indicates if the session is in active or passive mode. passive: bool &default=F; - ## This determines if the password will be captured for this request. + ## Determines if the password will be captured for this request. capture_password: bool &default=default_capture_password; }; - - type ExpectedConn: record { - host: addr; - state: Info; - }; - + ## This record is to hold a parsed FTP reply code. For example, for the ## 201 status code, the digits would be parsed as: x->2, y->0, z=>1. type ReplyCode: record { @@ -57,22 +78,12 @@ export { y: count; z: count; }; - - # TODO: add this back in some form. raise a notice again? - #const excessive_filename_len = 250 &redef; - #const excessive_filename_trunc_len = 32 &redef; - - ## These are user IDs that can be considered "anonymous". - const guest_ids = { "anonymous", "ftp", "guest" } &redef; - ## The list of commands that should have their command/response pairs logged. - const logged_commands = { - "APPE", "DELE", "RETR", "STOR", "STOU", "ACCT" - } &redef; - - ## This function splits FTP reply codes into the three constituent + ## Parse FTP reply codes into the three constituent single digit values. global parse_ftp_reply_code: function(code: count): ReplyCode; - + + ## Event that can be handled to access the :bro:type:`FTP::Info` + ## record as it is sent on to the logging framework. global log_ftp: event(rec: Info); } @@ -86,12 +97,14 @@ const ports = { 21/tcp } &redef; redef capture_filters += { ["ftp"] = "port 21" }; redef dpd_config += { [ANALYZER_FTP] = [$ports = ports] }; +redef likely_server_ports += { 21/tcp }; + # Establish the variable for tracking expected connections. -global ftp_data_expected: table[addr, port] of ExpectedConn &create_expire=5mins; +global ftp_data_expected: table[addr, port] of Info &create_expire=5mins; event bro_init() &priority=5 { - Log::create_stream(FTP, [$columns=Info, $ev=log_ftp]); + Log::create_stream(FTP::LOG, [$columns=Info, $ev=log_ftp]); } ## A set of commands where the argument can be expected to refer @@ -152,7 +165,12 @@ function ftp_message(s: Info) local arg = s$cmdarg$arg; if ( s$cmdarg$cmd in file_cmds ) - arg = fmt("ftp://%s%s", s$id$resp_h, build_path_compressed(s$cwd, arg)); + { + if ( is_v4_addr(s$id$resp_h) ) + arg = fmt("ftp://%s%s", s$id$resp_h, build_path_compressed(s$cwd, arg)); + else + arg = fmt("ftp://[%s]%s", s$id$resp_h, build_path_compressed(s$cwd, arg)); + } s$ts=s$cmdarg$ts; s$command=s$cmdarg$cmd; @@ -161,7 +179,7 @@ function ftp_message(s: Info) else s$arg=arg; - Log::write(FTP, s); + Log::write(FTP::LOG, s); } # The MIME and file_size fields are specific to file transfer commands @@ -207,9 +225,7 @@ event ftp_request(c: connection, command: string, arg: string) &priority=5 if ( data$valid ) { c$ftp$passive=F; - - local expected = [$host=id$resp_h, $state=copy(c$ftp)]; - ftp_data_expected[data$h, data$p] = expected; + ftp_data_expected[data$h, data$p] = c$ftp; expect_connection(id$resp_h, data$h, data$p, ANALYZER_FILE, 5mins); } else @@ -259,11 +275,10 @@ event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool) &prior { c$ftp$passive=T; - if ( code == 229 && data$h == 0.0.0.0 ) + if ( code == 229 && data$h == [::] ) data$h = id$resp_h; - local expected = [$host=id$orig_h, $state=c$ftp]; - ftp_data_expected[data$h, data$p] = expected; + ftp_data_expected[data$h, data$p] = c$ftp; expect_connection(id$orig_h, data$h, data$p, ANALYZER_FILE, 5mins); } else @@ -308,9 +323,8 @@ event file_transferred(c: connection, prefix: string, descr: string, local id = c$id; if ( [id$resp_h, id$resp_p] in ftp_data_expected ) { - local expected = ftp_data_expected[id$resp_h, id$resp_p]; - local s = expected$state; - s$mime_type = mime_type; + local s = ftp_data_expected[id$resp_h, id$resp_p]; + s$mime_type = split1(mime_type, /;/)[1]; s$mime_desc = descr; } } diff --git a/scripts/base/protocols/ftp/utils-commands.bro b/scripts/base/protocols/ftp/utils-commands.bro index 40dacf9b66..ddfad3e08d 100644 --- a/scripts/base/protocols/ftp/utils-commands.bro +++ b/scripts/base/protocols/ftp/utils-commands.bro @@ -2,14 +2,22 @@ module FTP; export { type CmdArg: record { + ## Time when the command was sent. ts: time; + ## Command. cmd: string &default=""; + ## Argument for the command if one was given. arg: string &default=""; + ## Counter to track how many commands have been executed. seq: count &default=0; }; - + + ## Structure for tracking pending commands in the event that the client + ## sends a large number of commands before the server has a chance to + ## reply. type PendingCmds: table[count] of CmdArg; - + + ## Possible response codes for a wide variety of FTP commands. const cmd_reply_code: set[string, count] = { # According to RFC 959 ["", [120, 220, 421]], diff --git a/scripts/base/protocols/http/file-extract.bro b/scripts/base/protocols/http/file-extract.bro index 24ee1d8b93..466d18c3b4 100644 --- a/scripts/base/protocols/http/file-extract.bro +++ b/scripts/base/protocols/http/file-extract.bro @@ -1,43 +1,47 @@ ##! Extracts the items from HTTP traffic, one per file. At this time only ##! the message body from the server can be extracted with this script. +@load ./main +@load ./file-ident +@load base/utils/files + module HTTP; export { - ## Pattern of file mime types to extract from HTTP entity bodies. + ## Pattern of file mime types to extract from HTTP response entity bodies. const extract_file_types = /NO_DEFAULT/ &redef; ## The on-disk prefix for files to be extracted from HTTP entity bodies. const extraction_prefix = "http-item" &redef; redef record Info += { - ## This field can be set per-connection to determine if the entity body - ## will be extracted. It must be set to T on or before the first - ## entity_body_data event. - extracting_file: bool &default=F; - - ## This is the holder for the file handle as the file is being written - ## to disk. + ## On-disk file where the response body was extracted to. extraction_file: file &log &optional; - }; - - redef record State += { - entity_bodies: count &default=0; + + ## Indicates if the response body is to be extracted or not. Must be + ## set before or by the first :bro:id:`http_entity_data` event for the + ## content. + extract_file: bool &default=F; }; } -event http_entity_data(c: connection, is_orig: bool, length: count, data: string) &priority=5 +event http_entity_data(c: connection, is_orig: bool, length: count, data: string) &priority=-5 { # Client body extraction is not currently supported in this script. - if ( is_orig || ! c$http$first_chunk ) return; + if ( is_orig ) + return; if ( c$http$first_chunk ) { if ( c$http?$mime_type && extract_file_types in c$http$mime_type ) { - c$http$extracting_file = T; - local suffix = fmt("%s_%d.dat", is_orig ? "orig" : "resp", ++c$http_state$entity_bodies); + c$http$extract_file = T; + } + + if ( c$http$extract_file ) + { + local suffix = fmt("%s_%d.dat", is_orig ? "orig" : "resp", c$http_state$current_response); local fname = generate_extraction_filename(extraction_prefix, c, suffix); c$http$extraction_file = open(fname); @@ -45,12 +49,12 @@ event http_entity_data(c: connection, is_orig: bool, length: count, data: string } } - if ( c$http$extracting_file ) + if ( c$http?$extraction_file ) print c$http$extraction_file, data; } event http_end_entity(c: connection, is_orig: bool) { - if ( c$http$extracting_file ) + if ( c$http?$extraction_file ) close(c$http$extraction_file); } diff --git a/scripts/base/protocols/http/file-hash.bro b/scripts/base/protocols/http/file-hash.bro index 26f8abf51a..7e8e5cceaf 100644 --- a/scripts/base/protocols/http/file-hash.bro +++ b/scripts/base/protocols/http/file-hash.bro @@ -1,5 +1,7 @@ ##! Calculate hashes for HTTP body transfers. +@load ./file-ident + module HTTP; export { @@ -9,7 +11,8 @@ export { }; redef record Info += { - ## The MD5 sum for a file transferred over HTTP will be stored here. + ## MD5 sum for a file transferred over HTTP calculated from the + ## response body. md5: string &log &optional; ## This value can be set per-transfer to determine per request @@ -17,8 +20,8 @@ export { ## set to T at the time of or before the first chunk of body data. calc_md5: bool &default=F; - ## This boolean value indicates if an MD5 sum is currently being - ## calculated for the current file transfer. + ## Indicates if an MD5 sum is being calculated for the current + ## request/response pair. calculating_md5: bool &default=F; }; @@ -52,14 +55,11 @@ event http_entity_data(c: connection, is_orig: bool, length: count, data: string ## incorrect anyway. event content_gap(c: connection, is_orig: bool, seq: count, length: count) &priority=5 { - if ( is_orig || ! c?$http ) return; - + if ( is_orig || ! c?$http || ! c$http$calculating_md5 ) return; + set_state(c, F, is_orig); - if ( c$http$calculating_md5 ) - { - c$http$calculating_md5 = F; - md5_hash_finish(c$id); - } + c$http$calculating_md5 = F; + md5_hash_finish(c$id); } ## When the file finishes downloading, finish the hash and generate a notice. diff --git a/scripts/base/protocols/http/file-ident.bro b/scripts/base/protocols/http/file-ident.bro index 082adf75d3..f2cb9d19ac 100644 --- a/scripts/base/protocols/http/file-ident.bro +++ b/scripts/base/protocols/http/file-ident.bro @@ -1,5 +1,9 @@ -##! This script is involved in the identification of file types in HTTP -##! response bodies. +##! Identification of file types in HTTP response bodies with file content sniffing. + +@load base/frameworks/signatures +@load base/frameworks/notice +@load ./main +@load ./utils # Add the magic number signatures to the core signature set. redef signature_files += "base/protocols/http/file-ident.sig"; @@ -10,30 +14,32 @@ module HTTP; export { redef enum Notice::Type += { - # This notice is thrown when the file extension doesn't - # seem to match the file contents. + ## Indicates when the file extension doesn't seem to match the file contents. Incorrect_File_Type, }; redef record Info += { - ## This will record the mime_type identified. + ## Mime type of response body identified by content sniffing. mime_type: string &log &optional; - ## This indicates that no data of the current file transfer has been + ## Indicates that no data of the current file transfer has been ## seen yet. After the first :bro:id:`http_entity_data` event, it - ## will be set to T. + ## will be set to F. first_chunk: bool &default=T; }; - - redef enum Tags += { - IDENTIFIED_FILE - }; - # Create regexes that *should* in be in the urls for specifics mime types. - # Notices are thrown if the pattern doesn't match the url for the file type. + ## Mapping between mime types and regular expressions for URLs + ## The :bro:enum:`HTTP::Incorrect_File_Type` notice is generated if the pattern + ## doesn't match the mime type that was discovered. const mime_types_extensions: table[string] of pattern = { ["application/x-dosexec"] = /\.([eE][xX][eE]|[dD][lL][lL])/, } &redef; + + ## A pattern for filtering out :bro:enum:`HTTP::Incorrect_File_Type` urls + ## that are not noteworthy before a notice is created. Each + ## pattern added should match the complete URL (the matched URLs include + ## "http://" at the beginning). + const ignored_incorrect_file_type_urls = /^$/ &redef; } event signature_match(state: signature_state, msg: string, data: string) &priority=5 @@ -54,6 +60,10 @@ event signature_match(state: signature_state, msg: string, data: string) &priori c$http?$uri && mime_types_extensions[msg] !in c$http$uri ) { local url = build_url_http(c$http); + + if ( url == ignored_incorrect_file_type_urls ) + return; + local message = fmt("%s %s %s", msg, c$http$method, url); NOTICE([$note=Incorrect_File_Type, $msg=message, diff --git a/scripts/base/protocols/http/main.bro b/scripts/base/protocols/http/main.bro index 8cd80bde5f..6571548145 100644 --- a/scripts/base/protocols/http/main.bro +++ b/scripts/base/protocols/http/main.bro @@ -1,11 +1,18 @@ +##! Implements base functionality for HTTP analysis. The logging model is +##! to log request/response pairs and all relevant metadata together in +##! a single record. + +@load base/utils/numbers +@load base/utils/files module HTTP; export { - redef enum Log::ID += { HTTP }; + redef enum Log::ID += { LOG }; ## Indicate a type of attack or compromise in the record to be logged. type Tags: enum { + ## Placeholder. EMPTY }; @@ -13,55 +20,69 @@ export { const default_capture_password = F &redef; type Info: record { - ts: time &log; - uid: string &log; - id: conn_id &log; - ## The verb used in the HTTP request (GET, POST, HEAD, etc.). - method: string &log &optional; - ## The value of the HOST header. - host: string &log &optional; - ## The URI used in the request. - uri: string &log &optional; - ## The value of the "referer" header. The comment is deliberately + ## Timestamp for when the request happened. + ts: time &log; + uid: string &log; + id: conn_id &log; + ## Represents the pipelined depth into the connection of this + ## request/response transaction. + trans_depth: count &log; + ## Verb used in the HTTP request (GET, POST, HEAD, etc.). + method: string &log &optional; + ## Value of the HOST header. + host: string &log &optional; + ## URI used in the request. + uri: string &log &optional; + ## Value of the "referer" header. The comment is deliberately ## misspelled like the standard declares, but the name used here is ## "referrer" spelled correctly. - referrer: string &log &optional; - ## The value of the User-Agent header from the client. - user_agent: string &log &optional; - ## The value of the Content-Length header from the client. - request_content_length: count &log &optional; - ## The value of the Content-Length header from the server. - response_content_length: count &log &optional; - ## The status code returned by the server. - status_code: count &log &optional; - ## The status message returned by the server. - status_msg: string &log &optional; - ## The filename given in the Content-Disposition header - ## sent by the server. - filename: string &log &optional; - ## This is a set of indicators of various attributes discovered and + referrer: string &log &optional; + ## Value of the User-Agent header from the client. + user_agent: string &log &optional; + ## Actual uncompressed content size of the data transferred from + ## the client. + request_body_len: count &log &default=0; + ## Actual uncompressed content size of the data transferred from + ## the server. + response_body_len: count &log &default=0; + ## Status code returned by the server. + status_code: count &log &optional; + ## Status message returned by the server. + status_msg: string &log &optional; + ## Last seen 1xx informational reply code returned by the server. + info_code: count &log &optional; + ## Last seen 1xx informational reply message returned by the server. + info_msg: string &log &optional; + ## Filename given in the Content-Disposition header sent by the server. + filename: string &log &optional; + ## A set of indicators of various attributes discovered and ## related to a particular request/response pair. tags: set[Tags] &log; - ## The username if basic-auth is performed for the request. - username: string &log &optional; - ## The password if basic-auth is performed for the request. - password: string &log &optional; + ## Username if basic-auth is performed for the request. + username: string &log &optional; + ## Password if basic-auth is performed for the request. + password: string &log &optional; - ## This determines if the password will be captured for this request. - capture_password: bool &default=default_capture_password; + ## Determines if the password will be captured for this request. + capture_password: bool &default=default_capture_password; ## All of the headers that may indicate if the request was proxied. - proxied: set[string] &log &optional; + proxied: set[string] &log &optional; }; + ## Structure to maintain state for an HTTP connection with multiple + ## requests and responses. type State: record { + ## Pending requests. pending: table[count] of Info; - current_response: count &default=0; + ## Current request in the pending queue. current_request: count &default=0; + ## Current response in the pending queue. + current_response: count &default=0; }; - ## The list of HTTP headers typically used to indicate a proxied request. + ## A list of HTTP headers typically used to indicate proxied requests. const proxy_headers: set[string] = { "FORWARDED", "X-FORWARDED-FOR", @@ -72,6 +93,8 @@ export { "PROXY-CONNECTION", } &redef; + ## Event that can be handled to access the HTTP record as it is sent on + ## to the logging framework. global log_http: event(rec: Info); } @@ -84,7 +107,7 @@ redef record connection += { # Initialize the HTTP logging stream. event bro_init() &priority=5 { - Log::create_stream(HTTP, [$columns=Info, $ev=log_http]); + Log::create_stream(HTTP::LOG, [$columns=Info, $ev=log_http]); } # DPD configuration. @@ -99,12 +122,25 @@ redef capture_filters += { ["http"] = "tcp and port (80 or 81 or 631 or 1080 or 3138 or 8000 or 8080 or 8888)" }; +redef likely_server_ports += { + 80/tcp, 81/tcp, 631/tcp, 1080/tcp, 3138/tcp, + 8000/tcp, 8080/tcp, 8888/tcp, +}; + +function code_in_range(c: count, min: count, max: count) : bool + { + return c >= min && c <= max; + } + function new_http_session(c: connection): Info { local tmp: Info; tmp$ts=network_time(); tmp$uid=c$uid; tmp$id=c$id; + # $current_request is set prior to the Info record creation so we + # can use the value directly here. + tmp$trans_depth = c$http_state$current_request; return tmp; } @@ -115,7 +151,7 @@ function set_state(c: connection, request: bool, is_orig: bool) local s: State; c$http_state = s; } - + # These deal with new requests and responses. if ( request || c$http_state$current_request !in c$http_state$pending ) c$http_state$pending[c$http_state$current_request] = new_http_session(c); @@ -152,11 +188,21 @@ event http_reply(c: connection, version: string, code: count, reason: string) &p c$http_state = s; } - ++c$http_state$current_response; + # If the last response was an informational 1xx, we're still expecting + # the real response to the request, so don't create a new Info record yet. + if ( c$http_state$current_response !in c$http_state$pending || + (c$http_state$pending[c$http_state$current_response]?$status_code && + ! code_in_range(c$http_state$pending[c$http_state$current_response]$status_code, 100, 199)) ) + ++c$http_state$current_response; set_state(c, F, F); c$http$status_code = code; c$http$status_msg = reason; + if ( code_in_range(code, 100, 199) ) + { + c$http$info_code = code; + c$http$info_msg = reason; + } } event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=5 @@ -167,24 +213,21 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) &pr { if ( name == "REFERER" ) c$http$referrer = value; - + else if ( name == "HOST" ) # The split is done to remove the occasional port value that shows up here. c$http$host = split1(value, /:/)[1]; - else if ( name == "CONTENT-LENGTH" ) - c$http$request_content_length = extract_count(value); - else if ( name == "USER-AGENT" ) c$http$user_agent = value; - + else if ( name in proxy_headers ) { if ( ! c$http?$proxied ) c$http$proxied = set(); add c$http$proxied[fmt("%s -> %s", name, value)]; } - + else if ( name == "AUTHORIZATION" ) { if ( /^[bB][aA][sS][iI][cC] / in value ) @@ -199,21 +242,18 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) &pr } else { - c$http$username = ""; + c$http$username = fmt(" (%s)", value); if ( c$http$capture_password ) c$http$password = userpass; } } } - - } + else # server headers { - if ( name == "CONTENT-LENGTH" ) - c$http$response_content_length = extract_count(value); - else if ( name == "CONTENT-DISPOSITION" && - /[fF][iI][lL][eE][nN][aA][mM][eE]/ in value ) + if ( name == "CONTENT-DISPOSITION" && + /[fF][iI][lL][eE][nN][aA][mM][eE]/ in value ) c$http$filename = extract_filename_from_content_disposition(value); } } @@ -221,6 +261,11 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) &pr event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) &priority = 5 { set_state(c, F, is_orig); + + if ( is_orig ) + c$http$request_body_len = stat$body_length; + else + c$http$response_body_len = stat$body_length; } event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) &priority = -5 @@ -228,19 +273,26 @@ event http_message_done(c: connection, is_orig: bool, stat: http_message_stat) & # The reply body is done so we're ready to log. if ( ! is_orig ) { - Log::write(HTTP, c$http); - delete c$http_state$pending[c$http_state$current_response]; + # If the response was an informational 1xx, we're still expecting + # the real response later, so we'll continue using the same record. + if ( ! (c$http?$status_code && code_in_range(c$http$status_code, 100, 199)) ) + { + Log::write(HTTP::LOG, c$http); + delete c$http_state$pending[c$http_state$current_response]; + } } } -event connection_state_remove(c: connection) +event connection_state_remove(c: connection) &priority=-5 { # Flush all pending but incomplete request/response pairs. if ( c?$http_state ) { for ( r in c$http_state$pending ) { - Log::write(HTTP, c$http_state$pending[r]); + # We don't use pending elements at index 0. + if ( r == 0 ) next; + Log::write(HTTP::LOG, c$http_state$pending[r]); } } } diff --git a/scripts/base/protocols/http/partial-content.bro b/scripts/base/protocols/http/partial-content.bro deleted file mode 100644 index 130cc0db28..0000000000 --- a/scripts/base/protocols/http/partial-content.bro +++ /dev/null @@ -1,94 +0,0 @@ -##! This script makes it possible for the HTTP analysis scripts to analyze -##! the apparent normal case of "206 Partial Content" responses. -##! -##! This script doesn't work yet and isn't loaded by default. - -module HTTP; - -export { - redef enum Notice::Type += { - Partial_Content_Out_Of_Order, - }; - - type Range: record { - from: count; - to: count; - } &log; - - redef record Info += { - current_range: count &default=0; - request_ranges: vector of Range &optional; - response_range: Range &optional; - }; - - ## Index is client IP address, server IP address, and URL being requested. The - ## URL is tracked as part of the index in case multiple partial content segmented - ## files are being transferred simultaneously between the server and client. - global partial_content_files: table[addr, addr, string] of Info &read_expire=5mins &redef; -} - -event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=2 - { - local parts: table[count] of string; - if ( is_orig && name == "RANGE" ) - { - # Example --> Range: bytes=1-1,2336-4951 - parts = split(value, /[=]/); - if ( 2 in parts ) - { - local ranges = split(parts[2], /,/); - for ( i in ranges ) - { - if ( ! c$http?$request_ranges ) - c$http$request_ranges = vector(); - parts = split(ranges[i], /-/); - local r: Range = [$from=extract_count(parts[1]), $to=extract_count(parts[2])]; - print r; - c$http$request_ranges[|c$http$request_ranges|] = r; - } - } - } - else if ( ! is_orig && name == "CONTENT-RANGE" ) - { - # Example --> Content-Range: bytes 2336-4951/489528 - parts = split(value, /[0-9]*/); - - c$http$response_range = [$from=extract_count(parts[2]), $to=extract_count(parts[4])]; - - } - } - -event http_reply(c: connection, version: string, code: count, reason: string) &priority=5 - { - if ( code != 206 || ! c$http?$request_ranges ) - return; - - local url = build_url(c$http); - if ( [c$id$orig_h, c$id$resp_h, url] !in partial_content_files ) - { - partial_content_files[c$id$orig_h, c$id$resp_h, url] = copy(c$http); - } - } - -event http_entity_data(c: connection, is_orig: bool, length: count, data: string) - { - if ( is_orig || c$http$status_code != 206 || ! c$http?$request_ranges ) - return; - - local url = build_url(c$http); - local http = partial_content_files[c$id$orig_h, c$id$resp_h, url]; - local range = http$request_ranges[http$current_range]; - - print http$current_range; - if ( http$current_range == 0 && - c$http$response_range$from == 0 ) - { - print "correct file beginning!"; - } - } - -event http_end_entity(c: connection, is_orig: bool) - { - print "end entity"; - ++c$http$current_range; - } diff --git a/scripts/base/protocols/http/utils.bro b/scripts/base/protocols/http/utils.bro index 716b1c608b..0f2666fade 100644 --- a/scripts/base/protocols/http/utils.bro +++ b/scripts/base/protocols/http/utils.bro @@ -1,10 +1,35 @@ ##! Utilities specific for HTTP processing. +@load ./main + module HTTP; export { + ## Given a string containing a series of key-value pairs separated by "=", + ## this function can be used to parse out all of the key names. + ## + ## data: The raw data, such as a URL or cookie value. + ## + ## kv_splitter: A regular expression representing the separator between + ## key-value pairs. + ## + ## Returns: A vector of strings containing the keys. global extract_keys: function(data: string, kv_splitter: pattern): string_vec; + + ## Creates a URL from an :bro:type:`HTTP::Info` record. This should handle + ## edge cases such as proxied requests appropriately. + ## + ## rec: An :bro:type:`HTTP::Info` record. + ## + ## Returns: A URL, not prefixed by "http://". global build_url: function(rec: Info): string; + + ## Creates a URL from an :bro:type:`HTTP::Info` record. This should handle + ## edge cases such as proxied requests appropriately. + ## + ## rec: An :bro:type:`HTTP::Info` record. + ## + ## Returns: A URL prefixed with "http://". global build_url_http: function(rec: Info): string; } diff --git a/scripts/base/protocols/irc/dcc-send.bro b/scripts/base/protocols/irc/dcc-send.bro index 1b8dc67c25..d07a0edf5a 100644 --- a/scripts/base/protocols/irc/dcc-send.bro +++ b/scripts/base/protocols/irc/dcc-send.bro @@ -5,30 +5,35 @@ ##! but that connection will actually be between B and C which could be ##! analyzed on a different worker. ##! -##! Example line from IRC server indicating that the DCC SEND is about to start: -##! PRIVMSG my_nick :^ADCC SEND whateverfile.zip 3640061780 1026 41709^A + +# Example line from IRC server indicating that the DCC SEND is about to start: +# PRIVMSG my_nick :^ADCC SEND whateverfile.zip 3640061780 1026 41709^A + +@load ./main +@load base/utils/files module IRC; export { - redef enum Tag += { EXTRACTED_FILE }; - ## Pattern of file mime types to extract from IRC DCC file transfers. const extract_file_types = /NO_DEFAULT/ &redef; - ## The on-disk prefix for files to be extracted from IRC DCC file transfers. + ## On-disk prefix for files to be extracted from IRC DCC file transfers. const extraction_prefix = "irc-dcc-item" &redef; redef record Info += { - dcc_file_name: string &log &optional; - dcc_file_size: count &log &optional; - dcc_mime_type: string &log &optional; + ## DCC filename requested. + dcc_file_name: string &log &optional; + ## Size of the DCC transfer as indicated by the sender. + dcc_file_size: count &log &optional; + ## Sniffed mime type of the file. + dcc_mime_type: string &log &optional; ## The file handle for the file to be extracted - extraction_file: file &log &optional; + extraction_file: file &log &optional; - ## A boolean to indicate if the current file transfer should be extraced. - extract_file: bool &default=F; + ## A boolean to indicate if the current file transfer should be extracted. + extract_file: bool &default=F; ## The count of the number of file that have been extracted during the session. num_extracted_files: count &default=0; @@ -51,8 +56,10 @@ event file_transferred(c: connection, prefix: string, descr: string, if ( extract_file_types == irc$dcc_mime_type ) { irc$extract_file = T; - add irc$tags[EXTRACTED_FILE]; + } + if ( irc$extract_file ) + { local suffix = fmt("%d.dat", ++irc$num_extracted_files); local fname = generate_extraction_filename(extraction_prefix, c, suffix); irc$extraction_file = open(fname); @@ -70,10 +77,10 @@ event file_transferred(c: connection, prefix: string, descr: string, local tmp = irc$command; irc$command = "DCC"; - Log::write(IRC, irc); + Log::write(IRC::LOG, irc); irc$command = tmp; - if ( irc$extract_file && irc?$extraction_file ) + if ( irc?$extraction_file ) set_contents_file(id, CONTENTS_RESP, irc$extraction_file); # Delete these values in case another DCC transfer @@ -96,7 +103,7 @@ event irc_dcc_message(c: connection, is_orig: bool, return; c$irc$dcc_file_name = argument; c$irc$dcc_file_size = size; - local p = to_port(dest_port, tcp); + local p = count_to_port(dest_port, tcp); expect_connection(to_addr("0.0.0.0"), address, p, ANALYZER_FILE, 5 min); dcc_expected_transfers[address, p] = c$irc; } diff --git a/scripts/base/protocols/irc/main.bro b/scripts/base/protocols/irc/main.bro index c394d8f0c6..2bf2a9bbb9 100644 --- a/scripts/base/protocols/irc/main.bro +++ b/scripts/base/protocols/irc/main.bro @@ -1,50 +1,56 @@ -##! This is the script that implements the core IRC analysis support. It only -##! logs a very limited subset of the IRC protocol by default. The points -##! that it logs at are NICK commands, USER commands, and JOIN commands. It -##! log various bits of meta data as indicated in the :bro:type:`Info` record -##! along with the command at the command arguments. +##! Implements the core IRC analysis support. The logging model is to log +##! IRC commands along with the associated response and some additional +##! metadata about the connection if it's available. module IRC; export { - redef enum Log::ID += { IRC }; - - type Tag: enum { - EMPTY - }; + + redef enum Log::ID += { LOG }; type Info: record { + ## Timestamp when the command was seen. ts: time &log; uid: string &log; id: conn_id &log; + ## Nick name given for the connection. nick: string &log &optional; + ## User name given for the connection. user: string &log &optional; - channels: set[string] &log &optional; - + + ## Command given by the client. command: string &log &optional; + ## Value for the command given by the client. value: string &log &optional; + ## Any additional data for the command. addl: string &log &optional; - tags: set[Tag] &log; }; + ## Event that can be handled to access the IRC record as it is sent on + ## to the logging framework. global irc_log: event(rec: Info); } redef record connection += { + ## IRC session information. irc: Info &optional; }; # Some common IRC ports. redef capture_filters += { ["irc-6666"] = "port 6666" }; redef capture_filters += { ["irc-6667"] = "port 6667" }; +redef capture_filters += { ["irc-6668"] = "port 6668" }; +redef capture_filters += { ["irc-6669"] = "port 6669" }; # DPD configuration. -global irc_ports = { 6666/tcp, 6667/tcp } &redef; +const irc_ports = { 6666/tcp, 6667/tcp, 6668/tcp, 6669/tcp }; redef dpd_config += { [ANALYZER_IRC] = [$ports = irc_ports] }; +redef likely_server_ports += { 6666/tcp, 6667/tcp, 6668/tcp, 6669/tcp }; + event bro_init() &priority=5 { - Log::create_stream(IRC, [$columns=Info, $ev=irc_log]); + Log::create_stream(IRC::LOG, [$columns=Info, $ev=irc_log]); } function new_session(c: connection): Info @@ -78,7 +84,7 @@ event irc_nick_message(c: connection, is_orig: bool, who: string, newnick: strin { if ( is_orig ) { - Log::write(IRC, c$irc); + Log::write(IRC::LOG, c$irc); c$irc$nick = newnick; } } @@ -98,7 +104,7 @@ event irc_user_message(c: connection, is_orig: bool, user: string, host: string, { if ( is_orig ) { - Log::write(IRC, c$irc); + Log::write(IRC::LOG, c$irc); c$irc$user = user; } } @@ -118,7 +124,7 @@ event irc_join_message(c: connection, is_orig: bool, info_list: irc_join_list) & { c$irc$value = l$channel; c$irc$addl = (l$password != "" ? fmt(" with channel key: '%s'", l$password) : ""); - Log::write(IRC, c$irc); + Log::write(IRC::LOG, c$irc); } } } diff --git a/scripts/base/protocols/mime/__load__.bro b/scripts/base/protocols/mime/__load__.bro deleted file mode 100644 index 36e9f16426..0000000000 --- a/scripts/base/protocols/mime/__load__.bro +++ /dev/null @@ -1,4 +0,0 @@ -@load protocols/mime/base -@load protocols/mime/file-ident -@load protocols/mime/file-extract -@load protocols/mime/file-hash diff --git a/scripts/base/protocols/mime/base.bro b/scripts/base/protocols/mime/base.bro deleted file mode 100644 index df495387d7..0000000000 --- a/scripts/base/protocols/mime/base.bro +++ /dev/null @@ -1,101 +0,0 @@ -##! The mime script does analysis of MIME encoded messages seen in certain -##! protocols (only SMTP and POP3 at the moment). - -@load base/utils/strings - -module MIME; - -export { - redef enum Log::ID += { MIME }; - - # Let's assume for now that nothing transferring files using - # MIME attachments is multiplexing for simplicity's sake. - # We can make the assumption that one connection == one file (at a time) - - type Info: record { - ## This is the timestamp of when the MIME content transfer began. - ts: time &log; - uid: string &log; - id: conn_id &log; - ## The application layer protocol over which the transfer was seen. - app_protocol: string &log &optional; - ## The filename seen in the Content-Disposition header. - filename: string &log &optional; - ## Track how many byte of the MIME encoded file have been seen. - content_len: count &log &default=0; - }; - - type State: record { - ## Track the number of MIME encoded files transferred during this session. - level: count &default=0; - }; - - global log_mime: event(rec: Info); -} - -redef record connection += { - mime: Info &optional; - mime_state: State &optional; -}; - -event bro_init() - { - Log::create_stream(MIME, [$columns=Info, $ev=log_mime]); - } - -function new_mime_session(c: connection): Info - { - local info: Info; - - info$ts=network_time(); - info$uid=c$uid; - info$id=c$id; - return info; - } - -function set_session(c: connection, new_entity: bool) - { - if ( ! c?$mime_state ) - c$mime_state = []; - - if ( ! c?$mime || new_entity ) - c$mime = new_mime_session(c); - } - -event mime_begin_entity(c: connection) &priority=10 - { - set_session(c, T); - - ++c$mime_state$level; - - if ( |c$service| > 0 ) - c$mime$app_protocol = join_string_set(c$service, ","); - } - -# This has priority -10 because other handlers need to know the current -# content_len before it's updated by this handler. -event mime_segment_data(c: connection, length: count, data: string) &priority=-10 - { - c$mime$content_len = c$mime$content_len + length; - } - -event mime_one_header(c: connection, h: mime_header_rec) - { - if ( h$name == "CONTENT-DISPOSITION" && - /[fF][iI][lL][eE][nN][aA][mM][eE]/ in h$value ) - c$mime$filename = sub(h$value, /^.*[fF][iI][lL][eE][nN][aA][mM][eE]=/, ""); - } - -event mime_end_entity(c: connection) &priority=-5 - { - # This check and the delete below are just to cope with a bug where - # mime_end_entity can be generated multiple times for the same event. - if ( ! c?$mime ) - return; - - # Don't log anything if there wasn't any content. - if ( c$mime$content_len > 0 ) - Log::write(MIME, c$mime); - - delete c$mime; - } diff --git a/scripts/base/protocols/mime/file-extract.bro b/scripts/base/protocols/mime/file-extract.bro deleted file mode 100644 index 4e25f19d10..0000000000 --- a/scripts/base/protocols/mime/file-extract.bro +++ /dev/null @@ -1,62 +0,0 @@ -@load ./file-ident -@load base/utils/files - -module MIME; - -export { - ## Pattern of file mime types to extract from MIME bodies. - const extract_file_types = /NO_DEFAULT/ &redef; - - ## The on-disk prefix for files to be extracted from MIME entity bodies. - const extraction_prefix = "mime-item" &redef; - - redef record Info += { - ## Optionally write the file to disk. Must be set prior to first - ## data chunk being seen in an event. - extract_file: bool &default=F; - - ## Store the file handle here for the file currently being extracted. - extraction_file: file &log &optional; - }; - - redef record State += { - ## Store a count of the number of files that have been transferred in - ## this conversation to create unique file names on disk. - num_extracted_files: count &default=0; - }; -} - -event mime_segment_data(c: connection, length: count, data: string) &priority=5 - { - if ( extract_file_types in c$mime$mime_type ) - c$mime$extract_file = T; - } - -event mime_segment_data(c: connection, length: count, data: string) &priority=3 - { - if ( c$mime$extract_file && c$mime$content_len == 0 ) - { - local suffix = fmt("%d.dat", ++c$mime_state$num_extracted_files); - local fname = generate_extraction_filename(extraction_prefix, c, suffix); - c$mime$extraction_file = open(fname); - enable_raw_output(c$mime$extraction_file); - } - } - -event mime_segment_data(c: connection, length: count, data: string) &priority=-5 - { - if ( c$mime$extract_file && c$mime?$extraction_file ) - print c$mime$extraction_file, data; - } - -event mime_end_entity(c: connection) &priority=-3 - { - # TODO: this check is only due to a bug in mime_end_entity that - # causes the event to be generated twice for the same real event. - if ( ! c?$mime ) - return; - - if ( c$mime?$extraction_file ) - close(c$mime$extraction_file); - } - diff --git a/scripts/base/protocols/mime/file-hash.bro b/scripts/base/protocols/mime/file-hash.bro deleted file mode 100644 index 5139810b8e..0000000000 --- a/scripts/base/protocols/mime/file-hash.bro +++ /dev/null @@ -1,78 +0,0 @@ -@load ./file-ident - -module MIME; - -export { - redef enum Notice::Type += { - ## Indicates that an MD5 sum was calculated for a MIME message. - MD5, - }; - - redef record Info += { - ## The calculated MD5 sum for the MIME entity. - md5: string &log &optional; - - ## Optionally calculate the file's MD5 sum. Must be set prior to the - ## first data chunk being see in an event. - calc_md5: bool &default=F; - - ## This boolean value indicates if an MD5 sum is being calculated - ## for the current file transfer. - calculating_md5: bool &default=F; - }; - - ## Generate MD5 sums for these filetypes. - const generate_md5 = /application\/x-dosexec/ # Windows and DOS executables - | /application\/x-executable/ # *NIX executable binary - &redef; -} - -event mime_segment_data(c: connection, length: count, data: string) &priority=-5 - { - if ( ! c?$mime ) return; - - if ( c$mime$content_len == 0 ) - { - if ( generate_md5 in c$mime$mime_type ) - c$mime$calc_md5 = T; - - if ( c$mime$calc_md5 ) - { - c$mime$calculating_md5 = T; - md5_hash_init(c$id); - } - } - - if ( c$mime$calculating_md5 ) - md5_hash_update(c$id, data); - } - -## In the event of a content gap during the MIME transfer, detect the state for -## the MD5 sum calculation and stop calculating the MD5 since it would be -## incorrect anyway. -event content_gap(c: connection, is_orig: bool, seq: count, length: count) &priority=5 - { - if ( is_orig || ! c?$mime ) return; - - if ( c$mime$calculating_md5 ) - { - c$mime$calculating_md5 = F; - md5_hash_finish(c$id); - } - } - -event mime_end_entity(c: connection) &priority=-3 - { - # TODO: this check is only due to a bug in mime_end_entity that - # causes the event to be generated twice for the same real event. - if ( ! c?$mime ) - return; - - if ( c$mime$calculating_md5 ) - { - c$mime$md5 = md5_hash_finish(c$id); - - NOTICE([$note=MD5, $msg=fmt("Calculated a hash for a MIME entity from %s", c$id$orig_h), - $sub=c$mime$md5, $conn=c]); - } - } diff --git a/scripts/base/protocols/mime/file-ident.bro b/scripts/base/protocols/mime/file-ident.bro deleted file mode 100644 index 346fde1bba..0000000000 --- a/scripts/base/protocols/mime/file-ident.bro +++ /dev/null @@ -1,16 +0,0 @@ -@load ./base - -module MIME; - -export { - redef record Info += { - ## Sniffed MIME type for the transfer. - mime_type: string &log &optional; - }; -} - -event mime_segment_data(c: connection, length: count, data: string) &priority=7 - { - if ( c$mime$content_len == 0 ) - c$mime$mime_type = split1(identify_data(data, T), /;/)[1]; - } diff --git a/scripts/base/protocols/rpc/base.bro b/scripts/base/protocols/rpc/base.bro deleted file mode 100644 index 936684a728..0000000000 --- a/scripts/base/protocols/rpc/base.bro +++ /dev/null @@ -1,147 +0,0 @@ - -# -# Log RPC request and reply messages. Does not in itself start/activate -# an analyzer. You need to load portmap and/or NFS for that -# -# TODO: maybe automatically load portmap, add a generic RPC analyzer and -# use expect connection, so that we can see RPC request/replies for RPC -# programs for which we don't have an analyzer. -# - -module RPC; - -export { - global log_file = open_log_file("rpc") &redef; - # whether to match request to replies on the policy layer. - # (will report on rexmit and missing requests or replies) - global track_requests_replies = T &redef; -} - - -type rpc_call_state: enum { - NONE, - HAVE_CALL, - HAVE_REPLY -}; - -type rpc_call_info: record { - state: rpc_call_state; - calltime: time; - cid: conn_id; -}; - -function new_call(cid: conn_id): rpc_call_info - { - local ci: rpc_call_info; - - ci$state = NONE; - ci$calltime = network_time(); - ci$cid = cid; - return ci; - } - -function rpc_expire_xid(t: table[count] of rpc_call_info, xid: count): interval - { - local ci = t[xid]; - if (ci$state != HAVE_REPLY) - print log_file, fmt("%.6f %s %s note XID %d never recevied a reply", - ci$calltime, id_string(ci$cid), - get_port_transport_proto(ci$cid$orig_p), xid); - return 0 sec; - } - -function new_xid_table(): table[count] of rpc_call_info - { - local inner: table[count] of rpc_call_info &write_expire=rpc_timeout &expire_func=rpc_expire_xid; - return inner; - } - - -# Match requests to replies. -# The analyzer does this indepently and might differ in timeouts and -# handling of xid reuse. -# FIXME: add timeouts. Note, we do clean up on connection_state_remove -global rpc_calls: table[conn_id] of table[count] of rpc_call_info; -# &write_expire = rpc_timeout &expire_func=expire_rpc_call; - - -event rpc_dialogue(c: connection, prog: count, ver: count, proc: count, status: rpc_status, start_time: time, call_len: count, reply_len: count) - { - # TODO: We currently do nothing here. - # using the rpc_call and rpc_reply events, is all we need. - } - -event rpc_call(c: connection, xid: count, prog: count, ver: count, proc: count, call_len: count) - { - if (track_requests_replies) - { - if (c$id !in rpc_calls) - rpc_calls[c$id] = new_xid_table(); - if (xid !in rpc_calls[c$id]) - rpc_calls[c$id][xid] = new_call(c$id); - local curstate = rpc_calls[c$id][xid]$state; - - if (curstate == HAVE_CALL) - print log_file, fmt("%.6f %s %s note XID %d call retransmitted", - network_time(), id_string(c$id), get_port_transport_proto(c$id$orig_p), - xid); - else if (curstate == HAVE_REPLY) - print log_file, fmt("%.6f %s %s note XID %d call received after reply", - network_time(), id_string(c$id), get_port_transport_proto(c$id$orig_p), - xid); - rpc_calls[c$id][xid]$state = HAVE_CALL; - } - - print log_file, fmt("%.6f %s %s rpc_call %d %d %d %d %d", - network_time(), id_string(c$id), get_port_transport_proto(c$id$orig_p), - xid, prog, ver, proc, call_len); - } - -event rpc_reply(c: connection, xid: count, status: rpc_status, reply_len: count) - { - if (track_requests_replies) - { - if (c$id !in rpc_calls) - rpc_calls[c$id] = new_xid_table(); - if (xid !in rpc_calls[c$id]) - { - rpc_calls[c$id][xid] = new_call(c$id); - # XXX: what to do about calltime in rpc_call_info?? - } - if (rpc_calls[c$id][xid]$state == NONE) - print log_file, fmt("%.6f %s %s note XID %d reply but call is missing", - network_time(), id_string(c$id), get_port_transport_proto(c$id$orig_p), - xid); - else if (rpc_calls[c$id][xid]$state == HAVE_REPLY) - print log_file, fmt("%.6f %s %s note XID %d reply retransmitted", - network_time(), id_string(c$id), get_port_transport_proto(c$id$orig_p), - xid); - rpc_calls[c$id][xid]$state = HAVE_REPLY; - } - - print log_file, fmt("%.6f %s %s rpc_reply %d %s %d", - network_time(), reverse_id_string(c$id), get_port_transport_proto(c$id$orig_p), - xid, status, reply_len); - } - - - -function finish_calls(cid: conn_id) - { - for (xid in rpc_calls[cid]) - rpc_expire_xid(rpc_calls[cid], xid); - } - -event connection_state_remove(c: connection) - { - if (c$id !in rpc_calls) - return; - finish_calls(c$id); - delete rpc_calls[c$id]; - } - -event bro_done() - { - for (cid in rpc_calls) - finish_calls(cid); - } diff --git a/scripts/base/protocols/smtp/entities.bro b/scripts/base/protocols/smtp/entities.bro index 4296488ec7..e158d045e0 100644 --- a/scripts/base/protocols/smtp/entities.bro +++ b/scripts/base/protocols/smtp/entities.bro @@ -12,16 +12,16 @@ export { MD5, }; - redef enum Log::ID += { SMTP_ENTITIES }; + redef enum Log::ID += { ENTITIES_LOG }; type EntityInfo: record { ## This is the timestamp of when the MIME content transfer began. ts: time &log; uid: string &log; id: conn_id &log; - ## Internally generated "message id" that ties back to the particular - ## message in the SMTP log where this entity was seen. - mid: string &log; + ## A count to represent the depth of this message transaction in a + ## single connection where multiple messages were transferred. + trans_depth: count &log; ## The filename seen in the Content-Disposition header. filename: string &log &optional; ## Track how many bytes of the MIME encoded file have been seen. @@ -69,12 +69,17 @@ export { ## The on-disk prefix for files to be extracted from MIME entity bodies. const extraction_prefix = "smtp-entity" &redef; + ## If set, never generate MD5s. This is mainly for testing purposes to create + ## reproducable output in the case that the decision whether to create + ## checksums depends on environment specifics. + const never_calc_md5 = F &redef; + global log_mime: event(rec: EntityInfo); } event bro_init() &priority=5 { - Log::create_stream(SMTP_ENTITIES, [$columns=EntityInfo, $ev=log_mime]); + Log::create_stream(SMTP::ENTITIES_LOG, [$columns=EntityInfo, $ev=log_mime]); } function set_session(c: connection, new_entity: bool) @@ -85,7 +90,7 @@ function set_session(c: connection, new_entity: bool) info$ts=network_time(); info$uid=c$uid; info$id=c$id; - info$mid=c$smtp$mid; + info$trans_depth=c$smtp$trans_depth; c$smtp$current_entity = info; ++c$smtp_state$mime_level; @@ -121,7 +126,7 @@ event mime_segment_data(c: connection, length: count, data: string) &priority=-5 if ( c$smtp$current_entity$content_len == 0 ) { - if ( generate_md5 in c$smtp$current_entity$mime_type ) + if ( generate_md5 in c$smtp$current_entity$mime_type && ! never_calc_md5 ) c$smtp$current_entity$calc_md5 = T; if ( c$smtp$current_entity$calc_md5 ) @@ -185,7 +190,7 @@ event mime_end_entity(c: connection) &priority=-5 # Only log is there was some content. if ( c$smtp$current_entity$content_len > 0 ) - Log::write(SMTP_ENTITIES, c$smtp$current_entity); + Log::write(SMTP::ENTITIES_LOG, c$smtp$current_entity); delete c$smtp$current_entity; } diff --git a/scripts/base/protocols/smtp/main.bro b/scripts/base/protocols/smtp/main.bro index 02b282894c..513b85e342 100644 --- a/scripts/base/protocols/smtp/main.bro +++ b/scripts/base/protocols/smtp/main.bro @@ -1,17 +1,19 @@ +@load base/frameworks/notice +@load base/utils/addrs +@load base/utils/directions-and-hosts module SMTP; export { - redef enum Log::ID += { SMTP }; + redef enum Log::ID += { LOG }; type Info: record { ts: time &log; uid: string &log; id: conn_id &log; - ## This is an internally generated "message id" that can be used to - ## map between SMTP messages and MIME entities in the SMTP entities - ## log. - mid: string &log; + ## This is a number that indicates the number of messages deep into + ## this connection where this particular message was transferred. + trans_depth: count &log; helo: string &log &optional; mailfrom: string &log &optional; rcptto: set[string] &log &optional; @@ -65,12 +67,14 @@ redef record connection += { }; # Configure DPD -redef capture_filters += { ["smtp"] = "tcp port smtp or tcp port 587" }; +redef capture_filters += { ["smtp"] = "tcp port 25 or tcp port 587" }; redef dpd_config += { [ANALYZER_SMTP] = [$ports = ports] }; +redef likely_server_ports += { 25/tcp, 587/tcp }; + event bro_init() &priority=5 { - Log::create_stream(SMTP, [$columns=SMTP::Info, $ev=log_smtp]); + Log::create_stream(SMTP::LOG, [$columns=SMTP::Info, $ev=log_smtp]); } function find_address_in_smtp_header(header: string): string @@ -93,8 +97,11 @@ function new_smtp_log(c: connection): Info l$ts=network_time(); l$uid=c$uid; l$id=c$id; - l$mid=unique_id("@"); - if ( c?$smtp_state && c$smtp_state?$helo ) + # The messages_transferred count isn't incremented until the message is + # finished so we need to increment the count by 1 here. + l$trans_depth = c$smtp_state$messages_transferred+1; + + if ( c$smtp_state?$helo ) l$helo = c$smtp_state$helo; # The path will always end with the hosts involved in this connection. @@ -116,7 +123,7 @@ function set_smtp_session(c: connection) function smtp_message(c: connection) { if ( c$smtp$has_client_activity ) - Log::write(SMTP, c$smtp); + Log::write(SMTP::LOG, c$smtp); } event smtp_request(c: connection, is_orig: bool, command: string, arg: string) &priority=5 @@ -160,7 +167,6 @@ event smtp_reply(c: connection, is_orig: bool, code: count, cmd: string, event smtp_reply(c: connection, is_orig: bool, code: count, cmd: string, msg: string, cont_resp: bool) &priority=-5 { - set_smtp_session(c); if ( cmd == "." ) { # Track the number of messages seen in this session. diff --git a/scripts/base/protocols/ssh/main.bro b/scripts/base/protocols/ssh/main.bro index 5233c6da97..0d3439bb1f 100644 --- a/scripts/base/protocols/ssh/main.bro +++ b/scripts/base/protocols/ssh/main.bro @@ -5,12 +5,26 @@ ##! Requires that :bro:id:`use_conn_size_analyzer` is set to T! The heuristic ##! is not attempted if the connection size analyzer isn't enabled. +@load base/frameworks/notice +@load base/utils/site +@load base/utils/thresholds +@load base/utils/conn-ids +@load base/utils/directions-and-hosts + module SSH; export { - redef enum Log::ID += { SSH }; + ## The SSH protocol logging stream identifier. + redef enum Log::ID += { LOG }; + + redef enum Notice::Type += { + ## Indicates that a heuristically detected "successful" SSH + ## authentication occurred. + Login + }; type Info: record { + ## Time when the SSH connection began. ts: time &log; uid: string &log; id: conn_id &log; @@ -22,11 +36,11 @@ export { ## would be set for the opposite situation. # TODO: handle local-local and remote-remote better. direction: Direction &log &optional; - ## The software string given by the client. + ## Software string given by the client. client: string &log &optional; - ## The software string given by the server. + ## Software string given by the server. server: string &log &optional; - ## The amount of data returned from the server. This is currently + ## Amount of data returned from the server. This is currently ## the only measure of the success heuristic and it is logged to ## assist analysts looking at the logs to make their own determination ## about the success on a case-by-case basis. @@ -36,8 +50,8 @@ export { done: bool &default=F; }; - ## The size in bytes at which the SSH connection is presumed to be - ## successful. + ## The size in bytes of data sent by the server at which the SSH + ## connection is presumed to be successful. const authentication_data_size = 5500 &redef; ## If true, we tell the event engine to not look at further data @@ -46,14 +60,16 @@ export { ## kinds of analyses (e.g., tracking connection size). const skip_processing_after_detection = F &redef; - ## This event is generated when the heuristic thinks that a login + ## Event that is generated when the heuristic thinks that a login ## was successful. global heuristic_successful_login: event(c: connection); - ## This event is generated when the heuristic thinks that a login + ## Event that is generated when the heuristic thinks that a login ## failed. global heuristic_failed_login: event(c: connection); + ## Event that can be handled to access the :bro:type:`SSH::Info` + ## record as it is sent on to the logging framework. global log_ssh: event(rec: Info); } @@ -61,13 +77,15 @@ export { redef capture_filters += { ["ssh"] = "tcp port 22" }; redef dpd_config += { [ANALYZER_SSH] = [$ports = set(22/tcp)] }; +redef likely_server_ports += { 22/tcp }; + redef record connection += { ssh: Info &optional; }; event bro_init() &priority=5 { - Log::create_stream(SSH, [$columns=Info, $ev=log_ssh]); + Log::create_stream(SSH::LOG, [$columns=Info, $ev=log_ssh]); } function set_session(c: connection) @@ -88,21 +106,36 @@ function check_ssh_connection(c: connection, done: bool) if ( c$ssh$done ) return; - # If this is still a live connection and the byte count has not - # crossed the threshold, just return and let the resheduled check happen later. - if ( !done && c$resp$num_bytes_ip < authentication_data_size ) + # Make sure conn_size_analyzer is active by checking + # resp$num_bytes_ip. In general it should always be active though. + if ( ! c$resp?$num_bytes_ip ) + return; + + # Remove the IP and TCP header length from the total size. + # TODO: Fix for IPv6. This whole approach also seems to break in some + # cases where there are more header bytes than num_bytes_ip. + local header_bytes = c$resp$num_pkts*32 + c$resp$num_pkts*20; + local server_bytes = c$resp$num_bytes_ip; + if ( server_bytes >= header_bytes ) + server_bytes = server_bytes - header_bytes; + else + server_bytes = c$resp$size; + + # If this is still a live connection and the byte count has not crossed + # the threshold, just return and let the rescheduled check happen later. + if ( ! done && server_bytes < authentication_data_size ) return; # Make sure the server has sent back more than 50 bytes to filter out # hosts that are just port scanning. Nothing is ever logged if the server # doesn't send back at least 50 bytes. - if ( c$resp$num_bytes_ip < 50 ) + if ( server_bytes < 50 ) return; c$ssh$direction = Site::is_local_addr(c$id$orig_h) ? OUTBOUND : INBOUND; - c$ssh$resp_size = c$resp$num_bytes_ip; + c$ssh$resp_size = server_bytes; - if ( c$resp$num_bytes_ip < authentication_data_size ) + if ( server_bytes < authentication_data_size ) { c$ssh$status = "failure"; event SSH::heuristic_failed_login(c); @@ -128,11 +161,15 @@ function check_ssh_connection(c: connection, done: bool) event SSH::heuristic_successful_login(c: connection) &priority=-5 { - Log::write(SSH, c$ssh); + NOTICE([$note=Login, + $msg="Heuristically detected successful SSH login.", + $conn=c]); + + Log::write(SSH::LOG, c$ssh); } event SSH::heuristic_failed_login(c: connection) &priority=-5 { - Log::write(SSH, c$ssh); + Log::write(SSH::LOG, c$ssh); } event connection_state_remove(c: connection) &priority=-5 diff --git a/scripts/base/protocols/ssl/consts.bro b/scripts/base/protocols/ssl/consts.bro index f20495deb5..ab130c4318 100644 --- a/scripts/base/protocols/ssl/consts.bro +++ b/scripts/base/protocols/ssl/consts.bro @@ -1,18 +1,65 @@ module SSL; export { - const SSLv2 = 0x0002; const SSLv3 = 0x0300; const TLSv10 = 0x0301; const TLSv11 = 0x0302; + const TLSv12 = 0x0303; + ## Mapping between the constants and string values for SSL/TLS versions. const version_strings: table[count] of string = { [SSLv2] = "SSLv2", [SSLv3] = "SSLv3", [TLSv10] = "TLSv10", [TLSv11] = "TLSv11", - } &default="UNKNOWN"; - + [TLSv12] = "TLSv12", + } &default=function(i: count):string { return fmt("unknown-%d", i); }; + + ## Mapping between numeric codes and human readable strings for alert + ## levels. + const alert_levels: table[count] of string = { + [1] = "warning", + [2] = "fatal", + } &default=function(i: count):string { return fmt("unknown-%d", i); }; + + ## Mapping between numeric codes and human readable strings for alert + ## descriptions.. + const alert_descriptions: table[count] of string = { + [0] = "close_notify", + [10] = "unexpected_message", + [20] = "bad_record_mac", + [21] = "decryption_failed", + [22] = "record_overflow", + [30] = "decompression_failure", + [40] = "handshake_failure", + [41] = "no_certificate", + [42] = "bad_certificate", + [43] = "unsupported_certificate", + [44] = "certificate_revoked", + [45] = "certificate_expired", + [46] = "certificate_unknown", + [47] = "illegal_parameter", + [48] = "unknown_ca", + [49] = "access_denied", + [50] = "decode_error", + [51] = "decrypt_error", + [60] = "export_restriction", + [70] = "protocol_version", + [71] = "insufficient_security", + [80] = "internal_error", + [90] = "user_canceled", + [100] = "no_renegotiation", + [110] = "unsupported_extension", + [111] = "certificate_unobtainable", + [112] = "unrecognized_name", + [113] = "bad_certificate_status_response", + [114] = "bad_certificate_hash_value", + [115] = "unknown_psk_identity", + } &default=function(i: count):string { return fmt("unknown-%d", i); }; + + ## Mapping between numeric codes and human readable strings for SSL/TLS + ## extensions. + # More information can be found here: # http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml const extensions: table[count] of string = { [0] = "server_name", @@ -31,10 +78,11 @@ export { [13] = "signature_algorithms", [14] = "use_srtp", [35] = "SessionTicket TLS", + [13172] = "next_protocol_negotiation", [65281] = "renegotiation_info" } &default=function(i: count):string { return fmt("unknown-%d", i); }; - ## SSLv2 + # SSLv2 const SSLv20_CK_RC4_128_WITH_MD5 = 0x010080; const SSLv20_CK_RC4_128_EXPORT40_WITH_MD5 = 0x020080; const SSLv20_CK_RC2_128_CBC_WITH_MD5 = 0x030080; @@ -43,7 +91,7 @@ export { const SSLv20_CK_DES_64_CBC_WITH_MD5 = 0x060040; const SSLv20_CK_DES_192_EDE3_CBC_WITH_MD5 = 0x0700C0; - ## TLS + # TLS const TLS_NULL_WITH_NULL_NULL = 0x0000; const TLS_RSA_WITH_NULL_MD5 = 0x0001; const TLS_RSA_WITH_NULL_SHA = 0x0002; @@ -260,13 +308,11 @@ export { const SSL_RSA_WITH_DES_CBC_MD5 = 0xFF82; const SSL_RSA_WITH_3DES_EDE_CBC_MD5 = 0xFF83; const TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0x00FF; - - # --- This is a table of all known cipher specs. - # --- It can be used for detecting unknown ciphers and for - # --- converting the cipher spec constants into a human readable format. - + + ## This is a table of all known cipher specs. It can be used for + ## detecting unknown ciphers and for converting the cipher spec constants + ## into a human readable format. const cipher_desc: table[count] of string = { - # --- sslv20 --- [SSLv20_CK_RC4_128_EXPORT40_WITH_MD5] = "SSLv20_CK_RC4_128_EXPORT40_WITH_MD5", [SSLv20_CK_RC4_128_WITH_MD5] = "SSLv20_CK_RC4_128_WITH_MD5", @@ -278,7 +324,6 @@ export { "SSLv20_CK_DES_192_EDE3_CBC_WITH_MD5", [SSLv20_CK_DES_64_CBC_WITH_MD5] = "SSLv20_CK_DES_64_CBC_WITH_MD5", - # --- TLS --- [TLS_NULL_WITH_NULL_NULL] = "TLS_NULL_WITH_NULL_NULL", [TLS_RSA_WITH_NULL_MD5] = "TLS_RSA_WITH_NULL_MD5", [TLS_RSA_WITH_NULL_SHA] = "TLS_RSA_WITH_NULL_SHA", @@ -490,43 +535,44 @@ export { [SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA] = "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA", [SSL_RSA_FIPS_WITH_DES_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_DES_CBC_SHA_2", [SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA_2] = "SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA_2", - } &default="UNKNOWN"; - + } &default=function(i: count):string { return fmt("unknown-%d", i); }; + + ## Mapping between the constants and string values for SSL/TLS errors. const x509_errors: table[count] of string = { - [0] = "X509_V_OK", - [1] = "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT", - [2] = "X509_V_ERR_UNABLE_TO_GET_CRL", - [3] = "X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE", - [4] = "X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE", - [5] = "X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY", - [6] = "X509_V_ERR_CERT_SIGNATURE_FAILURE", - [7] = "X509_V_ERR_CRL_SIGNATURE_FAILURE", - [8] = "X509_V_ERR_CERT_NOT_YET_VALID", - [9] = "X509_V_ERR_CERT_HAS_EXPIRED", - [10] = "X509_V_ERR_CRL_NOT_YET_VALID", - [11] = "X509_V_ERR_CRL_HAS_EXPIRED", - [12] = "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD", - [13] = "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD", - [14] = "X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD", - [15] = "X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD", - [16] = "X509_V_ERR_OUT_OF_MEM", - [17] = "X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT", - [18] = "X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN", - [19] = "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY", - [20] = "X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE", - [21] = "X509_V_ERR_CERT_CHAIN_TOO_LONG", - [22] = "X509_V_ERR_CERT_REVOKED", - [23] = "X509_V_ERR_INVALID_CA", - [24] = "X509_V_ERR_PATH_LENGTH_EXCEEDED", - [25] = "X509_V_ERR_INVALID_PURPOSE", - [26] = "X509_V_ERR_CERT_UNTRUSTED", - [27] = "X509_V_ERR_CERT_REJECTED", - [28] = "X509_V_ERR_SUBJECT_ISSUER_MISMATCH", - [29] = "X509_V_ERR_AKID_SKID_MISMATCH", - [30] = "X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH", - [31] = "X509_V_ERR_KEYUSAGE_NO_CERTSIGN", - [32] = "X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER", - [33] = "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION" - }; + [0] = "ok", + [1] = "unable to get issuer cert", + [2] = "unable to get crl", + [3] = "unable to decrypt cert signature", + [4] = "unable to decrypt crl signature", + [5] = "unable to decode issuer public key", + [6] = "cert signature failure", + [7] = "crl signature failure", + [8] = "cert not yet valid", + [9] = "cert has expired", + [10] = "crl not yet valid", + [11] = "crl has expired", + [12] = "error in cert not before field", + [13] = "error in cert not after field", + [14] = "error in crl last update field", + [15] = "error in crl next update field", + [16] = "out of mem", + [17] = "depth zero self signed cert", + [18] = "self signed cert in chain", + [19] = "unable to get issuer cert locally", + [20] = "unable to verify leaf signature", + [21] = "cert chain too long", + [22] = "cert revoked", + [23] = "invalid ca", + [24] = "path length exceeded", + [25] = "invalid purpose", + [26] = "cert untrusted", + [27] = "cert rejected", + [28] = "subject issuer mismatch", + [29] = "akid skid mismatch", + [30] = "akid issuer serial mismatch", + [31] = "keyusage no certsign", + [32] = "unable to get crl issuer", + [33] = "unhandled critical extension", + } &default=function(i: count):string { return fmt("unknown-%d", i); }; } diff --git a/scripts/base/protocols/ssl/main.bro b/scripts/base/protocols/ssl/main.bro index 775b59a6e5..0b280a6bcf 100644 --- a/scripts/base/protocols/ssl/main.bro +++ b/scripts/base/protocols/ssl/main.bro @@ -1,38 +1,65 @@ +##! Base SSL analysis script. This script logs information about the SSL/TLS +##! handshaking and encryption establishment process. + +@load ./consts module SSL; export { - redef enum Log::ID += { SSL }; - - redef enum Notice::Type += { - Self_Signed_Cert - }; + redef enum Log::ID += { LOG }; type Info: record { + ## Time when the SSL connection began. ts: time &log; uid: string &log; id: conn_id &log; + ## SSL/TLS version the server offered. version: string &log &optional; + ## SSL/TLS cipher suite the server chose. cipher: string &log &optional; + ## Value of the Server Name Indicator SSL/TLS extension. It + ## indicates the server name that the client was requesting. server_name: string &log &optional; + ## Session ID offered by the client for session resumption. + session_id: string &log &optional; + ## Subject of the X.509 certificate offered by the server. subject: string &log &optional; + ## NotValidBefore field value from the server certificate. not_valid_before: time &log &optional; + ## NotValidAfter field value from the serve certificate. not_valid_after: time &log &optional; + ## Last alert that was seen during the connection. + last_alert: string &log &optional; + ## Full binary server certificate stored in DER format. cert: string &optional; + ## Chain of certificates offered by the server to validate its + ## complete signing chain. cert_chain: vector of string &optional; + + ## The analyzer ID used for the analyzer instance attached + ## to each connection. It is not used for logging since it's a + ## meaningless arbitrary number. + analyzer_id: count &optional; }; - ## This is where the default root CA bundle is defined. By loading the + ## The default root CA bundle. By loading the ## mozilla-ca-list.bro script it will be set to Mozilla's root CA list. const root_certs: table[string] of string = {} &redef; - global log_ssl: event(rec: Info); + ## If true, detach the SSL analyzer from the connection to prevent + ## continuing to process encrypted traffic. Helps with performance + ## (especially with large file transfers). + const disable_analyzer_after_detection = T &redef; - const ports = { - 443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp, - 989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp - } &redef; + ## The openssl command line utility. If it's in the path the default + ## value will work, otherwise a full path string can be supplied for the + ## utility. + const openssl_util = "openssl" &redef; + + ## Event that can be handled to access the SSL + ## record as it is sent on to the logging framework. + global log_ssl: event(rec: Info); } redef record connection += { @@ -41,7 +68,7 @@ redef record connection += { event bro_init() &priority=5 { - Log::create_stream(SSL, [$columns=Info, $ev=log_ssl]); + Log::create_stream(SSL::LOG, [$columns=Info, $ev=log_ssl]); } redef capture_filters += { @@ -59,38 +86,64 @@ redef capture_filters += { ["xmpps"] = "tcp port 5223", }; +const ports = { + 443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp, + 989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp +}; + redef dpd_config += { [[ANALYZER_SSL]] = [$ports = ports] }; +redef likely_server_ports += { + 443/tcp, 563/tcp, 585/tcp, 614/tcp, 636/tcp, + 989/tcp, 990/tcp, 992/tcp, 993/tcp, 995/tcp, 5223/tcp +}; + function set_session(c: connection) { if ( ! c?$ssl ) c$ssl = [$ts=network_time(), $uid=c$uid, $id=c$id, $cert_chain=vector()]; } +function finish(c: connection) + { + Log::write(SSL::LOG, c$ssl); + if ( disable_analyzer_after_detection && c?$ssl && c$ssl?$analyzer_id ) + disable_analyzer(c$id, c$ssl$analyzer_id); + delete c$ssl; + } + event ssl_client_hello(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set) &priority=5 { set_session(c); + + # Save the session_id if there is one set. + if ( session_id != /^\x00{32}$/ ) + c$ssl$session_id = bytestring_to_hexstr(session_id); } - + event ssl_server_hello(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count) &priority=5 { set_session(c); - + c$ssl$version = version_strings[version]; c$ssl$cipher = cipher_desc[cipher]; } -event x509_certificate(c: connection, cert: X509, is_server: bool, chain_idx: count, chain_len: count, der_cert: string) &priority=5 +event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string) &priority=5 { set_session(c); - + + # We aren't doing anything with client certificates yet. + if ( is_orig ) + return; + if ( chain_idx == 0 ) { # Save the primary cert. c$ssl$cert = der_cert; - + # Also save other certificate information about the primary cert. c$ssl$subject = cert$subject; c$ssl$not_valid_before = cert$not_valid_before; @@ -102,19 +155,42 @@ event x509_certificate(c: connection, cert: X509, is_server: bool, chain_idx: co c$ssl$cert_chain[|c$ssl$cert_chain|] = der_cert; } } - -event ssl_extension(c: connection, code: count, val: string) &priority=5 + +event ssl_extension(c: connection, is_orig: bool, code: count, val: string) &priority=5 { set_session(c); - - if ( extensions[code] == "server_name" ) + + if ( is_orig && extensions[code] == "server_name" ) c$ssl$server_name = sub_bytes(val, 6, |val|); } - -event ssl_established(c: connection) &priority=-5 + +event ssl_alert(c: connection, is_orig: bool, level: count, desc: count) &priority=5 { set_session(c); - - Log::write(SSL, c$ssl); + + c$ssl$last_alert = alert_descriptions[desc]; + } + +event ssl_established(c: connection) &priority=5 + { + set_session(c); + } + +event ssl_established(c: connection) &priority=-5 + { + finish(c); + } + +event protocol_confirmation(c: connection, atype: count, aid: count) &priority=5 + { + # Check by checking for existence of c$ssl record. + if ( c?$ssl && analyzer_name(atype) == "SSL" ) + c$ssl$analyzer_id = aid; + } + +event protocol_violation(c: connection, atype: count, aid: count, + reason: string) &priority=5 + { + if ( c?$ssl ) + finish(c); } - diff --git a/scripts/base/protocols/ssl/mozilla-ca-list.bro b/scripts/base/protocols/ssl/mozilla-ca-list.bro index 0df3e0b9f2..4c4dccb755 100644 --- a/scripts/base/protocols/ssl/mozilla-ca-list.bro +++ b/scripts/base/protocols/ssl/mozilla-ca-list.bro @@ -1,140 +1,142 @@ # Don't edit! This file is automatically generated. -# Generated at: Wed Jun 29 07:52:38 -0400 2011 - +# Generated at: 2011-10-25 11:03:20 -0500 +@load base/protocols/ssl module SSL; redef root_certs += { - ["GTE CyberTrust Global Root"] = "\x30\x82\x02\x5A\x30\x82\x01\xC3\x02\x02\x01\xA5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x13\x0F\x47\x54\x45\x20\x43\x6F\x72\x70\x6F\x72\x61\x74\x69\x6F\x6E\x31\x27\x30\x25\x06\x03\x55\x04\x0B\x13\x1E\x47\x54\x45\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x2C\x20\x49\x6E\x63\x2E\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x47\x54\x45\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x39\x38\x30\x38\x31\x33\x30\x30\x32\x39\x30\x30\x5A\x17\x0D\x31\x38\x30\x38\x31\x33\x32\x33\x35\x39\x30\x30\x5A\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x13\x0F\x47\x54\x45\x20\x43\x6F\x72\x70\x6F\x72\x61\x74\x69\x6F\x6E\x31\x27\x30\x25\x06\x03\x55\x04\x0B\x13\x1E\x47\x54\x45\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x2C\x20\x49\x6E\x63\x2E\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x47\x54\x45\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\x95\x0F\xA0\xB6\xF0\x50\x9C\xE8\x7A\xC7\x88\xCD\xDD\x17\x0E\x2E\xB0\x94\xD0\x1B\x3D\x0E\xF6\x94\xC0\x8A\x94\xC7\x06\xC8\x90\x97\xC8\xB8\x64\x1A\x7A\x7E\x6C\x3C\x53\xE1\x37\x28\x73\x60\x7F\xB2\x97\x53\x07\x9F\x53\xF9\x6D\x58\x94\xD2\xAF\x8D\x6D\x88\x67\x80\xE6\xED\xB2\x95\xCF\x72\x31\xCA\xA5\x1C\x72\xBA\x5C\x02\xE7\x64\x42\xE7\xF9\xA9\x2C\xD6\x3A\x0D\xAC\x8D\x42\xAA\x24\x01\x39\xE6\x9C\x3F\x01\x85\x57\x0D\x58\x87\x45\xF8\xD3\x85\xAA\x93\x69\x26\x85\x70\x48\x80\x3F\x12\x15\xC7\x79\xB4\x1F\x05\x2F\x3B\x62\x99\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x6D\xEB\x1B\x09\xE9\x5E\xD9\x51\xDB\x67\x22\x61\xA4\x2A\x3C\x48\x77\xE3\xA0\x7C\xA6\xDE\x73\xA2\x14\x03\x85\x3D\xFB\xAB\x0E\x30\xC5\x83\x16\x33\x81\x13\x08\x9E\x7B\x34\x4E\xDF\x40\xC8\x74\xD7\xB9\x7D\xDC\xF4\x76\x55\x7D\x9B\x63\x54\x18\xE9\xF0\xEA\xF3\x5C\xB1\xD9\x8B\x42\x1E\xB9\xC0\x95\x4E\xBA\xFA\xD5\xE2\x7C\xF5\x68\x61\xBF\x8E\xEC\x05\x97\x5F\x5B\xB0\xD7\xA3\x85\x34\xC4\x24\xA7\x0D\x0F\x95\x93\xEF\xCB\x94\xD8\x9E\x1F\x9D\x5C\x85\x6D\xC7\xAA\xAE\x4F\x1F\x22\xB5\xCD\x95\xAD\xBA\xA7\xCC\xF9\xAB\x0B\x7A\x7F", - ["Thawte Server CA"] = "\x30\x82\x03\x13\x30\x82\x02\x7C\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\xC4\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5A\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0C\x57\x65\x73\x74\x65\x72\x6E\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6F\x77\x6E\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6F\x6E\x73\x75\x6C\x74\x69\x6E\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x54\x68\x61\x77\x74\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x26\x30\x24\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x17\x73\x65\x72\x76\x65\x72\x2D\x63\x65\x72\x74\x73\x40\x74\x68\x61\x77\x74\x65\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x39\x36\x30\x38\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x30\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xC4\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5A\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0C\x57\x65\x73\x74\x65\x72\x6E\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6F\x77\x6E\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6F\x6E\x73\x75\x6C\x74\x69\x6E\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x54\x68\x61\x77\x74\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x26\x30\x24\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x17\x73\x65\x72\x76\x65\x72\x2D\x63\x65\x72\x74\x73\x40\x74\x68\x61\x77\x74\x65\x2E\x63\x6F\x6D\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xD3\xA4\x50\x6E\xC8\xFF\x56\x6B\xE6\xCF\x5D\xB6\xEA\x0C\x68\x75\x47\xA2\xAA\xC2\xDA\x84\x25\xFC\xA8\xF4\x47\x51\xDA\x85\xB5\x20\x74\x94\x86\x1E\x0F\x75\xC9\xE9\x08\x61\xF5\x06\x6D\x30\x6E\x15\x19\x02\xE9\x52\xC0\x62\xDB\x4D\x99\x9E\xE2\x6A\x0C\x44\x38\xCD\xFE\xBE\xE3\x64\x09\x70\xC5\xFE\xB1\x6B\x29\xB6\x2F\x49\xC8\x3B\xD4\x27\x04\x25\x10\x97\x2F\xE7\x90\x6D\xC0\x28\x42\x99\xD7\x4C\x43\xDE\xC3\xF5\x21\x6D\x54\x9F\x5D\xC3\x58\xE1\xC0\xE4\xD9\x5B\xB0\xB8\xDC\xB4\x7B\xDF\x36\x3A\xC2\xB5\x66\x22\x12\xD6\x87\x0D\x02\x03\x01\x00\x01\xA3\x13\x30\x11\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x07\xFA\x4C\x69\x5C\xFB\x95\xCC\x46\xEE\x85\x83\x4D\x21\x30\x8E\xCA\xD9\xA8\x6F\x49\x1A\xE6\xDA\x51\xE3\x60\x70\x6C\x84\x61\x11\xA1\x1A\xC8\x48\x3E\x59\x43\x7D\x4F\x95\x3D\xA1\x8B\xB7\x0B\x62\x98\x7A\x75\x8A\xDD\x88\x4E\x4E\x9E\x40\xDB\xA8\xCC\x32\x74\xB9\x6F\x0D\xC6\xE3\xB3\x44\x0B\xD9\x8A\x6F\x9A\x29\x9B\x99\x18\x28\x3B\xD1\xE3\x40\x28\x9A\x5A\x3C\xD5\xB5\xE7\x20\x1B\x8B\xCA\xA4\xAB\x8D\xE9\x51\xD9\xE2\x4C\x2C\x59\xA9\xDA\xB9\xB2\x75\x1B\xF6\x42\xF2\xEF\xC7\xF2\x18\xF9\x89\xBC\xA3\xFF\x8A\x23\x2E\x70\x47", - ["Thawte Premium Server CA"] = "\x30\x82\x03\x27\x30\x82\x02\x90\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\xCE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5A\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0C\x57\x65\x73\x74\x65\x72\x6E\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6F\x77\x6E\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6F\x6E\x73\x75\x6C\x74\x69\x6E\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x72\x65\x6D\x69\x75\x6D\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x19\x70\x72\x65\x6D\x69\x75\x6D\x2D\x73\x65\x72\x76\x65\x72\x40\x74\x68\x61\x77\x74\x65\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x39\x36\x30\x38\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x30\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5A\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0C\x57\x65\x73\x74\x65\x72\x6E\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6F\x77\x6E\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6F\x6E\x73\x75\x6C\x74\x69\x6E\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x72\x65\x6D\x69\x75\x6D\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x19\x70\x72\x65\x6D\x69\x75\x6D\x2D\x73\x65\x72\x76\x65\x72\x40\x74\x68\x61\x77\x74\x65\x2E\x63\x6F\x6D\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xD2\x36\x36\x6A\x8B\xD7\xC2\x5B\x9E\xDA\x81\x41\x62\x8F\x38\xEE\x49\x04\x55\xD6\xD0\xEF\x1C\x1B\x95\x16\x47\xEF\x18\x48\x35\x3A\x52\xF4\x2B\x6A\x06\x8F\x3B\x2F\xEA\x56\xE3\xAF\x86\x8D\x9E\x17\xF7\x9E\xB4\x65\x75\x02\x4D\xEF\xCB\x09\xA2\x21\x51\xD8\x9B\xD0\x67\xD0\xBA\x0D\x92\x06\x14\x73\xD4\x93\xCB\x97\x2A\x00\x9C\x5C\x4E\x0C\xBC\xFA\x15\x52\xFC\xF2\x44\x6E\xDA\x11\x4A\x6E\x08\x9F\x2F\x2D\xE3\xF9\xAA\x3A\x86\x73\xB6\x46\x53\x58\xC8\x89\x05\xBD\x83\x11\xB8\x73\x3F\xAA\x07\x8D\xF4\x42\x4D\xE7\x40\x9D\x1C\x37\x02\x03\x01\x00\x01\xA3\x13\x30\x11\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x26\x48\x2C\x16\xC2\x58\xFA\xE8\x16\x74\x0C\xAA\xAA\x5F\x54\x3F\xF2\xD7\xC9\x78\x60\x5E\x5E\x6E\x37\x63\x22\x77\x36\x7E\xB2\x17\xC4\x34\xB9\xF5\x08\x85\xFC\xC9\x01\x38\xFF\x4D\xBE\xF2\x16\x42\x43\xE7\xBB\x5A\x46\xFB\xC1\xC6\x11\x1F\xF1\x4A\xB0\x28\x46\xC9\xC3\xC4\x42\x7D\xBC\xFA\xAB\x59\x6E\xD5\xB7\x51\x88\x11\xE3\xA4\x85\x19\x6B\x82\x4C\xA4\x0C\x12\xAD\xE9\xA4\xAE\x3F\xF1\xC3\x49\x65\x9A\x8C\xC5\xC8\x3E\x25\xB7\x94\x99\xBB\x92\x32\x71\x07\xF0\x86\x5E\xED\x50\x27\xA6\x0D\xA6\x23\xF9\xBB\xCB\xA6\x07\x14\x42", - ["Equifax Secure CA"] = "\x30\x82\x03\x20\x30\x82\x02\x89\xA0\x03\x02\x01\x02\x02\x04\x35\xDE\xF4\xCF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x45\x71\x75\x69\x66\x61\x78\x31\x2D\x30\x2B\x06\x03\x55\x04\x0B\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x39\x38\x30\x38\x32\x32\x31\x36\x34\x31\x35\x31\x5A\x17\x0D\x31\x38\x30\x38\x32\x32\x31\x36\x34\x31\x35\x31\x5A\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x45\x71\x75\x69\x66\x61\x78\x31\x2D\x30\x2B\x06\x03\x55\x04\x0B\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xC1\x5D\xB1\x58\x67\x08\x62\xEE\xA0\x9A\x2D\x1F\x08\x6D\x91\x14\x68\x98\x0A\x1E\xFE\xDA\x04\x6F\x13\x84\x62\x21\xC3\xD1\x7C\xCE\x9F\x05\xE0\xB8\x01\xF0\x4E\x34\xEC\xE2\x8A\x95\x04\x64\xAC\xF1\x6B\x53\x5F\x05\xB3\xCB\x67\x80\xBF\x42\x02\x8E\xFE\xDD\x01\x09\xEC\xE1\x00\x14\x4F\xFC\xFB\xF0\x0C\xDD\x43\xBA\x5B\x2B\xE1\x1F\x80\x70\x99\x15\x57\x93\x16\xF1\x0F\x97\x6A\xB7\xC2\x68\x23\x1C\xCC\x4D\x59\x30\xAC\x51\x1E\x3B\xAF\x2B\xD6\xEE\x63\x45\x7B\xC5\xD9\x5F\x50\xD2\xE3\x50\x0F\x3A\x88\xE7\xBF\x14\xFD\xE0\xC7\xB9\x02\x03\x01\x00\x01\xA3\x82\x01\x09\x30\x82\x01\x05\x30\x70\x06\x03\x55\x1D\x1F\x04\x69\x30\x67\x30\x65\xA0\x63\xA0\x61\xA4\x5F\x30\x5D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x45\x71\x75\x69\x66\x61\x78\x31\x2D\x30\x2B\x06\x03\x55\x04\x0B\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x1A\x06\x03\x55\x1D\x10\x04\x13\x30\x11\x81\x0F\x32\x30\x31\x38\x30\x38\x32\x32\x31\x36\x34\x31\x35\x31\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x48\xE6\x68\xF9\x2B\xD2\xB2\x95\xD7\x47\xD8\x23\x20\x10\x4F\x33\x98\x90\x9F\xD4\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x48\xE6\x68\xF9\x2B\xD2\xB2\x95\xD7\x47\xD8\x23\x20\x10\x4F\x33\x98\x90\x9F\xD4\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x1A\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0D\x30\x0B\x1B\x05\x56\x33\x2E\x30\x63\x03\x02\x06\xC0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x58\xCE\x29\xEA\xFC\xF7\xDE\xB5\xCE\x02\xB9\x17\xB5\x85\xD1\xB9\xE3\xE0\x95\xCC\x25\x31\x0D\x00\xA6\x92\x6E\x7F\xB6\x92\x63\x9E\x50\x95\xD1\x9A\x6F\xE4\x11\xDE\x63\x85\x6E\x98\xEE\xA8\xFF\x5A\xC8\xD3\x55\xB2\x66\x71\x57\xDE\xC0\x21\xEB\x3D\x2A\xA7\x23\x49\x01\x04\x86\x42\x7B\xFC\xEE\x7F\xA2\x16\x52\xB5\x67\x67\xD3\x40\xDB\x3B\x26\x58\xB2\x28\x77\x3D\xAE\x14\x77\x61\xD6\xFA\x2A\x66\x27\xA0\x0D\xFA\xA7\x73\x5C\xEA\x70\xF1\x94\x21\x65\x44\x5F\xFA\xFC\xEF\x29\x68\xA9\xA2\x87\x79\xEF\x79\xEF\x4F\xAC\x07\x77\x38", - ["Digital Signature Trust Co. Global CA 1"] = "\x30\x82\x03\x29\x30\x82\x02\x92\xA0\x03\x02\x01\x02\x02\x04\x36\x70\x15\x96\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x46\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x31\x30\x1E\x17\x0D\x39\x38\x31\x32\x31\x30\x31\x38\x31\x30\x32\x33\x5A\x17\x0D\x31\x38\x31\x32\x31\x30\x31\x38\x34\x30\x32\x33\x5A\x30\x46\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x31\x30\x81\x9D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8B\x00\x30\x81\x87\x02\x81\x81\x00\xA0\x6C\x81\xA9\xCF\x34\x1E\x24\xDD\xFE\x86\x28\xCC\xDE\x83\x2F\xF9\x5E\xD4\x42\xD2\xE8\x74\x60\x66\x13\x98\x06\x1C\xA9\x51\x12\x69\x6F\x31\x55\xB9\x49\x72\x00\x08\x7E\xD3\xA5\x62\x44\x37\x24\x99\x8F\xD9\x83\x48\x8F\x99\x6D\x95\x13\xBB\x43\x3B\x2E\x49\x4E\x88\x37\xC1\xBB\x58\x7F\xFE\xE1\xBD\xF8\xBB\x61\xCD\xF3\x47\xC0\x99\xA6\xF1\xF3\x91\xE8\x78\x7C\x00\xCB\x61\xC9\x44\x27\x71\x69\x55\x4A\x7E\x49\x4D\xED\xA2\xA3\xBE\x02\x4C\x00\xCA\x02\xA8\xEE\x01\x02\x31\x64\x0F\x52\x2D\x13\x74\x76\x36\xB5\x7A\xB4\x2D\x71\x02\x01\x03\xA3\x82\x01\x24\x30\x82\x01\x20\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x68\x06\x03\x55\x1D\x1F\x04\x61\x30\x5F\x30\x5D\xA0\x5B\xA0\x59\xA4\x57\x30\x55\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x31\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x31\x39\x39\x38\x31\x32\x31\x30\x31\x38\x31\x30\x32\x33\x5A\x81\x0F\x32\x30\x31\x38\x31\x32\x31\x30\x31\x38\x31\x30\x32\x33\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x6A\x79\x7E\x91\x69\x46\x18\x13\x0A\x02\x77\xA5\x59\x5B\x60\x98\x25\x0E\xA2\xF8\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x6A\x79\x7E\x91\x69\x46\x18\x13\x0A\x02\x77\xA5\x59\x5B\x60\x98\x25\x0E\xA2\xF8\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x19\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0C\x30\x0A\x1B\x04\x56\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x22\x12\xD8\x7A\x1D\xDC\x81\x06\xB6\x09\x65\xB2\x87\xC8\x1F\x5E\xB4\x2F\xE9\xC4\x1E\xF2\x3C\xC1\xBB\x04\x90\x11\x4A\x83\x4E\x7E\x93\xB9\x4D\x42\xC7\x92\x26\xA0\x5C\x34\x9A\x38\x72\xF8\xFD\x6B\x16\x3E\x20\xEE\x82\x8B\x31\x2A\x93\x36\x85\x23\x88\x8A\x3C\x03\x68\xD3\xC9\x09\x0F\x4D\xFC\x6C\xA4\xDA\x28\x72\x93\x0E\x89\x80\xB0\x7D\xFE\x80\x6F\x65\x6D\x18\x33\x97\x8B\xC2\x6B\x89\xEE\x60\x3D\xC8\x9B\xEF\x7F\x2B\x32\x62\x73\x93\xCB\x3C\xE3\x7B\xE2\x76\x78\x45\xBC\xA1\x93\x04\xBB\x86\x9F\x3A\x5B\x43\x7A\xC3\x8A\x65", - ["Digital Signature Trust Co. Global CA 3"] = "\x30\x82\x03\x29\x30\x82\x02\x92\xA0\x03\x02\x01\x02\x02\x04\x36\x6E\xD3\xCE\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x46\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x32\x30\x1E\x17\x0D\x39\x38\x31\x32\x30\x39\x31\x39\x31\x37\x32\x36\x5A\x17\x0D\x31\x38\x31\x32\x30\x39\x31\x39\x34\x37\x32\x36\x5A\x30\x46\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x32\x30\x81\x9D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8B\x00\x30\x81\x87\x02\x81\x81\x00\xBF\x93\x8F\x17\x92\xEF\x33\x13\x18\xEB\x10\x7F\x4E\x16\xBF\xFF\x06\x8F\x2A\x85\xBC\x5E\xF9\x24\xA6\x24\x88\xB6\x03\xB7\xC1\xC3\x5F\x03\x5B\xD1\x6F\xAE\x7E\x42\xEA\x66\x23\xB8\x63\x83\x56\xFB\x28\x2D\xE1\x38\x8B\xB4\xEE\xA8\x01\xE1\xCE\x1C\xB6\x88\x2A\x22\x46\x85\xFB\x9F\xA7\x70\xA9\x47\x14\x3F\xCE\xDE\x65\xF0\xA8\x71\xF7\x4F\x26\x6C\x8C\xBC\xC6\xB5\xEF\xDE\x49\x27\xFF\x48\x2A\x7D\xE8\x4D\x03\xCC\xC7\xB2\x52\xC6\x17\x31\x13\x3B\xB5\x4D\xDB\xC8\xC4\xF6\xC3\x0F\x24\x2A\xDA\x0C\x9D\xE7\x91\x5B\x80\xCD\x94\x9D\x02\x01\x03\xA3\x82\x01\x24\x30\x82\x01\x20\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x68\x06\x03\x55\x1D\x1F\x04\x61\x30\x5F\x30\x5D\xA0\x5B\xA0\x59\xA4\x57\x30\x55\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x32\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x31\x39\x39\x38\x31\x32\x30\x39\x31\x39\x31\x37\x32\x36\x5A\x81\x0F\x32\x30\x31\x38\x31\x32\x30\x39\x31\x39\x31\x37\x32\x36\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x1E\x82\x4D\x28\x65\x80\x3C\xC9\x41\x6E\xAC\x35\x2E\x5A\xCB\xDE\xEE\xF8\x39\x5B\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x1E\x82\x4D\x28\x65\x80\x3C\xC9\x41\x6E\xAC\x35\x2E\x5A\xCB\xDE\xEE\xF8\x39\x5B\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x19\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0C\x30\x0A\x1B\x04\x56\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x47\x8D\x83\xAD\x62\xF2\xDB\xB0\x9E\x45\x22\x05\xB9\xA2\xD6\x03\x0E\x38\x72\xE7\x9E\xFC\x7B\xE6\x93\xB6\x9A\xA5\xA2\x94\xC8\x34\x1D\x91\xD1\xC5\xD7\xF4\x0A\x25\x0F\x3D\x78\x81\x9E\x0F\xB1\x67\xC4\x90\x4C\x63\xDD\x5E\xA7\xE2\xBA\x9F\xF5\xF7\x4D\xA5\x31\x7B\x9C\x29\x2D\x4C\xFE\x64\x3E\xEC\xB6\x53\xFE\xEA\x9B\xED\x82\xDB\x74\x75\x4B\x07\x79\x6E\x1E\xD8\x19\x83\x73\xDE\xF5\x3E\xD0\xB5\xDE\xE7\x4B\x68\x7D\x43\x2E\x2A\x20\xE1\x7E\xA0\x78\x44\x9E\x08\xF5\x98\xF9\xC7\x7F\x1B\x1B\xD6\x06\x20\x02\x58\xA1\xC3\xA2\x03", - ["Verisign Class 3 Public Primary Certification Authority"] = "\x30\x82\x02\x3C\x30\x82\x01\xA5\x02\x10\x70\xBA\xE4\x1D\x10\xD9\x29\x34\xB6\x38\xCA\x7B\x03\xCC\xBA\xBF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x02\x05\x00\x30\x5F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x37\x30\x35\x06\x03\x55\x04\x0B\x13\x2E\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x39\x36\x30\x31\x32\x39\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x5F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x37\x30\x35\x06\x03\x55\x04\x0B\x13\x2E\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xC9\x5C\x59\x9E\xF2\x1B\x8A\x01\x14\xB4\x10\xDF\x04\x40\xDB\xE3\x57\xAF\x6A\x45\x40\x8F\x84\x0C\x0B\xD1\x33\xD9\xD9\x11\xCF\xEE\x02\x58\x1F\x25\xF7\x2A\xA8\x44\x05\xAA\xEC\x03\x1F\x78\x7F\x9E\x93\xB9\x9A\x00\xAA\x23\x7D\xD6\xAC\x85\xA2\x63\x45\xC7\x72\x27\xCC\xF4\x4C\xC6\x75\x71\xD2\x39\xEF\x4F\x42\xF0\x75\xDF\x0A\x90\xC6\x8E\x20\x6F\x98\x0F\xF8\xAC\x23\x5F\x70\x29\x36\xA4\xC9\x86\xE7\xB1\x9A\x20\xCB\x53\xA5\x85\xE7\x3D\xBE\x7D\x9A\xFE\x24\x45\x33\xDC\x76\x15\xED\x0F\xA2\x71\x64\x4C\x65\x2E\x81\x68\x45\xA7\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x02\x05\x00\x03\x81\x81\x00\xBB\x4C\x12\x2B\xCF\x2C\x26\x00\x4F\x14\x13\xDD\xA6\xFB\xFC\x0A\x11\x84\x8C\xF3\x28\x1C\x67\x92\x2F\x7C\xB6\xC5\xFA\xDF\xF0\xE8\x95\xBC\x1D\x8F\x6C\x2C\xA8\x51\xCC\x73\xD8\xA4\xC0\x53\xF0\x4E\xD6\x26\xC0\x76\x01\x57\x81\x92\x5E\x21\xF1\xD1\xB1\xFF\xE7\xD0\x21\x58\xCD\x69\x17\xE3\x44\x1C\x9C\x19\x44\x39\x89\x5C\xDC\x9C\x00\x0F\x56\x8D\x02\x99\xED\xA2\x90\x45\x4C\xE4\xBB\x10\xA4\x3D\xF0\x32\x03\x0E\xF1\xCE\xF8\xE8\xC9\x51\x8C\xE6\x62\x9F\xE6\x9F\xC0\x7D\xB7\x72\x9C\xC9\x36\x3A\x6B\x9F\x4E\xA8\xFF\x64\x0D\x64", - ["Verisign Class 3 Public Primary Certification Authority - G2"] = "\x30\x82\x03\x02\x30\x82\x02\x6B\x02\x10\x7D\xD9\xFE\x07\xCF\xA8\x1E\xB7\x10\x79\x67\xFB\xA7\x89\x34\xC6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xC1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x0B\x13\x33\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x30\x1E\x17\x0D\x39\x38\x30\x35\x31\x38\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xC1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x0B\x13\x33\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xCC\x5E\xD1\x11\x5D\x5C\x69\xD0\xAB\xD3\xB9\x6A\x4C\x99\x1F\x59\x98\x30\x8E\x16\x85\x20\x46\x6D\x47\x3F\xD4\x85\x20\x84\xE1\x6D\xB3\xF8\xA4\xED\x0C\xF1\x17\x0F\x3B\xF9\xA7\xF9\x25\xD7\xC1\xCF\x84\x63\xF2\x7C\x63\xCF\xA2\x47\xF2\xC6\x5B\x33\x8E\x64\x40\x04\x68\xC1\x80\xB9\x64\x1C\x45\x77\xC7\xD8\x6E\xF5\x95\x29\x3C\x50\xE8\x34\xD7\x78\x1F\xA8\xBA\x6D\x43\x91\x95\x8F\x45\x57\x5E\x7E\xC5\xFB\xCA\xA4\x04\xEB\xEA\x97\x37\x54\x30\x6F\xBB\x01\x47\x32\x33\xCD\xDC\x57\x9B\x64\x69\x61\xF8\x9B\x1D\x1C\x89\x4F\x5C\x67\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x51\x4D\xCD\xBE\x5C\xCB\x98\x19\x9C\x15\xB2\x01\x39\x78\x2E\x4D\x0F\x67\x70\x70\x99\xC6\x10\x5A\x94\xA4\x53\x4D\x54\x6D\x2B\xAF\x0D\x5D\x40\x8B\x64\xD3\xD7\xEE\xDE\x56\x61\x92\x5F\xA6\xC4\x1D\x10\x61\x36\xD3\x2C\x27\x3C\xE8\x29\x09\xB9\x11\x64\x74\xCC\xB5\x73\x9F\x1C\x48\xA9\xBC\x61\x01\xEE\xE2\x17\xA6\x0C\xE3\x40\x08\x3B\x0E\xE7\xEB\x44\x73\x2A\x9A\xF1\x69\x92\xEF\x71\x14\xC3\x39\xAC\x71\xA7\x91\x09\x6F\xE4\x71\x06\xB3\xBA\x59\x57\x26\x79\x00\xF6\xF8\x0D\xA2\x33\x30\x28\xD4\xAA\x58\xA0\x9D\x9D\x69\x91\xFD", - ["Verisign Class 4 Public Primary Certification Authority - G2"] = "\x30\x82\x03\x02\x30\x82\x02\x6B\x02\x10\x32\x88\x8E\x9A\xD2\xF5\xEB\x13\x47\xF8\x7F\xC4\x20\x37\x25\xF8\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xC1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x0B\x13\x33\x43\x6C\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x30\x1E\x17\x0D\x39\x38\x30\x35\x31\x38\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xC1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x0B\x13\x33\x43\x6C\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xBA\xF0\xE4\xCF\xF9\xC4\xAE\x85\x54\xB9\x07\x57\xF9\x8F\xC5\x7F\x68\x11\xF8\xC4\x17\xB0\x44\xDC\xE3\x30\x73\xD5\x2A\x62\x2A\xB8\xD0\xCC\x1C\xED\x28\x5B\x7E\xBD\x6A\xDC\xB3\x91\x24\xCA\x41\x62\x3C\xFC\x02\x01\xBF\x1C\x16\x31\x94\x05\x97\x76\x6E\xA2\xAD\xBD\x61\x17\x6C\x4E\x30\x86\xF0\x51\x37\x2A\x50\xC7\xA8\x62\x81\xDC\x5B\x4A\xAA\xC1\xA0\xB4\x6E\xEB\x2F\xE5\x57\xC5\xB1\x2B\x40\x70\xDB\x5A\x4D\xA1\x8E\x1F\xBD\x03\x1F\xD8\x03\xD4\x8F\x4C\x99\x71\xBC\xE2\x82\xCC\x58\xE8\x98\x3A\x86\xD3\x86\x38\xF3\x00\x29\x1F\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x85\x8C\x12\xC1\xA7\xB9\x50\x15\x7A\xCB\x3E\xAC\xB8\x43\x8A\xDC\xAA\xDD\x14\xBA\x89\x81\x7E\x01\x3C\x23\x71\x21\x88\x2F\x82\xDC\x63\xFA\x02\x45\xAC\x45\x59\xD7\x2A\x58\x44\x5B\xB7\x9F\x81\x3B\x92\x68\x3D\xE2\x37\x24\xF5\x7B\x6C\x8F\x76\x35\x96\x09\xA8\x59\x9D\xB9\xCE\x23\xAB\x74\xD6\x83\xFD\x32\x73\x27\xD8\x69\x3E\x43\x74\xF6\xAE\xC5\x89\x9A\xE7\x53\x7C\xE9\x7B\xF6\x4B\xF3\xC1\x65\x83\xDE\x8D\x8A\x9C\x3C\x88\x8D\x39\x59\xFC\xAA\x3F\x22\x8D\xA1\xC1\x66\x50\x81\x72\x4C\xED\x22\x64\x4F\x4F\xCA\x80\x91\xB6\x29", - ["GlobalSign Root CA"] = "\x30\x82\x03\x75\x30\x82\x02\x5D\xA0\x03\x02\x01\x02\x02\x0B\x04\x00\x00\x00\x00\x01\x15\x4B\x5A\xC3\x94\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x57\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x6E\x76\x2D\x73\x61\x31\x10\x30\x0E\x06\x03\x55\x04\x0B\x13\x07\x52\x6F\x6F\x74\x20\x43\x41\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x39\x38\x30\x39\x30\x31\x31\x32\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x30\x31\x32\x38\x31\x32\x30\x30\x30\x30\x5A\x30\x57\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x6E\x76\x2D\x73\x61\x31\x10\x30\x0E\x06\x03\x55\x04\x0B\x13\x07\x52\x6F\x6F\x74\x20\x43\x41\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xDA\x0E\xE6\x99\x8D\xCE\xA3\xE3\x4F\x8A\x7E\xFB\xF1\x8B\x83\x25\x6B\xEA\x48\x1F\xF1\x2A\xB0\xB9\x95\x11\x04\xBD\xF0\x63\xD1\xE2\x67\x66\xCF\x1C\xDD\xCF\x1B\x48\x2B\xEE\x8D\x89\x8E\x9A\xAF\x29\x80\x65\xAB\xE9\xC7\x2D\x12\xCB\xAB\x1C\x4C\x70\x07\xA1\x3D\x0A\x30\xCD\x15\x8D\x4F\xF8\xDD\xD4\x8C\x50\x15\x1C\xEF\x50\xEE\xC4\x2E\xF7\xFC\xE9\x52\xF2\x91\x7D\xE0\x6D\xD5\x35\x30\x8E\x5E\x43\x73\xF2\x41\xE9\xD5\x6A\xE3\xB2\x89\x3A\x56\x39\x38\x6F\x06\x3C\x88\x69\x5B\x2A\x4D\xC5\xA7\x54\xB8\x6C\x89\xCC\x9B\xF9\x3C\xCA\xE5\xFD\x89\xF5\x12\x3C\x92\x78\x96\xD6\xDC\x74\x6E\x93\x44\x61\xD1\x8D\xC7\x46\xB2\x75\x0E\x86\xE8\x19\x8A\xD5\x6D\x6C\xD5\x78\x16\x95\xA2\xE9\xC8\x0A\x38\xEB\xF2\x24\x13\x4F\x73\x54\x93\x13\x85\x3A\x1B\xBC\x1E\x34\xB5\x8B\x05\x8C\xB9\x77\x8B\xB1\xDB\x1F\x20\x91\xAB\x09\x53\x6E\x90\xCE\x7B\x37\x74\xB9\x70\x47\x91\x22\x51\x63\x16\x79\xAE\xB1\xAE\x41\x26\x08\xC8\x19\x2B\xD1\x46\xAA\x48\xD6\x64\x2A\xD7\x83\x34\xFF\x2C\x2A\xC1\x6C\x19\x43\x4A\x07\x85\xE7\xD3\x7C\xF6\x21\x68\xEF\xEA\xF2\x52\x9F\x7F\x93\x90\xCF\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x60\x7B\x66\x1A\x45\x0D\x97\xCA\x89\x50\x2F\x7D\x04\xCD\x34\xA8\xFF\xFC\xFD\x4B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xD6\x73\xE7\x7C\x4F\x76\xD0\x8D\xBF\xEC\xBA\xA2\xBE\x34\xC5\x28\x32\xB5\x7C\xFC\x6C\x9C\x2C\x2B\xBD\x09\x9E\x53\xBF\x6B\x5E\xAA\x11\x48\xB6\xE5\x08\xA3\xB3\xCA\x3D\x61\x4D\xD3\x46\x09\xB3\x3E\xC3\xA0\xE3\x63\x55\x1B\xF2\xBA\xEF\xAD\x39\xE1\x43\xB9\x38\xA3\xE6\x2F\x8A\x26\x3B\xEF\xA0\x50\x56\xF9\xC6\x0A\xFD\x38\xCD\xC4\x0B\x70\x51\x94\x97\x98\x04\xDF\xC3\x5F\x94\xD5\x15\xC9\x14\x41\x9C\xC4\x5D\x75\x64\x15\x0D\xFF\x55\x30\xEC\x86\x8F\xFF\x0D\xEF\x2C\xB9\x63\x46\xF6\xAA\xFC\xDF\xBC\x69\xFD\x2E\x12\x48\x64\x9A\xE0\x95\xF0\xA6\xEF\x29\x8F\x01\xB1\x15\xB5\x0C\x1D\xA5\xFE\x69\x2C\x69\x24\x78\x1E\xB3\xA7\x1C\x71\x62\xEE\xCA\xC8\x97\xAC\x17\x5D\x8A\xC2\xF8\x47\x86\x6E\x2A\xC4\x56\x31\x95\xD0\x67\x89\x85\x2B\xF9\x6C\xA6\x5D\x46\x9D\x0C\xAA\x82\xE4\x99\x51\xDD\x70\xB7\xDB\x56\x3D\x61\xE4\x6A\xE1\x5C\xD6\xF6\xFE\x3D\xDE\x41\xCC\x07\xAE\x63\x52\xBF\x53\x53\xF4\x2B\xE9\xC7\xFD\xB6\xF7\x82\x5F\x85\xD2\x41\x18\xDB\x81\xB3\x04\x1C\xC5\x1F\xA4\x80\x6F\x15\x20\xC9\xDE\x0C\x88\x0A\x1D\xD6\x66\x55\xE2\xFC\x48\xC9\x29\x26\x69\xE0", - ["GlobalSign Root CA - R2"] = "\x30\x82\x03\xBA\x30\x82\x02\xA2\xA0\x03\x02\x01\x02\x02\x0B\x04\x00\x00\x00\x00\x01\x0F\x86\x26\xE6\x0D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4C\x31\x20\x30\x1E\x06\x03\x55\x04\x0B\x13\x17\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x52\x32\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x30\x1E\x17\x0D\x30\x36\x31\x32\x31\x35\x30\x38\x30\x30\x30\x30\x5A\x17\x0D\x32\x31\x31\x32\x31\x35\x30\x38\x30\x30\x30\x30\x5A\x30\x4C\x31\x20\x30\x1E\x06\x03\x55\x04\x0B\x13\x17\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x52\x32\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\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\xA6\xCF\x24\x0E\xBE\x2E\x6F\x28\x99\x45\x42\xC4\xAB\x3E\x21\x54\x9B\x0B\xD3\x7F\x84\x70\xFA\x12\xB3\xCB\xBF\x87\x5F\xC6\x7F\x86\xD3\xB2\x30\x5C\xD6\xFD\xAD\xF1\x7B\xDC\xE5\xF8\x60\x96\x09\x92\x10\xF5\xD0\x53\xDE\xFB\x7B\x7E\x73\x88\xAC\x52\x88\x7B\x4A\xA6\xCA\x49\xA6\x5E\xA8\xA7\x8C\x5A\x11\xBC\x7A\x82\xEB\xBE\x8C\xE9\xB3\xAC\x96\x25\x07\x97\x4A\x99\x2A\x07\x2F\xB4\x1E\x77\xBF\x8A\x0F\xB5\x02\x7C\x1B\x96\xB8\xC5\xB9\x3A\x2C\xBC\xD6\x12\xB9\xEB\x59\x7D\xE2\xD0\x06\x86\x5F\x5E\x49\x6A\xB5\x39\x5E\x88\x34\xEC\xBC\x78\x0C\x08\x98\x84\x6C\xA8\xCD\x4B\xB4\xA0\x7D\x0C\x79\x4D\xF0\xB8\x2D\xCB\x21\xCA\xD5\x6C\x5B\x7D\xE1\xA0\x29\x84\xA1\xF9\xD3\x94\x49\xCB\x24\x62\x91\x20\xBC\xDD\x0B\xD5\xD9\xCC\xF9\xEA\x27\x0A\x2B\x73\x91\xC6\x9D\x1B\xAC\xC8\xCB\xE8\xE0\xA0\xF4\x2F\x90\x8B\x4D\xFB\xB0\x36\x1B\xF6\x19\x7A\x85\xE0\x6D\xF2\x61\x13\x88\x5C\x9F\xE0\x93\x0A\x51\x97\x8A\x5A\xCE\xAF\xAB\xD5\xF7\xAA\x09\xAA\x60\xBD\xDC\xD9\x5F\xDF\x72\xA9\x60\x13\x5E\x00\x01\xC9\x4A\xFA\x3F\xA4\xEA\x07\x03\x21\x02\x8E\x82\xCA\x03\xC2\x9B\x8F\x02\x03\x01\x00\x01\xA3\x81\x9C\x30\x81\x99\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9B\xE2\x07\x57\x67\x1C\x1E\xC0\x6A\x06\xDE\x59\xB4\x9A\x2D\xDF\xDC\x19\x86\x2E\x30\x36\x06\x03\x55\x1D\x1F\x04\x2F\x30\x2D\x30\x2B\xA0\x29\xA0\x27\x86\x25\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x67\x6C\x6F\x62\x61\x6C\x73\x69\x67\x6E\x2E\x6E\x65\x74\x2F\x72\x6F\x6F\x74\x2D\x72\x32\x2E\x63\x72\x6C\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x9B\xE2\x07\x57\x67\x1C\x1E\xC0\x6A\x06\xDE\x59\xB4\x9A\x2D\xDF\xDC\x19\x86\x2E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x99\x81\x53\x87\x1C\x68\x97\x86\x91\xEC\xE0\x4A\xB8\x44\x0B\xAB\x81\xAC\x27\x4F\xD6\xC1\xB8\x1C\x43\x78\xB3\x0C\x9A\xFC\xEA\x2C\x3C\x6E\x61\x1B\x4D\x4B\x29\xF5\x9F\x05\x1D\x26\xC1\xB8\xE9\x83\x00\x62\x45\xB6\xA9\x08\x93\xB9\xA9\x33\x4B\x18\x9A\xC2\xF8\x87\x88\x4E\xDB\xDD\x71\x34\x1A\xC1\x54\xDA\x46\x3F\xE0\xD3\x2A\xAB\x6D\x54\x22\xF5\x3A\x62\xCD\x20\x6F\xBA\x29\x89\xD7\xDD\x91\xEE\xD3\x5C\xA2\x3E\xA1\x5B\x41\xF5\xDF\xE5\x64\x43\x2D\xE9\xD5\x39\xAB\xD2\xA2\xDF\xB7\x8B\xD0\xC0\x80\x19\x1C\x45\xC0\x2D\x8C\xE8\xF8\x2D\xA4\x74\x56\x49\xC5\x05\xB5\x4F\x15\xDE\x6E\x44\x78\x39\x87\xA8\x7E\xBB\xF3\x79\x18\x91\xBB\xF4\x6F\x9D\xC1\xF0\x8C\x35\x8C\x5D\x01\xFB\xC3\x6D\xB9\xEF\x44\x6D\x79\x46\x31\x7E\x0A\xFE\xA9\x82\xC1\xFF\xEF\xAB\x6E\x20\xC4\x50\xC9\x5F\x9D\x4D\x9B\x17\x8C\x0C\xE5\x01\xC9\xA0\x41\x6A\x73\x53\xFA\xA5\x50\xB4\x6E\x25\x0F\xFB\x4C\x18\xF4\xFD\x52\xD9\x8E\x69\xB1\xE8\x11\x0F\xDE\x88\xD8\xFB\x1D\x49\xF7\xAA\xDE\x95\xCF\x20\x78\xC2\x60\x12\xDB\x25\x40\x8C\x6A\xFC\x7E\x42\x38\x40\x64\x12\xF7\x9E\x81\xE1\x93\x2E", - ["ValiCert Class 1 VA"] = "\x30\x82\x02\xE7\x30\x82\x02\x50\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xBB\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1B\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x61\x6C\x69\x43\x65\x72\x74\x2C\x20\x49\x6E\x63\x2E\x31\x35\x30\x33\x06\x03\x55\x04\x0B\x13\x2C\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x50\x6F\x6C\x69\x63\x79\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x2F\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x35\x32\x32\x32\x33\x34\x38\x5A\x17\x0D\x31\x39\x30\x36\x32\x35\x32\x32\x32\x33\x34\x38\x5A\x30\x81\xBB\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1B\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x61\x6C\x69\x43\x65\x72\x74\x2C\x20\x49\x6E\x63\x2E\x31\x35\x30\x33\x06\x03\x55\x04\x0B\x13\x2C\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x50\x6F\x6C\x69\x63\x79\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x2F\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xD8\x59\x82\x7A\x89\xB8\x96\xBA\xA6\x2F\x68\x6F\x58\x2E\xA7\x54\x1C\x06\x6E\xF4\xEA\x8D\x48\xBC\x31\x94\x17\xF0\xF3\x4E\xBC\xB2\xB8\x35\x92\x76\xB0\xD0\xA5\xA5\x01\xD7\x00\x03\x12\x22\x19\x08\xF8\xFF\x11\x23\x9B\xCE\x07\xF5\xBF\x69\x1A\x26\xFE\x4E\xE9\xD1\x7F\x9D\x2C\x40\x1D\x59\x68\x6E\xA6\xF8\x58\xB0\x9D\x1A\x8F\xD3\x3F\xF1\xDC\x19\x06\x81\xA8\x0E\xE0\x3A\xDD\xC8\x53\x45\x09\x06\xE6\x0F\x70\xC3\xFA\x40\xA6\x0E\xE2\x56\x05\x0F\x18\x4D\xFC\x20\x82\xD1\x73\x55\x74\x8D\x76\x72\xA0\x1D\x9D\x1D\xC0\xDD\x3F\x71\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x50\x68\x3D\x49\xF4\x2C\x1C\x06\x94\xDF\x95\x60\x7F\x96\x7B\x17\xFE\x4F\x71\xAD\x64\xC8\xDD\x77\xD2\xEF\x59\x55\xE8\x3F\xE8\x8E\x05\x2A\x21\xF2\x07\xD2\xB5\xA7\x52\xFE\x9C\xB1\xB6\xE2\x5B\x77\x17\x40\xEA\x72\xD6\x23\xCB\x28\x81\x32\xC3\x00\x79\x18\xEC\x59\x17\x89\xC9\xC6\x6A\x1E\x71\xC9\xFD\xB7\x74\xA5\x25\x45\x69\xC5\x48\xAB\x19\xE1\x45\x8A\x25\x6B\x19\xEE\xE5\xBB\x12\xF5\x7F\xF7\xA6\x8D\x51\xC3\xF0\x9D\x74\xB7\xA9\x3E\xA0\xA5\xFF\xB6\x49\x03\x13\xDA\x22\xCC\xED\x71\x82\x2B\x99\xCF\x3A\xB7\xF5\x2D\x72\xC8", - ["ValiCert Class 2 VA"] = "\x30\x82\x02\xE7\x30\x82\x02\x50\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xBB\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1B\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x61\x6C\x69\x43\x65\x72\x74\x2C\x20\x49\x6E\x63\x2E\x31\x35\x30\x33\x06\x03\x55\x04\x0B\x13\x2C\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x50\x6F\x6C\x69\x63\x79\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x2F\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x36\x30\x30\x31\x39\x35\x34\x5A\x17\x0D\x31\x39\x30\x36\x32\x36\x30\x30\x31\x39\x35\x34\x5A\x30\x81\xBB\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1B\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x61\x6C\x69\x43\x65\x72\x74\x2C\x20\x49\x6E\x63\x2E\x31\x35\x30\x33\x06\x03\x55\x04\x0B\x13\x2C\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x50\x6F\x6C\x69\x63\x79\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x2F\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xCE\x3A\x71\xCA\xE5\xAB\xC8\x59\x92\x55\xD7\xAB\xD8\x74\x0E\xF9\xEE\xD9\xF6\x55\x47\x59\x65\x47\x0E\x05\x55\xDC\xEB\x98\x36\x3C\x5C\x53\x5D\xD3\x30\xCF\x38\xEC\xBD\x41\x89\xED\x25\x42\x09\x24\x6B\x0A\x5E\xB3\x7C\xDD\x52\x2D\x4C\xE6\xD4\xD6\x7D\x5A\x59\xA9\x65\xD4\x49\x13\x2D\x24\x4D\x1C\x50\x6F\xB5\xC1\x85\x54\x3B\xFE\x71\xE4\xD3\x5C\x42\xF9\x80\xE0\x91\x1A\x0A\x5B\x39\x36\x67\xF3\x3F\x55\x7C\x1B\x3F\xB4\x5F\x64\x73\x34\xE3\xB4\x12\xBF\x87\x64\xF8\xDA\x12\xFF\x37\x27\xC1\xB3\x43\xBB\xEF\x7B\x6E\x2E\x69\xF7\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x3B\x7F\x50\x6F\x6F\x50\x94\x99\x49\x62\x38\x38\x1F\x4B\xF8\xA5\xC8\x3E\xA7\x82\x81\xF6\x2B\xC7\xE8\xC5\xCE\xE8\x3A\x10\x82\xCB\x18\x00\x8E\x4D\xBD\xA8\x58\x7F\xA1\x79\x00\xB5\xBB\xE9\x8D\xAF\x41\xD9\x0F\x34\xEE\x21\x81\x19\xA0\x32\x49\x28\xF4\xC4\x8E\x56\xD5\x52\x33\xFD\x50\xD5\x7E\x99\x6C\x03\xE4\xC9\x4C\xFC\xCB\x6C\xAB\x66\xB3\x4A\x21\x8C\xE5\xB5\x0C\x32\x3E\x10\xB2\xCC\x6C\xA1\xDC\x9A\x98\x4C\x02\x5B\xF3\xCE\xB9\x9E\xA5\x72\x0E\x4A\xB7\x3F\x3C\xE6\x16\x68\xF8\xBE\xED\x74\x4C\xBC\x5B\xD5\x62\x1F\x43\xDD", - ["RSA Root Certificate 1"] = "\x30\x82\x02\xE7\x30\x82\x02\x50\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xBB\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1B\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x61\x6C\x69\x43\x65\x72\x74\x2C\x20\x49\x6E\x63\x2E\x31\x35\x30\x33\x06\x03\x55\x04\x0B\x13\x2C\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x6F\x6C\x69\x63\x79\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x2F\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x36\x30\x30\x32\x32\x33\x33\x5A\x17\x0D\x31\x39\x30\x36\x32\x36\x30\x30\x32\x32\x33\x33\x5A\x30\x81\xBB\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1B\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x61\x6C\x69\x43\x65\x72\x74\x2C\x20\x49\x6E\x63\x2E\x31\x35\x30\x33\x06\x03\x55\x04\x0B\x13\x2C\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x6F\x6C\x69\x63\x79\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x2F\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xE3\x98\x51\x96\x1C\xE8\xD5\xB1\x06\x81\x6A\x57\xC3\x72\x75\x93\xAB\xCF\x9E\xA6\xFC\xF3\x16\x52\xD6\x2D\x4D\x9F\x35\x44\xA8\x2E\x04\x4D\x07\x49\x8A\x38\x29\xF5\x77\x37\xE7\xB7\xAB\x5D\xDF\x36\x71\x14\x99\x8F\xDC\xC2\x92\xF1\xE7\x60\x92\x97\xEC\xD8\x48\xDC\xBF\xC1\x02\x20\xC6\x24\xA4\x28\x4C\x30\x5A\x76\x6D\xB1\x5C\xF3\xDD\xDE\x9E\x10\x71\xA1\x88\xC7\x5B\x9B\x41\x6D\xCA\xB0\xB8\x8E\x15\xEE\xAD\x33\x2B\xCF\x47\x04\x5C\x75\x71\x0A\x98\x24\x98\x29\xA7\x49\x59\xA5\xDD\xF8\xB7\x43\x62\x61\xF3\xD3\xE2\xD0\x55\x3F\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x56\xBB\x02\x58\x84\x67\x08\x2C\xDF\x1F\xDB\x7B\x49\x33\xF5\xD3\x67\x9D\xF4\xB4\x0A\x10\xB3\xC9\xC5\x2C\xE2\x92\x6A\x71\x78\x27\xF2\x70\x83\x42\xD3\x3E\xCF\xA9\x54\xF4\xF1\xD8\x92\x16\x8C\xD1\x04\xCB\x4B\xAB\xC9\x9F\x45\xAE\x3C\x8A\xA9\xB0\x71\x33\x5D\xC8\xC5\x57\xDF\xAF\xA8\x35\xB3\x7F\x89\x87\xE9\xE8\x25\x92\xB8\x7F\x85\x7A\xAE\xD6\xBC\x1E\x37\x58\x2A\x67\xC9\x91\xCF\x2A\x81\x3E\xED\xC6\x39\xDF\xC0\x3E\x19\x9C\x19\xCC\x13\x4D\x82\x41\xB5\x8C\xDE\xE0\x3D\x60\x08\x20\x0F\x45\x7E\x6B\xA2\x7F\xA3\x8C\x15\xEE", - ["Verisign Class 3 Public Primary Certification Authority - G3"] = "\x30\x82\x04\x1A\x30\x82\x03\x02\x02\x11\x00\x9B\x7E\x06\x49\xA3\x3E\x62\xB9\xD5\xEE\x90\x48\x71\x29\xEF\x57\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\x30\x1E\x17\x0D\x39\x39\x31\x30\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\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\xCB\xBA\x9C\x52\xFC\x78\x1F\x1A\x1E\x6F\x1B\x37\x73\xBD\xF8\xC9\x6B\x94\x12\x30\x4F\xF0\x36\x47\xF5\xD0\x91\x0A\xF5\x17\xC8\xA5\x61\xC1\x16\x40\x4D\xFB\x8A\x61\x90\xE5\x76\x20\xC1\x11\x06\x7D\xAB\x2C\x6E\xA6\xF5\x11\x41\x8E\xFA\x2D\xAD\x2A\x61\x59\xA4\x67\x26\x4C\xD0\xE8\xBC\x52\x5B\x70\x20\x04\x58\xD1\x7A\xC9\xA4\x69\xBC\x83\x17\x64\xAD\x05\x8B\xBC\xD0\x58\xCE\x8D\x8C\xF5\xEB\xF0\x42\x49\x0B\x9D\x97\x27\x67\x32\x6E\xE1\xAE\x93\x15\x1C\x70\xBC\x20\x4D\x2F\x18\xDE\x92\x88\xE8\x6C\x85\x57\x11\x1A\xE9\x7E\xE3\x26\x11\x54\xA2\x45\x96\x55\x83\xCA\x30\x89\xE8\xDC\xD8\xA3\xED\x2A\x80\x3F\x7F\x79\x65\x57\x3E\x15\x20\x66\x08\x2F\x95\x93\xBF\xAA\x47\x2F\xA8\x46\x97\xF0\x12\xE2\xFE\xC2\x0A\x2B\x51\xE6\x76\xE6\xB7\x46\xB7\xE2\x0D\xA6\xCC\xA8\xC3\x4C\x59\x55\x89\xE6\xE8\x53\x5C\x1C\xEA\x9D\xF0\x62\x16\x0B\xA7\xC9\x5F\x0C\xF0\xDE\xC2\x76\xCE\xAF\xF7\x6A\xF2\xFA\x41\xA6\xA2\x33\x14\xC9\xE5\x7A\x63\xD3\x9E\x62\x37\xD5\x85\x65\x9E\x0E\xE6\x53\x24\x74\x1B\x5E\x1D\x12\x53\x5B\xC7\x2C\xE7\x83\x49\x3B\x15\xAE\x8A\x68\xB9\x57\x97\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x11\x14\x96\xC1\xAB\x92\x08\xF7\x3F\x2F\xC9\xB2\xFE\xE4\x5A\x9F\x64\xDE\xDB\x21\x4F\x86\x99\x34\x76\x36\x57\xDD\xD0\x15\x2F\xC5\xAD\x7F\x15\x1F\x37\x62\x73\x3E\xD4\xE7\x5F\xCE\x17\x03\xDB\x35\xFA\x2B\xDB\xAE\x60\x09\x5F\x1E\x5F\x8F\x6E\xBB\x0B\x3D\xEA\x5A\x13\x1E\x0C\x60\x6F\xB5\xC0\xB5\x23\x22\x2E\x07\x0B\xCB\xA9\x74\xCB\x47\xBB\x1D\xC1\xD7\xA5\x6B\xCC\x2F\xD2\x42\xFD\x49\xDD\xA7\x89\xCF\x53\xBA\xDA\x00\x5A\x28\xBF\x82\xDF\xF8\xBA\x13\x1D\x50\x86\x82\xFD\x8E\x30\x8F\x29\x46\xB0\x1E\x3D\x35\xDA\x38\x62\x16\x18\x4A\xAD\xE6\xB6\x51\x6C\xDE\xAF\x62\xEB\x01\xD0\x1E\x24\xFE\x7A\x8F\x12\x1A\x12\x68\xB8\xFB\x66\x99\x14\x14\x45\x5C\xAE\xE7\xAE\x69\x17\x81\x2B\x5A\x37\xC9\x5E\x2A\xF4\xC6\xE2\xA1\x5C\x54\x9B\xA6\x54\x00\xCF\xF0\xF1\xC1\xC7\x98\x30\x1A\x3B\x36\x16\xDB\xA3\x6E\xEA\xFD\xAD\xB2\xC2\xDA\xEF\x02\x47\x13\x8A\xC0\xF1\xB3\x31\xAD\x4F\x1C\xE1\x4F\x9C\xAF\x0F\x0C\x9D\xF7\x78\x0D\xD8\xF4\x35\x56\x80\xDA\xB7\x6D\x17\x8F\x9D\x1E\x81\x64\xE1\xFE\xC5\x45\xBA\xAD\x6B\xB9\x0A\x7A\x4E\x4F\x4B\x84\xEE\x4B\xF1\x7D\xDD\x11", - ["Verisign Class 4 Public Primary Certification Authority - G3"] = "\x30\x82\x04\x1A\x30\x82\x03\x02\x02\x11\x00\xEC\xA0\xA7\x8B\x6E\x75\x6A\x01\xCF\xC4\x7C\xCC\x2F\x94\x5E\xD7\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\x30\x1E\x17\x0D\x39\x39\x31\x30\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\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\xAD\xCB\xA5\x11\x69\xC6\x59\xAB\xF1\x8F\xB5\x19\x0F\x56\xCE\xCC\xB5\x1F\x20\xE4\x9E\x26\x25\x4B\xE0\x73\x65\x89\x59\xDE\xD0\x83\xE4\xF5\x0F\xB5\xBB\xAD\xF1\x7C\xE8\x21\xFC\xE4\xE8\x0C\xEE\x7C\x45\x22\x19\x76\x92\xB4\x13\xB7\x20\x5B\x09\xFA\x61\xAE\xA8\xF2\xA5\x8D\x85\xC2\x2A\xD6\xDE\x66\x36\xD2\x9B\x02\xF4\xA8\x92\x60\x7C\x9C\x69\xB4\x8F\x24\x1E\xD0\x86\x52\xF6\x32\x9C\x41\x58\x1E\x22\xBD\xCD\x45\x62\x95\x08\x6E\xD0\x66\xDD\x53\xA2\xCC\xF0\x10\xDC\x54\x73\x8B\x04\xA1\x46\x33\x33\x5C\x17\x40\xB9\x9E\x4D\xD3\xF3\xBE\x55\x83\xE8\xB1\x89\x8E\x5A\x7C\x9A\x96\x22\x90\x3B\x88\x25\xF2\xD2\x53\x88\x02\x0C\x0B\x78\xF2\xE6\x37\x17\x4B\x30\x46\x07\xE4\x80\x6D\xA6\xD8\x96\x2E\xE8\x2C\xF8\x11\xB3\x38\x0D\x66\xA6\x9B\xEA\xC9\x23\x5B\xDB\x8E\xE2\xF3\x13\x8E\x1A\x59\x2D\xAA\x02\xF0\xEC\xA4\x87\x66\xDC\xC1\x3F\xF5\xD8\xB9\xF4\xEC\x82\xC6\xD2\x3D\x95\x1D\xE5\xC0\x4F\x84\xC9\xD9\xA3\x44\x28\x06\x6A\xD7\x45\xAC\xF0\x6B\x6A\xEF\x4E\x5F\xF8\x11\x82\x1E\x38\x63\x34\x66\x50\xD4\x3E\x93\x73\xFA\x30\xC3\x66\xAD\xFF\x93\x2D\x97\xEF\x03\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x8F\xFA\x25\x6B\x4F\x5B\xE4\xA4\x4E\x27\x55\xAB\x22\x15\x59\x3C\xCA\xB5\x0A\xD4\x4A\xDB\xAB\xDD\xA1\x5F\x53\xC5\xA0\x57\x39\xC2\xCE\x47\x2B\xBE\x3A\xC8\x56\xBF\xC2\xD9\x27\x10\x3A\xB1\x05\x3C\xC0\x77\x31\xBB\x3A\xD3\x05\x7B\x6D\x9A\x1C\x30\x8C\x80\xCB\x93\x93\x2A\x83\xAB\x05\x51\x82\x02\x00\x11\x67\x6B\xF3\x88\x61\x47\x5F\x03\x93\xD5\x5B\x0D\xE0\xF1\xD4\xA1\x32\x35\x85\xB2\x3A\xDB\xB0\x82\xAB\xD1\xCB\x0A\xBC\x4F\x8C\x5B\xC5\x4B\x00\x3B\x1F\x2A\x82\xA6\x7E\x36\x85\xDC\x7E\x3C\x67\x00\xB5\xE4\x3B\x52\xE0\xA8\xEB\x5D\x15\xF9\xC6\x6D\xF0\xAD\x1D\x0E\x85\xB7\xA9\x9A\x73\x14\x5A\x5B\x8F\x41\x28\xC0\xD5\xE8\x2D\x4D\xA4\x5E\xCD\xAA\xD9\xED\xCE\xDC\xD8\xD5\x3C\x42\x1D\x17\xC1\x12\x5D\x45\x38\xC3\x38\xF3\xFC\x85\x2E\x83\x46\x48\xB2\xD7\x20\x5F\x92\x36\x8F\xE7\x79\x0F\x98\x5E\x99\xE8\xF0\xD0\xA4\xBB\xF5\x53\xBD\x2A\xCE\x59\xB0\xAF\x6E\x7F\x6C\xBB\xD2\x1E\x00\xB0\x21\xED\xF8\x41\x62\x82\xB9\xD8\xB2\xC4\xBB\x46\x50\xF3\x31\xC5\x8F\x01\xA8\x74\xEB\xF5\x78\x27\xDA\xE7\xF7\x66\x43\xF3\x9E\x83\x3E\x20\xAA\xC3\x35\x60\x91\xCE", - ["Entrust.net Secure Server CA"] = "\x30\x82\x04\xD8\x30\x82\x04\x41\xA0\x03\x02\x01\x02\x02\x04\x37\x4A\xD2\x43\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xC3\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x3B\x30\x39\x06\x03\x55\x04\x0B\x13\x32\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x3A\x30\x38\x06\x03\x55\x04\x03\x13\x31\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x53\x65\x63\x75\x72\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x39\x39\x30\x35\x32\x35\x31\x36\x30\x39\x34\x30\x5A\x17\x0D\x31\x39\x30\x35\x32\x35\x31\x36\x33\x39\x34\x30\x5A\x30\x81\xC3\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x3B\x30\x39\x06\x03\x55\x04\x0B\x13\x32\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x3A\x30\x38\x06\x03\x55\x04\x03\x13\x31\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x53\x65\x63\x75\x72\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x81\x9D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8B\x00\x30\x81\x87\x02\x81\x81\x00\xCD\x28\x83\x34\x54\x1B\x89\xF3\x0F\xAF\x37\x91\x31\xFF\xAF\x31\x60\xC9\xA8\xE8\xB2\x10\x68\xED\x9F\xE7\x93\x36\xF1\x0A\x64\xBB\x47\xF5\x04\x17\x3F\x23\x47\x4D\xC5\x27\x19\x81\x26\x0C\x54\x72\x0D\x88\x2D\xD9\x1F\x9A\x12\x9F\xBC\xB3\x71\xD3\x80\x19\x3F\x47\x66\x7B\x8C\x35\x28\xD2\xB9\x0A\xDF\x24\xDA\x9C\xD6\x50\x79\x81\x7A\x5A\xD3\x37\xF7\xC2\x4A\xD8\x29\x92\x26\x64\xD1\xE4\x98\x6C\x3A\x00\x8A\xF5\x34\x9B\x65\xF8\xED\xE3\x10\xFF\xFD\xB8\x49\x58\xDC\xA0\xDE\x82\x39\x6B\x81\xB1\x16\x19\x61\xB9\x54\xB6\xE6\x43\x02\x01\x03\xA3\x82\x01\xD7\x30\x82\x01\xD3\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x01\x19\x06\x03\x55\x1D\x1F\x04\x82\x01\x10\x30\x82\x01\x0C\x30\x81\xDE\xA0\x81\xDB\xA0\x81\xD8\xA4\x81\xD5\x30\x81\xD2\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x3B\x30\x39\x06\x03\x55\x04\x0B\x13\x32\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x3A\x30\x38\x06\x03\x55\x04\x03\x13\x31\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x53\x65\x63\x75\x72\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x29\xA0\x27\xA0\x25\x86\x23\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x52\x4C\x2F\x6E\x65\x74\x31\x2E\x63\x72\x6C\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x31\x39\x39\x39\x30\x35\x32\x35\x31\x36\x30\x39\x34\x30\x5A\x81\x0F\x32\x30\x31\x39\x30\x35\x32\x35\x31\x36\x30\x39\x34\x30\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xF0\x17\x62\x13\x55\x3D\xB3\xFF\x0A\x00\x6B\xFB\x50\x84\x97\xF3\xED\x62\xD0\x1A\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xF0\x17\x62\x13\x55\x3D\xB3\xFF\x0A\x00\x6B\xFB\x50\x84\x97\xF3\xED\x62\xD0\x1A\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x19\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0C\x30\x0A\x1B\x04\x56\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x90\xDC\x30\x02\xFA\x64\x74\xC2\xA7\x0A\xA5\x7C\x21\x8D\x34\x17\xA8\xFB\x47\x0E\xFF\x25\x7C\x8D\x13\x0A\xFB\xE4\x98\xB5\xEF\x8C\xF8\xC5\x10\x0D\xF7\x92\xBE\xF1\xC3\xD5\xD5\x95\x6A\x04\xBB\x2C\xCE\x26\x36\x65\xC8\x31\xC6\xE7\xEE\x3F\xE3\x57\x75\x84\x7A\x11\xEF\x46\x4F\x18\xF4\xD3\x98\xBB\xA8\x87\x32\xBA\x72\xF6\x3C\xE2\x3D\x9F\xD7\x1D\xD9\xC3\x60\x43\x8C\x58\x0E\x22\x96\x2F\x62\xA3\x2C\x1F\xBA\xAD\x05\xEF\xAB\x32\x78\x87\xA0\x54\x73\x19\xB5\x5C\x05\xF9\x52\x3E\x6D\x2D\x45\x0B\xF7\x0A\x93\xEA\xED\x06\xF9\xB2", - ["Entrust.net Premium 2048 Secure Server CA"] = "\x30\x82\x04\x5C\x30\x82\x03\x44\xA0\x03\x02\x01\x02\x02\x04\x38\x63\xB9\x66\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xB4\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x40\x30\x3E\x06\x03\x55\x04\x0B\x14\x37\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x5F\x32\x30\x34\x38\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2A\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x28\x32\x30\x34\x38\x29\x30\x1E\x17\x0D\x39\x39\x31\x32\x32\x34\x31\x37\x35\x30\x35\x31\x5A\x17\x0D\x31\x39\x31\x32\x32\x34\x31\x38\x32\x30\x35\x31\x5A\x30\x81\xB4\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x40\x30\x3E\x06\x03\x55\x04\x0B\x14\x37\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x5F\x32\x30\x34\x38\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2A\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x28\x32\x30\x34\x38\x29\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\xAD\x4D\x4B\xA9\x12\x86\xB2\xEA\xA3\x20\x07\x15\x16\x64\x2A\x2B\x4B\xD1\xBF\x0B\x4A\x4D\x8E\xED\x80\x76\xA5\x67\xB7\x78\x40\xC0\x73\x42\xC8\x68\xC0\xDB\x53\x2B\xDD\x5E\xB8\x76\x98\x35\x93\x8B\x1A\x9D\x7C\x13\x3A\x0E\x1F\x5B\xB7\x1E\xCF\xE5\x24\x14\x1E\xB1\x81\xA9\x8D\x7D\xB8\xCC\x6B\x4B\x03\xF1\x02\x0C\xDC\xAB\xA5\x40\x24\x00\x7F\x74\x94\xA1\x9D\x08\x29\xB3\x88\x0B\xF5\x87\x77\x9D\x55\xCD\xE4\xC3\x7E\xD7\x6A\x64\xAB\x85\x14\x86\x95\x5B\x97\x32\x50\x6F\x3D\xC8\xBA\x66\x0C\xE3\xFC\xBD\xB8\x49\xC1\x76\x89\x49\x19\xFD\xC0\xA8\xBD\x89\xA3\x67\x2F\xC6\x9F\xBC\x71\x19\x60\xB8\x2D\xE9\x2C\xC9\x90\x76\x66\x7B\x94\xE2\xAF\x78\xD6\x65\x53\x5D\x3C\xD6\x9C\xB2\xCF\x29\x03\xF9\x2F\xA4\x50\xB2\xD4\x48\xCE\x05\x32\x55\x8A\xFD\xB2\x64\x4C\x0E\xE4\x98\x07\x75\xDB\x7F\xDF\xB9\x08\x55\x60\x85\x30\x29\xF9\x7B\x48\xA4\x69\x86\xE3\x35\x3F\x1E\x86\x5D\x7A\x7A\x15\xBD\xEF\x00\x8E\x15\x22\x54\x17\x00\x90\x26\x93\xBC\x0E\x49\x68\x91\xBF\xF8\x47\xD3\x9D\x95\x42\xC1\x0E\x4D\xDF\x6F\x26\xCF\xC3\x18\x21\x62\x66\x43\x70\xD6\xD5\xC0\x07\xE1\x02\x03\x01\x00\x01\xA3\x74\x30\x72\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x55\xE4\x81\xD1\x11\x80\xBE\xD8\x89\xB9\x08\xA3\x31\xF9\xA1\x24\x09\x16\xB9\x70\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x55\xE4\x81\xD1\x11\x80\xBE\xD8\x89\xB9\x08\xA3\x31\xF9\xA1\x24\x09\x16\xB9\x70\x30\x1D\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x10\x30\x0E\x1B\x08\x56\x35\x2E\x30\x3A\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x59\x47\xAC\x21\x84\x8A\x17\xC9\x9C\x89\x53\x1E\xBA\x80\x85\x1A\xC6\x3C\x4E\x3E\xB1\x9C\xB6\x7C\xC6\x92\x5D\x18\x64\x02\xE3\xD3\x06\x08\x11\x61\x7C\x63\xE3\x2B\x9D\x31\x03\x70\x76\xD2\xA3\x28\xA0\xF4\xBB\x9A\x63\x73\xED\x6D\xE5\x2A\xDB\xED\x14\xA9\x2B\xC6\x36\x11\xD0\x2B\xEB\x07\x8B\xA5\xDA\x9E\x5C\x19\x9D\x56\x12\xF5\x54\x29\xC8\x05\xED\xB2\x12\x2A\x8D\xF4\x03\x1B\xFF\xE7\x92\x10\x87\xB0\x3A\xB5\xC3\x9D\x05\x37\x12\xA3\xC7\xF4\x15\xB9\xD5\xA4\x39\x16\x9B\x53\x3A\x23\x91\xF1\xA8\x82\xA2\x6A\x88\x68\xC1\x79\x02\x22\xBC\xAA\xA6\xD6\xAE\xDF\xB0\x14\x5F\xB8\x87\xD0\xDD\x7C\x7F\x7B\xFF\xAF\x1C\xCF\xE6\xDB\x07\xAD\x5E\xDB\x85\x9D\xD0\x2B\x0D\x33\xDB\x04\xD1\xE6\x49\x40\x13\x2B\x76\xFB\x3E\xE9\x9C\x89\x0F\x15\xCE\x18\xB0\x85\x78\x21\x4F\x6B\x4F\x0E\xFA\x36\x67\xCD\x07\xF2\xFF\x08\xD0\xE2\xDE\xD9\xBF\x2A\xAF\xB8\x87\x86\x21\x3C\x04\xCA\xB7\x94\x68\x7F\xCF\x3C\xE9\x98\xD7\x38\xFF\xEC\xC0\xD9\x50\xF0\x2E\x4B\x58\xAE\x46\x6F\xD0\x2E\xC3\x60\xDA\x72\x55\x72\xBD\x4C\x45\x9E\x61\xBA\xBF\x84\x81\x92\x03\xD1\xD2\x69\x7C\xC5", - ["Baltimore CyberTrust Root"] = "\x30\x82\x03\x77\x30\x82\x02\x5F\xA0\x03\x02\x01\x02\x02\x04\x02\x00\x00\xB9\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x45\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x13\x09\x42\x61\x6C\x74\x69\x6D\x6F\x72\x65\x31\x13\x30\x11\x06\x03\x55\x04\x0B\x13\x0A\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x42\x61\x6C\x74\x69\x6D\x6F\x72\x65\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x31\x32\x31\x38\x34\x36\x30\x30\x5A\x17\x0D\x32\x35\x30\x35\x31\x32\x32\x33\x35\x39\x30\x30\x5A\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x45\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x13\x09\x42\x61\x6C\x74\x69\x6D\x6F\x72\x65\x31\x13\x30\x11\x06\x03\x55\x04\x0B\x13\x0A\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x42\x61\x6C\x74\x69\x6D\x6F\x72\x65\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x52\x6F\x6F\x74\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\xA3\x04\xBB\x22\xAB\x98\x3D\x57\xE8\x26\x72\x9A\xB5\x79\xD4\x29\xE2\xE1\xE8\x95\x80\xB1\xB0\xE3\x5B\x8E\x2B\x29\x9A\x64\xDF\xA1\x5D\xED\xB0\x09\x05\x6D\xDB\x28\x2E\xCE\x62\xA2\x62\xFE\xB4\x88\xDA\x12\xEB\x38\xEB\x21\x9D\xC0\x41\x2B\x01\x52\x7B\x88\x77\xD3\x1C\x8F\xC7\xBA\xB9\x88\xB5\x6A\x09\xE7\x73\xE8\x11\x40\xA7\xD1\xCC\xCA\x62\x8D\x2D\xE5\x8F\x0B\xA6\x50\xD2\xA8\x50\xC3\x28\xEA\xF5\xAB\x25\x87\x8A\x9A\x96\x1C\xA9\x67\xB8\x3F\x0C\xD5\xF7\xF9\x52\x13\x2F\xC2\x1B\xD5\x70\x70\xF0\x8F\xC0\x12\xCA\x06\xCB\x9A\xE1\xD9\xCA\x33\x7A\x77\xD6\xF8\xEC\xB9\xF1\x68\x44\x42\x48\x13\xD2\xC0\xC2\xA4\xAE\x5E\x60\xFE\xB6\xA6\x05\xFC\xB4\xDD\x07\x59\x02\xD4\x59\x18\x98\x63\xF5\xA5\x63\xE0\x90\x0C\x7D\x5D\xB2\x06\x7A\xF3\x85\xEA\xEB\xD4\x03\xAE\x5E\x84\x3E\x5F\xFF\x15\xED\x69\xBC\xF9\x39\x36\x72\x75\xCF\x77\x52\x4D\xF3\xC9\x90\x2C\xB9\x3D\xE5\xC9\x23\x53\x3F\x1F\x24\x98\x21\x5C\x07\x99\x29\xBD\xC6\x3A\xEC\xE7\x6E\x86\x3A\x6B\x97\x74\x63\x33\xBD\x68\x18\x31\xF0\x78\x8D\x76\xBF\xFC\x9E\x8E\x5D\x2A\x86\xA7\x4D\x90\xDC\x27\x1A\x39\x02\x03\x01\x00\x01\xA3\x45\x30\x43\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE5\x9D\x59\x30\x82\x47\x58\xCC\xAC\xFA\x08\x54\x36\x86\x7B\x3A\xB5\x04\x4D\xF0\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x03\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x85\x0C\x5D\x8E\xE4\x6F\x51\x68\x42\x05\xA0\xDD\xBB\x4F\x27\x25\x84\x03\xBD\xF7\x64\xFD\x2D\xD7\x30\xE3\xA4\x10\x17\xEB\xDA\x29\x29\xB6\x79\x3F\x76\xF6\x19\x13\x23\xB8\x10\x0A\xF9\x58\xA4\xD4\x61\x70\xBD\x04\x61\x6A\x12\x8A\x17\xD5\x0A\xBD\xC5\xBC\x30\x7C\xD6\xE9\x0C\x25\x8D\x86\x40\x4F\xEC\xCC\xA3\x7E\x38\xC6\x37\x11\x4F\xED\xDD\x68\x31\x8E\x4C\xD2\xB3\x01\x74\xEE\xBE\x75\x5E\x07\x48\x1A\x7F\x70\xFF\x16\x5C\x84\xC0\x79\x85\xB8\x05\xFD\x7F\xBE\x65\x11\xA3\x0F\xC0\x02\xB4\xF8\x52\x37\x39\x04\xD5\xA9\x31\x7A\x18\xBF\xA0\x2A\xF4\x12\x99\xF7\xA3\x45\x82\xE3\x3C\x5E\xF5\x9D\x9E\xB5\xC8\x9E\x7C\x2E\xC8\xA4\x9E\x4E\x08\x14\x4B\x6D\xFD\x70\x6D\x6B\x1A\x63\xBD\x64\xE6\x1F\xB7\xCE\xF0\xF2\x9F\x2E\xBB\x1B\xB7\xF2\x50\x88\x73\x92\xC2\xE2\xE3\x16\x8D\x9A\x32\x02\xAB\x8E\x18\xDD\xE9\x10\x11\xEE\x7E\x35\xAB\x90\xAF\x3E\x30\x94\x7A\xD0\x33\x3D\xA7\x65\x0F\xF5\xFC\x8E\x9E\x62\xCF\x47\x44\x2C\x01\x5D\xBB\x1D\xB5\x32\xD2\x47\xD2\x38\x2E\xD0\xFE\x81\xDC\x32\x6A\x1E\xB5\xEE\x3C\xD5\xFC\xE7\x81\x1D\x19\xC3\x24\x42\xEA\x63\x39\xA9", - ["Equifax Secure Global eBusiness CA"] = "\x30\x82\x02\x90\x30\x82\x01\xF9\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6E\x63\x2E\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x47\x6C\x6F\x62\x61\x6C\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x31\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x17\x0D\x32\x30\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6E\x63\x2E\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x47\x6C\x6F\x62\x61\x6C\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x31\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xBA\xE7\x17\x90\x02\x65\xB1\x34\x55\x3C\x49\xC2\x51\xD5\xDF\xA7\xD1\x37\x8F\xD1\xE7\x81\x73\x41\x52\x60\x9B\x9D\xA1\x17\x26\x78\xAD\xC7\xB1\xE8\x26\x94\x32\xB5\xDE\x33\x8D\x3A\x2F\xDB\xF2\x9A\x7A\x5A\x73\x98\xA3\x5C\xE9\xFB\x8A\x73\x1B\x5C\xE7\xC3\xBF\x80\x6C\xCD\xA9\xF4\xD6\x2B\xC0\xF7\xF9\x99\xAA\x63\xA2\xB1\x47\x02\x0F\xD4\xE4\x51\x3A\x12\x3C\x6C\x8A\x5A\x54\x84\x70\xDB\xC1\xC5\x90\xCF\x72\x45\xCB\xA8\x59\xC0\xCD\x33\x9D\x3F\xA3\x96\xEB\x85\x33\x21\x1C\x3E\x1E\x3E\x60\x6E\x76\x9C\x67\x85\xC5\xC8\xC3\x61\x02\x03\x01\x00\x01\xA3\x66\x30\x64\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xBE\xA8\xA0\x74\x72\x50\x6B\x44\xB7\xC9\x23\xD8\xFB\xA8\xFF\xB3\x57\x6B\x68\x6C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xBE\xA8\xA0\x74\x72\x50\x6B\x44\xB7\xC9\x23\xD8\xFB\xA8\xFF\xB3\x57\x6B\x68\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x30\xE2\x01\x51\xAA\xC7\xEA\x5F\xDA\xB9\xD0\x65\x0F\x30\xD6\x3E\xDA\x0D\x14\x49\x6E\x91\x93\x27\x14\x31\xEF\xC4\xF7\x2D\x45\xF8\xEC\xC7\xBF\xA2\x41\x0D\x23\xB4\x92\xF9\x19\x00\x67\xBD\x01\xAF\xCD\xE0\x71\xFC\x5A\xCF\x64\xC4\xE0\x96\x98\xD0\xA3\x40\xE2\x01\x8A\xEF\x27\x07\xF1\x65\x01\x8A\x44\x2D\x06\x65\x75\x52\xC0\x86\x10\x20\x21\x5F\x6C\x6B\x0F\x6C\xAE\x09\x1C\xAF\xF2\xA2\x18\x34\xC4\x75\xA4\x73\x1C\xF1\x8D\xDC\xEF\xAD\xF9\xB3\x76\xB4\x92\xBF\xDC\x95\x10\x1E\xBE\xCB\xC8\x3B\x5A\x84\x60\x19\x56\x94\xA9\x55", - ["Equifax Secure eBusiness CA 1"] = "\x30\x82\x02\x82\x30\x82\x01\xEB\xA0\x03\x02\x01\x02\x02\x01\x04\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6E\x63\x2E\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x31\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x17\x0D\x32\x30\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x30\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6E\x63\x2E\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x31\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xCE\x2F\x19\xBC\x17\xB7\x77\xDE\x93\xA9\x5F\x5A\x0D\x17\x4F\x34\x1A\x0C\x98\xF4\x22\xD9\x59\xD4\xC4\x68\x46\xF0\xB4\x35\xC5\x85\x03\x20\xC6\xAF\x45\xA5\x21\x51\x45\x41\xEB\x16\x58\x36\x32\x6F\xE2\x50\x62\x64\xF9\xFD\x51\x9C\xAA\x24\xD9\xF4\x9D\x83\x2A\x87\x0A\x21\xD3\x12\x38\x34\x6C\x8D\x00\x6E\x5A\xA0\xD9\x42\xEE\x1A\x21\x95\xF9\x52\x4C\x55\x5A\xC5\x0F\x38\x4F\x46\xFA\x6D\xF8\x2E\x35\xD6\x1D\x7C\xEB\xE2\xF0\xB0\x75\x80\xC8\xA9\x13\xAC\xBE\x88\xEF\x3A\x6E\xAB\x5F\x2A\x38\x62\x02\xB0\x12\x7B\xFE\x8F\xA6\x03\x02\x03\x01\x00\x01\xA3\x66\x30\x64\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x4A\x78\x32\x52\x11\xDB\x59\x16\x36\x5E\xDF\xC1\x14\x36\x40\x6A\x47\x7C\x4C\xA1\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x4A\x78\x32\x52\x11\xDB\x59\x16\x36\x5E\xDF\xC1\x14\x36\x40\x6A\x47\x7C\x4C\xA1\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x75\x5B\xA8\x9B\x03\x11\xE6\xE9\x56\x4C\xCD\xF9\xA9\x4C\xC0\x0D\x9A\xF3\xCC\x65\x69\xE6\x25\x76\xCC\x59\xB7\xD6\x54\xC3\x1D\xCD\x99\xAC\x19\xDD\xB4\x85\xD5\xE0\x3D\xFC\x62\x20\xA7\x84\x4B\x58\x65\xF1\xE2\xF9\x95\x21\x3F\xF5\xD4\x7E\x58\x1E\x47\x87\x54\x3E\x58\xA1\xB5\xB5\xF8\x2A\xEF\x71\xE7\xBC\xC3\xF6\xB1\x49\x46\xE2\xD7\xA0\x6B\xE5\x56\x7A\x9A\x27\x98\x7C\x46\x62\x14\xE7\xC9\xFC\x6E\x03\x12\x79\x80\x38\x1D\x48\x82\x8D\xFC\x17\xFE\x2A\x96\x2B\xB5\x62\xA6\xA6\x3D\xBD\x7F\x92\x59\xCD\x5A\x2A\x82\xB2\x37\x79", - ["Equifax Secure eBusiness CA 2"] = "\x30\x82\x03\x20\x30\x82\x02\x89\xA0\x03\x02\x01\x02\x02\x04\x37\x70\xCF\xB5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x32\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x33\x31\x32\x31\x34\x34\x35\x5A\x17\x0D\x31\x39\x30\x36\x32\x33\x31\x32\x31\x34\x34\x35\x5A\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x32\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xE4\x39\x39\x93\x1E\x52\x06\x1B\x28\x36\xF8\xB2\xA3\x29\xC5\xED\x8E\xB2\x11\xBD\xFE\xEB\xE7\xB4\x74\xC2\x8F\xFF\x05\xE7\xD9\x9D\x06\xBF\x12\xC8\x3F\x0E\xF2\xD6\xD1\x24\xB2\x11\xDE\xD1\x73\x09\x8A\xD4\xB1\x2C\x98\x09\x0D\x1E\x50\x46\xB2\x83\xA6\x45\x8D\x62\x68\xBB\x85\x1B\x20\x70\x32\xAA\x40\xCD\xA6\x96\x5F\xC4\x71\x37\x3F\x04\xF3\xB7\x41\x24\x39\x07\x1A\x1E\x2E\x61\x58\xA0\x12\x0B\xE5\xA5\xDF\xC5\xAB\xEA\x37\x71\xCC\x1C\xC8\x37\x3A\xB9\x97\x52\xA7\xAC\xC5\x6A\x24\x94\x4E\x9C\x7B\xCF\xC0\x6A\xD6\xDF\x21\xBD\x02\x03\x01\x00\x01\xA3\x82\x01\x09\x30\x82\x01\x05\x30\x70\x06\x03\x55\x1D\x1F\x04\x69\x30\x67\x30\x65\xA0\x63\xA0\x61\xA4\x5F\x30\x5D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x32\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x1A\x06\x03\x55\x1D\x10\x04\x13\x30\x11\x81\x0F\x32\x30\x31\x39\x30\x36\x32\x33\x31\x32\x31\x34\x34\x35\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x50\x9E\x0B\xEA\xAF\x5E\xB9\x20\x48\xA6\x50\x6A\xCB\xFD\xD8\x20\x7A\xA7\x82\x76\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x50\x9E\x0B\xEA\xAF\x5E\xB9\x20\x48\xA6\x50\x6A\xCB\xFD\xD8\x20\x7A\xA7\x82\x76\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x1A\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0D\x30\x0B\x1B\x05\x56\x33\x2E\x30\x63\x03\x02\x06\xC0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x0C\x86\x82\xAD\xE8\x4E\x1A\xF5\x8E\x89\x27\xE2\x35\x58\x3D\x29\xB4\x07\x8F\x36\x50\x95\xBF\x6E\xC1\x9E\xEB\xC4\x90\xB2\x85\xA8\xBB\xB7\x42\xE0\x0F\x07\x39\xDF\xFB\x9E\x90\xB2\xD1\xC1\x3E\x53\x9F\x03\x44\xB0\x7E\x4B\xF4\x6F\xE4\x7C\x1F\xE7\xE2\xB1\xE4\xB8\x9A\xEF\xC3\xBD\xCE\xDE\x0B\x32\x34\xD9\xDE\x28\xED\x33\x6B\xC4\xD4\xD7\x3D\x12\x58\xAB\x7D\x09\x2D\xCB\x70\xF5\x13\x8A\x94\xA1\x27\xA4\xD6\x70\xC5\x6D\x94\xB5\xC9\x7D\x9D\xA0\xD2\xC6\x08\x49\xD9\x66\x9B\xA6\xD3\xF4\x0B\xDC\xC5\x26\x57\xE1\x91\x30\xEA\xCD", - ["AddTrust Low-Value Services Root"] = "\x30\x82\x04\x18\x30\x82\x03\x00\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x41\x64\x64\x54\x72\x75\x73\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x33\x30\x31\x30\x33\x38\x33\x31\x5A\x17\x0D\x32\x30\x30\x35\x33\x30\x31\x30\x33\x38\x33\x31\x5A\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x41\x64\x64\x54\x72\x75\x73\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x43\x41\x20\x52\x6F\x6F\x74\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\x96\x96\xD4\x21\x49\x60\xE2\x6B\xE8\x41\x07\x0C\xDE\xC4\xE0\xDC\x13\x23\xCD\xC1\x35\xC7\xFB\xD6\x4E\x11\x0A\x67\x5E\xF5\x06\x5B\x6B\xA5\x08\x3B\x5B\x29\x16\x3A\xE7\x87\xB2\x34\x06\xC5\xBC\x05\xA5\x03\x7C\x82\xCB\x29\x10\xAE\xE1\x88\x81\xBD\xD6\x9E\xD3\xFE\x2D\x56\xC1\x15\xCE\xE3\x26\x9D\x15\x2E\x10\xFB\x06\x8F\x30\x04\xDE\xA7\xB4\x63\xB4\xFF\xB1\x9C\xAE\x3C\xAF\x77\xB6\x56\xC5\xB5\xAB\xA2\xE9\x69\x3A\x3D\x0E\x33\x79\x32\x3F\x70\x82\x92\x99\x61\x6D\x8D\x30\x08\x8F\x71\x3F\xA6\x48\x57\x19\xF8\x25\xDC\x4B\x66\x5C\xA5\x74\x8F\x98\xAE\xC8\xF9\xC0\x06\x22\xE7\xAC\x73\xDF\xA5\x2E\xFB\x52\xDC\xB1\x15\x65\x20\xFA\x35\x66\x69\xDE\xDF\x2C\xF1\x6E\xBC\x30\xDB\x2C\x24\x12\xDB\xEB\x35\x35\x68\x90\xCB\x00\xB0\x97\x21\x3D\x74\x21\x23\x65\x34\x2B\xBB\x78\x59\xA3\xD6\xE1\x76\x39\x9A\xA4\x49\x8E\x8C\x74\xAF\x6E\xA4\x9A\xA3\xD9\x9B\xD2\x38\x5C\x9B\xA2\x18\xCC\x75\x23\x84\xBE\xEB\xE2\x4D\x33\x71\x8E\x1A\xF0\xC2\xF8\xC7\x1D\xA2\xAD\x03\x97\x2C\xF8\xCF\x25\xC6\xF6\xB8\x24\x31\xB1\x63\x5D\x92\x7F\x63\xF0\x25\xC9\x53\x2E\x1F\xBF\x4D\x02\x03\x01\x00\x01\xA3\x81\xD2\x30\x81\xCF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x95\xB1\xB4\xF0\x94\xB6\xBD\xC7\xDA\xD1\x11\x09\x21\xBE\xC1\xAF\x49\xFD\x10\x7B\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x8F\x06\x03\x55\x1D\x23\x04\x81\x87\x30\x81\x84\x80\x14\x95\xB1\xB4\xF0\x94\xB6\xBD\xC7\xDA\xD1\x11\x09\x21\xBE\xC1\xAF\x49\xFD\x10\x7B\xA1\x69\xA4\x67\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x41\x64\x64\x54\x72\x75\x73\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x43\x41\x20\x52\x6F\x6F\x74\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x2C\x6D\x64\x1B\x1F\xCD\x0D\xDD\xB9\x01\xFA\x96\x63\x34\x32\x48\x47\x99\xAE\x97\xED\xFD\x72\x16\xA6\x73\x47\x5A\xF4\xEB\xDD\xE9\xF5\xD6\xFB\x45\xCC\x29\x89\x44\x5D\xBF\x46\x39\x3D\xE8\xEE\xBC\x4D\x54\x86\x1E\x1D\x6C\xE3\x17\x27\x43\xE1\x89\x56\x2B\xA9\x6F\x72\x4E\x49\x33\xE3\x72\x7C\x2A\x23\x9A\xBC\x3E\xFF\x28\x2A\xED\xA3\xFF\x1C\x23\xBA\x43\x57\x09\x67\x4D\x4B\x62\x06\x2D\xF8\xFF\x6C\x9D\x60\x1E\xD8\x1C\x4B\x7D\xB5\x31\x2F\xD9\xD0\x7C\x5D\xF8\xDE\x6B\x83\x18\x78\x37\x57\x2F\xE8\x33\x07\x67\xDF\x1E\xC7\x6B\x2A\x95\x76\xAE\x8F\x57\xA3\xF0\xF4\x52\xB4\xA9\x53\x08\xCF\xE0\x4F\xD3\x7A\x53\x8B\xFD\xBB\x1C\x56\x36\xF2\xFE\xB2\xB6\xE5\x76\xBB\xD5\x22\x65\xA7\x3F\xFE\xD1\x66\xAD\x0B\xBC\x6B\x99\x86\xEF\x3F\x7D\xF3\x18\x32\xCA\x7B\xC6\xE3\xAB\x64\x46\x95\xF8\x26\x69\xD9\x55\x83\x7B\x2C\x96\x07\xFF\x59\x2C\x44\xA3\xC6\xE5\xE9\xA9\xDC\xA1\x63\x80\x5A\x21\x5E\x21\xCF\x53\x54\xF0\xBA\x6F\x89\xDB\xA8\xAA\x95\xCF\x8B\xE3\x71\xCC\x1E\x1B\x20\x44\x08\xC0\x7A\xB6\x40\xFD\xC4\xE4\x35\xE1\x1D\x16\x1C\xD0\xBC\x2B\x8E\xD6\x71\xD9", - ["AddTrust External Root"] = "\x30\x82\x04\x36\x30\x82\x03\x1E\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x6F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x33\x30\x31\x30\x34\x38\x33\x38\x5A\x17\x0D\x32\x30\x30\x35\x33\x30\x31\x30\x34\x38\x33\x38\x5A\x30\x6F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x43\x41\x20\x52\x6F\x6F\x74\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\xB7\xF7\x1A\x33\xE6\xF2\x00\x04\x2D\x39\xE0\x4E\x5B\xED\x1F\xBC\x6C\x0F\xCD\xB5\xFA\x23\xB6\xCE\xDE\x9B\x11\x33\x97\xA4\x29\x4C\x7D\x93\x9F\xBD\x4A\xBC\x93\xED\x03\x1A\xE3\x8F\xCF\xE5\x6D\x50\x5A\xD6\x97\x29\x94\x5A\x80\xB0\x49\x7A\xDB\x2E\x95\xFD\xB8\xCA\xBF\x37\x38\x2D\x1E\x3E\x91\x41\xAD\x70\x56\xC7\xF0\x4F\x3F\xE8\x32\x9E\x74\xCA\xC8\x90\x54\xE9\xC6\x5F\x0F\x78\x9D\x9A\x40\x3C\x0E\xAC\x61\xAA\x5E\x14\x8F\x9E\x87\xA1\x6A\x50\xDC\xD7\x9A\x4E\xAF\x05\xB3\xA6\x71\x94\x9C\x71\xB3\x50\x60\x0A\xC7\x13\x9D\x38\x07\x86\x02\xA8\xE9\xA8\x69\x26\x18\x90\xAB\x4C\xB0\x4F\x23\xAB\x3A\x4F\x84\xD8\xDF\xCE\x9F\xE1\x69\x6F\xBB\xD7\x42\xD7\x6B\x44\xE4\xC7\xAD\xEE\x6D\x41\x5F\x72\x5A\x71\x08\x37\xB3\x79\x65\xA4\x59\xA0\x94\x37\xF7\x00\x2F\x0D\xC2\x92\x72\xDA\xD0\x38\x72\xDB\x14\xA8\x45\xC4\x5D\x2A\x7D\xB7\xB4\xD6\xC4\xEE\xAC\xCD\x13\x44\xB7\xC9\x2B\xDD\x43\x00\x25\xFA\x61\xB9\x69\x6A\x58\x23\x11\xB7\xA7\x33\x8F\x56\x75\x59\xF5\xCD\x29\xD7\x46\xB7\x0A\x2B\x65\xB6\xD3\x42\x6F\x15\xB2\xB8\x7B\xFB\xEF\xE9\x5D\x53\xD5\x34\x5A\x27\x02\x03\x01\x00\x01\xA3\x81\xDC\x30\x81\xD9\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xAD\xBD\x98\x7A\x34\xB4\x26\xF7\xFA\xC4\x26\x54\xEF\x03\xBD\xE0\x24\xCB\x54\x1A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x99\x06\x03\x55\x1D\x23\x04\x81\x91\x30\x81\x8E\x80\x14\xAD\xBD\x98\x7A\x34\xB4\x26\xF7\xFA\xC4\x26\x54\xEF\x03\xBD\xE0\x24\xCB\x54\x1A\xA1\x73\xA4\x71\x30\x6F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x43\x41\x20\x52\x6F\x6F\x74\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xB0\x9B\xE0\x85\x25\xC2\xD6\x23\xE2\x0F\x96\x06\x92\x9D\x41\x98\x9C\xD9\x84\x79\x81\xD9\x1E\x5B\x14\x07\x23\x36\x65\x8F\xB0\xD8\x77\xBB\xAC\x41\x6C\x47\x60\x83\x51\xB0\xF9\x32\x3D\xE7\xFC\xF6\x26\x13\xC7\x80\x16\xA5\xBF\x5A\xFC\x87\xCF\x78\x79\x89\x21\x9A\xE2\x4C\x07\x0A\x86\x35\xBC\xF2\xDE\x51\xC4\xD2\x96\xB7\xDC\x7E\x4E\xEE\x70\xFD\x1C\x39\xEB\x0C\x02\x51\x14\x2D\x8E\xBD\x16\xE0\xC1\xDF\x46\x75\xE7\x24\xAD\xEC\xF4\x42\xB4\x85\x93\x70\x10\x67\xBA\x9D\x06\x35\x4A\x18\xD3\x2B\x7A\xCC\x51\x42\xA1\x7A\x63\xD1\xE6\xBB\xA1\xC5\x2B\xC2\x36\xBE\x13\x0D\xE6\xBD\x63\x7E\x79\x7B\xA7\x09\x0D\x40\xAB\x6A\xDD\x8F\x8A\xC3\xF6\xF6\x8C\x1A\x42\x05\x51\xD4\x45\xF5\x9F\xA7\x62\x21\x68\x15\x20\x43\x3C\x99\xE7\x7C\xBD\x24\xD8\xA9\x91\x17\x73\x88\x3F\x56\x1B\x31\x38\x18\xB4\x71\x0F\x9A\xCD\xC8\x0E\x9E\x8E\x2E\x1B\xE1\x8C\x98\x83\xCB\x1F\x31\xF1\x44\x4C\xC6\x04\x73\x49\x76\x60\x0F\xC7\xF8\xBD\x17\x80\x6B\x2E\xE9\xCC\x4C\x0E\x5A\x9A\x79\x0F\x20\x0A\x2E\xD5\x9E\x63\x26\x1E\x55\x92\x94\xD8\x82\x17\x5A\x7B\xD0\xBC\xC7\x8F\x4E\x86\x04", - ["AddTrust Public Services Root"] = "\x30\x82\x04\x15\x30\x82\x02\xFD\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x41\x64\x64\x54\x72\x75\x73\x74\x20\x50\x75\x62\x6C\x69\x63\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x33\x30\x31\x30\x34\x31\x35\x30\x5A\x17\x0D\x32\x30\x30\x35\x33\x30\x31\x30\x34\x31\x35\x30\x5A\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x41\x64\x64\x54\x72\x75\x73\x74\x20\x50\x75\x62\x6C\x69\x63\x20\x43\x41\x20\x52\x6F\x6F\x74\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\xE9\x1A\x30\x8F\x83\x88\x14\xC1\x20\xD8\x3C\x9B\x8F\x1B\x7E\x03\x74\xBB\xDA\x69\xD3\x46\xA5\xF8\x8E\xC2\x0C\x11\x90\x51\xA5\x2F\x66\x54\x40\x55\xEA\xDB\x1F\x4A\x56\xEE\x9F\x23\x6E\xF4\x39\xCB\xA1\xB9\x6F\xF2\x7E\xF9\x5D\x87\x26\x61\x9E\x1C\xF8\xE2\xEC\xA6\x81\xF8\x21\xC5\x24\xCC\x11\x0C\x3F\xDB\x26\x72\x7A\xC7\x01\x97\x07\x17\xF9\xD7\x18\x2C\x30\x7D\x0E\x7A\x1E\x62\x1E\xC6\x4B\xC0\xFD\x7D\x62\x77\xD3\x44\x1E\x27\xF6\x3F\x4B\x44\xB3\xB7\x38\xD9\x39\x1F\x60\xD5\x51\x92\x73\x03\xB4\x00\x69\xE3\xF3\x14\x4E\xEE\xD1\xDC\x09\xCF\x77\x34\x46\x50\xB0\xF8\x11\xF2\xFE\x38\x79\xF7\x07\x39\xFE\x51\x92\x97\x0B\x5B\x08\x5F\x34\x86\x01\xAD\x88\x97\xEB\x66\xCD\x5E\xD1\xFF\xDC\x7D\xF2\x84\xDA\xBA\x77\xAD\xDC\x80\x08\xC7\xA7\x87\xD6\x55\x9F\x97\x6A\xE8\xC8\x11\x64\xBA\xE7\x19\x29\x3F\x11\xB3\x78\x90\x84\x20\x52\x5B\x11\xEF\x78\xD0\x83\xF6\xD5\x48\x90\xD0\x30\x1C\xCF\x80\xF9\x60\xFE\x79\xE4\x88\xF2\xDD\x00\xEB\x94\x45\xEB\x65\x94\x69\x40\xBA\xC0\xD5\xB4\xB8\xBA\x7D\x04\x11\xA8\xEB\x31\x05\x96\x94\x4E\x58\x21\x8E\x9F\xD0\x60\xFD\x02\x03\x01\x00\x01\xA3\x81\xD1\x30\x81\xCE\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x81\x3E\x37\xD8\x92\xB0\x1F\x77\x9F\x5C\xB4\xAB\x73\xAA\xE7\xF6\x34\x60\x2F\xFA\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x8E\x06\x03\x55\x1D\x23\x04\x81\x86\x30\x81\x83\x80\x14\x81\x3E\x37\xD8\x92\xB0\x1F\x77\x9F\x5C\xB4\xAB\x73\xAA\xE7\xF6\x34\x60\x2F\xFA\xA1\x68\xA4\x66\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x41\x64\x64\x54\x72\x75\x73\x74\x20\x50\x75\x62\x6C\x69\x63\x20\x43\x41\x20\x52\x6F\x6F\x74\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x03\xF7\x15\x4A\xF8\x24\xDA\x23\x56\x16\x93\x76\xDD\x36\x28\xB9\xAE\x1B\xB8\xC3\xF1\x64\xBA\x20\x18\x78\x95\x29\x27\x57\x05\xBC\x7C\x2A\xF4\xB9\x51\x55\xDA\x87\x02\xDE\x0F\x16\x17\x31\xF8\xAA\x79\x2E\x09\x13\xBB\xAF\xB2\x20\x19\x12\xE5\x93\xF9\x4B\xF9\x83\xE8\x44\xD5\xB2\x41\x25\xBF\x88\x75\x6F\xFF\x10\xFC\x4A\x54\xD0\x5F\xF0\xFA\xEF\x36\x73\x7D\x1B\x36\x45\xC6\x21\x6D\xB4\x15\xB8\x4E\xCF\x9C\x5C\xA5\x3D\x5A\x00\x8E\x06\xE3\x3C\x6B\x32\x7B\xF2\x9F\xF0\xB6\xFD\xDF\xF0\x28\x18\x48\xF0\xC6\xBC\xD0\xBF\x34\x80\x96\xC2\x4A\xB1\x6D\x8E\xC7\x90\x45\xDE\x2F\x67\xAC\x45\x04\xA3\x7A\xDC\x55\x92\xC9\x47\x66\xD8\x1A\x8C\xC7\xED\x9C\x4E\x9A\xE0\x12\xBB\xB5\x6A\x4C\x84\xE1\xE1\x22\x0D\x87\x00\x64\xFE\x8C\x7D\x62\x39\x65\xA6\xEF\x42\xB6\x80\x25\x12\x61\x01\xA8\x24\x13\x70\x00\x11\x26\x5F\xFA\x35\x50\xC5\x48\xCC\x06\x47\xE8\x27\xD8\x70\x8D\x5F\x64\xE6\xA1\x44\x26\x5E\x22\xEC\x92\xCD\xFF\x42\x9A\x44\x21\x6D\x5C\xC5\xE3\x22\x1D\x5F\x47\x12\xE7\xCE\x5F\x5D\xFA\xD8\xAA\xB1\x33\x2D\xD9\x76\xF2\x4E\x3A\x33\x0C\x2B\xB3\x2D\x90\x06", - ["AddTrust Qualified Certificates Root"] = "\x30\x82\x04\x1E\x30\x82\x03\x06\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x67\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x41\x64\x64\x54\x72\x75\x73\x74\x20\x51\x75\x61\x6C\x69\x66\x69\x65\x64\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x33\x30\x31\x30\x34\x34\x35\x30\x5A\x17\x0D\x32\x30\x30\x35\x33\x30\x31\x30\x34\x34\x35\x30\x5A\x30\x67\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x41\x64\x64\x54\x72\x75\x73\x74\x20\x51\x75\x61\x6C\x69\x66\x69\x65\x64\x20\x43\x41\x20\x52\x6F\x6F\x74\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\xE4\x1E\x9A\xFE\xDC\x09\x5A\x87\xA4\x9F\x47\xBE\x11\x5F\xAF\x84\x34\xDB\x62\x3C\x79\x78\xB7\xE9\x30\xB5\xEC\x0C\x1C\x2A\xC4\x16\xFF\xE0\xEC\x71\xEB\x8A\xF5\x11\x6E\xED\x4F\x0D\x91\xD2\x12\x18\x2D\x49\x15\x01\xC2\xA4\x22\x13\xC7\x11\x64\xFF\x22\x12\x9A\xB9\x8E\x5C\x2F\x08\xCF\x71\x6A\xB3\x67\x01\x59\xF1\x5D\x46\xF3\xB0\x78\xA5\xF6\x0E\x42\x7A\xE3\x7F\x1B\xCC\xD0\xF0\xB7\x28\xFD\x2A\xEA\x9E\xB3\xB0\xB9\x04\xAA\xFD\xF6\xC7\xB4\xB1\xB8\x2A\xA0\xFB\x58\xF1\x19\xA0\x6F\x70\x25\x7E\x3E\x69\x4A\x7F\x0F\x22\xD8\xEF\xAD\x08\x11\x9A\x29\x99\xE1\xAA\x44\x45\x9A\x12\x5E\x3E\x9D\x6D\x52\xFC\xE7\xA0\x3D\x68\x2F\xF0\x4B\x70\x7C\x13\x38\xAD\xBC\x15\x25\xF1\xD6\xCE\xAB\xA2\xC0\x31\xD6\x2F\x9F\xE0\xFF\x14\x59\xFC\x84\x93\xD9\x87\x7C\x4C\x54\x13\xEB\x9F\xD1\x2D\x11\xF8\x18\x3A\x3A\xDE\x25\xD9\xF7\xD3\x40\xED\xA4\x06\x12\xC4\x3B\xE1\x91\xC1\x56\x35\xF0\x14\xDC\x65\x36\x09\x6E\xAB\xA4\x07\xC7\x35\xD1\xC2\x03\x33\x36\x5B\x75\x26\x6D\x42\xF1\x12\x6B\x43\x6F\x4B\x71\x94\xFA\x34\x1D\xED\x13\x6E\xCA\x80\x7F\x98\x2F\x6C\xB9\x65\xD8\xE9\x02\x03\x01\x00\x01\xA3\x81\xD4\x30\x81\xD1\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x39\x95\x8B\x62\x8B\x5C\xC9\xD4\x80\xBA\x58\x0F\x97\x3F\x15\x08\x43\xCC\x98\xA7\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x91\x06\x03\x55\x1D\x23\x04\x81\x89\x30\x81\x86\x80\x14\x39\x95\x8B\x62\x8B\x5C\xC9\xD4\x80\xBA\x58\x0F\x97\x3F\x15\x08\x43\xCC\x98\xA7\xA1\x6B\xA4\x69\x30\x67\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x41\x64\x64\x54\x72\x75\x73\x74\x20\x51\x75\x61\x6C\x69\x66\x69\x65\x64\x20\x43\x41\x20\x52\x6F\x6F\x74\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x19\xAB\x75\xEA\xF8\x8B\x65\x61\x95\x13\xBA\x69\x04\xEF\x86\xCA\x13\xA0\xC7\xAA\x4F\x64\x1B\x3F\x18\xF6\xA8\x2D\x2C\x55\x8F\x05\xB7\x30\xEA\x42\x6A\x1D\xC0\x25\x51\x2D\xA7\xBF\x0C\xB3\xED\xEF\x08\x7F\x6C\x3C\x46\x1A\xEA\x18\x43\xDF\x76\xCC\xF9\x66\x86\x9C\x2C\x68\xF5\xE9\x17\xF8\x31\xB3\x18\xC4\xD6\x48\x7D\x23\x4C\x68\xC1\x7E\xBB\x01\x14\x6F\xC5\xD9\x6E\xDE\xBB\x04\x42\x6A\xF8\xF6\x5C\x7D\xE5\xDA\xFA\x87\xEB\x0D\x35\x52\x67\xD0\x9E\x97\x76\x05\x93\x3F\x95\xC7\x01\xE6\x69\x55\x38\x7F\x10\x61\x99\xC9\xE3\x5F\xA6\xCA\x3E\x82\x63\x48\xAA\xE2\x08\x48\x3E\xAA\xF2\xB2\x85\x62\xA6\xB4\xA7\xD9\xBD\x37\x9C\x68\xB5\x2D\x56\x7D\xB0\xB7\x3F\xA0\xB1\x07\xD6\xE9\x4F\xDC\xDE\x45\x71\x30\x32\x7F\x1B\x2E\x09\xF9\xBF\x52\xA1\xEE\xC2\x80\x3E\x06\x5C\x2E\x55\x40\xC1\x1B\xF5\x70\x45\xB0\xDC\x5D\xFA\xF6\x72\x5A\x77\xD2\x63\xCD\xCF\x58\x89\x00\x42\x63\x3F\x79\x39\xD0\x44\xB0\x82\x6E\x41\x19\xE8\xDD\xE0\xC1\x88\x5A\xD1\x1E\x71\x93\x1F\x24\x30\x74\xE5\x1E\xA8\xDE\x3C\x27\x37\x7F\x83\xAE\x9E\x77\xCF\xF0\x30\xB1\xFF\x4B\x99\xE8\xC6\xA1", - ["Entrust Root Certification Authority"] = "\x30\x82\x04\x91\x30\x82\x03\x79\xA0\x03\x02\x01\x02\x02\x04\x45\x6B\x50\x54\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xB0\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x45\x6E\x74\x72\x75\x73\x74\x2C\x20\x49\x6E\x63\x2E\x31\x39\x30\x37\x06\x03\x55\x04\x0B\x13\x30\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x73\x20\x69\x6E\x63\x6F\x72\x70\x6F\x72\x61\x74\x65\x64\x20\x62\x79\x20\x72\x65\x66\x65\x72\x65\x6E\x63\x65\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x28\x63\x29\x20\x32\x30\x30\x36\x20\x45\x6E\x74\x72\x75\x73\x74\x2C\x20\x49\x6E\x63\x2E\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x45\x6E\x74\x72\x75\x73\x74\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x36\x31\x31\x32\x37\x32\x30\x32\x33\x34\x32\x5A\x17\x0D\x32\x36\x31\x31\x32\x37\x32\x30\x35\x33\x34\x32\x5A\x30\x81\xB0\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x45\x6E\x74\x72\x75\x73\x74\x2C\x20\x49\x6E\x63\x2E\x31\x39\x30\x37\x06\x03\x55\x04\x0B\x13\x30\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x73\x20\x69\x6E\x63\x6F\x72\x70\x6F\x72\x61\x74\x65\x64\x20\x62\x79\x20\x72\x65\x66\x65\x72\x65\x6E\x63\x65\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x28\x63\x29\x20\x32\x30\x30\x36\x20\x45\x6E\x74\x72\x75\x73\x74\x2C\x20\x49\x6E\x63\x2E\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x45\x6E\x74\x72\x75\x73\x74\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xB6\x95\xB6\x43\x42\xFA\xC6\x6D\x2A\x6F\x48\xDF\x94\x4C\x39\x57\x05\xEE\xC3\x79\x11\x41\x68\x36\xED\xEC\xFE\x9A\x01\x8F\xA1\x38\x28\xFC\xF7\x10\x46\x66\x2E\x4D\x1E\x1A\xB1\x1A\x4E\xC6\xD1\xC0\x95\x88\xB0\xC9\xFF\x31\x8B\x33\x03\xDB\xB7\x83\x7B\x3E\x20\x84\x5E\xED\xB2\x56\x28\xA7\xF8\xE0\xB9\x40\x71\x37\xC5\xCB\x47\x0E\x97\x2A\x68\xC0\x22\x95\x62\x15\xDB\x47\xD9\xF5\xD0\x2B\xFF\x82\x4B\xC9\xAD\x3E\xDE\x4C\xDB\x90\x80\x50\x3F\x09\x8A\x84\x00\xEC\x30\x0A\x3D\x18\xCD\xFB\xFD\x2A\x59\x9A\x23\x95\x17\x2C\x45\x9E\x1F\x6E\x43\x79\x6D\x0C\x5C\x98\xFE\x48\xA7\xC5\x23\x47\x5C\x5E\xFD\x6E\xE7\x1E\xB4\xF6\x68\x45\xD1\x86\x83\x5B\xA2\x8A\x8D\xB1\xE3\x29\x80\xFE\x25\x71\x88\xAD\xBE\xBC\x8F\xAC\x52\x96\x4B\xAA\x51\x8D\xE4\x13\x31\x19\xE8\x4E\x4D\x9F\xDB\xAC\xB3\x6A\xD5\xBC\x39\x54\x71\xCA\x7A\x7A\x7F\x90\xDD\x7D\x1D\x80\xD9\x81\xBB\x59\x26\xC2\x11\xFE\xE6\x93\xE2\xF7\x80\xE4\x65\xFB\x34\x37\x0E\x29\x80\x70\x4D\xAF\x38\x86\x2E\x9E\x7F\x57\xAF\x9E\x17\xAE\xEB\x1C\xCB\x28\x21\x5F\xB6\x1C\xD8\xE7\xA2\x04\x22\xF9\xD3\xDA\xD8\xCB\x02\x03\x01\x00\x01\xA3\x81\xB0\x30\x81\xAD\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x32\x30\x30\x36\x31\x31\x32\x37\x32\x30\x32\x33\x34\x32\x5A\x81\x0F\x32\x30\x32\x36\x31\x31\x32\x37\x32\x30\x35\x33\x34\x32\x5A\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x68\x90\xE4\x67\xA4\xA6\x53\x80\xC7\x86\x66\xA4\xF1\xF7\x4B\x43\xFB\x84\xBD\x6D\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x68\x90\xE4\x67\xA4\xA6\x53\x80\xC7\x86\x66\xA4\xF1\xF7\x4B\x43\xFB\x84\xBD\x6D\x30\x1D\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x10\x30\x0E\x1B\x08\x56\x37\x2E\x31\x3A\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x93\xD4\x30\xB0\xD7\x03\x20\x2A\xD0\xF9\x63\xE8\x91\x0C\x05\x20\xA9\x5F\x19\xCA\x7B\x72\x4E\xD4\xB1\xDB\xD0\x96\xFB\x54\x5A\x19\x2C\x0C\x08\xF7\xB2\xBC\x85\xA8\x9D\x7F\x6D\x3B\x52\xB3\x2A\xDB\xE7\xD4\x84\x8C\x63\xF6\x0F\xCB\x26\x01\x91\x50\x6C\xF4\x5F\x14\xE2\x93\x74\xC0\x13\x9E\x30\x3A\x50\xE3\xB4\x60\xC5\x1C\xF0\x22\x44\x8D\x71\x47\xAC\xC8\x1A\xC9\xE9\x9B\x9A\x00\x60\x13\xFF\x70\x7E\x5F\x11\x4D\x49\x1B\xB3\x15\x52\x7B\xC9\x54\xDA\xBF\x9D\x95\xAF\x6B\x9A\xD8\x9E\xE9\xF1\xE4\x43\x8D\xE2\x11\x44\x3A\xBF\xAF\xBD\x83\x42\x73\x52\x8B\xAA\xBB\xA7\x29\xCF\xF5\x64\x1C\x0A\x4D\xD1\xBC\xAA\xAC\x9F\x2A\xD0\xFF\x7F\x7F\xDA\x7D\xEA\xB1\xED\x30\x25\xC1\x84\xDA\x34\xD2\x5B\x78\x83\x56\xEC\x9C\x36\xC3\x26\xE2\x11\xF6\x67\x49\x1D\x92\xAB\x8C\xFB\xEB\xFF\x7A\xEE\x85\x4A\xA7\x50\x80\xF0\xA7\x5C\x4A\x94\x2E\x5F\x05\x99\x3C\x52\x41\xE0\xCD\xB4\x63\xCF\x01\x43\xBA\x9C\x83\xDC\x8F\x60\x3B\xF3\x5A\xB4\xB4\x7B\xAE\xDA\x0B\x90\x38\x75\xEF\x81\x1D\x66\xD2\xF7\x57\x70\x36\xB3\xBF\xFC\x28\xAF\x71\x25\x85\x5B\x13\xFE\x1E\x7F\x5A\xB4\x3C", - ["RSA Security 2048 v3"] = "\x30\x82\x03\x61\x30\x82\x02\x49\xA0\x03\x02\x01\x02\x02\x10\x0A\x01\x01\x01\x00\x00\x02\x7C\x00\x00\x00\x0A\x00\x00\x00\x02\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3A\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x52\x53\x41\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x49\x6E\x63\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x52\x53\x41\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x32\x30\x34\x38\x20\x56\x33\x30\x1E\x17\x0D\x30\x31\x30\x32\x32\x32\x32\x30\x33\x39\x32\x33\x5A\x17\x0D\x32\x36\x30\x32\x32\x32\x32\x30\x33\x39\x32\x33\x5A\x30\x3A\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x52\x53\x41\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x49\x6E\x63\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x52\x53\x41\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x32\x30\x34\x38\x20\x56\x33\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\xB7\x8F\x55\x71\xD2\x80\xDD\x7B\x69\x79\xA7\xF0\x18\x50\x32\x3C\x62\x67\xF6\x0A\x95\x07\xDD\xE6\x1B\xF3\x9E\xD9\xD2\x41\x54\x6B\xAD\x9F\x7C\xBE\x19\xCD\xFB\x46\xAB\x41\x68\x1E\x18\xEA\x55\xC8\x2F\x91\x78\x89\x28\xFB\x27\x29\x60\xFF\xDF\x8F\x8C\x3B\xC9\x49\x9B\xB5\xA4\x94\xCE\x01\xEA\x3E\xB5\x63\x7B\x7F\x26\xFD\x19\xDD\xC0\x21\xBD\x84\xD1\x2D\x4F\x46\xC3\x4E\xDC\xD8\x37\x39\x3B\x28\xAF\xCB\x9D\x1A\xEA\x2B\xAF\x21\xA5\xC1\x23\x22\xB8\xB8\x1B\x5A\x13\x87\x57\x83\xD1\xF0\x20\xE7\xE8\x4F\x23\x42\xB0\x00\xA5\x7D\x89\xE9\xE9\x61\x73\x94\x98\x71\x26\xBC\x2D\x6A\xE0\xF7\x4D\xF0\xF1\xB6\x2A\x38\x31\x81\x0D\x29\xE1\x00\xC1\x51\x0F\x4C\x52\xF8\x04\x5A\xAA\x7D\x72\xD3\xB8\x87\x2A\xBB\x63\x10\x03\x2A\xB3\xA1\x4F\x0D\x5A\x5E\x46\xB7\x3D\x0E\xF5\x74\xEC\x99\x9F\xF9\x3D\x24\x81\x88\xA6\xDD\x60\x54\xE8\x95\x36\x3D\xC6\x09\x93\x9A\xA3\x12\x80\x00\x55\x99\x19\x47\xBD\xD0\xA5\x7C\xC3\xBA\xFB\x1F\xF7\xF5\x0F\xF8\xAC\xB9\xB5\xF4\x37\x98\x13\x18\xDE\x85\x5B\xB7\x0C\x82\x3B\x87\x6F\x95\x39\x58\x30\xDA\x6E\x01\x68\x17\x22\xCC\xC0\x0B\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x07\xC3\x51\x30\xA4\xAA\xE9\x45\xAE\x35\x24\xFA\xFF\x24\x2C\x33\xD0\xB1\x9D\x8C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x07\xC3\x51\x30\xA4\xAA\xE9\x45\xAE\x35\x24\xFA\xFF\x24\x2C\x33\xD0\xB1\x9D\x8C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5F\x3E\x86\x76\x6E\xB8\x35\x3C\x4E\x36\x1C\x1E\x79\x98\xBF\xFD\xD5\x12\x11\x79\x52\x0E\xEE\x31\x89\xBC\xDD\x7F\xF9\xD1\xC6\x15\x21\xE8\x8A\x01\x54\x0D\x3A\xFB\x54\xB9\xD6\x63\xD4\xB1\xAA\x96\x4D\xA2\x42\x4D\xD4\x53\x1F\x8B\x10\xDE\x7F\x65\xBE\x60\x13\x27\x71\x88\xA4\x73\xE3\x84\x63\xD1\xA4\x55\xE1\x50\x93\xE6\x1B\x0E\x79\xD0\x67\xBC\x46\xC8\xBF\x3F\x17\x0D\x95\xE6\xC6\x90\x69\xDE\xE7\xB4\x2F\xDE\x95\x7D\xD0\x12\x3F\x3D\x3E\x7F\x4D\x3F\x14\x68\xF5\x11\x50\xD5\xC1\xF4\x90\xA5\x08\x1D\x31\x60\xFF\x60\x8C\x23\x54\x0A\xAF\xFE\xA1\x6E\xC5\xD1\x7A\x2A\x68\x78\xCF\x1E\x82\x0A\x20\xB4\x1F\xAD\xE5\x85\xB2\x6A\x68\x75\x4E\xAD\x25\x37\x94\x85\xBE\xBD\xA1\xD4\xEA\xB7\x0C\x4B\x3C\x9D\xE8\x12\x00\xF0\x5F\xAC\x0D\xE1\xAC\x70\x63\x73\xF7\x7F\x79\x9F\x32\x25\x42\x74\x05\x80\x28\xBF\xBD\xC1\x24\x96\x58\x15\xB1\x17\x21\xE9\x89\x4B\xDB\x07\x88\x67\xF4\x15\xAD\x70\x3E\x2F\x4D\x85\x3B\xC2\xB7\xDB\xFE\x98\x68\x23\x89\xE1\x74\x0F\xDE\xF4\xC5\x84\x63\x29\x1B\xCC\xCB\x07\xC9\x00\xA4\xA9\xD7\xC2\x22\x4F\x67\xD7\x77\xEC\x20\x05\x61\xDE", - ["GeoTrust Global CA"] = "\x30\x82\x03\x54\x30\x82\x02\x3C\xA0\x03\x02\x01\x02\x02\x03\x02\x34\x56\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x42\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x41\x30\x1E\x17\x0D\x30\x32\x30\x35\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x17\x0D\x32\x32\x30\x35\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x30\x42\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x41\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\xDA\xCC\x18\x63\x30\xFD\xF4\x17\x23\x1A\x56\x7E\x5B\xDF\x3C\x6C\x38\xE4\x71\xB7\x78\x91\xD4\xBC\xA1\xD8\x4C\xF8\xA8\x43\xB6\x03\xE9\x4D\x21\x07\x08\x88\xDA\x58\x2F\x66\x39\x29\xBD\x05\x78\x8B\x9D\x38\xE8\x05\xB7\x6A\x7E\x71\xA4\xE6\xC4\x60\xA6\xB0\xEF\x80\xE4\x89\x28\x0F\x9E\x25\xD6\xED\x83\xF3\xAD\xA6\x91\xC7\x98\xC9\x42\x18\x35\x14\x9D\xAD\x98\x46\x92\x2E\x4F\xCA\xF1\x87\x43\xC1\x16\x95\x57\x2D\x50\xEF\x89\x2D\x80\x7A\x57\xAD\xF2\xEE\x5F\x6B\xD2\x00\x8D\xB9\x14\xF8\x14\x15\x35\xD9\xC0\x46\xA3\x7B\x72\xC8\x91\xBF\xC9\x55\x2B\xCD\xD0\x97\x3E\x9C\x26\x64\xCC\xDF\xCE\x83\x19\x71\xCA\x4E\xE6\xD4\xD5\x7B\xA9\x19\xCD\x55\xDE\xC8\xEC\xD2\x5E\x38\x53\xE5\x5C\x4F\x8C\x2D\xFE\x50\x23\x36\xFC\x66\xE6\xCB\x8E\xA4\x39\x19\x00\xB7\x95\x02\x39\x91\x0B\x0E\xFE\x38\x2E\xD1\x1D\x05\x9A\xF6\x4D\x3E\x6F\x0F\x07\x1D\xAF\x2C\x1E\x8F\x60\x39\xE2\xFA\x36\x53\x13\x39\xD4\x5E\x26\x2B\xDB\x3D\xA8\x14\xBD\x32\xEB\x18\x03\x28\x52\x04\x71\xE5\xAB\x33\x3D\xE1\x38\xBB\x07\x36\x84\x62\x9C\x79\xEA\x16\x30\xF4\x5F\xC0\x2B\xE8\x71\x6B\xE4\xF9\x02\x03\x01\x00\x01\xA3\x53\x30\x51\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC0\x7A\x98\x68\x8D\x89\xFB\xAB\x05\x64\x0C\x11\x7D\xAA\x7D\x65\xB8\xCA\xCC\x4E\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xC0\x7A\x98\x68\x8D\x89\xFB\xAB\x05\x64\x0C\x11\x7D\xAA\x7D\x65\xB8\xCA\xCC\x4E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x35\xE3\x29\x6A\xE5\x2F\x5D\x54\x8E\x29\x50\x94\x9F\x99\x1A\x14\xE4\x8F\x78\x2A\x62\x94\xA2\x27\x67\x9E\xD0\xCF\x1A\x5E\x47\xE9\xC1\xB2\xA4\xCF\xDD\x41\x1A\x05\x4E\x9B\x4B\xEE\x4A\x6F\x55\x52\xB3\x24\xA1\x37\x0A\xEB\x64\x76\x2A\x2E\x2C\xF3\xFD\x3B\x75\x90\xBF\xFA\x71\xD8\xC7\x3D\x37\xD2\xB5\x05\x95\x62\xB9\xA6\xDE\x89\x3D\x36\x7B\x38\x77\x48\x97\xAC\xA6\x20\x8F\x2E\xA6\xC9\x0C\xC2\xB2\x99\x45\x00\xC7\xCE\x11\x51\x22\x22\xE0\xA5\xEA\xB6\x15\x48\x09\x64\xEA\x5E\x4F\x74\xF7\x05\x3E\xC7\x8A\x52\x0C\xDB\x15\xB4\xBD\x6D\x9B\xE5\xC6\xB1\x54\x68\xA9\xE3\x69\x90\xB6\x9A\xA5\x0F\xB8\xB9\x3F\x20\x7D\xAE\x4A\xB5\xB8\x9C\xE4\x1D\xB6\xAB\xE6\x94\xA5\xC1\xC7\x83\xAD\xDB\xF5\x27\x87\x0E\x04\x6C\xD5\xFF\xDD\xA0\x5D\xED\x87\x52\xB7\x2B\x15\x02\xAE\x39\xA6\x6A\x74\xE9\xDA\xC4\xE7\xBC\x4D\x34\x1E\xA9\x5C\x4D\x33\x5F\x92\x09\x2F\x88\x66\x5D\x77\x97\xC7\x1D\x76\x13\xA9\xD5\xE5\xF1\x16\x09\x11\x35\xD5\xAC\xDB\x24\x71\x70\x2C\x98\x56\x0B\xD9\x17\xB4\xD1\xE3\x51\x2B\x5E\x75\xE8\xD5\xD0\xDC\x4F\x34\xED\xC2\x05\x66\x80\xA1\xCB\xE6\x33", - ["GeoTrust Global CA 2"] = "\x30\x82\x03\x66\x30\x82\x02\x4E\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x44\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x1D\x30\x1B\x06\x03\x55\x04\x03\x13\x14\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x41\x20\x32\x30\x1E\x17\x0D\x30\x34\x30\x33\x30\x34\x30\x35\x30\x30\x30\x30\x5A\x17\x0D\x31\x39\x30\x33\x30\x34\x30\x35\x30\x30\x30\x30\x5A\x30\x44\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x1D\x30\x1B\x06\x03\x55\x04\x03\x13\x14\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x41\x20\x32\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\xEF\x3C\x4D\x40\x3D\x10\xDF\x3B\x53\x00\xE1\x67\xFE\x94\x60\x15\x3E\x85\x88\xF1\x89\x0D\x90\xC8\x28\x23\x99\x05\xE8\x2B\x20\x9D\xC6\xF3\x60\x46\xD8\xC1\xB2\xD5\x8C\x31\xD9\xDC\x20\x79\x24\x81\xBF\x35\x32\xFC\x63\x69\xDB\xB1\x2A\x6B\xEE\x21\x58\xF2\x08\xE9\x78\xCB\x6F\xCB\xFC\x16\x52\xC8\x91\xC4\xFF\x3D\x73\xDE\xB1\x3E\xA7\xC2\x7D\x66\xC1\xF5\x7E\x52\x24\x1A\xE2\xD5\x67\x91\xD0\x82\x10\xD7\x78\x4B\x4F\x2B\x42\x39\xBD\x64\x2D\x40\xA0\xB0\x10\xD3\x38\x48\x46\x88\xA1\x0C\xBB\x3A\x33\x2A\x62\x98\xFB\x00\x9D\x13\x59\x7F\x6F\x3B\x72\xAA\xEE\xA6\x0F\x86\xF9\x05\x61\xEA\x67\x7F\x0C\x37\x96\x8B\xE6\x69\x16\x47\x11\xC2\x27\x59\x03\xB3\xA6\x60\xC2\x21\x40\x56\xFA\xA0\xC7\x7D\x3A\x13\xE3\xEC\x57\xC7\xB3\xD6\xAE\x9D\x89\x80\xF7\x01\xE7\x2C\xF6\x96\x2B\x13\x0D\x79\x2C\xD9\xC0\xE4\x86\x7B\x4B\x8C\x0C\x72\x82\x8A\xFB\x17\xCD\x00\x6C\x3A\x13\x3C\xB0\x84\x87\x4B\x16\x7A\x29\xB2\x4F\xDB\x1D\xD4\x0B\xF3\x66\x37\xBD\xD8\xF6\x57\xBB\x5E\x24\x7A\xB8\x3C\x8B\xB9\xFA\x92\x1A\x1A\x84\x9E\xD8\x74\x8F\xAA\x1B\x7F\x5E\xF4\xFE\x45\x22\x21\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x71\x38\x36\xF2\x02\x31\x53\x47\x2B\x6E\xBA\x65\x46\xA9\x10\x15\x58\x20\x05\x09\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x71\x38\x36\xF2\x02\x31\x53\x47\x2B\x6E\xBA\x65\x46\xA9\x10\x15\x58\x20\x05\x09\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x03\xF7\xB5\x2B\xAB\x5D\x10\xFC\x7B\xB2\xB2\x5E\xAC\x9B\x0E\x7E\x53\x78\x59\x3E\x42\x04\xFE\x75\xA3\xAD\xAC\x81\x4E\xD7\x02\x8B\x5E\xC4\x2D\xC8\x52\x76\xC7\x2C\x1F\xFC\x81\x32\x98\xD1\x4B\xC6\x92\x93\x33\x35\x31\x2F\xFC\xD8\x1D\x44\xDD\xE0\x81\x7F\x9D\xE9\x8B\xE1\x64\x91\x62\x0B\x39\x08\x8C\xAC\x74\x9D\x59\xD9\x7A\x59\x52\x97\x11\xB9\x16\x7B\x6F\x45\xD3\x96\xD9\x31\x7D\x02\x36\x0F\x9C\x3B\x6E\xCF\x2C\x0D\x03\x46\x45\xEB\xA0\xF4\x7F\x48\x44\xC6\x08\x40\xCC\xDE\x1B\x70\xB5\x29\xAD\xBA\x8B\x3B\x34\x65\x75\x1B\x71\x21\x1D\x2C\x14\x0A\xB0\x96\x95\xB8\xD6\xEA\xF2\x65\xFB\x29\xBA\x4F\xEA\x91\x93\x74\x69\xB6\xF2\xFF\xE1\x1A\xD0\x0C\xD1\x76\x85\xCB\x8A\x25\xBD\x97\x5E\x2C\x6F\x15\x99\x26\xE7\xB6\x29\xFF\x22\xEC\xC9\x02\xC7\x56\x00\xCD\x49\xB9\xB3\x6C\x7B\x53\x04\x1A\xE2\xA8\xC9\xAA\x12\x05\x23\xC2\xCE\xE7\xBB\x04\x02\xCC\xC0\x47\xA2\xE4\xC4\x29\x2F\x5B\x45\x57\x89\x51\xEE\x3C\xEB\x52\x08\xFF\x07\x35\x1E\x9F\x35\x6A\x47\x4A\x56\x98\xD1\x5A\x85\x1F\x8C\xF5\x22\xBF\xAB\xCE\x83\xF3\xE2\x22\x29\xAE\x7D\x83\x40\xA8\xBA\x6C", - ["GeoTrust Universal CA"] = "\x30\x82\x05\x68\x30\x82\x03\x50\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x1E\x30\x1C\x06\x03\x55\x04\x03\x13\x15\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x30\x1E\x17\x0D\x30\x34\x30\x33\x30\x34\x30\x35\x30\x30\x30\x30\x5A\x17\x0D\x32\x39\x30\x33\x30\x34\x30\x35\x30\x30\x30\x30\x5A\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x1E\x30\x1C\x06\x03\x55\x04\x03\x13\x15\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xA6\x15\x55\xA0\xA3\xC6\xE0\x1F\x8C\x9D\x21\x50\xD7\xC1\xBE\x2B\x5B\xB5\xA4\x9E\xA1\xD9\x72\x58\xBD\x00\x1B\x4C\xBF\x61\xC9\x14\x1D\x45\x82\xAB\xC6\x1D\x80\xD6\x3D\xEB\x10\x9C\x3A\xAF\x6D\x24\xF8\xBC\x71\x01\x9E\x06\xF5\x7C\x5F\x1E\xC1\x0E\x55\xCA\x83\x9A\x59\x30\xAE\x19\xCB\x30\x48\x95\xED\x22\x37\x8D\xF4\x4A\x9A\x72\x66\x3E\xAD\x95\xC0\xE0\x16\x00\xE0\x10\x1F\x2B\x31\x0E\xD7\x94\x54\xD3\x42\x33\xA0\x34\x1D\x1E\x45\x76\xDD\x4F\xCA\x18\x37\xEC\x85\x15\x7A\x19\x08\xFC\xD5\xC7\x9C\xF0\xF2\xA9\x2E\x10\xA9\x92\xE6\x3D\x58\x3D\xA9\x16\x68\x3C\x2F\x75\x21\x18\x7F\x28\x77\xA5\xE1\x61\x17\xB7\xA6\xE9\xF8\x1E\x99\xDB\x73\x6E\xF4\x0A\xA2\x21\x6C\xEE\xDA\xAA\x85\x92\x66\xAF\xF6\x7A\x6B\x82\xDA\xBA\x22\x08\x35\x0F\xCF\x42\xF1\x35\xFA\x6A\xEE\x7E\x2B\x25\xCC\x3A\x11\xE4\x6D\xAF\x73\xB2\x76\x1D\xAD\xD0\xB2\x78\x67\x1A\xA4\x39\x1C\x51\x0B\x67\x56\x83\xFD\x38\x5D\x0D\xCE\xDD\xF0\xBB\x2B\x96\x1F\xDE\x7B\x32\x52\xFD\x1D\xBB\xB5\x06\xA1\xB2\x21\x5E\xA5\xD6\x95\x68\x7F\xF0\x99\x9E\xDC\x45\x08\x3E\xE7\xD2\x09\x0D\x35\x94\xDD\x80\x4E\x53\x97\xD7\xB5\x09\x44\x20\x64\x16\x17\x03\x02\x4C\x53\x0D\x68\xDE\xD5\xAA\x72\x4D\x93\x6D\x82\x0E\xDB\x9C\xBD\xCF\xB4\xF3\x5C\x5D\x54\x7A\x69\x09\x96\xD6\xDB\x11\xC1\x8D\x75\xA8\xB4\xCF\x39\xC8\xCE\x3C\xBC\x24\x7C\xE6\x62\xCA\xE1\xBD\x7D\xA7\xBD\x57\x65\x0B\xE4\xFE\x25\xED\xB6\x69\x10\xDC\x28\x1A\x46\xBD\x01\x1D\xD0\x97\xB5\xE1\x98\x3B\xC0\x37\x64\xD6\x3D\x94\xEE\x0B\xE1\xF5\x28\xAE\x0B\x56\xBF\x71\x8B\x23\x29\x41\x8E\x86\xC5\x4B\x52\x7B\xD8\x71\xAB\x1F\x8A\x15\xA6\x3B\x83\x5A\xD7\x58\x01\x51\xC6\x4C\x41\xD9\x7F\xD8\x41\x67\x72\xA2\x28\xDF\x60\x83\xA9\x9E\xC8\x7B\xFC\x53\x73\x72\x59\xF5\x93\x7A\x17\x76\x0E\xCE\xF7\xE5\x5C\xD9\x0B\x55\x34\xA2\xAA\x5B\xB5\x6A\x54\xE7\x13\xCA\x57\xEC\x97\x6D\xF4\x5E\x06\x2F\x45\x8B\x58\xD4\x23\x16\x92\xE4\x16\x6E\x28\x63\x59\x30\xDF\x50\x01\x9C\x63\x89\x1A\x9F\xDB\x17\x94\x82\x70\x37\xC3\x24\x9E\x9A\x47\xD6\x5A\xCA\x4E\xA8\x69\x89\x72\x1F\x91\x6C\xDB\x7E\x9E\x1B\xAD\xC7\x1F\x73\xDD\x2C\x4F\x19\x65\xFD\x7F\x93\x40\x10\x2E\xD2\xF0\xED\x3C\x9E\x2E\x28\x3E\x69\x26\x33\xC5\x7B\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xDA\xBB\x2E\xAA\xB0\x0C\xB8\x88\x26\x51\x74\x5C\x6D\x03\xD3\xC0\xD8\x8F\x7A\xD6\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xDA\xBB\x2E\xAA\xB0\x0C\xB8\x88\x26\x51\x74\x5C\x6D\x03\xD3\xC0\xD8\x8F\x7A\xD6\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x31\x78\xE6\xC7\xB5\xDF\xB8\x94\x40\xC9\x71\xC4\xA8\x35\xEC\x46\x1D\xC2\x85\xF3\x28\x58\x86\xB0\x0B\xFC\x8E\xB2\x39\x8F\x44\x55\xAB\x64\x84\x5C\x69\xA9\xD0\x9A\x38\x3C\xFA\xE5\x1F\x35\xE5\x44\xE3\x80\x79\x94\x68\xA4\xBB\xC4\x9F\x3D\xE1\x34\xCD\x30\x46\x8B\x54\x2B\x95\xA5\xEF\xF7\x3F\x99\x84\xFD\x35\xE6\xCF\x31\xC6\xDC\x6A\xBF\xA7\xD7\x23\x08\xE1\x98\x5E\xC3\x5A\x08\x76\xA9\xA6\xAF\x77\x2F\xB7\x60\xBD\x44\x46\x6A\xEF\x97\xFF\x73\x95\xC1\x8E\xE8\x93\xFB\xFD\x31\xB7\xEC\x57\x11\x11\x45\x9B\x30\xF1\x1A\x88\x39\xC1\x4F\x3C\xA7\x00\xD5\xC7\xFC\xAB\x6D\x80\x22\x70\xA5\x0C\xE0\x5D\x04\x29\x02\xFB\xCB\xA0\x91\xD1\x7C\xD6\xC3\x7E\x50\xD5\x9D\x58\xBE\x41\x38\xEB\xB9\x75\x3C\x15\xD9\x9B\xC9\x4A\x83\x59\xC0\xDA\x53\xFD\x33\xBB\x36\x18\x9B\x85\x0F\x15\xDD\xEE\x2D\xAC\x76\x93\xB9\xD9\x01\x8D\x48\x10\xA8\xFB\xF5\x38\x86\xF1\xDB\x0A\xC6\xBD\x84\xA3\x23\x41\xDE\xD6\x77\x6F\x85\xD4\x85\x1C\x50\xE0\xAE\x51\x8A\xBA\x8D\x3E\x76\xE2\xB9\xCA\x27\xF2\x5F\x9F\xEF\x6E\x59\x0D\x06\xD8\x2B\x17\xA4\xD2\x7C\x6B\xBB\x5F\x14\x1A\x48\x8F\x1A\x4C\xE7\xB3\x47\x1C\x8E\x4C\x45\x2B\x20\xEE\x48\xDF\xE7\xDD\x09\x8E\x18\xA8\xDA\x40\x8D\x92\x26\x11\x53\x61\x73\x5D\xEB\xBD\xE7\xC4\x4D\x29\x37\x61\xEB\xAC\x39\x2D\x67\x2E\x16\xD6\xF5\x00\x83\x85\xA1\xCC\x7F\x76\xC4\x7D\xE4\xB7\x4B\x66\xEF\x03\x45\x60\x69\xB6\x0C\x52\x96\x92\x84\x5E\xA6\xA3\xB5\xA4\x3E\x2B\xD9\xCC\xD8\x1B\x47\xAA\xF2\x44\xDA\x4F\xF9\x03\xE8\xF0\x14\xCB\x3F\xF3\x83\xDE\xD0\xC1\x54\xE3\xB7\xE8\x0A\x37\x4D\x8B\x20\x59\x03\x30\x19\xA1\x2C\xC8\xBD\x11\x1F\xDF\xAE\xC9\x4A\xC5\xF3\x27\x66\x66\x86\xAC\x68\x91\xFF\xD9\xE6\x53\x1C\x0F\x8B\x5C\x69\x65\x0A\x26\xC8\x1E\x34\xC3\x5D\x51\x7B\xD7\xA9\x9C\x06\xA1\x36\xDD\xD5\x89\x94\xBC\xD9\xE4\x2D\x0C\x5E\x09\x6C\x08\x97\x7C\xA3\x3D\x7C\x93\xFF\x3F\xA1\x14\xA7\xCF\xB5\x5D\xEB\xDB\xDB\x1C\xC4\x76\xDF\x88\xB9\xBD\x45\x05\x95\x1B\xAE\xFC\x46\x6A\x4C\xAF\x48\xE3\xCE\xAE\x0F\xD2\x7E\xEB\xE6\x6C\x9C\x4F\x81\x6A\x7A\x64\xAC\xBB\x3E\xD5\xE7\xCB\x76\x2E\xC5\xA7\x48\xC1\x5C\x90\x0F\xCB\xC8\x3F\xFA\xE6\x32\xE1\x8D\x1B\x6F\xA4\xE6\x8E\xD8\xF9\x29\x48\x8A\xCE\x73\xFE\x2C", - ["GeoTrust Universal CA 2"] = "\x30\x82\x05\x6C\x30\x82\x03\x54\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x47\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x32\x30\x1E\x17\x0D\x30\x34\x30\x33\x30\x34\x30\x35\x30\x30\x30\x30\x5A\x17\x0D\x32\x39\x30\x33\x30\x34\x30\x35\x30\x30\x30\x30\x5A\x30\x47\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xB3\x54\x52\xC1\xC9\x3E\xF2\xD9\xDC\xB1\x53\x1A\x59\x29\xE7\xB1\xC3\x45\x28\xE5\xD7\xD1\xED\xC5\xC5\x4B\xA1\xAA\x74\x7B\x57\xAF\x4A\x26\xFC\xD8\xF5\x5E\xA7\x6E\x19\xDB\x74\x0C\x4F\x35\x5B\x32\x0B\x01\xE3\xDB\xEB\x7A\x77\x35\xEA\xAA\x5A\xE0\xD6\xE8\xA1\x57\x94\xF0\x90\xA3\x74\x56\x94\x44\x30\x03\x1E\x5C\x4E\x2B\x85\x26\x74\x82\x7A\x0C\x76\xA0\x6F\x4D\xCE\x41\x2D\xA0\x15\x06\x14\x5F\xB7\x42\xCD\x7B\x8F\x58\x61\x34\xDC\x2A\x08\xF9\x2E\xC3\x01\xA6\x22\x44\x1C\x4C\x07\x82\xE6\x5B\xCE\xD0\x4A\x7C\x04\xD3\x19\x73\x27\xF0\xAA\x98\x7F\x2E\xAF\x4E\xEB\x87\x1E\x24\x77\x6A\x5D\xB6\xE8\x5B\x45\xBA\xDC\xC3\xA1\x05\x6F\x56\x8E\x8F\x10\x26\xA5\x49\xC3\x2E\xD7\x41\x87\x22\xE0\x4F\x86\xCA\x60\xB5\xEA\xA1\x63\xC0\x01\x97\x10\x79\xBD\x00\x3C\x12\x6D\x2B\x15\xB1\xAC\x4B\xB1\xEE\x18\xB9\x4E\x96\xDC\xDC\x76\xFF\x3B\xBE\xCF\x5F\x03\xC0\xFC\x3B\xE8\xBE\x46\x1B\xFF\xDA\x40\xC2\x52\xF7\xFE\xE3\x3A\xF7\x6A\x77\x35\xD0\xDA\x8D\xEB\x5E\x18\x6A\x31\xC7\x1E\xBA\x3C\x1B\x28\xD6\x6B\x54\xC6\xAA\x5B\xD7\xA2\x2C\x1B\x19\xCC\xA2\x02\xF6\x9B\x59\xBD\x37\x6B\x86\xB5\x6D\x82\xBA\xD8\xEA\xC9\x56\xBC\xA9\x36\x58\xFD\x3E\x19\xF3\xED\x0C\x26\xA9\x93\x38\xF8\x4F\xC1\x5D\x22\x06\xD0\x97\xEA\xE1\xAD\xC6\x55\xE0\x81\x2B\x28\x83\x3A\xFA\xF4\x7B\x21\x51\x00\xBE\x52\x38\xCE\xCD\x66\x79\xA8\xF4\x81\x56\xE2\xD0\x83\x09\x47\x51\x5B\x50\x6A\xCF\xDB\x48\x1A\x5D\x3E\xF7\xCB\xF6\x65\xF7\x6C\xF1\x95\xF8\x02\x3B\x32\x56\x82\x39\x7A\x5B\xBD\x2F\x89\x1B\xBF\xA1\xB4\xE8\xFF\x7F\x8D\x8C\xDF\x03\xF1\x60\x4E\x58\x11\x4C\xEB\xA3\x3F\x10\x2B\x83\x9A\x01\x73\xD9\x94\x6D\x84\x00\x27\x66\xAC\xF0\x70\x40\x09\x42\x92\xAD\x4F\x93\x0D\x61\x09\x51\x24\xD8\x92\xD5\x0B\x94\x61\xB2\x87\xB2\xED\xFF\x9A\x35\xFF\x85\x54\xCA\xED\x44\x43\xAC\x1B\x3C\x16\x6B\x48\x4A\x0A\x1C\x40\x88\x1F\x92\xC2\x0B\x00\x05\xFF\xF2\xC8\x02\x4A\xA4\xAA\xA9\xCC\x99\x96\x9C\x2F\x58\xE0\x7D\xE1\xBE\xBB\x07\xDC\x5F\x04\x72\x5C\x31\x34\xC3\xEC\x5F\x2D\xE0\x3D\x64\x90\x22\xE6\xD1\xEC\xB8\x2E\xDD\x59\xAE\xD9\xA1\x37\xBF\x54\x35\xDC\x73\x32\x4F\x8C\x04\x1E\x33\xB2\xC9\x46\xF1\xD8\x5C\xC8\x55\x50\xC9\x68\xBD\xA8\xBA\x36\x09\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x76\xF3\x55\xE1\xFA\xA4\x36\xFB\xF0\x9F\x5C\x62\x71\xED\x3C\xF4\x47\x38\x10\x2B\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x76\xF3\x55\xE1\xFA\xA4\x36\xFB\xF0\x9F\x5C\x62\x71\xED\x3C\xF4\x47\x38\x10\x2B\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x66\xC1\xC6\x23\xF3\xD9\xE0\x2E\x6E\x5F\xE8\xCF\xAE\xB0\xB0\x25\x4D\x2B\xF8\x3B\x58\x9B\x40\x24\x37\x5A\xCB\xAB\x16\x49\xFF\xB3\x75\x79\x33\xA1\x2F\x6D\x70\x17\x34\x91\xFE\x67\x7E\x8F\xEC\x9B\xE5\x5E\x82\xA9\x55\x1F\x2F\xDC\xD4\x51\x07\x12\xFE\xAC\x16\x3E\x2C\x35\xC6\x63\xFC\xDC\x10\xEB\x0D\xA3\xAA\xD0\x7C\xCC\xD1\xD0\x2F\x51\x2E\xC4\x14\x5A\xDE\xE8\x19\xE1\x3E\xC6\xCC\xA4\x29\xE7\x2E\x84\xAA\x06\x30\x78\x76\x54\x73\x28\x98\x59\x38\xE0\x00\x0D\x62\xD3\x42\x7D\x21\x9F\xAE\x3D\x3A\x8C\xD5\xFA\x77\x0D\x18\x2B\x16\x0E\x5F\x36\xE1\xFC\x2A\xB5\x30\x24\xCF\xE0\x63\x0C\x7B\x58\x1A\xFE\x99\xBA\x42\x12\xB1\x91\xF4\x7C\x68\xE2\xC8\xE8\xAF\x2C\xEA\xC9\x7E\xAE\xBB\x2A\x3D\x0D\x15\xDC\x34\x95\xB6\x18\x74\xA8\x6A\x0F\xC7\xB4\xF4\x13\xC4\xE4\x5B\xED\x0A\xD2\xA4\x97\x4C\x2A\xED\x2F\x6C\x12\x89\x3D\xF1\x27\x70\xAA\x6A\x03\x52\x21\x9F\x40\xA8\x67\x50\xF2\xF3\x5A\x1F\xDF\xDF\x23\xF6\xDC\x78\x4E\xE6\x98\x4F\x55\x3A\x53\xE3\xEF\xF2\xF4\x9F\xC7\x7C\xD8\x58\xAF\x29\x22\x97\xB8\xE0\xBD\x91\x2E\xB0\x76\xEC\x57\x11\xCF\xEF\x29\x44\xF3\xE9\x85\x7A\x60\x63\xE4\x5D\x33\x89\x17\xD9\x31\xAA\xDA\xD6\xF3\x18\x35\x72\xCF\x87\x2B\x2F\x63\x23\x84\x5D\x84\x8C\x3F\x57\xA0\x88\xFC\x99\x91\x28\x26\x69\x99\xD4\x8F\x97\x44\xBE\x8E\xD5\x48\xB1\xA4\x28\x29\xF1\x15\xB4\xE1\xE5\x9E\xDD\xF8\x8F\xA6\x6F\x26\xD7\x09\x3C\x3A\x1C\x11\x0E\xA6\x6C\x37\xF7\xAD\x44\x87\x2C\x28\xC7\xD8\x74\x82\xB3\xD0\x6F\x4A\x57\xBB\x35\x29\x27\xA0\x8B\xE8\x21\xA7\x87\x64\x36\x5D\xCC\xD8\x16\xAC\xC7\xB2\x27\x40\x92\x55\x38\x28\x8D\x51\x6E\xDD\x14\x67\x53\x6C\x71\x5C\x26\x84\x4D\x75\x5A\xB6\x7E\x60\x56\xA9\x4D\xAD\xFB\x9B\x1E\x97\xF3\x0D\xD9\xD2\x97\x54\x77\xDA\x3D\x12\xB7\xE0\x1E\xEF\x08\x06\xAC\xF9\x85\x87\xE9\xA2\xDC\xAF\x7E\x18\x12\x83\xFD\x56\x17\x41\x2E\xD5\x29\x82\x7D\x99\xF4\x31\xF6\x71\xA9\xCF\x2C\x01\x27\xA5\x05\xB9\xAA\xB2\x48\x4E\x2A\xEF\x9F\x93\x52\x51\x95\x3C\x52\x73\x8E\x56\x4C\x17\x40\xC0\x09\x28\xE4\x8B\x6A\x48\x53\xDB\xEC\xCD\x55\x55\xF1\xC6\xF8\xE9\xA2\x2C\x4C\xA6\xD1\x26\x5F\x7E\xAF\x5A\x4C\xDA\x1F\xA6\xF2\x1C\x2C\x7E\xAE\x02\x16\xD2\x56\xD0\x2F\x57\x53\x47\xE8\x92", - ["America Online Root Certification Authority 1"] = "\x30\x82\x03\xA4\x30\x82\x02\x8C\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x49\x6E\x63\x2E\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x31\x30\x1E\x17\x0D\x30\x32\x30\x35\x32\x38\x30\x36\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x31\x31\x39\x32\x30\x34\x33\x30\x30\x5A\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x49\x6E\x63\x2E\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x31\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\xA8\x2F\xE8\xA4\x69\x06\x03\x47\xC3\xE9\x2A\x98\xFF\x19\xA2\x70\x9A\xC6\x50\xB2\x7E\xA5\xDF\x68\x4D\x1B\x7C\x0F\xB6\x97\x68\x7D\x2D\xA6\x8B\x97\xE9\x64\x86\xC9\xA3\xEF\xA0\x86\xBF\x60\x65\x9C\x4B\x54\x88\xC2\x48\xC5\x4A\x39\xBF\x14\xE3\x59\x55\xE5\x19\xB4\x74\xC8\xB4\x05\x39\x5C\x16\xA5\xE2\x95\x05\xE0\x12\xAE\x59\x8B\xA2\x33\x68\x58\x1C\xA6\xD4\x15\xB7\xD8\x9F\xD7\xDC\x71\xAB\x7E\x9A\xBF\x9B\x8E\x33\x0F\x22\xFD\x1F\x2E\xE7\x07\x36\xEF\x62\x39\xC5\xDD\xCB\xBA\x25\x14\x23\xDE\x0C\xC6\x3D\x3C\xCE\x82\x08\xE6\x66\x3E\xDA\x51\x3B\x16\x3A\xA3\x05\x7F\xA0\xDC\x87\xD5\x9C\xFC\x72\xA9\xA0\x7D\x78\xE4\xB7\x31\x55\x1E\x65\xBB\xD4\x61\xB0\x21\x60\xED\x10\x32\x72\xC5\x92\x25\x1E\xF8\x90\x4A\x18\x78\x47\xDF\x7E\x30\x37\x3E\x50\x1B\xDB\x1C\xD3\x6B\x9A\x86\x53\x07\xB0\xEF\xAC\x06\x78\xF8\x84\x99\xFE\x21\x8D\x4C\x80\xB6\x0C\x82\xF6\x66\x70\x79\x1A\xD3\x4F\xA3\xCF\xF1\xCF\x46\xB0\x4B\x0F\x3E\xDD\x88\x62\xB8\x8C\xA9\x09\x28\x3B\x7A\xC7\x97\xE1\x1E\xE5\xF4\x9F\xC0\xC0\xAE\x24\xA0\xC8\xA1\xD9\x0F\xD6\x7B\x26\x82\x69\x32\x3D\xA7\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x00\xAD\xD9\xA3\xF6\x79\xF6\x6E\x74\xA9\x7F\x33\x3D\x81\x17\xD7\x4C\xCF\x33\xDE\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x00\xAD\xD9\xA3\xF6\x79\xF6\x6E\x74\xA9\x7F\x33\x3D\x81\x17\xD7\x4C\xCF\x33\xDE\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7C\x8A\xD1\x1F\x18\x37\x82\xE0\xB8\xB0\xA3\xED\x56\x95\xC8\x62\x61\x9C\x05\xA2\xCD\xC2\x62\x26\x61\xCD\x10\x16\xD7\xCC\xB4\x65\x34\xD0\x11\x8A\xAD\xA8\xA9\x05\x66\xEF\x74\xF3\x6D\x5F\x9D\x99\xAF\xF6\x8B\xFB\xEB\x52\xB2\x05\x98\xA2\x6F\x2A\xC5\x54\xBD\x25\xBD\x5F\xAE\xC8\x86\xEA\x46\x2C\xC1\xB3\xBD\xC1\xE9\x49\x70\x18\x16\x97\x08\x13\x8C\x20\xE0\x1B\x2E\x3A\x47\xCB\x1E\xE4\x00\x30\x95\x5B\xF4\x45\xA3\xC0\x1A\xB0\x01\x4E\xAB\xBD\xC0\x23\x6E\x63\x3F\x80\x4A\xC5\x07\xED\xDC\xE2\x6F\xC7\xC1\x62\xF1\xE3\x72\xD6\x04\xC8\x74\x67\x0B\xFA\x88\xAB\xA1\x01\xC8\x6F\xF0\x14\xAF\xD2\x99\xCD\x51\x93\x7E\xED\x2E\x38\xC7\xBD\xCE\x46\x50\x3D\x72\xE3\x79\x25\x9D\x9B\x88\x2B\x10\x20\xDD\xA5\xB8\x32\x9F\x8D\xE0\x29\xDF\x21\x74\x86\x82\xDB\x2F\x82\x30\xC6\xC7\x35\x86\xB3\xF9\x96\x5F\x46\xDB\x0C\x45\xFD\xF3\x50\xC3\x6F\xC6\xC3\x48\xAD\x46\xA6\xE1\x27\x47\x0A\x1D\x0E\x9B\xB6\xC2\x77\x7F\x63\xF2\xE0\x7D\x1A\xBE\xFC\xE0\xDF\xD7\xC7\xA7\x6C\xB0\xF9\xAE\xBA\x3C\xFD\x74\xB4\x11\xE8\x58\x0D\x80\xBC\xD3\xA8\x80\x3A\x99\xED\x75\xCC\x46\x7B", - ["America Online Root Certification Authority 2"] = "\x30\x82\x05\xA4\x30\x82\x03\x8C\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x49\x6E\x63\x2E\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x32\x30\x1E\x17\x0D\x30\x32\x30\x35\x32\x38\x30\x36\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x30\x39\x32\x39\x31\x34\x30\x38\x30\x30\x5A\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x49\x6E\x63\x2E\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xCC\x41\x45\x1D\xE9\x3D\x4D\x10\xF6\x8C\xB1\x41\xC9\xE0\x5E\xCB\x0D\xB7\xBF\x47\x73\xD3\xF0\x55\x4D\xDD\xC6\x0C\xFA\xB1\x66\x05\x6A\xCD\x78\xB4\xDC\x02\xDB\x4E\x81\xF3\xD7\xA7\x7C\x71\xBC\x75\x63\xA0\x5D\xE3\x07\x0C\x48\xEC\x25\xC4\x03\x20\xF4\xFF\x0E\x3B\x12\xFF\x9B\x8D\xE1\xC6\xD5\x1B\xB4\x6D\x22\xE3\xB1\xDB\x7F\x21\x64\xAF\x86\xBC\x57\x22\x2A\xD6\x47\x81\x57\x44\x82\x56\x53\xBD\x86\x14\x01\x0B\xFC\x7F\x74\xA4\x5A\xAE\xF1\xBA\x11\xB5\x9B\x58\x5A\x80\xB4\x37\x78\x09\x33\x7C\x32\x47\x03\x5C\xC4\xA5\x83\x48\xF4\x57\x56\x6E\x81\x36\x27\x18\x4F\xEC\x9B\x28\xC2\xD4\xB4\xD7\x7C\x0C\x3E\x0C\x2B\xDF\xCA\x04\xD7\xC6\x8E\xEA\x58\x4E\xA8\xA4\xA5\x18\x1C\x6C\x45\x98\xA3\x41\xD1\x2D\xD2\xC7\x6D\x8D\x19\xF1\xAD\x79\xB7\x81\x3F\xBD\x06\x82\x27\x2D\x10\x58\x05\xB5\x78\x05\xB9\x2F\xDB\x0C\x6B\x90\x90\x7E\x14\x59\x38\xBB\x94\x24\x13\xE5\xD1\x9D\x14\xDF\xD3\x82\x4D\x46\xF0\x80\x39\x52\x32\x0F\xE3\x84\xB2\x7A\x43\xF2\x5E\xDE\x5F\x3F\x1D\xDD\xE3\xB2\x1B\xA0\xA1\x2A\x23\x03\x6E\x2E\x01\x15\x87\x5C\xA6\x75\x75\xC7\x97\x61\xBE\xDE\x86\xDC\xD4\x48\xDB\xBD\x2A\xBF\x4A\x55\xDA\xE8\x7D\x50\xFB\xB4\x80\x17\xB8\x94\xBF\x01\x3D\xEA\xDA\xBA\x7C\xE0\x58\x67\x17\xB9\x58\xE0\x88\x86\x46\x67\x6C\x9D\x10\x47\x58\x32\xD0\x35\x7C\x79\x2A\x90\xA2\x5A\x10\x11\x23\x35\xAD\x2F\xCC\xE4\x4A\x5B\xA7\xC8\x27\xF2\x83\xDE\x5E\xBB\x5E\x77\xE7\xE8\xA5\x6E\x63\xC2\x0D\x5D\x61\xD0\x8C\xD2\x6C\x5A\x21\x0E\xCA\x28\xA3\xCE\x2A\xE9\x95\xC7\x48\xCF\x96\x6F\x1D\x92\x25\xC8\xC6\xC6\xC1\xC1\x0C\x05\xAC\x26\xC4\xD2\x75\xD2\xE1\x2A\x67\xC0\x3D\x5B\xA5\x9A\xEB\xCF\x7B\x1A\xA8\x9D\x14\x45\xE5\x0F\xA0\x9A\x65\xDE\x2F\x28\xBD\xCE\x6F\x94\x66\x83\x48\x29\xD8\xEA\x65\x8C\xAF\x93\xD9\x64\x9F\x55\x57\x26\xBF\x6F\xCB\x37\x31\x99\xA3\x60\xBB\x1C\xAD\x89\x34\x32\x62\xB8\x43\x21\x06\x72\x0C\xA1\x5C\x6D\x46\xC5\xFA\x29\xCF\x30\xDE\x89\xDC\x71\x5B\xDD\xB6\x37\x3E\xDF\x50\xF5\xB8\x07\x25\x26\xE5\xBC\xB5\xFE\x3C\x02\xB3\xB7\xF8\xBE\x43\xC1\x87\x11\x94\x9E\x23\x6C\x17\x8A\xB8\x8A\x27\x0C\x54\x47\xF0\xA9\xB3\xC0\x80\x8C\xA0\x27\xEB\x1D\x19\xE3\x07\x8E\x77\x70\xCA\x2B\xF4\x7D\x76\xE0\x78\x67\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x4D\x45\xC1\x68\x38\xBB\x73\xA9\x69\xA1\x20\xE7\xED\xF5\x22\xA1\x23\x14\xD7\x9E\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x4D\x45\xC1\x68\x38\xBB\x73\xA9\x69\xA1\x20\xE7\xED\xF5\x22\xA1\x23\x14\xD7\x9E\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x67\x6B\x06\xB9\x5F\x45\x3B\x2A\x4B\x33\xB3\xE6\x1B\x6B\x59\x4E\x22\xCC\xB9\xB7\xA4\x25\xC9\xA7\xC4\xF0\x54\x96\x0B\x64\xF3\xB1\x58\x4F\x5E\x51\xFC\xB2\x97\x7B\x27\x65\xC2\xE5\xCA\xE7\x0D\x0C\x25\x7B\x62\xE3\xFA\x9F\xB4\x87\xB7\x45\x46\xAF\x83\xA5\x97\x48\x8C\xA5\xBD\xF1\x16\x2B\x9B\x76\x2C\x7A\x35\x60\x6C\x11\x80\x97\xCC\xA9\x92\x52\xE6\x2B\xE6\x69\xED\xA9\xF8\x36\x2D\x2C\x77\xBF\x61\x48\xD1\x63\x0B\xB9\x5B\x52\xED\x18\xB0\x43\x42\x22\xA6\xB1\x77\xAE\xDE\x69\xC5\xCD\xC7\x1C\xA1\xB1\xA5\x1C\x10\xFB\x18\xBE\x1A\x70\xDD\xC1\x92\x4B\xBE\x29\x5A\x9D\x3F\x35\xBE\xE5\x7D\x51\xF8\x55\xE0\x25\x75\x23\x87\x1E\x5C\xDC\xBA\x9D\xB0\xAC\xB3\x69\xDB\x17\x83\xC9\xF7\xDE\x0C\xBC\x08\xDC\x91\x9E\xA8\xD0\xD7\x15\x37\x73\xA5\x35\xB8\xFC\x7E\xC5\x44\x40\x06\xC3\xEB\xF8\x22\x80\x5C\x47\xCE\x02\xE3\x11\x9F\x44\xFF\xFD\x9A\x32\xCC\x7D\x64\x51\x0E\xEB\x57\x26\x76\x3A\xE3\x1E\x22\x3C\xC2\xA6\x36\xDD\x19\xEF\xA7\xFC\x12\xF3\x26\xC0\x59\x31\x85\x4C\x9C\xD8\xCF\xDF\xA4\xCC\xCC\x29\x93\xFF\x94\x6D\x76\x5C\x13\x08\x97\xF2\xED\xA5\x0B\x4D\xDD\xE8\xC9\x68\x0E\x66\xD3\x00\x0E\x33\x12\x5B\xBC\x95\xE5\x32\x90\xA8\xB3\xC6\x6C\x83\xAD\x77\xEE\x8B\x7E\x7E\xB1\xA9\xAB\xD3\xE1\xF1\xB6\xC0\xB1\xEA\x88\xC0\xE7\xD3\x90\xE9\x28\x92\x94\x7B\x68\x7B\x97\x2A\x0A\x67\x2D\x85\x02\x38\x10\xE4\x03\x61\xD4\xDA\x25\x36\xC7\x08\x58\x2D\xA1\xA7\x51\xAF\x30\x0A\x49\xF5\xA6\x69\x87\x07\x2D\x44\x46\x76\x8E\x2A\xE5\x9A\x3B\xD7\x18\xA2\xFC\x9C\x38\x10\xCC\xC6\x3B\xD2\xB5\x17\x3A\x6F\xFD\xAE\x25\xBD\xF5\x72\x59\x64\xB1\x74\x2A\x38\x5F\x18\x4C\xDF\xCF\x71\x04\x5A\x36\xD4\xBF\x2F\x99\x9C\xE8\xD9\xBA\xB1\x95\xE6\x02\x4B\x21\xA1\x5B\xD5\xC1\x4F\x8F\xAE\x69\x6D\x53\xDB\x01\x93\xB5\x5C\x1E\x18\xDD\x64\x5A\xCA\x18\x28\x3E\x63\x04\x11\xFD\x1C\x8D\x00\x0F\xB8\x37\xDF\x67\x8A\x9D\x66\xA9\x02\x6A\x91\xFF\x13\xCA\x2F\x5D\x83\xBC\x87\x93\x6C\xDC\x24\x51\x16\x04\x25\x66\xFA\xB3\xD9\xC2\xBA\x29\xBE\x9A\x48\x38\x82\x99\xF4\xBF\x3B\x4A\x31\x19\xF9\xBF\x8E\x21\x33\x14\xCA\x4F\x54\x5F\xFB\xCE\xFB\x8F\x71\x7F\xFD\x5E\x19\xA0\x0F\x4B\x91\xB8\xC4\x54\xBC\x06\xB0\x45\x8F\x26\x91\xA2\x8E\xFE\xA9", - ["Visa eCommerce Root"] = "\x30\x82\x03\xA2\x30\x82\x02\x8A\xA0\x03\x02\x01\x02\x02\x10\x13\x86\x35\x4D\x1D\x3F\x06\xF2\xC1\xF9\x65\x05\xD5\x90\x1C\x62\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x6B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0D\x30\x0B\x06\x03\x55\x04\x0A\x13\x04\x56\x49\x53\x41\x31\x2F\x30\x2D\x06\x03\x55\x04\x0B\x13\x26\x56\x69\x73\x61\x20\x49\x6E\x74\x65\x72\x6E\x61\x74\x69\x6F\x6E\x61\x6C\x20\x53\x65\x72\x76\x69\x63\x65\x20\x41\x73\x73\x6F\x63\x69\x61\x74\x69\x6F\x6E\x31\x1C\x30\x1A\x06\x03\x55\x04\x03\x13\x13\x56\x69\x73\x61\x20\x65\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x32\x30\x36\x32\x36\x30\x32\x31\x38\x33\x36\x5A\x17\x0D\x32\x32\x30\x36\x32\x34\x30\x30\x31\x36\x31\x32\x5A\x30\x6B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0D\x30\x0B\x06\x03\x55\x04\x0A\x13\x04\x56\x49\x53\x41\x31\x2F\x30\x2D\x06\x03\x55\x04\x0B\x13\x26\x56\x69\x73\x61\x20\x49\x6E\x74\x65\x72\x6E\x61\x74\x69\x6F\x6E\x61\x6C\x20\x53\x65\x72\x76\x69\x63\x65\x20\x41\x73\x73\x6F\x63\x69\x61\x74\x69\x6F\x6E\x31\x1C\x30\x1A\x06\x03\x55\x04\x03\x13\x13\x56\x69\x73\x61\x20\x65\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\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\xAF\x57\xDE\x56\x1E\x6E\xA1\xDA\x60\xB1\x94\x27\xCB\x17\xDB\x07\x3F\x80\x85\x4F\xC8\x9C\xB6\xD0\xF4\x6F\x4F\xCF\x99\xD8\xE1\xDB\xC2\x48\x5C\x3A\xAC\x39\x33\xC7\x1F\x6A\x8B\x26\x3D\x2B\x35\xF5\x48\xB1\x91\xC1\x02\x4E\x04\x96\x91\x7B\xB0\x33\xF0\xB1\x14\x4E\x11\x6F\xB5\x40\xAF\x1B\x45\xA5\x4A\xEF\x7E\xB6\xAC\xF2\xA0\x1F\x58\x3F\x12\x46\x60\x3C\x8D\xA1\xE0\x7D\xCF\x57\x3E\x33\x1E\xFB\x47\xF1\xAA\x15\x97\x07\x55\x66\xA5\xB5\x2D\x2E\xD8\x80\x59\xB2\xA7\x0D\xB7\x46\xEC\x21\x63\xFF\x35\xAB\xA5\x02\xCF\x2A\xF4\x4C\xFE\x7B\xF5\x94\x5D\x84\x4D\xA8\xF2\x60\x8F\xDB\x0E\x25\x3C\x9F\x73\x71\xCF\x94\xDF\x4A\xEA\xDB\xDF\x72\x38\x8C\xF3\x96\xBD\xF1\x17\xBC\xD2\xBA\x3B\x45\x5A\xC6\xA7\xF6\xC6\x17\x8B\x01\x9D\xFC\x19\xA8\x2A\x83\x16\xB8\x3A\x48\xFE\x4E\x3E\xA0\xAB\x06\x19\xE9\x53\xF3\x80\x13\x07\xED\x2D\xBF\x3F\x0A\x3C\x55\x20\x39\x2C\x2C\x00\x69\x74\x95\x4A\xBC\x20\xB2\xA9\x79\xE5\x18\x89\x91\xA8\xDC\x1C\x4D\xEF\xBB\x7E\x37\x0B\x5D\xFE\x39\xA5\x88\x52\x8C\x00\x6C\xEC\x18\x7C\x41\xBD\xF6\x8B\x75\x77\xBA\x60\x9D\x84\xE7\xFE\x2D\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x15\x38\x83\x0F\x3F\x2C\x3F\x70\x33\x1E\xCD\x46\xFE\x07\x8C\x20\xE0\xD7\xC3\xB7\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5F\xF1\x41\x7D\x7C\x5C\x08\xB9\x2B\xE0\xD5\x92\x47\xFA\x67\x5C\xA5\x13\xC3\x03\x21\x9B\x2B\x4C\x89\x46\xCF\x59\x4D\xC9\xFE\xA5\x40\xB6\x63\xCD\xDD\x71\x28\x95\x67\x11\xCC\x24\xAC\xD3\x44\x6C\x71\xAE\x01\x20\x6B\x03\xA2\x8F\x18\xB7\x29\x3A\x7D\xE5\x16\x60\x53\x78\x3C\xC0\xAF\x15\x83\xF7\x8F\x52\x33\x24\xBD\x64\x93\x97\xEE\x8B\xF7\xDB\x18\xA8\x6D\x71\xB3\xF7\x2C\x17\xD0\x74\x25\x69\xF7\xFE\x6B\x3C\x94\xBE\x4D\x4B\x41\x8C\x4E\xE2\x73\xD0\xE3\x90\x22\x73\x43\xCD\xF3\xEF\xEA\x73\xCE\x45\x8A\xB0\xA6\x49\xFF\x4C\x7D\x9D\x71\x88\xC4\x76\x1D\x90\x5B\x1D\xEE\xFD\xCC\xF7\xEE\xFD\x60\xA5\xB1\x7A\x16\x71\xD1\x16\xD0\x7C\x12\x3C\x6C\x69\x97\xDB\xAE\x5F\x39\x9A\x70\x2F\x05\x3C\x19\x46\x04\x99\x20\x36\xD0\x60\x6E\x61\x06\xBB\x16\x42\x8C\x70\xF7\x30\xFB\xE0\xDB\x66\xA3\x00\x01\xBD\xE6\x2C\xDA\x91\x5F\xA0\x46\x8B\x4D\x6A\x9C\x3D\x3D\xDD\x05\x46\xFE\x76\xBF\xA0\x0A\x3C\xE4\x00\xE6\x27\xB7\xFF\x84\x2D\xDE\xBA\x22\x27\x96\x10\x71\xEB\x22\xED\xDF\xDF\x33\x9C\xCF\xE3\xAD\xAE\x8E\xD4\x8E\xE6\x4F\x51\xAF\x16\x92\xE0\x5C\xF6\x07\x0F", - ["TC TrustCenter, Germany, Class 2 CA"] = "\x30\x82\x03\x5C\x30\x82\x02\xC5\xA0\x03\x02\x01\x02\x02\x02\x03\xEA\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\xBC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x3A\x30\x38\x06\x03\x55\x04\x0A\x13\x31\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x66\x6F\x72\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x69\x6E\x20\x44\x61\x74\x61\x20\x4E\x65\x74\x77\x6F\x72\x6B\x73\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x31\x29\x30\x27\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x1A\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x40\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x30\x1E\x17\x0D\x39\x38\x30\x33\x30\x39\x31\x31\x35\x39\x35\x39\x5A\x17\x0D\x31\x31\x30\x31\x30\x31\x31\x31\x35\x39\x35\x39\x5A\x30\x81\xBC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x3A\x30\x38\x06\x03\x55\x04\x0A\x13\x31\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x66\x6F\x72\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x69\x6E\x20\x44\x61\x74\x61\x20\x4E\x65\x74\x77\x6F\x72\x6B\x73\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x31\x29\x30\x27\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x1A\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x40\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xDA\x38\xE8\xED\x32\x00\x29\x71\x83\x01\x0D\xBF\x8C\x01\xDC\xDA\xC6\xAD\x39\xA4\xA9\x8A\x2F\xD5\x8B\x5C\x68\x5F\x50\xC6\x62\xF5\x66\xBD\xCA\x91\x22\xEC\xAA\x1D\x51\xD7\x3D\xB3\x51\xB2\x83\x4E\x5D\xCB\x49\xB0\xF0\x4C\x55\xE5\x6B\x2D\xC7\x85\x0B\x30\x1C\x92\x4E\x82\xD4\xCA\x02\xED\xF7\x6F\xBE\xDC\xE0\xE3\x14\xB8\x05\x53\xF2\x9A\xF4\x56\x8B\x5A\x9E\x85\x93\xD1\xB4\x82\x56\xAE\x4D\xBB\xA8\x4B\x57\x16\xBC\xFE\xF8\x58\x9E\xF8\x29\x8D\xB0\x7B\xCD\x78\xC9\x4F\xAC\x8B\x67\x0C\xF1\x9C\xFB\xFC\x57\x9B\x57\x5C\x4F\x0D\x02\x03\x01\x00\x01\xA3\x6B\x30\x69\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x33\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x08\x04\x26\x16\x24\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x2F\x67\x75\x69\x64\x65\x6C\x69\x6E\x65\x73\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x84\x52\xFB\x28\xDF\xFF\x1F\x75\x01\xBC\x01\xBE\x04\x56\x97\x6A\x74\x42\x24\x31\x83\xF9\x46\xB1\x06\x8A\x89\xCF\x96\x2C\x33\xBF\x8C\xB5\x5F\x7A\x72\xA1\x85\x06\xCE\x86\xF8\x05\x8E\xE8\xF9\x25\xCA\xDA\x83\x8C\x06\xAC\xEB\x36\x6D\x85\x91\x34\x04\x36\xF4\x42\xF0\xF8\x79\x2E\x0A\x48\x5C\xAB\xCC\x51\x4F\x78\x76\xA0\xD9\xAC\x19\xBD\x2A\xD1\x69\x04\x28\x91\xCA\x36\x10\x27\x80\x57\x5B\xD2\x5C\xF5\xC2\x5B\xAB\x64\x81\x63\x74\x51\xF4\x97\xBF\xCD\x12\x28\xF7\x4D\x66\x7F\xA7\xF0\x1C\x01\x26\x78\xB2\x66\x47\x70\x51\x64", - ["TC TrustCenter, Germany, Class 3 CA"] = "\x30\x82\x03\x5C\x30\x82\x02\xC5\xA0\x03\x02\x01\x02\x02\x02\x03\xEB\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\xBC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x3A\x30\x38\x06\x03\x55\x04\x0A\x13\x31\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x66\x6F\x72\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x69\x6E\x20\x44\x61\x74\x61\x20\x4E\x65\x74\x77\x6F\x72\x6B\x73\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x31\x29\x30\x27\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x1A\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x40\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x30\x1E\x17\x0D\x39\x38\x30\x33\x30\x39\x31\x31\x35\x39\x35\x39\x5A\x17\x0D\x31\x31\x30\x31\x30\x31\x31\x31\x35\x39\x35\x39\x5A\x30\x81\xBC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x3A\x30\x38\x06\x03\x55\x04\x0A\x13\x31\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x66\x6F\x72\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x69\x6E\x20\x44\x61\x74\x61\x20\x4E\x65\x74\x77\x6F\x72\x6B\x73\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x31\x29\x30\x27\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x1A\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x40\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xB6\xB4\xC1\x35\x05\x2E\x0D\x8D\xEC\xA0\x40\x6A\x1C\x0E\x27\xA6\x50\x92\x6B\x50\x1B\x07\xDE\x2E\xE7\x76\xCC\xE0\xDA\xFC\x84\xA8\x5E\x8C\x63\x6A\x2B\x4D\xD9\x4E\x02\x76\x11\xC1\x0B\xF2\x8D\x79\xCA\x00\xB6\xF1\xB0\x0E\xD7\xFB\xA4\x17\x3D\xAF\xAB\x69\x7A\x96\x27\xBF\xAF\x33\xA1\x9A\x2A\x59\xAA\xC4\xB5\x37\x08\xF2\x12\xA5\x31\xB6\x43\xF5\x32\x96\x71\x28\x28\xAB\x8D\x28\x86\xDF\xBB\xEE\xE3\x0C\x7D\x30\xD6\xC3\x52\xAB\x8F\x5D\x27\x9C\x6B\xC0\xA3\xE7\x05\x6B\x57\x49\x44\xB3\x6E\xEA\x64\xCF\xD2\x8E\x7A\x50\x77\x77\x02\x03\x01\x00\x01\xA3\x6B\x30\x69\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x33\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x08\x04\x26\x16\x24\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x2F\x67\x75\x69\x64\x65\x6C\x69\x6E\x65\x73\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x16\x3D\xC6\xCD\xC1\xBB\x85\x71\x85\x46\x9F\x3E\x20\x8F\x51\x28\x99\xEC\x2D\x45\x21\x63\x23\x5B\x04\xBB\x4C\x90\xB8\x88\x92\x04\x4D\xBD\x7D\x01\xA3\x3F\xF6\xEC\xCE\xF1\xDE\xFE\x7D\xE5\xE1\x3E\xBB\xC6\xAB\x5E\x0B\xDD\x3D\x96\xC4\xCB\xA9\xD4\xF9\x26\xE6\x06\x4E\x9E\x0C\xA5\x7A\xBA\x6E\xC3\x7C\x82\x19\xD1\xC7\xB1\xB1\xC3\xDB\x0D\x8E\x9B\x40\x7C\x37\x0B\xF1\x5D\xE8\xFD\x1F\x90\x88\xA5\x0E\x4E\x37\x64\x21\xA8\x4E\x8D\xB4\x9F\xF1\xDE\x48\xAD\xD5\x56\x18\x52\x29\x8B\x47\x34\x12\x09\xD4\xBB\x92\x35\xEF\x0F\xDB\x34", - ["Certum Root CA"] = "\x30\x82\x03\x0C\x30\x82\x01\xF4\xA0\x03\x02\x01\x02\x02\x03\x01\x00\x20\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x50\x4C\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x55\x6E\x69\x7A\x65\x74\x6F\x20\x53\x70\x2E\x20\x7A\x20\x6F\x2E\x6F\x2E\x31\x12\x30\x10\x06\x03\x55\x04\x03\x13\x09\x43\x65\x72\x74\x75\x6D\x20\x43\x41\x30\x1E\x17\x0D\x30\x32\x30\x36\x31\x31\x31\x30\x34\x36\x33\x39\x5A\x17\x0D\x32\x37\x30\x36\x31\x31\x31\x30\x34\x36\x33\x39\x5A\x30\x3E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x50\x4C\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x55\x6E\x69\x7A\x65\x74\x6F\x20\x53\x70\x2E\x20\x7A\x20\x6F\x2E\x6F\x2E\x31\x12\x30\x10\x06\x03\x55\x04\x03\x13\x09\x43\x65\x72\x74\x75\x6D\x20\x43\x41\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\xCE\xB1\xC1\x2E\xD3\x4F\x7C\xCD\x25\xCE\x18\x3E\x4F\xC4\x8C\x6F\x80\x6A\x73\xC8\x5B\x51\xF8\x9B\xD2\xDC\xBB\x00\x5C\xB1\xA0\xFC\x75\x03\xEE\x81\xF0\x88\xEE\x23\x52\xE9\xE6\x15\x33\x8D\xAC\x2D\x09\xC5\x76\xF9\x2B\x39\x80\x89\xE4\x97\x4B\x90\xA5\xA8\x78\xF8\x73\x43\x7B\xA4\x61\xB0\xD8\x58\xCC\xE1\x6C\x66\x7E\x9C\xF3\x09\x5E\x55\x63\x84\xD5\xA8\xEF\xF3\xB1\x2E\x30\x68\xB3\xC4\x3C\xD8\xAC\x6E\x8D\x99\x5A\x90\x4E\x34\xDC\x36\x9A\x8F\x81\x88\x50\xB7\x6D\x96\x42\x09\xF3\xD7\x95\x83\x0D\x41\x4B\xB0\x6A\x6B\xF8\xFC\x0F\x7E\x62\x9F\x67\xC4\xED\x26\x5F\x10\x26\x0F\x08\x4F\xF0\xA4\x57\x28\xCE\x8F\xB8\xED\x45\xF6\x6E\xEE\x25\x5D\xAA\x6E\x39\xBE\xE4\x93\x2F\xD9\x47\xA0\x72\xEB\xFA\xA6\x5B\xAF\xCA\x53\x3F\xE2\x0E\xC6\x96\x56\x11\x6E\xF7\xE9\x66\xA9\x26\xD8\x7F\x95\x53\xED\x0A\x85\x88\xBA\x4F\x29\xA5\x42\x8C\x5E\xB6\xFC\x85\x20\x00\xAA\x68\x0B\xA1\x1A\x85\x01\x9C\xC4\x46\x63\x82\x88\xB6\x22\xB1\xEE\xFE\xAA\x46\x59\x7E\xCF\x35\x2C\xD5\xB6\xDA\x5D\xF7\x48\x33\x14\x54\xB6\xEB\xD9\x6F\xCE\xCD\x88\xD6\xAB\x1B\xDA\x96\x3B\x1D\x59\x02\x03\x01\x00\x01\xA3\x13\x30\x11\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xB8\x8D\xCE\xEF\xE7\x14\xBA\xCF\xEE\xB0\x44\x92\x6C\xB4\x39\x3E\xA2\x84\x6E\xAD\xB8\x21\x77\xD2\xD4\x77\x82\x87\xE6\x20\x41\x81\xEE\xE2\xF8\x11\xB7\x63\xD1\x17\x37\xBE\x19\x76\x24\x1C\x04\x1A\x4C\xEB\x3D\xAA\x67\x6F\x2D\xD4\xCD\xFE\x65\x31\x70\xC5\x1B\xA6\x02\x0A\xBA\x60\x7B\x6D\x58\xC2\x9A\x49\xFE\x63\x32\x0B\x6B\xE3\x3A\xC0\xAC\xAB\x3B\xB0\xE8\xD3\x09\x51\x8C\x10\x83\xC6\x34\xE0\xC5\x2B\xE0\x1A\xB6\x60\x14\x27\x6C\x32\x77\x8C\xBC\xB2\x72\x98\xCF\xCD\xCC\x3F\xB9\xC8\x24\x42\x14\xD6\x57\xFC\xE6\x26\x43\xA9\x1D\xE5\x80\x90\xCE\x03\x54\x28\x3E\xF7\x3F\xD3\xF8\x4D\xED\x6A\x0A\x3A\x93\x13\x9B\x3B\x14\x23\x13\x63\x9C\x3F\xD1\x87\x27\x79\xE5\x4C\x51\xE3\x01\xAD\x85\x5D\x1A\x3B\xB1\xD5\x73\x10\xA4\xD3\xF2\xBC\x6E\x64\xF5\x5A\x56\x90\xA8\xC7\x0E\x4C\x74\x0F\x2E\x71\x3B\xF7\xC8\x47\xF4\x69\x6F\x15\xF2\x11\x5E\x83\x1E\x9C\x7C\x52\xAE\xFD\x02\xDA\x12\xA8\x59\x67\x18\xDB\xBC\x70\xDD\x9B\xB1\x69\xED\x80\xCE\x89\x40\x48\x6A\x0E\x35\xCA\x29\x66\x15\x21\x94\x2C\xE8\x60\x2A\x9B\x85\x4A\x40\xF3\x6B\x8A\x24\xEC\x06\x16\x2C\x73", - ["Comodo AAA Services root"] = "\x30\x82\x04\x32\x30\x82\x03\x1A\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x0C\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x0C\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x0C\x11\x43\x6F\x6D\x6F\x64\x6F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x0C\x18\x41\x41\x41\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x30\x1E\x17\x0D\x30\x34\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x0C\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x0C\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x0C\x11\x43\x6F\x6D\x6F\x64\x6F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x0C\x18\x41\x41\x41\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\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\xBE\x40\x9D\xF4\x6E\xE1\xEA\x76\x87\x1C\x4D\x45\x44\x8E\xBE\x46\xC8\x83\x06\x9D\xC1\x2A\xFE\x18\x1F\x8E\xE4\x02\xFA\xF3\xAB\x5D\x50\x8A\x16\x31\x0B\x9A\x06\xD0\xC5\x70\x22\xCD\x49\x2D\x54\x63\xCC\xB6\x6E\x68\x46\x0B\x53\xEA\xCB\x4C\x24\xC0\xBC\x72\x4E\xEA\xF1\x15\xAE\xF4\x54\x9A\x12\x0A\xC3\x7A\xB2\x33\x60\xE2\xDA\x89\x55\xF3\x22\x58\xF3\xDE\xDC\xCF\xEF\x83\x86\xA2\x8C\x94\x4F\x9F\x68\xF2\x98\x90\x46\x84\x27\xC7\x76\xBF\xE3\xCC\x35\x2C\x8B\x5E\x07\x64\x65\x82\xC0\x48\xB0\xA8\x91\xF9\x61\x9F\x76\x20\x50\xA8\x91\xC7\x66\xB5\xEB\x78\x62\x03\x56\xF0\x8A\x1A\x13\xEA\x31\xA3\x1E\xA0\x99\xFD\x38\xF6\xF6\x27\x32\x58\x6F\x07\xF5\x6B\xB8\xFB\x14\x2B\xAF\xB7\xAA\xCC\xD6\x63\x5F\x73\x8C\xDA\x05\x99\xA8\x38\xA8\xCB\x17\x78\x36\x51\xAC\xE9\x9E\xF4\x78\x3A\x8D\xCF\x0F\xD9\x42\xE2\x98\x0C\xAB\x2F\x9F\x0E\x01\xDE\xEF\x9F\x99\x49\xF1\x2D\xDF\xAC\x74\x4D\x1B\x98\xB5\x47\xC5\xE5\x29\xD1\xF9\x90\x18\xC7\x62\x9C\xBE\x83\xC7\x26\x7B\x3E\x8A\x25\xC7\xC0\xDD\x9D\xE6\x35\x68\x10\x20\x9D\x8F\xD8\xDE\xD2\xC3\x84\x9C\x0D\x5E\xE8\x2F\xC9\x02\x03\x01\x00\x01\xA3\x81\xC0\x30\x81\xBD\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xA0\x11\x0A\x23\x3E\x96\xF1\x07\xEC\xE2\xAF\x29\xEF\x82\xA5\x7F\xD0\x30\xA4\xB4\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x7B\x06\x03\x55\x1D\x1F\x04\x74\x30\x72\x30\x38\xA0\x36\xA0\x34\x86\x32\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x63\x61\x2E\x63\x6F\x6D\x2F\x41\x41\x41\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2E\x63\x72\x6C\x30\x36\xA0\x34\xA0\x32\x86\x30\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x2E\x6E\x65\x74\x2F\x41\x41\x41\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x08\x56\xFC\x02\xF0\x9B\xE8\xFF\xA4\xFA\xD6\x7B\xC6\x44\x80\xCE\x4F\xC4\xC5\xF6\x00\x58\xCC\xA6\xB6\xBC\x14\x49\x68\x04\x76\xE8\xE6\xEE\x5D\xEC\x02\x0F\x60\xD6\x8D\x50\x18\x4F\x26\x4E\x01\xE3\xE6\xB0\xA5\xEE\xBF\xBC\x74\x54\x41\xBF\xFD\xFC\x12\xB8\xC7\x4F\x5A\xF4\x89\x60\x05\x7F\x60\xB7\x05\x4A\xF3\xF6\xF1\xC2\xBF\xC4\xB9\x74\x86\xB6\x2D\x7D\x6B\xCC\xD2\xF3\x46\xDD\x2F\xC6\xE0\x6A\xC3\xC3\x34\x03\x2C\x7D\x96\xDD\x5A\xC2\x0E\xA7\x0A\x99\xC1\x05\x8B\xAB\x0C\x2F\xF3\x5C\x3A\xCF\x6C\x37\x55\x09\x87\xDE\x53\x40\x6C\x58\xEF\xFC\xB6\xAB\x65\x6E\x04\xF6\x1B\xDC\x3C\xE0\x5A\x15\xC6\x9E\xD9\xF1\x59\x48\x30\x21\x65\x03\x6C\xEC\xE9\x21\x73\xEC\x9B\x03\xA1\xE0\x37\xAD\xA0\x15\x18\x8F\xFA\xBA\x02\xCE\xA7\x2C\xA9\x10\x13\x2C\xD4\xE5\x08\x26\xAB\x22\x97\x60\xF8\x90\x5E\x74\xD4\xA2\x9A\x53\xBD\xF2\xA9\x68\xE0\xA2\x6E\xC2\xD7\x6C\xB1\xA3\x0F\x9E\xBF\xEB\x68\xE7\x56\xF2\xAE\xF2\xE3\x2B\x38\x3A\x09\x81\xB5\x6B\x85\xD7\xBE\x2D\xED\x3F\x1A\xB7\xB2\x63\xE2\xF5\x62\x2C\x82\xD4\x6A\x00\x41\x50\xF1\x39\x83\x9F\x95\xE9\x36\x96\x98\x6E", - ["Comodo Secure Services root"] = "\x30\x82\x04\x3F\x30\x82\x03\x27\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x0C\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x0C\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x0C\x11\x43\x6F\x6D\x6F\x64\x6F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x24\x30\x22\x06\x03\x55\x04\x03\x0C\x1B\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x30\x1E\x17\x0D\x30\x34\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x7E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x0C\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x0C\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x0C\x11\x43\x6F\x6D\x6F\x64\x6F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x24\x30\x22\x06\x03\x55\x04\x03\x0C\x1B\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\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\xC0\x71\x33\x82\x8A\xD0\x70\xEB\x73\x87\x82\x40\xD5\x1D\xE4\xCB\xC9\x0E\x42\x90\xF9\xDE\x34\xB9\xA1\xBA\x11\xF4\x25\x85\xF3\xCC\x72\x6D\xF2\x7B\x97\x6B\xB3\x07\xF1\x77\x24\x91\x5F\x25\x8F\xF6\x74\x3D\xE4\x80\xC2\xF8\x3C\x0D\xF3\xBF\x40\xEA\xF7\xC8\x52\xD1\x72\x6F\xEF\xC8\xAB\x41\xB8\x6E\x2E\x17\x2A\x95\x69\x0C\xCD\xD2\x1E\x94\x7B\x2D\x94\x1D\xAA\x75\xD7\xB3\x98\xCB\xAC\xBC\x64\x53\x40\xBC\x8F\xAC\xAC\x36\xCB\x5C\xAD\xBB\xDD\xE0\x94\x17\xEC\xD1\x5C\xD0\xBF\xEF\xA5\x95\xC9\x90\xC5\xB0\xAC\xFB\x1B\x43\xDF\x7A\x08\x5D\xB7\xB8\xF2\x40\x1B\x2B\x27\x9E\x50\xCE\x5E\x65\x82\x88\x8C\x5E\xD3\x4E\x0C\x7A\xEA\x08\x91\xB6\x36\xAA\x2B\x42\xFB\xEA\xC2\xA3\x39\xE5\xDB\x26\x38\xAD\x8B\x0A\xEE\x19\x63\xC7\x1C\x24\xDF\x03\x78\xDA\xE6\xEA\xC1\x47\x1A\x0B\x0B\x46\x09\xDD\x02\xFC\xDE\xCB\x87\x5F\xD7\x30\x63\x68\xA1\xAE\xDC\x32\xA1\xBA\xBE\xFE\x44\xAB\x68\xB6\xA5\x17\x15\xFD\xBD\xD5\xA7\xA7\x9A\xE4\x44\x33\xE9\x88\x8E\xFC\xED\x51\xEB\x93\x71\x4E\xAD\x01\xE7\x44\x8E\xAB\x2D\xCB\xA8\xFE\x01\x49\x48\xF0\xC0\xDD\xC7\x68\xD8\x92\xFE\x3D\x02\x03\x01\x00\x01\xA3\x81\xC7\x30\x81\xC4\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x3C\xD8\x93\x88\xC2\xC0\x82\x09\xCC\x01\x99\x06\x93\x20\xE9\x9E\x70\x09\x63\x4F\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x81\x06\x03\x55\x1D\x1F\x04\x7A\x30\x78\x30\x3B\xA0\x39\xA0\x37\x86\x35\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x63\x61\x2E\x63\x6F\x6D\x2F\x53\x65\x63\x75\x72\x65\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2E\x63\x72\x6C\x30\x39\xA0\x37\xA0\x35\x86\x33\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x2E\x6E\x65\x74\x2F\x53\x65\x63\x75\x72\x65\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x87\x01\x6D\x23\x1D\x7E\x5B\x17\x7D\xC1\x61\x32\xCF\x8F\xE7\xF3\x8A\x94\x59\x66\xE0\x9E\x28\xA8\x5E\xD3\xB7\xF4\x34\xE6\xAA\x39\xB2\x97\x16\xC5\x82\x6F\x32\xA4\xE9\x8C\xE7\xAF\xFD\xEF\xC2\xE8\xB9\x4B\xAA\xA3\xF4\xE6\xDA\x8D\x65\x21\xFB\xBA\x80\xEB\x26\x28\x85\x1A\xFE\x39\x8C\xDE\x5B\x04\x04\xB4\x54\xF9\xA3\x67\x9E\x41\xFA\x09\x52\xCC\x05\x48\xA8\xC9\x3F\x21\x04\x1E\xCE\x48\x6B\xFC\x85\xE8\xC2\x7B\xAF\x7F\xB7\xCC\xF8\x5F\x3A\xFD\x35\xC6\x0D\xEF\x97\xDC\x4C\xAB\x11\xE1\x6B\xCB\x31\xD1\x6C\xFB\x48\x80\xAB\xDC\x9C\x37\xB8\x21\x14\x4B\x0D\x71\x3D\xEC\x83\x33\x6E\xD1\x6E\x32\x16\xEC\x98\xC7\x16\x8B\x59\xA6\x34\xAB\x05\x57\x2D\x93\xF7\xAA\x13\xCB\xD2\x13\xE2\xB7\x2E\x3B\xCD\x6B\x50\x17\x09\x68\x3E\xB5\x26\x57\xEE\xB6\xE0\xB6\xDD\xB9\x29\x80\x79\x7D\x8F\xA3\xF0\xA4\x28\xA4\x15\xC4\x85\xF4\x27\xD4\x6B\xBF\xE5\x5C\xE4\x65\x02\x76\x54\xB4\xE3\x37\x66\x24\xD3\x19\x61\xC8\x52\x10\xE5\x8B\x37\x9A\xB9\xA9\xF9\x1D\xBF\xEA\x99\x92\x61\x96\xFF\x01\xCD\xA1\x5F\x0D\xBC\x71\xBC\x0E\xAC\x0B\x1D\x47\x45\x1D\xC1\xEC\x7C\xEC\xFD\x29", - ["Comodo Trusted Services root"] = "\x30\x82\x04\x43\x30\x82\x03\x2B\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x0C\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x0C\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x0C\x11\x43\x6F\x6D\x6F\x64\x6F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x03\x0C\x1C\x54\x72\x75\x73\x74\x65\x64\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x30\x1E\x17\x0D\x30\x34\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x0C\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x0C\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x0C\x11\x43\x6F\x6D\x6F\x64\x6F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x03\x0C\x1C\x54\x72\x75\x73\x74\x65\x64\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\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\xDF\x71\x6F\x36\x58\x53\x5A\xF2\x36\x54\x57\x80\xC4\x74\x08\x20\xED\x18\x7F\x2A\x1D\xE6\x35\x9A\x1E\x25\xAC\x9C\xE5\x96\x7E\x72\x52\xA0\x15\x42\xDB\x59\xDD\x64\x7A\x1A\xD0\xB8\x7B\xDD\x39\x15\xBC\x55\x48\xC4\xED\x3A\x00\xEA\x31\x11\xBA\xF2\x71\x74\x1A\x67\xB8\xCF\x33\xCC\xA8\x31\xAF\xA3\xE3\xD7\x7F\xBF\x33\x2D\x4C\x6A\x3C\xEC\x8B\xC3\x92\xD2\x53\x77\x24\x74\x9C\x07\x6E\x70\xFC\xBD\x0B\x5B\x76\xBA\x5F\xF2\xFF\xD7\x37\x4B\x4A\x60\x78\xF7\xF0\xFA\xCA\x70\xB4\xEA\x59\xAA\xA3\xCE\x48\x2F\xA9\xC3\xB2\x0B\x7E\x17\x72\x16\x0C\xA6\x07\x0C\x1B\x38\xCF\xC9\x62\xB7\x3F\xA0\x93\xA5\x87\x41\xF2\xB7\x70\x40\x77\xD8\xBE\x14\x7C\xE3\xA8\xC0\x7A\x8E\xE9\x63\x6A\xD1\x0F\x9A\xC6\xD2\xF4\x8B\x3A\x14\x04\x56\xD4\xED\xB8\xCC\x6E\xF5\xFB\xE2\x2C\x58\xBD\x7F\x4F\x6B\x2B\xF7\x60\x24\x58\x24\xCE\x26\xEF\x34\x91\x3A\xD5\xE3\x81\xD0\xB2\xF0\x04\x02\xD7\x5B\xB7\x3E\x92\xAC\x6B\x12\x8A\xF9\xE4\x05\xB0\x3B\x91\x49\x5C\xB2\xEB\x53\xEA\xF8\x9F\x47\x86\xEE\xBF\x95\xC0\xC0\x06\x9F\xD2\x5B\x5E\x11\x1B\xF4\xC7\x04\x35\x29\xD2\x55\x5C\xE4\xED\xEB\x02\x03\x01\x00\x01\xA3\x81\xC9\x30\x81\xC6\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC5\x7B\x58\xBD\xED\xDA\x25\x69\xD2\xF7\x59\x16\xA8\xB3\x32\xC0\x7B\x27\x5B\xF4\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x83\x06\x03\x55\x1D\x1F\x04\x7C\x30\x7A\x30\x3C\xA0\x3A\xA0\x38\x86\x36\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x63\x61\x2E\x63\x6F\x6D\x2F\x54\x72\x75\x73\x74\x65\x64\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2E\x63\x72\x6C\x30\x3A\xA0\x38\xA0\x36\x86\x34\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x2E\x6E\x65\x74\x2F\x54\x72\x75\x73\x74\x65\x64\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xC8\x93\x81\x3B\x89\xB4\xAF\xB8\x84\x12\x4C\x8D\xD2\xF0\xDB\x70\xBA\x57\x86\x15\x34\x10\xB9\x2F\x7F\x1E\xB0\xA8\x89\x60\xA1\x8A\xC2\x77\x0C\x50\x4A\x9B\x00\x8B\xD8\x8B\xF4\x41\xE2\xD0\x83\x8A\x4A\x1C\x14\x06\xB0\xA3\x68\x05\x70\x31\x30\xA7\x53\x9B\x0E\xE9\x4A\xA0\x58\x69\x67\x0E\xAE\x9D\xF6\xA5\x2C\x41\xBF\x3C\x06\x6B\xE4\x59\xCC\x6D\x10\xF1\x96\x6F\x1F\xDF\xF4\x04\x02\xA4\x9F\x45\x3E\xC8\xD8\xFA\x36\x46\x44\x50\x3F\x82\x97\x91\x1F\x28\xDB\x18\x11\x8C\x2A\xE4\x65\x83\x57\x12\x12\x8C\x17\x3F\x94\x36\xFE\x5D\xB0\xC0\x04\x77\x13\xB8\xF4\x15\xD5\x3F\x38\xCC\x94\x3A\x55\xD0\xAC\x98\xF5\xBA\x00\x5F\xE0\x86\x19\x81\x78\x2F\x28\xC0\x7E\xD3\xCC\x42\x0A\xF5\xAE\x50\xA0\xD1\x3E\xC6\xA1\x71\xEC\x3F\xA0\x20\x8C\x66\x3A\x89\xB4\x8E\xD4\xD8\xB1\x4D\x25\x47\xEE\x2F\x88\xC8\xB5\xE1\x05\x45\xC0\xBE\x14\x71\xDE\x7A\xFD\x8E\x7B\x7D\x4D\x08\x96\xA5\x12\x73\xF0\x2D\xCA\x37\x27\x74\x12\x27\x4C\xCB\xB6\x97\xE9\xD9\xAE\x08\x6D\x5A\x39\x40\xDD\x05\x47\x75\x6A\x5A\x21\xB3\xA3\x18\xCF\x4E\xF7\x2E\x57\xB7\x98\x70\x5E\xC8\xC4\x78\xB0\x62", - ["QuoVadis Root CA"] = "\x30\x82\x05\xD0\x30\x82\x04\xB8\xA0\x03\x02\x01\x02\x02\x04\x3A\xB6\x50\x8B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x2E\x30\x2C\x06\x03\x55\x04\x03\x13\x25\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x31\x30\x33\x31\x39\x31\x38\x33\x33\x33\x33\x5A\x17\x0D\x32\x31\x30\x33\x31\x37\x31\x38\x33\x33\x33\x33\x5A\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x2E\x30\x2C\x06\x03\x55\x04\x03\x13\x25\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\x61\xB5\x95\x53\xBA\x57\xFC\xFA\xF2\x67\x0B\x3A\x1A\xDF\x11\x80\x64\x95\xB4\xD1\xBC\xCD\x7A\xCF\xF6\x29\x96\x2E\x24\x54\x40\x24\x38\xF7\x1A\x85\xDC\x58\x4C\xCB\xA4\x27\x42\x97\xD0\x9F\x83\x8A\xC3\xE4\x06\x03\x5B\x00\xA5\x51\x1E\x70\x04\x74\xE2\xC1\xD4\x3A\xAB\xD7\xAD\x3B\x07\x18\x05\x8E\xFD\x83\xAC\xEA\x66\xD9\x18\x1B\x68\x8A\xF5\x57\x1A\x98\xBA\xF5\xED\x76\x3D\x7C\xD9\xDE\x94\x6A\x3B\x4B\x17\xC1\xD5\x8F\xBD\x65\x38\x3A\x95\xD0\x3D\x55\x36\x4E\xDF\x79\x57\x31\x2A\x1E\xD8\x59\x65\x49\x58\x20\x98\x7E\xAB\x5F\x7E\x9F\xE9\xD6\x4D\xEC\x83\x74\xA9\xC7\x6C\xD8\xEE\x29\x4A\x85\x2A\x06\x14\xF9\x54\xE6\xD3\xDA\x65\x07\x8B\x63\x37\x12\xD7\xD0\xEC\xC3\x7B\x20\x41\x44\xA3\xED\xCB\xA0\x17\xE1\x71\x65\xCE\x1D\x66\x31\xF7\x76\x01\x19\xC8\x7D\x03\x58\xB6\x95\x49\x1D\xA6\x12\x26\xE8\xC6\x0C\x76\xE0\xE3\x66\xCB\xEA\x5D\xA6\x26\xEE\xE5\xCC\x5F\xBD\x67\xA7\x01\x27\x0E\xA2\xCA\x54\xC5\xB1\x7A\x95\x1D\x71\x1E\x4A\x29\x8A\x03\xDC\x6A\x45\xC1\xA4\x19\x5E\x6F\x36\xCD\xC3\xA2\xB0\xB7\xFE\x5C\x38\xE2\x52\xBC\xF8\x44\x43\xE6\x90\xBB\x02\x03\x01\x00\x01\xA3\x82\x02\x52\x30\x82\x02\x4E\x30\x3D\x06\x08\x2B\x06\x01\x05\x05\x07\x01\x01\x04\x31\x30\x2F\x30\x2D\x06\x08\x2B\x06\x01\x05\x05\x07\x30\x01\x86\x21\x68\x74\x74\x70\x73\x3A\x2F\x2F\x6F\x63\x73\x70\x2E\x71\x75\x6F\x76\x61\x64\x69\x73\x6F\x66\x66\x73\x68\x6F\x72\x65\x2E\x63\x6F\x6D\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x82\x01\x1A\x06\x03\x55\x1D\x20\x04\x82\x01\x11\x30\x82\x01\x0D\x30\x82\x01\x09\x06\x09\x2B\x06\x01\x04\x01\xBE\x58\x00\x01\x30\x81\xFB\x30\x81\xD4\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x81\xC7\x1A\x81\xC4\x52\x65\x6C\x69\x61\x6E\x63\x65\x20\x6F\x6E\x20\x74\x68\x65\x20\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x62\x79\x20\x61\x6E\x79\x20\x70\x61\x72\x74\x79\x20\x61\x73\x73\x75\x6D\x65\x73\x20\x61\x63\x63\x65\x70\x74\x61\x6E\x63\x65\x20\x6F\x66\x20\x74\x68\x65\x20\x74\x68\x65\x6E\x20\x61\x70\x70\x6C\x69\x63\x61\x62\x6C\x65\x20\x73\x74\x61\x6E\x64\x61\x72\x64\x20\x74\x65\x72\x6D\x73\x20\x61\x6E\x64\x20\x63\x6F\x6E\x64\x69\x74\x69\x6F\x6E\x73\x20\x6F\x66\x20\x75\x73\x65\x2C\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x70\x72\x61\x63\x74\x69\x63\x65\x73\x2C\x20\x61\x6E\x64\x20\x74\x68\x65\x20\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x50\x6F\x6C\x69\x63\x79\x2E\x30\x22\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x16\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x71\x75\x6F\x76\x61\x64\x69\x73\x2E\x62\x6D\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x8B\x4B\x6D\xED\xD3\x29\xB9\x06\x19\xEC\x39\x39\xA9\xF0\x97\x84\x6A\xCB\xEF\xDF\x30\x81\xAE\x06\x03\x55\x1D\x23\x04\x81\xA6\x30\x81\xA3\x80\x14\x8B\x4B\x6D\xED\xD3\x29\xB9\x06\x19\xEC\x39\x39\xA9\xF0\x97\x84\x6A\xCB\xEF\xDF\xA1\x81\x84\xA4\x81\x81\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x2E\x30\x2C\x06\x03\x55\x04\x03\x13\x25\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x82\x04\x3A\xB6\x50\x8B\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x8A\xD4\x14\xB5\xFE\xF4\x9A\x92\xA7\x19\xD4\xA4\x7E\x72\x18\x8F\xD9\x68\x7C\x52\x24\xDD\x67\x6F\x39\x7A\xC4\xAA\x5E\x3D\xE2\x58\xB0\x4D\x70\x98\x84\x61\xE8\x1B\xE3\x69\x18\x0E\xCE\xFB\x47\x50\xA0\x4E\xFF\xF0\x24\x1F\xBD\xB2\xCE\xF5\x27\xFC\xEC\x2F\x53\xAA\x73\x7B\x03\x3D\x74\x6E\xE6\x16\x9E\xEB\xA5\x2E\xC4\xBF\x56\x27\x50\x2B\x62\xBA\xBE\x4B\x1C\x3C\x55\x5C\x41\x1D\x24\xBE\x82\x20\x47\x5D\xD5\x44\x7E\x7A\x16\x68\xDF\x7D\x4D\x51\x70\x78\x57\x1D\x33\x1E\xFD\x02\x99\x9C\x0C\xCD\x0A\x05\x4F\xC7\xBB\x8E\xA4\x75\xFA\x4A\x6D\xB1\x80\x8E\x09\x56\xB9\x9C\x1A\x60\xFE\x5D\xC1\xD7\x7A\xDC\x11\x78\xD0\xD6\x5D\xC1\xB7\xD5\xAD\x32\x99\x03\x3A\x8A\xCC\x54\x25\x39\x31\x81\x7B\x13\x22\x51\xBA\x46\x6C\xA1\xBB\x9E\xFA\x04\x6C\x49\x26\x74\x8F\xD2\x73\xEB\xCC\x30\xA2\xE6\xEA\x59\x22\x87\xF8\x97\xF5\x0E\xFD\xEA\xCC\x92\xA4\x16\xC4\x52\x18\xEA\x21\xCE\xB1\xF1\xE6\x84\x81\xE5\xBA\xA9\x86\x28\xF2\x43\x5A\x5D\x12\x9D\xAC\x1E\xD9\xA8\xE5\x0A\x6A\xA7\x7F\xA0\x87\x29\xCF\xF2\x89\x4D\xD4\xEC\xC5\xE2\xE6\x7A\xD0\x36\x23\x8A\x4A\x74\x36\xF9", - ["QuoVadis Root CA 2"] = "\x30\x82\x05\xB7\x30\x82\x03\x9F\xA0\x03\x02\x01\x02\x02\x02\x05\x09\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x1E\x17\x0D\x30\x36\x31\x31\x32\x34\x31\x38\x32\x37\x30\x30\x5A\x17\x0D\x33\x31\x31\x31\x32\x34\x31\x38\x32\x33\x33\x33\x5A\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\x9A\x18\xCA\x4B\x94\x0D\x00\x2D\xAF\x03\x29\x8A\xF0\x0F\x81\xC8\xAE\x4C\x19\x85\x1D\x08\x9F\xAB\x29\x44\x85\xF3\x2F\x81\xAD\x32\x1E\x90\x46\xBF\xA3\x86\x26\x1A\x1E\xFE\x7E\x1C\x18\x3A\x5C\x9C\x60\x17\x2A\x3A\x74\x83\x33\x30\x7D\x61\x54\x11\xCB\xED\xAB\xE0\xE6\xD2\xA2\x7E\xF5\x6B\x6F\x18\xB7\x0A\x0B\x2D\xFD\xE9\x3E\xEF\x0A\xC6\xB3\x10\xE9\xDC\xC2\x46\x17\xF8\x5D\xFD\xA4\xDA\xFF\x9E\x49\x5A\x9C\xE6\x33\xE6\x24\x96\xF7\x3F\xBA\x5B\x2B\x1C\x7A\x35\xC2\xD6\x67\xFE\xAB\x66\x50\x8B\x6D\x28\x60\x2B\xEF\xD7\x60\xC3\xC7\x93\xBC\x8D\x36\x91\xF3\x7F\xF8\xDB\x11\x13\xC4\x9C\x77\x76\xC1\xAE\xB7\x02\x6A\x81\x7A\xA9\x45\x83\xE2\x05\xE6\xB9\x56\xC1\x94\x37\x8F\x48\x71\x63\x22\xEC\x17\x65\x07\x95\x8A\x4B\xDF\x8F\xC6\x5A\x0A\xE5\xB0\xE3\x5F\x5E\x6B\x11\xAB\x0C\xF9\x85\xEB\x44\xE9\xF8\x04\x73\xF2\xE9\xFE\x5C\x98\x8C\xF5\x73\xAF\x6B\xB4\x7E\xCD\xD4\x5C\x02\x2B\x4C\x39\xE1\xB2\x95\x95\x2D\x42\x87\xD7\xD5\xB3\x90\x43\xB7\x6C\x13\xF1\xDE\xDD\xF6\xC4\xF8\x89\x3F\xD1\x75\xF5\x92\xC3\x91\xD5\x8A\x88\xD0\x90\xEC\xDC\x6D\xDE\x89\xC2\x65\x71\x96\x8B\x0D\x03\xFD\x9C\xBF\x5B\x16\xAC\x92\xDB\xEA\xFE\x79\x7C\xAD\xEB\xAF\xF7\x16\xCB\xDB\xCD\x25\x2B\xE5\x1F\xFB\x9A\x9F\xE2\x51\xCC\x3A\x53\x0C\x48\xE6\x0E\xBD\xC9\xB4\x76\x06\x52\xE6\x11\x13\x85\x72\x63\x03\x04\xE0\x04\x36\x2B\x20\x19\x02\xE8\x74\xA7\x1F\xB6\xC9\x56\x66\xF0\x75\x25\xDC\x67\xC1\x0E\x61\x60\x88\xB3\x3E\xD1\xA8\xFC\xA3\xDA\x1D\xB0\xD1\xB1\x23\x54\xDF\x44\x76\x6D\xED\x41\xD8\xC1\xB2\x22\xB6\x53\x1C\xDF\x35\x1D\xDC\xA1\x77\x2A\x31\xE4\x2D\xF5\xE5\xE5\xDB\xC8\xE0\xFF\xE5\x80\xD7\x0B\x63\xA0\xFF\x33\xA1\x0F\xBA\x2C\x15\x15\xEA\x97\xB3\xD2\xA2\xB5\xBE\xF2\x8C\x96\x1E\x1A\x8F\x1D\x6C\xA4\x61\x37\xB9\x86\x73\x33\xD7\x97\x96\x9E\x23\x7D\x82\xA4\x4C\x81\xE2\xA1\xD1\xBA\x67\x5F\x95\x07\xA3\x27\x11\xEE\x16\x10\x7B\xBC\x45\x4A\x4C\xB2\x04\xD2\xAB\xEF\xD5\xFD\x0C\x51\xCE\x50\x6A\x08\x31\xF9\x91\xDA\x0C\x8F\x64\x5C\x03\xC3\x3A\x8B\x20\x3F\x6E\x8D\x67\x3D\x3A\xD6\xFE\x7D\x5B\x88\xC9\x5E\xFB\xCC\x61\xDC\x8B\x33\x77\xD3\x44\x32\x35\x09\x62\x04\x92\x16\x10\xD8\x9E\x27\x47\xFB\x3B\x21\xE3\xF8\xEB\x1D\x5B\x02\x03\x01\x00\x01\xA3\x81\xB0\x30\x81\xAD\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x1A\x84\x62\xBC\x48\x4C\x33\x25\x04\xD4\xEE\xD0\xF6\x03\xC4\x19\x46\xD1\x94\x6B\x30\x6E\x06\x03\x55\x1D\x23\x04\x67\x30\x65\x80\x14\x1A\x84\x62\xBC\x48\x4C\x33\x25\x04\xD4\xEE\xD0\xF6\x03\xC4\x19\x46\xD1\x94\x6B\xA1\x49\xA4\x47\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x82\x02\x05\x09\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x3E\x0A\x16\x4D\x9F\x06\x5B\xA8\xAE\x71\x5D\x2F\x05\x2F\x67\xE6\x13\x45\x83\xC4\x36\xF6\xF3\xC0\x26\x0C\x0D\xB5\x47\x64\x5D\xF8\xB4\x72\xC9\x46\xA5\x03\x18\x27\x55\x89\x78\x7D\x76\xEA\x96\x34\x80\x17\x20\xDC\xE7\x83\xF8\x8D\xFC\x07\xB8\xDA\x5F\x4D\x2E\x67\xB2\x84\xFD\xD9\x44\xFC\x77\x50\x81\xE6\x7C\xB4\xC9\x0D\x0B\x72\x53\xF8\x76\x07\x07\x41\x47\x96\x0C\xFB\xE0\x82\x26\x93\x55\x8C\xFE\x22\x1F\x60\x65\x7C\x5F\xE7\x26\xB3\xF7\x32\x90\x98\x50\xD4\x37\x71\x55\xF6\x92\x21\x78\xF7\x95\x79\xFA\xF8\x2D\x26\x87\x66\x56\x30\x77\xA6\x37\x78\x33\x52\x10\x58\xAE\x3F\x61\x8E\xF2\x6A\xB1\xEF\x18\x7E\x4A\x59\x63\xCA\x8D\xA2\x56\xD5\xA7\x2F\xBC\x56\x1F\xCF\x39\xC1\xE2\xFB\x0A\xA8\x15\x2C\x7D\x4D\x7A\x63\xC6\x6C\x97\x44\x3C\xD2\x6F\xC3\x4A\x17\x0A\xF8\x90\xD2\x57\xA2\x19\x51\xA5\x2D\x97\x41\xDA\x07\x4F\xA9\x50\xDA\x90\x8D\x94\x46\xE1\x3E\xF0\x94\xFD\x10\x00\x38\xF5\x3B\xE8\x40\xE1\xB4\x6E\x56\x1A\x20\xCC\x6F\x58\x8D\xED\x2E\x45\x8F\xD6\xE9\x93\x3F\xE7\xB1\x2C\xDF\x3A\xD6\x22\x8C\xDC\x84\xBB\x22\x6F\xD0\xF8\xE4\xC6\x39\xE9\x04\x88\x3C\xC3\xBA\xEB\x55\x7A\x6D\x80\x99\x24\xF5\x6C\x01\xFB\xF8\x97\xB0\x94\x5B\xEB\xFD\xD2\x6F\xF1\x77\x68\x0D\x35\x64\x23\xAC\xB8\x55\xA1\x03\xD1\x4D\x42\x19\xDC\xF8\x75\x59\x56\xA3\xF9\xA8\x49\x79\xF8\xAF\x0E\xB9\x11\xA0\x7C\xB7\x6A\xED\x34\xD0\xB6\x26\x62\x38\x1A\x87\x0C\xF8\xE8\xFD\x2E\xD3\x90\x7F\x07\x91\x2A\x1D\xD6\x7E\x5C\x85\x83\x99\xB0\x38\x08\x3F\xE9\x5E\xF9\x35\x07\xE4\xC9\x62\x6E\x57\x7F\xA7\x50\x95\xF7\xBA\xC8\x9B\xE6\x8E\xA2\x01\xC5\xD6\x66\xBF\x79\x61\xF3\x3C\x1C\xE1\xB9\x82\x5C\x5D\xA0\xC3\xE9\xD8\x48\xBD\x19\xA2\x11\x14\x19\x6E\xB2\x86\x1B\x68\x3E\x48\x37\x1A\x88\xB7\x5D\x96\x5E\x9C\xC7\xEF\x27\x62\x08\xE2\x91\x19\x5C\xD2\xF1\x21\xDD\xBA\x17\x42\x82\x97\x71\x81\x53\x31\xA9\x9F\xF6\x7D\x62\xBF\x72\xE1\xA3\x93\x1D\xCC\x8A\x26\x5A\x09\x38\xD0\xCE\xD7\x0D\x80\x16\xB4\x78\xA5\x3A\x87\x4C\x8D\x8A\xA5\xD5\x46\x97\xF2\x2C\x10\xB9\xBC\x54\x22\xC0\x01\x50\x69\x43\x9E\xF4\xB2\xEF\x6D\xF8\xEC\xDA\xF1\xE3\xB1\xEF\xDF\x91\x8F\x54\x2A\x0B\x25\xC1\x26\x19\xC4\x52\x10\x05\x65\xD5\x82\x10\xEA\xC2\x31\xCD\x2E", - ["QuoVadis Root CA 3"] = "\x30\x82\x06\x9D\x30\x82\x04\x85\xA0\x03\x02\x01\x02\x02\x02\x05\xC6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x33\x30\x1E\x17\x0D\x30\x36\x31\x31\x32\x34\x31\x39\x31\x31\x32\x33\x5A\x17\x0D\x33\x31\x31\x31\x32\x34\x31\x39\x30\x36\x34\x34\x5A\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x33\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xCC\x57\x42\x16\x54\x9C\xE6\x98\xD3\xD3\x4D\xEE\xFE\xED\xC7\x9F\x43\x39\x4A\x65\xB3\xE8\x16\x88\x34\xDB\x0D\x59\x91\x74\xCF\x92\xB8\x04\x40\xAD\x02\x4B\x31\xAB\xBC\x8D\x91\x68\xD8\x20\x0E\x1A\x01\xE2\x1A\x7B\x4E\x17\x5D\xE2\x8A\xB7\x3F\x99\x1A\xCD\xEB\x61\xAB\xC2\x65\xA6\x1F\xB7\xB7\xBD\xB7\x8F\xFC\xFD\x70\x8F\x0B\xA0\x67\xBE\x01\xA2\x59\xCF\x71\xE6\x0F\x29\x76\xFF\xB1\x56\x79\x45\x2B\x1F\x9E\x7A\x54\xE8\xA3\x29\x35\x68\xA4\x01\x4F\x0F\xA4\x2E\x37\xEF\x1B\xBF\xE3\x8F\x10\xA8\x72\xAB\x58\x57\xE7\x54\x86\xC8\xC9\xF3\x5B\xDA\x2C\xDA\x5D\x8E\x6E\x3C\xA3\x3E\xDA\xFB\x82\xE5\xDD\xF2\x5C\xB2\x05\x33\x6F\x8A\x36\xCE\xD0\x13\x4E\xFF\xBF\x4A\x0C\x34\x4C\xA6\xC3\x21\xBD\x50\x04\x55\xEB\xB1\xBB\x9D\xFB\x45\x1E\x64\x15\xDE\x55\x01\x8C\x02\x76\xB5\xCB\xA1\x3F\x42\x69\xBC\x2F\xBD\x68\x43\x16\x56\x89\x2A\x37\x61\x91\xFD\xA6\xAE\x4E\xC0\xCB\x14\x65\x94\x37\x4B\x92\x06\xEF\x04\xD0\xC8\x9C\x88\xDB\x0B\x7B\x81\xAF\xB1\x3D\x2A\xC4\x65\x3A\x78\xB6\xEE\xDC\x80\xB1\xD2\xD3\x99\x9C\x3A\xEE\x6B\x5A\x6B\xB3\x8D\xB7\xD5\xCE\x9C\xC2\xBE\xA5\x4B\x2F\x16\xB1\x9E\x68\x3B\x06\x6F\xAE\x7D\x9F\xF8\xDE\xEC\xCC\x29\xA7\x98\xA3\x25\x43\x2F\xEF\xF1\x5F\x26\xE1\x88\x4D\xF8\x5E\x6E\xD7\xD9\x14\x6E\x19\x33\x69\xA7\x3B\x84\x89\x93\xC4\x53\x55\x13\xA1\x51\x78\x40\xF8\xB8\xC9\xA2\xEE\x7B\xBA\x52\x42\x83\x9E\x14\xED\x05\x52\x5A\x59\x56\xA7\x97\xFC\x9D\x3F\x0A\x29\xD8\xDC\x4F\x91\x0E\x13\xBC\xDE\x95\xA4\xDF\x8B\x99\xBE\xAC\x9B\x33\x88\xEF\xB5\x81\xAF\x1B\xC6\x22\x53\xC8\xF6\xC7\xEE\x97\x14\xB0\xC5\x7C\x78\x52\xC8\xF0\xCE\x6E\x77\x60\x84\xA6\xE9\x2A\x76\x20\xED\x58\x01\x17\x30\x93\xE9\x1A\x8B\xE0\x73\x63\xD9\x6A\x92\x94\x49\x4E\xB4\xAD\x4A\x85\xC4\xA3\x22\x30\xFC\x09\xED\x68\x22\x73\xA6\x88\x0C\x55\x21\x58\xC5\xE1\x3A\x9F\x2A\xDD\xCA\xE1\x90\xE0\xD9\x73\xAB\x6C\x80\xB8\xE8\x0B\x64\x93\xA0\x9C\x8C\x19\xFF\xB3\xD2\x0C\xEC\x91\x26\x87\x8A\xB3\xA2\xE1\x70\x8F\x2C\x0A\xE5\xCD\x6D\x68\x51\xEB\xDA\x3F\x05\x7F\x8B\x32\xE6\x13\x5C\x6B\xFE\x5F\x40\xE2\x22\xC8\xB4\xB4\x64\x4F\xD6\xBA\x7D\x48\x3E\xA8\x69\x0C\xD7\xBB\x86\x71\xC9\x73\xB8\x3F\x3B\x9D\x25\x4B\xDA\xFF\x40\xEB\x02\x03\x01\x00\x01\xA3\x82\x01\x95\x30\x82\x01\x91\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\xE1\x06\x03\x55\x1D\x20\x04\x81\xD9\x30\x81\xD6\x30\x81\xD3\x06\x09\x2B\x06\x01\x04\x01\xBE\x58\x00\x03\x30\x81\xC5\x30\x81\x93\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x81\x86\x1A\x81\x83\x41\x6E\x79\x20\x75\x73\x65\x20\x6F\x66\x20\x74\x68\x69\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x63\x6F\x6E\x73\x74\x69\x74\x75\x74\x65\x73\x20\x61\x63\x63\x65\x70\x74\x61\x6E\x63\x65\x20\x6F\x66\x20\x74\x68\x65\x20\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x50\x6F\x6C\x69\x63\x79\x20\x2F\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x50\x72\x61\x63\x74\x69\x63\x65\x20\x53\x74\x61\x74\x65\x6D\x65\x6E\x74\x2E\x30\x2D\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x21\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x71\x75\x6F\x76\x61\x64\x69\x73\x67\x6C\x6F\x62\x61\x6C\x2E\x63\x6F\x6D\x2F\x63\x70\x73\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xF2\xC0\x13\xE0\x82\x43\x3E\xFB\xEE\x2F\x67\x32\x96\x35\x5C\xDB\xB8\xCB\x02\xD0\x30\x6E\x06\x03\x55\x1D\x23\x04\x67\x30\x65\x80\x14\xF2\xC0\x13\xE0\x82\x43\x3E\xFB\xEE\x2F\x67\x32\x96\x35\x5C\xDB\xB8\xCB\x02\xD0\xA1\x49\xA4\x47\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x33\x82\x02\x05\xC6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x4F\xAD\xA0\x2C\x4C\xFA\xC0\xF2\x6F\xF7\x66\x55\xAB\x23\x34\xEE\xE7\x29\xDA\xC3\x5B\xB6\xB0\x83\xD9\xD0\xD0\xE2\x21\xFB\xF3\x60\xA7\x3B\x5D\x60\x53\x27\xA2\x9B\xF6\x08\x22\x2A\xE7\xBF\xA0\x72\xE5\x9C\x24\x6A\x31\xB1\x90\x7A\x27\xDB\x84\x11\x89\x27\xA6\x77\x5A\x38\xD7\xBF\xAC\x86\xFC\xEE\x5D\x83\xBC\x06\xC6\xD1\x77\x6B\x0F\x6D\x24\x2F\x4B\x7A\x6C\xA7\x07\x96\xCA\xE3\x84\x9F\xAD\x88\x8B\x1D\xAB\x16\x8D\x5B\x66\x17\xD9\x16\xF4\x8B\x80\xD2\xDD\xF8\xB2\x76\xC3\xFC\x38\x13\xAA\x0C\xDE\x42\x69\x2B\x6E\xF3\x3C\xEB\x80\x27\xDB\xF5\xA6\x44\x0D\x9F\x5A\x55\x59\x0B\xD5\x0D\x52\x48\xC5\xAE\x9F\xF2\x2F\x80\xC5\xEA\x32\x50\x35\x12\x97\x2E\xC1\xE1\xFF\xF1\x23\x88\x51\x38\x9F\xF2\x66\x56\x76\xE7\x0F\x51\x97\xA5\x52\x0C\x4D\x49\x51\x95\x36\x3D\xBF\xA2\x4B\x0C\x10\x1D\x86\x99\x4C\xAA\xF3\x72\x11\x93\xE4\xEA\xF6\x9B\xDA\xA8\x5D\xA7\x4D\xB7\x9E\x02\xAE\x73\x00\xC8\xDA\x23\x03\xE8\xF9\xEA\x19\x74\x62\x00\x94\xCB\x22\x20\xBE\x94\xA7\x59\xB5\x82\x6A\xBE\x99\x79\x7A\xA9\xF2\x4A\x24\x52\xF7\x74\xFD\xBA\x4E\xE6\xA8\x1D\x02\x6E\xB1\x0D\x80\x44\xC1\xAE\xD3\x23\x37\x5F\xBB\x85\x7C\x2B\x92\x2E\xE8\x7E\xA5\x8B\xDD\x99\xE1\xBF\x27\x6F\x2D\x5D\xAA\x7B\x87\xFE\x0A\xDD\x4B\xFC\x8E\xF5\x26\xE4\x6E\x70\x42\x6E\x33\xEC\x31\x9E\x7B\x93\xC1\xE4\xC9\x69\x1A\x3D\xC0\x6B\x4E\x22\x6D\xEE\xAB\x58\x4D\xC6\xD0\x41\xC1\x2B\xEA\x4F\x12\x87\x5E\xEB\x45\xD8\x6C\xF5\x98\x02\xD3\xA0\xD8\x55\x8A\x06\x99\x19\xA2\xA0\x77\xD1\x30\x9E\xAC\xCC\x75\xEE\x83\xF5\xB0\x62\x39\xCF\x6C\x57\xE2\x4C\xD2\x91\x0B\x0E\x75\x28\x1B\x9A\xBF\xFD\x1A\x43\xF1\xCA\x77\xFB\x3B\x8F\x61\xB8\x69\x28\x16\x42\x04\x5E\x70\x2A\x1C\x21\xD8\x8F\xE1\xBD\x23\x5B\x2D\x74\x40\x92\xD9\x63\x19\x0D\x73\xDD\x69\xBC\x62\x47\xBC\xE0\x74\x2B\xB2\xEB\x7D\xBE\x41\x1B\xB5\xC0\x46\xC5\xA1\x22\xCB\x5F\x4E\xC1\x28\x92\xDE\x18\xBA\xD5\x2A\x28\xBB\x11\x8B\x17\x93\x98\x99\x60\x94\x5C\x23\xCF\x5A\x27\x97\x5E\x0B\x05\x06\x93\x37\x1E\x3B\x69\x36\xEB\xA9\x9E\x61\x1D\x8F\x32\xDA\x8E\x0C\xD6\x74\x3E\x7B\x09\x24\xDA\x01\x77\x47\xC4\x3B\xCD\x34\x8C\x99\xF5\xCA\xE1\x25\x61\x33\xB2\x59\x1B\xE2\x6E\xD7\x37\x57\xB6\x0D\xA9\x12\xDA", - ["Security Communication Root CA"] = "\x30\x82\x03\x5A\x30\x82\x02\x42\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x50\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x13\x0F\x53\x45\x43\x4F\x4D\x20\x54\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0B\x13\x1E\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6F\x6D\x6D\x75\x6E\x69\x63\x61\x74\x69\x6F\x6E\x20\x52\x6F\x6F\x74\x43\x41\x31\x30\x1E\x17\x0D\x30\x33\x30\x39\x33\x30\x30\x34\x32\x30\x34\x39\x5A\x17\x0D\x32\x33\x30\x39\x33\x30\x30\x34\x32\x30\x34\x39\x5A\x30\x50\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x13\x0F\x53\x45\x43\x4F\x4D\x20\x54\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0B\x13\x1E\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6F\x6D\x6D\x75\x6E\x69\x63\x61\x74\x69\x6F\x6E\x20\x52\x6F\x6F\x74\x43\x41\x31\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\xB3\xB3\xFE\x7F\xD3\x6D\xB1\xEF\x16\x7C\x57\xA5\x0C\x6D\x76\x8A\x2F\x4B\xBF\x64\xFB\x4C\xEE\x8A\xF0\xF3\x29\x7C\xF5\xFF\xEE\x2A\xE0\xE9\xE9\xBA\x5B\x64\x22\x9A\x9A\x6F\x2C\x3A\x26\x69\x51\x05\x99\x26\xDC\xD5\x1C\x6A\x71\xC6\x9A\x7D\x1E\x9D\xDD\x7C\x6C\xC6\x8C\x67\x67\x4A\x3E\xF8\x71\xB0\x19\x27\xA9\x09\x0C\xA6\x95\xBF\x4B\x8C\x0C\xFA\x55\x98\x3B\xD8\xE8\x22\xA1\x4B\x71\x38\x79\xAC\x97\x92\x69\xB3\x89\x7E\xEA\x21\x68\x06\x98\x14\x96\x87\xD2\x61\x36\xBC\x6D\x27\x56\x9E\x57\xEE\xC0\xC0\x56\xFD\x32\xCF\xA4\xD9\x8E\xC2\x23\xD7\x8D\xA8\xF3\xD8\x25\xAC\x97\xE4\x70\x38\xF4\xB6\x3A\xB4\x9D\x3B\x97\x26\x43\xA3\xA1\xBC\x49\x59\x72\x4C\x23\x30\x87\x01\x58\xF6\x4E\xBE\x1C\x68\x56\x66\xAF\xCD\x41\x5D\xC8\xB3\x4D\x2A\x55\x46\xAB\x1F\xDA\x1E\xE2\x40\x3D\xDB\xCD\x7D\xB9\x92\x80\x9C\x37\xDD\x0C\x96\x64\x9D\xDC\x22\xF7\x64\x8B\xDF\x61\xDE\x15\x94\x52\x15\xA0\x7D\x52\xC9\x4B\xA8\x21\xC9\xC6\xB1\xED\xCB\xC3\x95\x60\xD1\x0F\xF0\xAB\x70\xF8\xDF\xCB\x4D\x7E\xEC\xD6\xFA\xAB\xD9\xBD\x7F\x54\xF2\xA5\xE9\x79\xFA\xD9\xD6\x76\x24\x28\x73\x02\x03\x01\x00\x01\xA3\x3F\x30\x3D\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xA0\x73\x49\x99\x68\xDC\x85\x5B\x65\xE3\x9B\x28\x2F\x57\x9F\xBD\x33\xBC\x07\x48\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x68\x40\xA9\xA8\xBB\xE4\x4F\x5D\x79\xB3\x05\xB5\x17\xB3\x60\x13\xEB\xC6\x92\x5D\xE0\xD1\xD3\x6A\xFE\xFB\xBE\x9B\x6D\xBF\xC7\x05\x6D\x59\x20\xC4\x1C\xF0\xB7\xDA\x84\x58\x02\x63\xFA\x48\x16\xEF\x4F\xA5\x0B\xF7\x4A\x98\xF2\x3F\x9E\x1B\xAD\x47\x6B\x63\xCE\x08\x47\xEB\x52\x3F\x78\x9C\xAF\x4D\xAE\xF8\xD5\x4F\xCF\x9A\x98\x2A\x10\x41\x39\x52\xC4\xDD\xD9\x9B\x0E\xEF\x93\x01\xAE\xB2\x2E\xCA\x68\x42\x24\x42\x6C\xB0\xB3\x3A\x3E\xCD\xE9\xDA\x48\xC4\x15\xCB\xE9\xF9\x07\x0F\x92\x50\x49\x8A\xDD\x31\x97\x5F\xC9\xE9\x37\xAA\x3B\x59\x65\x97\x94\x32\xC9\xB3\x9F\x3E\x3A\x62\x58\xC5\x49\xAD\x62\x0E\x71\xA5\x32\xAA\x2F\xC6\x89\x76\x43\x40\x13\x13\x67\x3D\xA2\x54\x25\x10\xCB\xF1\x3A\xF2\xD9\xFA\xDB\x49\x56\xBB\xA6\xFE\xA7\x41\x35\xC3\xE0\x88\x61\xC9\x88\xC7\xDF\x36\x10\x22\x98\x59\xEA\xB0\x4A\xFB\x56\x16\x73\x6E\xAC\x4D\xF7\x22\xA1\x4F\xAD\x1D\x7A\x2D\x45\x27\xE5\x30\xC1\x5E\xF2\xDA\x13\xCB\x25\x42\x51\x95\x47\x03\x8C\x6C\x21\xCC\x74\x42\xED\x53\xFF\x33\x8B\x8F\x0F\x57\x01\x16\x2F\xCF\xA6\xEE\xC9\x70\x22\x14\xBD\xFD\xBE\x6C\x0B\x03", - ["Sonera Class 2 Root CA"] = "\x30\x82\x03\x20\x30\x82\x02\x08\xA0\x03\x02\x01\x02\x02\x01\x1D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x39\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x49\x31\x0F\x30\x0D\x06\x03\x55\x04\x0A\x13\x06\x53\x6F\x6E\x65\x72\x61\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x6F\x6E\x65\x72\x61\x20\x43\x6C\x61\x73\x73\x32\x20\x43\x41\x30\x1E\x17\x0D\x30\x31\x30\x34\x30\x36\x30\x37\x32\x39\x34\x30\x5A\x17\x0D\x32\x31\x30\x34\x30\x36\x30\x37\x32\x39\x34\x30\x5A\x30\x39\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x49\x31\x0F\x30\x0D\x06\x03\x55\x04\x0A\x13\x06\x53\x6F\x6E\x65\x72\x61\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x6F\x6E\x65\x72\x61\x20\x43\x6C\x61\x73\x73\x32\x20\x43\x41\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\x90\x17\x4A\x35\x9D\xCA\xF0\x0D\x96\xC7\x44\xFA\x16\x37\xFC\x48\xBD\xBD\x7F\x80\x2D\x35\x3B\xE1\x6F\xA8\x67\xA9\xBF\x03\x1C\x4D\x8C\x6F\x32\x47\xD5\x41\x68\xA4\x13\x04\xC1\x35\x0C\x9A\x84\x43\xFC\x5C\x1D\xFF\x89\xB3\xE8\x17\x18\xCD\x91\x5F\xFB\x89\xE3\xEA\xBF\x4E\x5D\x7C\x1B\x26\xD3\x75\x79\xED\xE6\x84\xE3\x57\xE5\xAD\x29\xC4\xF4\x3A\x28\xE7\xA5\x7B\x84\x36\x69\xB3\xFD\x5E\x76\xBD\xA3\x2D\x99\xD3\x90\x4E\x23\x28\x7D\x18\x63\xF1\x54\x3B\x26\x9D\x76\x5B\x97\x42\xB2\xFF\xAE\xF0\x4E\xEC\xDD\x39\x95\x4E\x83\x06\x7F\xE7\x49\x40\xC8\xC5\x01\xB2\x54\x5A\x66\x1D\x3D\xFC\xF9\xE9\x3C\x0A\x9E\x81\xB8\x70\xF0\x01\x8B\xE4\x23\x54\x7C\xC8\xAE\xF8\x90\x1E\x00\x96\x72\xD4\x54\xCF\x61\x23\xBC\xEA\xFB\x9D\x02\x95\xD1\xB6\xB9\x71\x3A\x69\x08\x3F\x0F\xB4\xE1\x42\xC7\x88\xF5\x3F\x98\xA8\xA7\xBA\x1C\xE0\x71\x71\xEF\x58\x57\x81\x50\x7A\x5C\x6B\x74\x46\x0E\x83\x03\x98\xC3\x8E\xA8\x6E\xF2\x76\x32\x6E\x27\x83\xC2\x73\xF3\xDC\x18\xE8\xB4\x93\xEA\x75\x44\x6B\x04\x60\x20\x71\x57\x87\x9D\xF3\xBE\xA0\x90\x23\x3D\x8A\x24\xE1\xDA\x21\xDB\xC3\x02\x03\x01\x00\x01\xA3\x33\x30\x31\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x11\x06\x03\x55\x1D\x0E\x04\x0A\x04\x08\x4A\xA0\xAA\x58\x84\xD3\x5E\x3C\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5A\xCE\x87\xF9\x16\x72\x15\x57\x4B\x1D\xD9\x9B\xE7\xA2\x26\x30\xEC\x93\x67\xDF\xD6\x2D\xD2\x34\xAF\xF7\x38\xA5\xCE\xAB\x16\xB9\xAB\x2F\x7C\x35\xCB\xAC\xD0\x0F\xB4\x4C\x2B\xFC\x80\xEF\x6B\x8C\x91\x5F\x36\x76\xF7\xDB\xB3\x1B\x19\xEA\xF4\xB2\x11\xFD\x61\x71\x44\xBF\x28\xB3\x3A\x1D\xBF\xB3\x43\xE8\x9F\xBF\xDC\x31\x08\x71\xB0\x9D\x8D\xD6\x34\x47\x32\x90\xC6\x65\x24\xF7\xA0\x4A\x7C\x04\x73\x8F\x39\x6F\x17\x8C\x72\xB5\xBD\x4B\xC8\x7A\xF8\x7B\x83\xC3\x28\x4E\x9C\x09\xEA\x67\x3F\xB2\x67\x04\x1B\xC3\x14\xDA\xF8\xE7\x49\x24\x91\xD0\x1D\x6A\xFA\x61\x39\xEF\x6B\xE7\x21\x75\x06\x07\xD8\x12\xB4\x21\x20\x70\x42\x71\x81\xDA\x3C\x9A\x36\xBE\xA6\x5B\x0D\x6A\x6C\x9A\x1F\x91\x7B\xF9\xF9\xEF\x42\xBA\x4E\x4E\x9E\xCC\x0C\x8D\x94\xDC\xD9\x45\x9C\x5E\xEC\x42\x50\x63\xAE\xF4\x5D\xC4\xB1\x12\xDC\xCA\x3B\xA8\x2E\x9D\x14\x5A\x05\x75\xB7\xEC\xD7\x63\xE2\xBA\x35\xB6\x04\x08\x91\xE8\xDA\x9D\x9C\xF6\x66\xB5\x18\xAC\x0A\xA6\x54\x26\x34\x33\xD2\x1B\xC1\xD4\x7F\x1A\x3A\x8E\x0B\xAA\x32\x6E\xDB\xFC\x4F\x25\x9F\xD9\x32\xC7\x96\x5A\x70\xAC\xDF\x4C", - ["Staat der Nederlanden Root CA"] = "\x30\x82\x03\xBA\x30\x82\x02\xA2\xA0\x03\x02\x01\x02\x02\x04\x00\x98\x96\x8A\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x55\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4C\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x13\x15\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x32\x31\x32\x31\x37\x30\x39\x32\x33\x34\x39\x5A\x17\x0D\x31\x35\x31\x32\x31\x36\x30\x39\x31\x35\x33\x38\x5A\x30\x55\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4C\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x13\x15\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\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\x98\xD2\xB5\x51\x11\x7A\x81\xA6\x14\x98\x71\x6D\xBE\xCC\xE7\x13\x1B\xD6\x27\x0E\x7A\xB3\x6A\x18\x1C\xB6\x61\x5A\xD5\x61\x09\xBF\xDE\x90\x13\xC7\x67\xEE\xDD\xF3\xDA\xC5\x0C\x12\x9E\x35\x55\x3E\x2C\x27\x88\x40\x6B\xF7\xDC\xDD\x22\x61\xF5\xC2\xC7\x0E\xF5\xF6\xD5\x76\x53\x4D\x8F\x8C\xBC\x18\x76\x37\x85\x9D\xE8\xCA\x49\xC7\xD2\x4F\x98\x13\x09\xA2\x3E\x22\x88\x9C\x7F\xD6\xF2\x10\x65\xB4\xEE\x5F\x18\xD5\x17\xE3\xF8\xC5\xFD\xE2\x9D\xA2\xEF\x53\x0E\x85\x77\xA2\x0F\xE1\x30\x47\xEE\x00\xE7\x33\x7D\x44\x67\x1A\x0B\x51\xE8\x8B\xA0\x9E\x50\x98\x68\x34\x52\x1F\x2E\x6D\x01\xF2\x60\x45\xF2\x31\xEB\xA9\x31\x68\x29\xBB\x7A\x41\x9E\xC6\x19\x7F\x94\xB4\x51\x39\x03\x7F\xB2\xDE\xA7\x32\x9B\xB4\x47\x8E\x6F\xB4\x4A\xAE\xE5\xAF\xB1\xDC\xB0\x1B\x61\xBC\x99\x72\xDE\xE4\x89\xB7\x7A\x26\x5D\xDA\x33\x49\x5B\x52\x9C\x0E\xF5\x8A\xAD\xC3\xB8\x3D\xE8\x06\x6A\xC2\xD5\x2A\x0B\x6C\x7B\x84\xBD\x56\x05\xCB\x86\x65\x92\xEC\x44\x2B\xB0\x8E\xB9\xDC\x70\x0B\x46\xDA\xAD\xBC\x63\x88\x39\xFA\xDB\x6A\xFE\x23\xFA\xBC\xE4\x48\xF4\x67\x2B\x6A\x11\x10\x21\x49\x02\x03\x01\x00\x01\xA3\x81\x91\x30\x81\x8E\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x4F\x06\x03\x55\x1D\x20\x04\x48\x30\x46\x30\x44\x06\x04\x55\x1D\x20\x00\x30\x3C\x30\x3A\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x2E\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x70\x6B\x69\x6F\x76\x65\x72\x68\x65\x69\x64\x2E\x6E\x6C\x2F\x70\x6F\x6C\x69\x63\x69\x65\x73\x2F\x72\x6F\x6F\x74\x2D\x70\x6F\x6C\x69\x63\x79\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xA8\x7D\xEB\xBC\x63\xA4\x74\x13\x74\x00\xEC\x96\xE0\xD3\x34\xC1\x2C\xBF\x6C\xF8\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x05\x84\x87\x55\x74\x36\x61\xC1\xBB\xD1\xD4\xC6\x15\xA8\x13\xB4\x9F\xA4\xFE\xBB\xEE\x15\xB4\x2F\x06\x0C\x29\xF2\xA8\x92\xA4\x61\x0D\xFC\xAB\x5C\x08\x5B\x51\x13\x2B\x4D\xC2\x2A\x61\xC8\xF8\x09\x58\xFC\x2D\x02\xB2\x39\x7D\x99\x66\x81\xBF\x6E\x5C\x95\x45\x20\x6C\xE6\x79\xA7\xD1\xD8\x1C\x29\xFC\xC2\x20\x27\x51\xC8\xF1\x7C\x5D\x34\x67\x69\x85\x11\x30\xC6\x00\xD2\xD7\xF3\xD3\x7C\xB6\xF0\x31\x57\x28\x12\x82\x73\xE9\x33\x2F\xA6\x55\xB4\x0B\x91\x94\x47\x9C\xFA\xBB\x7A\x42\x32\xE8\xAE\x7E\x2D\xC8\xBC\xAC\x14\xBF\xD9\x0F\xD9\x5B\xFC\xC1\xF9\x7A\x95\xE1\x7D\x7E\x96\xFC\x71\xB0\xC2\x4C\xC8\xDF\x45\x34\xC9\xCE\x0D\xF2\x9C\x64\x08\xD0\x3B\xC3\x29\xC5\xB2\xED\x90\x04\xC1\xB1\x29\x91\xC5\x30\x6F\xC1\xA9\x72\x33\xCC\xFE\x5D\x16\x17\x2C\x11\x69\xE7\x7E\xFE\xC5\x83\x08\xDF\xBC\xDC\x22\x3A\x2E\x20\x69\x23\x39\x56\x60\x67\x90\x8B\x2E\x76\x39\xFB\x11\x88\x97\xF6\x7C\xBD\x4B\xB8\x20\x16\x67\x05\x8D\xE2\x3B\xC1\x72\x3F\x94\x95\x37\xC7\x5D\xB9\x9E\xD8\x93\xA1\x17\x8F\xFF\x0C\x66\x15\xC1\x24\x7C\x32\x7C\x03\x1D\x3B\xA1\x58\x45\x32\x93", - ["TDC Internet Root CA"] = "\x30\x82\x04\x2B\x30\x82\x03\x13\xA0\x03\x02\x01\x02\x02\x04\x3A\xCC\xA5\x4C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x43\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4B\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x54\x44\x43\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x54\x44\x43\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x31\x30\x34\x30\x35\x31\x36\x33\x33\x31\x37\x5A\x17\x0D\x32\x31\x30\x34\x30\x35\x31\x37\x30\x33\x31\x37\x5A\x30\x43\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4B\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x54\x44\x43\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x54\x44\x43\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xC4\xB8\x40\xBC\x91\xD5\x63\x1F\xD7\x99\xA0\x8B\x0C\x40\x1E\x74\xB7\x48\x9D\x46\x8C\x02\xB2\xE0\x24\x5F\xF0\x19\x13\xA7\x37\x83\x6B\x5D\xC7\x8E\xF9\x84\x30\xCE\x1A\x3B\xFA\xFB\xCE\x8B\x6D\x23\xC6\xC3\x6E\x66\x9F\x89\xA5\xDF\xE0\x42\x50\x67\xFA\x1F\x6C\x1E\xF4\xD0\x05\xD6\xBF\xCA\xD6\x4E\xE4\x68\x60\x6C\x46\xAA\x1C\x5D\x63\xE1\x07\x86\x0E\x65\x00\xA7\x2E\xA6\x71\xC6\xBC\xB9\x81\xA8\x3A\x7D\x1A\xD2\xF9\xD1\xAC\x4B\xCB\xCE\x75\xAF\xDC\x7B\xFA\x81\x73\xD4\xFC\xBA\xBD\x41\x88\xD4\x74\xB3\xF9\x5E\x38\x3A\x3C\x43\xA8\xD2\x95\x4E\x77\x6D\x13\x0C\x9D\x8F\x78\x01\xB7\x5A\x20\x1F\x03\x37\x35\xE2\x2C\xDB\x4B\x2B\x2C\x78\xB9\x49\xDB\xC4\xD0\xC7\x9C\x9C\xE4\x8A\x20\x09\x21\x16\x56\x66\xFF\x05\xEC\x5B\xE3\xF0\xCF\xAB\x24\x24\x5E\xC3\x7F\x70\x7A\x12\xC4\xD2\xB5\x10\xA0\xB6\x21\xE1\x8D\x78\x69\x55\x44\x69\xF5\xCA\x96\x1C\x34\x85\x17\x25\x77\xE2\xF6\x2F\x27\x98\x78\xFD\x79\x06\x3A\xA2\xD6\x5A\x43\xC1\xFF\xEC\x04\x3B\xEE\x13\xEF\xD3\x58\x5A\xFF\x92\xEB\xEC\xAE\xDA\xF2\x37\x03\x47\x41\xB6\x97\xC9\x2D\x0A\x41\x22\xBB\xBB\xE6\xA7\x02\x03\x01\x00\x01\xA3\x82\x01\x25\x30\x82\x01\x21\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x65\x06\x03\x55\x1D\x1F\x04\x5E\x30\x5C\x30\x5A\xA0\x58\xA0\x56\xA4\x54\x30\x52\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4B\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x54\x44\x43\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x54\x44\x43\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x52\x6F\x6F\x74\x20\x43\x41\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x32\x30\x30\x31\x30\x34\x30\x35\x31\x36\x33\x33\x31\x37\x5A\x81\x0F\x32\x30\x32\x31\x30\x34\x30\x35\x31\x37\x30\x33\x31\x37\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x6C\x64\x01\xC7\xFD\x85\x6D\xAC\xC8\xDA\x9E\x50\x08\x85\x08\xB5\x3C\x56\xA8\x50\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x6C\x64\x01\xC7\xFD\x85\x6D\xAC\xC8\xDA\x9E\x50\x08\x85\x08\xB5\x3C\x56\xA8\x50\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x10\x30\x0E\x1B\x08\x56\x35\x2E\x30\x3A\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x4E\x43\xCC\xD1\xDD\x1D\x10\x1B\x06\x7F\xB7\xA4\xFA\xD3\xD9\x4D\xFB\x23\x9F\x23\x54\x5B\xE6\x8B\x2F\x04\x28\x8B\xB5\x27\x6D\x89\xA1\xEC\x98\x69\xDC\xE7\x8D\x26\x83\x05\x79\x74\xEC\xB4\xB9\xA3\x97\xC1\x35\x00\xFD\x15\xDA\x39\x81\x3A\x95\x31\x90\xDE\x97\xE9\x86\xA8\x99\x77\x0C\xE5\x5A\xA0\x84\xFF\x12\x16\xAC\x6E\xB8\x8D\xC3\x7B\x92\xC2\xAC\x2E\xD0\x7D\x28\xEC\xB6\xF3\x60\x38\x69\x6F\x3E\xD8\x04\x55\x3E\x9E\xCC\x55\xD2\xBA\xFE\xBB\x47\x04\xD7\x0A\xD9\x16\x0A\x34\x29\xF5\x58\x13\xD5\x4F\xCF\x8F\x56\x4B\xB3\x1E\xEE\xD3\x98\x79\xDA\x08\x1E\x0C\x6F\xB8\xF8\x16\x27\xEF\xC2\x6F\x3D\xF6\xA3\x4B\x3E\x0E\xE4\x6D\x6C\xDB\x3B\x41\x12\x9B\xBD\x0D\x47\x23\x7F\x3C\x4A\xD0\xAF\xC0\xAF\xF6\xEF\x1B\xB5\x15\xC4\xEB\x83\xC4\x09\x5F\x74\x8B\xD9\x11\xFB\xC2\x56\xB1\x3C\xF8\x70\xCA\x34\x8D\x43\x40\x13\x8C\xFD\x99\x03\x54\x79\xC6\x2E\xEA\x86\xA1\xF6\x3A\xD4\x09\xBC\xF4\xBC\x66\xCC\x3D\x58\xD0\x57\x49\x0A\xEE\x25\xE2\x41\xEE\x13\xF9\x9B\x38\x34\xD1\x00\xF5\x7E\xE7\x94\x1D\xFC\x69\x03\x62\xB8\x99\x05\x05\x3D\x6B\x78\x12\xBD\xB0\x6F\x65", - ["TDC OCES Root CA"] = "\x30\x82\x05\x19\x30\x82\x04\x01\xA0\x03\x02\x01\x02\x02\x04\x3E\x48\xBD\xC4\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x31\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4B\x31\x0C\x30\x0A\x06\x03\x55\x04\x0A\x13\x03\x54\x44\x43\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0B\x54\x44\x43\x20\x4F\x43\x45\x53\x20\x43\x41\x30\x1E\x17\x0D\x30\x33\x30\x32\x31\x31\x30\x38\x33\x39\x33\x30\x5A\x17\x0D\x33\x37\x30\x32\x31\x31\x30\x39\x30\x39\x33\x30\x5A\x30\x31\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4B\x31\x0C\x30\x0A\x06\x03\x55\x04\x0A\x13\x03\x54\x44\x43\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0B\x54\x44\x43\x20\x4F\x43\x45\x53\x20\x43\x41\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\x62\xF6\x61\x20\xB2\xCF\xC0\xC6\x85\xD7\xE3\x79\xE6\xCC\xED\xF2\x39\x92\xA4\x97\x2E\x64\xA3\x84\x5B\x87\x9C\x4C\xFD\xA4\xF3\xC4\x5F\x21\xBD\x56\x10\xEB\xDB\x2E\x61\xEC\x93\x69\xE3\xA3\xCC\xBD\x99\xC3\x05\xFC\x06\xB8\xCA\x36\x1C\xFE\x90\x8E\x49\x4C\xC4\x56\x9A\x2F\x56\xBC\xCF\x7B\x0C\xF1\x6F\x47\xA6\x0D\x43\x4D\xE2\xE9\x1D\x39\x34\xCD\x8D\x2C\xD9\x12\x98\xF9\xE3\xE1\xC1\x4A\x7C\x86\x38\xC4\xA9\xC4\x61\x88\xD2\x5E\xAF\x1A\x26\x4D\xD5\xE4\xA0\x22\x47\x84\xD9\x64\xB7\x19\x96\xFC\xEC\x19\xE4\xB2\x97\x26\x4E\x4A\x4C\xCB\x8F\x24\x8B\x54\x18\x1C\x48\x61\x7B\xD5\x88\x68\xDA\x5D\xB5\xEA\xCD\x1A\x30\xC1\x80\x83\x76\x50\xAA\x4F\xD1\xD4\xDD\x38\xF0\xEF\x16\xF4\xE1\x0C\x50\x06\xBF\xEA\xFB\x7A\x49\xA1\x28\x2B\x1C\xF6\xFC\x15\x32\xA3\x74\x6A\x8F\xA9\xC3\x62\x29\x71\x31\xE5\x3B\xA4\x60\x17\x5E\x74\xE6\xDA\x13\xED\xE9\x1F\x1F\x1B\xD1\xB2\x68\x73\xC6\x10\x34\x75\x46\x10\x10\xE3\x90\x00\x76\x40\xCB\x8B\xB7\x43\x09\x21\xFF\xAB\x4E\x93\xC6\x58\xE9\xA5\x82\xDB\x77\xC4\x3A\x99\xB1\x72\x95\x49\x04\xF0\xB7\x2B\xFA\x7B\x59\x8E\xDD\x02\x03\x01\x00\x01\xA3\x82\x02\x37\x30\x82\x02\x33\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x81\xEC\x06\x03\x55\x1D\x20\x04\x81\xE4\x30\x81\xE1\x30\x81\xDE\x06\x08\x2A\x81\x50\x81\x29\x01\x01\x01\x30\x81\xD1\x30\x2F\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x65\x72\x74\x69\x66\x69\x6B\x61\x74\x2E\x64\x6B\x2F\x72\x65\x70\x6F\x73\x69\x74\x6F\x72\x79\x30\x81\x9D\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x81\x90\x30\x0A\x16\x03\x54\x44\x43\x30\x03\x02\x01\x01\x1A\x81\x81\x43\x65\x72\x74\x69\x66\x69\x6B\x61\x74\x65\x72\x20\x66\x72\x61\x20\x64\x65\x6E\x6E\x65\x20\x43\x41\x20\x75\x64\x73\x74\x65\x64\x65\x73\x20\x75\x6E\x64\x65\x72\x20\x4F\x49\x44\x20\x31\x2E\x32\x2E\x32\x30\x38\x2E\x31\x36\x39\x2E\x31\x2E\x31\x2E\x31\x2E\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x73\x20\x66\x72\x6F\x6D\x20\x74\x68\x69\x73\x20\x43\x41\x20\x61\x72\x65\x20\x69\x73\x73\x75\x65\x64\x20\x75\x6E\x64\x65\x72\x20\x4F\x49\x44\x20\x31\x2E\x32\x2E\x32\x30\x38\x2E\x31\x36\x39\x2E\x31\x2E\x31\x2E\x31\x2E\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x81\x81\x06\x03\x55\x1D\x1F\x04\x7A\x30\x78\x30\x48\xA0\x46\xA0\x44\xA4\x42\x30\x40\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4B\x31\x0C\x30\x0A\x06\x03\x55\x04\x0A\x13\x03\x54\x44\x43\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0B\x54\x44\x43\x20\x4F\x43\x45\x53\x20\x43\x41\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x2C\xA0\x2A\xA0\x28\x86\x26\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x6F\x63\x65\x73\x2E\x63\x65\x72\x74\x69\x66\x69\x6B\x61\x74\x2E\x64\x6B\x2F\x6F\x63\x65\x73\x2E\x63\x72\x6C\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x32\x30\x30\x33\x30\x32\x31\x31\x30\x38\x33\x39\x33\x30\x5A\x81\x0F\x32\x30\x33\x37\x30\x32\x31\x31\x30\x39\x30\x39\x33\x30\x5A\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x60\xB5\x85\xEC\x56\x64\x7E\x12\x19\x27\x67\x1D\x50\x15\x4B\x73\xAE\x3B\xF9\x12\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x60\xB5\x85\xEC\x56\x64\x7E\x12\x19\x27\x67\x1D\x50\x15\x4B\x73\xAE\x3B\xF9\x12\x30\x1D\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x10\x30\x0E\x1B\x08\x56\x36\x2E\x30\x3A\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x0A\xBA\x26\x26\x46\xD3\x73\xA8\x09\xF3\x6B\x0B\x30\x99\xFD\x8A\xE1\x57\x7A\x11\xD3\xB8\x94\xD7\x09\x10\x6E\xA3\xB1\x38\x03\xD1\xB6\xF2\x43\x41\x29\x62\xA7\x72\xD8\xFB\x7C\x05\xE6\x31\x70\x27\x54\x18\x4E\x8A\x7C\x4E\xE5\xD1\xCA\x8C\x78\x88\xCF\x1B\xD3\x90\x8B\xE6\x23\xF8\x0B\x0E\x33\x43\x7D\x9C\xE2\x0A\x19\x8F\xC9\x01\x3E\x74\x5D\x74\xC9\x8B\x1C\x03\xE5\x18\xC8\x01\x4C\x3F\xCB\x97\x05\x5D\x98\x71\xA6\x98\x6F\xB6\x7C\xBD\x37\x7F\xBE\xE1\x93\x25\x6D\x6F\xF0\x0A\xAD\x17\x18\xE1\x03\xBC\x07\x29\xC8\xAD\x26\xE8\xF8\x61\xF0\xFD\x21\x09\x7E\x9A\x8E\xA9\x68\x7D\x48\x62\x72\xBD\x00\xEA\x01\x99\xB8\x06\x82\x51\x81\x4E\xF1\xF5\xB4\x91\x54\xB9\x23\x7A\x00\x9A\x9F\x5D\x8D\xE0\x3C\x64\xB9\x1A\x12\x92\x2A\xC7\x82\x44\x72\x39\xDC\xE2\x3C\xC6\xD8\x55\xF5\x15\x4E\xC8\x05\x0E\xDB\xC6\xD0\x62\xA6\xEC\x15\xB4\xB5\x02\x82\xDB\xAC\x8C\xA2\x81\xF0\x9B\x99\x31\xF5\x20\x20\xA8\x88\x61\x0A\x07\x9F\x94\xFC\xD0\xD7\x1B\xCC\x2E\x17\xF3\x04\x27\x76\x67\xEB\x54\x83\xFD\xA4\x90\x7E\x06\x3D\x04\xA3\x43\x2D\xDA\xFC\x0B\x62\xEA\x2F\x5F\x62\x53", - ["UTN DATACorp SGC Root CA"] = "\x30\x82\x04\x5E\x30\x82\x03\x46\xA0\x03\x02\x01\x02\x02\x10\x44\xBE\x0C\x8B\x50\x00\x21\xB4\x11\xD3\x2A\x68\x06\xA9\xAD\x69\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x93\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0E\x53\x61\x6C\x74\x20\x4C\x61\x6B\x65\x20\x43\x69\x74\x79\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x0B\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x55\x54\x4E\x20\x2D\x20\x44\x41\x54\x41\x43\x6F\x72\x70\x20\x53\x47\x43\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x34\x31\x38\x35\x37\x32\x31\x5A\x17\x0D\x31\x39\x30\x36\x32\x34\x31\x39\x30\x36\x33\x30\x5A\x30\x81\x93\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0E\x53\x61\x6C\x74\x20\x4C\x61\x6B\x65\x20\x43\x69\x74\x79\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x0B\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x55\x54\x4E\x20\x2D\x20\x44\x41\x54\x41\x43\x6F\x72\x70\x20\x53\x47\x43\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\xDF\xEE\x58\x10\xA2\x2B\x6E\x55\xC4\x8E\xBF\x2E\x46\x09\xE7\xE0\x08\x0F\x2E\x2B\x7A\x13\x94\x1B\xBD\xF6\xB6\x80\x8E\x65\x05\x93\x00\x1E\xBC\xAF\xE2\x0F\x8E\x19\x0D\x12\x47\xEC\xAC\xAD\xA3\xFA\x2E\x70\xF8\xDE\x6E\xFB\x56\x42\x15\x9E\x2E\x5C\xEF\x23\xDE\x21\xB9\x05\x76\x27\x19\x0F\x4F\xD6\xC3\x9C\xB4\xBE\x94\x19\x63\xF2\xA6\x11\x0A\xEB\x53\x48\x9C\xBE\xF2\x29\x3B\x16\xE8\x1A\xA0\x4C\xA6\xC9\xF4\x18\x59\x68\xC0\x70\xF2\x53\x00\xC0\x5E\x50\x82\xA5\x56\x6F\x36\xF9\x4A\xE0\x44\x86\xA0\x4D\x4E\xD6\x47\x6E\x49\x4A\xCB\x67\xD7\xA6\xC4\x05\xB9\x8E\x1E\xF4\xFC\xFF\xCD\xE7\x36\xE0\x9C\x05\x6C\xB2\x33\x22\x15\xD0\xB4\xE0\xCC\x17\xC0\xB2\xC0\xF4\xFE\x32\x3F\x29\x2A\x95\x7B\xD8\xF2\xA7\x4E\x0F\x54\x7C\xA1\x0D\x80\xB3\x09\x03\xC1\xFF\x5C\xDD\x5E\x9A\x3E\xBC\xAE\xBC\x47\x8A\x6A\xAE\x71\xCA\x1F\xB1\x2A\xB8\x5F\x42\x05\x0B\xEC\x46\x30\xD1\x72\x0B\xCA\xE9\x56\x6D\xF5\xEF\xDF\x78\xBE\x61\xBA\xB2\xA5\xAE\x04\x4C\xBC\xA8\xAC\x69\x15\x97\xBD\xEF\xEB\xB4\x8C\xBF\x35\xF8\xD4\xC3\xD1\x28\x0E\x5C\x3A\x9F\x70\x18\x33\x20\x77\xC4\xA2\xAF\x02\x03\x01\x00\x01\xA3\x81\xAB\x30\x81\xA8\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\xC6\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x53\x32\xD1\xB3\xCF\x7F\xFA\xE0\xF1\xA0\x5D\x85\x4E\x92\xD2\x9E\x45\x1D\xB4\x4F\x30\x3D\x06\x03\x55\x1D\x1F\x04\x36\x30\x34\x30\x32\xA0\x30\xA0\x2E\x86\x2C\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x2F\x55\x54\x4E\x2D\x44\x41\x54\x41\x43\x6F\x72\x70\x53\x47\x43\x2E\x63\x72\x6C\x30\x2A\x06\x03\x55\x1D\x25\x04\x23\x30\x21\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x01\x06\x0A\x2B\x06\x01\x04\x01\x82\x37\x0A\x03\x03\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x04\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x27\x35\x97\x00\x8A\x8B\x28\xBD\xC6\x33\x30\x1E\x29\xFC\xE2\xF7\xD5\x98\xD4\x40\xBB\x60\xCA\xBF\xAB\x17\x2C\x09\x36\x7F\x50\xFA\x41\xDC\xAE\x96\x3A\x0A\x23\x3E\x89\x59\xC9\xA3\x07\xED\x1B\x37\xAD\xFC\x7C\xBE\x51\x49\x5A\xDE\x3A\x0A\x54\x08\x16\x45\xC2\x99\xB1\x87\xCD\x8C\x68\xE0\x69\x03\xE9\xC4\x4E\x98\xB2\x3B\x8C\x16\xB3\x0E\xA0\x0C\x98\x50\x9B\x93\xA9\x70\x09\xC8\x2C\xA3\x8F\xDF\x02\xE4\xE0\x71\x3A\xF1\xB4\x23\x72\xA0\xAA\x01\xDF\xDF\x98\x3E\x14\x50\xA0\x31\x26\xBD\x28\xE9\x5A\x30\x26\x75\xF9\x7B\x60\x1C\x8D\xF3\xCD\x50\x26\x6D\x04\x27\x9A\xDF\xD5\x0D\x45\x47\x29\x6B\x2C\xE6\x76\xD9\xA9\x29\x7D\x32\xDD\xC9\x36\x3C\xBD\xAE\x35\xF1\x11\x9E\x1D\xBB\x90\x3F\x12\x47\x4E\x8E\xD7\x7E\x0F\x62\x73\x1D\x52\x26\x38\x1C\x18\x49\xFD\x30\x74\x9A\xC4\xE5\x22\x2F\xD8\xC0\x8D\xED\x91\x7A\x4C\x00\x8F\x72\x7F\x5D\xDA\xDD\x1B\x8B\x45\x6B\xE7\xDD\x69\x97\xA8\xC5\x56\x4C\x0F\x0C\xF6\x9F\x7A\x91\x37\xF6\x97\x82\xE0\xDD\x71\x69\xFF\x76\x3F\x60\x4D\x3C\xCF\xF7\x99\xF9\xC6\x57\xF4\xC9\x55\x39\x78\xBA\x2C\x79\xC9\xA6\x88\x2B\xF4\x08", - ["UTN USERFirst Hardware Root CA"] = "\x30\x82\x04\x74\x30\x82\x03\x5C\xA0\x03\x02\x01\x02\x02\x10\x44\xBE\x0C\x8B\x50\x00\x24\xB4\x11\xD3\x36\x2A\xFE\x65\x0A\xFD\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x97\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0E\x53\x61\x6C\x74\x20\x4C\x61\x6B\x65\x20\x43\x69\x74\x79\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x0B\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x55\x54\x4E\x2D\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2D\x48\x61\x72\x64\x77\x61\x72\x65\x30\x1E\x17\x0D\x39\x39\x30\x37\x30\x39\x31\x38\x31\x30\x34\x32\x5A\x17\x0D\x31\x39\x30\x37\x30\x39\x31\x38\x31\x39\x32\x32\x5A\x30\x81\x97\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0E\x53\x61\x6C\x74\x20\x4C\x61\x6B\x65\x20\x43\x69\x74\x79\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x0B\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x55\x54\x4E\x2D\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2D\x48\x61\x72\x64\x77\x61\x72\x65\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\xB1\xF7\xC3\x38\x3F\xB4\xA8\x7F\xCF\x39\x82\x51\x67\xD0\x6D\x9F\xD2\xFF\x58\xF3\xE7\x9F\x2B\xEC\x0D\x89\x54\x99\xB9\x38\x99\x16\xF7\xE0\x21\x79\x48\xC2\xBB\x61\x74\x12\x96\x1D\x3C\x6A\x72\xD5\x3C\x10\x67\x3A\x39\xED\x2B\x13\xCD\x66\xEB\x95\x09\x33\xA4\x6C\x97\xB1\xE8\xC6\xEC\xC1\x75\x79\x9C\x46\x5E\x8D\xAB\xD0\x6A\xFD\xB9\x2A\x55\x17\x10\x54\xB3\x19\xF0\x9A\xF6\xF1\xB1\x5D\xB6\xA7\x6D\xFB\xE0\x71\x17\x6B\xA2\x88\xFB\x00\xDF\xFE\x1A\x31\x77\x0C\x9A\x01\x7A\xB1\x32\xE3\x2B\x01\x07\x38\x6E\xC3\xA5\x5E\x23\xBC\x45\x9B\x7B\x50\xC1\xC9\x30\x8F\xDB\xE5\x2B\x7A\xD3\x5B\xFB\x33\x40\x1E\xA0\xD5\x98\x17\xBC\x8B\x87\xC3\x89\xD3\x5D\xA0\x8E\xB2\xAA\xAA\xF6\x8E\x69\x88\x06\xC5\xFA\x89\x21\xF3\x08\x9D\x69\x2E\x09\x33\x9B\x29\x0D\x46\x0F\x8C\xCC\x49\x34\xB0\x69\x51\xBD\xF9\x06\xCD\x68\xAD\x66\x4C\xBC\x3E\xAC\x61\xBD\x0A\x88\x0E\xC8\xDF\x3D\xEE\x7C\x04\x4C\x9D\x0A\x5E\x6B\x91\xD6\xEE\xC7\xED\x28\x8D\xAB\x4D\x87\x89\x73\xD0\x6E\xA4\xD0\x1E\x16\x8B\x14\xE1\x76\x44\x03\x7F\x63\xAC\xE4\xCD\x49\x9C\xC5\x92\xF4\xAB\x32\xA1\x48\x5B\x02\x03\x01\x00\x01\xA3\x81\xB9\x30\x81\xB6\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\xC6\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xA1\x72\x5F\x26\x1B\x28\x98\x43\x95\x5D\x07\x37\xD5\x85\x96\x9D\x4B\xD2\xC3\x45\x30\x44\x06\x03\x55\x1D\x1F\x04\x3D\x30\x3B\x30\x39\xA0\x37\xA0\x35\x86\x33\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x2F\x55\x54\x4E\x2D\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2D\x48\x61\x72\x64\x77\x61\x72\x65\x2E\x63\x72\x6C\x30\x31\x06\x03\x55\x1D\x25\x04\x2A\x30\x28\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x05\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x06\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x07\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x47\x19\x0F\xDE\x74\xC6\x99\x97\xAF\xFC\xAD\x28\x5E\x75\x8E\xEB\x2D\x67\xEE\x4E\x7B\x2B\xD7\x0C\xFF\xF6\xDE\xCB\x55\xA2\x0A\xE1\x4C\x54\x65\x93\x60\x6B\x9F\x12\x9C\xAD\x5E\x83\x2C\xEB\x5A\xAE\xC0\xE4\x2D\xF4\x00\x63\x1D\xB8\xC0\x6C\xF2\xCF\x49\xBB\x4D\x93\x6F\x06\xA6\x0A\x22\xB2\x49\x62\x08\x4E\xFF\xC8\xC8\x14\xB2\x88\x16\x5D\xE7\x01\xE4\x12\x95\xE5\x45\x34\xB3\x8B\x69\xBD\xCF\xB4\x85\x8F\x75\x51\x9E\x7D\x3A\x38\x3A\x14\x48\x12\xC6\xFB\xA7\x3B\x1A\x8D\x0D\x82\x40\x07\xE8\x04\x08\x90\xA1\x89\xCB\x19\x50\xDF\xCA\x1C\x01\xBC\x1D\x04\x19\x7B\x10\x76\x97\x3B\xEE\x90\x90\xCA\xC4\x0E\x1F\x16\x6E\x75\xEF\x33\xF8\xD3\x6F\x5B\x1E\x96\xE3\xE0\x74\x77\x74\x7B\x8A\xA2\x6E\x2D\xDD\x76\xD6\x39\x30\x82\xF0\xAB\x9C\x52\xF2\x2A\xC7\xAF\x49\x5E\x7E\xC7\x68\xE5\x82\x81\xC8\x6A\x27\xF9\x27\x88\x2A\xD5\x58\x50\x95\x1F\xF0\x3B\x1C\x57\xBB\x7D\x14\x39\x62\x2B\x9A\xC9\x94\x92\x2A\xA3\x22\x0C\xFF\x89\x26\x7D\x5F\x23\x2B\x47\xD7\x15\x1D\xA9\x6A\x9E\x51\x0D\x2A\x51\x9E\x81\xF9\xD4\x3B\x5E\x70\x12\x7F\x10\x32\x9C\x1E\xBB\x9D\xF8\x66\xA8", - ["Camerfirma Chambers of Commerce Root"] = "\x30\x82\x04\xBD\x30\x82\x03\xA5\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x41\x20\x43\x49\x46\x20\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x13\x1A\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x33\x30\x39\x33\x30\x31\x36\x31\x33\x34\x33\x5A\x17\x0D\x33\x37\x30\x39\x33\x30\x31\x36\x31\x33\x34\x34\x5A\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x41\x20\x43\x49\x46\x20\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x13\x1A\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x30\x82\x01\x20\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0D\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xB7\x36\x55\xE5\xA5\x5D\x18\x30\xE0\xDA\x89\x54\x91\xFC\xC8\xC7\x52\xF8\x2F\x50\xD9\xEF\xB1\x75\x73\x65\x47\x7D\x1B\x5B\xBA\x75\xC5\xFC\xA1\x88\x24\xFA\x2F\xED\xCA\x08\x4A\x39\x54\xC4\x51\x7A\xB5\xDA\x60\xEA\x38\x3C\x81\xB2\xCB\xF1\xBB\xD9\x91\x23\x3F\x48\x01\x70\x75\xA9\x05\x2A\xAD\x1F\x71\xF3\xC9\x54\x3D\x1D\x06\x6A\x40\x3E\xB3\x0C\x85\xEE\x5C\x1B\x79\xC2\x62\xC4\xB8\x36\x8E\x35\x5D\x01\x0C\x23\x04\x47\x35\xAA\x9B\x60\x4E\xA0\x66\x3D\xCB\x26\x0A\x9C\x40\xA1\xF4\x5D\x98\xBF\x71\xAB\xA5\x00\x68\x2A\xED\x83\x7A\x0F\xA2\x14\xB5\xD4\x22\xB3\x80\xB0\x3C\x0C\x5A\x51\x69\x2D\x58\x18\x8F\xED\x99\x9E\xF1\xAE\xE2\x95\xE6\xF6\x47\xA8\xD6\x0C\x0F\xB0\x58\x58\xDB\xC3\x66\x37\x9E\x9B\x91\x54\x33\x37\xD2\x94\x1C\x6A\x48\xC9\xC9\xF2\xA5\xDA\xA5\x0C\x23\xF7\x23\x0E\x9C\x32\x55\x5E\x71\x9C\x84\x05\x51\x9A\x2D\xFD\xE6\x4E\x2A\x34\x5A\xDE\xCA\x40\x37\x67\x0C\x54\x21\x55\x77\xDA\x0A\x0C\xCC\x97\xAE\x80\xDC\x94\x36\x4A\xF4\x3E\xCE\x36\x13\x1E\x53\xE4\xAC\x4E\x3A\x05\xEC\xDB\xAE\x72\x9C\x38\x8B\xD0\x39\x3B\x89\x0A\x3E\x77\xFE\x75\x02\x01\x03\xA3\x82\x01\x44\x30\x82\x01\x40\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x0C\x30\x3C\x06\x03\x55\x1D\x1F\x04\x35\x30\x33\x30\x31\xA0\x2F\xA0\x2D\x86\x2B\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x2F\x63\x68\x61\x6D\x62\x65\x72\x73\x72\x6F\x6F\x74\x2E\x63\x72\x6C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE3\x94\xF5\xB1\x4D\xE9\xDB\xA1\x29\x5B\x57\x8B\x4D\x76\x06\x76\xE1\xD1\xA2\x8A\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x27\x06\x03\x55\x1D\x11\x04\x20\x30\x1E\x81\x1C\x63\x68\x61\x6D\x62\x65\x72\x73\x72\x6F\x6F\x74\x40\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x30\x27\x06\x03\x55\x1D\x12\x04\x20\x30\x1E\x81\x1C\x63\x68\x61\x6D\x62\x65\x72\x73\x72\x6F\x6F\x74\x40\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x30\x58\x06\x03\x55\x1D\x20\x04\x51\x30\x4F\x30\x4D\x06\x0B\x2B\x06\x01\x04\x01\x81\x87\x2E\x0A\x03\x01\x30\x3E\x30\x3C\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x30\x68\x74\x74\x70\x3A\x2F\x2F\x63\x70\x73\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x2F\x63\x70\x73\x2F\x63\x68\x61\x6D\x62\x65\x72\x73\x72\x6F\x6F\x74\x2E\x68\x74\x6D\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x0C\x41\x97\xC2\x1A\x86\xC0\x22\x7C\x9F\xFB\x90\xF3\x1A\xD1\x03\xB1\xEF\x13\xF9\x21\x5F\x04\x9C\xDA\xC9\xA5\x8D\x27\x6C\x96\x87\x91\xBE\x41\x90\x01\x72\x93\xE7\x1E\x7D\x5F\xF6\x89\xC6\x5D\xA7\x40\x09\x3D\xAC\x49\x45\x45\xDC\x2E\x8D\x30\x68\xB2\x09\xBA\xFB\xC3\x2F\xCC\xBA\x0B\xDF\x3F\x77\x7B\x46\x7D\x3A\x12\x24\x8E\x96\x8F\x3C\x05\x0A\x6F\xD2\x94\x28\x1D\x6D\x0C\xC0\x2E\x88\x22\xD5\xD8\xCF\x1D\x13\xC7\xF0\x48\xD7\xD7\x05\xA7\xCF\xC7\x47\x9E\x3B\x3C\x34\xC8\x80\x4F\xD4\x14\xBB\xFC\x0D\x50\xF7\xFA\xB3\xEC\x42\x5F\xA9\xDD\x6D\xC8\xF4\x75\xCF\x7B\xC1\x72\x26\xB1\x01\x1C\x5C\x2C\xFD\x7A\x4E\xB4\x01\xC5\x05\x57\xB9\xE7\x3C\xAA\x05\xD9\x88\xE9\x07\x46\x41\xCE\xEF\x41\x81\xAE\x58\xDF\x83\xA2\xAE\xCA\xD7\x77\x1F\xE7\x00\x3C\x9D\x6F\x8E\xE4\x32\x09\x1D\x4D\x78\x34\x78\x34\x3C\x94\x9B\x26\xED\x4F\x71\xC6\x19\x7A\xBD\x20\x22\x48\x5A\xFE\x4B\x7D\x03\xB7\xE7\x58\xBE\xC6\x32\x4E\x74\x1E\x68\xDD\xA8\x68\x5B\xB3\x3E\xEE\x62\x7D\xD9\x80\xE8\x0A\x75\x7A\xB7\xEE\xB4\x65\x9A\x21\x90\xE0\xAA\xD0\x98\xBC\x38\xB5\x73\x3C\x8B\xF8\xDC", - ["Camerfirma Global Chambersign Root"] = "\x30\x82\x04\xC5\x30\x82\x03\xAD\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x41\x20\x43\x49\x46\x20\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x13\x1A\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x47\x6C\x6F\x62\x61\x6C\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x33\x30\x39\x33\x30\x31\x36\x31\x34\x31\x38\x5A\x17\x0D\x33\x37\x30\x39\x33\x30\x31\x36\x31\x34\x31\x38\x5A\x30\x7D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x41\x20\x43\x49\x46\x20\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x13\x1A\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x47\x6C\x6F\x62\x61\x6C\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x20\x52\x6F\x6F\x74\x30\x82\x01\x20\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0D\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xA2\x70\xA2\xD0\x9F\x42\xAE\x5B\x17\xC7\xD8\x7D\xCF\x14\x83\xFC\x4F\xC9\xA1\xB7\x13\xAF\x8A\xD7\x9E\x3E\x04\x0A\x92\x8B\x60\x56\xFA\xB4\x32\x2F\x88\x4D\xA1\x60\x08\xF4\xB7\x09\x4E\xA0\x49\x2F\x49\xD6\xD3\xDF\x9D\x97\x5A\x9F\x94\x04\x70\xEC\x3F\x59\xD9\xB7\xCC\x66\x8B\x98\x52\x28\x09\x02\xDF\xC5\x2F\x84\x8D\x7A\x97\x77\xBF\xEC\x40\x9D\x25\x72\xAB\xB5\x3F\x32\x98\xFB\xB7\xB7\xFC\x72\x84\xE5\x35\x87\xF9\x55\xFA\xA3\x1F\x0E\x6F\x2E\x28\xDD\x69\xA0\xD9\x42\x10\xC6\xF8\xB5\x44\xC2\xD0\x43\x7F\xDB\xBC\xE4\xA2\x3C\x6A\x55\x78\x0A\x77\xA9\xD8\xEA\x19\x32\xB7\x2F\xFE\x5C\x3F\x1B\xEE\xB1\x98\xEC\xCA\xAD\x7A\x69\x45\xE3\x96\x0F\x55\xF6\xE6\xED\x75\xEA\x65\xE8\x32\x56\x93\x46\x89\xA8\x25\x8A\x65\x06\xEE\x6B\xBF\x79\x07\xD0\xF1\xB7\xAF\xED\x2C\x4D\x92\xBB\xC0\xA8\x5F\xA7\x67\x7D\x04\xF2\x15\x08\x70\xAC\x92\xD6\x7D\x04\xD2\x33\xFB\x4C\xB6\x0B\x0B\xFB\x1A\xC9\xC4\x8D\x03\xA9\x7E\x5C\xF2\x50\xAB\x12\xA5\xA1\xCF\x48\x50\xA5\xEF\xD2\xC8\x1A\x13\xFA\xB0\x7F\xB1\x82\x1C\x77\x6A\x0F\x5F\xDC\x0B\x95\x8F\xEF\x43\x7E\xE6\x45\x09\x25\x02\x01\x03\xA3\x82\x01\x50\x30\x82\x01\x4C\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x0C\x30\x3F\x06\x03\x55\x1D\x1F\x04\x38\x30\x36\x30\x34\xA0\x32\xA0\x30\x86\x2E\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x2F\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x72\x6F\x6F\x74\x2E\x63\x72\x6C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x43\x9C\x36\x9F\xB0\x9E\x30\x4D\xC6\xCE\x5F\xAD\x10\xAB\xE5\x03\xA5\xFA\xA9\x14\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x2A\x06\x03\x55\x1D\x11\x04\x23\x30\x21\x81\x1F\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x72\x6F\x6F\x74\x40\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x30\x2A\x06\x03\x55\x1D\x12\x04\x23\x30\x21\x81\x1F\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x72\x6F\x6F\x74\x40\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x30\x5B\x06\x03\x55\x1D\x20\x04\x54\x30\x52\x30\x50\x06\x0B\x2B\x06\x01\x04\x01\x81\x87\x2E\x0A\x01\x01\x30\x41\x30\x3F\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x33\x68\x74\x74\x70\x3A\x2F\x2F\x63\x70\x73\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x2F\x63\x70\x73\x2F\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x72\x6F\x6F\x74\x2E\x68\x74\x6D\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3C\x3B\x70\x91\xF9\x04\x54\x27\x91\xE1\xED\xED\xFE\x68\x7F\x61\x5D\xE5\x41\x65\x4F\x32\xF1\x18\x05\x94\x6A\x1C\xDE\x1F\x70\xDB\x3E\x7B\x32\x02\x34\xB5\x0C\x6C\xA1\x8A\x7C\xA5\xF4\x8F\xFF\xD4\xD8\xAD\x17\xD5\x2D\x04\xD1\x3F\x58\x80\xE2\x81\x59\x88\xBE\xC0\xE3\x46\x93\x24\xFE\x90\xBD\x26\xA2\x30\x2D\xE8\x97\x26\x57\x35\x89\x74\x96\x18\xF6\x15\xE2\xAF\x24\x19\x56\x02\x02\xB2\xBA\x0F\x14\xEA\xC6\x8A\x66\xC1\x86\x45\x55\x8B\xBE\x92\xBE\x9C\xA4\x04\xC7\x49\x3C\x9E\xE8\x29\x7A\x89\xD7\xFE\xAF\xFF\x68\xF5\xA5\x17\x90\xBD\xAC\x99\xCC\xA5\x86\x57\x09\x67\x46\xDB\xD6\x16\xC2\x46\xF1\xE4\xA9\x50\xF5\x8F\xD1\x92\x15\xD3\x5F\x3E\xC6\x00\x49\x3A\x6E\x58\xB2\xD1\xD1\x27\x0D\x25\xC8\x32\xF8\x20\x11\xCD\x7D\x32\x33\x48\x94\x54\x4C\xDD\xDC\x79\xC4\x30\x9F\xEB\x8E\xB8\x55\xB5\xD7\x88\x5C\xC5\x6A\x24\x3D\xB2\xD3\x05\x03\x51\xC6\x07\xEF\xCC\x14\x72\x74\x3D\x6E\x72\xCE\x18\x28\x8C\x4A\xA0\x77\xE5\x09\x2B\x45\x44\x47\xAC\xB7\x67\x7F\x01\x8A\x05\x5A\x93\xBE\xA1\xC1\xFF\xF8\xE7\x0E\x67\xA4\x47\x49\x76\x5D\x75\x90\x1A\xF5\x26\x8F\xF0", - ["NetLock Notary (Class A) Root"] = "\x30\x82\x06\x7D\x30\x82\x05\x65\xA0\x03\x02\x01\x02\x02\x02\x01\x03\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\xAF\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x48\x75\x6E\x67\x61\x72\x79\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x48\x61\x6C\x6F\x7A\x61\x74\x62\x69\x7A\x74\x6F\x6E\x73\x61\x67\x69\x20\x4B\x66\x74\x2E\x31\x1A\x30\x18\x06\x03\x55\x04\x0B\x13\x11\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x6B\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x6F\x7A\x6A\x65\x67\x79\x7A\x6F\x69\x20\x28\x43\x6C\x61\x73\x73\x20\x41\x29\x20\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x30\x1E\x17\x0D\x39\x39\x30\x32\x32\x34\x32\x33\x31\x34\x34\x37\x5A\x17\x0D\x31\x39\x30\x32\x31\x39\x32\x33\x31\x34\x34\x37\x5A\x30\x81\xAF\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x48\x75\x6E\x67\x61\x72\x79\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x48\x61\x6C\x6F\x7A\x61\x74\x62\x69\x7A\x74\x6F\x6E\x73\x61\x67\x69\x20\x4B\x66\x74\x2E\x31\x1A\x30\x18\x06\x03\x55\x04\x0B\x13\x11\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x6B\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x6F\x7A\x6A\x65\x67\x79\x7A\x6F\x69\x20\x28\x43\x6C\x61\x73\x73\x20\x41\x29\x20\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\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\xBC\x74\x8C\x0F\xBB\x4C\xF4\x37\x1E\xA9\x05\x82\xD8\xE6\xE1\x6C\x70\xEA\x78\xB5\x6E\xD1\x38\x44\x0D\xA8\x83\xCE\x5D\xD2\xD6\xD5\x81\xC5\xD4\x4B\xE7\x5B\x94\x70\x26\xDB\x3B\x9D\x6A\x4C\x62\xF7\x71\xF3\x64\xD6\x61\x3B\x3D\xEB\x73\xA3\x37\xD9\xCF\xEA\x8C\x92\x3B\xCD\xF7\x07\xDC\x66\x74\x97\xF4\x45\x22\xDD\xF4\x5C\xE0\xBF\x6D\xF3\xBE\x65\x33\xE4\x15\x3A\xBF\xDB\x98\x90\x55\x38\xC4\xED\xA6\x55\x63\x0B\xB0\x78\x04\xF4\xE3\x6E\xC1\x3F\x8E\xFC\x51\x78\x1F\x92\x9E\x83\xC2\xFE\xD9\xB0\xA9\xC9\xBC\x5A\x00\xFF\xA9\xA8\x98\x74\xFB\xF6\x2C\x3E\x15\x39\x0D\xB6\x04\x55\xA8\x0E\x98\x20\x42\xB3\xB1\x25\xAD\x7E\x9A\x6F\x5D\x53\xB1\xAB\x0C\xFC\xEB\xE0\xF3\x7A\xB3\xA8\xB3\xFF\x46\xF6\x63\xA2\xD8\x3A\x98\x7B\xB6\xAC\x85\xFF\xB0\x25\x4F\x74\x63\xE7\x13\x07\xA5\x0A\x8F\x05\xF7\xC0\x64\x6F\x7E\xA7\x27\x80\x96\xDE\xD4\x2E\x86\x60\xC7\x6B\x2B\x5E\x73\x7B\x17\xE7\x91\x3F\x64\x0C\xD8\x4B\x22\x34\x2B\x9B\x32\xF2\x48\x1F\x9F\xA1\x0A\x84\x7A\xE2\xC2\xAD\x97\x3D\x8E\xD5\xC1\xF9\x56\xA3\x50\xE9\xC6\xB4\xFA\x98\xA2\xEE\x95\xE6\x2A\x03\x8C\xDF\x02\x03\x01\x00\x01\xA3\x82\x02\x9F\x30\x82\x02\x9B\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x00\x06\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x04\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x02\x60\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x0D\x04\x82\x02\x51\x16\x82\x02\x4D\x46\x49\x47\x59\x45\x4C\x45\x4D\x21\x20\x45\x7A\x65\x6E\x20\x74\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x41\x6C\x74\x61\x6C\x61\x6E\x6F\x73\x20\x53\x7A\x6F\x6C\x67\x61\x6C\x74\x61\x74\x61\x73\x69\x20\x46\x65\x6C\x74\x65\x74\x65\x6C\x65\x69\x62\x65\x6E\x20\x6C\x65\x69\x72\x74\x20\x65\x6C\x6A\x61\x72\x61\x73\x6F\x6B\x20\x61\x6C\x61\x70\x6A\x61\x6E\x20\x6B\x65\x73\x7A\x75\x6C\x74\x2E\x20\x41\x20\x68\x69\x74\x65\x6C\x65\x73\x69\x74\x65\x73\x20\x66\x6F\x6C\x79\x61\x6D\x61\x74\x61\x74\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x74\x65\x72\x6D\x65\x6B\x66\x65\x6C\x65\x6C\x6F\x73\x73\x65\x67\x2D\x62\x69\x7A\x74\x6F\x73\x69\x74\x61\x73\x61\x20\x76\x65\x64\x69\x2E\x20\x41\x20\x64\x69\x67\x69\x74\x61\x6C\x69\x73\x20\x61\x6C\x61\x69\x72\x61\x73\x20\x65\x6C\x66\x6F\x67\x61\x64\x61\x73\x61\x6E\x61\x6B\x20\x66\x65\x6C\x74\x65\x74\x65\x6C\x65\x20\x61\x7A\x20\x65\x6C\x6F\x69\x72\x74\x20\x65\x6C\x6C\x65\x6E\x6F\x72\x7A\x65\x73\x69\x20\x65\x6C\x6A\x61\x72\x61\x73\x20\x6D\x65\x67\x74\x65\x74\x65\x6C\x65\x2E\x20\x41\x7A\x20\x65\x6C\x6A\x61\x72\x61\x73\x20\x6C\x65\x69\x72\x61\x73\x61\x20\x6D\x65\x67\x74\x61\x6C\x61\x6C\x68\x61\x74\x6F\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x68\x6F\x6E\x6C\x61\x70\x6A\x61\x6E\x20\x61\x20\x68\x74\x74\x70\x73\x3A\x2F\x2F\x77\x77\x77\x2E\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2F\x64\x6F\x63\x73\x20\x63\x69\x6D\x65\x6E\x20\x76\x61\x67\x79\x20\x6B\x65\x72\x68\x65\x74\x6F\x20\x61\x7A\x20\x65\x6C\x6C\x65\x6E\x6F\x72\x7A\x65\x73\x40\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x20\x65\x2D\x6D\x61\x69\x6C\x20\x63\x69\x6D\x65\x6E\x2E\x20\x49\x4D\x50\x4F\x52\x54\x41\x4E\x54\x21\x20\x54\x68\x65\x20\x69\x73\x73\x75\x61\x6E\x63\x65\x20\x61\x6E\x64\x20\x74\x68\x65\x20\x75\x73\x65\x20\x6F\x66\x20\x74\x68\x69\x73\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x20\x73\x75\x62\x6A\x65\x63\x74\x20\x74\x6F\x20\x74\x68\x65\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x43\x50\x53\x20\x61\x76\x61\x69\x6C\x61\x62\x6C\x65\x20\x61\x74\x20\x68\x74\x74\x70\x73\x3A\x2F\x2F\x77\x77\x77\x2E\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2F\x64\x6F\x63\x73\x20\x6F\x72\x20\x62\x79\x20\x65\x2D\x6D\x61\x69\x6C\x20\x61\x74\x20\x63\x70\x73\x40\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x82\x01\x01\x00\x48\x24\x46\xF7\xBA\x56\x6F\xFA\xC8\x28\x03\x40\x4E\xE5\x31\x39\x6B\x26\x6B\x53\x7F\xDB\xDF\xDF\xF3\x71\x3D\x26\xC0\x14\x0E\xC6\x67\x7B\x23\xA8\x0C\x73\xDD\x01\xBB\xC6\xCA\x6E\x37\x39\x55\xD5\xC7\x8C\x56\x20\x0E\x28\x0A\x0E\xD2\x2A\xA4\xB0\x49\x52\xC6\x38\x07\xFE\xBE\x0A\x09\x8C\xD1\x98\xCF\xCA\xDA\x14\x31\xA1\x4F\xD2\x39\xFC\x0F\x11\x2C\x43\xC3\xDD\xAB\x93\xC7\x55\x3E\x47\x7C\x18\x1A\x00\xDC\xF3\x7B\xD8\xF2\x7F\x52\x6C\x20\xF4\x0B\x5F\x69\x52\xF4\xEE\xF8\xB2\x29\x60\xEB\xE3\x49\x31\x21\x0D\xD6\xB5\x10\x41\xE2\x41\x09\x6C\xE2\x1A\x9A\x56\x4B\x77\x02\xF6\xA0\x9B\x9A\x27\x87\xE8\x55\x29\x71\xC2\x90\x9F\x45\x78\x1A\xE1\x15\x64\x3D\xD0\x0E\xD8\xA0\x76\x9F\xAE\xC5\xD0\x2E\xEA\xD6\x0F\x56\xEC\x64\x7F\x5A\x9B\x14\x58\x01\x27\x7E\x13\x50\xC7\x6B\x2A\xE6\x68\x3C\xBF\x5C\xA0\x0A\x1B\xE1\x0E\x7A\xE9\xE2\x80\xC3\xE9\xE9\xF6\xFD\x6C\x11\x9E\xD0\xE5\x28\x27\x2B\x54\x32\x42\x14\x82\x75\xE6\x4A\xF0\x2B\x66\x75\x63\x8C\xA2\xFB\x04\x3E\x83\x0E\x9B\x36\xF0\x18\xE4\x26\x20\xC3\x8C\xF0\x28\x07\xAD\x3C\x17\x66\x88\xB5\xFD\xB6\x88", - ["NetLock Business (Class B) Root"] = "\x30\x82\x05\x4B\x30\x82\x04\xB4\xA0\x03\x02\x01\x02\x02\x01\x69\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\x99\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x48\x61\x6C\x6F\x7A\x61\x74\x62\x69\x7A\x74\x6F\x6E\x73\x61\x67\x69\x20\x4B\x66\x74\x2E\x31\x1A\x30\x18\x06\x03\x55\x04\x0B\x13\x11\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x6B\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x55\x7A\x6C\x65\x74\x69\x20\x28\x43\x6C\x61\x73\x73\x20\x42\x29\x20\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x30\x1E\x17\x0D\x39\x39\x30\x32\x32\x35\x31\x34\x31\x30\x32\x32\x5A\x17\x0D\x31\x39\x30\x32\x32\x30\x31\x34\x31\x30\x32\x32\x5A\x30\x81\x99\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x48\x61\x6C\x6F\x7A\x61\x74\x62\x69\x7A\x74\x6F\x6E\x73\x61\x67\x69\x20\x4B\x66\x74\x2E\x31\x1A\x30\x18\x06\x03\x55\x04\x0B\x13\x11\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x6B\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x55\x7A\x6C\x65\x74\x69\x20\x28\x43\x6C\x61\x73\x73\x20\x42\x29\x20\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xB1\xEA\x04\xEC\x20\xA0\x23\xC2\x8F\x38\x60\xCF\xC7\x46\xB3\xD5\x1B\xFE\xFB\xB9\x99\x9E\x04\xDC\x1C\x7F\x8C\x4A\x81\x98\xEE\xA4\xD4\xCA\x8A\x17\xB9\x22\x7F\x83\x0A\x75\x4C\x9B\xC0\x69\xD8\x64\x39\xA3\xED\x92\xA3\xFD\x5B\x5C\x74\x1A\xC0\x47\xCA\x3A\x69\x76\x9A\xBA\xE2\x44\x17\xFC\x4C\xA3\xD5\xFE\xB8\x97\x88\xAF\x88\x03\x89\x1F\xA4\xF2\x04\x3E\xC8\x07\x0B\xE6\xF9\xB3\x2F\x7A\x62\x14\x09\x46\x14\xCA\x64\xF5\x8B\x80\xB5\x62\xA8\xD8\x6B\xD6\x71\x93\x2D\xB3\xBF\x09\x54\x58\xED\x06\xEB\xA8\x7B\xDC\x43\xB1\xA1\x69\x02\x03\x01\x00\x01\xA3\x82\x02\x9F\x30\x82\x02\x9B\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x04\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x00\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x02\x60\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x0D\x04\x82\x02\x51\x16\x82\x02\x4D\x46\x49\x47\x59\x45\x4C\x45\x4D\x21\x20\x45\x7A\x65\x6E\x20\x74\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x41\x6C\x74\x61\x6C\x61\x6E\x6F\x73\x20\x53\x7A\x6F\x6C\x67\x61\x6C\x74\x61\x74\x61\x73\x69\x20\x46\x65\x6C\x74\x65\x74\x65\x6C\x65\x69\x62\x65\x6E\x20\x6C\x65\x69\x72\x74\x20\x65\x6C\x6A\x61\x72\x61\x73\x6F\x6B\x20\x61\x6C\x61\x70\x6A\x61\x6E\x20\x6B\x65\x73\x7A\x75\x6C\x74\x2E\x20\x41\x20\x68\x69\x74\x65\x6C\x65\x73\x69\x74\x65\x73\x20\x66\x6F\x6C\x79\x61\x6D\x61\x74\x61\x74\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x74\x65\x72\x6D\x65\x6B\x66\x65\x6C\x65\x6C\x6F\x73\x73\x65\x67\x2D\x62\x69\x7A\x74\x6F\x73\x69\x74\x61\x73\x61\x20\x76\x65\x64\x69\x2E\x20\x41\x20\x64\x69\x67\x69\x74\x61\x6C\x69\x73\x20\x61\x6C\x61\x69\x72\x61\x73\x20\x65\x6C\x66\x6F\x67\x61\x64\x61\x73\x61\x6E\x61\x6B\x20\x66\x65\x6C\x74\x65\x74\x65\x6C\x65\x20\x61\x7A\x20\x65\x6C\x6F\x69\x72\x74\x20\x65\x6C\x6C\x65\x6E\x6F\x72\x7A\x65\x73\x69\x20\x65\x6C\x6A\x61\x72\x61\x73\x20\x6D\x65\x67\x74\x65\x74\x65\x6C\x65\x2E\x20\x41\x7A\x20\x65\x6C\x6A\x61\x72\x61\x73\x20\x6C\x65\x69\x72\x61\x73\x61\x20\x6D\x65\x67\x74\x61\x6C\x61\x6C\x68\x61\x74\x6F\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x68\x6F\x6E\x6C\x61\x70\x6A\x61\x6E\x20\x61\x20\x68\x74\x74\x70\x73\x3A\x2F\x2F\x77\x77\x77\x2E\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2F\x64\x6F\x63\x73\x20\x63\x69\x6D\x65\x6E\x20\x76\x61\x67\x79\x20\x6B\x65\x72\x68\x65\x74\x6F\x20\x61\x7A\x20\x65\x6C\x6C\x65\x6E\x6F\x72\x7A\x65\x73\x40\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x20\x65\x2D\x6D\x61\x69\x6C\x20\x63\x69\x6D\x65\x6E\x2E\x20\x49\x4D\x50\x4F\x52\x54\x41\x4E\x54\x21\x20\x54\x68\x65\x20\x69\x73\x73\x75\x61\x6E\x63\x65\x20\x61\x6E\x64\x20\x74\x68\x65\x20\x75\x73\x65\x20\x6F\x66\x20\x74\x68\x69\x73\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x20\x73\x75\x62\x6A\x65\x63\x74\x20\x74\x6F\x20\x74\x68\x65\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x43\x50\x53\x20\x61\x76\x61\x69\x6C\x61\x62\x6C\x65\x20\x61\x74\x20\x68\x74\x74\x70\x73\x3A\x2F\x2F\x77\x77\x77\x2E\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2F\x64\x6F\x63\x73\x20\x6F\x72\x20\x62\x79\x20\x65\x2D\x6D\x61\x69\x6C\x20\x61\x74\x20\x63\x70\x73\x40\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x04\xDB\xAE\x8C\x17\xAF\xF8\x0E\x90\x31\x4E\xCD\x3E\x09\xC0\x6D\x3A\xB0\xF8\x33\x4C\x47\x4C\xE3\x75\x88\x10\x97\xAC\xB0\x38\x15\x91\xC6\x29\x96\xCC\x21\xC0\x6D\x3C\xA5\x74\xCF\xD8\x82\xA5\x39\xC3\x65\xE3\x42\x70\xBB\x22\x90\xE3\x7D\xDB\x35\x76\xE1\xA0\xB5\xDA\x9F\x70\x6E\x93\x1A\x30\x39\x1D\x30\xDB\x2E\xE3\x7C\xB2\x91\xB2\xD1\x37\x29\xFA\xB9\xD6\x17\x5C\x47\x4F\xE3\x1D\x38\xEB\x9F\xD5\x7B\x95\xA8\x28\x9E\x15\x4A\xD1\xD1\xD0\x2B\x00\x97\xA0\xE2\x92\x36\x2B\x63\xAC\x58\x01\x6B\x33\x29\x50\x86\x83\xF1\x01\x48", - ["NetLock Express (Class C) Root"] = "\x30\x82\x05\x4F\x30\x82\x04\xB8\xA0\x03\x02\x01\x02\x02\x01\x68\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\x9B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x48\x61\x6C\x6F\x7A\x61\x74\x62\x69\x7A\x74\x6F\x6E\x73\x61\x67\x69\x20\x4B\x66\x74\x2E\x31\x1A\x30\x18\x06\x03\x55\x04\x0B\x13\x11\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x6B\x31\x34\x30\x32\x06\x03\x55\x04\x03\x13\x2B\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x45\x78\x70\x72\x65\x73\x73\x7A\x20\x28\x43\x6C\x61\x73\x73\x20\x43\x29\x20\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x30\x1E\x17\x0D\x39\x39\x30\x32\x32\x35\x31\x34\x30\x38\x31\x31\x5A\x17\x0D\x31\x39\x30\x32\x32\x30\x31\x34\x30\x38\x31\x31\x5A\x30\x81\x9B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x48\x61\x6C\x6F\x7A\x61\x74\x62\x69\x7A\x74\x6F\x6E\x73\x61\x67\x69\x20\x4B\x66\x74\x2E\x31\x1A\x30\x18\x06\x03\x55\x04\x0B\x13\x11\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x6B\x31\x34\x30\x32\x06\x03\x55\x04\x03\x13\x2B\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x45\x78\x70\x72\x65\x73\x73\x7A\x20\x28\x43\x6C\x61\x73\x73\x20\x43\x29\x20\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xEB\xEC\xB0\x6C\x61\x8A\x23\x25\xAF\x60\x20\xE3\xD9\x9F\xFC\x93\x0B\xDB\x5D\x8D\xB0\xA1\xB3\x40\x3A\x82\xCE\xFD\x75\xE0\x78\x32\x03\x86\x5A\x86\x95\x91\xED\x53\xFA\x9D\x40\xFC\xE6\xE8\xDD\xD9\x5B\x7A\x03\xBD\x5D\xF3\x3B\x0C\xC3\x51\x79\x9B\xAD\x55\xA0\xE9\xD0\x03\x10\xAF\x0A\xBA\x14\x42\xD9\x52\x26\x11\x22\xC7\xD2\x20\xCC\x82\xA4\x9A\xA9\xFE\xB8\x81\x76\x9D\x6A\xB7\xD2\x36\x75\x3E\xB1\x86\x09\xF6\x6E\x6D\x7E\x4E\xB7\x7A\xEC\xAE\x71\x84\xF6\x04\x33\x08\x25\x32\xEB\x74\xAC\x16\x44\xC6\xE4\x40\x93\x1D\x7F\xAD\x02\x03\x01\x00\x01\xA3\x82\x02\x9F\x30\x82\x02\x9B\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x04\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x00\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x02\x60\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x0D\x04\x82\x02\x51\x16\x82\x02\x4D\x46\x49\x47\x59\x45\x4C\x45\x4D\x21\x20\x45\x7A\x65\x6E\x20\x74\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x41\x6C\x74\x61\x6C\x61\x6E\x6F\x73\x20\x53\x7A\x6F\x6C\x67\x61\x6C\x74\x61\x74\x61\x73\x69\x20\x46\x65\x6C\x74\x65\x74\x65\x6C\x65\x69\x62\x65\x6E\x20\x6C\x65\x69\x72\x74\x20\x65\x6C\x6A\x61\x72\x61\x73\x6F\x6B\x20\x61\x6C\x61\x70\x6A\x61\x6E\x20\x6B\x65\x73\x7A\x75\x6C\x74\x2E\x20\x41\x20\x68\x69\x74\x65\x6C\x65\x73\x69\x74\x65\x73\x20\x66\x6F\x6C\x79\x61\x6D\x61\x74\x61\x74\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x74\x65\x72\x6D\x65\x6B\x66\x65\x6C\x65\x6C\x6F\x73\x73\x65\x67\x2D\x62\x69\x7A\x74\x6F\x73\x69\x74\x61\x73\x61\x20\x76\x65\x64\x69\x2E\x20\x41\x20\x64\x69\x67\x69\x74\x61\x6C\x69\x73\x20\x61\x6C\x61\x69\x72\x61\x73\x20\x65\x6C\x66\x6F\x67\x61\x64\x61\x73\x61\x6E\x61\x6B\x20\x66\x65\x6C\x74\x65\x74\x65\x6C\x65\x20\x61\x7A\x20\x65\x6C\x6F\x69\x72\x74\x20\x65\x6C\x6C\x65\x6E\x6F\x72\x7A\x65\x73\x69\x20\x65\x6C\x6A\x61\x72\x61\x73\x20\x6D\x65\x67\x74\x65\x74\x65\x6C\x65\x2E\x20\x41\x7A\x20\x65\x6C\x6A\x61\x72\x61\x73\x20\x6C\x65\x69\x72\x61\x73\x61\x20\x6D\x65\x67\x74\x61\x6C\x61\x6C\x68\x61\x74\x6F\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x68\x6F\x6E\x6C\x61\x70\x6A\x61\x6E\x20\x61\x20\x68\x74\x74\x70\x73\x3A\x2F\x2F\x77\x77\x77\x2E\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2F\x64\x6F\x63\x73\x20\x63\x69\x6D\x65\x6E\x20\x76\x61\x67\x79\x20\x6B\x65\x72\x68\x65\x74\x6F\x20\x61\x7A\x20\x65\x6C\x6C\x65\x6E\x6F\x72\x7A\x65\x73\x40\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x20\x65\x2D\x6D\x61\x69\x6C\x20\x63\x69\x6D\x65\x6E\x2E\x20\x49\x4D\x50\x4F\x52\x54\x41\x4E\x54\x21\x20\x54\x68\x65\x20\x69\x73\x73\x75\x61\x6E\x63\x65\x20\x61\x6E\x64\x20\x74\x68\x65\x20\x75\x73\x65\x20\x6F\x66\x20\x74\x68\x69\x73\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x20\x73\x75\x62\x6A\x65\x63\x74\x20\x74\x6F\x20\x74\x68\x65\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x43\x50\x53\x20\x61\x76\x61\x69\x6C\x61\x62\x6C\x65\x20\x61\x74\x20\x68\x74\x74\x70\x73\x3A\x2F\x2F\x77\x77\x77\x2E\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2F\x64\x6F\x63\x73\x20\x6F\x72\x20\x62\x79\x20\x65\x2D\x6D\x61\x69\x6C\x20\x61\x74\x20\x63\x70\x73\x40\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x10\xAD\x7F\xD7\x0C\x32\x80\x0A\xD8\x86\xF1\x79\x98\xB5\xAD\xD4\xCD\xB3\x36\xC4\x96\x48\xC1\x5C\xCD\x9A\xD9\x05\x2E\x9F\xBE\x50\xEB\xF4\x26\x14\x10\x2D\xD4\x66\x17\xF8\x9E\xC1\x27\xFD\xF1\xED\xE4\x7B\x4B\xA0\x6C\xB5\xAB\x9A\x57\x70\xA6\xED\xA0\xA4\xED\x2E\xF5\xFD\xFC\xBD\xFE\x4D\x37\x08\x0C\xBC\xE3\x96\x83\x22\xF5\x49\x1B\x7F\x4B\x2B\xB4\x54\xC1\x80\x7C\x99\x4E\x1D\xD0\x8C\xEE\xD0\xAC\xE5\x92\xFA\x75\x56\xFE\x64\xA0\x13\x8F\xB8\xB8\x16\x9D\x61\x05\x67\x80\xC8\xD0\xD8\xA5\x07\x02\x34\x98\x04\x8D\x33\x04\xD4", - ["XRamp Global CA Root"] = "\x30\x82\x04\x30\x30\x82\x03\x18\xA0\x03\x02\x01\x02\x02\x10\x50\x94\x6C\xEC\x18\xEA\xD5\x9C\x4D\xD5\x97\xEF\x75\x8F\xA0\xAD\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1E\x30\x1C\x06\x03\x55\x04\x0B\x13\x15\x77\x77\x77\x2E\x78\x72\x61\x6D\x70\x73\x65\x63\x75\x72\x69\x74\x79\x2E\x63\x6F\x6D\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x58\x52\x61\x6D\x70\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x49\x6E\x63\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x58\x52\x61\x6D\x70\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x34\x31\x31\x30\x31\x31\x37\x31\x34\x30\x34\x5A\x17\x0D\x33\x35\x30\x31\x30\x31\x30\x35\x33\x37\x31\x39\x5A\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1E\x30\x1C\x06\x03\x55\x04\x0B\x13\x15\x77\x77\x77\x2E\x78\x72\x61\x6D\x70\x73\x65\x63\x75\x72\x69\x74\x79\x2E\x63\x6F\x6D\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x58\x52\x61\x6D\x70\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x49\x6E\x63\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x58\x52\x61\x6D\x70\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\x98\x24\x1E\xBD\x15\xB4\xBA\xDF\xC7\x8C\xA5\x27\xB6\x38\x0B\x69\xF3\xB6\x4E\xA8\x2C\x2E\x21\x1D\x5C\x44\xDF\x21\x5D\x7E\x23\x74\xFE\x5E\x7E\xB4\x4A\xB7\xA6\xAD\x1F\xAE\xE0\x06\x16\xE2\x9B\x5B\xD9\x67\x74\x6B\x5D\x80\x8F\x29\x9D\x86\x1B\xD9\x9C\x0D\x98\x6D\x76\x10\x28\x58\xE4\x65\xB0\x7F\x4A\x98\x79\x9F\xE0\xC3\x31\x7E\x80\x2B\xB5\x8C\xC0\x40\x3B\x11\x86\xD0\xCB\xA2\x86\x36\x60\xA4\xD5\x30\x82\x6D\xD9\x6E\xD0\x0F\x12\x04\x33\x97\x5F\x4F\x61\x5A\xF0\xE4\xF9\x91\xAB\xE7\x1D\x3B\xBC\xE8\xCF\xF4\x6B\x2D\x34\x7C\xE2\x48\x61\x1C\x8E\xF3\x61\x44\xCC\x6F\xA0\x4A\xA9\x94\xB0\x4D\xDA\xE7\xA9\x34\x7A\x72\x38\xA8\x41\xCC\x3C\x94\x11\x7D\xEB\xC8\xA6\x8C\xB7\x86\xCB\xCA\x33\x3B\xD9\x3D\x37\x8B\xFB\x7A\x3E\x86\x2C\xE7\x73\xD7\x0A\x57\xAC\x64\x9B\x19\xEB\xF4\x0F\x04\x08\x8A\xAC\x03\x17\x19\x64\xF4\x5A\x25\x22\x8D\x34\x2C\xB2\xF6\x68\x1D\x12\x6D\xD3\x8A\x1E\x14\xDA\xC4\x8F\xA6\xE2\x23\x85\xD5\x7A\x0D\xBD\x6A\xE0\xE9\xEC\xEC\x17\xBB\x42\x1B\x67\xAA\x25\xED\x45\x83\x21\xFC\xC1\xC9\x7C\xD5\x62\x3E\xFA\xF2\xC5\x2D\xD3\xFD\xD4\x65\x02\x03\x01\x00\x01\xA3\x81\x9F\x30\x81\x9C\x30\x13\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x14\x02\x04\x06\x1E\x04\x00\x43\x00\x41\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC6\x4F\xA2\x3D\x06\x63\x84\x09\x9C\xCE\x62\xE4\x04\xAC\x8D\x5C\xB5\xE9\xB6\x1B\x30\x36\x06\x03\x55\x1D\x1F\x04\x2F\x30\x2D\x30\x2B\xA0\x29\xA0\x27\x86\x25\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x78\x72\x61\x6D\x70\x73\x65\x63\x75\x72\x69\x74\x79\x2E\x63\x6F\x6D\x2F\x58\x47\x43\x41\x2E\x63\x72\x6C\x30\x10\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x91\x15\x39\x03\x01\x1B\x67\xFB\x4A\x1C\xF9\x0A\x60\x5B\xA1\xDA\x4D\x97\x62\xF9\x24\x53\x27\xD7\x82\x64\x4E\x90\x2E\xC3\x49\x1B\x2B\x9A\xDC\xFC\xA8\x78\x67\x35\xF1\x1D\xF0\x11\xBD\xB7\x48\xE3\x10\xF6\x0D\xDF\x3F\xD2\xC9\xB6\xAA\x55\xA4\x48\xBA\x02\xDB\xDE\x59\x2E\x15\x5B\x3B\x9D\x16\x7D\x47\xD7\x37\xEA\x5F\x4D\x76\x12\x36\xBB\x1F\xD7\xA1\x81\x04\x46\x20\xA3\x2C\x6D\xA9\x9E\x01\x7E\x3F\x29\xCE\x00\x93\xDF\xFD\xC9\x92\x73\x89\x89\x64\x9E\xE7\x2B\xE4\x1C\x91\x2C\xD2\xB9\xCE\x7D\xCE\x6F\x31\x99\xD3\xE6\xBE\xD2\x1E\x90\xF0\x09\x14\x79\x5C\x23\xAB\x4D\xD2\xDA\x21\x1F\x4D\x99\x79\x9D\xE1\xCF\x27\x9F\x10\x9B\x1C\x88\x0D\xB0\x8A\x64\x41\x31\xB8\x0E\x6C\x90\x24\xA4\x9B\x5C\x71\x8F\xBA\xBB\x7E\x1C\x1B\xDB\x6A\x80\x0F\x21\xBC\xE9\xDB\xA6\xB7\x40\xF4\xB2\x8B\xA9\xB1\xE4\xEF\x9A\x1A\xD0\x3D\x69\x99\xEE\xA8\x28\xA3\xE1\x3C\xB3\xF0\xB2\x11\x9C\xCF\x7C\x40\xE6\xDD\xE7\x43\x7D\xA2\xD8\x3A\xB5\xA9\x8D\xF2\x34\x99\xC4\xD4\x10\xE1\x06\xFD\x09\x84\x10\x3B\xEE\xC4\x4C\xF4\xEC\x27\x7C\x42\xC2\x74\x7C\x82\x8A\x09\xC9\xB4\x03\x25\xBC", - ["Go Daddy Class 2 CA"] = "\x30\x82\x04\x00\x30\x82\x02\xE8\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1F\x06\x03\x55\x04\x0A\x13\x18\x54\x68\x65\x20\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x47\x72\x6F\x75\x70\x2C\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x0B\x13\x28\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x34\x30\x36\x32\x39\x31\x37\x30\x36\x32\x30\x5A\x17\x0D\x33\x34\x30\x36\x32\x39\x31\x37\x30\x36\x32\x30\x5A\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1F\x06\x03\x55\x04\x0A\x13\x18\x54\x68\x65\x20\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x47\x72\x6F\x75\x70\x2C\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x0B\x13\x28\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x82\x01\x20\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0D\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xDE\x9D\xD7\xEA\x57\x18\x49\xA1\x5B\xEB\xD7\x5F\x48\x86\xEA\xBE\xDD\xFF\xE4\xEF\x67\x1C\xF4\x65\x68\xB3\x57\x71\xA0\x5E\x77\xBB\xED\x9B\x49\xE9\x70\x80\x3D\x56\x18\x63\x08\x6F\xDA\xF2\xCC\xD0\x3F\x7F\x02\x54\x22\x54\x10\xD8\xB2\x81\xD4\xC0\x75\x3D\x4B\x7F\xC7\x77\xC3\x3E\x78\xAB\x1A\x03\xB5\x20\x6B\x2F\x6A\x2B\xB1\xC5\x88\x7E\xC4\xBB\x1E\xB0\xC1\xD8\x45\x27\x6F\xAA\x37\x58\xF7\x87\x26\xD7\xD8\x2D\xF6\xA9\x17\xB7\x1F\x72\x36\x4E\xA6\x17\x3F\x65\x98\x92\xDB\x2A\x6E\x5D\xA2\xFE\x88\xE0\x0B\xDE\x7F\xE5\x8D\x15\xE1\xEB\xCB\x3A\xD5\xE2\x12\xA2\x13\x2D\xD8\x8E\xAF\x5F\x12\x3D\xA0\x08\x05\x08\xB6\x5C\xA5\x65\x38\x04\x45\x99\x1E\xA3\x60\x60\x74\xC5\x41\xA5\x72\x62\x1B\x62\xC5\x1F\x6F\x5F\x1A\x42\xBE\x02\x51\x65\xA8\xAE\x23\x18\x6A\xFC\x78\x03\xA9\x4D\x7F\x80\xC3\xFA\xAB\x5A\xFC\xA1\x40\xA4\xCA\x19\x16\xFE\xB2\xC8\xEF\x5E\x73\x0D\xEE\x77\xBD\x9A\xF6\x79\x98\xBC\xB1\x07\x67\xA2\x15\x0D\xDD\xA0\x58\xC6\x44\x7B\x0A\x3E\x62\x28\x5F\xBA\x41\x07\x53\x58\xCF\x11\x7E\x38\x74\xC5\xF8\xFF\xB5\x69\x90\x8F\x84\x74\xEA\x97\x1B\xAF\x02\x01\x03\xA3\x81\xC0\x30\x81\xBD\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xD2\xC4\xB0\xD2\x91\xD4\x4C\x11\x71\xB3\x61\xCB\x3D\xA1\xFE\xDD\xA8\x6A\xD4\xE3\x30\x81\x8D\x06\x03\x55\x1D\x23\x04\x81\x85\x30\x81\x82\x80\x14\xD2\xC4\xB0\xD2\x91\xD4\x4C\x11\x71\xB3\x61\xCB\x3D\xA1\xFE\xDD\xA8\x6A\xD4\xE3\xA1\x67\xA4\x65\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1F\x06\x03\x55\x04\x0A\x13\x18\x54\x68\x65\x20\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x47\x72\x6F\x75\x70\x2C\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x0B\x13\x28\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x82\x01\x00\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x32\x4B\xF3\xB2\xCA\x3E\x91\xFC\x12\xC6\xA1\x07\x8C\x8E\x77\xA0\x33\x06\x14\x5C\x90\x1E\x18\xF7\x08\xA6\x3D\x0A\x19\xF9\x87\x80\x11\x6E\x69\xE4\x96\x17\x30\xFF\x34\x91\x63\x72\x38\xEE\xCC\x1C\x01\xA3\x1D\x94\x28\xA4\x31\xF6\x7A\xC4\x54\xD7\xF6\xE5\x31\x58\x03\xA2\xCC\xCE\x62\xDB\x94\x45\x73\xB5\xBF\x45\xC9\x24\xB5\xD5\x82\x02\xAD\x23\x79\x69\x8D\xB8\xB6\x4D\xCE\xCF\x4C\xCA\x33\x23\xE8\x1C\x88\xAA\x9D\x8B\x41\x6E\x16\xC9\x20\xE5\x89\x9E\xCD\x3B\xDA\x70\xF7\x7E\x99\x26\x20\x14\x54\x25\xAB\x6E\x73\x85\xE6\x9B\x21\x9D\x0A\x6C\x82\x0E\xA8\xF8\xC2\x0C\xFA\x10\x1E\x6C\x96\xEF\x87\x0D\xC4\x0F\x61\x8B\xAD\xEE\x83\x2B\x95\xF8\x8E\x92\x84\x72\x39\xEB\x20\xEA\x83\xED\x83\xCD\x97\x6E\x08\xBC\xEB\x4E\x26\xB6\x73\x2B\xE4\xD3\xF6\x4C\xFE\x26\x71\xE2\x61\x11\x74\x4A\xFF\x57\x1A\x87\x0F\x75\x48\x2E\xCF\x51\x69\x17\xA0\x02\x12\x61\x95\xD5\xD1\x40\xB2\x10\x4C\xEE\xC4\xAC\x10\x43\xA6\xA5\x9E\x0A\xD5\x95\x62\x9A\x0D\xCF\x88\x82\xC5\x32\x0C\xE4\x2B\x9F\x45\xE6\x0D\x9F\x28\x9C\xB1\xB9\x2A\x5A\x57\xAD\x37\x0F\xAF\x1D\x7F\xDB\xBD\x9F", - ["Starfield Class 2 CA"] = "\x30\x82\x04\x0F\x30\x82\x02\xF7\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x68\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x32\x30\x30\x06\x03\x55\x04\x0B\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x34\x30\x36\x32\x39\x31\x37\x33\x39\x31\x36\x5A\x17\x0D\x33\x34\x30\x36\x32\x39\x31\x37\x33\x39\x31\x36\x5A\x30\x68\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x32\x30\x30\x06\x03\x55\x04\x0B\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x82\x01\x20\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0D\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xB7\x32\xC8\xFE\xE9\x71\xA6\x04\x85\xAD\x0C\x11\x64\xDF\xCE\x4D\xEF\xC8\x03\x18\x87\x3F\xA1\xAB\xFB\x3C\xA6\x9F\xF0\xC3\xA1\xDA\xD4\xD8\x6E\x2B\x53\x90\xFB\x24\xA4\x3E\x84\xF0\x9E\xE8\x5F\xEC\xE5\x27\x44\xF5\x28\xA6\x3F\x7B\xDE\xE0\x2A\xF0\xC8\xAF\x53\x2F\x9E\xCA\x05\x01\x93\x1E\x8F\x66\x1C\x39\xA7\x4D\xFA\x5A\xB6\x73\x04\x25\x66\xEB\x77\x7F\xE7\x59\xC6\x4A\x99\x25\x14\x54\xEB\x26\xC7\xF3\x7F\x19\xD5\x30\x70\x8F\xAF\xB0\x46\x2A\xFF\xAD\xEB\x29\xED\xD7\x9F\xAA\x04\x87\xA3\xD4\xF9\x89\xA5\x34\x5F\xDB\x43\x91\x82\x36\xD9\x66\x3C\xB1\xB8\xB9\x82\xFD\x9C\x3A\x3E\x10\xC8\x3B\xEF\x06\x65\x66\x7A\x9B\x19\x18\x3D\xFF\x71\x51\x3C\x30\x2E\x5F\xBE\x3D\x77\x73\xB2\x5D\x06\x6C\xC3\x23\x56\x9A\x2B\x85\x26\x92\x1C\xA7\x02\xB3\xE4\x3F\x0D\xAF\x08\x79\x82\xB8\x36\x3D\xEA\x9C\xD3\x35\xB3\xBC\x69\xCA\xF5\xCC\x9D\xE8\xFD\x64\x8D\x17\x80\x33\x6E\x5E\x4A\x5D\x99\xC9\x1E\x87\xB4\x9D\x1A\xC0\xD5\x6E\x13\x35\x23\x5E\xDF\x9B\x5F\x3D\xEF\xD6\xF7\x76\xC2\xEA\x3E\xBB\x78\x0D\x1C\x42\x67\x6B\x04\xD8\xF8\xD6\xDA\x6F\x8B\xF2\x44\xA0\x01\xAB\x02\x01\x03\xA3\x81\xC5\x30\x81\xC2\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xBF\x5F\xB7\xD1\xCE\xDD\x1F\x86\xF4\x5B\x55\xAC\xDC\xD7\x10\xC2\x0E\xA9\x88\xE7\x30\x81\x92\x06\x03\x55\x1D\x23\x04\x81\x8A\x30\x81\x87\x80\x14\xBF\x5F\xB7\xD1\xCE\xDD\x1F\x86\xF4\x5B\x55\xAC\xDC\xD7\x10\xC2\x0E\xA9\x88\xE7\xA1\x6C\xA4\x6A\x30\x68\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x32\x30\x30\x06\x03\x55\x04\x0B\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x82\x01\x00\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x05\x9D\x3F\x88\x9D\xD1\xC9\x1A\x55\xA1\xAC\x69\xF3\xF3\x59\xDA\x9B\x01\x87\x1A\x4F\x57\xA9\xA1\x79\x09\x2A\xDB\xF7\x2F\xB2\x1E\xCC\xC7\x5E\x6A\xD8\x83\x87\xA1\x97\xEF\x49\x35\x3E\x77\x06\x41\x58\x62\xBF\x8E\x58\xB8\x0A\x67\x3F\xEC\xB3\xDD\x21\x66\x1F\xC9\x54\xFA\x72\xCC\x3D\x4C\x40\xD8\x81\xAF\x77\x9E\x83\x7A\xBB\xA2\xC7\xF5\x34\x17\x8E\xD9\x11\x40\xF4\xFC\x2C\x2A\x4D\x15\x7F\xA7\x62\x5D\x2E\x25\xD3\x00\x0B\x20\x1A\x1D\x68\xF9\x17\xB8\xF4\xBD\x8B\xED\x28\x59\xDD\x4D\x16\x8B\x17\x83\xC8\xB2\x65\xC7\x2D\x7A\xA5\xAA\xBC\x53\x86\x6D\xDD\x57\xA4\xCA\xF8\x20\x41\x0B\x68\xF0\xF4\xFB\x74\xBE\x56\x5D\x7A\x79\xF5\xF9\x1D\x85\xE3\x2D\x95\xBE\xF5\x71\x90\x43\xCC\x8D\x1F\x9A\x00\x0A\x87\x29\xE9\x55\x22\x58\x00\x23\xEA\xE3\x12\x43\x29\x5B\x47\x08\xDD\x8C\x41\x6A\x65\x06\xA8\xE5\x21\xAA\x41\xB4\x95\x21\x95\xB9\x7D\xD1\x34\xAB\x13\xD6\xAD\xBC\xDC\xE2\x3D\x39\xCD\xBD\x3E\x75\x70\xA1\x18\x59\x03\xC9\x22\xB4\x8F\x9C\xD5\x5E\x2A\xD7\xA5\xB6\xD4\x0A\x6D\xF8\xB7\x40\x11\x46\x9A\x1F\x79\x0E\x62\xBF\x0F\x97\xEC\xE0\x2F\x1F\x17\x94", - ["StartCom Certification Authority"] = "\x30\x82\x07\xC9\x30\x82\x05\xB1\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4C\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x4C\x74\x64\x2E\x31\x2B\x30\x29\x06\x03\x55\x04\x0B\x13\x22\x53\x65\x63\x75\x72\x65\x20\x44\x69\x67\x69\x74\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x69\x67\x6E\x69\x6E\x67\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x36\x30\x39\x31\x37\x31\x39\x34\x36\x33\x36\x5A\x17\x0D\x33\x36\x30\x39\x31\x37\x31\x39\x34\x36\x33\x36\x5A\x30\x7D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4C\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x4C\x74\x64\x2E\x31\x2B\x30\x29\x06\x03\x55\x04\x0B\x13\x22\x53\x65\x63\x75\x72\x65\x20\x44\x69\x67\x69\x74\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x69\x67\x6E\x69\x6E\x67\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC1\x88\xDB\x09\xBC\x6C\x46\x7C\x78\x9F\x95\x7B\xB5\x33\x90\xF2\x72\x62\xD6\xC1\x36\x20\x22\x24\x5E\xCE\xE9\x77\xF2\x43\x0A\xA2\x06\x64\xA4\xCC\x8E\x36\xF8\x38\xE6\x23\xF0\x6E\x6D\xB1\x3C\xDD\x72\xA3\x85\x1C\xA1\xD3\x3D\xB4\x33\x2B\xD3\x2F\xAF\xFE\xEA\xB0\x41\x59\x67\xB6\xC4\x06\x7D\x0A\x9E\x74\x85\xD6\x79\x4C\x80\x37\x7A\xDF\x39\x05\x52\x59\xF7\xF4\x1B\x46\x43\xA4\xD2\x85\x85\xD2\xC3\x71\xF3\x75\x62\x34\xBA\x2C\x8A\x7F\x1E\x8F\xEE\xED\x34\xD0\x11\xC7\x96\xCD\x52\x3D\xBA\x33\xD6\xDD\x4D\xDE\x0B\x3B\x4A\x4B\x9F\xC2\x26\x2F\xFA\xB5\x16\x1C\x72\x35\x77\xCA\x3C\x5D\xE6\xCA\xE1\x26\x8B\x1A\x36\x76\x5C\x01\xDB\x74\x14\x25\xFE\xED\xB5\xA0\x88\x0F\xDD\x78\xCA\x2D\x1F\x07\x97\x30\x01\x2D\x72\x79\xFA\x46\xD6\x13\x2A\xA8\xB9\xA6\xAB\x83\x49\x1D\xE5\xF2\xEF\xDD\xE4\x01\x8E\x18\x0A\x8F\x63\x53\x16\x85\x62\xA9\x0E\x19\x3A\xCC\xB5\x66\xA6\xC2\x6B\x74\x07\xE4\x2B\xE1\x76\x3E\xB4\x6D\xD8\xF6\x44\xE1\x73\x62\x1F\x3B\xC4\xBE\xA0\x53\x56\x25\x6C\x51\x09\xF7\xAA\xAB\xCA\xBF\x76\xFD\x6D\x9B\xF3\x9D\xDB\xBF\x3D\x66\xBC\x0C\x56\xAA\xAF\x98\x48\x95\x3A\x4B\xDF\xA7\x58\x50\xD9\x38\x75\xA9\x5B\xEA\x43\x0C\x02\xFF\x99\xEB\xE8\x6C\x4D\x70\x5B\x29\x65\x9C\xDD\xAA\x5D\xCC\xAF\x01\x31\xEC\x0C\xEB\xD2\x8D\xE8\xEA\x9C\x7B\xE6\x6E\xF7\x27\x66\x0C\x1A\x48\xD7\x6E\x42\xE3\x3F\xDE\x21\x3E\x7B\xE1\x0D\x70\xFB\x63\xAA\xA8\x6C\x1A\x54\xB4\x5C\x25\x7A\xC9\xA2\xC9\x8B\x16\xA6\xBB\x2C\x7E\x17\x5E\x05\x4D\x58\x6E\x12\x1D\x01\xEE\x12\x10\x0D\xC6\x32\x7F\x18\xFF\xFC\xF4\xFA\xCD\x6E\x91\xE8\x36\x49\xBE\x1A\x48\x69\x8B\xC2\x96\x4D\x1A\x12\xB2\x69\x17\xC1\x0A\x90\xD6\xFA\x79\x22\x48\xBF\xBA\x7B\x69\xF8\x70\xC7\xFA\x7A\x37\xD8\xD8\x0D\xD2\x76\x4F\x57\xFF\x90\xB7\xE3\x91\xD2\xDD\xEF\xC2\x60\xB7\x67\x3A\xDD\xFE\xAA\x9C\xF0\xD4\x8B\x7F\x72\x22\xCE\xC6\x9F\x97\xB6\xF8\xAF\x8A\xA0\x10\xA8\xD9\xFB\x18\xC6\xB6\xB5\x5C\x52\x3C\x89\xB6\x19\x2A\x73\x01\x0A\x0F\x03\xB3\x12\x60\xF2\x7A\x2F\x81\xDB\xA3\x6E\xFF\x26\x30\x97\xF5\x8B\xDD\x89\x57\xB6\xAD\x3D\xB3\xAF\x2B\xC5\xB7\x76\x02\xF0\xA5\xD6\x2B\x9A\x86\x14\x2A\x72\xF6\xE3\x33\x8C\x5D\x09\x4B\x13\xDF\xBB\x8C\x74\x13\x52\x4B\x02\x03\x01\x00\x01\xA3\x82\x02\x52\x30\x82\x02\x4E\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\xAE\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x4E\x0B\xEF\x1A\xA4\x40\x5B\xA5\x17\x69\x87\x30\xCA\x34\x68\x43\xD0\x41\xAE\xF2\x30\x64\x06\x03\x55\x1D\x1F\x04\x5D\x30\x5B\x30\x2C\xA0\x2A\xA0\x28\x86\x26\x68\x74\x74\x70\x3A\x2F\x2F\x63\x65\x72\x74\x2E\x73\x74\x61\x72\x74\x63\x6F\x6D\x2E\x6F\x72\x67\x2F\x73\x66\x73\x63\x61\x2D\x63\x72\x6C\x2E\x63\x72\x6C\x30\x2B\xA0\x29\xA0\x27\x86\x25\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x73\x74\x61\x72\x74\x63\x6F\x6D\x2E\x6F\x72\x67\x2F\x73\x66\x73\x63\x61\x2D\x63\x72\x6C\x2E\x63\x72\x6C\x30\x82\x01\x5D\x06\x03\x55\x1D\x20\x04\x82\x01\x54\x30\x82\x01\x50\x30\x82\x01\x4C\x06\x0B\x2B\x06\x01\x04\x01\x81\xB5\x37\x01\x01\x01\x30\x82\x01\x3B\x30\x2F\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x63\x65\x72\x74\x2E\x73\x74\x61\x72\x74\x63\x6F\x6D\x2E\x6F\x72\x67\x2F\x70\x6F\x6C\x69\x63\x79\x2E\x70\x64\x66\x30\x35\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x29\x68\x74\x74\x70\x3A\x2F\x2F\x63\x65\x72\x74\x2E\x73\x74\x61\x72\x74\x63\x6F\x6D\x2E\x6F\x72\x67\x2F\x69\x6E\x74\x65\x72\x6D\x65\x64\x69\x61\x74\x65\x2E\x70\x64\x66\x30\x81\xD0\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x81\xC3\x30\x27\x16\x20\x53\x74\x61\x72\x74\x20\x43\x6F\x6D\x6D\x65\x72\x63\x69\x61\x6C\x20\x28\x53\x74\x61\x72\x74\x43\x6F\x6D\x29\x20\x4C\x74\x64\x2E\x30\x03\x02\x01\x01\x1A\x81\x97\x4C\x69\x6D\x69\x74\x65\x64\x20\x4C\x69\x61\x62\x69\x6C\x69\x74\x79\x2C\x20\x72\x65\x61\x64\x20\x74\x68\x65\x20\x73\x65\x63\x74\x69\x6F\x6E\x20\x2A\x4C\x65\x67\x61\x6C\x20\x4C\x69\x6D\x69\x74\x61\x74\x69\x6F\x6E\x73\x2A\x20\x6F\x66\x20\x74\x68\x65\x20\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x50\x6F\x6C\x69\x63\x79\x20\x61\x76\x61\x69\x6C\x61\x62\x6C\x65\x20\x61\x74\x20\x68\x74\x74\x70\x3A\x2F\x2F\x63\x65\x72\x74\x2E\x73\x74\x61\x72\x74\x63\x6F\x6D\x2E\x6F\x72\x67\x2F\x70\x6F\x6C\x69\x63\x79\x2E\x70\x64\x66\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x38\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x0D\x04\x2B\x16\x29\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x46\x72\x65\x65\x20\x53\x53\x4C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x16\x6C\x99\xF4\x66\x0C\x34\xF5\xD0\x85\x5E\x7D\x0A\xEC\xDA\x10\x4E\x38\x1C\x5E\xDF\xA6\x25\x05\x4B\x91\x32\xC1\xE8\x3B\xF1\x3D\xDD\x44\x09\x5B\x07\x49\x8A\x29\xCB\x66\x02\xB7\xB1\x9A\xF7\x25\x98\x09\x3C\x8E\x1B\xE1\xDD\x36\x87\x2B\x4B\xBB\x68\xD3\x39\x66\x3D\xA0\x26\xC7\xF2\x39\x91\x1D\x51\xAB\x82\x7B\x7E\xD5\xCE\x5A\xE4\xE2\x03\x57\x70\x69\x97\x08\xF9\x5E\x58\xA6\x0A\xDF\x8C\x06\x9A\x45\x16\x16\x38\x0A\x5E\x57\xF6\x62\xC7\x7A\x02\x05\xE6\xBC\x1E\xB5\xF2\x9E\xF4\xA9\x29\x83\xF8\xB2\x14\xE3\x6E\x28\x87\x44\xC3\x90\x1A\xDE\x38\xA9\x3C\xAC\x43\x4D\x64\x45\xCE\xDD\x28\xA9\x5C\xF2\x73\x7B\x04\xF8\x17\xE8\xAB\xB1\xF3\x2E\x5C\x64\x6E\x73\x31\x3A\x12\xB8\xBC\xB3\x11\xE4\x7D\x8F\x81\x51\x9A\x3B\x8D\x89\xF4\x4D\x93\x66\x7B\x3C\x03\xED\xD3\x9A\x1D\x9A\xF3\x65\x50\xF5\xA0\xD0\x75\x9F\x2F\xAF\xF0\xEA\x82\x43\x98\xF8\x69\x9C\x89\x79\xC4\x43\x8E\x46\x72\xE3\x64\x36\x12\xAF\xF7\x25\x1E\x38\x89\x90\x77\x7E\xC3\x6B\x6A\xB9\xC3\xCB\x44\x4B\xAC\x78\x90\x8B\xE7\xC7\x2C\x1E\x4B\x11\x44\xC8\x34\x52\x27\xCD\x0A\x5D\x9F\x85\xC1\x89\xD5\x1A\x78\xF2\x95\x10\x53\x32\xDD\x80\x84\x66\x75\xD9\xB5\x68\x28\xFB\x61\x2E\xBE\x84\xA8\x38\xC0\x99\x12\x86\xA5\x1E\x67\x64\xAD\x06\x2E\x2F\xA9\x70\x85\xC7\x96\x0F\x7C\x89\x65\xF5\x8E\x43\x54\x0E\xAB\xDD\xA5\x80\x39\x94\x60\xC0\x34\xC9\x96\x70\x2C\xA3\x12\xF5\x1F\x48\x7B\xBD\x1C\x7E\x6B\xB7\x9D\x90\xF4\x22\x3B\xAE\xF8\xFC\x2A\xCA\xFA\x82\x52\xA0\xEF\xAF\x4B\x55\x93\xEB\xC1\xB5\xF0\x22\x8B\xAC\x34\x4E\x26\x22\x04\xA1\x87\x2C\x75\x4A\xB7\xE5\x7D\x13\xD7\xB8\x0C\x64\xC0\x36\xD2\xC9\x2F\x86\x12\x8C\x23\x09\xC1\x1B\x82\x3B\x73\x49\xA3\x6A\x57\x87\x94\xE5\xD6\x78\xC5\x99\x43\x63\xE3\x4D\xE0\x77\x2D\xE1\x65\x99\x72\x69\x04\x1A\x47\x09\xE6\x0F\x01\x56\x24\xFB\x1F\xBF\x0E\x79\xA9\x58\x2E\xB9\xC4\x09\x01\x7E\x95\xBA\x6D\x00\x06\x3E\xB2\xEA\x4A\x10\x39\xD8\xD0\x2B\xF5\xBF\xEC\x75\xBF\x97\x02\xC5\x09\x1B\x08\xDC\x55\x37\xE2\x81\xFB\x37\x84\x43\x62\x20\xCA\xE7\x56\x4B\x65\xEA\xFE\x6C\xC1\x24\x93\x24\xA1\x34\xEB\x05\xFF\x9A\x22\xAE\x9B\x7D\x3F\xF1\x65\x51\x0A\xA6\x30\x6A\xB3\xF4\x88\x1C\x80\x0D\xFC\x72\x8A\xE8\x83\x5E", - ["Taiwan GRCA"] = "\x30\x82\x05\x72\x30\x82\x03\x5A\xA0\x03\x02\x01\x02\x02\x10\x1F\x9D\x59\x5A\xD7\x2F\xC2\x06\x44\xA5\x80\x08\x69\xE3\x5E\xF6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x30\x30\x2E\x06\x03\x55\x04\x0A\x0C\x27\x47\x6F\x76\x65\x72\x6E\x6D\x65\x6E\x74\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x32\x31\x32\x30\x35\x31\x33\x32\x33\x33\x33\x5A\x17\x0D\x33\x32\x31\x32\x30\x35\x31\x33\x32\x33\x33\x33\x5A\x30\x3F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x30\x30\x2E\x06\x03\x55\x04\x0A\x0C\x27\x47\x6F\x76\x65\x72\x6E\x6D\x65\x6E\x74\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\x9A\x25\xB8\xEC\xCC\xA2\x75\xA8\x7B\xF7\xCE\x5B\x59\x8A\xC9\xD1\x86\x12\x08\x54\xEC\x9C\xF2\xE7\x46\xF6\x88\xF3\x7C\xE9\xA5\xDF\x4C\x47\x36\xA4\x1B\x01\x1C\x7F\x1E\x57\x8A\x8D\xC3\xC5\xD1\x21\xE3\xDA\x24\x3F\x48\x2B\xFB\x9F\x2E\xA1\x94\xE7\x2C\x1C\x93\xD1\xBF\x1B\x01\x87\x53\x99\xCE\xA7\xF5\x0A\x21\x76\x77\xFF\xA9\xB7\xC6\x73\x94\x4F\x46\xF7\x10\x49\x37\xFA\xA8\x59\x49\x5D\x6A\x81\x07\x56\xF2\x8A\xF9\x06\xD0\xF7\x70\x22\x4D\xB4\xB7\x41\xB9\x32\xB8\xB1\xF0\xB1\xC3\x9C\x3F\x70\xFD\x53\xDD\x81\xAA\xD8\x63\x78\xF6\xD8\x53\x6E\xA1\xAC\x6A\x84\x24\x72\x54\x86\xC6\xD2\xB2\xCA\x1C\x0E\x79\x81\xD6\xB5\x70\x62\x08\x01\x2E\x4E\x4F\x0E\xD5\x11\xAF\xA9\xAF\xE5\x9A\xBF\xDC\xCC\x87\x6D\x26\xE4\xC9\x57\xA2\xFB\x96\xF9\xCC\xE1\x3F\x53\x8C\x6C\x4C\x7E\x9B\x53\x08\x0B\x6C\x17\xFB\x67\xC8\xC2\xAD\xB1\xCD\x80\xB4\x97\xDC\x76\x01\x16\x15\xE9\x6A\xD7\xA4\xE1\x78\x47\xCE\x86\xD5\xFB\x31\xF3\xFA\x31\xBE\x34\xAA\x28\xFB\x70\x4C\x1D\x49\xC7\xAF\x2C\x9D\x6D\x66\xA6\xB6\x8D\x64\x7E\xB5\x20\x6A\x9D\x3B\x81\xB6\x8F\x40\x00\x67\x4B\x89\x86\xB8\xCC\x65\xFE\x15\x53\xE9\x04\xC1\xD6\x5F\x1D\x44\xD7\x0A\x2F\x27\x9A\x46\x7D\xA1\x0D\x75\xAD\x54\x86\x15\xDC\x49\x3B\xF1\x96\xCE\x0F\x9B\xA0\xEC\xA3\x7A\x5D\xBE\xD5\x2A\x75\x42\xE5\x7B\xDE\xA5\xB6\xAA\xAF\x28\xAC\xAC\x90\xAC\x38\xB7\xD5\x68\x35\x26\x7A\xDC\xF7\x3B\xF3\xFD\x45\x9B\xD1\xBB\x43\x78\x6E\x6F\xF1\x42\x54\x6A\x98\xF0\x0D\xAD\x97\xE9\x52\x5E\xE9\xD5\x6A\x72\xDE\x6A\xF7\x1B\x60\x14\xF4\xA5\xE4\xB6\x71\x67\xAA\x1F\xEA\xE2\x4D\xC1\x42\x40\xFE\x67\x46\x17\x38\x2F\x47\x3F\x71\x9C\xAE\xE5\x21\xCA\x61\x2D\x6D\x07\xA8\x84\x7C\x2D\xEE\x51\x25\xF1\x63\x90\x9E\xFD\xE1\x57\x88\x6B\xEF\x8A\x23\x6D\xB1\xE6\xBD\x3F\xAD\xD1\x3D\x96\x0B\x85\x8D\xCD\x6B\x27\xBB\xB7\x05\x9B\xEC\xBB\x91\xA9\x0A\x07\x12\x02\x97\x4E\x20\x90\xF0\xFF\x0D\x1E\xE2\x41\x3B\xD3\x40\x3A\xE7\x8D\x5D\xDA\x66\xE4\x02\xB0\x07\x52\x98\x5C\x0E\x8E\x33\x9C\xC2\xA6\x95\xFB\x55\x19\x6E\x4C\x8E\xAE\x4B\x0F\xBD\xC1\x38\x4D\x5E\x8F\x84\x1D\x66\xCD\xC5\x60\x96\xB4\x52\x5A\x05\x89\x8E\x95\x7A\x98\xC1\x91\x3C\x95\x23\xB2\x0E\xF4\x79\xB4\xC9\x7C\xC1\x4A\x21\x02\x03\x01\x00\x01\xA3\x6A\x30\x68\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xCC\xCC\xEF\xCC\x29\x60\xA4\x3B\xB1\x92\xB6\x3C\xFA\x32\x62\x8F\xAC\x25\x15\x3B\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x39\x06\x04\x67\x2A\x07\x00\x04\x31\x30\x2F\x30\x2D\x02\x01\x00\x30\x09\x06\x05\x2B\x0E\x03\x02\x1A\x05\x00\x30\x07\x06\x05\x67\x2A\x03\x00\x00\x04\x14\x03\x9B\xF0\x22\x13\xFF\x95\x28\x36\xD3\xDC\x9E\xC0\x32\xFB\x31\x3A\x8A\x51\x65\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x40\x80\x4A\xFA\x26\xC9\xCE\x5E\x30\xDD\x4F\x86\x74\x76\x58\xF5\xAE\xB3\x83\x33\x78\xA4\x7A\x74\x17\x19\x4E\xE9\x52\xB5\xB9\xE0\x0A\x74\x62\xAA\x68\xCA\x78\xA0\x4C\x9A\x8E\x2C\x23\x2E\xD5\x6A\x12\x24\xBF\xD4\x68\xD3\x8A\xD0\xD8\x9C\x9F\xB4\x1F\x0C\xDE\x38\x7E\x57\x38\xFC\x8D\xE2\x4F\x5E\x0C\x9F\xAB\x3B\xD2\xFF\x75\x97\xCB\xA4\xE3\x67\x08\xFF\xE5\xC0\x16\xB5\x48\x01\x7D\xE9\xF9\x0A\xFF\x1B\xE5\x6A\x69\xBF\x78\x21\xA8\xC2\xA7\x23\xA9\x86\xAB\x76\x56\xE8\x0E\x0C\xF6\x13\xDD\x2A\x66\x8A\x64\x49\x3D\x1A\x18\x87\x90\x04\x9F\x42\x52\xB7\x4F\xCB\xFE\x47\x41\x76\x35\xEF\xFF\x00\x76\x36\x45\x32\x9B\xC6\x46\x85\x5D\xE2\x24\xB0\x1E\xE3\x48\x96\x98\x57\x47\x94\x55\x7A\x0F\x41\xB1\x44\x24\xF3\xC1\xFE\x1A\x6B\xBF\x88\xFD\xC1\xA6\xDA\x93\x60\x5E\x81\x4A\x99\x20\x9C\x48\x66\x19\xB5\x00\x79\x54\x0F\xB8\x2C\x2F\x4B\xBC\xA9\x5D\x5B\x60\x7F\x8C\x87\xA5\xE0\x52\x63\x2A\xBE\xD8\x3B\x85\x40\x15\xFE\x1E\xB6\x65\x3F\xC5\x4B\xDA\x7E\xB5\x7A\x35\x29\xA3\x2E\x7A\x98\x60\x22\xA3\xF4\x7D\x27\x4E\x2D\xEA\xB4\x74\x3C\xE9\x0F\xA4\x33\x0F\x10\x11\xBC\x13\x01\xD6\xE5\x0E\xD3\xBF\xB5\x12\xA2\xE1\x45\x23\xC0\xCC\x08\x6E\x61\xB7\x89\xAB\x83\xE3\x24\x1E\xE6\x5D\x07\xE7\x1F\x20\x3E\xCF\x67\xC8\xE7\xAC\x30\x6D\x27\x4B\x68\x6E\x4B\x2A\x5C\x02\x08\x34\xDB\xF8\x76\xE4\x67\xA3\x26\x9C\x3F\xA2\x32\xC2\x4A\xC5\x81\x18\x31\x10\x56\xAA\x84\xEF\x2D\x0A\xFF\xB8\x1F\x77\xD2\xBF\xA5\x58\xA0\x62\xE4\xD7\x4B\x91\x75\x8D\x89\x80\x98\x7E\x6D\xCB\x53\x4E\x5E\xAF\xF6\xB2\x97\x85\x97\xB9\xDA\x55\x06\xB9\x24\xEE\xD7\xC6\x38\x1E\x63\x1B\x12\x3B\x95\xE1\x58\xAC\xF2\xDF\x84\xD5\x5F\x99\x2F\x0D\x55\x5B\xE6\x38\xDB\x2E\x3F\x72\xE9\x48\x85\xCB\xBB\x29\x13\x8F\x1E\x38\x55\xB9\xF3\xB2\xC4\x30\x99\x23\x4E\x5D\xF2\x48\xA1\x12\x0C\xDC\x12\x90\x09\x90\x54\x91\x03\x3C\x47\xE5\xD5\xC9\x65\xE0\xB7\x4B\x7D\xEC\x47\xD3\xB3\x0B\x3E\xAD\x9E\xD0\x74\x00\x0E\xEB\xBD\x51\xAD\xC0\xDE\x2C\xC0\xC3\x6A\xFE\xEF\xDC\x0B\xA7\xFA\x46\xDF\x60\xDB\x9C\xA6\x59\x50\x75\x23\x69\x73\x93\xB2\xF9\xFC\x02\xD3\x47\xE6\x71\xCE\x10\x02\xEE\x27\x8C\x84\xFF\xAC\x45\x0D\x13\x5C\x83\x32\xE0\x25\xA5\x86\x2C\x7C\xF4\x12", - ["Firmaprofesional Root CA"] = "\x30\x82\x04\x57\x30\x82\x03\x3F\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x9D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x22\x30\x20\x06\x03\x55\x04\x07\x13\x19\x43\x2F\x20\x4D\x75\x6E\x74\x61\x6E\x65\x72\x20\x32\x34\x34\x20\x42\x61\x72\x63\x65\x6C\x6F\x6E\x61\x31\x42\x30\x40\x06\x03\x55\x04\x03\x13\x39\x41\x75\x74\x6F\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x46\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x20\x43\x49\x46\x20\x41\x36\x32\x36\x33\x34\x30\x36\x38\x31\x26\x30\x24\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x17\x63\x61\x40\x66\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x30\x31\x31\x30\x32\x34\x32\x32\x30\x30\x30\x30\x5A\x17\x0D\x31\x33\x31\x30\x32\x34\x32\x32\x30\x30\x30\x30\x5A\x30\x81\x9D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x22\x30\x20\x06\x03\x55\x04\x07\x13\x19\x43\x2F\x20\x4D\x75\x6E\x74\x61\x6E\x65\x72\x20\x32\x34\x34\x20\x42\x61\x72\x63\x65\x6C\x6F\x6E\x61\x31\x42\x30\x40\x06\x03\x55\x04\x03\x13\x39\x41\x75\x74\x6F\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x46\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x20\x43\x49\x46\x20\x41\x36\x32\x36\x33\x34\x30\x36\x38\x31\x26\x30\x24\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x17\x63\x61\x40\x66\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x2E\x63\x6F\x6D\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\xE7\x23\x03\x6F\x6F\x23\xA5\x5E\x78\xCE\x95\x2C\xED\x94\x1E\x6E\x0A\x9E\x01\xC7\xEA\x30\xD1\x2C\x9D\xDD\x37\xE8\x9B\x98\x79\x56\xD3\xFC\x73\xDF\xD0\x8A\xDE\x55\x8F\x51\xF9\x5A\xEA\xDE\xB5\x70\xC4\xED\xA4\xED\xFF\xA3\x0D\x6E\x0F\x64\x50\x31\xAF\x01\x27\x58\xAE\xFE\x6C\xA7\x4A\x2F\x17\x2D\xD3\x73\xD5\x13\x1C\x8F\x59\xA5\x34\x2C\x1D\x54\x04\x45\xCD\x68\xB8\xA0\xC0\x03\xA5\xCF\x85\x42\x47\x95\x28\x5B\xCF\xEF\x80\x6C\xE0\x90\x97\x8A\x01\x3C\x1D\xF3\x87\x10\x30\x26\x48\x7D\xD7\xFC\xE9\x9D\x91\x71\xFF\x41\x9A\xA9\x40\xB5\x37\x9C\x29\x20\x4F\x1F\x52\xE3\xA0\x7D\x13\x6D\x54\xB7\x0A\xDE\xE9\x6A\x4E\x07\xAC\xAC\x19\x5F\xDC\x7E\x62\x74\xF6\xB2\x05\x00\xBA\x85\xA0\xFD\x1D\x38\x6E\xCB\x5A\xBB\x86\xBC\x94\x67\x33\x35\x83\x2C\x1F\x23\xCD\xF8\xC8\x91\x71\xCC\x97\x8B\xEF\xAE\x0F\xDC\x29\x03\x1B\xC0\x39\xEB\x70\xED\xC1\x6E\x0E\xD8\x67\x0B\x89\xA9\xBC\x35\xE4\xEF\xB6\x34\xB4\xA5\xB6\xC4\x2D\xA5\xBE\xD0\xC3\x94\x24\x48\xDB\xDF\x96\xD3\x00\xB5\x66\x1A\x8B\x66\x05\x0F\xDD\x3F\x3F\xCB\x3F\xAA\x5E\x9A\x4A\xF8\xB4\x4A\xEF\x95\x37\x1B\x02\x03\x01\x00\x01\xA3\x81\x9F\x30\x81\x9C\x30\x2A\x06\x03\x55\x1D\x11\x04\x23\x30\x21\x86\x1F\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x66\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x2E\x63\x6F\x6D\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x01\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x32\x30\x30\x31\x31\x30\x32\x34\x32\x32\x30\x30\x30\x30\x5A\x81\x0F\x32\x30\x31\x33\x31\x30\x32\x34\x32\x32\x30\x30\x30\x30\x5A\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x33\x0B\xA0\x66\xD1\xEA\xDA\xCE\xDE\x62\x93\x04\x28\x52\xB5\x14\x7F\x38\x68\xB7\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x47\x73\xFE\x8D\x27\x54\xF0\xF5\xD4\x77\x9C\x27\x79\x57\x57\xB7\x15\x56\xEC\xC7\xD8\x58\xB7\x01\x02\xF4\x33\xED\x93\x50\x88\x9E\x7C\x46\xB1\xBD\x3F\x14\x6F\xF1\xB3\x47\x48\x8B\x8C\x97\x06\xD7\xEA\x7E\xA3\x5C\x2A\xBB\x4D\x2F\x47\xE2\xF8\x39\x06\xC9\x9C\x2E\x31\x1A\x03\x78\xF4\xBC\x38\xC6\x22\x8B\x33\x31\xF0\x16\x04\x04\x7D\xF9\x76\xE4\x4B\xD7\xC0\xE6\x83\xEC\x59\xCC\x3F\xDE\xFF\x4F\x6B\xB7\x67\x7E\xA6\x86\x81\x32\x23\x03\x9D\xC8\xF7\x5F\xC1\x4A\x60\xA5\x92\xA9\xB1\xA4\xA0\x60\xC3\x78\x87\xB3\x22\xF3\x2A\xEB\x5B\xA9\xED\x05\xAB\x37\x0F\xB1\xE2\xD3\x95\x76\x63\x56\x74\x8C\x58\x72\x1B\x37\xE5\x64\xA1\xBE\x4D\x0C\x93\x98\x0C\x97\xF6\x87\x6D\xB3\x3F\xE7\xCB\x80\xA6\xED\x88\xC7\x5F\x50\x62\x02\xE8\x99\x74\x16\xD0\xE6\xB4\x39\xF1\x27\xCB\xC8\x40\xD6\xE3\x86\x10\xA9\x23\x12\x92\xE0\x69\x41\x63\xA7\xAF\x25\x0B\xC0\xC5\x92\xCB\x1E\x98\xA3\x5A\xBA\xC5\x33\x0F\xA0\x97\x01\xDD\x7F\xE0\x7B\xD6\x06\x54\xCF\xA1\xE2\x4D\x38\xEB\x4B\x50\xB5\xCB\x26\xF4\xCA\xDA\x70\x4A\x6A\xA1\xE2\x79\xAA\xE1\xA7\x33\xF6\xFD\x4A\x1F\xF6\xD9\x60", - ["Wells Fargo Root CA"] = "\x30\x82\x03\xE5\x30\x82\x02\xCD\xA0\x03\x02\x01\x02\x02\x04\x39\xE4\x97\x9E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x31\x2C\x30\x2A\x06\x03\x55\x04\x0B\x13\x23\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x2F\x30\x2D\x06\x03\x55\x04\x03\x13\x26\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x30\x31\x30\x31\x31\x31\x36\x34\x31\x32\x38\x5A\x17\x0D\x32\x31\x30\x31\x31\x34\x31\x36\x34\x31\x32\x38\x5A\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x31\x2C\x30\x2A\x06\x03\x55\x04\x0B\x13\x23\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x2F\x30\x2D\x06\x03\x55\x04\x03\x13\x26\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xD5\xA8\x33\x3B\x26\xF9\x34\xFF\xCD\x9B\x7E\xE5\x04\x47\xCE\x00\xE2\x7D\x77\xE7\x31\xC2\x2E\x27\xA5\x4D\x68\xB9\x31\xBA\x8D\x43\x59\x97\xC7\x73\xAA\x7F\x3D\x5C\x40\x9E\x05\xE5\xA1\xE2\x89\xD9\x4C\xB8\x3F\x9B\xF9\x0C\xB4\xC8\x62\x19\x2C\x45\xAE\x91\x1E\x73\x71\x41\xC4\x4B\x13\xFD\x70\xC2\x25\xAC\x22\xF5\x75\x0B\xB7\x53\xE4\xA5\x2B\xDD\xCE\xBD\x1C\x3A\x7A\xC3\xF7\x13\x8F\x26\x54\x9C\x16\x6B\x6B\xAF\xFB\xD8\x96\xB1\x60\x9A\x48\xE0\x25\x22\x24\x79\x34\xCE\x0E\x26\x00\x0B\x4E\xAB\xFD\x8B\xCE\x82\xD7\x2F\x08\x70\x68\xC1\xA8\x0A\xF9\x74\x4F\x07\xAB\xA4\xF9\xE2\x83\x7E\x27\x73\x74\x3E\xB8\xF9\x38\x42\xFC\xA5\xA8\x5B\x48\x23\xB3\xEB\xE3\x25\xB2\x80\xAE\x96\xD4\x0A\x9C\xC2\x78\x9A\xC6\x68\x18\xAE\x37\x62\x37\x5E\x51\x75\xA8\x58\x63\xC0\x51\xEE\x40\x78\x7E\xA8\xAF\x1A\xA0\xE1\xB0\x78\x9D\x50\x8C\x7B\xE7\xB3\xFC\x8E\x23\xB0\xDB\x65\x00\x70\x84\x01\x08\x00\x14\x6E\x54\x86\x9A\xBA\xCC\xF9\x37\x10\xF6\xE0\xDE\x84\x2D\x9D\xA4\x85\x37\xD3\x87\xE3\x15\xD0\xC1\x17\x90\x7E\x19\x21\x6A\x12\xA9\x76\xFD\x12\x02\xE9\x4F\x21\x5E\x17\x02\x03\x01\x00\x01\xA3\x61\x30\x5F\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x4C\x06\x03\x55\x1D\x20\x04\x45\x30\x43\x30\x41\x06\x0B\x60\x86\x48\x01\x86\xFB\x7B\x87\x07\x01\x0B\x30\x32\x30\x30\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x24\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x77\x65\x6C\x6C\x73\x66\x61\x72\x67\x6F\x2E\x63\x6F\x6D\x2F\x63\x65\x72\x74\x70\x6F\x6C\x69\x63\x79\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xD2\x27\xDD\x9C\x0A\x77\x2B\xBB\x22\xF2\x02\xB5\x4A\x4A\x91\xF9\xD1\x2D\xBE\xE4\xBB\x1A\x68\xEF\x0E\xA4\x00\xE9\xEE\xE7\xEF\xEE\xF6\xF9\xE5\x74\xA4\xC2\xD8\x52\x58\xC4\x74\xFB\xCE\x6B\xB5\x3B\x29\x79\x18\x5A\xEF\x9B\xED\x1F\x6B\x36\xEE\x48\x25\x25\x14\xB6\x56\xA2\x10\xE8\xEE\xA7\x7F\xD0\x3F\xA3\xD0\xC3\x5D\x26\xEE\x07\xCC\xC3\xC1\x24\x21\x87\x1E\xDF\x2A\x12\x53\x6F\x41\x16\xE7\xED\xAE\x94\xFA\x8C\x72\xFA\x13\x47\xF0\x3C\x7E\xAE\x7D\x11\x3A\x13\xEC\xED\xFA\x6F\x72\x64\x7B\x9D\x7D\x7F\x26\xFD\x7A\xFB\x25\xAD\xEA\x3E\x29\x7F\x4C\xE3\x00\x57\x32\xB0\xB3\xE9\xED\x53\x17\xD9\x8B\xB2\x14\x0E\x30\xE8\xE5\xD5\x13\xC6\x64\xAF\xC4\x00\xD5\xD8\x58\x24\xFC\xF5\x8F\xEC\xF1\xC7\x7D\xA5\xDB\x0F\x27\xD1\xC6\xF2\x40\x88\xE6\x1F\xF6\x61\xA8\xF4\x42\xC8\xB9\x37\xD3\xA9\xBE\x2C\x56\x78\xC2\x72\x9B\x59\x5D\x35\x40\x8A\xE8\x4E\x63\x1A\xB6\xE9\x20\x6A\x51\xE2\xCE\xA4\x90\xDF\x76\x70\x99\x5C\x70\x43\x4D\xB7\xB6\xA7\x19\x64\x4E\x92\xB7\xC5\x91\x3C\x7F\x48\x16\x65\x7B\x16\xFD\xCB\xFC\xFB\xD9\xD5\xD6\x4F\x21\x65\x3B\x4A\x7F\x47\xA3\xFB", - ["Swisscom Root CA 1"] = "\x30\x82\x05\xD9\x30\x82\x03\xC1\xA0\x03\x02\x01\x02\x02\x10\x5C\x0B\x85\x5C\x0B\xE7\x59\x41\xDF\x57\xCC\x3F\x7F\x9D\xA8\x36\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x53\x77\x69\x73\x73\x63\x6F\x6D\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x44\x69\x67\x69\x74\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x53\x77\x69\x73\x73\x63\x6F\x6D\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x31\x30\x1E\x17\x0D\x30\x35\x30\x38\x31\x38\x31\x32\x30\x36\x32\x30\x5A\x17\x0D\x32\x35\x30\x38\x31\x38\x32\x32\x30\x36\x32\x30\x5A\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x53\x77\x69\x73\x73\x63\x6F\x6D\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x44\x69\x67\x69\x74\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x53\x77\x69\x73\x73\x63\x6F\x6D\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x31\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xD0\xB9\xB0\xA8\x0C\xD9\xBB\x3F\x21\xF8\x1B\xD5\x33\x93\x80\x16\x65\x20\x75\xB2\x3D\x9B\x60\x6D\x46\xC8\x8C\x31\x6F\x17\xC3\xFA\x9A\x6C\x56\xED\x3C\xC5\x91\x57\xC3\xCD\xAB\x96\x49\x90\x2A\x19\x4B\x1E\xA3\x6D\x57\xDD\xF1\x2B\x62\x28\x75\x45\x5E\xAA\xD6\x5B\xFA\x0B\x25\xD8\xA1\x16\xF9\x1C\xC4\x2E\xE6\x95\x2A\x67\xCC\xD0\x29\x6E\x3C\x85\x34\x38\x61\x49\xB1\x00\x9F\xD6\x3A\x71\x5F\x4D\x6D\xCE\x5F\xB9\xA9\xE4\x89\x7F\x6A\x52\xFA\xCA\x9B\xF2\xDC\xA9\xF9\x9D\x99\x47\x3F\x4E\x29\x5F\xB4\xA6\x8D\x5D\x7B\x0B\x99\x11\x03\x03\xFE\xE7\xDB\xDB\xA3\xFF\x1D\xA5\xCD\x90\x1E\x01\x1F\x35\xB0\x7F\x00\xDB\x90\x6F\xC6\x7E\x7B\xD1\xEE\x7A\x7A\xA7\xAA\x0C\x57\x6F\xA4\x6D\xC5\x13\x3B\xB0\xA5\xD9\xED\x32\x1C\xB4\x5E\x67\x8B\x54\xDC\x73\x87\xE5\xD3\x17\x7C\x66\x50\x72\x5D\xD4\x1A\x58\xC1\xD9\xCF\xD8\x89\x02\x6F\xA7\x49\xB4\x36\x5D\xD0\xA4\xDE\x07\x2C\xB6\x75\xB7\x28\x91\xD6\x97\xBE\x28\xF5\x98\x1E\xEA\x5B\x26\xC9\xBD\xB0\x97\x73\xDA\xAE\x91\x26\xEB\x68\xC1\xF9\x39\x15\xD6\x67\x4B\x0A\x6D\x4F\xCB\xCF\xB0\xE4\x42\x71\x8C\x53\x79\xE7\xEE\xE1\xDB\x1D\xA0\x6E\x1D\x8C\x1A\x77\x35\x5C\x16\x1E\x2B\x53\x1F\x34\x8B\xD1\x6C\xFC\xF2\x67\x07\x7A\xF5\xAD\xED\xD6\x9A\xAB\xA1\xB1\x4B\xE1\xCC\x37\x5F\xFD\x7F\xCD\x4D\xAE\xB8\x1F\x9C\x43\xF9\x2A\x58\x55\x43\x45\xBC\x96\xCD\x70\x0E\xFC\xC9\xE3\x66\xBA\x4E\x8D\x3B\x81\xCB\x15\x64\x7B\xB9\x94\xE8\x5D\x33\x52\x85\x71\x2E\x4F\x8E\xA2\x06\x11\x51\xC9\xE3\xCB\xA1\x6E\x31\x08\x64\x0C\xC2\xD2\x3C\xF5\x36\xE8\xD7\xD0\x0E\x78\x23\x20\x91\xC9\x24\x2A\x65\x29\x5B\x22\xF7\x21\xCE\x83\x5E\xA4\xF3\xDE\x4B\xD3\x68\x8F\x46\x75\x5C\x83\x09\x6E\x29\x6B\xC4\x70\x8C\xF5\x9D\xD7\x20\x2F\xFF\x46\xD2\x2B\x38\xC2\x2F\x75\x1C\x3D\x7E\xDA\xA5\xEF\x1E\x60\x85\x69\x42\xD3\xCC\xF8\x63\xFE\x1E\x43\x39\x85\xA6\xB6\x63\x41\x10\xB3\x73\x1E\xBC\xD3\xFA\xCA\x7D\x16\x47\xE2\xA7\xD5\xD0\xA3\x8A\x0A\x08\x96\x62\x56\x6E\x34\xDB\xD9\x02\xB9\x30\x75\xE3\x04\xD2\xE7\x8F\xC2\xB0\x11\x40\x0A\xAC\xD5\x71\x02\x62\x8B\x31\xBE\xDD\xC6\x23\x58\x31\x42\x43\x2D\x74\xF9\xC6\x9E\xA6\x8A\x0F\xE9\xFE\xBF\x83\xE6\x43\x57\x24\xBA\xEF\x46\x34\xAA\xD7\x12\x01\x38\xED\x02\x03\x01\x00\x01\xA3\x81\x86\x30\x81\x83\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x1D\x06\x03\x55\x1D\x21\x04\x16\x30\x14\x30\x12\x06\x07\x60\x85\x74\x01\x53\x00\x01\x06\x07\x60\x85\x74\x01\x53\x00\x01\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x07\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x03\x25\x2F\xDE\x6F\x82\x01\x3A\x5C\x2C\xDC\x2B\xA1\x69\xB5\x67\xD4\x8C\xD3\xFD\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x03\x25\x2F\xDE\x6F\x82\x01\x3A\x5C\x2C\xDC\x2B\xA1\x69\xB5\x67\xD4\x8C\xD3\xFD\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x35\x10\xCB\xEC\xA6\x04\x0D\x0D\x0F\xCD\xC0\xDB\xAB\xA8\xF2\x88\x97\x0C\xDF\x93\x2F\x4D\x7C\x40\x56\x31\x7A\xEB\xA4\x0F\x60\xCD\x7A\xF3\xBE\xC3\x27\x8E\x03\x3E\xA4\xDD\x12\xEF\x7E\x1E\x74\x06\x3C\x3F\x31\xF2\x1C\x7B\x91\x31\x21\xB4\xF0\xD0\x6C\x97\xD4\xE9\x97\xB2\x24\x56\x1E\x56\xC3\x35\xBD\x88\x05\x0F\x5B\x10\x1A\x64\xE1\xC7\x82\x30\xF9\x32\xAD\x9E\x50\x2C\xE7\x78\x05\xD0\x31\xB1\x5A\x98\x8A\x75\x4E\x90\x5C\x6A\x14\x2A\xE0\x52\x47\x82\x60\xE6\x1E\xDA\x81\xB1\xFB\x14\x0B\x5A\xF1\x9F\xD2\x95\xBA\x3E\xD0\x1B\xD6\x15\x1D\xA3\xBE\x86\xD5\xDB\x0F\xC0\x49\x64\xBB\x2E\x50\x19\x4B\xD2\x24\xF8\xDD\x1E\x07\x56\xD0\x38\xA0\x95\x70\x20\x76\x8C\xD7\xDD\x1E\xDE\x9F\x71\xC4\x23\xEF\x83\x13\x5C\xA3\x24\x15\x4D\x29\x40\x3C\x6A\xC4\xA9\xD8\xB7\xA6\x44\xA5\x0D\xF4\xE0\x9D\x77\x1E\x40\x70\x26\xFC\xDA\xD9\x36\xE4\x79\xE4\xB5\x3F\xBC\x9B\x65\xBE\xBB\x11\x96\xCF\xDB\xC6\x28\x39\x3A\x08\xCE\x47\x5B\x53\x5A\xC5\x99\xFE\x5D\xA9\xDD\xEF\x4C\xD4\xC6\xA5\xAD\x02\xE6\x8C\x07\x12\x1E\x6F\x03\xD1\x6F\xA0\xA3\xF3\x29\xBD\x12\xC7\x50\xA2\xB0\x7F\x88\xA9\x99\x77\x9A\xB1\xC0\xA5\x39\x2E\x5C\x7C\x69\xE2\x2C\xB0\xEA\x37\x6A\xA4\xE1\x5A\xE1\xF5\x50\xE5\x83\xEF\xA5\xBB\x2A\x88\xE7\x8C\xDB\xFD\x6D\x5E\x97\x19\xA8\x7E\x66\x75\x6B\x71\xEA\xBF\xB1\xC7\x6F\xA0\xF4\x8E\xA4\xEC\x34\x51\x5B\x8C\x26\x03\x70\xA1\x77\xD5\x01\x12\x57\x00\x35\xDB\x23\xDE\x0E\x8A\x28\x99\xFD\xB1\x10\x6F\x4B\xFF\x38\x2D\x60\x4E\x2C\x9C\xEB\x67\xB5\xAD\x49\xEE\x4B\x1F\xAC\xAF\xFB\x0D\x90\x5A\x66\x60\x70\x5D\xAA\xCD\x78\xD4\x24\xEE\xC8\x41\xA0\x93\x01\x92\x9C\x6A\x9E\xFC\xB9\x24\xC5\xB3\x15\x82\x7E\xBE\xAE\x95\x2B\xEB\xB1\xC0\xDA\xE3\x01\x60\x0B\x5E\x69\xAC\x84\x56\x61\xBE\x71\x17\xFE\x1D\x13\x0F\xFE\xC6\x87\x45\xE9\xFE\x32\xA0\x1A\x0D\x13\xA4\x94\x55\x71\xA5\x16\x8B\xBA\xCA\x89\xB0\xB2\xC7\xFC\x8F\xD8\x54\xB5\x93\x62\x9D\xCE\xCF\x59\xFB\x3D\x18\xCE\x2A\xCB\x35\x15\x82\x5D\xFF\x54\x22\x5B\x71\x52\xFB\xB7\xC9\xFE\x60\x9B\x00\x41\x64\xF0\xAA\x2A\xEC\xB6\x42\x43\xCE\x89\x66\x81\xC8\x8B\x9F\x39\x54\x03\x25\xD3\x16\x35\x8E\x84\xD0\x5F\xFA\x30\x1A\xF5\x9A\x6C\xF4\x0E\x53\xF9\x3A\x5B\xD1\x1C", - ["DigiCert Assured ID Root CA"] = "\x30\x82\x03\xB7\x30\x82\x02\x9F\xA0\x03\x02\x01\x02\x02\x10\x0C\xE7\xE0\xE5\x17\xD8\x46\xFE\x8F\xE5\x60\xFC\x1B\xF0\x30\x39\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6E\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x77\x77\x77\x2E\x64\x69\x67\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1B\x44\x69\x67\x69\x43\x65\x72\x74\x20\x41\x73\x73\x75\x72\x65\x64\x20\x49\x44\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x31\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5A\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6E\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x77\x77\x77\x2E\x64\x69\x67\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1B\x44\x69\x67\x69\x43\x65\x72\x74\x20\x41\x73\x73\x75\x72\x65\x64\x20\x49\x44\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xAD\x0E\x15\xCE\xE4\x43\x80\x5C\xB1\x87\xF3\xB7\x60\xF9\x71\x12\xA5\xAE\xDC\x26\x94\x88\xAA\xF4\xCE\xF5\x20\x39\x28\x58\x60\x0C\xF8\x80\xDA\xA9\x15\x95\x32\x61\x3C\xB5\xB1\x28\x84\x8A\x8A\xDC\x9F\x0A\x0C\x83\x17\x7A\x8F\x90\xAC\x8A\xE7\x79\x53\x5C\x31\x84\x2A\xF6\x0F\x98\x32\x36\x76\xCC\xDE\xDD\x3C\xA8\xA2\xEF\x6A\xFB\x21\xF2\x52\x61\xDF\x9F\x20\xD7\x1F\xE2\xB1\xD9\xFE\x18\x64\xD2\x12\x5B\x5F\xF9\x58\x18\x35\xBC\x47\xCD\xA1\x36\xF9\x6B\x7F\xD4\xB0\x38\x3E\xC1\x1B\xC3\x8C\x33\xD9\xD8\x2F\x18\xFE\x28\x0F\xB3\xA7\x83\xD6\xC3\x6E\x44\xC0\x61\x35\x96\x16\xFE\x59\x9C\x8B\x76\x6D\xD7\xF1\xA2\x4B\x0D\x2B\xFF\x0B\x72\xDA\x9E\x60\xD0\x8E\x90\x35\xC6\x78\x55\x87\x20\xA1\xCF\xE5\x6D\x0A\xC8\x49\x7C\x31\x98\x33\x6C\x22\xE9\x87\xD0\x32\x5A\xA2\xBA\x13\x82\x11\xED\x39\x17\x9D\x99\x3A\x72\xA1\xE6\xFA\xA4\xD9\xD5\x17\x31\x75\xAE\x85\x7D\x22\xAE\x3F\x01\x46\x86\xF6\x28\x79\xC8\xB1\xDA\xE4\x57\x17\xC4\x7E\x1C\x0E\xB0\xB4\x92\xA6\x56\xB3\xBD\xB2\x97\xED\xAA\xA7\xF0\xB7\xC5\xA8\x3F\x95\x16\xD0\xFF\xA1\x96\xEB\x08\x5F\x18\x77\x4F\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x45\xEB\xA2\xAF\xF4\x92\xCB\x82\x31\x2D\x51\x8B\xA7\xA7\x21\x9D\xF3\x6D\xC8\x0F\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x45\xEB\xA2\xAF\xF4\x92\xCB\x82\x31\x2D\x51\x8B\xA7\xA7\x21\x9D\xF3\x6D\xC8\x0F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA2\x0E\xBC\xDF\xE2\xED\xF0\xE3\x72\x73\x7A\x64\x94\xBF\xF7\x72\x66\xD8\x32\xE4\x42\x75\x62\xAE\x87\xEB\xF2\xD5\xD9\xDE\x56\xB3\x9F\xCC\xCE\x14\x28\xB9\x0D\x97\x60\x5C\x12\x4C\x58\xE4\xD3\x3D\x83\x49\x45\x58\x97\x35\x69\x1A\xA8\x47\xEA\x56\xC6\x79\xAB\x12\xD8\x67\x81\x84\xDF\x7F\x09\x3C\x94\xE6\xB8\x26\x2C\x20\xBD\x3D\xB3\x28\x89\xF7\x5F\xFF\x22\xE2\x97\x84\x1F\xE9\x65\xEF\x87\xE0\xDF\xC1\x67\x49\xB3\x5D\xEB\xB2\x09\x2A\xEB\x26\xED\x78\xBE\x7D\x3F\x2B\xF3\xB7\x26\x35\x6D\x5F\x89\x01\xB6\x49\x5B\x9F\x01\x05\x9B\xAB\x3D\x25\xC1\xCC\xB6\x7F\xC2\xF1\x6F\x86\xC6\xFA\x64\x68\xEB\x81\x2D\x94\xEB\x42\xB7\xFA\x8C\x1E\xDD\x62\xF1\xBE\x50\x67\xB7\x6C\xBD\xF3\xF1\x1F\x6B\x0C\x36\x07\x16\x7F\x37\x7C\xA9\x5B\x6D\x7A\xF1\x12\x46\x60\x83\xD7\x27\x04\xBE\x4B\xCE\x97\xBE\xC3\x67\x2A\x68\x11\xDF\x80\xE7\x0C\x33\x66\xBF\x13\x0D\x14\x6E\xF3\x7F\x1F\x63\x10\x1E\xFA\x8D\x1B\x25\x6D\x6C\x8F\xA5\xB7\x61\x01\xB1\xD2\xA3\x26\xA1\x10\x71\x9D\xAD\xE2\xC3\xF9\xC3\x99\x51\xB7\x2B\x07\x08\xCE\x2E\xE6\x50\xB2\xA7\xFA\x0A\x45\x2F\xA2\xF0\xF2", - ["DigiCert Global Root CA"] = "\x30\x82\x03\xAF\x30\x82\x02\x97\xA0\x03\x02\x01\x02\x02\x10\x08\x3B\xE0\x56\x90\x42\x46\xB1\xA1\x75\x6A\xC9\x59\x91\xC7\x4A\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x61\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6E\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x77\x77\x77\x2E\x64\x69\x67\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x44\x69\x67\x69\x43\x65\x72\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x31\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5A\x30\x61\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6E\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x77\x77\x77\x2E\x64\x69\x67\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x44\x69\x67\x69\x43\x65\x72\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xE2\x3B\xE1\x11\x72\xDE\xA8\xA4\xD3\xA3\x57\xAA\x50\xA2\x8F\x0B\x77\x90\xC9\xA2\xA5\xEE\x12\xCE\x96\x5B\x01\x09\x20\xCC\x01\x93\xA7\x4E\x30\xB7\x53\xF7\x43\xC4\x69\x00\x57\x9D\xE2\x8D\x22\xDD\x87\x06\x40\x00\x81\x09\xCE\xCE\x1B\x83\xBF\xDF\xCD\x3B\x71\x46\xE2\xD6\x66\xC7\x05\xB3\x76\x27\x16\x8F\x7B\x9E\x1E\x95\x7D\xEE\xB7\x48\xA3\x08\xDA\xD6\xAF\x7A\x0C\x39\x06\x65\x7F\x4A\x5D\x1F\xBC\x17\xF8\xAB\xBE\xEE\x28\xD7\x74\x7F\x7A\x78\x99\x59\x85\x68\x6E\x5C\x23\x32\x4B\xBF\x4E\xC0\xE8\x5A\x6D\xE3\x70\xBF\x77\x10\xBF\xFC\x01\xF6\x85\xD9\xA8\x44\x10\x58\x32\xA9\x75\x18\xD5\xD1\xA2\xBE\x47\xE2\x27\x6A\xF4\x9A\x33\xF8\x49\x08\x60\x8B\xD4\x5F\xB4\x3A\x84\xBF\xA1\xAA\x4A\x4C\x7D\x3E\xCF\x4F\x5F\x6C\x76\x5E\xA0\x4B\x37\x91\x9E\xDC\x22\xE6\x6D\xCE\x14\x1A\x8E\x6A\xCB\xFE\xCD\xB3\x14\x64\x17\xC7\x5B\x29\x9E\x32\xBF\xF2\xEE\xFA\xD3\x0B\x42\xD4\xAB\xB7\x41\x32\xDA\x0C\xD4\xEF\xF8\x81\xD5\xBB\x8D\x58\x3F\xB5\x1B\xE8\x49\x28\xA2\x70\xDA\x31\x04\xDD\xF7\xB2\x16\xF2\x4C\x0A\x4E\x07\xA8\xED\x4A\x3D\x5E\xB5\x7F\xA3\x90\xC3\xAF\x27\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x03\xDE\x50\x35\x56\xD1\x4C\xBB\x66\xF0\xA3\xE2\x1B\x1B\xC3\x97\xB2\x3D\xD1\x55\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x03\xDE\x50\x35\x56\xD1\x4C\xBB\x66\xF0\xA3\xE2\x1B\x1B\xC3\x97\xB2\x3D\xD1\x55\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xCB\x9C\x37\xAA\x48\x13\x12\x0A\xFA\xDD\x44\x9C\x4F\x52\xB0\xF4\xDF\xAE\x04\xF5\x79\x79\x08\xA3\x24\x18\xFC\x4B\x2B\x84\xC0\x2D\xB9\xD5\xC7\xFE\xF4\xC1\x1F\x58\xCB\xB8\x6D\x9C\x7A\x74\xE7\x98\x29\xAB\x11\xB5\xE3\x70\xA0\xA1\xCD\x4C\x88\x99\x93\x8C\x91\x70\xE2\xAB\x0F\x1C\xBE\x93\xA9\xFF\x63\xD5\xE4\x07\x60\xD3\xA3\xBF\x9D\x5B\x09\xF1\xD5\x8E\xE3\x53\xF4\x8E\x63\xFA\x3F\xA7\xDB\xB4\x66\xDF\x62\x66\xD6\xD1\x6E\x41\x8D\xF2\x2D\xB5\xEA\x77\x4A\x9F\x9D\x58\xE2\x2B\x59\xC0\x40\x23\xED\x2D\x28\x82\x45\x3E\x79\x54\x92\x26\x98\xE0\x80\x48\xA8\x37\xEF\xF0\xD6\x79\x60\x16\xDE\xAC\xE8\x0E\xCD\x6E\xAC\x44\x17\x38\x2F\x49\xDA\xE1\x45\x3E\x2A\xB9\x36\x53\xCF\x3A\x50\x06\xF7\x2E\xE8\xC4\x57\x49\x6C\x61\x21\x18\xD5\x04\xAD\x78\x3C\x2C\x3A\x80\x6B\xA7\xEB\xAF\x15\x14\xE9\xD8\x89\xC1\xB9\x38\x6C\xE2\x91\x6C\x8A\xFF\x64\xB9\x77\x25\x57\x30\xC0\x1B\x24\xA3\xE1\xDC\xE9\xDF\x47\x7C\xB5\xB4\x24\x08\x05\x30\xEC\x2D\xBD\x0B\xBF\x45\xBF\x50\xB9\xA9\xF3\xEB\x98\x01\x12\xAD\xC8\x88\xC6\x98\x34\x5F\x8D\x0A\x3C\xC6\xE9\xD5\x95\x95\x6D\xDE", - ["DigiCert High Assurance EV Root CA"] = "\x30\x82\x03\xC5\x30\x82\x02\xAD\xA0\x03\x02\x01\x02\x02\x10\x02\xAC\x5C\x26\x6A\x0B\x40\x9B\x8F\x0B\x79\xF2\xAE\x46\x25\x77\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x6C\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6E\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x77\x77\x77\x2E\x64\x69\x67\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x31\x2B\x30\x29\x06\x03\x55\x04\x03\x13\x22\x44\x69\x67\x69\x43\x65\x72\x74\x20\x48\x69\x67\x68\x20\x41\x73\x73\x75\x72\x61\x6E\x63\x65\x20\x45\x56\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x31\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5A\x30\x6C\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6E\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x77\x77\x77\x2E\x64\x69\x67\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x31\x2B\x30\x29\x06\x03\x55\x04\x03\x13\x22\x44\x69\x67\x69\x43\x65\x72\x74\x20\x48\x69\x67\x68\x20\x41\x73\x73\x75\x72\x61\x6E\x63\x65\x20\x45\x56\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xC6\xCC\xE5\x73\xE6\xFB\xD4\xBB\xE5\x2D\x2D\x32\xA6\xDF\xE5\x81\x3F\xC9\xCD\x25\x49\xB6\x71\x2A\xC3\xD5\x94\x34\x67\xA2\x0A\x1C\xB0\x5F\x69\xA6\x40\xB1\xC4\xB7\xB2\x8F\xD0\x98\xA4\xA9\x41\x59\x3A\xD3\xDC\x94\xD6\x3C\xDB\x74\x38\xA4\x4A\xCC\x4D\x25\x82\xF7\x4A\xA5\x53\x12\x38\xEE\xF3\x49\x6D\x71\x91\x7E\x63\xB6\xAB\xA6\x5F\xC3\xA4\x84\xF8\x4F\x62\x51\xBE\xF8\xC5\xEC\xDB\x38\x92\xE3\x06\xE5\x08\x91\x0C\xC4\x28\x41\x55\xFB\xCB\x5A\x89\x15\x7E\x71\xE8\x35\xBF\x4D\x72\x09\x3D\xBE\x3A\x38\x50\x5B\x77\x31\x1B\x8D\xB3\xC7\x24\x45\x9A\xA7\xAC\x6D\x00\x14\x5A\x04\xB7\xBA\x13\xEB\x51\x0A\x98\x41\x41\x22\x4E\x65\x61\x87\x81\x41\x50\xA6\x79\x5C\x89\xDE\x19\x4A\x57\xD5\x2E\xE6\x5D\x1C\x53\x2C\x7E\x98\xCD\x1A\x06\x16\xA4\x68\x73\xD0\x34\x04\x13\x5C\xA1\x71\xD3\x5A\x7C\x55\xDB\x5E\x64\xE1\x37\x87\x30\x56\x04\xE5\x11\xB4\x29\x80\x12\xF1\x79\x39\x88\xA2\x02\x11\x7C\x27\x66\xB7\x88\xB7\x78\xF2\xCA\x0A\xA8\x38\xAB\x0A\x64\xC2\xBF\x66\x5D\x95\x84\xC1\xA1\x25\x1E\x87\x5D\x1A\x50\x0B\x20\x12\xCC\x41\xBB\x6E\x0B\x51\x38\xB8\x4B\xCB\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB1\x3E\xC3\x69\x03\xF8\xBF\x47\x01\xD4\x98\x26\x1A\x08\x02\xEF\x63\x64\x2B\xC3\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xB1\x3E\xC3\x69\x03\xF8\xBF\x47\x01\xD4\x98\x26\x1A\x08\x02\xEF\x63\x64\x2B\xC3\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x1C\x1A\x06\x97\xDC\xD7\x9C\x9F\x3C\x88\x66\x06\x08\x57\x21\xDB\x21\x47\xF8\x2A\x67\xAA\xBF\x18\x32\x76\x40\x10\x57\xC1\x8A\xF3\x7A\xD9\x11\x65\x8E\x35\xFA\x9E\xFC\x45\xB5\x9E\xD9\x4C\x31\x4B\xB8\x91\xE8\x43\x2C\x8E\xB3\x78\xCE\xDB\xE3\x53\x79\x71\xD6\xE5\x21\x94\x01\xDA\x55\x87\x9A\x24\x64\xF6\x8A\x66\xCC\xDE\x9C\x37\xCD\xA8\x34\xB1\x69\x9B\x23\xC8\x9E\x78\x22\x2B\x70\x43\xE3\x55\x47\x31\x61\x19\xEF\x58\xC5\x85\x2F\x4E\x30\xF6\xA0\x31\x16\x23\xC8\xE7\xE2\x65\x16\x33\xCB\xBF\x1A\x1B\xA0\x3D\xF8\xCA\x5E\x8B\x31\x8B\x60\x08\x89\x2D\x0C\x06\x5C\x52\xB7\xC4\xF9\x0A\x98\xD1\x15\x5F\x9F\x12\xBE\x7C\x36\x63\x38\xBD\x44\xA4\x7F\xE4\x26\x2B\x0A\xC4\x97\x69\x0D\xE9\x8C\xE2\xC0\x10\x57\xB8\xC8\x76\x12\x91\x55\xF2\x48\x69\xD8\xBC\x2A\x02\x5B\x0F\x44\xD4\x20\x31\xDB\xF4\xBA\x70\x26\x5D\x90\x60\x9E\xBC\x4B\x17\x09\x2F\xB4\xCB\x1E\x43\x68\xC9\x07\x27\xC1\xD2\x5C\xF7\xEA\x21\xB9\x68\x12\x9C\x3C\x9C\xBF\x9E\xFC\x80\x5C\x9B\x63\xCD\xEC\x47\xAA\x25\x27\x67\xA0\x37\xF3\x00\x82\x7D\x54\xD7\xA9\xF8\xE9\x2E\x13\xA3\x77\xE8\x1F\x4A", - ["Certplus Class 2 Primary CA"] = "\x30\x82\x03\x92\x30\x82\x02\x7A\xA0\x03\x02\x01\x02\x02\x11\x00\x85\xBD\x4B\xF3\xD8\xDA\xE3\x69\xF6\x94\xD7\x5F\xC3\xA5\x44\x23\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x43\x65\x72\x74\x70\x6C\x75\x73\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x43\x6C\x61\x73\x73\x20\x32\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x41\x30\x1E\x17\x0D\x39\x39\x30\x37\x30\x37\x31\x37\x30\x35\x30\x30\x5A\x17\x0D\x31\x39\x30\x37\x30\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x3D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x43\x65\x72\x74\x70\x6C\x75\x73\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x43\x6C\x61\x73\x73\x20\x32\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x41\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\xDC\x50\x96\xD0\x12\xF8\x35\xD2\x08\x78\x7A\xB6\x52\x70\xFD\x6F\xEE\xCF\xB9\x11\xCB\x5D\x77\xE1\xEC\xE9\x7E\x04\x8D\xD6\xCC\x6F\x73\x43\x57\x60\xAC\x33\x0A\x44\xEC\x03\x5F\x1C\x80\x24\x91\xE5\xA8\x91\x56\x12\x82\xF7\xE0\x2B\xF4\xDB\xAE\x61\x2E\x89\x10\x8D\x6B\x6C\xBA\xB3\x02\xBD\xD5\x36\xC5\x48\x37\x23\xE2\xF0\x5A\x37\x52\x33\x17\x12\xE2\xD1\x60\x4D\xBE\x2F\x41\x11\xE3\xF6\x17\x25\x0C\x8B\x91\xC0\x1B\x99\x7B\x99\x56\x0D\xAF\xEE\xD2\xBC\x47\x57\xE3\x79\x49\x7B\x34\x89\x27\x24\x84\xDE\xB1\xEC\xE9\x58\x4E\xFE\x4E\xDF\x5A\xBE\x41\xAD\xAC\x08\xC5\x18\x0E\xEF\xD2\x53\xEE\x6C\xD0\x9D\x12\x01\x13\x8D\xDC\x80\x62\xF7\x95\xA9\x44\x88\x4A\x71\x4E\x60\x55\x9E\xDB\x23\x19\x79\x56\x07\x0C\x3F\x63\x0B\x5C\xB0\xE2\xBE\x7E\x15\xFC\x94\x33\x58\x41\x38\x74\xC4\xE1\x8F\x8B\xDF\x26\xAC\x1F\xB5\x8B\x3B\xB7\x43\x59\x6B\xB0\x24\xA6\x6D\x90\x8B\xC4\x72\xEA\x5D\x33\x98\xB7\xCB\xDE\x5E\x7B\xEF\x94\xF1\x1B\x3E\xCA\xC9\x21\xC1\xC5\x98\x02\xAA\xA2\xF6\x5B\x77\x9B\xF5\x7E\x96\x55\x34\x1C\x67\x69\xC0\xF1\x42\xE3\x47\xAC\xFC\x28\x1C\x66\x55\x02\x03\x01\x00\x01\xA3\x81\x8C\x30\x81\x89\x30\x0F\x06\x03\x55\x1D\x13\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x0A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE3\x73\x2D\xDF\xCB\x0E\x28\x0C\xDE\xDD\xB3\xA4\xCA\x79\xB8\x8E\xBB\xE8\x30\x89\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x01\x06\x30\x37\x06\x03\x55\x1D\x1F\x04\x30\x30\x2E\x30\x2C\xA0\x2A\xA0\x28\x86\x26\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x65\x72\x74\x70\x6C\x75\x73\x2E\x63\x6F\x6D\x2F\x43\x52\x4C\x2F\x63\x6C\x61\x73\x73\x32\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA7\x54\xCF\x88\x44\x19\xCB\xDF\xD4\x7F\x00\xDF\x56\x33\x62\xB5\xF7\x51\x01\x90\xEB\xC3\x3F\xD1\x88\x44\xE9\x24\x5D\xEF\xE7\x14\xBD\x20\xB7\x9A\x3C\x00\xFE\x6D\x9F\xDB\x90\xDC\xD7\xF4\x62\xD6\x8B\x70\x5D\xE7\xE5\x04\x48\xA9\x68\x7C\xC9\xF1\x42\xF3\x6C\x7F\xC5\x7A\x7C\x1D\x51\x88\xBA\xD2\x0A\x3E\x27\x5D\xDE\x2D\x51\x4E\xD3\x13\x64\x69\xE4\x2E\xE3\xD3\xE7\x9B\x09\x99\xA6\xE0\x95\x9B\xCE\x1A\xD7\x7F\xBE\x3C\xCE\x52\xB3\x11\x15\xC1\x0F\x17\xCD\x03\xBB\x9C\x25\x15\xBA\xA2\x76\x89\xFC\x06\xF1\x18\xD0\x93\x4B\x0E\x7C\x82\xB7\xA5\xF4\xF6\x5F\xFE\xED\x40\xA6\x9D\x84\x74\x39\xB9\xDC\x1E\x85\x16\xDA\x29\x1B\x86\x23\x00\xC9\xBB\x89\x7E\x6E\x80\x88\x1E\x2F\x14\xB4\x03\x24\xA8\x32\x6F\x03\x9A\x47\x2C\x30\xBE\x56\xC6\xA7\x42\x02\x70\x1B\xEA\x40\xD8\xBA\x05\x03\x70\x07\xA4\x96\xFF\xFD\x48\x33\x0A\xE1\xDC\xA5\x81\x90\x9B\x4D\xDD\x7D\xE7\xE7\xB2\xCD\x5C\xC8\x6A\x95\xF8\xA5\xF6\x8D\xC4\x5D\x78\x08\xBE\x7B\x06\xD6\x49\xCF\x19\x36\x50\x23\x2E\x08\xE6\x9E\x05\x4D\x47\x18\xD5\x16\xE9\xB1\xD6\xB6\x10\xD5\xBB\x97\xBF\xA2\x8E\xB4\x54", - ["DST Root CA X3"] = "\x30\x82\x03\x4A\x30\x82\x02\x32\xA0\x03\x02\x01\x02\x02\x10\x44\xAF\xB0\x80\xD6\xA3\x27\xBA\x89\x30\x39\x86\x2E\xF8\x40\x6B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3F\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0E\x44\x53\x54\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x58\x33\x30\x1E\x17\x0D\x30\x30\x30\x39\x33\x30\x32\x31\x31\x32\x31\x39\x5A\x17\x0D\x32\x31\x30\x39\x33\x30\x31\x34\x30\x31\x31\x35\x5A\x30\x3F\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0E\x44\x53\x54\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x58\x33\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\xDF\xAF\xE9\x97\x50\x08\x83\x57\xB4\xCC\x62\x65\xF6\x90\x82\xEC\xC7\xD3\x2C\x6B\x30\xCA\x5B\xEC\xD9\xC3\x7D\xC7\x40\xC1\x18\x14\x8B\xE0\xE8\x33\x76\x49\x2A\xE3\x3F\x21\x49\x93\xAC\x4E\x0E\xAF\x3E\x48\xCB\x65\xEE\xFC\xD3\x21\x0F\x65\xD2\x2A\xD9\x32\x8F\x8C\xE5\xF7\x77\xB0\x12\x7B\xB5\x95\xC0\x89\xA3\xA9\xBA\xED\x73\x2E\x7A\x0C\x06\x32\x83\xA2\x7E\x8A\x14\x30\xCD\x11\xA0\xE1\x2A\x38\xB9\x79\x0A\x31\xFD\x50\xBD\x80\x65\xDF\xB7\x51\x63\x83\xC8\xE2\x88\x61\xEA\x4B\x61\x81\xEC\x52\x6B\xB9\xA2\xE2\x4B\x1A\x28\x9F\x48\xA3\x9E\x0C\xDA\x09\x8E\x3E\x17\x2E\x1E\xDD\x20\xDF\x5B\xC6\x2A\x8A\xAB\x2E\xBD\x70\xAD\xC5\x0B\x1A\x25\x90\x74\x72\xC5\x7B\x6A\xAB\x34\xD6\x30\x89\xFF\xE5\x68\x13\x7B\x54\x0B\xC8\xD6\xAE\xEC\x5A\x9C\x92\x1E\x3D\x64\xB3\x8C\xC6\xDF\xBF\xC9\x41\x70\xEC\x16\x72\xD5\x26\xEC\x38\x55\x39\x43\xD0\xFC\xFD\x18\x5C\x40\xF1\x97\xEB\xD5\x9A\x9B\x8D\x1D\xBA\xDA\x25\xB9\xC6\xD8\xDF\xC1\x15\x02\x3A\xAB\xDA\x6E\xF1\x3E\x2E\xF5\x5C\x08\x9C\x3C\xD6\x83\x69\xE4\x10\x9B\x19\x2A\xB6\x29\x57\xE3\xE5\x3D\x9B\x9F\xF0\x02\x5D\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC4\xA7\xB1\xA4\x7B\x2C\x71\xFA\xDB\xE1\x4B\x90\x75\xFF\xC4\x15\x60\x85\x89\x10\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA3\x1A\x2C\x9B\x17\x00\x5C\xA9\x1E\xEE\x28\x66\x37\x3A\xBF\x83\xC7\x3F\x4B\xC3\x09\xA0\x95\x20\x5D\xE3\xD9\x59\x44\xD2\x3E\x0D\x3E\xBD\x8A\x4B\xA0\x74\x1F\xCE\x10\x82\x9C\x74\x1A\x1D\x7E\x98\x1A\xDD\xCB\x13\x4B\xB3\x20\x44\xE4\x91\xE9\xCC\xFC\x7D\xA5\xDB\x6A\xE5\xFE\xE6\xFD\xE0\x4E\xDD\xB7\x00\x3A\xB5\x70\x49\xAF\xF2\xE5\xEB\x02\xF1\xD1\x02\x8B\x19\xCB\x94\x3A\x5E\x48\xC4\x18\x1E\x58\x19\x5F\x1E\x02\x5A\xF0\x0C\xF1\xB1\xAD\xA9\xDC\x59\x86\x8B\x6E\xE9\x91\xF5\x86\xCA\xFA\xB9\x66\x33\xAA\x59\x5B\xCE\xE2\xA7\x16\x73\x47\xCB\x2B\xCC\x99\xB0\x37\x48\xCF\xE3\x56\x4B\xF5\xCF\x0F\x0C\x72\x32\x87\xC6\xF0\x44\xBB\x53\x72\x6D\x43\xF5\x26\x48\x9A\x52\x67\xB7\x58\xAB\xFE\x67\x76\x71\x78\xDB\x0D\xA2\x56\x14\x13\x39\x24\x31\x85\xA2\xA8\x02\x5A\x30\x47\xE1\xDD\x50\x07\xBC\x02\x09\x90\x00\xEB\x64\x63\x60\x9B\x16\xBC\x88\xC9\x12\xE6\xD2\x7D\x91\x8B\xF9\x3D\x32\x8D\x65\xB4\xE9\x7C\xB1\x57\x76\xEA\xC5\xB6\x28\x39\xBF\x15\x65\x1C\xC8\xF6\x77\x96\x6A\x0A\x8D\x77\x0B\xD8\x91\x0B\x04\x8E\x07\xDB\x29\xB6\x0A\xEE\x9D\x82\x35\x35\x10", - ["DST ACES CA X6"] = "\x30\x82\x04\x09\x30\x82\x02\xF1\xA0\x03\x02\x01\x02\x02\x10\x0D\x5E\x99\x0A\xD6\x9D\xB7\x78\xEC\xD8\x07\x56\x3B\x86\x15\xD9\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x5B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x13\x17\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x20\x41\x43\x45\x53\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0E\x44\x53\x54\x20\x41\x43\x45\x53\x20\x43\x41\x20\x58\x36\x30\x1E\x17\x0D\x30\x33\x31\x31\x32\x30\x32\x31\x31\x39\x35\x38\x5A\x17\x0D\x31\x37\x31\x31\x32\x30\x32\x31\x31\x39\x35\x38\x5A\x30\x5B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x13\x17\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x20\x41\x43\x45\x53\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0E\x44\x53\x54\x20\x41\x43\x45\x53\x20\x43\x41\x20\x58\x36\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\xB9\x3D\xF5\x2C\xC9\x94\xDC\x75\x8A\x95\x5D\x63\xE8\x84\x77\x76\x66\xB9\x59\x91\x5C\x46\xDD\x92\x3E\x9F\xF9\x0E\x03\xB4\x3D\x61\x92\xBD\x23\x26\xB5\x63\xEE\x92\xD2\x9E\xD6\x3C\xC8\x0D\x90\x5F\x64\x81\xB1\xA8\x08\x0D\x4C\xD8\xF9\xD3\x05\x28\x52\xB4\x01\x25\xC5\x95\x1C\x0C\x7E\x3E\x10\x84\x75\xCF\xC1\x19\x91\x63\xCF\xE8\xA8\x91\x88\xB9\x43\x52\xBB\x80\xB1\x55\x89\x8B\x31\xFA\xD0\xB7\x76\xBE\x41\x3D\x30\x9A\xA4\x22\x25\x17\x73\xE8\x1E\xE2\xD3\xAC\x2A\xBD\x5B\x38\x21\xD5\x2A\x4B\xD7\x55\x7D\xE3\x3A\x55\xBD\xD7\x6D\x6B\x02\x57\x6B\xE6\x47\x7C\x08\xC8\x82\xBA\xDE\xA7\x87\x3D\xA1\x6D\xB8\x30\x56\xC2\xB3\x02\x81\x5F\x2D\xF5\xE2\x9A\x30\x18\x28\xB8\x66\xD3\xCB\x01\x96\x6F\xEA\x8A\x45\x55\xD6\xE0\x9D\xFF\x67\x2B\x17\x02\xA6\x4E\x1A\x6A\x11\x0B\x7E\xB7\x7B\xE7\x98\xD6\x8C\x76\x6F\xC1\x3B\xDB\x50\x93\x7E\xE5\xD0\x8E\x1F\x37\xB8\xBD\xBA\xC6\x9F\x6C\xE9\x7C\x33\xF2\x32\x3C\x26\x47\xFA\x27\x24\x02\xC9\x7E\x1D\x5B\x88\x42\x13\x6A\x35\x7C\x7D\x35\xE9\x2E\x66\x91\x72\x93\xD5\x32\x26\xC4\x74\xF5\x53\xA3\xB3\x5D\x9A\xF6\x09\xCB\x02\x03\x01\x00\x01\xA3\x81\xC8\x30\x81\xC5\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\xC6\x30\x1F\x06\x03\x55\x1D\x11\x04\x18\x30\x16\x81\x14\x70\x6B\x69\x2D\x6F\x70\x73\x40\x74\x72\x75\x73\x74\x64\x73\x74\x2E\x63\x6F\x6D\x30\x62\x06\x03\x55\x1D\x20\x04\x5B\x30\x59\x30\x57\x06\x0A\x60\x86\x48\x01\x65\x03\x02\x01\x01\x01\x30\x49\x30\x47\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x3B\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x64\x73\x74\x2E\x63\x6F\x6D\x2F\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x73\x2F\x70\x6F\x6C\x69\x63\x79\x2F\x41\x43\x45\x53\x2D\x69\x6E\x64\x65\x78\x2E\x68\x74\x6D\x6C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x09\x72\x06\x4E\x18\x43\x0F\xE5\xD6\xCC\xC3\x6A\x8B\x31\x7B\x78\x8F\xA8\x83\xB8\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA3\xD8\x8E\xD6\xB2\xDB\xCE\x05\xE7\x32\xCD\x01\xD3\x04\x03\xE5\x76\xE4\x56\x2B\x9C\x99\x90\xE8\x08\x30\x6C\xDF\x7D\x3D\xEE\xE5\xBF\xB5\x24\x40\x84\x49\xE1\xD1\x28\xAE\xC4\xC2\x3A\x53\x30\x88\xF1\xF5\x77\x6E\x51\xCA\xFA\xFF\x99\xAF\x24\x5F\x1B\xA0\xFD\xF2\xAC\x84\xCA\xDF\xA9\xF0\x5F\x04\x2E\xAD\x16\xBF\x21\x97\x10\x81\x3D\xE3\xFF\x87\x8D\x32\xDC\x94\xE5\x47\x8A\x5E\x6A\x13\xC9\x94\x95\x3D\xD2\xEE\xC8\x34\x95\xD0\x80\xD4\xAD\x32\x08\x80\x54\x3C\xE0\xBD\x52\x53\xD7\x52\x7C\xB2\x69\x3F\x7F\x7A\xCF\x6A\x74\xCA\xFA\x04\x2A\x9C\x4C\x5A\x06\xA5\xE9\x20\xAD\x45\x66\x0F\x69\xF1\xDD\xBF\xE9\xE3\x32\x8B\xFA\xE0\xC1\x86\x4D\x72\x3C\x2E\xD8\x93\x78\x0A\x2A\xF8\xD8\xD2\x27\x3D\x19\x89\x5F\x5A\x7B\x8A\x3B\xCC\x0C\xDA\x51\xAE\xC7\x0B\xF7\x2B\xB0\x37\x05\xEC\xBC\x57\x23\xE2\x38\xD2\x9B\x68\xF3\x56\x12\x88\x4F\x42\x7C\xB8\x31\xC4\xB5\xDB\xE4\xC8\x21\x34\xE9\x48\x11\x35\xEE\xFA\xC7\x92\x57\xC5\x9F\x34\xE4\xC7\xF6\xF7\x0E\x0B\x4C\x9C\x68\x78\x7B\x71\x31\xC7\xEB\x1E\xE0\x67\x41\xF3\xB7\xA0\xA7\xCD\xE5\x7A\x33\x36\x6A\xFA\x9A\x2B", - ["TURKTRUST Certificate Services Provider Root 1"] = "\x30\x82\x03\xFB\x30\x82\x02\xE3\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xB7\x31\x3F\x30\x3D\x06\x03\x55\x04\x03\x0C\x36\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x0C\x02\x54\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x07\x0C\x06\x41\x4E\x4B\x41\x52\x41\x31\x56\x30\x54\x06\x03\x55\x04\x0A\x0C\x4D\x28\x63\x29\x20\x32\x30\x30\x35\x20\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x42\x69\x6C\x67\x69\x20\xC4\xB0\x6C\x65\x74\x69\xC5\x9F\x69\x6D\x20\x76\x65\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x47\xC3\xBC\x76\x65\x6E\x6C\x69\xC4\x9F\x69\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\x30\x1E\x17\x0D\x30\x35\x30\x35\x31\x33\x31\x30\x32\x37\x31\x37\x5A\x17\x0D\x31\x35\x30\x33\x32\x32\x31\x30\x32\x37\x31\x37\x5A\x30\x81\xB7\x31\x3F\x30\x3D\x06\x03\x55\x04\x03\x0C\x36\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x0C\x02\x54\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x07\x0C\x06\x41\x4E\x4B\x41\x52\x41\x31\x56\x30\x54\x06\x03\x55\x04\x0A\x0C\x4D\x28\x63\x29\x20\x32\x30\x30\x35\x20\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x42\x69\x6C\x67\x69\x20\xC4\xB0\x6C\x65\x74\x69\xC5\x9F\x69\x6D\x20\x76\x65\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x47\xC3\xBC\x76\x65\x6E\x6C\x69\xC4\x9F\x69\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\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\xCA\x52\x05\xD6\x63\x03\xD8\x1C\x5F\xDD\xD2\x7B\x5D\xF2\x0C\x60\x61\x5B\x6B\x3B\x74\x2B\x78\x0D\x7D\x45\xBD\x22\x74\xE8\x8C\x03\xC1\xC6\x11\x2A\x3D\x95\xBC\xA9\x94\xB0\xBB\x91\x97\xC8\x69\x7C\x84\xC5\xB4\x91\x6C\x6C\x13\x6A\xA4\x55\xAD\xA4\x85\xE8\x95\x7E\xB3\x00\xAF\x00\xC2\x05\x18\xF5\x70\x9D\x36\x8B\xAE\xCB\xE4\x1B\x81\x7F\x93\x88\xFB\x6A\x55\xBB\x7D\x85\x92\xCE\xBA\x58\x9F\xDB\x32\xC5\xBD\x5D\xEF\x22\x4A\x2F\x41\x07\x7E\x49\x61\xB3\x86\xEC\x4E\xA6\x41\x6E\x84\xBC\x03\xEC\xF5\x3B\x1C\xC8\x1F\xC2\xEE\xA8\xEE\xEA\x12\x4A\x8D\x14\xCF\xF3\x0A\xE0\x50\x39\xF9\x08\x35\xF8\x11\x59\xAD\xE7\x22\xEA\x4B\xCA\x14\x06\xDE\x42\xBA\xB2\x99\xF3\x2D\x54\x88\x10\x06\xEA\xE1\x1A\x3E\x3D\x67\x1F\xFB\xCE\xFB\x7C\x82\xE8\x11\x5D\x4A\xC1\xB9\x14\xEA\x54\xD9\x66\x9B\x7C\x89\x7D\x04\x9A\x62\xC9\xE9\x52\x3C\x9E\x9C\xEF\xD2\xF5\x26\xE4\xE6\xE5\x18\x7C\x8B\x6E\xDF\x6C\xCC\x78\x5B\x4F\x72\xB2\xCB\x5C\x3F\x8C\x05\x8D\xD1\x4C\x8C\xAD\x92\xC7\xE1\x78\x7F\x65\x6C\x49\x06\x50\x2C\x9E\x32\xC2\xD7\x4A\xC6\x75\x8A\x59\x4E\x75\x6F\x47\x5E\xC1\x02\x03\x01\x00\x01\xA3\x10\x30\x0E\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x15\xF5\x55\xFF\x37\x96\x80\x59\x21\xA4\xFC\xA1\x15\x4C\x20\xF6\xD4\x5F\xDA\x03\x24\xFC\xCF\x90\x1A\xF4\x21\x0A\x9A\xEE\x3A\xB1\x6A\xEF\xEF\xF8\x60\xD1\x4C\x36\x66\x45\x1D\xF3\x66\x02\x74\x04\x7B\x92\x30\xA8\xDE\x0A\x76\x0F\xEF\x95\x6E\xBD\xC9\x37\xE6\x1A\x0D\xAC\x89\x48\x5B\xCC\x83\x36\xC2\xF5\x46\x5C\x59\x82\x56\xB4\xD5\xFE\x23\xB4\xD8\x54\x1C\x44\xAB\xC4\xA7\xE5\x14\xCE\x3C\x41\x61\x7C\x43\xE6\xCD\xC4\x81\x09\x8B\x24\xFB\x54\x25\xD6\x16\xA8\x96\x0C\x67\x07\x6F\xB3\x50\x47\xE3\x1C\x24\x28\xDD\x2A\x98\xA4\x61\xFE\xDB\xEA\x12\x37\xBC\x01\x1A\x34\x85\xBD\x6E\x4F\xE7\x91\x72\x07\x44\x85\x1E\x58\xCA\x54\x44\xDD\xF7\xAC\xB9\xCB\x89\x21\x72\xDB\x8F\xC0\x69\x29\x97\x2A\xA3\xAE\x18\x23\x97\x1C\x41\x2A\x8B\x7C\x2A\xC1\x7C\x90\xE8\xA9\x28\xC0\xD3\x91\xC6\xAD\x28\x87\x40\x68\xB5\xFF\xEC\xA7\xD2\xD3\x38\x18\x9C\xD3\x7D\x69\x5D\xF0\xC6\xA5\x1E\x24\x1B\xA3\x47\xFC\x69\x07\x68\xE7\xE4\x9A\xB4\xED\x0F\xA1\x87\x87\x02\xCE\x87\xD2\x48\x4E\xE1\xBC\xFF\xCB\xF1\x72\x92\x44\x64\x03\x25\xEA\xDE\x5B\x6E\x9F\xC9\xF2\x4E\xAC\xDD\xC7", - ["TURKTRUST Certificate Services Provider Root 2"] = "\x30\x82\x04\x3C\x30\x82\x03\x24\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xBE\x31\x3F\x30\x3D\x06\x03\x55\x04\x03\x0C\x36\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x07\x0C\x06\x41\x6E\x6B\x61\x72\x61\x31\x5D\x30\x5B\x06\x03\x55\x04\x0A\x0C\x54\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x42\x69\x6C\x67\x69\x20\xC4\xB0\x6C\x65\x74\x69\xC5\x9F\x69\x6D\x20\x76\x65\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x47\xC3\xBC\x76\x65\x6E\x6C\x69\xC4\x9F\x69\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\x20\x28\x63\x29\x20\x4B\x61\x73\xC4\xB1\x6D\x20\x32\x30\x30\x35\x30\x1E\x17\x0D\x30\x35\x31\x31\x30\x37\x31\x30\x30\x37\x35\x37\x5A\x17\x0D\x31\x35\x30\x39\x31\x36\x31\x30\x30\x37\x35\x37\x5A\x30\x81\xBE\x31\x3F\x30\x3D\x06\x03\x55\x04\x03\x0C\x36\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x07\x0C\x06\x41\x6E\x6B\x61\x72\x61\x31\x5D\x30\x5B\x06\x03\x55\x04\x0A\x0C\x54\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x42\x69\x6C\x67\x69\x20\xC4\xB0\x6C\x65\x74\x69\xC5\x9F\x69\x6D\x20\x76\x65\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x47\xC3\xBC\x76\x65\x6E\x6C\x69\xC4\x9F\x69\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\x20\x28\x63\x29\x20\x4B\x61\x73\xC4\xB1\x6D\x20\x32\x30\x30\x35\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\xA9\x36\x7E\xC3\x91\x43\x4C\xC3\x19\x98\x08\xC8\xC7\x58\x7B\x4F\x16\x8C\xA5\xCE\x49\x01\x1F\x73\x0E\xAC\x75\x13\xA6\xFA\x9E\x2C\x20\xDE\xD8\x90\x0E\x0A\xD1\x69\xD2\x27\xFB\xAA\x77\x9F\x27\x52\x25\xE2\xCB\x5D\xD8\xD8\x83\x50\x17\x7D\x8A\xB5\x82\x3F\x04\x8E\xB4\xD5\xF0\x49\xA7\x64\xB7\x1E\x2E\x5F\x20\x9C\x50\x75\x4F\xAF\xE1\xB5\x41\x14\xF4\x98\x92\x88\xC7\xE5\xE5\x64\x47\x61\x47\x79\xFD\xC0\x51\xF1\xC1\x99\xE7\xDC\xCE\x6A\xFB\xAF\xB5\x01\x30\xDC\x46\x1C\xEF\x8A\xEC\x95\xEF\xDC\xFF\xAF\x10\x1C\xEB\x9D\xD8\xB0\xAA\x6A\x85\x18\x0D\x17\xC9\x3E\xBF\xF1\x9B\xD0\x09\x89\x42\xFD\xA0\x42\xB4\x9D\x89\x51\x55\x29\xCF\x1B\x70\xBC\x84\x54\xAD\xC1\x13\x1F\x98\xF4\x2E\x76\x60\x8B\x5D\x3F\x9A\xAD\xCA\x0C\xBF\xA7\x56\x5B\x8F\x77\xB8\xD5\x9E\x79\x49\x92\x3F\xE0\xF1\x97\x24\x7A\x6C\x9B\x17\x0F\x6D\xEF\x53\x98\x91\x2B\xE4\x0F\xBE\x59\x79\x07\x78\xBB\x97\x95\xF4\x9F\x69\xD4\x58\x87\x0A\xA9\xE3\xCC\xB6\x58\x19\x9F\x26\x21\xB1\xC4\x59\x8D\xB2\x41\x75\xC0\xAD\x69\xCE\x9C\x00\x08\xF2\x36\xFF\x3E\xF0\xA1\x0F\x1A\xAC\x14\xFD\xA6\x60\x0F\x02\x03\x01\x00\x01\xA3\x43\x30\x41\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xD9\x37\xB3\x4E\x05\xFD\xD9\xCF\x9F\x12\x16\xAE\xB6\x89\x2F\xEB\x25\x3A\x88\x1C\x30\x0F\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x05\x03\x03\x07\x06\x00\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x72\x60\x96\xB7\xC9\xDC\xD8\x29\x5E\x23\x85\x5F\xB2\xB3\x2D\x76\xFB\x88\xD7\x17\xFE\x7B\x6D\x45\xB8\xF6\x85\x6C\x9F\x22\xFC\x2A\x10\x22\xEC\xAA\xB9\x30\xF6\xAB\x58\xD6\x39\x10\x31\x99\x29\x00\xBD\x89\x66\x41\xFB\x74\xDE\x91\xC1\x18\x0B\x9F\xB5\x61\xCB\x9D\x3A\xBE\xF5\xA8\x94\xA3\x22\x55\x6E\x17\x49\xFF\xD2\x29\xF1\x38\x26\x5D\xEF\xA5\xAA\x3A\xF9\x71\x7B\xE6\xDA\x58\x1D\xD3\x74\xC2\x01\xFA\x3E\x69\x58\x5F\xAD\xCB\x68\xBE\x14\x2E\x9B\x6C\xC0\xB6\xDC\xA0\x26\xFA\x77\x1A\xE2\x24\xDA\x1A\x37\xE0\x67\xAD\xD1\x73\x83\x0D\xA5\x1A\x1D\x6E\x12\x92\x7E\x84\x62\x00\x17\xBD\xBC\x25\x18\x57\xF2\xD7\xA9\x6F\x59\x88\xBC\x34\xB7\x2E\x85\x78\x9D\x96\xDC\x14\xC3\x2C\x8A\x52\x9B\x96\x8C\x52\x66\x3D\x86\x16\x8B\x47\xB8\x51\x09\x8C\xEA\x7D\xCD\x88\x72\xB3\x60\x33\xB1\xF0\x0A\x44\xEF\x0F\xF5\x09\x37\x88\x24\x0E\x2C\x6B\x20\x3A\xA2\xFA\x11\xF2\x40\x35\x9C\x44\x68\x63\x3B\xAC\x33\x6F\x63\xBC\x2C\xBB\xF2\xD2\xCB\x76\x7D\x7D\x88\xD8\x1D\xC8\x05\x1D\x6E\xBC\x94\xA9\x66\x8C\x77\x71\xC7\xFA\x91\xFA\x2F\x51\x9E\xE9\x39\x52\xB6\xE7\x04\x42", - ["SwissSign Gold CA - G2"] = "\x30\x82\x05\xBA\x30\x82\x03\xA2\xA0\x03\x02\x01\x02\x02\x09\x00\xBB\x40\x1C\x43\xF5\x5E\x4F\xB0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x41\x47\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x47\x6F\x6C\x64\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x36\x31\x30\x32\x35\x30\x38\x33\x30\x33\x35\x5A\x17\x0D\x33\x36\x31\x30\x32\x35\x30\x38\x33\x30\x33\x35\x5A\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x41\x47\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x47\x6F\x6C\x64\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xAF\xE4\xEE\x7E\x8B\x24\x0E\x12\x6E\xA9\x50\x2D\x16\x44\x3B\x92\x92\x5C\xCA\xB8\x5D\x84\x92\x42\x13\x2A\xBC\x65\x57\x82\x40\x3E\x57\x24\xCD\x50\x8B\x25\x2A\xB7\x6F\xFC\xEF\xA2\xD0\xC0\x1F\x02\x24\x4A\x13\x96\x8F\x23\x13\xE6\x28\x58\x00\xA3\x47\xC7\x06\xA7\x84\x23\x2B\xBB\xBD\x96\x2B\x7F\x55\xCC\x8B\xC1\x57\x1F\x0E\x62\x65\x0F\xDD\x3D\x56\x8A\x73\xDA\xAE\x7E\x6D\xBA\x81\x1C\x7E\x42\x8C\x20\x35\xD9\x43\x4D\x84\xFA\x84\xDB\x52\x2C\xF3\x0E\x27\x77\x0B\x6B\xBF\x11\x2F\x72\x78\x9F\x2E\xD8\x3E\xE6\x18\x37\x5A\x2A\x72\xF9\xDA\x62\x90\x92\x95\xCA\x1F\x9C\xE9\xB3\x3C\x2B\xCB\xF3\x01\x13\xBF\x5A\xCF\xC1\xB5\x0A\x60\xBD\xDD\xB5\x99\x64\x53\xB8\xA0\x96\xB3\x6F\xE2\x26\x77\x91\x8C\xE0\x62\x10\x02\x9F\x34\x0F\xA4\xD5\x92\x33\x51\xDE\xBE\x8D\xBA\x84\x7A\x60\x3C\x6A\xDB\x9F\x2B\xEC\xDE\xDE\x01\x3F\x6E\x4D\xE5\x50\x86\xCB\xB4\xAF\xED\x44\x40\xC5\xCA\x5A\x8C\xDA\xD2\x2B\x7C\xA8\xEE\xBE\xA6\xE5\x0A\xAA\x0E\xA5\xDF\x05\x52\xB7\x55\xC7\x22\x5D\x32\x6A\x97\x97\x63\x13\xDB\xC9\xDB\x79\x36\x7B\x85\x3A\x4A\xC5\x52\x89\xF9\x24\xE7\x9D\x77\xA9\x82\xFF\x55\x1C\xA5\x71\x69\x2B\xD1\x02\x24\xF2\xB3\x26\xD4\x6B\xDA\x04\x55\xE5\xC1\x0A\xC7\x6D\x30\x37\x90\x2A\xE4\x9E\x14\x33\x5E\x16\x17\x55\xC5\x5B\xB5\xCB\x34\x89\x92\xF1\x9D\x26\x8F\xA1\x07\xD4\xC6\xB2\x78\x50\xDB\x0C\x0C\x0B\x7C\x0B\x8C\x41\xD7\xB9\xE9\xDD\x8C\x88\xF7\xA3\x4D\xB2\x32\xCC\xD8\x17\xDA\xCD\xB7\xCE\x66\x9D\xD4\xFD\x5E\xFF\xBD\x97\x3E\x29\x75\xE7\x7E\xA7\x62\x58\xAF\x25\x34\xA5\x41\xC7\x3D\xBC\x0D\x50\xCA\x03\x03\x0F\x08\x5A\x1F\x95\x73\x78\x62\xBF\xAF\x72\x14\x69\x0E\xA5\xE5\x03\x0E\x78\x8E\x26\x28\x42\xF0\x07\x0B\x62\x20\x10\x67\x39\x46\xFA\xA9\x03\xCC\x04\x38\x7A\x66\xEF\x20\x83\xB5\x8C\x4A\x56\x8E\x91\x00\xFC\x8E\x5C\x82\xDE\x88\xA0\xC3\xE2\x68\x6E\x7D\x8D\xEF\x3C\xDD\x65\xF4\x5D\xAC\x51\xEF\x24\x80\xAE\xAA\x56\x97\x6F\xF9\xAD\x7D\xDA\x61\x3F\x98\x77\x3C\xA5\x91\xB6\x1C\x8C\x26\xDA\x65\xA2\x09\x6D\xC1\xE2\x54\xE3\xB9\xCA\x4C\x4C\x80\x8F\x77\x7B\x60\x9A\x1E\xDF\xB6\xF2\x48\x1E\x0E\xBA\x4E\x54\x6D\x98\xE0\xE1\xA2\x1A\xA2\x77\x50\xCF\xC4\x63\x92\xEC\x47\x19\x9D\xEB\xE6\x6B\xCE\xC1\x02\x03\x01\x00\x01\xA3\x81\xAC\x30\x81\xA9\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x5B\x25\x7B\x96\xA4\x65\x51\x7E\xB8\x39\xF3\xC0\x78\x66\x5E\xE8\x3A\xE7\xF0\xEE\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x5B\x25\x7B\x96\xA4\x65\x51\x7E\xB8\x39\xF3\xC0\x78\x66\x5E\xE8\x3A\xE7\xF0\xEE\x30\x46\x06\x03\x55\x1D\x20\x04\x3F\x30\x3D\x30\x3B\x06\x09\x60\x85\x74\x01\x59\x01\x02\x01\x01\x30\x2E\x30\x2C\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x20\x68\x74\x74\x70\x3A\x2F\x2F\x72\x65\x70\x6F\x73\x69\x74\x6F\x72\x79\x2E\x73\x77\x69\x73\x73\x73\x69\x67\x6E\x2E\x63\x6F\x6D\x2F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x27\xBA\xE3\x94\x7C\xF1\xAE\xC0\xDE\x17\xE6\xE5\xD8\xD5\xF5\x54\xB0\x83\xF4\xBB\xCD\x5E\x05\x7B\x4F\x9F\x75\x66\xAF\x3C\xE8\x56\x7E\xFC\x72\x78\x38\x03\xD9\x2B\x62\x1B\x00\xB9\xF8\xE9\x60\xCD\xCC\xCE\x51\x8A\xC7\x50\x31\x6E\xE1\x4A\x7E\x18\x2F\x69\x59\xB6\x3D\x64\x81\x2B\xE3\x83\x84\xE6\x22\x87\x8E\x7D\xE0\xEE\x02\x99\x61\xB8\x1E\xF4\xB8\x2B\x88\x12\x16\x84\xC2\x31\x93\x38\x96\x31\xA6\xB9\x3B\x53\x3F\xC3\x24\x93\x56\x5B\x69\x92\xEC\xC5\xC1\xBB\x38\x00\xE3\xEC\x17\xA9\xB8\xDC\xC7\x7C\x01\x83\x9F\x32\x47\xBA\x52\x22\x34\x1D\x32\x7A\x09\x56\xA7\x7C\x25\x36\xA9\x3D\x4B\xDA\xC0\x82\x6F\x0A\xBB\x12\xC8\x87\x4B\x27\x11\xF9\x1E\x2D\xC7\x93\x3F\x9E\xDB\x5F\x26\x6B\x52\xD9\x2E\x8A\xF1\x14\xC6\x44\x8D\x15\xA9\xB7\xBF\xBD\xDE\xA6\x1A\xEE\xAE\x2D\xFB\x48\x77\x17\xFE\xBB\xEC\xAF\x18\xF5\x2A\x51\xF0\x39\x84\x97\x95\x6C\x6E\x1B\xC3\x2B\xC4\x74\x60\x79\x25\xB0\x0A\x27\xDF\xDF\x5E\xD2\x39\xCF\x45\x7D\x42\x4B\xDF\xB3\x2C\x1E\xC5\xC6\x5D\xCA\x55\x3A\xA0\x9C\x69\x9A\x8F\xDA\xEF\xB2\xB0\x3C\x9F\x87\x6C\x12\x2B\x65\x70\x15\x52\x31\x1A\x24\xCF\x6F\x31\x23\x50\x1F\x8C\x4F\x8F\x23\xC3\x74\x41\x63\x1C\x55\xA8\x14\xDD\x3E\xE0\x51\x50\xCF\xF1\x1B\x30\x56\x0E\x92\xB0\x82\x85\xD8\x83\xCB\x22\x64\xBC\x2D\xB8\x25\xD5\x54\xA2\xB8\x06\xEA\xAD\x92\xA4\x24\xA0\xC1\x86\xB5\x4A\x13\x6A\x47\xCF\x2E\x0B\x56\x95\x54\xCB\xCE\x9A\xDB\x6A\xB4\xA6\xB2\xDB\x41\x08\x86\x27\x77\xF7\x6A\xA0\x42\x6C\x0B\x38\xCE\xD7\x75\x50\x32\x92\xC2\xDF\x2B\x30\x22\x48\xD0\xD5\x41\x38\x25\x5D\xA4\xE9\x5D\x9F\xC6\x94\x75\xD0\x45\xFD\x30\x97\x43\x8F\x90\xAB\x0A\xC7\x86\x73\x60\x4A\x69\x2D\xDE\xA5\x78\xD7\x06\xDA\x6A\x9E\x4B\x3E\x77\x3A\x20\x13\x22\x01\xD0\xBF\x68\x9E\x63\x60\x6B\x35\x4D\x0B\x6D\xBA\xA1\x3D\xC0\x93\xE0\x7F\x23\xB3\x55\xAD\x72\x25\x4E\x46\xF9\xD2\x16\xEF\xB0\x64\xC1\x01\x9E\xE9\xCA\xA0\x6A\x98\x0E\xCF\xD8\x60\xF2\x2F\x49\xB8\xE4\x42\xE1\x38\x35\x16\xF4\xC8\x6E\x4F\xF7\x81\x56\xE8\xBA\xA3\xBE\x23\xAF\xAE\xFD\x6F\x03\xE0\x02\x3B\x30\x76\xFA\x1B\x6D\x41\xCF\x01\xB1\xE9\xB8\xC9\x66\xF4\xDB\x26\xF3\x3A\xA4\x74\xF2\x49\x24\x5B\xC9\xB0\xD0\x57\xC1\xFA\x3E\x7A\xE1\x97\xC9", - ["SwissSign Silver CA - G2"] = "\x30\x82\x05\xBD\x30\x82\x03\xA5\xA0\x03\x02\x01\x02\x02\x08\x4F\x1B\xD4\x2F\x54\xBB\x2F\x4B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x47\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x41\x47\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x53\x69\x6C\x76\x65\x72\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x36\x31\x30\x32\x35\x30\x38\x33\x32\x34\x36\x5A\x17\x0D\x33\x36\x31\x30\x32\x35\x30\x38\x33\x32\x34\x36\x5A\x30\x47\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x41\x47\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x53\x69\x6C\x76\x65\x72\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC4\xF1\x87\x7F\xD3\x78\x31\xF7\x38\xC9\xF8\xC3\x99\x43\xBC\xC7\xF7\xBC\x37\xE7\x4E\x71\xBA\x4B\x8F\xA5\x73\x1D\x5C\x6E\x98\xAE\x03\x57\xAE\x38\x37\x43\x2F\x17\x3D\x1F\xC8\xCE\x68\x10\xC1\x78\xAE\x19\x03\x2B\x10\xFA\x2C\x79\x83\xF6\xE8\xB9\x68\xB9\x55\xF2\x04\x44\xA7\x39\xF9\xFC\x04\x8B\x1E\xF1\xA2\x4D\x27\xF9\x61\x7B\xBA\xB7\xE5\xA2\x13\xB6\xEB\x61\x3E\xD0\x6C\xD1\xE6\xFB\xFA\x5E\xED\x1D\xB4\x9E\xA0\x35\x5B\xA1\x92\xCB\xF0\x49\x92\xFE\x85\x0A\x05\x3E\xE6\xD9\x0B\xE2\x4F\xBB\xDC\x95\x37\xFC\x91\xE9\x32\x35\x22\xD1\x1F\x3A\x4E\x27\x85\x9D\xB0\x15\x94\x32\xDA\x61\x0D\x47\x4D\x60\x42\xAE\x92\x47\xE8\x83\x5A\x50\x58\xE9\x8A\x8B\xB9\x5D\xA1\xDC\xDD\x99\x4A\x1F\x36\x67\xBB\x48\xE4\x83\xB6\x37\xEB\x48\x3A\xAF\x0F\x67\x8F\x17\x07\xE8\x04\xCA\xEF\x6A\x31\x87\xD4\xC0\xB6\xF9\x94\x71\x7B\x67\x64\xB8\xB6\x91\x4A\x42\x7B\x65\x2E\x30\x6A\x0C\xF5\x90\xEE\x95\xE6\xF2\xCD\x82\xEC\xD9\xA1\x4A\xEC\xF6\xB2\x4B\xE5\x45\x85\xE6\x6D\x78\x93\x04\x2E\x9C\x82\x6D\x36\xA9\xC4\x31\x64\x1F\x86\x83\x0B\x2A\xF4\x35\x0A\x78\xC9\x55\xCF\x41\xB0\x47\xE9\x30\x9F\x99\xBE\x61\xA8\x06\x84\xB9\x28\x7A\x5F\x38\xD9\x1B\xA9\x38\xB0\x83\x7F\x73\xC1\xC3\x3B\x48\x2A\x82\x0F\x21\x9B\xB8\xCC\xA8\x35\xC3\x84\x1B\x83\xB3\x3E\xBE\xA4\x95\x69\x01\x3A\x89\x00\x78\x04\xD9\xC9\xF4\x99\x19\xAB\x56\x7E\x5B\x8B\x86\x39\x15\x91\xA4\x10\x2C\x09\x32\x80\x60\xB3\x93\xC0\x2A\xB6\x18\x0B\x9D\x7E\x8D\x49\xF2\x10\x4A\x7F\xF9\xD5\x46\x2F\x19\x92\xA3\x99\xA7\x26\xAC\xBB\x8C\x3C\xE6\x0E\xBC\x47\x07\xDC\x73\x51\xF1\x70\x64\x2F\x08\xF9\xB4\x47\x1D\x30\x6C\x44\xEA\x29\x37\x85\x92\x68\x66\xBC\x83\x38\xFE\x7B\x39\x2E\xD3\x50\xF0\x1F\xFB\x5E\x60\xB6\xA9\xA6\xFA\x27\x41\xF1\x9B\x18\x72\xF2\xF5\x84\x74\x4A\xC9\x67\xC4\x54\xAE\x48\x64\xDF\x8C\xD1\x6E\xB0\x1D\xE1\x07\x8F\x08\x1E\x99\x9C\x71\xE9\x4C\xD8\xA5\xF7\x47\x12\x1F\x74\xD1\x51\x9E\x86\xF3\xC2\xA2\x23\x40\x0B\x73\xDB\x4B\xA6\xE7\x73\x06\x8C\xC1\xA0\xE9\xC1\x59\xAC\x46\xFA\xE6\x2F\xF8\xCF\x71\x9C\x46\x6D\xB9\xC4\x15\x8D\x38\x79\x03\x45\x48\xEF\xC4\x5D\xD7\x08\xEE\x87\x39\x22\x86\xB2\x0D\x0F\x58\x43\xF7\x71\xA9\x48\x2E\xFD\xEA\xD6\x1F\x02\x03\x01\x00\x01\xA3\x81\xAC\x30\x81\xA9\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x17\xA0\xCD\xC1\xE4\x41\xB6\x3A\x5B\x3B\xCB\x45\x9D\xBD\x1C\xC2\x98\xFA\x86\x58\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x17\xA0\xCD\xC1\xE4\x41\xB6\x3A\x5B\x3B\xCB\x45\x9D\xBD\x1C\xC2\x98\xFA\x86\x58\x30\x46\x06\x03\x55\x1D\x20\x04\x3F\x30\x3D\x30\x3B\x06\x09\x60\x85\x74\x01\x59\x01\x03\x01\x01\x30\x2E\x30\x2C\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x20\x68\x74\x74\x70\x3A\x2F\x2F\x72\x65\x70\x6F\x73\x69\x74\x6F\x72\x79\x2E\x73\x77\x69\x73\x73\x73\x69\x67\x6E\x2E\x63\x6F\x6D\x2F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x73\xC6\x81\xE0\x27\xD2\x2D\x0F\xE0\x95\x30\xE2\x9A\x41\x7F\x50\x2C\x5F\x5F\x62\x61\xA9\x86\x6A\x69\x18\x0C\x74\x49\xD6\x5D\x84\xEA\x41\x52\x18\x6F\x58\xAD\x50\x56\x20\x6A\xC6\xBD\x28\x69\x58\x91\xDC\x91\x11\x35\xA9\x3A\x1D\xBC\x1A\xA5\x60\x9E\xD8\x1F\x7F\x45\x91\x69\xD9\x7E\xBB\x78\x72\xC1\x06\x0F\x2A\xCE\x8F\x85\x70\x61\xAC\xA0\xCD\x0B\xB8\x39\x29\x56\x84\x32\x4E\x86\xBB\x3D\xC4\x2A\xD9\xD7\x1F\x72\xEE\xFE\x51\xA1\x22\x41\xB1\x71\x02\x63\x1A\x82\xB0\x62\xAB\x5E\x57\x12\x1F\xDF\xCB\xDD\x75\xA0\xC0\x5D\x79\x90\x8C\x1B\xE0\x50\xE6\xDE\x31\xFE\x98\x7B\x70\x5F\xA5\x90\xD8\xAD\xF8\x02\xB6\x6F\xD3\x60\xDD\x40\x4B\x22\xC5\x3D\xAD\x3A\x7A\x9F\x1A\x1A\x47\x91\x79\x33\xBA\x82\xDC\x32\x69\x03\x96\x6E\x1F\x4B\xF0\x71\xFE\xE3\x67\x72\xA0\xB1\xBF\x5C\x8B\xE4\xFA\x99\x22\xC7\x84\xB9\x1B\x8D\x23\x97\x3F\xED\x25\xE0\xCF\x65\xBB\xF5\x61\x04\xEF\xDD\x1E\xB2\x5A\x41\x22\x5A\xA1\x9F\x5D\x2C\xE8\x5B\xC9\x6D\xA9\x0C\x0C\x78\xAA\x60\xC6\x56\x8F\x01\x5A\x0C\x68\xBC\x69\x19\x79\xC4\x1F\x7E\x97\x05\xBF\xC5\xE9\x24\x51\x5E\xD4\xD5\x4B\x53\xED\xD9\x23\x5A\x36\x03\x65\xA3\xC1\x03\xAD\x41\x30\xF3\x46\x1B\x85\x90\xAF\x65\xB5\xD5\xB1\xE4\x16\x5B\x78\x75\x1D\x97\x7A\x6D\x59\xA9\x2A\x8F\x7B\xDE\xC3\x87\x89\x10\x99\x49\x73\x78\xC8\x3D\xBD\x51\x35\x74\x2A\xD5\xF1\x7E\x69\x1B\x2A\xBB\x3B\xBD\x25\xB8\x9A\x5A\x3D\x72\x61\x90\x66\x87\xEE\x0C\xD6\x4D\xD4\x11\x74\x0B\x6A\xFE\x0B\x03\xFC\xA3\x55\x57\x89\xFE\x4A\xCB\xAE\x5B\x17\x05\xC8\xF2\x8D\x23\x31\x53\x38\xD2\x2D\x6A\x3F\x82\xB9\x8D\x08\x6A\xF7\x5E\x41\x74\x6E\xC3\x11\x7E\x07\xAC\x29\x60\x91\x3F\x38\xCA\x57\x10\x0D\xBD\x30\x2F\xC7\xA5\xE6\x41\xA0\xDA\xAE\x05\x87\x9A\xA0\xA4\x65\x6C\x4C\x09\x0C\x89\xBA\xB8\xD3\xB9\xC0\x93\x8A\x30\xFA\x8D\xE5\x9A\x6B\x15\x01\x4E\x67\xAA\xDA\x62\x56\x3E\x84\x08\x66\xD2\xC4\x36\x7D\xA7\x3E\x10\xFC\x88\xE0\xD4\x80\xE5\x00\xBD\xAA\xF3\x4E\x06\xA3\x7A\x6A\xF9\x62\x72\xE3\x09\x4F\xEB\x9B\x0E\x01\x23\xF1\x9F\xBB\x7C\xDC\xDC\x6C\x11\x97\x25\xB2\xF2\xB4\x63\x14\xD2\x06\x2A\x67\x8C\x83\xF5\xCE\xEA\x07\xD8\x9A\x6A\x1E\xEC\xE4\x0A\xBB\x2A\x4C\xEB\x09\x60\x39\xCE\xCA\x62\xD8\x2E\x6E", - ["GeoTrust Primary Certification Authority"] = "\x30\x82\x03\x7C\x30\x82\x02\x64\xA0\x03\x02\x01\x02\x02\x10\x18\xAC\xB5\x6A\xFD\x69\xB6\x15\x3A\x63\x6C\xAF\xDA\xFA\xC4\xA1\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x58\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x03\x13\x28\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x36\x31\x31\x32\x37\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x58\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x03\x13\x28\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xBE\xB8\x15\x7B\xFF\xD4\x7C\x7D\x67\xAD\x83\x64\x7B\xC8\x42\x53\x2D\xDF\xF6\x84\x08\x20\x61\xD6\x01\x59\x6A\x9C\x44\x11\xAF\xEF\x76\xFD\x95\x7E\xCE\x61\x30\xBB\x7A\x83\x5F\x02\xBD\x01\x66\xCA\xEE\x15\x8D\x6F\xA1\x30\x9C\xBD\xA1\x85\x9E\x94\x3A\xF3\x56\x88\x00\x31\xCF\xD8\xEE\x6A\x96\x02\xD9\xED\x03\x8C\xFB\x75\x6D\xE7\xEA\xB8\x55\x16\x05\x16\x9A\xF4\xE0\x5E\xB1\x88\xC0\x64\x85\x5C\x15\x4D\x88\xC7\xB7\xBA\xE0\x75\xE9\xAD\x05\x3D\x9D\xC7\x89\x48\xE0\xBB\x28\xC8\x03\xE1\x30\x93\x64\x5E\x52\xC0\x59\x70\x22\x35\x57\x88\x8A\xF1\x95\x0A\x83\xD7\xBC\x31\x73\x01\x34\xED\xEF\x46\x71\xE0\x6B\x02\xA8\x35\x72\x6B\x97\x9B\x66\xE0\xCB\x1C\x79\x5F\xD8\x1A\x04\x68\x1E\x47\x02\xE6\x9D\x60\xE2\x36\x97\x01\xDF\xCE\x35\x92\xDF\xBE\x67\xC7\x6D\x77\x59\x3B\x8F\x9D\xD6\x90\x15\x94\xBC\x42\x34\x10\xC1\x39\xF9\xB1\x27\x3E\x7E\xD6\x8A\x75\xC5\xB2\xAF\x96\xD3\xA2\xDE\x9B\xE4\x98\xBE\x7D\xE1\xE9\x81\xAD\xB6\x6F\xFC\xD7\x0E\xDA\xE0\x34\xB0\x0D\x1A\x77\xE7\xE3\x08\x98\xEF\x58\xFA\x9C\x84\xB7\x36\xAF\xC2\xDF\xAC\xD2\xF4\x10\x06\x70\x71\x35\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x2C\xD5\x50\x41\x97\x15\x8B\xF0\x8F\x36\x61\x5B\x4A\xFB\x6B\xD9\x99\xC9\x33\x92\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5A\x70\x7F\x2C\xDD\xB7\x34\x4F\xF5\x86\x51\xA9\x26\xBE\x4B\xB8\xAA\xF1\x71\x0D\xDC\x61\xC7\xA0\xEA\x34\x1E\x7A\x77\x0F\x04\x35\xE8\x27\x8F\x6C\x90\xBF\x91\x16\x24\x46\x3E\x4A\x4E\xCE\x2B\x16\xD5\x0B\x52\x1D\xFC\x1F\x67\xA2\x02\x45\x31\x4F\xCE\xF3\xFA\x03\xA7\x79\x9D\x53\x6A\xD9\xDA\x63\x3A\xF8\x80\xD7\xD3\x99\xE1\xA5\xE1\xBE\xD4\x55\x71\x98\x35\x3A\xBE\x93\xEA\xAE\xAD\x42\xB2\x90\x6F\xE0\xFC\x21\x4D\x35\x63\x33\x89\x49\xD6\x9B\x4E\xCA\xC7\xE7\x4E\x09\x00\xF7\xDA\xC7\xEF\x99\x62\x99\x77\xB6\x95\x22\x5E\x8A\xA0\xAB\xF4\xB8\x78\x98\xCA\x38\x19\x99\xC9\x72\x9E\x78\xCD\x4B\xAC\xAF\x19\xA0\x73\x12\x2D\xFC\xC2\x41\xBA\x81\x91\xDA\x16\x5A\x31\xB7\xF9\xB4\x71\x80\x12\x48\x99\x72\x73\x5A\x59\x53\xC1\x63\x52\x33\xED\xA7\xC9\xD2\x39\x02\x70\xFA\xE0\xB1\x42\x66\x29\xAA\x9B\x51\xED\x30\x54\x22\x14\x5F\xD9\xAB\x1D\xC1\xE4\x94\xF0\xF8\xF5\x2B\xF7\xEA\xCA\x78\x46\xD6\xB8\x91\xFD\xA6\x0D\x2B\x1A\x14\x01\x3E\x80\xF0\x42\xA0\x95\x07\x5E\x6D\xCD\xCC\x4B\xA4\x45\x8D\xAB\x12\xE8\xB3\xDE\x5A\xE5\xA0\x7C\xE8\x0F\x22\x1D\x5A\xE9\x59", - ["thawte Primary Root CA"] = "\x30\x82\x04\x20\x30\x82\x03\x08\xA0\x03\x02\x01\x02\x02\x10\x34\x4E\xD5\x57\x20\xD5\xED\xEC\x49\xF4\x2F\xCE\x37\xDB\x2B\x6D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xA9\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x38\x30\x36\x06\x03\x55\x04\x0B\x13\x2F\x28\x63\x29\x20\x32\x30\x30\x36\x20\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x31\x31\x31\x37\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xA9\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x38\x30\x36\x06\x03\x55\x04\x0B\x13\x2F\x28\x63\x29\x20\x32\x30\x30\x36\x20\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xA0\xF0\xFB\x80\x59\xD4\x9C\xC7\xA4\xCF\x9D\xA1\x59\x73\x09\x10\x45\x0C\x0D\x2C\x6E\x68\xF1\x6C\x5B\x48\x68\x49\x59\x37\xFC\x0B\x33\x19\xC2\x77\x7F\xCC\x10\x2D\x95\x34\x1C\xE6\xEB\x4D\x09\xA7\x1C\xD2\xB8\xC9\x97\x36\x02\xB7\x89\xD4\x24\x5F\x06\xC0\xCC\x44\x94\x94\x8D\x02\x62\x6F\xEB\x5A\xDD\x11\x8D\x28\x9A\x5C\x84\x90\x10\x7A\x0D\xBD\x74\x66\x2F\x6A\x38\xA0\xE2\xD5\x54\x44\xEB\x1D\x07\x9F\x07\xBA\x6F\xEE\xE9\xFD\x4E\x0B\x29\xF5\x3E\x84\xA0\x01\xF1\x9C\xAB\xF8\x1C\x7E\x89\xA4\xE8\xA1\xD8\x71\x65\x0D\xA3\x51\x7B\xEE\xBC\xD2\x22\x60\x0D\xB9\x5B\x9D\xDF\xBA\xFC\x51\x5B\x0B\xAF\x98\xB2\xE9\x2E\xE9\x04\xE8\x62\x87\xDE\x2B\xC8\xD7\x4E\xC1\x4C\x64\x1E\xDD\xCF\x87\x58\xBA\x4A\x4F\xCA\x68\x07\x1D\x1C\x9D\x4A\xC6\xD5\x2F\x91\xCC\x7C\x71\x72\x1C\xC5\xC0\x67\xEB\x32\xFD\xC9\x92\x5C\x94\xDA\x85\xC0\x9B\xBF\x53\x7D\x2B\x09\xF4\x8C\x9D\x91\x1F\x97\x6A\x52\xCB\xDE\x09\x36\xA4\x77\xD8\x7B\x87\x50\x44\xD5\x3E\x6E\x29\x69\xFB\x39\x49\x26\x1E\x09\xA5\x80\x7B\x40\x2D\xEB\xE8\x27\x85\xC9\xFE\x61\xFD\x7E\xE6\x7C\x97\x1D\xD5\x9D\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x7B\x5B\x45\xCF\xAF\xCE\xCB\x7A\xFD\x31\x92\x1A\x6A\xB6\xF3\x46\xEB\x57\x48\x50\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x79\x11\xC0\x4B\xB3\x91\xB6\xFC\xF0\xE9\x67\xD4\x0D\x6E\x45\xBE\x55\xE8\x93\xD2\xCE\x03\x3F\xED\xDA\x25\xB0\x1D\x57\xCB\x1E\x3A\x76\xA0\x4C\xEC\x50\x76\xE8\x64\x72\x0C\xA4\xA9\xF1\xB8\x8B\xD6\xD6\x87\x84\xBB\x32\xE5\x41\x11\xC0\x77\xD9\xB3\x60\x9D\xEB\x1B\xD5\xD1\x6E\x44\x44\xA9\xA6\x01\xEC\x55\x62\x1D\x77\xB8\x5C\x8E\x48\x49\x7C\x9C\x3B\x57\x11\xAC\xAD\x73\x37\x8E\x2F\x78\x5C\x90\x68\x47\xD9\x60\x60\xE6\xFC\x07\x3D\x22\x20\x17\xC4\xF7\x16\xE9\xC4\xD8\x72\xF9\xC8\x73\x7C\xDF\x16\x2F\x15\xA9\x3E\xFD\x6A\x27\xB6\xA1\xEB\x5A\xBA\x98\x1F\xD5\xE3\x4D\x64\x0A\x9D\x13\xC8\x61\xBA\xF5\x39\x1C\x87\xBA\xB8\xBD\x7B\x22\x7F\xF6\xFE\xAC\x40\x79\xE5\xAC\x10\x6F\x3D\x8F\x1B\x79\x76\x8B\xC4\x37\xB3\x21\x18\x84\xE5\x36\x00\xEB\x63\x20\x99\xB9\xE9\xFE\x33\x04\xBB\x41\xC8\xC1\x02\xF9\x44\x63\x20\x9E\x81\xCE\x42\xD3\xD6\x3F\x2C\x76\xD3\x63\x9C\x59\xDD\x8F\xA6\xE1\x0E\xA0\x2E\x41\xF7\x2E\x95\x47\xCF\xBC\xFD\x33\xF3\xF6\x0B\x61\x7E\x7E\x91\x2B\x81\x47\xC2\x27\x30\xEE\xA7\x10\x5D\x37\x8F\x5C\x39\x2B\xE4\x04\xF0\x7B\x8D\x56\x8C\x68", - ["VeriSign Class 3 Public Primary Certification Authority - G5"] = "\x30\x82\x04\xD3\x30\x82\x03\xBB\xA0\x03\x02\x01\x02\x02\x10\x18\xDA\xD1\x9E\x26\x7D\xE8\xBB\x4A\x21\x58\xCD\xCC\x6B\x3B\x4A\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x32\x30\x30\x36\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x35\x30\x1E\x17\x0D\x30\x36\x31\x31\x30\x38\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x32\x30\x30\x36\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x35\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\xAF\x24\x08\x08\x29\x7A\x35\x9E\x60\x0C\xAA\xE7\x4B\x3B\x4E\xDC\x7C\xBC\x3C\x45\x1C\xBB\x2B\xE0\xFE\x29\x02\xF9\x57\x08\xA3\x64\x85\x15\x27\xF5\xF1\xAD\xC8\x31\x89\x5D\x22\xE8\x2A\xAA\xA6\x42\xB3\x8F\xF8\xB9\x55\xB7\xB1\xB7\x4B\xB3\xFE\x8F\x7E\x07\x57\xEC\xEF\x43\xDB\x66\x62\x15\x61\xCF\x60\x0D\xA4\xD8\xDE\xF8\xE0\xC3\x62\x08\x3D\x54\x13\xEB\x49\xCA\x59\x54\x85\x26\xE5\x2B\x8F\x1B\x9F\xEB\xF5\xA1\x91\xC2\x33\x49\xD8\x43\x63\x6A\x52\x4B\xD2\x8F\xE8\x70\x51\x4D\xD1\x89\x69\x7B\xC7\x70\xF6\xB3\xDC\x12\x74\xDB\x7B\x5D\x4B\x56\xD3\x96\xBF\x15\x77\xA1\xB0\xF4\xA2\x25\xF2\xAF\x1C\x92\x67\x18\xE5\xF4\x06\x04\xEF\x90\xB9\xE4\x00\xE4\xDD\x3A\xB5\x19\xFF\x02\xBA\xF4\x3C\xEE\xE0\x8B\xEB\x37\x8B\xEC\xF4\xD7\xAC\xF2\xF6\xF0\x3D\xAF\xDD\x75\x91\x33\x19\x1D\x1C\x40\xCB\x74\x24\x19\x21\x93\xD9\x14\xFE\xAC\x2A\x52\xC7\x8F\xD5\x04\x49\xE4\x8D\x63\x47\x88\x3C\x69\x83\xCB\xFE\x47\xBD\x2B\x7E\x4F\xC5\x95\xAE\x0E\x9D\xD4\xD1\x43\xC0\x67\x73\xE3\x14\x08\x7E\xE5\x3F\x9F\x73\xB8\x33\x0A\xCF\x5D\x3F\x34\x87\x96\x8A\xEE\x53\xE8\x25\x15\x02\x03\x01\x00\x01\xA3\x81\xB2\x30\x81\xAF\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x6D\x06\x08\x2B\x06\x01\x05\x05\x07\x01\x0C\x04\x61\x30\x5F\xA1\x5D\xA0\x5B\x30\x59\x30\x57\x30\x55\x16\x09\x69\x6D\x61\x67\x65\x2F\x67\x69\x66\x30\x21\x30\x1F\x30\x07\x06\x05\x2B\x0E\x03\x02\x1A\x04\x14\x8F\xE5\xD3\x1A\x86\xAC\x8D\x8E\x6B\xC3\xCF\x80\x6A\xD4\x48\x18\x2C\x7B\x19\x2E\x30\x25\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x6C\x6F\x67\x6F\x2E\x76\x65\x72\x69\x73\x69\x67\x6E\x2E\x63\x6F\x6D\x2F\x76\x73\x6C\x6F\x67\x6F\x2E\x67\x69\x66\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x7F\xD3\x65\xA7\xC2\xDD\xEC\xBB\xF0\x30\x09\xF3\x43\x39\xFA\x02\xAF\x33\x31\x33\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x93\x24\x4A\x30\x5F\x62\xCF\xD8\x1A\x98\x2F\x3D\xEA\xDC\x99\x2D\xBD\x77\xF6\xA5\x79\x22\x38\xEC\xC4\xA7\xA0\x78\x12\xAD\x62\x0E\x45\x70\x64\xC5\xE7\x97\x66\x2D\x98\x09\x7E\x5F\xAF\xD6\xCC\x28\x65\xF2\x01\xAA\x08\x1A\x47\xDE\xF9\xF9\x7C\x92\x5A\x08\x69\x20\x0D\xD9\x3E\x6D\x6E\x3C\x0D\x6E\xD8\xE6\x06\x91\x40\x18\xB9\xF8\xC1\xED\xDF\xDB\x41\xAA\xE0\x96\x20\xC9\xCD\x64\x15\x38\x81\xC9\x94\xEE\xA2\x84\x29\x0B\x13\x6F\x8E\xDB\x0C\xDD\x25\x02\xDB\xA4\x8B\x19\x44\xD2\x41\x7A\x05\x69\x4A\x58\x4F\x60\xCA\x7E\x82\x6A\x0B\x02\xAA\x25\x17\x39\xB5\xDB\x7F\xE7\x84\x65\x2A\x95\x8A\xBD\x86\xDE\x5E\x81\x16\x83\x2D\x10\xCC\xDE\xFD\xA8\x82\x2A\x6D\x28\x1F\x0D\x0B\xC4\xE5\xE7\x1A\x26\x19\xE1\xF4\x11\x6F\x10\xB5\x95\xFC\xE7\x42\x05\x32\xDB\xCE\x9D\x51\x5E\x28\xB6\x9E\x85\xD3\x5B\xEF\xA5\x7D\x45\x40\x72\x8E\xB7\x0E\x6B\x0E\x06\xFB\x33\x35\x48\x71\xB8\x9D\x27\x8B\xC4\x65\x5F\x0D\x86\x76\x9C\x44\x7A\xF6\x95\x5C\xF6\x5D\x32\x08\x33\xA4\x54\xB6\x18\x3F\x68\x5C\xF2\x42\x4A\x85\x38\x54\x83\x5F\xD1\xE8\x2C\xF2\xAC\x11\xD6\xA8\xED\x63\x6A", - ["SecureTrust CA"] = "\x30\x82\x03\xB8\x30\x82\x02\xA0\xA0\x03\x02\x01\x02\x02\x10\x0C\xF0\x8E\x5C\x08\x16\xA5\xAD\x42\x7F\xF0\xEB\x27\x18\x59\xD0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x48\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x13\x17\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x6F\x72\x70\x6F\x72\x61\x74\x69\x6F\x6E\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0E\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x31\x31\x30\x37\x31\x39\x33\x31\x31\x38\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x31\x39\x34\x30\x35\x35\x5A\x30\x48\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x13\x17\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x6F\x72\x70\x6F\x72\x61\x74\x69\x6F\x6E\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0E\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x41\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\xAB\xA4\x81\xE5\x95\xCD\xF5\xF6\x14\x8E\xC2\x4F\xCA\xD4\xE2\x78\x95\x58\x9C\x41\xE1\x0D\x99\x40\x24\x17\x39\x91\x33\x66\xE9\xBE\xE1\x83\xAF\x62\x5C\x89\xD1\xFC\x24\x5B\x61\xB3\xE0\x11\x11\x41\x1C\x1D\x6E\xF0\xB8\xBB\xF8\xDE\xA7\x81\xBA\xA6\x48\xC6\x9F\x1D\xBD\xBE\x8E\xA9\x41\x3E\xB8\x94\xED\x29\x1A\xD4\x8E\xD2\x03\x1D\x03\xEF\x6D\x0D\x67\x1C\x57\xD7\x06\xAD\xCA\xC8\xF5\xFE\x0E\xAF\x66\x25\x48\x04\x96\x0B\x5D\xA3\xBA\x16\xC3\x08\x4F\xD1\x46\xF8\x14\x5C\xF2\xC8\x5E\x01\x99\x6D\xFD\x88\xCC\x86\xA8\xC1\x6F\x31\x42\x6C\x52\x3E\x68\xCB\xF3\x19\x34\xDF\xBB\x87\x18\x56\x80\x26\xC4\xD0\xDC\xC0\x6F\xDF\xDE\xA0\xC2\x91\x16\xA0\x64\x11\x4B\x44\xBC\x1E\xF6\xE7\xFA\x63\xDE\x66\xAC\x76\xA4\x71\xA3\xEC\x36\x94\x68\x7A\x77\xA4\xB1\xE7\x0E\x2F\x81\x7A\xE2\xB5\x72\x86\xEF\xA2\x6B\x8B\xF0\x0F\xDB\xD3\x59\x3F\xBA\x72\xBC\x44\x24\x9C\xE3\x73\xB3\xF7\xAF\x57\x2F\x42\x26\x9D\xA9\x74\xBA\x00\x52\xF2\x4B\xCD\x53\x7C\x47\x0B\x36\x85\x0E\x66\xA9\x08\x97\x16\x34\x57\xC1\x66\xF7\x80\xE3\xED\x70\x54\xC7\x93\xE0\x2E\x28\x15\x59\x87\xBA\xBB\x02\x03\x01\x00\x01\xA3\x81\x9D\x30\x81\x9A\x30\x13\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x14\x02\x04\x06\x1E\x04\x00\x43\x00\x41\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x42\x32\xB6\x16\xFA\x04\xFD\xFE\x5D\x4B\x7A\xC3\xFD\xF7\x4C\x40\x1D\x5A\x43\xAF\x30\x34\x06\x03\x55\x1D\x1F\x04\x2D\x30\x2B\x30\x29\xA0\x27\xA0\x25\x86\x23\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x73\x65\x63\x75\x72\x65\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x2F\x53\x54\x43\x41\x2E\x63\x72\x6C\x30\x10\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x30\xED\x4F\x4A\xE1\x58\x3A\x52\x72\x5B\xB5\xA6\xA3\x65\x18\xA6\xBB\x51\x3B\x77\xE9\x9D\xEA\xD3\x9F\x5C\xE0\x45\x65\x7B\x0D\xCA\x5B\xE2\x70\x50\xB2\x94\x05\x14\xAE\x49\xC7\x8D\x41\x07\x12\x73\x94\x7E\x0C\x23\x21\xFD\xBC\x10\x7F\x60\x10\x5A\x72\xF5\x98\x0E\xAC\xEC\xB9\x7F\xDD\x7A\x6F\x5D\xD3\x1C\xF4\xFF\x88\x05\x69\x42\xA9\x05\x71\xC8\xB7\xAC\x26\xE8\x2E\xB4\x8C\x6A\xFF\x71\xDC\xB8\xB1\xDF\x99\xBC\x7C\x21\x54\x2B\xE4\x58\xA2\xBB\x57\x29\xAE\x9E\xA9\xA3\x19\x26\x0F\x99\x2E\x08\xB0\xEF\xFD\x69\xCF\x99\x1A\x09\x8D\xE3\xA7\x9F\x2B\xC9\x36\x34\x7B\x24\xB3\x78\x4C\x95\x17\xA4\x06\x26\x1E\xB6\x64\x52\x36\x5F\x60\x67\xD9\x9C\xC5\x05\x74\x0B\xE7\x67\x23\xD2\x08\xFC\x88\xE9\xAE\x8B\x7F\xE1\x30\xF4\x37\x7E\xFD\xC6\x32\xDA\x2D\x9E\x44\x30\x30\x6C\xEE\x07\xDE\xD2\x34\xFC\xD2\xFF\x40\xF6\x4B\xF4\x66\x46\x06\x54\xA6\xF2\x32\x0A\x63\x26\x30\x6B\x9B\xD1\xDC\x8B\x47\xBA\xE1\xB9\xD5\x62\xD0\xA2\xA0\xF4\x67\x05\x78\x29\x63\x1A\x6F\x04\xD6\xF8\xC6\x4C\xA3\x9A\xB1\x37\xB4\x8D\xE5\x28\x4B\x1D\x9E\x2C\xC2\xB8\x68\xBC\xED\x02\xEE\x31", - ["Secure Global CA"] = "\x30\x82\x03\xBC\x30\x82\x02\xA4\xA0\x03\x02\x01\x02\x02\x10\x07\x56\x22\xA4\xE8\xD4\x8A\x89\x4D\xF4\x13\xC8\xF0\xF8\xEA\xA5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x13\x17\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x6F\x72\x70\x6F\x72\x61\x74\x69\x6F\x6E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x65\x63\x75\x72\x65\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x31\x31\x30\x37\x31\x39\x34\x32\x32\x38\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x31\x39\x35\x32\x30\x36\x5A\x30\x4A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x13\x17\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x6F\x72\x70\x6F\x72\x61\x74\x69\x6F\x6E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x65\x63\x75\x72\x65\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x41\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\xAF\x35\x2E\xD8\xAC\x6C\x55\x69\x06\x71\xE5\x13\x68\x24\xB3\x4F\xD8\xCC\x21\x47\xF8\xF1\x60\x38\x89\x89\x03\xE9\xBD\xEA\x5E\x46\x53\x09\xDC\x5C\xF5\x5A\xE8\xF7\x45\x2A\x02\xEB\x31\x61\xD7\x29\x33\x4C\xCE\xC7\x7C\x0A\x37\x7E\x0F\xBA\x32\x98\xE1\x1D\x97\xAF\x8F\xC7\xDC\xC9\x38\x96\xF3\xDB\x1A\xFC\x51\xED\x68\xC6\xD0\x6E\xA4\x7C\x24\xD1\xAE\x42\xC8\x96\x50\x63\x2E\xE0\xFE\x75\xFE\x98\xA7\x5F\x49\x2E\x95\xE3\x39\x33\x64\x8E\x1E\xA4\x5F\x90\xD2\x67\x3C\xB2\xD9\xFE\x41\xB9\x55\xA7\x09\x8E\x72\x05\x1E\x8B\xDD\x44\x85\x82\x42\xD0\x49\xC0\x1D\x60\xF0\xD1\x17\x2C\x95\xEB\xF6\xA5\xC1\x92\xA3\xC5\xC2\xA7\x08\x60\x0D\x60\x04\x10\x96\x79\x9E\x16\x34\xE6\xA9\xB6\xFA\x25\x45\x39\xC8\x1E\x65\xF9\x93\xF5\xAA\xF1\x52\xDC\x99\x98\x3D\xA5\x86\x1A\x0C\x35\x33\xFA\x4B\xA5\x04\x06\x15\x1C\x31\x80\xEF\xAA\x18\x6B\xC2\x7B\xD7\xDA\xCE\xF9\x33\x20\xD5\xF5\xBD\x6A\x33\x2D\x81\x04\xFB\xB0\x5C\xD4\x9C\xA3\xE2\x5C\x1D\xE3\xA9\x42\x75\x5E\x7B\xD4\x77\xEF\x39\x54\xBA\xC9\x0A\x18\x1B\x12\x99\x49\x2F\x88\x4B\xFD\x50\x62\xD1\x73\xE7\x8F\x7A\x43\x02\x03\x01\x00\x01\xA3\x81\x9D\x30\x81\x9A\x30\x13\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x14\x02\x04\x06\x1E\x04\x00\x43\x00\x41\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xAF\x44\x04\xC2\x41\x7E\x48\x83\xDB\x4E\x39\x02\xEC\xEC\x84\x7A\xE6\xCE\xC9\xA4\x30\x34\x06\x03\x55\x1D\x1F\x04\x2D\x30\x2B\x30\x29\xA0\x27\xA0\x25\x86\x23\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x73\x65\x63\x75\x72\x65\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x2F\x53\x47\x43\x41\x2E\x63\x72\x6C\x30\x10\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x63\x1A\x08\x40\x7D\xA4\x5E\x53\x0D\x77\xD8\x7A\xAE\x1F\x0D\x0B\x51\x16\x03\xEF\x18\x7C\xC8\xE3\xAF\x6A\x58\x93\x14\x60\x91\xB2\x84\xDC\x88\x4E\xBE\x39\x8A\x3A\xF3\xE6\x82\x89\x5D\x01\x37\xB3\xAB\x24\xA4\x15\x0E\x92\x35\x5A\x4A\x44\x5E\x4E\x57\xFA\x75\xCE\x1F\x48\xCE\x66\xF4\x3C\x40\x26\x92\x98\x6C\x1B\xEE\x24\x46\x0C\x17\xB3\x52\xA5\xDB\xA5\x91\x91\xCF\x37\xD3\x6F\xE7\x27\x08\x3A\x4E\x19\x1F\x3A\xA7\x58\x5C\x17\xCF\x79\x3F\x8B\xE4\xA7\xD3\x26\x23\x9D\x26\x0F\x58\x69\xFC\x47\x7E\xB2\xD0\x8D\x8B\x93\xBF\x29\x4F\x43\x69\x74\x76\x67\x4B\xCF\x07\x8C\xE6\x02\xF7\xB5\xE1\xB4\x43\xB5\x4B\x2D\x14\x9F\xF9\xDC\x26\x0D\xBF\xA6\x47\x74\x06\xD8\x88\xD1\x3A\x29\x30\x84\xCE\xD2\x39\x80\x62\x1B\xA8\xC7\x57\x49\xBC\x6A\x55\x51\x67\x15\x4A\xBE\x35\x07\xE4\xD5\x75\x98\x37\x79\x30\x14\xDB\x29\x9D\x6C\xC5\x69\xCC\x47\x55\xA2\x30\xF7\xCC\x5C\x7F\xC2\xC3\x98\x1C\x6B\x4E\x16\x80\xEB\x7A\x78\x65\x45\xA2\x00\x1A\xAF\x0C\x0D\x55\x64\x34\x48\xB8\x92\xB9\xF1\xB4\x50\x29\xF2\x4F\x23\x1F\xDA\x6C\xAC\x1F\x44\xE1\xDD\x23\x78\x51\x5B\xC7\x16", - ["COMODO Certification Authority"] = "\x30\x82\x04\x1D\x30\x82\x03\x05\xA0\x03\x02\x01\x02\x02\x10\x4E\x81\x2D\x8A\x82\x65\xE0\x0B\x02\xEE\x3E\x35\x02\x46\xE5\x3D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x81\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x13\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x13\x11\x43\x4F\x4D\x4F\x44\x4F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x43\x4F\x4D\x4F\x44\x4F\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x36\x31\x32\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x81\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x13\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x13\x11\x43\x4F\x4D\x4F\x44\x4F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x43\x4F\x4D\x4F\x44\x4F\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xD0\x40\x8B\x8B\x72\xE3\x91\x1B\xF7\x51\xC1\x1B\x54\x04\x98\xD3\xA9\xBF\xC1\xE6\x8A\x5D\x3B\x87\xFB\xBB\x88\xCE\x0D\xE3\x2F\x3F\x06\x96\xF0\xA2\x29\x50\x99\xAE\xDB\x3B\xA1\x57\xB0\x74\x51\x71\xCD\xED\x42\x91\x4D\x41\xFE\xA9\xC8\xD8\x6A\x86\x77\x44\xBB\x59\x66\x97\x50\x5E\xB4\xD4\x2C\x70\x44\xCF\xDA\x37\x95\x42\x69\x3C\x30\xC4\x71\xB3\x52\xF0\x21\x4D\xA1\xD8\xBA\x39\x7C\x1C\x9E\xA3\x24\x9D\xF2\x83\x16\x98\xAA\x16\x7C\x43\x9B\x15\x5B\xB7\xAE\x34\x91\xFE\xD4\x62\x26\x18\x46\x9A\x3F\xEB\xC1\xF9\xF1\x90\x57\xEB\xAC\x7A\x0D\x8B\xDB\x72\x30\x6A\x66\xD5\xE0\x46\xA3\x70\xDC\x68\xD9\xFF\x04\x48\x89\x77\xDE\xB5\xE9\xFB\x67\x6D\x41\xE9\xBC\x39\xBD\x32\xD9\x62\x02\xF1\xB1\xA8\x3D\x6E\x37\x9C\xE2\x2F\xE2\xD3\xA2\x26\x8B\xC6\xB8\x55\x43\x88\xE1\x23\x3E\xA5\xD2\x24\x39\x6A\x47\xAB\x00\xD4\xA1\xB3\xA9\x25\xFE\x0D\x3F\xA7\x1D\xBA\xD3\x51\xC1\x0B\xA4\xDA\xAC\x38\xEF\x55\x50\x24\x05\x65\x46\x93\x34\x4F\x2D\x8D\xAD\xC6\xD4\x21\x19\xD2\x8E\xCA\x05\x61\x71\x07\x73\x47\xE5\x8A\x19\x12\xBD\x04\x4D\xCE\x4E\x9C\xA5\x48\xAC\xBB\x26\xF7\x02\x03\x01\x00\x01\xA3\x81\x8E\x30\x81\x8B\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x0B\x58\xE5\x8B\xC6\x4C\x15\x37\xA4\x40\xA9\x30\xA9\x21\xBE\x47\x36\x5A\x56\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x49\x06\x03\x55\x1D\x1F\x04\x42\x30\x40\x30\x3E\xA0\x3C\xA0\x3A\x86\x38\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x63\x61\x2E\x63\x6F\x6D\x2F\x43\x4F\x4D\x4F\x44\x4F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3E\x98\x9E\x9B\xF6\x1B\xE9\xD7\x39\xB7\x78\xAE\x1D\x72\x18\x49\xD3\x87\xE4\x43\x82\xEB\x3F\xC9\xAA\xF5\xA8\xB5\xEF\x55\x7C\x21\x52\x65\xF9\xD5\x0D\xE1\x6C\xF4\x3E\x8C\x93\x73\x91\x2E\x02\xC4\x4E\x07\x71\x6F\xC0\x8F\x38\x61\x08\xA8\x1E\x81\x0A\xC0\x2F\x20\x2F\x41\x8B\x91\xDC\x48\x45\xBC\xF1\xC6\xDE\xBA\x76\x6B\x33\xC8\x00\x2D\x31\x46\x4C\xED\xE7\x9D\xCF\x88\x94\xFF\x33\xC0\x56\xE8\x24\x86\x26\xB8\xD8\x38\x38\xDF\x2A\x6B\xDD\x12\xCC\xC7\x3F\x47\x17\x4C\xA2\xC2\x06\x96\x09\xD6\xDB\xFE\x3F\x3C\x46\x41\xDF\x58\xE2\x56\x0F\x3C\x3B\xC1\x1C\x93\x35\xD9\x38\x52\xAC\xEE\xC8\xEC\x2E\x30\x4E\x94\x35\xB4\x24\x1F\x4B\x78\x69\xDA\xF2\x02\x38\xCC\x95\x52\x93\xF0\x70\x25\x59\x9C\x20\x67\xC4\xEE\xF9\x8B\x57\x61\xF4\x92\x76\x7D\x3F\x84\x8D\x55\xB7\xE8\xE5\xAC\xD5\xF1\xF5\x19\x56\xA6\x5A\xFB\x90\x1C\xAF\x93\xEB\xE5\x1C\xD4\x67\x97\x5D\x04\x0E\xBE\x0B\x83\xA6\x17\x83\xB9\x30\x12\xA0\xC5\x33\x15\x05\xB9\x0D\xFB\xC7\x05\x76\xE3\xD8\x4A\x8D\xFC\x34\x17\xA3\xC6\x21\x28\xBE\x30\x45\x31\x1E\xC7\x78\xBE\x58\x61\x38\xAC\x3B\xE2\x01\x65", - ["DigiNotar Root CA"] = "\x30\x82\x05\x8A\x30\x82\x03\x72\xA0\x03\x02\x01\x02\x02\x10\x0C\x76\xDA\x9C\x91\x0C\x4E\x2C\x9E\xFE\x15\xD0\x58\x93\x3C\x4C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x5F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4C\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x13\x09\x44\x69\x67\x69\x4E\x6F\x74\x61\x72\x31\x1A\x30\x18\x06\x03\x55\x04\x03\x13\x11\x44\x69\x67\x69\x4E\x6F\x74\x61\x72\x20\x52\x6F\x6F\x74\x20\x43\x41\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x64\x69\x67\x69\x6E\x6F\x74\x61\x72\x2E\x6E\x6C\x30\x1E\x17\x0D\x30\x37\x30\x35\x31\x36\x31\x37\x31\x39\x33\x36\x5A\x17\x0D\x32\x35\x30\x33\x33\x31\x31\x38\x31\x39\x32\x31\x5A\x30\x5F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4C\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x13\x09\x44\x69\x67\x69\x4E\x6F\x74\x61\x72\x31\x1A\x30\x18\x06\x03\x55\x04\x03\x13\x11\x44\x69\x67\x69\x4E\x6F\x74\x61\x72\x20\x52\x6F\x6F\x74\x20\x43\x41\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x64\x69\x67\x69\x6E\x6F\x74\x61\x72\x2E\x6E\x6C\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xAC\xB0\x58\xC1\x00\xBD\xD8\x21\x08\x0B\x2B\x9A\xFE\x6E\x56\x30\x05\x9F\x1B\x77\x90\x10\x41\x5C\xC3\x0D\x87\x11\x77\x8E\x81\xF1\xCA\x7C\xE9\x8C\x6A\xED\x38\x74\x35\xBB\xDA\xDF\xF9\xBB\xC0\x09\x37\xB4\x96\x73\x81\x7D\x33\x1A\x98\x39\xF7\x93\x6F\x95\x7F\x3D\xB9\xB1\x75\x87\xBA\x51\x48\xE8\x8B\x70\x3E\x95\x04\xC5\xD8\xB6\xC3\x16\xD9\x88\xB0\xB1\x87\x1D\x70\xDA\x86\xB4\x0F\x14\x8B\x7A\xCF\x10\xD1\x74\x36\xA2\x12\x7B\x77\x86\x4A\x79\xE6\x7B\xDF\x02\x11\x68\xA5\x4E\x86\xAE\x34\x58\x9B\x24\x13\x78\x56\x22\x25\x1E\x01\x8B\x4B\x51\x71\xFB\x82\xCC\x59\x96\x69\x88\x5A\x68\x53\xC5\xB9\x0D\x02\x37\xCB\x4B\xBC\x66\x4A\x90\x7E\x2A\x0B\x05\x07\xED\x16\x5F\x55\x90\x75\xD8\x46\xC9\x1B\x83\xE2\x08\xBE\xF1\x23\xCC\x99\x1D\xD6\x2A\x0F\x83\x20\x15\x58\x27\x82\x2E\xFA\xE2\x22\xC2\x49\xB1\xB9\x01\x81\x6A\x9D\x6D\x9D\x40\x77\x68\x76\x4E\x21\x2A\x6D\x84\x40\x85\x4E\x76\x99\x7C\x82\xF3\xF3\xB7\x02\x59\xD4\x26\x01\x1B\x8E\xDF\xAD\x53\x06\xD1\xAE\x18\xDD\xE2\xB2\x3A\xCB\xD7\x88\x38\x8E\xAC\x5B\x29\xB9\x19\xD3\x98\xF9\x18\x03\xCF\x48\x82\x86\x66\x0B\x1B\x69\x0F\xC9\xEB\x38\x88\x7A\x26\x1A\x05\x4C\x92\xD7\x24\xD4\x96\xF2\xAC\x52\x2D\xA3\x47\xD5\x52\xF6\x3F\xFE\xCE\x84\x06\x70\xA6\xAA\x3E\xA2\xF2\xB6\x56\x34\x18\x57\xA2\xE4\x81\x6D\xE7\xCA\xF0\x6A\xD3\xC7\x91\x6B\x02\x83\x41\x7C\x15\xEF\x6B\x9A\x64\x5E\xE3\xD0\x3C\xE5\xB1\xEB\x7B\x5D\x86\xFB\xCB\xE6\x77\x49\xCD\xA3\x65\xDC\xF7\xB9\x9C\xB8\xE4\x0B\x5F\x93\xCF\xCC\x30\x1A\x32\x1C\xCE\x1C\x63\x95\xA5\xF9\xEA\xE1\x74\x8B\x9E\xE9\x2B\xA9\x30\x7B\xA0\x18\x1F\x0E\x18\x0B\xE5\x5B\xA9\xD3\xD1\x6C\x1E\x07\x67\x8F\x91\x4B\xA9\x8A\xBC\xD2\x66\xAA\x93\x01\x88\xB2\x91\xFA\x31\x5C\xD5\xA6\xC1\x52\x08\x09\xCD\x0A\x63\xA2\xD3\x22\xA6\xE8\xA1\xD9\x39\x06\x97\xF5\x6E\x8D\x02\x90\x8C\x14\x7B\x3F\x80\xCD\x1B\x9C\xBA\xC4\x58\x72\x23\xAF\xB6\x56\x9F\xC6\x7A\x42\x33\x29\x07\x3F\x82\xC9\xE6\x1F\x05\x0D\xCD\x4C\x28\x36\x8B\xD3\xC8\x3E\x1C\xC6\x88\xEF\x5E\xEE\x89\x64\xE9\x1D\xEB\xDA\x89\x7E\x32\xA6\x69\xD1\xDD\xCC\x88\x9F\xD1\xD0\xC9\x66\x21\xDC\x06\x67\xC5\x94\x7A\x9A\x6D\x62\x4C\x7D\xCC\xE0\x64\x80\xB2\x9E\x47\x8E\xA3\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x88\x68\xBF\xE0\x8E\x35\xC4\x3B\x38\x6B\x62\xF7\x28\x3B\x84\x81\xC8\x0C\xD7\x4D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x3B\x02\x8D\xCB\x3C\x30\xE8\x6E\xA0\xAD\xF2\x73\xB3\x5F\x9E\x25\x13\x04\x05\xD3\xF6\xE3\x8B\xBB\x0B\x79\xCE\x53\xDE\xE4\x96\xC5\xD1\xAF\x73\xBC\xD5\xC3\xD0\x40\x55\x7C\x40\x7F\xCD\x1B\x5F\x09\xD5\xF2\x7C\x9F\x68\x1D\xBB\x5D\xCE\x7A\x39\xC2\x8C\xD6\x98\x7B\xC5\x83\x55\xA8\xD5\x7D\x40\xCA\xE0\x1E\xF7\x89\x5E\x63\x5D\xA1\x13\xC2\x5D\x8A\xB6\x8A\x7C\x00\xF3\x23\xC3\xED\x85\x5F\x71\x76\xF0\x68\x63\xAA\x45\x21\x39\x48\x61\x78\x36\xDC\xF1\x43\x93\xD4\x25\xC7\xF2\x80\x65\xE1\x53\x02\x75\x51\xFC\x7A\x3A\xEF\x37\xAB\x84\x28\x57\x0C\xD8\xD4\xD4\x99\x56\x6C\xE3\xA2\xFE\x59\x84\xB4\x31\xE8\x33\xF8\x64\x94\x94\x51\x97\xAB\x39\xC5\x4B\xED\xDA\xDD\x80\x0B\x6F\x7C\x29\x0D\xC4\x8E\x8A\x72\x0D\xE7\x53\x14\xB2\x60\x41\x3D\x84\x91\x31\x68\x3D\x27\x44\xDB\xE5\xDE\xF4\xFA\x63\x45\xC8\x4C\x3E\x98\xF5\x3F\x41\xBA\x4E\xCB\x37\x0D\xBA\x66\x98\xF1\xDD\xCB\x9F\x5C\xF7\x54\x36\x82\x6B\x2C\xBC\x13\x61\x97\x42\xF8\x78\xBB\xCC\xC8\xA2\x9F\xCA\xF0\x68\xBD\x6B\x1D\xB2\xDF\x8D\x6F\x07\x9D\xDA\x8E\x67\xC7\x47\x1E\xCA\xB9\xBF\x2A\x42\x91\xB7\x63\x53\x66\xF1\x42\xA3\xE1\xF4\x5A\x4D\x58\x6B\xB5\xE4\xA4\x33\xAD\x5C\x70\x1D\xDC\xE0\xF2\xEB\x73\x14\x91\x9A\x03\xC1\xEA\x00\x65\xBC\x07\xFC\xCF\x12\x11\x22\x2C\xAE\xA0\xBD\x3A\xE0\xA2\x2A\xD8\x59\xE9\x29\xD3\x18\x35\xA4\xAC\x11\x5F\x19\xB5\xB5\x1B\xFF\x22\x4A\x5C\xC6\x7A\xE4\x17\xEF\x20\xA9\xA7\xF4\x3F\xAD\x8A\xA7\x9A\x04\x25\x9D\x0E\xCA\x37\xE6\x50\xFD\x8C\x42\x29\x04\x9A\xEC\xB9\xCF\x4B\x72\xBD\xE2\x08\x36\xAF\x23\x2F\x62\xE5\xCA\x01\xD3\x70\xDB\x7C\x82\x23\x2C\x16\x31\x0C\xC6\x36\x07\x90\x7A\xB1\x1F\x67\x58\xC4\x3B\x58\x59\x89\xB0\x8C\x8C\x50\xB3\xD8\x86\xCB\x68\xA3\xC4\x0A\xE7\x69\x4B\x20\xCE\xC1\x1E\x56\x4B\x95\xA9\x23\x68\xD8\x30\xD8\xC3\xEB\xB0\x55\x51\xCD\xE5\xFD\x2B\xB8\xF5\xBB\x11\x9F\x53\x54\xF6\x34\x19\x8C\x79\x09\x36\xCA\x61\x17\x25\x17\x0B\x82\x98\x73\x0C\x77\x74\xC3\xD5\x0D\xC7\xA8\x12\x4C\xC7\xA7\x54\x71\x47\x2E\x2C\x1A\x7D\xC9\xE3\x2B\x3B\x48\xDE\x27\x84\xA7\x63\x36\xB3\x7D\x8F\xA0\x64\x39\x24\x0D\x3D\x7B\x87\xAF\x66\x5C\x74\x1B\x4B\x73\xB2\xE5\x8C\xF0\x86\x99\xB8\xE5\xC5\xDF\x84\xC1\xB7\xEB", - ["Network Solutions Certificate Authority"] = "\x30\x82\x03\xE6\x30\x82\x02\xCE\xA0\x03\x02\x01\x02\x02\x10\x57\xCB\x33\x6F\xC2\x5C\x16\xE6\x47\x16\x17\xE3\x90\x31\x68\xE0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x62\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1F\x06\x03\x55\x04\x0A\x13\x18\x4E\x65\x74\x77\x6F\x72\x6B\x20\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x20\x4C\x2E\x4C\x2E\x43\x2E\x31\x30\x30\x2E\x06\x03\x55\x04\x03\x13\x27\x4E\x65\x74\x77\x6F\x72\x6B\x20\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x36\x31\x32\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x62\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1F\x06\x03\x55\x04\x0A\x13\x18\x4E\x65\x74\x77\x6F\x72\x6B\x20\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x20\x4C\x2E\x4C\x2E\x43\x2E\x31\x30\x30\x2E\x06\x03\x55\x04\x03\x13\x27\x4E\x65\x74\x77\x6F\x72\x6B\x20\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xE4\xBC\x7E\x92\x30\x6D\xC6\xD8\x8E\x2B\x0B\xBC\x46\xCE\xE0\x27\x96\xDE\xDE\xF9\xFA\x12\xD3\x3C\x33\x73\xB3\x04\x2F\xBC\x71\x8C\xE5\x9F\xB6\x22\x60\x3E\x5F\x5D\xCE\x09\xFF\x82\x0C\x1B\x9A\x51\x50\x1A\x26\x89\xDD\xD5\x61\x5D\x19\xDC\x12\x0F\x2D\x0A\xA2\x43\x5D\x17\xD0\x34\x92\x20\xEA\x73\xCF\x38\x2C\x06\x26\x09\x7A\x72\xF7\xFA\x50\x32\xF8\xC2\x93\xD3\x69\xA2\x23\xCE\x41\xB1\xCC\xE4\xD5\x1F\x36\xD1\x8A\x3A\xF8\x8C\x63\xE2\x14\x59\x69\xED\x0D\xD3\x7F\x6B\xE8\xB8\x03\xE5\x4F\x6A\xE5\x98\x63\x69\x48\x05\xBE\x2E\xFF\x33\xB6\xE9\x97\x59\x69\xF8\x67\x19\xAE\x93\x61\x96\x44\x15\xD3\x72\xB0\x3F\xBC\x6A\x7D\xEC\x48\x7F\x8D\xC3\xAB\xAA\x71\x2B\x53\x69\x41\x53\x34\xB5\xB0\xB9\xC5\x06\x0A\xC4\xB0\x45\xF5\x41\x5D\x6E\x89\x45\x7B\x3D\x3B\x26\x8C\x74\xC2\xE5\xD2\xD1\x7D\xB2\x11\xD4\xFB\x58\x32\x22\x9A\x80\xC9\xDC\xFD\x0C\xE9\x7F\x5E\x03\x97\xCE\x3B\x00\x14\x87\x27\x70\x38\xA9\x8E\x6E\xB3\x27\x76\x98\x51\xE0\x05\xE3\x21\xAB\x1A\xD5\x85\x22\x3C\x29\xB5\x9A\x16\xC5\x80\xA8\xF4\xBB\x6B\x30\x8F\x2F\x46\x02\xA2\xB1\x0C\x22\xE0\xD3\x02\x03\x01\x00\x01\xA3\x81\x97\x30\x81\x94\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x21\x30\xC9\xFB\x00\xD7\x4E\x98\xDA\x87\xAA\x2A\xD0\xA7\x2E\xB1\x40\x31\xA7\x4C\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x52\x06\x03\x55\x1D\x1F\x04\x4B\x30\x49\x30\x47\xA0\x45\xA0\x43\x86\x41\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x6E\x65\x74\x73\x6F\x6C\x73\x73\x6C\x2E\x63\x6F\x6D\x2F\x4E\x65\x74\x77\x6F\x72\x6B\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xBB\xAE\x4B\xE7\xB7\x57\xEB\x7F\xAA\x2D\xB7\x73\x47\x85\x6A\xC1\xE4\xA5\x1D\xE4\xE7\x3C\xE9\xF4\x59\x65\x77\xB5\x7A\x5B\x5A\x8D\x25\x36\xE0\x7A\x97\x2E\x38\xC0\x57\x60\x83\x98\x06\x83\x9F\xB9\x76\x7A\x6E\x50\xE0\xBA\x88\x2C\xFC\x45\xCC\x18\xB0\x99\x95\x51\x0E\xEC\x1D\xB8\x88\xFF\x87\x50\x1C\x82\xC2\xE3\xE0\x32\x80\xBF\xA0\x0B\x47\xC8\xC3\x31\xEF\x99\x67\x32\x80\x4F\x17\x21\x79\x0C\x69\x5C\xDE\x5E\x34\xAE\x02\xB5\x26\xEA\x50\xDF\x7F\x18\x65\x2C\xC9\xF2\x63\xE1\xA9\x07\xFE\x7C\x71\x1F\x6B\x33\x24\x6A\x1E\x05\xF7\x05\x68\xC0\x6A\x12\xCB\x2E\x5E\x61\xCB\xAE\x28\xD3\x7E\xC2\xB4\x66\x91\x26\x5F\x3C\x2E\x24\x5F\xCB\x58\x0F\xEB\x28\xEC\xAF\x11\x96\xF3\xDC\x7B\x6F\xC0\xA7\x88\xF2\x53\x77\xB3\x60\x5E\xAE\xAE\x28\xDA\x35\x2C\x6F\x34\x45\xD3\x26\xE1\xDE\xEC\x5B\x4F\x27\x6B\x16\x7C\xBD\x44\x04\x18\x82\xB3\x89\x79\x17\x10\x71\x3D\x7A\xA2\x16\x4E\xF5\x01\xCD\xA4\x6C\x65\x68\xA1\x49\x76\x5C\x43\xC9\xD8\xBC\x36\x67\x6C\xA5\x94\xB5\xD4\xCC\xB9\xBD\x6A\x35\x56\x21\xDE\xD8\xC3\xEB\xFB\xCB\xA4\x60\x4C\xB0\x55\xA0\xA0\x7B\x57\xB2", - ["WellsSecure Public Root Certificate Authority"] = "\x30\x82\x04\xBD\x30\x82\x03\xA5\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x0C\x17\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x57\x65\x6C\x6C\x73\x53\x65\x63\x75\x72\x65\x31\x1C\x30\x1A\x06\x03\x55\x04\x0B\x0C\x13\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x42\x61\x6E\x6B\x20\x4E\x41\x31\x36\x30\x34\x06\x03\x55\x04\x03\x0C\x2D\x57\x65\x6C\x6C\x73\x53\x65\x63\x75\x72\x65\x20\x50\x75\x62\x6C\x69\x63\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x37\x31\x32\x31\x33\x31\x37\x30\x37\x35\x34\x5A\x17\x0D\x32\x32\x31\x32\x31\x34\x30\x30\x30\x37\x35\x34\x5A\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x0C\x17\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x57\x65\x6C\x6C\x73\x53\x65\x63\x75\x72\x65\x31\x1C\x30\x1A\x06\x03\x55\x04\x0B\x0C\x13\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x42\x61\x6E\x6B\x20\x4E\x41\x31\x36\x30\x34\x06\x03\x55\x04\x03\x0C\x2D\x57\x65\x6C\x6C\x73\x53\x65\x63\x75\x72\x65\x20\x50\x75\x62\x6C\x69\x63\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xEE\x6F\xB4\xBD\x79\xE2\x8F\x08\x21\x9E\x38\x04\x41\x25\xEF\xAB\x5B\x1C\x53\x92\xAC\x6D\x9E\xDD\xC2\xC4\x2E\x45\x94\x03\x35\x88\x67\x74\x57\xE3\xDF\x8C\xB8\xA7\x76\x8F\x3B\xF7\xA8\xC4\xDB\x29\x63\x0E\x91\x68\x36\x8A\x97\x8E\x8A\x71\x68\x09\x07\xE4\xE8\xD4\x0E\x4F\xF8\xD6\x2B\x4C\xA4\x16\xF9\xEF\x43\x98\x8F\xB3\x9E\x52\xDF\x6D\x91\x39\x8F\x38\xBD\x77\x8B\x43\x63\xEB\xB7\x93\xFC\x30\x4C\x1C\x01\x93\xB6\x13\xFB\xF7\xA1\x1F\xBF\x25\xE1\x74\x37\x2C\x1E\xA4\x5E\x3C\x68\xF8\x4B\xBF\x0D\xB9\x1E\x2E\x36\xE8\xA9\xE4\xA7\xF8\x0F\xCB\x82\x75\x7C\x35\x2D\x22\xD6\xC2\xBF\x0B\xF3\xB4\xFC\x6C\x95\x61\x1E\x57\xD7\x04\x81\x32\x83\x52\x79\xE6\x83\x63\xCF\xB7\xCB\x63\x8B\x11\xE2\xBD\x5E\xEB\xF6\x8D\xED\x95\x72\x28\xB4\xAC\x12\x62\xE9\x4A\x33\xE6\x83\x32\xAE\x05\x75\x95\xBD\x84\x95\xDB\x2A\x5C\x9B\x8E\x2E\x0C\xB8\x81\x2B\x41\xE6\x38\x56\x9F\x49\x9B\x6C\x76\xFA\x8A\x5D\xF7\x01\x79\x81\x7C\xC1\x83\x40\x05\xFE\x71\xFD\x0C\x3F\xCC\x4E\x60\x09\x0E\x65\x47\x10\x2F\x01\xC0\x05\x3F\x8F\xF8\xB3\x41\xEF\x5A\x42\x7E\x59\xEF\xD2\x97\x0C\x65\x02\x03\x01\x00\x01\xA3\x82\x01\x34\x30\x82\x01\x30\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x39\x06\x03\x55\x1D\x1F\x04\x32\x30\x30\x30\x2E\xA0\x2C\xA0\x2A\x86\x28\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x70\x6B\x69\x2E\x77\x65\x6C\x6C\x73\x66\x61\x72\x67\x6F\x2E\x63\x6F\x6D\x2F\x77\x73\x70\x72\x63\x61\x2E\x63\x72\x6C\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\xC6\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x26\x95\x19\x10\xD9\xE8\xA1\x97\x91\xFF\xDC\x19\xD9\xB5\x04\x3E\xD2\x73\x0A\x6A\x30\x81\xB2\x06\x03\x55\x1D\x23\x04\x81\xAA\x30\x81\xA7\x80\x14\x26\x95\x19\x10\xD9\xE8\xA1\x97\x91\xFF\xDC\x19\xD9\xB5\x04\x3E\xD2\x73\x0A\x6A\xA1\x81\x8B\xA4\x81\x88\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x0C\x17\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x57\x65\x6C\x6C\x73\x53\x65\x63\x75\x72\x65\x31\x1C\x30\x1A\x06\x03\x55\x04\x0B\x0C\x13\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x42\x61\x6E\x6B\x20\x4E\x41\x31\x36\x30\x34\x06\x03\x55\x04\x03\x0C\x2D\x57\x65\x6C\x6C\x73\x53\x65\x63\x75\x72\x65\x20\x50\x75\x62\x6C\x69\x63\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xB9\x15\xB1\x44\x91\xCC\x23\xC8\x2B\x4D\x77\xE3\xF8\x9A\x7B\x27\x0D\xCD\x72\xBB\x99\x00\xCA\x7C\x66\x19\x50\xC6\xD5\x98\xED\xAB\xBF\x03\x5A\xE5\x4D\xE5\x1E\xC8\x4F\x71\x97\x86\xD5\xE3\x1D\xFD\x90\xC9\x3C\x75\x77\x57\x7A\x7D\xF8\xDE\xF4\xD4\xD5\xF7\x95\xE6\x74\x6E\x1D\x3C\xAE\x7C\x9D\xDB\x02\x03\x05\x2C\x71\x4B\x25\x3E\x07\xE3\x5E\x9A\xF5\x66\x17\x29\x88\x1A\x38\x9F\xCF\xAA\x41\x03\x84\x97\x6B\x93\x38\x7A\xCA\x30\x44\x1B\x24\x44\x33\xD0\xE4\xD1\xDC\x28\x38\xF4\x13\x43\x35\x35\x29\x63\xA8\x7C\xA2\xB5\xAD\x38\xA4\xED\xAD\xFD\xC6\x9A\x1F\xFF\x97\x73\xFE\xFB\xB3\x35\xA7\x93\x86\xC6\x76\x91\x00\xE6\xAC\x51\x16\xC4\x27\x32\x5C\xDB\x73\xDA\xA5\x93\x57\x8E\x3E\x6D\x35\x26\x08\x59\xD5\xE7\x44\xD7\x76\x20\x63\xE7\xAC\x13\x67\xC3\x6D\xB1\x70\x46\x7C\xD5\x96\x11\x3D\x89\x6F\x5D\xA8\xA1\xEB\x8D\x0A\xDA\xC3\x1D\x33\x6C\xA3\xEA\x67\x19\x9A\x99\x7F\x4B\x3D\x83\x51\x2A\x1D\xCA\x2F\x86\x0C\xA2\x7E\x10\x2D\x2B\xD4\x16\x95\x0B\x07\xAA\x2E\x14\x92\x49\xB7\x29\x6F\xD8\x6D\x31\x7D\xF5\xFC\xA1\x10\x07\x87\xCE\x2F\x59\xDC\x3E\x58\xDB", - ["COMODO ECC Certification Authority"] = "\x30\x82\x02\x89\x30\x82\x02\x0F\xA0\x03\x02\x01\x02\x02\x10\x1F\x47\xAF\xAA\x62\x00\x70\x50\x54\x4C\x01\x9E\x9B\x63\x99\x2A\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x13\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x13\x11\x43\x4F\x4D\x4F\x44\x4F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x2B\x30\x29\x06\x03\x55\x04\x03\x13\x22\x43\x4F\x4D\x4F\x44\x4F\x20\x45\x43\x43\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x38\x30\x33\x30\x36\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x38\x30\x31\x31\x38\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x13\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x13\x11\x43\x4F\x4D\x4F\x44\x4F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x2B\x30\x29\x06\x03\x55\x04\x03\x13\x22\x43\x4F\x4D\x4F\x44\x4F\x20\x45\x43\x43\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x76\x30\x10\x06\x07\x2A\x86\x48\xCE\x3D\x02\x01\x06\x05\x2B\x81\x04\x00\x22\x03\x62\x00\x04\x03\x47\x7B\x2F\x75\xC9\x82\x15\x85\xFB\x75\xE4\x91\x16\xD4\xAB\x62\x99\xF5\x3E\x52\x0B\x06\xCE\x41\x00\x7F\x97\xE1\x0A\x24\x3C\x1D\x01\x04\xEE\x3D\xD2\x8D\x09\x97\x0C\xE0\x75\xE4\xFA\xFB\x77\x8A\x2A\xF5\x03\x60\x4B\x36\x8B\x16\x23\x16\xAD\x09\x71\xF4\x4A\xF4\x28\x50\xB4\xFE\x88\x1C\x6E\x3F\x6C\x2F\x2F\x09\x59\x5B\xA5\x5B\x0B\x33\x99\xE2\xC3\x3D\x89\xF9\x6A\x2C\xEF\xB2\xD3\x06\xE9\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x75\x71\xA7\x19\x48\x19\xBC\x9D\x9D\xEA\x41\x47\xDF\x94\xC4\x48\x77\x99\xD3\x79\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x03\x68\x00\x30\x65\x02\x31\x00\xEF\x03\x5B\x7A\xAC\xB7\x78\x0A\x72\xB7\x88\xDF\xFF\xB5\x46\x14\x09\x0A\xFA\xA0\xE6\x7D\x08\xC6\x1A\x87\xBD\x18\xA8\x73\xBD\x26\xCA\x60\x0C\x9D\xCE\x99\x9F\xCF\x5C\x0F\x30\xE1\xBE\x14\x31\xEA\x02\x30\x14\xF4\x93\x3C\x49\xA7\x33\x7A\x90\x46\x47\xB3\x63\x7D\x13\x9B\x4E\xB7\x6F\x18\x37\x80\x53\xFE\xDD\x20\xE0\x35\x9A\x36\xD1\xC7\x01\xB9\xE6\xDC\xDD\xF3\xFF\x1D\x2C\x3A\x16\x57\xD9\x92\x39\xD6", - ["IGC/A"] = "\x30\x82\x04\x02\x30\x82\x02\xEA\xA0\x03\x02\x01\x02\x02\x05\x39\x11\x45\x10\x94\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x08\x13\x06\x46\x72\x61\x6E\x63\x65\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05\x50\x61\x72\x69\x73\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x50\x4D\x2F\x53\x47\x44\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13\x05\x44\x43\x53\x53\x49\x31\x0E\x30\x0C\x06\x03\x55\x04\x03\x13\x05\x49\x47\x43\x2F\x41\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x14\x69\x67\x63\x61\x40\x73\x67\x64\x6E\x2E\x70\x6D\x2E\x67\x6F\x75\x76\x2E\x66\x72\x30\x1E\x17\x0D\x30\x32\x31\x32\x31\x33\x31\x34\x32\x39\x32\x33\x5A\x17\x0D\x32\x30\x31\x30\x31\x37\x31\x34\x32\x39\x32\x32\x5A\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x08\x13\x06\x46\x72\x61\x6E\x63\x65\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05\x50\x61\x72\x69\x73\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x50\x4D\x2F\x53\x47\x44\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13\x05\x44\x43\x53\x53\x49\x31\x0E\x30\x0C\x06\x03\x55\x04\x03\x13\x05\x49\x47\x43\x2F\x41\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x14\x69\x67\x63\x61\x40\x73\x67\x64\x6E\x2E\x70\x6D\x2E\x67\x6F\x75\x76\x2E\x66\x72\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\xB2\x1F\xD1\xD0\x62\xC5\x33\x3B\xC0\x04\x86\x88\xB3\xDC\xF8\x88\xF7\xFD\xDF\x43\xDF\x7A\x8D\x9A\x49\x5C\xF6\x4E\xAA\xCC\x1C\xB9\xA1\xEB\x27\x89\xF2\x46\xE9\x3B\x4A\x71\xD5\x1D\x8E\x2D\xCF\xE6\xAD\xAB\x63\x50\xC7\x54\x0B\x6E\x12\xC9\x90\x36\xC6\xD8\x2F\xDA\x91\xAA\x68\xC5\x72\xFE\x17\x0A\xB2\x17\x7E\x79\xB5\x32\x88\x70\xCA\x70\xC0\x96\x4A\x8E\xE4\x55\xCD\x1D\x27\x94\xBF\xCE\x72\x2A\xEC\x5C\xF9\x73\x20\xFE\xBD\xF7\x2E\x89\x67\xB8\xBB\x47\x73\x12\xF7\xD1\x35\x69\x3A\xF2\x0A\xB9\xAE\xFF\x46\x42\x46\xA2\xBF\xA1\x85\x1A\xF9\xBF\xE4\xFF\x49\x85\xF7\xA3\x70\x86\x32\x1C\x5D\x9F\x60\xF7\xA9\xAD\xA5\xFF\xCF\xD1\x34\xF9\x7D\x5B\x17\xC6\xDC\xD6\x0E\x28\x6B\xC2\xDD\xF1\xF5\x33\x68\x9D\x4E\xFC\x87\x7C\x36\x12\xD6\xA3\x80\xE8\x43\x0D\x55\x61\x94\xEA\x64\x37\x47\xEA\x77\xCA\xD0\xB2\x58\x05\xC3\x5D\x7E\xB1\xA8\x46\x90\x31\x56\xCE\x70\x2A\x96\xB2\x30\xB8\x77\xE6\x79\xC0\xBD\x29\x3B\xFD\x94\x77\x4C\xBD\x20\xCD\x41\x25\xE0\x2E\xC7\x1B\xBB\xEE\xA4\x04\x41\xD2\x5D\xAD\x12\x6A\x8A\x9B\x47\xFB\xC9\xDD\x46\x40\xE1\x9D\x3C\x33\xD0\xB5\x02\x03\x01\x00\x01\xA3\x77\x30\x75\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x46\x30\x15\x06\x03\x55\x1D\x20\x04\x0E\x30\x0C\x30\x0A\x06\x08\x2A\x81\x7A\x01\x79\x01\x01\x01\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xA3\x05\x2F\x18\x60\x50\xC2\x89\x0A\xDD\x2B\x21\x4F\xFF\x8E\x4E\xA8\x30\x31\x36\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xA3\x05\x2F\x18\x60\x50\xC2\x89\x0A\xDD\x2B\x21\x4F\xFF\x8E\x4E\xA8\x30\x31\x36\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x05\xDC\x26\xD8\xFA\x77\x15\x44\x68\xFC\x2F\x66\x3A\x74\xE0\x5D\xE4\x29\xFF\x06\x07\x13\x84\x4A\xAB\xCF\x6D\xA0\x1F\x51\x94\xF8\x49\xCB\x74\x36\x14\xBC\x15\xDD\xDB\x89\x2F\xDD\x8F\xA0\x5D\x7C\xF5\x12\xEB\x9F\x9E\x38\xA4\x47\xCC\xB3\x96\xD9\xBE\x9C\x25\xAB\x03\x7E\x33\x0F\x95\x81\x0D\xFD\x16\xE0\x88\xBE\x37\xF0\x6C\x5D\xD0\x31\x9B\x32\x2B\x5D\x17\x65\x93\x98\x60\xBC\x6E\x8F\xB1\xA8\x3C\x1E\xD9\x1C\xF3\xA9\x26\x42\xF9\x64\x1D\xC2\xE7\x92\xF6\xF4\x1E\x5A\xAA\x19\x52\x5D\xAF\xE8\xA2\xF7\x60\xA0\xF6\x8D\xF0\x89\xF5\x6E\xE0\x0A\x05\x01\x95\xC9\x8B\x20\x0A\xBA\x5A\xFC\x9A\x2C\x3C\xBD\xC3\xB7\xC9\x5D\x78\x25\x05\x3F\x56\x14\x9B\x0C\xDA\xFB\x3A\x48\xFE\x97\x69\x5E\xCA\x10\x86\xF7\x4E\x96\x04\x08\x4D\xEC\xB0\xBE\x5D\xDC\x3B\x8E\x4F\xC1\xFD\x9A\x36\x34\x9A\x4C\x54\x7E\x17\x03\x48\x95\x08\x11\x1C\x07\x6F\x85\x08\x7E\x5D\x4D\xC4\x9D\xDB\xFB\xAE\xCE\xB2\xD1\xB3\xB8\x83\x6C\x1D\xB2\xB3\x79\xF1\xD8\x70\x99\x7E\xF0\x13\x02\xCE\x5E\xDD\x51\xD3\xDF\x36\x81\xA1\x1B\x78\x2F\x71\xB3\xF1\x59\x4C\x46\x18\x28\xAB\x85\xD2\x60\x56\x5A", - ["Security Communication EV RootCA1"] = "\x30\x82\x03\x7D\x30\x82\x02\x65\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x60\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x45\x43\x4F\x4D\x20\x54\x72\x75\x73\x74\x20\x53\x79\x73\x74\x65\x6D\x73\x20\x43\x4F\x2E\x2C\x4C\x54\x44\x2E\x31\x2A\x30\x28\x06\x03\x55\x04\x0B\x13\x21\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6F\x6D\x6D\x75\x6E\x69\x63\x61\x74\x69\x6F\x6E\x20\x45\x56\x20\x52\x6F\x6F\x74\x43\x41\x31\x30\x1E\x17\x0D\x30\x37\x30\x36\x30\x36\x30\x32\x31\x32\x33\x32\x5A\x17\x0D\x33\x37\x30\x36\x30\x36\x30\x32\x31\x32\x33\x32\x5A\x30\x60\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x45\x43\x4F\x4D\x20\x54\x72\x75\x73\x74\x20\x53\x79\x73\x74\x65\x6D\x73\x20\x43\x4F\x2E\x2C\x4C\x54\x44\x2E\x31\x2A\x30\x28\x06\x03\x55\x04\x0B\x13\x21\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6F\x6D\x6D\x75\x6E\x69\x63\x61\x74\x69\x6F\x6E\x20\x45\x56\x20\x52\x6F\x6F\x74\x43\x41\x31\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\xBC\x7F\xEC\x57\x9B\x24\xE0\xFE\x9C\xBA\x42\x79\xA9\x88\x8A\xFA\x80\xE0\xF5\x07\x29\x43\xEA\x8E\x0A\x34\x36\x8D\x1C\xFA\xA7\xB5\x39\x78\xFF\x97\x75\xF7\x2F\xE4\xAA\x6B\x04\x84\x44\xCA\xA6\xE2\x68\x8E\xFD\x55\x50\x62\x0F\xA4\x71\x0E\xCE\x07\x38\x2D\x42\x85\x50\xAD\x3C\x96\x6F\x8B\xD5\xA2\x0E\xCF\xDE\x49\x89\x3D\xD6\x64\x2E\x38\xE5\x1E\x6C\xB5\x57\x8A\x9E\xEF\x48\x0E\xCD\x7A\x69\x16\x87\x44\xB5\x90\xE4\x06\x9D\xAE\xA1\x04\x97\x58\x79\xEF\x20\x4A\x82\x6B\x8C\x22\xBF\xEC\x1F\x0F\xE9\x84\x71\xED\xF1\x0E\xE4\xB8\x18\x13\xCC\x56\x36\x5D\xD1\x9A\x1E\x51\x6B\x39\x6E\x60\x76\x88\x34\x0B\xF3\xB3\xD1\xB0\x9D\xCA\x61\xE2\x64\x1D\xC1\x46\x07\xB8\x63\xDD\x1E\x33\x65\xB3\x8E\x09\x55\x52\x3D\xB5\xBD\xFF\x07\xEB\xAD\x61\x55\x18\x2C\xA9\x69\x98\x4A\xAA\x40\xC5\x33\x14\x65\x74\x00\xF9\x91\xDE\xAF\x03\x48\xC5\x40\x54\xDC\x0F\x84\x90\x68\x20\xC5\x92\x96\xDC\x2E\xE5\x02\x45\xAA\xC0\x5F\x54\xF8\x6D\xEA\x49\xCF\x5D\x6C\x4B\xAF\xEF\x9A\xC2\x56\x5C\xC6\x35\x56\x42\x6A\x30\x5F\xC2\xAB\xF6\xE2\x3D\x3F\xB3\xC9\x11\x8F\x31\x4C\xD7\x9F\x49\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x35\x4A\xF5\x4D\xAF\x3F\xD7\x82\x38\xAC\xAB\x71\x65\x17\x75\x8C\x9D\x55\x93\xE6\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA8\x87\xE9\xEC\xF8\x40\x67\x5D\xC3\xC1\x66\xC7\x40\x4B\x97\xFC\x87\x13\x90\x5A\xC4\xEF\xA0\xCA\x5F\x8B\xB7\xA7\xB7\xF1\xD6\xB5\x64\xB7\x8A\xB3\xB8\x1B\xCC\xDA\xFB\xAC\x66\x88\x41\xCE\xE8\xFC\xE4\xDB\x1E\x88\xA6\xED\x27\x50\x1B\x02\x30\x24\x46\x79\xFE\x04\x87\x70\x97\x40\x73\xD1\xC0\xC1\x57\x19\x9A\x69\xA5\x27\x99\xAB\x9D\x62\x84\xF6\x51\xC1\x2C\xC9\x23\x15\xD8\x28\xB7\xAB\x25\x13\xB5\x46\xE1\x86\x02\xFF\x26\x8C\xC4\x88\x92\x1D\x56\xFE\x19\x67\xF2\x55\xE4\x80\xA3\x6B\x9C\xAB\x77\xE1\x51\x71\x0D\x20\xDB\x10\x9A\xDB\xBD\x76\x79\x07\x77\x99\x28\xAD\x9A\x5E\xDA\xB1\x4F\x44\x2C\x35\x8E\xA5\x96\xC7\xFD\x83\xF0\x58\xC6\x79\xD6\x98\x7C\xA8\x8D\xFE\x86\x3E\x07\x16\x92\xE1\x7B\xE7\x1D\xEC\x33\x76\x7E\x42\x2E\x4A\x85\xF9\x91\x89\x68\x84\x03\x81\xA5\x9B\x9A\xBE\xE3\x37\xC5\x54\xAB\x56\x3B\x18\x2D\x41\xA4\x0C\xF8\x42\xDB\x99\xA0\xE0\x72\x6F\xBB\x5D\xE1\x16\x4F\x53\x0A\x64\xF9\x4E\xF4\xBF\x4E\x54\xBD\x78\x6C\x88\xEA\xBF\x9C\x13\x24\xC2\x70\x69\xA2\x7F\x0F\xC8\x3C\xAD\x08\xC9\xB0\x98\x40\xA3\x2A\xE7\x88\x83\xED\x77\x8F\x74", - ["OISTE WISeKey Global Root GA CA"] = "\x30\x82\x03\xF1\x30\x82\x02\xD9\xA0\x03\x02\x01\x02\x02\x10\x41\x3D\x72\xC7\xF4\x6B\x1F\x81\x43\x7D\xF1\xD2\x28\x54\xDF\x9A\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x8A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x57\x49\x53\x65\x4B\x65\x79\x31\x1B\x30\x19\x06\x03\x55\x04\x0B\x13\x12\x43\x6F\x70\x79\x72\x69\x67\x68\x74\x20\x28\x63\x29\x20\x32\x30\x30\x35\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x4F\x49\x53\x54\x45\x20\x46\x6F\x75\x6E\x64\x61\x74\x69\x6F\x6E\x20\x45\x6E\x64\x6F\x72\x73\x65\x64\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1F\x4F\x49\x53\x54\x45\x20\x57\x49\x53\x65\x4B\x65\x79\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x20\x47\x41\x20\x43\x41\x30\x1E\x17\x0D\x30\x35\x31\x32\x31\x31\x31\x36\x30\x33\x34\x34\x5A\x17\x0D\x33\x37\x31\x32\x31\x31\x31\x36\x30\x39\x35\x31\x5A\x30\x81\x8A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x57\x49\x53\x65\x4B\x65\x79\x31\x1B\x30\x19\x06\x03\x55\x04\x0B\x13\x12\x43\x6F\x70\x79\x72\x69\x67\x68\x74\x20\x28\x63\x29\x20\x32\x30\x30\x35\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x4F\x49\x53\x54\x45\x20\x46\x6F\x75\x6E\x64\x61\x74\x69\x6F\x6E\x20\x45\x6E\x64\x6F\x72\x73\x65\x64\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1F\x4F\x49\x53\x54\x45\x20\x57\x49\x53\x65\x4B\x65\x79\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x20\x47\x41\x20\x43\x41\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\xCB\x4F\xB3\x00\x9B\x3D\x36\xDD\xF9\xD1\x49\x6A\x6B\x10\x49\x1F\xEC\xD8\x2B\xB2\xC6\xF8\x32\x81\x29\x43\x95\x4C\x9A\x19\x23\x21\x15\x45\xDE\xE3\xC8\x1C\x51\x55\x5B\xAE\x93\xE8\x37\xFF\x2B\x6B\xE9\xD4\xEA\xBE\x2A\xDD\xA8\x51\x2B\xD7\x66\xC3\x61\x5C\x60\x02\xC8\xF5\xCE\x72\x7B\x3B\xB8\xF2\x4E\x65\x08\x9A\xCD\xA4\x6A\x19\xC1\x01\xBB\x73\xA6\xD7\xF6\xC3\xDD\xCD\xBC\xA4\x8B\xB5\x99\x61\xB8\x01\xA2\xA3\xD4\x4D\xD4\x05\x3D\x91\xAD\xF8\xB4\x08\x71\x64\xAF\x70\xF1\x1C\x6B\x7E\xF6\xC3\x77\x9D\x24\x73\x7B\xE4\x0C\x8C\xE1\xD9\x36\xE1\x99\x8B\x05\x99\x0B\xED\x45\x31\x09\xCA\xC2\x00\xDB\xF7\x72\xA0\x96\xAA\x95\x87\xD0\x8E\xC7\xB6\x61\x73\x0D\x76\x66\x8C\xDC\x1B\xB4\x63\xA2\x9F\x7F\x93\x13\x30\xF1\xA1\x27\xDB\xD9\xFF\x2C\x55\x88\x91\xA0\xE0\x4F\x07\xB0\x28\x56\x8C\x18\x1B\x97\x44\x8E\x89\xDD\xE0\x17\x6E\xE7\x2A\xEF\x8F\x39\x0A\x31\x84\x82\xD8\x40\x14\x49\x2E\x7A\x41\xE4\xA7\xFE\xE3\x64\xCC\xC1\x59\x71\x4B\x2C\x21\xA7\x5B\x7D\xE0\x1D\xD1\x2E\x81\x9B\xC3\xD8\x68\xF7\xBD\x96\x1B\xAC\x70\xB1\x16\x14\x0B\xDB\x60\xB9\x26\x01\x05\x02\x03\x01\x00\x01\xA3\x51\x30\x4F\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB3\x03\x7E\xAE\x36\xBC\xB0\x79\xD1\xDC\x94\x26\xB6\x11\xBE\x21\xB2\x69\x86\x94\x30\x10\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x4B\xA1\xFF\x0B\x87\x6E\xB3\xF9\xC1\x43\xB1\x48\xF3\x28\xC0\x1D\x2E\xC9\x09\x41\xFA\x94\x00\x1C\xA4\xA4\xAB\x49\x4F\x8F\x3D\x1E\xEF\x4D\x6F\xBD\xBC\xA4\xF6\xF2\x26\x30\xC9\x10\xCA\x1D\x88\xFB\x74\x19\x1F\x85\x45\xBD\xB0\x6C\x51\xF9\x36\x7E\xDB\xF5\x4C\x32\x3A\x41\x4F\x5B\x47\xCF\xE8\x0B\x2D\xB6\xC4\x19\x9D\x74\xC5\x47\xC6\x3B\x6A\x0F\xAC\x14\xDB\x3C\xF4\x73\x9C\xA9\x05\xDF\x00\xDC\x74\x78\xFA\xF8\x35\x60\x59\x02\x13\x18\x7C\xBC\xFB\x4D\xB0\x20\x6D\x43\xBB\x60\x30\x7A\x67\x33\x5C\xC5\x99\xD1\xF8\x2D\x39\x52\x73\xFB\x8C\xAA\x97\x25\x5C\x72\xD9\x08\x1E\xAB\x4E\x3C\xE3\x81\x31\x9F\x03\xA6\xFB\xC0\xFE\x29\x88\x55\xDA\x84\xD5\x50\x03\xB6\xE2\x84\xA3\xA6\x36\xAA\x11\x3A\x01\xE1\x18\x4B\xD6\x44\x68\xB3\x3D\xF9\x53\x74\x84\xB3\x46\x91\x46\x96\x00\xB7\x80\x2C\xB6\xE1\xE3\x10\xE2\xDB\xA2\xE7\x28\x8F\x01\x96\x62\x16\x3E\x00\xE3\x1C\xA5\x36\x81\x18\xA2\x4C\x52\x76\xC0\x11\xA3\x6E\xE6\x1D\xBA\xE3\x5A\xBE\x36\x53\xC5\x3E\x75\x8F\x86\x69\x29\x58\x53\xB5\x9C\xBB\x6F\x9F\x5C\xC5\x18\xEC\xDD\x2F\xE1\x98\xC9\xFC\xBE\xDF\x0A\x0D", - ["Microsec e-Szigno Root CA"] = "\x30\x82\x07\xA8\x30\x82\x06\x90\xA0\x03\x02\x01\x02\x02\x11\x00\xCC\xB8\xE7\xBF\x4E\x29\x1A\xFD\xA2\xDC\x66\xA5\x1C\x2C\x0F\x11\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x72\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4C\x74\x64\x2E\x31\x14\x30\x12\x06\x03\x55\x04\x0B\x13\x0B\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x43\x41\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x35\x30\x34\x30\x36\x31\x32\x32\x38\x34\x34\x5A\x17\x0D\x31\x37\x30\x34\x30\x36\x31\x32\x32\x38\x34\x34\x5A\x30\x72\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4C\x74\x64\x2E\x31\x14\x30\x12\x06\x03\x55\x04\x0B\x13\x0B\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x43\x41\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xED\xC8\x00\xD5\x81\x7B\xCD\x38\x00\x47\xCC\xDB\x84\xC1\x21\x69\x2C\x74\x90\x0C\x21\xD9\x53\x87\xED\x3E\x43\x44\x53\xAF\xAB\xF8\x80\x9B\x3C\x78\x8D\xD4\x8D\xAE\xB8\xEF\xD3\x11\xDC\x81\xE6\xCF\x3B\x96\x8C\xD6\x6F\x15\xC6\x77\x7E\xA1\x2F\xE0\x5F\x92\xB6\x27\xD7\x76\x9A\x1D\x43\x3C\xEA\xD9\xEC\x2F\xEE\x39\xF3\x6A\x67\x4B\x8B\x82\xCF\x22\xF8\x65\x55\xFE\x2C\xCB\x2F\x7D\x48\x7A\x3D\x75\xF9\xAA\xA0\x27\xBB\x78\xC2\x06\xCA\x51\xC2\x7E\x66\x4B\xAF\xCD\xA2\xA7\x4D\x02\x82\x3F\x82\xAC\x85\xC6\xE1\x0F\x90\x47\x99\x94\x0A\x71\x72\x93\x2A\xC9\xA6\xC0\xBE\x3C\x56\x4C\x73\x92\x27\xF1\x6B\xB5\xF5\xFD\xFC\x30\x05\x60\x92\xC6\xEB\x96\x7E\x01\x91\xC2\x69\xB1\x1E\x1D\x7B\x53\x45\xB8\xDC\x41\x1F\xC9\x8B\x71\xD6\x54\x14\xE3\x8B\x54\x78\x3F\xBE\xF4\x62\x3B\x5B\xF5\xA3\xEC\xD5\x92\x74\xE2\x74\x30\xEF\x01\xDB\xE1\xD4\xAB\x99\x9B\x2A\x6B\xF8\xBD\xA6\x1C\x86\x23\x42\x5F\xEC\x49\xDE\x9A\x8B\x5B\xF4\x72\x3A\x40\xC5\x49\x3E\xA5\xBE\x8E\xAA\x71\xEB\x6C\xFA\xF5\x1A\xE4\x6A\xFD\x7B\x7D\x55\x40\xEF\x58\x6E\xE6\xD9\xD5\xBC\x24\xAB\xC1\xEF\xB7\x02\x03\x01\x00\x01\xA3\x82\x04\x37\x30\x82\x04\x33\x30\x67\x06\x08\x2B\x06\x01\x05\x05\x07\x01\x01\x04\x5B\x30\x59\x30\x28\x06\x08\x2B\x06\x01\x05\x05\x07\x30\x01\x86\x1C\x68\x74\x74\x70\x73\x3A\x2F\x2F\x72\x63\x61\x2E\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x2F\x6F\x63\x73\x70\x30\x2D\x06\x08\x2B\x06\x01\x05\x05\x07\x30\x02\x86\x21\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x2F\x52\x6F\x6F\x74\x43\x41\x2E\x63\x72\x74\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x82\x01\x73\x06\x03\x55\x1D\x20\x04\x82\x01\x6A\x30\x82\x01\x66\x30\x82\x01\x62\x06\x0C\x2B\x06\x01\x04\x01\x81\xA8\x18\x02\x01\x01\x01\x30\x82\x01\x50\x30\x28\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x1C\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x2F\x53\x5A\x53\x5A\x2F\x30\x82\x01\x22\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x82\x01\x14\x1E\x82\x01\x10\x00\x41\x00\x20\x00\x74\x00\x61\x00\x6E\x00\xFA\x00\x73\x00\xED\x00\x74\x00\x76\x00\xE1\x00\x6E\x00\x79\x00\x20\x00\xE9\x00\x72\x00\x74\x00\x65\x00\x6C\x00\x6D\x00\x65\x00\x7A\x00\xE9\x00\x73\x00\xE9\x00\x68\x00\x65\x00\x7A\x00\x20\x00\xE9\x00\x73\x00\x20\x00\x65\x00\x6C\x00\x66\x00\x6F\x00\x67\x00\x61\x00\x64\x00\xE1\x00\x73\x00\xE1\x00\x68\x00\x6F\x00\x7A\x00\x20\x00\x61\x00\x20\x00\x53\x00\x7A\x00\x6F\x00\x6C\x00\x67\x00\xE1\x00\x6C\x00\x74\x00\x61\x00\x74\x00\xF3\x00\x20\x00\x53\x00\x7A\x00\x6F\x00\x6C\x00\x67\x00\xE1\x00\x6C\x00\x74\x00\x61\x00\x74\x00\xE1\x00\x73\x00\x69\x00\x20\x00\x53\x00\x7A\x00\x61\x00\x62\x00\xE1\x00\x6C\x00\x79\x00\x7A\x00\x61\x00\x74\x00\x61\x00\x20\x00\x73\x00\x7A\x00\x65\x00\x72\x00\x69\x00\x6E\x00\x74\x00\x20\x00\x6B\x00\x65\x00\x6C\x00\x6C\x00\x20\x00\x65\x00\x6C\x00\x6A\x00\xE1\x00\x72\x00\x6E\x00\x69\x00\x3A\x00\x20\x00\x68\x00\x74\x00\x74\x00\x70\x00\x3A\x00\x2F\x00\x2F\x00\x77\x00\x77\x00\x77\x00\x2E\x00\x65\x00\x2D\x00\x73\x00\x7A\x00\x69\x00\x67\x00\x6E\x00\x6F\x00\x2E\x00\x68\x00\x75\x00\x2F\x00\x53\x00\x5A\x00\x53\x00\x5A\x00\x2F\x30\x81\xC8\x06\x03\x55\x1D\x1F\x04\x81\xC0\x30\x81\xBD\x30\x81\xBA\xA0\x81\xB7\xA0\x81\xB4\x86\x21\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x2F\x52\x6F\x6F\x74\x43\x41\x2E\x63\x72\x6C\x86\x81\x8E\x6C\x64\x61\x70\x3A\x2F\x2F\x6C\x64\x61\x70\x2E\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x2F\x43\x4E\x3D\x4D\x69\x63\x72\x6F\x73\x65\x63\x25\x32\x30\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x25\x32\x30\x52\x6F\x6F\x74\x25\x32\x30\x43\x41\x2C\x4F\x55\x3D\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x25\x32\x30\x43\x41\x2C\x4F\x3D\x4D\x69\x63\x72\x6F\x73\x65\x63\x25\x32\x30\x4C\x74\x64\x2E\x2C\x4C\x3D\x42\x75\x64\x61\x70\x65\x73\x74\x2C\x43\x3D\x48\x55\x3F\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x52\x65\x76\x6F\x63\x61\x74\x69\x6F\x6E\x4C\x69\x73\x74\x3B\x62\x69\x6E\x61\x72\x79\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x81\x96\x06\x03\x55\x1D\x11\x04\x81\x8E\x30\x81\x8B\x81\x10\x69\x6E\x66\x6F\x40\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\xA4\x77\x30\x75\x31\x23\x30\x21\x06\x03\x55\x04\x03\x0C\x1A\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\xC3\xB3\x20\x52\x6F\x6F\x74\x20\x43\x41\x31\x16\x30\x14\x06\x03\x55\x04\x0B\x0C\x0D\x65\x2D\x53\x7A\x69\x67\x6E\xC3\xB3\x20\x48\x53\x5A\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4B\x66\x74\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x30\x81\xAC\x06\x03\x55\x1D\x23\x04\x81\xA4\x30\x81\xA1\x80\x14\xC7\xA0\x49\x75\x16\x61\x84\xDB\x31\x4B\x84\xD2\xF1\x37\x40\x90\xEF\x4E\xDC\xF7\xA1\x76\xA4\x74\x30\x72\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4C\x74\x64\x2E\x31\x14\x30\x12\x06\x03\x55\x04\x0B\x13\x0B\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x43\x41\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x52\x6F\x6F\x74\x20\x43\x41\x82\x11\x00\xCC\xB8\xE7\xBF\x4E\x29\x1A\xFD\xA2\xDC\x66\xA5\x1C\x2C\x0F\x11\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC7\xA0\x49\x75\x16\x61\x84\xDB\x31\x4B\x84\xD2\xF1\x37\x40\x90\xEF\x4E\xDC\xF7\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xD3\x13\x9C\x66\x63\x59\x2E\xCA\x5C\x70\x0C\xFC\x83\xBC\x55\xB1\xF4\x8E\x07\x6C\x66\x27\xCE\xC1\x3B\x20\xA9\x1C\xBB\x46\x54\x70\xEE\x5A\xCC\xA0\x77\xEA\x68\x44\x27\xEB\xF2\x29\xDD\x77\xA9\xD5\xFB\xE3\xD4\xA7\x04\xC4\x95\xB8\x0B\xE1\x44\x68\x60\x07\x43\x30\x31\x42\x61\xE5\xEE\xD9\xE5\x24\xD5\x1B\xDF\xE1\x4A\x1B\xAA\x9F\xC7\x5F\xF8\x7A\x11\xEA\x13\x93\x00\xCA\x8A\x58\xB1\xEE\xED\x0E\x4D\xB4\xD7\xA8\x36\x26\x7C\xE0\x3A\xC1\xD5\x57\x82\xF1\x75\xB6\xFD\x89\x5F\xDA\xF3\xA8\x38\x9F\x35\x06\x08\xCE\x22\x95\xBE\xCD\xD5\xFC\xBE\x5B\xDE\x79\x6B\xDC\x7A\xA9\x65\x66\xBE\xB1\x25\x5A\x5F\xED\x7E\xD3\xAC\x46\x6D\x4C\xF4\x32\x87\xB4\x20\x04\xE0\x6C\x78\xB0\x77\xD1\x85\x46\x4B\xA6\x12\xB7\x75\xE8\x4A\xC9\x56\x6C\xD7\x92\xAB\x9D\xF5\x49\x38\xD2\x4F\x53\xE3\x55\x90\x11\xDB\x98\x96\xC6\x49\xF2\x3E\xF4\x9F\x1B\xE0\xF7\x88\xDC\x25\x62\x99\x44\xD8\x73\xBF\x3F\x30\xF3\x0C\x37\x3E\xD4\xC2\x28\x80\x73\xB1\x01\xB7\x9D\x5A\x96\x14\x01\x4B\xA9\x11\x9D\x29\x6A\x2E\xD0\x5D\x81\xC0\xCF\xB2\x20\x43\xC7\x03\xE0\x37\x4E\x5D\x0A\xDC\x59\x20\x25", - ["Certigna"] = "\x30\x82\x03\xA8\x30\x82\x02\x90\xA0\x03\x02\x01\x02\x02\x09\x00\xFE\xDC\xE3\x01\x0F\xC9\x48\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x34\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x0C\x09\x44\x68\x69\x6D\x79\x6F\x74\x69\x73\x31\x11\x30\x0F\x06\x03\x55\x04\x03\x0C\x08\x43\x65\x72\x74\x69\x67\x6E\x61\x30\x1E\x17\x0D\x30\x37\x30\x36\x32\x39\x31\x35\x31\x33\x30\x35\x5A\x17\x0D\x32\x37\x30\x36\x32\x39\x31\x35\x31\x33\x30\x35\x5A\x30\x34\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x0C\x09\x44\x68\x69\x6D\x79\x6F\x74\x69\x73\x31\x11\x30\x0F\x06\x03\x55\x04\x03\x0C\x08\x43\x65\x72\x74\x69\x67\x6E\x61\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\xC8\x68\xF1\xC9\xD6\xD6\xB3\x34\x75\x26\x82\x1E\xEC\xB4\xBE\xEA\x5C\xE1\x26\xED\x11\x47\x61\xE1\xA2\x7C\x16\x78\x40\x21\xE4\x60\x9E\x5A\xC8\x63\xE1\xC4\xB1\x96\x92\xFF\x18\x6D\x69\x23\xE1\x2B\x62\xF7\xDD\xE2\x36\x2F\x91\x07\xB9\x48\xCF\x0E\xEC\x79\xB6\x2C\xE7\x34\x4B\x70\x08\x25\xA3\x3C\x87\x1B\x19\xF2\x81\x07\x0F\x38\x90\x19\xD3\x11\xFE\x86\xB4\xF2\xD1\x5E\x1E\x1E\x96\xCD\x80\x6C\xCE\x3B\x31\x93\xB6\xF2\xA0\xD0\xA9\x95\x12\x7D\xA5\x9A\xCC\x6B\xC8\x84\x56\x8A\x33\xA9\xE7\x22\x15\x53\x16\xF0\xCC\x17\xEC\x57\x5F\xE9\xA2\x0A\x98\x09\xDE\xE3\x5F\x9C\x6F\xDC\x48\xE3\x85\x0B\x15\x5A\xA6\xBA\x9F\xAC\x48\xE3\x09\xB2\xF7\xF4\x32\xDE\x5E\x34\xBE\x1C\x78\x5D\x42\x5B\xCE\x0E\x22\x8F\x4D\x90\xD7\x7D\x32\x18\xB3\x0B\x2C\x6A\xBF\x8E\x3F\x14\x11\x89\x20\x0E\x77\x14\xB5\x3D\x94\x08\x87\xF7\x25\x1E\xD5\xB2\x60\x00\xEC\x6F\x2A\x28\x25\x6E\x2A\x3E\x18\x63\x17\x25\x3F\x3E\x44\x20\x16\xF6\x26\xC8\x25\xAE\x05\x4A\xB4\xE7\x63\x2C\xF3\x8C\x16\x53\x7E\x5C\xFB\x11\x1A\x08\xC1\x46\x62\x9F\x22\xB8\xF1\xC2\x8D\x69\xDC\xFA\x3A\x58\x06\xDF\x02\x03\x01\x00\x01\xA3\x81\xBC\x30\x81\xB9\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x1A\xED\xFE\x41\x39\x90\xB4\x24\x59\xBE\x01\xF2\x52\xD5\x45\xF6\x5A\x39\xDC\x11\x30\x64\x06\x03\x55\x1D\x23\x04\x5D\x30\x5B\x80\x14\x1A\xED\xFE\x41\x39\x90\xB4\x24\x59\xBE\x01\xF2\x52\xD5\x45\xF6\x5A\x39\xDC\x11\xA1\x38\xA4\x36\x30\x34\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x0C\x09\x44\x68\x69\x6D\x79\x6F\x74\x69\x73\x31\x11\x30\x0F\x06\x03\x55\x04\x03\x0C\x08\x43\x65\x72\x74\x69\x67\x6E\x61\x82\x09\x00\xFE\xDC\xE3\x01\x0F\xC9\x48\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x85\x03\x1E\x92\x71\xF6\x42\xAF\xE1\xA3\x61\x9E\xEB\xF3\xC0\x0F\xF2\xA5\xD4\xDA\x95\xE6\xD6\xBE\x68\x36\x3D\x7E\x6E\x1F\x4C\x8A\xEF\xD1\x0F\x21\x6D\x5E\xA5\x52\x63\xCE\x12\xF8\xEF\x2A\xDA\x6F\xEB\x37\xFE\x13\x02\xC7\xCB\x3B\x3E\x22\x6B\xDA\x61\x2E\x7F\xD4\x72\x3D\xDD\x30\xE1\x1E\x4C\x40\x19\x8C\x0F\xD7\x9C\xD1\x83\x30\x7B\x98\x59\xDC\x7D\xC6\xB9\x0C\x29\x4C\xA1\x33\xA2\xEB\x67\x3A\x65\x84\xD3\x96\xE2\xED\x76\x45\x70\x8F\xB5\x2B\xDE\xF9\x23\xD6\x49\x6E\x3C\x14\xB5\xC6\x9F\x35\x1E\x50\xD0\xC1\x8F\x6A\x70\x44\x02\x62\xCB\xAE\x1D\x68\x41\xA7\xAA\x57\xE8\x53\xAA\x07\xD2\x06\xF6\xD5\x14\x06\x0B\x91\x03\x75\x2C\x6C\x72\xB5\x61\x95\x9A\x0D\x8B\xB9\x0D\xE7\xF5\xDF\x54\xCD\xDE\xE6\xD8\xD6\x09\x08\x97\x63\xE5\xC1\x2E\xB0\xB7\x44\x26\xC0\x26\xC0\xAF\x55\x30\x9E\x3B\xD5\x36\x2A\x19\x04\xF4\x5C\x1E\xFF\xCF\x2C\xB7\xFF\xD0\xFD\x87\x40\x11\xD5\x11\x23\xBB\x48\xC0\x21\xA9\xA4\x28\x2D\xFD\x15\xF8\xB0\x4E\x2B\xF4\x30\x5B\x21\xFC\x11\x91\x34\xBE\x41\xEF\x7B\x9D\x97\x75\xFF\x97\x95\xC0\x96\x58\x2F\xEA\xBB\x46\xD7\xBB\xE4\xD9\x2E", - ["AC Ra\xC3\xADz Certic\xC3\xA1mara S.A."] = "\x30\x82\x06\x66\x30\x82\x04\x4E\xA0\x03\x02\x01\x02\x02\x0F\x07\x7E\x52\x93\x7B\xE0\x15\xE3\x57\xF0\x69\x8C\xCB\xEC\x0C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4F\x31\x47\x30\x45\x06\x03\x55\x04\x0A\x0C\x3E\x53\x6F\x63\x69\x65\x64\x61\x64\x20\x43\x61\x6D\x65\x72\x61\x6C\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\xC3\xB3\x6E\x20\x44\x69\x67\x69\x74\x61\x6C\x20\x2D\x20\x43\x65\x72\x74\x69\x63\xC3\xA1\x6D\x61\x72\x61\x20\x53\x2E\x41\x2E\x31\x23\x30\x21\x06\x03\x55\x04\x03\x0C\x1A\x41\x43\x20\x52\x61\xC3\xAD\x7A\x20\x43\x65\x72\x74\x69\x63\xC3\xA1\x6D\x61\x72\x61\x20\x53\x2E\x41\x2E\x30\x1E\x17\x0D\x30\x36\x31\x31\x32\x37\x32\x30\x34\x36\x32\x39\x5A\x17\x0D\x33\x30\x30\x34\x30\x32\x32\x31\x34\x32\x30\x32\x5A\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4F\x31\x47\x30\x45\x06\x03\x55\x04\x0A\x0C\x3E\x53\x6F\x63\x69\x65\x64\x61\x64\x20\x43\x61\x6D\x65\x72\x61\x6C\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\xC3\xB3\x6E\x20\x44\x69\x67\x69\x74\x61\x6C\x20\x2D\x20\x43\x65\x72\x74\x69\x63\xC3\xA1\x6D\x61\x72\x61\x20\x53\x2E\x41\x2E\x31\x23\x30\x21\x06\x03\x55\x04\x03\x0C\x1A\x41\x43\x20\x52\x61\xC3\xAD\x7A\x20\x43\x65\x72\x74\x69\x63\xC3\xA1\x6D\x61\x72\x61\x20\x53\x2E\x41\x2E\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xAB\x6B\x89\xA3\x53\xCC\x48\x23\x08\xFB\xC3\xCF\x51\x96\x08\x2E\xB8\x08\x7A\x6D\x3C\x90\x17\x86\xA9\xE9\xED\x2E\x13\x34\x47\xB2\xD0\x70\xDC\xC9\x3C\xD0\x8D\xCA\xEE\x4B\x17\xAB\xD0\x85\xB0\xA7\x23\x04\xCB\xA8\xA2\xFC\xE5\x75\xDB\x40\xCA\x62\x89\x8F\x50\x9E\x01\x3D\x26\x5B\x18\x84\x1C\xCB\x7C\x37\xB7\x7D\xEC\xD3\x7F\x73\x19\xB0\x6A\xB2\xD8\x88\x8A\x2D\x45\x74\xA8\xF7\xB3\xB8\xC0\xD4\xDA\xCD\x22\x89\x74\x4D\x5A\x15\x39\x73\x18\x74\x4F\xB5\xEB\x99\xA7\xC1\x1E\x88\xB4\xC2\x93\x90\x63\x97\xF3\xA7\xA7\x12\xB2\x09\x22\x07\x33\xD9\x91\xCD\x0E\x9C\x1F\x0E\x20\xC7\xEE\xBB\x33\x8D\x8F\xC2\xD2\x58\xA7\x5F\xFD\x65\x37\xE2\x88\xC2\xD8\x8F\x86\x75\x5E\xF9\x2D\xA7\x87\x33\xF2\x78\x37\x2F\x8B\xBC\x1D\x86\x37\x39\xB1\x94\xF2\xD8\xBC\x4A\x9C\x83\x18\x5A\x06\xFC\xF3\xD4\xD4\xBA\x8C\x15\x09\x25\xF0\xF9\xB6\x8D\x04\x7E\x17\x12\x33\x6B\x57\x48\x4C\x4F\xDB\x26\x1E\xEB\xCC\x90\xE7\x8B\xF9\x68\x7C\x70\x0F\xA3\x2A\xD0\x3A\x38\xDF\x37\x97\xE2\x5B\xDE\x80\x61\xD3\x80\xD8\x91\x83\x42\x5A\x4C\x04\x89\x68\x11\x3C\xAC\x5F\x68\x80\x41\xCC\x60\x42\xCE\x0D\x5A\x2A\x0C\x0F\x9B\x30\xC0\xA6\xF0\x86\xDB\xAB\x49\xD7\x97\x6D\x48\x8B\xF9\x03\xC0\x52\x67\x9B\x12\xF7\xC2\xF2\x2E\x98\x65\x42\xD9\xD6\x9A\xE3\xD0\x19\x31\x0C\xAD\x87\xD5\x57\x02\x7A\x30\xE8\x86\x26\xFB\x8F\x23\x8A\x54\x87\xE4\xBF\x3C\xEE\xEB\xC3\x75\x48\x5F\x1E\x39\x6F\x81\x62\x6C\xC5\x2D\xC4\x17\x54\x19\xB7\x37\x8D\x9C\x37\x91\xC8\xF6\x0B\xD5\xEA\x63\x6F\x83\xAC\x38\xC2\xF3\x3F\xDE\x9A\xFB\xE1\x23\x61\xF0\xC8\x26\xCB\x36\xC8\xA1\xF3\x30\x8F\xA4\xA3\xA2\xA1\xDD\x53\xB3\xDE\xF0\x9A\x32\x1F\x83\x91\x79\x30\xC1\xA9\x1F\x53\x9B\x53\xA2\x15\x53\x3F\xDD\x9D\xB3\x10\x3B\x48\x7D\x89\x0F\xFC\xED\x03\xF5\xFB\x25\x64\x75\x0E\x17\x19\x0D\x8F\x00\x16\x67\x79\x7A\x40\xFC\x2D\x59\x07\xD9\x90\xFA\x9A\xAD\x3D\xDC\x80\x8A\xE6\x5C\x35\xA2\x67\x4C\x11\x6B\xB1\xF8\x80\x64\x00\x2D\x6F\x22\x61\xC5\xAC\x4B\x26\xE5\x5A\x10\x82\x9B\xA4\x83\x7B\x34\xF7\x9E\x89\x91\x20\x97\x8E\xB7\x42\xC7\x66\xC3\xD0\xE9\xA4\xD6\xF5\x20\x8D\xC4\xC3\x95\xAC\x44\x0A\x9D\x5B\x73\x3C\x26\x3D\x2F\x4A\xBE\xA7\xC9\xA7\x10\x1E\xFB\x9F\x50\x69\xF3\x02\x03\x01\x00\x01\xA3\x81\xE6\x30\x81\xE3\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xD1\x09\xD0\xE9\xD7\xCE\x79\x74\x54\xF9\x3A\x30\xB3\xF4\x6D\x2C\x03\x03\x1B\x68\x30\x81\xA0\x06\x03\x55\x1D\x20\x04\x81\x98\x30\x81\x95\x30\x81\x92\x06\x04\x55\x1D\x20\x00\x30\x81\x89\x30\x2B\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x1F\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x65\x72\x74\x69\x63\x61\x6D\x61\x72\x61\x2E\x63\x6F\x6D\x2F\x64\x70\x63\x2F\x30\x5A\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x4E\x1A\x4C\x4C\x69\x6D\x69\x74\x61\x63\x69\x6F\x6E\x65\x73\x20\x64\x65\x20\x67\x61\x72\x61\x6E\x74\xED\x61\x73\x20\x64\x65\x20\x65\x73\x74\x65\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x64\x6F\x20\x73\x65\x20\x70\x75\x65\x64\x65\x6E\x20\x65\x6E\x63\x6F\x6E\x74\x72\x61\x72\x20\x65\x6E\x20\x6C\x61\x20\x44\x50\x43\x2E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x5C\x94\xB5\xB8\x45\x91\x4D\x8E\x61\x1F\x03\x28\x0F\x53\x7C\xE6\xA4\x59\xA9\xB3\x8A\x7A\xC5\xB0\xFF\x08\x7C\x2C\xA3\x71\x1C\x21\x13\x67\xA1\x95\x12\x40\x35\x83\x83\x8F\x74\xDB\x33\x5C\xF0\x49\x76\x0A\x81\x52\xDD\x49\xD4\x9A\x32\x33\xEF\x9B\xA7\xCB\x75\xE5\x7A\xCB\x97\x12\x90\x5C\xBA\x7B\xC5\x9B\xDF\xBB\x39\x23\xC8\xFF\x98\xCE\x0A\x4D\x22\x01\x48\x07\x7E\x8A\xC0\xD5\x20\x42\x94\x44\xEF\xBF\x77\xA2\x89\x67\x48\x1B\x40\x03\x05\xA1\x89\xEC\xCF\x62\xE3\x3D\x25\x76\x66\xBF\x26\xB7\xBB\x22\xBE\x6F\xFF\x39\x57\x74\xBA\x7A\xC9\x01\x95\xC1\x95\x51\xE8\xAB\x2C\xF8\xB1\x86\x20\xE9\x3F\xCB\x35\x5B\xD2\x17\xE9\x2A\xFE\x83\x13\x17\x40\xEE\x88\x62\x65\x5B\xD5\x3B\x60\xE9\x7B\x3C\xB8\xC9\xD5\x7F\x36\x02\x25\xAA\x68\xC2\x31\x15\xB7\x30\x65\xEB\x7F\x1D\x48\x79\xB1\xCF\x39\xE2\x42\x80\x16\xD3\xF5\x93\x23\xFC\x4C\x97\xC9\x5A\x37\x6C\x7C\x22\xD8\x4A\xCD\xD2\x8E\x36\x83\x39\x91\x90\x10\xC8\xF1\xC9\x35\x7E\x3F\xB8\xD3\x81\xC6\x20\x64\x1A\xB6\x50\xC2\x21\xA4\x78\xDC\xD0\x2F\x3B\x64\x93\x74\xF0\x96\x90\xF1\xEF\xFB\x09\x5A\x34\x40\x96\xF0\x36\x12\xC1\xA3\x74\x8C\x93\x7E\x41\xDE\x77\x8B\xEC\x86\xD9\xD2\x0F\x3F\x2D\xD1\xCC\x40\xA2\x89\x66\x48\x1E\x20\xB3\x9C\x23\x59\x73\xA9\x44\x73\xBC\x24\x79\x90\x56\x37\xB3\xC6\x29\x7E\xA3\x0F\xF1\x29\x39\xEF\x7E\x5C\x28\x32\x70\x35\xAC\xDA\xB8\xC8\x75\x66\xFC\x9B\x4C\x39\x47\x8E\x1B\x6F\x9B\x4D\x02\x54\x22\x33\xEF\x61\xBA\x9E\x29\x84\xEF\x4E\x4B\x33\x47\x76\x97\x6A\xCB\x7E\x5F\xFD\x15\xA6\x9E\x42\x43\x5B\x66\x5A\x8A\x88\x0D\xF7\x16\xB9\x3F\x51\x65\x2B\x66\x6A\x8B\xD1\x38\x52\xA2\xD6\x46\x11\xFA\xFC\x9A\x1C\x74\x9E\x8F\x97\x0B\x02\x4F\x64\xC6\xF5\x68\xD3\x4B\x2D\xFF\xA4\x37\x1E\x8B\x3F\xBF\x44\xBE\x61\x46\xA1\x84\x3D\x08\x27\x4C\x81\x20\x77\x89\x08\xEA\x67\x40\x5E\x6C\x08\x51\x5F\x34\x5A\x8C\x96\x68\xCD\xD7\xF7\x89\xC2\x1C\xD3\x32\x00\xAF\x52\xCB\xD3\x60\x5B\x2A\x3A\x47\x7E\x6B\x30\x33\xA1\x62\x29\x7F\x4A\xB9\xE1\x2D\xE7\x14\x23\x0E\x0E\x18\x47\xE1\x79\xFC\x15\x55\xD0\xB1\xFC\x25\x71\x63\x75\x33\x1C\x23\x2B\xAF\x5C\xD9\xED\x47\x77\x60\x0E\x3B\x0F\x1E\xD2\xC0\xDC\x64\x05\x89\xFC\x78\xD6\x5C\x2C\x26\x43\xA9", - ["TC TrustCenter Class 2 CA II"] = "\x30\x82\x04\xAA\x30\x82\x03\x92\xA0\x03\x02\x01\x02\x02\x0E\x2E\x6A\x00\x01\x00\x02\x1F\xD7\x52\x21\x2C\x11\x5C\x3B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x76\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1C\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x20\x49\x49\x30\x1E\x17\x0D\x30\x36\x30\x31\x31\x32\x31\x34\x33\x38\x34\x33\x5A\x17\x0D\x32\x35\x31\x32\x33\x31\x32\x32\x35\x39\x35\x39\x5A\x30\x76\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1C\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x20\x49\x49\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\xAB\x80\x87\x9B\x8E\xF0\xC3\x7C\x87\xD7\xE8\x24\x82\x11\xB3\x3C\xDD\x43\x62\xEE\xF8\xC3\x45\xDA\xE8\xE1\xA0\x5F\xD1\x2A\xB2\xEA\x93\x68\xDF\xB4\xC8\xD6\x43\xE9\xC4\x75\x59\x7F\xFC\xE1\x1D\xF8\x31\x70\x23\x1B\x88\x9E\x27\xB9\x7B\xFD\x3A\xD2\xC9\xA9\xE9\x14\x2F\x90\xBE\x03\x52\xC1\x49\xCD\xF6\xFD\xE4\x08\x66\x0B\x57\x8A\xA2\x42\xA0\xB8\xD5\x7F\x69\x5C\x90\x32\xB2\x97\x0D\xCA\x4A\xDC\x46\x3E\x02\x55\x89\x53\xE3\x1A\x5A\xCB\x36\xC6\x07\x56\xF7\x8C\xCF\x11\xF4\x4C\xBB\x30\x70\x04\x95\xA5\xF6\x39\x8C\xFD\x73\x81\x08\x7D\x89\x5E\x32\x1E\x22\xA9\x22\x45\x4B\xB0\x66\x2E\x30\xCC\x9F\x65\xFD\xFC\xCB\x81\xA9\xF1\xE0\x3B\xAF\xA3\x86\xD1\x89\xEA\xC4\x45\x79\x50\x5D\xAE\xE9\x21\x74\x92\x4D\x8B\x59\x82\x8F\x94\xE3\xE9\x4A\xF1\xE7\x49\xB0\x14\xE3\xF5\x62\xCB\xD5\x72\xBD\x1F\xB9\xD2\x9F\xA0\xCD\xA8\xFA\x01\xC8\xD9\x0D\xDF\xDA\xFC\x47\x9D\xB3\xC8\x54\xDF\x49\x4A\xF1\x21\xA9\xFE\x18\x4E\xEE\x48\xD4\x19\xBB\xEF\x7D\xE4\xE2\x9D\xCB\x5B\xB6\x6E\xFF\xE3\xCD\x5A\xE7\x74\x82\x05\xBA\x80\x25\x38\xCB\xE4\x69\x9E\xAF\x41\xAA\x1A\x84\xF5\x02\x03\x01\x00\x01\xA3\x82\x01\x34\x30\x82\x01\x30\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE3\xAB\x54\x4C\x80\xA1\xDB\x56\x43\xB7\x91\x4A\xCB\xF3\x82\x7A\x13\x5C\x08\xAB\x30\x81\xED\x06\x03\x55\x1D\x1F\x04\x81\xE5\x30\x81\xE2\x30\x81\xDF\xA0\x81\xDC\xA0\x81\xD9\x86\x35\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x2F\x63\x72\x6C\x2F\x76\x32\x2F\x74\x63\x5F\x63\x6C\x61\x73\x73\x5F\x32\x5F\x63\x61\x5F\x49\x49\x2E\x63\x72\x6C\x86\x81\x9F\x6C\x64\x61\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x2F\x43\x4E\x3D\x54\x43\x25\x32\x30\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x25\x32\x30\x43\x6C\x61\x73\x73\x25\x32\x30\x32\x25\x32\x30\x43\x41\x25\x32\x30\x49\x49\x2C\x4F\x3D\x54\x43\x25\x32\x30\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x25\x32\x30\x47\x6D\x62\x48\x2C\x4F\x55\x3D\x72\x6F\x6F\x74\x63\x65\x72\x74\x73\x2C\x44\x43\x3D\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2C\x44\x43\x3D\x64\x65\x3F\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x52\x65\x76\x6F\x63\x61\x74\x69\x6F\x6E\x4C\x69\x73\x74\x3F\x62\x61\x73\x65\x3F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x8C\xD7\xDF\x7E\xEE\x1B\x80\x10\xB3\x83\xF5\xDB\x11\xEA\x6B\x4B\xA8\x92\x18\xD9\xF7\x07\x39\xF5\x2C\xBE\x06\x75\x7A\x68\x53\x15\x1C\xEA\x4A\xED\x5E\xFC\x23\xB2\x13\xA0\xD3\x09\xFF\xF6\xF6\x2E\x6B\x41\x71\x79\xCD\xE2\x6D\xFD\xAE\x59\x6B\x85\x1D\xB8\x4E\x22\x9A\xED\x66\x39\x6E\x4B\x94\xE6\x55\xFC\x0B\x1B\x8B\x77\xC1\x53\x13\x66\x89\xD9\x28\xD6\x8B\xF3\x45\x4A\x63\xB7\xFD\x7B\x0B\x61\x5D\xB8\x6D\xBE\xC3\xDC\x5B\x79\xD2\xED\x86\xE5\xA2\x4D\xBE\x5E\x74\x7C\x6A\xED\x16\x38\x1F\x7F\x58\x81\x5A\x1A\xEB\x32\x88\x2D\xB2\xF3\x39\x77\x80\xAF\x5E\xB6\x61\x75\x29\xDB\x23\x4D\x88\xCA\x50\x28\xCB\x85\xD2\xD3\x10\xA2\x59\x6E\xD3\x93\x54\x00\x7A\xA2\x46\x95\x86\x05\x9C\xA9\x19\x98\xE5\x31\x72\x0C\x00\xE2\x67\xD9\x40\xE0\x24\x33\x7B\x6F\x2C\xB9\x5C\xAB\x65\x9D\x2C\xAC\x76\xEA\x35\x99\xF5\x97\xB9\x0F\x24\xEC\xC7\x76\x21\x28\x65\xAE\x57\xE8\x07\x88\x75\x4A\x56\xA0\xD2\x05\x3A\xA4\xE6\x8D\x92\x88\x2C\xF3\xF2\xE1\xC1\xC6\x61\xDB\x41\xC5\xC7\x9B\xF7\x0E\x1A\x51\x45\xC2\x61\x6B\xDC\x64\x27\x17\x8C\x5A\xB7\xDA\x74\x28\xCD\x97\xE4\xBD", - ["TC TrustCenter Class 3 CA II"] = "\x30\x82\x04\xAA\x30\x82\x03\x92\xA0\x03\x02\x01\x02\x02\x0E\x4A\x47\x00\x01\x00\x02\xE5\xA0\x5D\xD6\x3F\x00\x51\xBF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x76\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1C\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x20\x49\x49\x30\x1E\x17\x0D\x30\x36\x30\x31\x31\x32\x31\x34\x34\x31\x35\x37\x5A\x17\x0D\x32\x35\x31\x32\x33\x31\x32\x32\x35\x39\x35\x39\x5A\x30\x76\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1C\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x20\x49\x49\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\xB4\xE0\xBB\x51\xBB\x39\x5C\x8B\x04\xC5\x4C\x79\x1C\x23\x86\x31\x10\x63\x43\x55\x27\x3F\xC6\x45\xC7\xA4\x3D\xEC\x09\x0D\x1A\x1E\x20\xC2\x56\x1E\xDE\x1B\x37\x07\x30\x22\x2F\x6F\xF1\x06\xF1\xAB\xAD\xD6\xC8\xAB\x61\xA3\x2F\x43\xC4\xB0\xB2\x2D\xFC\xC3\x96\x69\x7B\x7E\x8A\xE4\xCC\xC0\x39\x12\x90\x42\x60\xC9\xCC\x35\x68\xEE\xDA\x5F\x90\x56\x5F\xCD\x1C\x4D\x5B\x58\x49\xEB\x0E\x01\x4F\x64\xFA\x2C\x3C\x89\x58\xD8\x2F\x2E\xE2\xB0\x68\xE9\x22\x3B\x75\x89\xD6\x44\x1A\x65\xF2\x1B\x97\x26\x1D\x28\x6D\xAC\xE8\xBD\x59\x1D\x2B\x24\xF6\xD6\x84\x03\x66\x88\x24\x00\x78\x60\xF1\xF8\xAB\xFE\x02\xB2\x6B\xFB\x22\xFB\x35\xE6\x16\xD1\xAD\xF6\x2E\x12\xE4\xFA\x35\x6A\xE5\x19\xB9\x5D\xDB\x3B\x1E\x1A\xFB\xD3\xFF\x15\x14\x08\xD8\x09\x6A\xBA\x45\x9D\x14\x79\x60\x7D\xAF\x40\x8A\x07\x73\xB3\x93\x96\xD3\x74\x34\x8D\x3A\x37\x29\xDE\x5C\xEC\xF5\xEE\x2E\x31\xC2\x20\xDC\xBE\xF1\x4F\x7F\x23\x52\xD9\x5B\xE2\x64\xD9\x9C\xAA\x07\x08\xB5\x45\xBD\xD1\xD0\x31\xC1\xAB\x54\x9F\xA9\xD2\xC3\x62\x60\x03\xF1\xBB\x39\x4A\x92\x4A\x3D\x0A\xB9\x9D\xC5\xA0\xFE\x37\x02\x03\x01\x00\x01\xA3\x82\x01\x34\x30\x82\x01\x30\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xD4\xA2\xFC\x9F\xB3\xC3\xD8\x03\xD3\x57\x5C\x07\xA4\xD0\x24\xA7\xC0\xF2\x00\xD4\x30\x81\xED\x06\x03\x55\x1D\x1F\x04\x81\xE5\x30\x81\xE2\x30\x81\xDF\xA0\x81\xDC\xA0\x81\xD9\x86\x35\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x2F\x63\x72\x6C\x2F\x76\x32\x2F\x74\x63\x5F\x63\x6C\x61\x73\x73\x5F\x33\x5F\x63\x61\x5F\x49\x49\x2E\x63\x72\x6C\x86\x81\x9F\x6C\x64\x61\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x2F\x43\x4E\x3D\x54\x43\x25\x32\x30\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x25\x32\x30\x43\x6C\x61\x73\x73\x25\x32\x30\x33\x25\x32\x30\x43\x41\x25\x32\x30\x49\x49\x2C\x4F\x3D\x54\x43\x25\x32\x30\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x25\x32\x30\x47\x6D\x62\x48\x2C\x4F\x55\x3D\x72\x6F\x6F\x74\x63\x65\x72\x74\x73\x2C\x44\x43\x3D\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2C\x44\x43\x3D\x64\x65\x3F\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x52\x65\x76\x6F\x63\x61\x74\x69\x6F\x6E\x4C\x69\x73\x74\x3F\x62\x61\x73\x65\x3F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x36\x60\xE4\x70\xF7\x06\x20\x43\xD9\x23\x1A\x42\xF2\xF8\xA3\xB2\xB9\x4D\x8A\xB4\xF3\xC2\x9A\x55\x31\x7C\xC4\x3B\x67\x9A\xB4\xDF\x4D\x0E\x8A\x93\x4A\x17\x8B\x1B\x8D\xCA\x89\xE1\xCF\x3A\x1E\xAC\x1D\xF1\x9C\x32\xB4\x8E\x59\x76\xA2\x41\x85\x25\x37\xA0\x13\xD0\xF5\x7C\x4E\xD5\xEA\x96\xE2\x6E\x72\xC1\xBB\x2A\xFE\x6C\x6E\xF8\x91\x98\x46\xFC\xC9\x1B\x57\x5B\xEA\xC8\x1A\x3B\x3F\xB0\x51\x98\x3C\x07\xDA\x2C\x59\x01\xDA\x8B\x44\xE8\xE1\x74\xFD\xA7\x68\xDD\x54\xBA\x83\x46\xEC\xC8\x46\xB5\xF8\xAF\x97\xC0\x3B\x09\x1C\x8F\xCE\x72\x96\x3D\x33\x56\x70\xBC\x96\xCB\xD8\xD5\x7D\x20\x9A\x83\x9F\x1A\xDC\x39\xF1\xC5\x72\xA3\x11\x03\xFD\x3B\x42\x52\x29\xDB\xE8\x01\xF7\x9B\x5E\x8C\xD6\x8D\x86\x4E\x19\xFA\xBC\x1C\xBE\xC5\x21\xA5\x87\x9E\x78\x2E\x36\xDB\x09\x71\xA3\x72\x34\xF8\x6C\xE3\x06\x09\xF2\x5E\x56\xA5\xD3\xDD\x98\xFA\xD4\xE6\x06\xF4\xF0\xB6\x20\x63\x4B\xEA\x29\xBD\xAA\x82\x66\x1E\xFB\x81\xAA\xA7\x37\xAD\x13\x18\xE6\x92\xC3\x81\xC1\x33\xBB\x88\x1E\xA1\xE7\xE2\xB4\xBD\x31\x6C\x0E\x51\x3D\x6F\xFB\x96\x56\x80\xE2\x36\x17\xD1\xDC\xE4", - ["TC TrustCenter Universal CA I"] = "\x30\x82\x03\xDD\x30\x82\x02\xC5\xA0\x03\x02\x01\x02\x02\x0E\x1D\xA2\x00\x01\x00\x02\xEC\xB7\x60\x80\x78\x8D\xB6\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x79\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0B\x13\x1B\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x49\x30\x1E\x17\x0D\x30\x36\x30\x33\x32\x32\x31\x35\x35\x34\x32\x38\x5A\x17\x0D\x32\x35\x31\x32\x33\x31\x32\x32\x35\x39\x35\x39\x5A\x30\x79\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0B\x13\x1B\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x49\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\xA4\x77\x23\x96\x44\xAF\x90\xF4\x31\xA7\x10\xF4\x26\x87\x9C\xF3\x38\xD9\x0F\x5E\xDE\xCF\x41\xE8\x31\xAD\xC6\x74\x91\x24\x96\x78\x1E\x09\xA0\x9B\x9A\x95\x4A\x4A\xF5\x62\x7C\x02\xA8\xCA\xAC\xFB\x5A\x04\x76\x39\xDE\x5F\xF1\xF9\xB3\xBF\xF3\x03\x58\x55\xD2\xAA\xB7\xE3\x04\x22\xD1\xF8\x94\xDA\x22\x08\x00\x8D\xD3\x7C\x26\x5D\xCC\x77\x79\xE7\x2C\x78\x39\xA8\x26\x73\x0E\xA2\x5D\x25\x69\x85\x4F\x55\x0E\x9A\xEF\xC6\xB9\x44\xE1\x57\x3D\xDF\x1F\x54\x22\xE5\x6F\x65\xAA\x33\x84\x3A\xF3\xCE\x7A\xBE\x55\x97\xAE\x8D\x12\x0F\x14\x33\xE2\x50\x70\xC3\x49\x87\x13\xBC\x51\xDE\xD7\x98\x12\x5A\xEF\x3A\x83\x33\x92\x06\x75\x8B\x92\x7C\x12\x68\x7B\x70\x6A\x0F\xB5\x9B\xB6\x77\x5B\x48\x59\x9D\xE4\xEF\x5A\xAD\xF3\xC1\x9E\xD4\xD7\x45\x4E\xCA\x56\x34\x21\xBC\x3E\x17\x5B\x6F\x77\x0C\x48\x01\x43\x29\xB0\xDD\x3F\x96\x6E\xE6\x95\xAA\x0C\xC0\x20\xB6\xFD\x3E\x36\x27\x9C\xE3\x5C\xCF\x4E\x81\xDC\x19\xBB\x91\x90\x7D\xEC\xE6\x97\x04\x1E\x93\xCC\x22\x49\xD7\x97\x86\xB6\x13\x0A\x3C\x43\x23\x77\x7E\xF0\xDC\xE6\xCD\x24\x1F\x3B\x83\x9B\x34\x3A\x83\x34\xE3\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x92\xA4\x75\x2C\xA4\x9E\xBE\x81\x44\xEB\x79\xFC\x8A\xC5\x95\xA5\xEB\x10\x75\x73\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x92\xA4\x75\x2C\xA4\x9E\xBE\x81\x44\xEB\x79\xFC\x8A\xC5\x95\xA5\xEB\x10\x75\x73\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x28\xD2\xE0\x86\xD5\xE6\xF8\x7B\xF0\x97\xDC\x22\x6B\x3B\x95\x14\x56\x0F\x11\x30\xA5\x9A\x4F\x3A\xB0\x3A\xE0\x06\xCB\x65\xF5\xED\xC6\x97\x27\xFE\x25\xF2\x57\xE6\x5E\x95\x8C\x3E\x64\x60\x15\x5A\x7F\x2F\x0D\x01\xC5\xB1\x60\xFD\x45\x35\xCF\xF0\xB2\xBF\x06\xD9\xEF\x5A\xBE\xB3\x62\x21\xB4\xD7\xAB\x35\x7C\x53\x3E\xA6\x27\xF1\xA1\x2D\xDA\x1A\x23\x9D\xCC\xDD\xEC\x3C\x2D\x9E\x27\x34\x5D\x0F\xC2\x36\x79\xBC\xC9\x4A\x62\x2D\xED\x6B\xD9\x7D\x41\x43\x7C\xB6\xAA\xCA\xED\x61\xB1\x37\x82\x15\x09\x1A\x8A\x16\x30\xD8\xEC\xC9\xD6\x47\x72\x78\x4B\x10\x46\x14\x8E\x5F\x0E\xAF\xEC\xC7\x2F\xAB\x10\xD7\xB6\xF1\x6E\xEC\x86\xB2\xC2\xE8\x0D\x92\x73\xDC\xA2\xF4\x0F\x3A\xBF\x61\x23\x10\x89\x9C\x48\x40\x6E\x70\x00\xB3\xD3\xBA\x37\x44\x58\x11\x7A\x02\x6A\x88\xF0\x37\x34\xF0\x19\xE9\xAC\xD4\x65\x73\xF6\x69\x8C\x64\x94\x3A\x79\x85\x29\xB0\x16\x2B\x0C\x82\x3F\x06\x9C\xC7\xFD\x10\x2B\x9E\x0F\x2C\xB6\x9E\xE3\x15\xBF\xD9\x36\x1C\xBA\x25\x1A\x52\x3D\x1A\xEC\x22\x0C\x1C\xE0\xA4\xA2\x3D\xF0\xE8\x39\xCF\x81\xC0\x7B\xED\x5D\x1F\x6F\xC5\xD0\x0B\xD7\x98", - ["Deutsche Telekom Root CA 2"] = "\x30\x82\x03\x9F\x30\x82\x02\x87\xA0\x03\x02\x01\x02\x02\x01\x26\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x71\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x44\x65\x75\x74\x73\x63\x68\x65\x20\x54\x65\x6C\x65\x6B\x6F\x6D\x20\x41\x47\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x54\x2D\x54\x65\x6C\x65\x53\x65\x63\x20\x54\x72\x75\x73\x74\x20\x43\x65\x6E\x74\x65\x72\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x44\x65\x75\x74\x73\x63\x68\x65\x20\x54\x65\x6C\x65\x6B\x6F\x6D\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x1E\x17\x0D\x39\x39\x30\x37\x30\x39\x31\x32\x31\x31\x30\x30\x5A\x17\x0D\x31\x39\x30\x37\x30\x39\x32\x33\x35\x39\x30\x30\x5A\x30\x71\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x44\x65\x75\x74\x73\x63\x68\x65\x20\x54\x65\x6C\x65\x6B\x6F\x6D\x20\x41\x47\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x54\x2D\x54\x65\x6C\x65\x53\x65\x63\x20\x54\x72\x75\x73\x74\x20\x43\x65\x6E\x74\x65\x72\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x44\x65\x75\x74\x73\x63\x68\x65\x20\x54\x65\x6C\x65\x6B\x6F\x6D\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\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\xAB\x0B\xA3\x35\xE0\x8B\x29\x14\xB1\x14\x85\xAF\x3C\x10\xE4\x39\x6F\x35\x5D\x4A\xAE\xDD\xEA\x61\x8D\x95\x49\xF4\x6F\x64\xA3\x1A\x60\x66\xA4\xA9\x40\x22\x84\xD9\xD4\xA5\xE5\x78\x93\x0E\x68\x01\xAD\xB9\x4D\x5C\x3A\xCE\xD3\xB8\xA8\x42\x40\xDF\xCF\xA3\xBA\x82\x59\x6A\x92\x1B\xAC\x1C\x9A\xDA\x08\x2B\x25\x27\xF9\x69\x23\x47\xF1\xE0\xEB\x2C\x7A\x9B\xF5\x13\x02\xD0\x7E\x34\x7C\xC2\x9E\x3C\x00\x59\xAB\xF5\xDA\x0C\xF5\x32\x3C\x2B\xAC\x50\xDA\xD6\xC3\xDE\x83\x94\xCA\xA8\x0C\x99\x32\x0E\x08\x48\x56\x5B\x6A\xFB\xDA\xE1\x58\x58\x01\x49\x5F\x72\x41\x3C\x15\x06\x01\x8E\x5D\xAD\xAA\xB8\x93\xB4\xCD\x9E\xEB\xA7\xE8\x6A\x2D\x52\x34\xDB\x3A\xEF\x5C\x75\x51\xDA\xDB\xF3\x31\xF9\xEE\x71\x98\x32\xC4\x54\x15\x44\x0C\xF9\x9B\x55\xED\xAD\xDF\x18\x08\xA0\xA3\x86\x8A\x49\xEE\x53\x05\x8F\x19\x4C\xD5\xDE\x58\x79\x9B\xD2\x6A\x1C\x42\xAB\xC5\xD5\xA7\xCF\x68\x0F\x96\xE4\xE1\x61\x98\x76\x61\xC8\x91\x7C\xD6\x3E\x00\xE2\x91\x50\x87\xE1\x9D\x0A\xE6\xAD\x97\xD2\x1D\xC6\x3A\x7D\xCB\xBC\xDA\x03\x34\xD5\x8E\x5B\x01\xF5\x6A\x07\xB7\x16\xB6\x6E\x4A\x7F\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x31\xC3\x79\x1B\xBA\xF5\x53\xD7\x17\xE0\x89\x7A\x2D\x17\x6C\x0A\xB3\x2B\x9D\x33\x30\x0F\x06\x03\x55\x1D\x13\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x05\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x94\x64\x59\xAD\x39\x64\xE7\x29\xEB\x13\xFE\x5A\xC3\x8B\x13\x57\xC8\x04\x24\xF0\x74\x77\xC0\x60\xE3\x67\xFB\xE9\x89\xA6\x83\xBF\x96\x82\x7C\x6E\xD4\xC3\x3D\xEF\x9E\x80\x6E\xBB\x29\xB4\x98\x7A\xB1\x3B\x54\xEB\x39\x17\x47\x7E\x1A\x8E\x0B\xFC\x1F\x31\x59\x31\x04\xB2\xCE\x17\xF3\x2C\xC7\x62\x36\x55\xE2\x22\xD8\x89\x55\xB4\x98\x48\xAA\x64\xFA\xD6\x1C\x36\xD8\x44\x78\x5A\x5A\x23\x3A\x57\x97\xF5\x7A\x30\x4F\xAE\x9F\x6A\x4C\x4B\x2B\x8E\xA0\x03\xE3\x3E\xE0\xA9\xD4\xD2\x7B\xD2\xB3\xA8\xE2\x72\x3C\xAD\x9E\xFF\x80\x59\xE4\x9B\x45\xB4\xF6\x3B\xB0\xCD\x39\x19\x98\x32\xE5\xEA\x21\x61\x90\xE4\x31\x21\x8E\x34\xB1\xF7\x2F\x35\x4A\x85\x10\xDA\xE7\x8A\x37\x21\xBE\x59\x63\xE0\xF2\x85\x88\x31\x53\xD4\x54\x14\x85\x70\x79\xF4\x2E\x06\x77\x27\x75\x2F\x1F\xB8\x8A\xF9\xFE\xC5\xBA\xD8\x36\xE4\x83\xEC\xE7\x65\xB7\xBF\x63\x5A\xF3\x46\xAF\x81\x94\x37\xD4\x41\x8C\xD6\x23\xD6\x1E\xCF\xF5\x68\x1B\x44\x63\xA2\x5A\xBA\xA7\x35\x59\xA1\xE5\x70\x05\x9B\x0E\x23\x57\x99\x94\x0A\x6D\xBA\x39\x63\x28\x86\x92\xF3\x18\x84\xD8\xFB\xD1\xCF\x05\x56\x64\x57", - ["ComSign Secured CA"] = "\x30\x82\x03\xAB\x30\x82\x02\x93\xA0\x03\x02\x01\x02\x02\x11\x00\xC7\x28\x47\x09\xB3\xB8\x6C\x45\x8C\x1D\xFA\x24\xF5\x36\x4E\xE9\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3C\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x43\x6F\x6D\x53\x69\x67\x6E\x20\x53\x65\x63\x75\x72\x65\x64\x20\x43\x41\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x43\x6F\x6D\x53\x69\x67\x6E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4C\x30\x1E\x17\x0D\x30\x34\x30\x33\x32\x34\x31\x31\x33\x37\x32\x30\x5A\x17\x0D\x32\x39\x30\x33\x31\x36\x31\x35\x30\x34\x35\x36\x5A\x30\x3C\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x43\x6F\x6D\x53\x69\x67\x6E\x20\x53\x65\x63\x75\x72\x65\x64\x20\x43\x41\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x43\x6F\x6D\x53\x69\x67\x6E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4C\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\xC6\xB5\x68\x5F\x1D\x94\x15\xC3\xA4\x08\x55\x2D\xE3\xA0\x57\x7A\xEF\xE9\x74\x2A\xBB\xB9\x7C\x57\x49\x1A\x11\x5E\x4F\x29\x87\x0C\x48\xD6\x6A\xE7\x8F\xD4\x7E\x57\x24\xB9\x06\x89\xE4\x1C\x3C\xEA\xAC\xE3\xDA\x21\x80\x73\x21\x0A\xEF\x79\x98\x6C\x1F\x08\xFF\xA1\x50\x7D\xF2\x98\x1B\xC9\x54\x6F\x3E\xA5\x28\xEC\x21\x04\x0F\x45\xBB\x07\x3D\xA1\xC0\xFA\x2A\x98\x1D\x4E\x06\x93\xFB\xF5\x88\x3B\xAB\x5F\xCB\x16\xBF\xE6\xF3\x9E\x4A\x87\xED\x19\xEA\xC2\x9F\x43\xE4\xF1\x81\xA5\x7F\x10\x4F\x3E\xD1\x4A\x62\xAD\x53\x1B\xCB\x83\xFF\x07\x65\xA5\x92\x2D\x66\xA9\x5B\xB8\x5A\xF4\x1D\xB4\x21\x91\x4A\x17\x7B\x9E\x32\xFE\x56\x24\x39\xB2\x54\x84\x43\xF5\x84\xC2\xD8\xBC\x41\x90\xCC\x9D\xD6\x68\xDA\xE9\x82\x50\xA9\x3B\x68\xCF\xB5\x5D\x02\x94\x60\x16\xB1\x43\xD9\x43\x5D\xDD\x5D\x87\x6E\xEA\xBB\xB3\xC9\x6B\xF6\x03\x94\x09\x70\xDE\x16\x11\x7A\x2B\xE8\x76\x8F\x49\x10\x98\x77\xB9\x63\x5C\x8B\x33\x97\x75\xF6\x0B\x8C\xB2\xAB\x5B\xDE\x74\x20\x25\x3F\xE3\xF3\x11\xF9\x87\x68\x86\x35\x71\xC3\x1D\x8C\x2D\xEB\xE5\x1A\xAC\x0F\x73\xD5\x82\x59\x40\x80\xD3\x02\x03\x01\x00\x01\xA3\x81\xA7\x30\x81\xA4\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x44\x06\x03\x55\x1D\x1F\x04\x3D\x30\x3B\x30\x39\xA0\x37\xA0\x35\x86\x33\x68\x74\x74\x70\x3A\x2F\x2F\x66\x65\x64\x69\x72\x2E\x63\x6F\x6D\x73\x69\x67\x6E\x2E\x63\x6F\x2E\x69\x6C\x2F\x63\x72\x6C\x2F\x43\x6F\x6D\x53\x69\x67\x6E\x53\x65\x63\x75\x72\x65\x64\x43\x41\x2E\x63\x72\x6C\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xC1\x4B\xED\x70\xB6\xF7\x3E\x7C\x00\x3B\x00\x8F\xC7\x3E\x0E\x45\x9F\x1E\x5D\xEC\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC1\x4B\xED\x70\xB6\xF7\x3E\x7C\x00\x3B\x00\x8F\xC7\x3E\x0E\x45\x9F\x1E\x5D\xEC\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x16\xCF\xEE\x92\x13\x50\xAB\x7B\x14\x9E\x33\xB6\x42\x20\x6A\xD4\x15\xBD\x09\xAB\xFC\x72\xE8\xEF\x47\x7A\x90\xAC\x51\xC1\x64\x4E\xE9\x88\xBD\x43\x45\x81\xE3\x66\x23\x3F\x12\x86\x4D\x19\xE4\x05\xB0\xE6\x37\xC2\x8D\xDA\x06\x28\xC9\x0F\x89\xA4\x53\xA9\x75\x3F\xB0\x96\xFB\xAB\x4C\x33\x55\xF9\x78\x26\x46\x6F\x1B\x36\x98\xFB\x42\x76\xC1\x82\xB9\x8E\xDE\xFB\x45\xF9\x63\x1B\x62\x3B\x39\x06\xCA\x77\x7A\xA8\x3C\x09\xCF\x6C\x36\x3D\x0F\x0A\x45\x4B\x69\x16\x1A\x45\x7D\x33\x03\x65\xF9\x52\x71\x90\x26\x95\xAC\x4C\x0C\xF5\x8B\x93\x3F\xCC\x75\x74\x85\x98\xBA\xFF\x62\x7A\x4D\x1F\x89\xFE\xAE\xBD\x94\x00\x99\xBF\x11\xA5\xDC\xE0\x79\xC5\x16\x0B\x7D\x02\x61\x1D\xEA\x85\xF9\x02\x15\x4F\xE7\x5A\x89\x4E\x14\x6F\xE3\x37\x4B\x85\xF5\xC1\x3C\x61\xE0\xFD\x05\x41\xB2\x92\x7F\xC3\x1D\xA0\xD0\xAE\x52\x64\x60\x6B\x18\xC6\x26\x9C\xD8\xF5\x64\xE4\x36\x1A\x62\x9F\x8A\x0F\x3E\xFF\x6D\x4E\x19\x56\x4E\x20\x91\x6C\x9F\x34\x33\x3A\x34\x57\x50\x3A\x6F\x81\x5E\x06\xC6\xF5\x3E\x7C\x4E\x8E\x2B\xCE\x65\x06\x2E\x5D\xD2\x2A\x53\x74\x5E\xD3\x6E\x27\x9E\x8F", - ["Cybertrust Global Root"] = "\x30\x82\x03\xA1\x30\x82\x02\x89\xA0\x03\x02\x01\x02\x02\x0B\x04\x00\x00\x00\x00\x01\x0F\x85\xAA\x2D\x48\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3B\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x13\x0F\x43\x79\x62\x65\x72\x74\x72\x75\x73\x74\x2C\x20\x49\x6E\x63\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x43\x79\x62\x65\x72\x74\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x36\x31\x32\x31\x35\x30\x38\x30\x30\x30\x30\x5A\x17\x0D\x32\x31\x31\x32\x31\x35\x30\x38\x30\x30\x30\x30\x5A\x30\x3B\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x13\x0F\x43\x79\x62\x65\x72\x74\x72\x75\x73\x74\x2C\x20\x49\x6E\x63\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x43\x79\x62\x65\x72\x74\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\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\xF8\xC8\xBC\xBD\x14\x50\x66\x13\xFF\xF0\xD3\x79\xEC\x23\xF2\xB7\x1A\xC7\x8E\x85\xF1\x12\x73\xA6\x19\xAA\x10\xDB\x9C\xA2\x65\x74\x5A\x77\x3E\x51\x7D\x56\xF6\xDC\x23\xB6\xD4\xED\x5F\x58\xB1\x37\x4D\xD5\x49\x0E\x6E\xF5\x6A\x87\xD6\xD2\x8C\xD2\x27\xC6\xE2\xFF\x36\x9F\x98\x65\xA0\x13\x4E\xC6\x2A\x64\x9B\xD5\x90\x12\xCF\x14\x06\xF4\x3B\xE3\xD4\x28\xBE\xE8\x0E\xF8\xAB\x4E\x48\x94\x6D\x8E\x95\x31\x10\x5C\xED\xA2\x2D\xBD\xD5\x3A\x6D\xB2\x1C\xBB\x60\xC0\x46\x4B\x01\xF5\x49\xAE\x7E\x46\x8A\xD0\x74\x8D\xA1\x0C\x02\xCE\xEE\xFC\xE7\x8F\xB8\x6B\x66\xF3\x7F\x44\x00\xBF\x66\x25\x14\x2B\xDD\x10\x30\x1D\x07\x96\x3F\x4D\xF6\x6B\xB8\x8F\xB7\x7B\x0C\xA5\x38\xEB\xDE\x47\xDB\xD5\x5D\x39\xFC\x88\xA7\xF3\xD7\x2A\x74\xF1\xE8\x5A\xA2\x3B\x9F\x50\xBA\xA6\x8C\x45\x35\xC2\x50\x65\x95\xDC\x63\x82\xEF\xDD\xBF\x77\x4D\x9C\x62\xC9\x63\x73\x16\xD0\x29\x0F\x49\xA9\x48\xF0\xB3\xAA\xB7\x6C\xC5\xA7\x30\x39\x40\x5D\xAE\xC4\xE2\x5D\x26\x53\xF0\xCE\x1C\x23\x08\x61\xA8\x94\x19\xBA\x04\x62\x40\xEC\x1F\x38\x70\x77\x12\x06\x71\xA7\x30\x18\x5D\x25\x27\xA5\x02\x03\x01\x00\x01\xA3\x81\xA5\x30\x81\xA2\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB6\x08\x7B\x0D\x7A\xCC\xAC\x20\x4C\x86\x56\x32\x5E\xCF\xAB\x6E\x85\x2D\x70\x57\x30\x3F\x06\x03\x55\x1D\x1F\x04\x38\x30\x36\x30\x34\xA0\x32\xA0\x30\x86\x2E\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x32\x2E\x70\x75\x62\x6C\x69\x63\x2D\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x2F\x63\x72\x6C\x2F\x63\x74\x2F\x63\x74\x72\x6F\x6F\x74\x2E\x63\x72\x6C\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xB6\x08\x7B\x0D\x7A\xCC\xAC\x20\x4C\x86\x56\x32\x5E\xCF\xAB\x6E\x85\x2D\x70\x57\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x56\xEF\x0A\x23\xA0\x54\x4E\x95\x97\xC9\xF8\x89\xDA\x45\xC1\xD4\xA3\x00\x25\xF4\x1F\x13\xAB\xB7\xA3\x85\x58\x69\xC2\x30\xAD\xD8\x15\x8A\x2D\xE3\xC9\xCD\x81\x5A\xF8\x73\x23\x5A\xA7\x7C\x05\xF3\xFD\x22\x3B\x0E\xD1\x06\xC4\xDB\x36\x4C\x73\x04\x8E\xE5\xB0\x22\xE4\xC5\xF3\x2E\xA5\xD9\x23\xE3\xB8\x4E\x4A\x20\xA7\x6E\x02\x24\x9F\x22\x60\x67\x7B\x8B\x1D\x72\x09\xC5\x31\x5C\xE9\x79\x9F\x80\x47\x3D\xAD\xA1\x0B\x07\x14\x3D\x47\xFF\x03\x69\x1A\x0C\x0B\x44\xE7\x63\x25\xA7\x7F\xB2\xC9\xB8\x76\x84\xED\x23\xF6\x7D\x07\xAB\x45\x7E\xD3\xDF\xB3\xBF\xE9\x8A\xB6\xCD\xA8\xA2\x67\x2B\x52\xD5\xB7\x65\xF0\x39\x4C\x63\xA0\x91\x79\x93\x52\x0F\x54\xDD\x83\xBB\x9F\xD1\x8F\xA7\x53\x73\xC3\xCB\xFF\x30\xEC\x7C\x04\xB8\xD8\x44\x1F\x93\x5F\x71\x09\x22\xB7\x6E\x3E\xEA\x1C\x03\x4E\x9D\x1A\x20\x61\xFB\x81\x37\xEC\x5E\xFC\x0A\x45\xAB\xD7\xE7\x17\x55\xD0\xA0\xEA\x60\x9B\xA6\xF6\xE3\x8C\x5B\x29\xC2\x06\x60\x14\x9D\x2D\x97\x4C\xA9\x93\x15\x9D\x61\xC4\x01\x5F\x48\xD6\x58\xBD\x56\x31\x12\x4E\x11\xC8\x21\xE0\xB3\x11\x91\x65\xDB\xB4\xA6\x88\x38\xCE\x55", - ["ePKI Root Certification Authority"] = "\x30\x82\x05\xB0\x30\x82\x03\x98\xA0\x03\x02\x01\x02\x02\x10\x15\xC8\xBD\x65\x47\x5C\xAF\xB8\x97\x00\x5E\xE4\x06\xD2\xBC\x9D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x5E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x23\x30\x21\x06\x03\x55\x04\x0A\x0C\x1A\x43\x68\x75\x6E\x67\x68\x77\x61\x20\x54\x65\x6C\x65\x63\x6F\x6D\x20\x43\x6F\x2E\x2C\x20\x4C\x74\x64\x2E\x31\x2A\x30\x28\x06\x03\x55\x04\x0B\x0C\x21\x65\x50\x4B\x49\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x34\x31\x32\x32\x30\x30\x32\x33\x31\x32\x37\x5A\x17\x0D\x33\x34\x31\x32\x32\x30\x30\x32\x33\x31\x32\x37\x5A\x30\x5E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x23\x30\x21\x06\x03\x55\x04\x0A\x0C\x1A\x43\x68\x75\x6E\x67\x68\x77\x61\x20\x54\x65\x6C\x65\x63\x6F\x6D\x20\x43\x6F\x2E\x2C\x20\x4C\x74\x64\x2E\x31\x2A\x30\x28\x06\x03\x55\x04\x0B\x0C\x21\x65\x50\x4B\x49\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xE1\x25\x0F\xEE\x8D\xDB\x88\x33\x75\x67\xCD\xAD\x1F\x7D\x3A\x4E\x6D\x9D\xD3\x2F\x14\xF3\x63\x74\xCB\x01\x21\x6A\x37\xEA\x84\x50\x07\x4B\x26\x5B\x09\x43\x6C\x21\x9E\x6A\xC8\xD5\x03\xF5\x60\x69\x8F\xCC\xF0\x22\xE4\x1F\xE7\xF7\x6A\x22\x31\xB7\x2C\x15\xF2\xE0\xFE\x00\x6A\x43\xFF\x87\x65\xC6\xB5\x1A\xC1\xA7\x4C\x6D\x22\x70\x21\x8A\x31\xF2\x97\x74\x89\x09\x12\x26\x1C\x9E\xCA\xD9\x12\xA2\x95\x3C\xDA\xE9\x67\xBF\x08\xA0\x64\xE3\xD6\x42\xB7\x45\xEF\x97\xF4\xF6\xF5\xD7\xB5\x4A\x15\x02\x58\x7D\x98\x58\x4B\x60\xBC\xCD\xD7\x0D\x9A\x13\x33\x53\xD1\x61\xF9\x7A\xD5\xD7\x78\xB3\x9A\x33\xF7\x00\x86\xCE\x1D\x4D\x94\x38\xAF\xA8\xEC\x78\x51\x70\x8A\x5C\x10\x83\x51\x21\xF7\x11\x3D\x34\x86\x5E\xE5\x48\xCD\x97\x81\x82\x35\x4C\x19\xEC\x65\xF6\x6B\xC5\x05\xA1\xEE\x47\x13\xD6\xB3\x21\x27\x94\x10\x0A\xD9\x24\x3B\xBA\xBE\x44\x13\x46\x30\x3F\x97\x3C\xD8\xD7\xD7\x6A\xEE\x3B\x38\xE3\x2B\xD4\x97\x0E\xB9\x1B\xE7\x07\x49\x7F\x37\x2A\xF9\x77\x78\xCF\x54\xED\x5B\x46\x9D\xA3\x80\x0E\x91\x43\xC1\xD6\x5B\x5F\x14\xBA\x9F\xA6\x8D\x24\x47\x40\x59\xBF\x72\x38\xB2\x36\x6C\x37\xFF\x99\xD1\x5D\x0E\x59\x0A\xAB\x69\xF7\xC0\xB2\x04\x45\x7A\x54\x00\xAE\xBE\x53\xF6\xB5\xE7\xE1\xF8\x3C\xA3\x31\xD2\xA9\xFE\x21\x52\x64\xC5\xA6\x67\xF0\x75\x07\x06\x94\x14\x81\x55\xC6\x27\xE4\x01\x8F\x17\xC1\x6A\x71\xD7\xBE\x4B\xFB\x94\x58\x7D\x7E\x11\x33\xB1\x42\xF7\x62\x6C\x18\xD6\xCF\x09\x68\x3E\x7F\x6C\xF6\x1E\x8F\x62\xAD\xA5\x63\xDB\x09\xA7\x1F\x22\x42\x41\x1E\x6F\x99\x8A\x3E\xD7\xF9\x3F\x40\x7A\x79\xB0\xA5\x01\x92\xD2\x9D\x3D\x08\x15\xA5\x10\x01\x2D\xB3\x32\x76\xA8\x95\x0D\xB3\x7A\x9A\xFB\x07\x10\x78\x11\x6F\xE1\x8F\xC7\xBA\x0F\x25\x1A\x74\x2A\xE5\x1C\x98\x41\x99\xDF\x21\x87\xE8\x95\x06\x6A\x0A\xB3\x6A\x47\x76\x65\xF6\x3A\xCF\x8F\x62\x17\x19\x7B\x0A\x28\xCD\x1A\xD2\x83\x1E\x21\xC7\x2C\xBF\xBE\xFF\x61\x68\xB7\x67\x1B\xBB\x78\x4D\x8D\xCE\x67\xE5\xE4\xC1\x8E\xB7\x23\x66\xE2\x9D\x90\x75\x34\x98\xA9\x36\x2B\x8A\x9A\x94\xB9\x9D\xEC\xCC\x8A\xB1\xF8\x25\x89\x5C\x5A\xB6\x2F\x8C\x1F\x6D\x79\x24\xA7\x52\x68\xC3\x84\x35\xE2\x66\x8D\x63\x0E\x25\x4D\xD5\x19\xB2\xE6\x79\x37\xA7\x22\x9D\x54\x31\x02\x03\x01\x00\x01\xA3\x6A\x30\x68\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x1E\x0C\xF7\xB6\x67\xF2\xE1\x92\x26\x09\x45\xC0\x55\x39\x2E\x77\x3F\x42\x4A\xA2\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x39\x06\x04\x67\x2A\x07\x00\x04\x31\x30\x2F\x30\x2D\x02\x01\x00\x30\x09\x06\x05\x2B\x0E\x03\x02\x1A\x05\x00\x30\x07\x06\x05\x67\x2A\x03\x00\x00\x04\x14\x45\xB0\xC2\xC7\x0A\x56\x7C\xEE\x5B\x78\x0C\x95\xF9\x18\x53\xC1\xA6\x1C\xD8\x10\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x09\xB3\x83\x53\x59\x01\x3E\x95\x49\xB9\xF1\x81\xBA\xF9\x76\x20\x23\xB5\x27\x60\x74\xD4\x6A\x99\x34\x5E\x6C\x00\x53\xD9\x9F\xF2\xA6\xB1\x24\x07\x44\x6A\x2A\xC6\xA5\x8E\x78\x12\xE8\x47\xD9\x58\x1B\x13\x2A\x5E\x79\x9B\x9F\x0A\x2A\x67\xA6\x25\x3F\x06\x69\x56\x73\xC3\x8A\x66\x48\xFB\x29\x81\x57\x74\x06\xCA\x9C\xEA\x28\xE8\x38\x67\x26\x2B\xF1\xD5\xB5\x3F\x65\x93\xF8\x36\x5D\x8E\x8D\x8D\x40\x20\x87\x19\xEA\xEF\x27\xC0\x3D\xB4\x39\x0F\x25\x7B\x68\x50\x74\x55\x9C\x0C\x59\x7D\x5A\x3D\x41\x94\x25\x52\x08\xE0\x47\x2C\x15\x31\x19\xD5\xBF\x07\x55\xC6\xBB\x12\xB5\x97\xF4\x5F\x83\x85\xBA\x71\xC1\xD9\x6C\x81\x11\x76\x0A\x0A\xB0\xBF\x82\x97\xF7\xEA\x3D\xFA\xFA\xEC\x2D\xA9\x28\x94\x3B\x56\xDD\xD2\x51\x2E\xAE\xC0\xBD\x08\x15\x8C\x77\x52\x34\x96\xD6\x9B\xAC\xD3\x1D\x8E\x61\x0F\x35\x7B\x9B\xAE\x39\x69\x0B\x62\x60\x40\x20\x36\x8F\xAF\xFB\x36\xEE\x2D\x08\x4A\x1D\xB8\xBF\x9B\x5C\xF8\xEA\xA5\x1B\xA0\x73\xA6\xD8\xF8\x6E\xE0\x33\x04\x5F\x68\xAA\x27\x87\xED\xD9\xC1\x90\x9C\xED\xBD\xE3\x6A\x35\xAF\x63\xDF\xAB\x18\xD9\xBA\xE6\xE9\x4A\xEA\x50\x8A\x0F\x61\x93\x1E\xE2\x2D\x19\xE2\x30\x94\x35\x92\x5D\x0E\xB6\x07\xAF\x19\x80\x8F\x47\x90\x51\x4B\x2E\x4D\xDD\x85\xE2\xD2\x0A\x52\x0A\x17\x9A\xFC\x1A\xB0\x50\x02\xE5\x01\xA3\x63\x37\x21\x4C\x44\xC4\x9B\x51\x99\x11\x0E\x73\x9C\x06\x8F\x54\x2E\xA7\x28\x5E\x44\x39\x87\x56\x2D\x37\xBD\x85\x44\x94\xE1\x0C\x4B\x2C\x9C\xC3\x92\x85\x34\x61\xCB\x0F\xB8\x9B\x4A\x43\x52\xFE\x34\x3A\x7D\xB8\xE9\x29\xDC\x76\xA9\xC8\x30\xF8\x14\x71\x80\xC6\x1E\x36\x48\x74\x22\x41\x5C\x87\x82\xE8\x18\x71\x8B\x41\x89\x44\xE7\x7E\x58\x5B\xA8\xB8\x8D\x13\xE9\xA7\x6C\xC3\x47\xED\xB3\x1A\x9D\x62\xAE\x8D\x82\xEA\x94\x9E\xDD\x59\x10\xC3\xAD\xDD\xE2\x4D\xE3\x31\xD5\xC7\xEC\xE8\xF2\xB0\xFE\x92\x1E\x16\x0A\x1A\xFC\xD9\xF3\xF8\x27\xB6\xC9\xBE\x1D\xB4\x6C\x64\x90\x7F\xF4\xE4\xC4\x5B\xD7\x37\xAE\x42\x0E\xDD\xA4\x1A\x6F\x7C\x88\x54\xC5\x16\x6E\xE1\x7A\x68\x2E\xF8\x3A\xBF\x0D\xA4\x3C\x89\x3B\x78\xA7\x4E\x63\x83\x04\x21\x08\x67\x8D\xF2\x82\x49\xD0\x5B\xFD\xB1\xCD\x0F\x83\x84\xD4\x3E\x20\x85\xF7\x4A\x3D\x2B\x9C\xFD\x2A\x0A\x09\x4D\xEA\x81\xF8\x11\x9C", - ["T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3"] = "\x30\x82\x05\x17\x30\x82\x03\xFF\xA0\x03\x02\x01\x02\x02\x01\x11\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x82\x01\x2B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x18\x30\x16\x06\x03\x55\x04\x07\x0C\x0F\x47\x65\x62\x7A\x65\x20\x2D\x20\x4B\x6F\x63\x61\x65\x6C\x69\x31\x47\x30\x45\x06\x03\x55\x04\x0A\x0C\x3E\x54\xC3\xBC\x72\x6B\x69\x79\x65\x20\x42\x69\x6C\x69\x6D\x73\x65\x6C\x20\x76\x65\x20\x54\x65\x6B\x6E\x6F\x6C\x6F\x6A\x69\x6B\x20\x41\x72\x61\xC5\x9F\x74\xC4\xB1\x72\x6D\x61\x20\x4B\x75\x72\x75\x6D\x75\x20\x2D\x20\x54\xC3\x9C\x42\xC4\xB0\x54\x41\x4B\x31\x48\x30\x46\x06\x03\x55\x04\x0B\x0C\x3F\x55\x6C\x75\x73\x61\x6C\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x76\x65\x20\x4B\x72\x69\x70\x74\x6F\x6C\x6F\x6A\x69\x20\x41\x72\x61\xC5\x9F\x74\xC4\xB1\x72\x6D\x61\x20\x45\x6E\x73\x74\x69\x74\xC3\xBC\x73\xC3\xBC\x20\x2D\x20\x55\x45\x4B\x41\x45\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x0C\x1A\x4B\x61\x6D\x75\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x73\x79\x6F\x6E\x20\x4D\x65\x72\x6B\x65\x7A\x69\x31\x4A\x30\x48\x06\x03\x55\x04\x03\x0C\x41\x54\xC3\x9C\x42\xC4\xB0\x54\x41\x4B\x20\x55\x45\x4B\x41\x45\x20\x4B\xC3\xB6\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x20\x2D\x20\x53\xC3\xBC\x72\xC3\xBC\x6D\x20\x33\x30\x1E\x17\x0D\x30\x37\x30\x38\x32\x34\x31\x31\x33\x37\x30\x37\x5A\x17\x0D\x31\x37\x30\x38\x32\x31\x31\x31\x33\x37\x30\x37\x5A\x30\x82\x01\x2B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x18\x30\x16\x06\x03\x55\x04\x07\x0C\x0F\x47\x65\x62\x7A\x65\x20\x2D\x20\x4B\x6F\x63\x61\x65\x6C\x69\x31\x47\x30\x45\x06\x03\x55\x04\x0A\x0C\x3E\x54\xC3\xBC\x72\x6B\x69\x79\x65\x20\x42\x69\x6C\x69\x6D\x73\x65\x6C\x20\x76\x65\x20\x54\x65\x6B\x6E\x6F\x6C\x6F\x6A\x69\x6B\x20\x41\x72\x61\xC5\x9F\x74\xC4\xB1\x72\x6D\x61\x20\x4B\x75\x72\x75\x6D\x75\x20\x2D\x20\x54\xC3\x9C\x42\xC4\xB0\x54\x41\x4B\x31\x48\x30\x46\x06\x03\x55\x04\x0B\x0C\x3F\x55\x6C\x75\x73\x61\x6C\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x76\x65\x20\x4B\x72\x69\x70\x74\x6F\x6C\x6F\x6A\x69\x20\x41\x72\x61\xC5\x9F\x74\xC4\xB1\x72\x6D\x61\x20\x45\x6E\x73\x74\x69\x74\xC3\xBC\x73\xC3\xBC\x20\x2D\x20\x55\x45\x4B\x41\x45\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x0C\x1A\x4B\x61\x6D\x75\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x73\x79\x6F\x6E\x20\x4D\x65\x72\x6B\x65\x7A\x69\x31\x4A\x30\x48\x06\x03\x55\x04\x03\x0C\x41\x54\xC3\x9C\x42\xC4\xB0\x54\x41\x4B\x20\x55\x45\x4B\x41\x45\x20\x4B\xC3\xB6\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x20\x2D\x20\x53\xC3\xBC\x72\xC3\xBC\x6D\x20\x33\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\x8A\x6D\x4B\xFF\x10\x88\x3A\xC3\xF6\x7E\x94\xE8\xEA\x20\x64\x70\xAE\x21\x81\xBE\x3A\x7B\x3C\xDB\xF1\x1D\x52\x7F\x59\xFA\xF3\x22\x4C\x95\xA0\x90\xBC\x48\x4E\x11\xAB\xFB\xB7\xB5\x8D\x7A\x83\x28\x8C\x26\x46\xD8\x4E\x95\x40\x87\x61\x9F\xC5\x9E\x6D\x81\x87\x57\x6C\x8A\x3B\xB4\x66\xEA\xCC\x40\xFC\xE3\xAA\x6C\xB2\xCB\x01\xDB\x32\xBF\xD2\xEB\x85\xCF\xA1\x0D\x55\xC3\x5B\x38\x57\x70\xB8\x75\xC6\x79\xD1\x14\x30\xED\x1B\x58\x5B\x6B\xEF\x35\xF2\xA1\x21\x4E\xC5\xCE\x7C\x99\x5F\x6C\xB9\xB8\x22\x93\x50\xA7\xCD\x4C\x70\x6A\xBE\x6A\x05\x7F\x13\x9C\x2B\x1E\xEA\xFE\x47\xCE\x04\xA5\x6F\xAC\x93\x2E\x7C\x2B\x9F\x9E\x79\x13\x91\xE8\xEA\x9E\xCA\x38\x75\x8E\x62\xB0\x95\x93\x2A\xE5\xDF\xE9\x5E\x97\x6E\x20\x5F\x5F\x84\x7A\x44\x39\x19\x40\x1C\xBA\x55\x2B\xFB\x30\xB2\x81\xEF\x84\xE3\xDC\xEC\x98\x38\x39\x03\x85\x08\xA9\x54\x03\x05\x29\xF0\xC9\x8F\x8B\xEA\x0B\x86\x65\x19\x11\xD3\xE9\x09\x23\xDE\x68\x93\x03\xC9\x36\x1C\x21\x6E\xCE\x8C\x66\xF1\x99\x30\xD8\xD7\xB3\xC3\x1D\xF8\x81\x2E\xA8\xBD\x82\x0B\x66\xFE\x82\xCB\xE1\xE0\x1A\x82\xC3\x40\x81\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xBD\x88\x87\xC9\x8F\xF6\xA4\x0A\x0B\xAA\xEB\xC5\xFE\x91\x23\x9D\xAB\x4A\x8A\x32\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x1D\x7C\xFA\x49\x8F\x34\xE9\xB7\x26\x92\x16\x9A\x05\x74\xE7\x4B\xD0\x6D\x39\x6C\xC3\x26\xF6\xCE\xB8\x31\xBC\xC4\xDF\xBC\x2A\xF8\x37\x91\x18\xDC\x04\xC8\x64\x99\x2B\x18\x6D\x80\x03\x59\xC9\xAE\xF8\x58\xD0\x3E\xED\xC3\x23\x9F\x69\x3C\x86\x38\x1C\x9E\xEF\xDA\x27\x78\xD1\x84\x37\x71\x8A\x3C\x4B\x39\xCF\x7E\x45\x06\xD6\x2D\xD8\x8A\x4D\x78\x12\xD6\xAD\xC2\xD3\xCB\xD2\xD0\x41\xF3\x26\x36\x4A\x9B\x95\x6C\x0C\xEE\xE5\xD1\x43\x27\x66\xC1\x88\xF7\x7A\xB3\x20\x6C\xEA\xB0\x69\x2B\xC7\x20\xE8\x0C\x03\xC4\x41\x05\x99\xE2\x3F\xE4\x6B\xF8\xA0\x86\x81\xC7\x84\xC6\x1F\xD5\x4B\x81\x12\xB2\x16\x21\x2C\x13\xA1\x80\xB2\x5E\x0C\x4A\x13\x9E\x20\xD8\x62\x40\xAB\x90\xEA\x64\x4A\x2F\xAC\x0D\x01\x12\x79\x45\xA8\x2F\x87\x19\x68\xC8\xE2\x85\xC7\x30\xB2\x75\xF9\x38\x3F\xB2\xC0\x93\xB4\x6B\xE2\x03\x44\xCE\x67\xA0\xDF\x89\xD6\xAD\x8C\x76\xA3\x13\xC3\x94\x61\x2B\x6B\xD9\x6C\xC1\x07\x0A\x22\x07\x85\x6C\x85\x24\x46\xA9\xBE\x3F\x8B\x78\x84\x82\x7E\x24\x0C\x9D\xFD\x81\x37\xE3\x25\xA8\xED\x36\x4E\x95\x2C\xC9\x9C\x90\xDA\xEC\xA9\x42\x3C\xAD\xB6\x02", - ["Buypass Class 2 CA 1"] = "\x30\x82\x03\x53\x30\x82\x02\x3B\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x1D\x30\x1B\x06\x03\x55\x04\x03\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x20\x31\x30\x1E\x17\x0D\x30\x36\x31\x30\x31\x33\x31\x30\x32\x35\x30\x39\x5A\x17\x0D\x31\x36\x31\x30\x31\x33\x31\x30\x32\x35\x30\x39\x5A\x30\x4B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x1D\x30\x1B\x06\x03\x55\x04\x03\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x20\x31\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\x8B\x3C\x07\x45\xD8\xF6\xDF\xE6\xC7\xCA\xBA\x8D\x43\xC5\x47\x8D\xB0\x5A\xC1\x38\xDB\x92\x84\x1C\xAF\x13\xD4\x0F\x6F\x36\x46\x20\xC4\x2E\xCC\x71\x70\x34\xA2\x34\xD3\x37\x2E\xD8\xDD\x3A\x77\x2F\xC0\xEB\x29\xE8\x5C\xD2\xB5\xA9\x91\x34\x87\x22\x59\xFE\xCC\xDB\xE7\x99\xAF\x96\xC1\xA8\xC7\x40\xDD\xA5\x15\x8C\x6E\xC8\x7C\x97\x03\xCB\xE6\x20\xF2\xD7\x97\x5F\x31\xA1\x2F\x37\xD2\xBE\xEE\xBE\xA9\xAD\xA8\x4C\x9E\x21\x66\x43\x3B\xA8\xBC\xF3\x09\xA3\x38\xD5\x59\x24\xC1\xC2\x47\x76\xB1\x88\x5C\x82\x3B\xBB\x2B\xA6\x04\xD7\x8C\x07\x8F\xCD\xD5\x41\x1D\xF0\xAE\xB8\x29\x2C\x94\x52\x60\x34\x94\x3B\xDA\xE0\x38\xD1\x9D\x33\x3E\x15\xF4\x93\x32\xC5\x00\xDA\xB5\x29\x66\x0E\x3A\x78\x0F\x21\x52\x5F\x02\xE5\x92\x7B\x25\xD3\x92\x1E\x2F\x15\x9D\x81\xE4\x9D\x8E\xE8\xEF\x89\xCE\x14\x4C\x54\x1D\x1C\x81\x12\x4D\x70\xA8\xBE\x10\x05\x17\x7E\x1F\xD1\xB8\x57\x55\xED\xCD\xBB\x52\xC2\xB0\x1E\x78\xC2\x4D\x36\x68\xCB\x56\x26\xC1\x52\xC1\xBD\x76\xF7\x58\xD5\x72\x7E\x1F\x44\x76\xBB\x00\x89\x1D\x16\x9D\x51\x35\xEF\x4D\xC2\x56\xEF\x6B\xE0\x8C\x3B\x0D\xE9\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x3F\x8D\x9A\x59\x8B\xFC\x7B\x7B\x9C\xA3\xAF\x38\xB0\x39\xED\x90\x71\x80\xD6\xC8\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x15\x1A\x7E\x13\x8A\xB9\xE8\x07\xA3\x4B\x27\x32\xB2\x40\x91\xF2\x21\xD1\x64\x85\xBE\x63\x6A\xD2\xCF\x81\xC2\x15\xD5\x7A\x7E\x0C\x29\xAC\x37\x1E\x1C\x7C\x76\x52\x95\xDA\xB5\x7F\x23\xA1\x29\x77\x65\xC9\x32\x9D\xA8\x2E\x56\xAB\x60\x76\xCE\x16\xB4\x8D\x7F\x78\xC0\xD5\x99\x51\x83\x7F\x5E\xD9\xBE\x0C\xA8\x50\xED\x22\xC7\xAD\x05\x4C\x76\xFB\xED\xEE\x1E\x47\x64\xF6\xF7\x27\x7D\x5C\x28\x0F\x45\xC5\x5C\x62\x5E\xA6\x9A\x91\x91\xB7\x53\x17\x2E\xDC\xAD\x60\x9D\x96\x64\x39\xBD\x67\x68\xB2\xAE\x05\xCB\x4D\xE7\x5F\x1F\x57\x86\xD5\x20\x9C\x28\xFB\x6F\x13\x38\xF5\xF6\x11\x92\xF6\x7D\x99\x5E\x1F\x0C\xE8\xAB\x44\x24\x29\x72\x40\x3D\x36\x52\xAF\x8C\x58\x90\x73\xC1\xEC\x61\x2C\x79\xA1\xEC\x87\xB5\x3F\xDA\x4D\xD9\x21\x00\x30\xDE\x90\xDA\x0E\xD3\x1A\x48\xA9\x3E\x85\x0B\x14\x8B\x8C\xBC\x41\x9E\x6A\xF7\x0E\x70\xC0\x35\xF7\x39\xA2\x5D\x66\xD0\x7B\x59\x9F\xA8\x47\x12\x9A\x27\x23\xA4\x2D\x8E\x27\x83\x92\x20\xA1\xD7\x15\x7F\xF1\x2E\x18\xEE\xF4\x48\x7F\x2F\x7F\xF1\xA1\x18\xB5\xA1\x0B\x94\xA0\x62\x20\x32\x9C\x1D\xF6\xD4\xEF\xBF\x4C\x88\x68", - ["Buypass Class 3 CA 1"] = "\x30\x82\x03\x53\x30\x82\x02\x3B\xA0\x03\x02\x01\x02\x02\x01\x02\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x1D\x30\x1B\x06\x03\x55\x04\x03\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x20\x31\x30\x1E\x17\x0D\x30\x35\x30\x35\x30\x39\x31\x34\x31\x33\x30\x33\x5A\x17\x0D\x31\x35\x30\x35\x30\x39\x31\x34\x31\x33\x30\x33\x5A\x30\x4B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x1D\x30\x1B\x06\x03\x55\x04\x03\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x20\x31\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\xA4\x8E\xD7\x74\xD9\x29\x64\xDE\x5F\x1F\x87\x80\x91\xEA\x4E\x39\xE6\x19\xC6\x44\x0B\x80\xD5\x0B\xAF\x53\x07\x8B\x12\xBD\xE6\x67\xF0\x02\xB1\x89\xF6\x60\x8A\xC4\x5B\xB0\x42\xD1\xC0\x21\xA8\xCB\xE1\x9B\xEF\x64\x51\xB6\xA7\xCF\x15\xF5\x74\x80\x68\x04\x90\xA0\x58\xA2\xE6\x74\xA6\x53\x53\x55\x48\x63\x3F\x92\x56\xDD\x24\x4E\x8E\xF8\xBA\x2B\xFF\xF3\x34\x8A\x9E\x28\xD7\x34\x9F\xAC\x2F\xD6\x0F\xF1\xA4\x2F\xBD\x52\xB2\x49\x85\x6D\x39\x35\xF0\x44\x30\x93\x46\x24\xF3\xB6\xE7\x53\xFB\xBC\x61\xAF\xA9\xA3\x14\xFB\xC2\x17\x17\x84\x6C\xE0\x7C\x88\xF8\xC9\x1C\x57\x2C\xF0\x3D\x7E\x94\xBC\x25\x93\x84\xE8\x9A\x00\x9A\x45\x05\x42\x57\x80\xF4\x4E\xCE\xD9\xAE\x39\xF6\xC8\x53\x10\x0C\x65\x3A\x47\x7B\x60\xC2\xD6\xFA\x91\xC9\xC6\x71\x6C\xBD\x91\x87\x3C\x91\x86\x49\xAB\xF3\x0F\xA0\x6C\x26\x76\x5E\x1C\xAC\x9B\x71\xE5\x8D\xBC\x9B\x21\x1E\x9C\xD6\x38\x7E\x24\x80\x15\x31\x82\x96\xB1\x49\xD3\x62\x37\x5B\x88\x0C\x0A\x62\x34\xFE\xA7\x48\x7E\x99\xB1\x30\x8B\x90\x37\x95\x1C\xA8\x1F\xA5\x2C\x8D\xF4\x55\xC8\xDB\xDD\x59\x0A\xC2\xAD\x78\xA0\xF4\x8B\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x38\x14\xE6\xC8\xF0\xA9\xA4\x03\xF4\x4E\x3E\x22\xA3\x5B\xF2\xD6\xE0\xAD\x40\x74\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x01\x67\xA3\x8C\xC9\x25\x3D\x13\x63\x5D\x16\x6F\xEC\xA1\x3E\x09\x5C\x91\x15\x2A\x2A\xD9\x80\x21\x4F\x05\xDC\xBB\xA5\x89\xAB\x13\x33\x2A\x9E\x38\xB7\x8C\x6F\x02\x72\x63\xC7\x73\x77\x1E\x09\x06\xBA\x3B\x28\x7B\xA4\x47\xC9\x61\x6B\x08\x08\x20\xFC\x8A\x05\x8A\x1F\xBC\xBA\xC6\xC2\xFE\xCF\x6E\xEC\x13\x33\x71\x67\x2E\x69\xFA\xA9\x2C\x3F\x66\xC0\x12\x59\x4D\x0B\x54\x02\x92\x84\xBB\xDB\x12\xEF\x83\x70\x70\x78\xC8\x53\xFA\xDF\xC6\xC6\xFF\xDC\x88\x2F\x07\xC0\x49\x9D\x32\x57\x60\xD3\xF2\xF6\x99\x29\x5F\xE7\xAA\x01\xCC\xAC\x33\xA8\x1C\x0A\xBB\x91\xC4\x03\xA0\x6F\xB6\x34\xF9\x86\xD3\xB3\x76\x54\x98\xF4\x4A\x81\xB3\x53\x9D\x4D\x40\xEC\xE5\x77\x13\x45\xAF\x5B\xAA\x1F\xD8\x2F\x4C\x82\x7B\xFE\x2A\xC4\x58\xBB\x4F\xFC\x9E\xFD\x03\x65\x1A\x2A\x0E\xC3\xA5\x20\x16\x94\x6B\x79\xA6\xA2\x12\xB4\xBB\x1A\xA4\x23\x7A\x5F\xF0\xAE\x84\x24\xE4\xF3\x2B\xFB\x8A\x24\xA3\x27\x98\x65\xDA\x30\x75\x76\xFC\x19\x91\xE8\xDB\xEB\x9B\x3F\x32\xBF\x40\x97\x07\x26\xBA\xCC\xF3\x94\x85\x4A\x7A\x27\x93\xCF\x90\x42\xD4\xB8\x5B\x16\xA6\xE7\xCB\x40\x03\xDD\x79", - ["EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1"] = "\x30\x82\x05\xE7\x30\x82\x03\xCF\xA0\x03\x02\x01\x02\x02\x08\x4C\xAF\x73\x42\x1C\x8E\x74\x02\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x80\x31\x38\x30\x36\x06\x03\x55\x04\x03\x0C\x2F\x45\x42\x47\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x37\x30\x35\x06\x03\x55\x04\x0A\x0C\x2E\x45\x42\x47\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x54\x65\x6B\x6E\x6F\x6C\x6F\x6A\x69\x6C\x65\x72\x69\x20\x76\x65\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x30\x1E\x17\x0D\x30\x36\x30\x38\x31\x37\x30\x30\x32\x31\x30\x39\x5A\x17\x0D\x31\x36\x30\x38\x31\x34\x30\x30\x33\x31\x30\x39\x5A\x30\x81\x80\x31\x38\x30\x36\x06\x03\x55\x04\x03\x0C\x2F\x45\x42\x47\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x37\x30\x35\x06\x03\x55\x04\x0A\x0C\x2E\x45\x42\x47\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x54\x65\x6B\x6E\x6F\x6C\x6F\x6A\x69\x6C\x65\x72\x69\x20\x76\x65\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xEE\xA0\x84\x61\xD0\x3A\x6A\x66\x10\x32\xD8\x31\x38\x7F\xA7\xA7\xE5\xFD\xA1\xE1\xFB\x97\x77\xB8\x71\x96\xE8\x13\x96\x46\x83\x4F\xB6\xF2\x5F\x72\x56\x6E\x13\x60\xA5\x01\x91\xE2\x5B\xC5\xCD\x57\x1F\x77\x63\x51\xFF\x2F\x3D\xDB\xB9\x3F\xAA\xA9\x35\xE7\x79\xD0\xF5\xD0\x24\xB6\x21\xEA\xEB\x23\x94\xFE\x29\xBF\xFB\x89\x91\x0C\x64\x9A\x05\x4A\x2B\xCC\x0C\xEE\xF1\x3D\x9B\x82\x69\xA4\x4C\xF8\x9A\x6F\xE7\x22\xDA\x10\xBA\x5F\x92\xFC\x18\x27\x0A\xA8\xAA\x44\xFA\x2E\x2C\xB4\xFB\x46\x9A\x08\x03\x83\x72\xAB\x88\xE4\x6A\x72\xC9\xE5\x65\x1F\x6E\x2A\x0F\x9D\xB3\xE8\x3B\xE4\x0C\x6E\x7A\xDA\x57\xFD\xD7\xEB\x79\x8B\x5E\x20\x06\xD3\x76\x0B\x6C\x02\x95\xA3\x96\xE4\xCB\x76\x51\xD1\x28\x9D\xA1\x1A\xFC\x44\xA2\x4D\xCC\x7A\x76\xA8\x0D\x3D\xBF\x17\x4F\x22\x88\x50\xFD\xAE\xB6\xEC\x90\x50\x4A\x5B\x9F\x95\x41\xAA\xCA\x0F\xB2\x4A\xFE\x80\x99\x4E\xA3\x46\x15\xAB\xF8\x73\x42\x6A\xC2\x66\x76\xB1\x0A\x26\x15\xDD\x93\x92\xEC\xDB\xA9\x5F\x54\x22\x52\x91\x70\x5D\x13\xEA\x48\xEC\x6E\x03\x6C\xD9\xDD\x6C\xFC\xEB\x0D\x03\xFF\xA6\x83\x12\x9B\xF1\xA9\x93\x0F\xC5\x26\x4C\x31\xB2\x63\x99\x61\x72\xE7\x2A\x64\x99\xD2\xB8\xE9\x75\xE2\x7C\xA9\xA9\x9A\x1A\xAA\xC3\x56\xDB\x10\x9A\x3C\x83\x52\xB6\x7B\x96\xB7\xAC\x87\x77\xA8\xB9\xF2\x67\x0B\x94\x43\xB3\xAF\x3E\x73\xFA\x42\x36\xB1\x25\xC5\x0A\x31\x26\x37\x56\x67\xBA\xA3\x0B\x7D\xD6\xF7\x89\xCD\x67\xA1\xB7\x3A\x1E\x66\x4F\xF6\xA0\x55\x14\x25\x4C\x2C\x33\x0D\xA6\x41\x8C\xBD\x04\x31\x6A\x10\x72\x0A\x9D\x0E\x2E\x76\xBD\x5E\xF3\x51\x89\x8B\xA8\x3F\x55\x73\xBF\xDB\x3A\xC6\x24\x05\x96\x92\x48\xAA\x4B\x8D\x2A\x03\xE5\x57\x91\x10\xF4\x6A\x28\x15\x6E\x47\x77\x84\x5C\x51\x74\x9F\x19\xE9\xE6\x1E\x63\x16\x39\xE3\x11\x15\xE3\x58\x1A\x44\xBD\xCB\xC4\x6C\x66\xD7\x84\x06\xDF\x30\xF4\x37\xA2\x43\x22\x79\xD2\x10\x6C\xDF\xBB\xE6\x13\x11\xFC\x9D\x84\x0A\x13\x7B\xF0\x3B\xD0\xFC\xA3\x0A\xD7\x89\xEA\x96\x7E\x8D\x48\x85\x1E\x64\x5F\xDB\x54\xA2\xAC\xD5\x7A\x02\x79\x6B\xD2\x8A\xF0\x67\xDA\x65\x72\x0D\x14\x70\xE4\xE9\x8E\x78\x8F\x32\x74\x7C\x57\xF2\xD6\xD6\xF4\x36\x89\x1B\xF8\x29\x6C\x8B\xB9\xF6\x97\xD1\xA4\x2E\xAA\xBE\x0B\x19\xC2\x45\xE9\x70\x5D\x02\x03\x00\x9D\xD9\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE7\xCE\xC6\x4F\xFC\x16\x67\x96\xFA\x4A\xA3\x07\xC1\x04\xA7\xCB\x6A\xDE\xDA\x47\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xE7\xCE\xC6\x4F\xFC\x16\x67\x96\xFA\x4A\xA3\x07\xC1\x04\xA7\xCB\x6A\xDE\xDA\x47\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x9B\x98\x9A\x5D\xBE\xF3\x28\x23\x76\xC6\x6C\xF7\x7F\xE6\x40\x9E\xC0\x36\xDC\x95\x0D\x1D\xAD\x15\xC5\x36\xD8\xD5\x39\xEF\xF2\x1E\x22\x5E\xB3\x82\xB4\x5D\xBB\x4C\x1A\xCA\x92\x0D\xDF\x47\x24\x1E\xB3\x24\xDA\x91\x88\xE9\x83\x70\xDD\x93\xD7\xE9\xBA\xB3\xDF\x16\x5A\x3E\xDE\xE0\xC8\xFB\xD3\xFD\x6C\x29\xF8\x15\x46\xA0\x68\x26\xCC\x93\x52\xAE\x82\x01\x93\x90\xCA\x77\xCA\x4D\x49\xEF\xE2\x5A\xD9\x2A\xBD\x30\xCE\x4C\xB2\x81\xB6\x30\xCE\x59\x4F\xDA\x59\x1D\x6A\x7A\xA4\x45\xB0\x82\x26\x81\x86\x76\xF5\xF5\x10\x00\xB8\xEE\xB3\x09\xE8\x4F\x87\x02\x07\xAE\x24\x5C\xF0\x5F\xAC\x0A\x30\xCC\x8A\x40\xA0\x73\x04\xC1\xFB\x89\x24\xF6\x9A\x1C\x5C\xB7\x3C\x0A\x67\x36\x05\x08\x31\xB3\xAF\xD8\x01\x68\x2A\xE0\x78\x8F\x74\xDE\xB8\x51\xA4\x8C\x6C\x20\x3D\xA2\xFB\xB3\xD4\x09\xFD\x7B\xC2\x80\xAA\x93\x6C\x29\x98\x21\xA8\xBB\x16\xF3\xA9\x12\x5F\x74\xB5\x87\x98\xF2\x95\x26\xDF\x34\xEF\x8A\x53\x91\x88\x5D\x1A\x94\xA3\x3F\x7C\x22\xF8\xD7\x88\xBA\xA6\x8C\x96\xA8\x3D\x52\x34\x62\x9F\x00\x1E\x54\x55\x42\x67\xC6\x4D\x46\x8F\xBB\x14\x45\x3D\x0A\x96\x16\x8E\x10\xA1\x97\x99\xD5\xD3\x30\x85\xCC\xDE\xB4\x72\xB7\xBC\x8A\x3C\x18\x29\x68\xFD\xDC\x71\x07\xEE\x24\x39\x6A\xFA\xED\xA5\xAC\x38\x2F\xF9\x1E\x10\x0E\x06\x71\x1A\x10\x4C\xFE\x75\x7E\xFF\x1E\x57\x39\x42\xCA\xD7\xE1\x15\xA1\x56\x55\x59\x1B\xD1\xA3\xAF\x11\xD8\x4E\xC3\xA5\x2B\xEF\x90\xBF\xC0\xEC\x82\x13\x5B\x8D\xD6\x72\x2C\x93\x4E\x8F\x6A\x29\xDF\x85\x3C\xD3\x0D\xE0\xA2\x18\x12\xCC\x55\x2F\x47\xB7\xA7\x9B\x02\xFE\x41\xF6\x88\x4C\x6D\xDA\xA9\x01\x47\x83\x64\x27\x62\x10\x82\xD6\x12\x7B\x5E\x03\x1F\x34\xA9\xC9\x91\xFE\xAF\x5D\x6D\x86\x27\xB7\x23\xAA\x75\x18\xCA\x20\xE7\xB0\x0F\xD7\x89\x0E\xA6\x67\x22\x63\xF4\x83\x41\x2B\x06\x4B\xBB\x58\xD5\xD1\xD7\xB7\xB9\x10\x63\xD8\x89\x4A\xB4\xAA\xDD\x16\x63\xF5\x6E\xBE\x60\xA1\xF8\xED\xE8\xD6\x90\x4F\x1A\xC6\xC5\xA0\x29\xD3\xA7\x21\xA8\xF5\x5A\x3C\xF7\xC7\x49\xA2\x21\x9A\x4A\x95\x52\x20\x96\x72\x9A\x66\xCB\xF7\xD2\x86\x43\x7C\x22\xBE\x96\xF9\xBD\x01\xA8\x47\xDD\xE5\x3B\x40\xF9\x75\x2B\x9B\x2B\x46\x64\x86\x8D\x1E\xF4\x8F\xFB\x07\x77\xD0\xEA\x49\xA2\x1C\x8D\x52\x14\xA6\x0A\x93", - ["certSIGN ROOT CA"] = "\x30\x82\x03\x38\x30\x82\x02\x20\xA0\x03\x02\x01\x02\x02\x06\x20\x06\x05\x16\x70\x02\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x52\x4F\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x63\x65\x72\x74\x53\x49\x47\x4E\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x63\x65\x72\x74\x53\x49\x47\x4E\x20\x52\x4F\x4F\x54\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x30\x37\x30\x34\x31\x37\x32\x30\x30\x34\x5A\x17\x0D\x33\x31\x30\x37\x30\x34\x31\x37\x32\x30\x30\x34\x5A\x30\x3B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x52\x4F\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x63\x65\x72\x74\x53\x49\x47\x4E\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x63\x65\x72\x74\x53\x49\x47\x4E\x20\x52\x4F\x4F\x54\x20\x43\x41\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\xB7\x33\xB9\x7E\xC8\x25\x4A\x8E\xB5\xDB\xB4\x28\x1B\xAA\x57\x90\xE8\xD1\x22\xD3\x64\xBA\xD3\x93\xE8\xD4\xAC\x86\x61\x40\x6A\x60\x57\x68\x54\x84\x4D\xBC\x6A\x54\x02\x05\xFF\xDF\x9B\x9A\x2A\xAE\x5D\x07\x8F\x4A\xC3\x28\x7F\xEF\xFB\x2B\xFA\x79\xF1\xC7\xAD\xF0\x10\x53\x24\x90\x8B\x66\xC9\xA8\x88\xAB\xAF\x5A\xA3\x00\xE9\xBE\xBA\x46\xEE\x5B\x73\x7B\x2C\x17\x82\x81\x5E\x62\x2C\xA1\x02\x65\xB3\xBD\xC5\x2B\x00\x7E\xC4\xFC\x03\x33\x57\x0D\xED\xE2\xFA\xCE\x5D\x45\xD6\x38\xCD\x35\xB6\xB2\xC1\xD0\x9C\x81\x4A\xAA\xE4\xB2\x01\x5C\x1D\x8F\x5F\x99\xC4\xB1\xAD\xDB\x88\x21\xEB\x90\x08\x82\x80\xF3\x30\xA3\x43\xE6\x90\x82\xAE\x55\x28\x49\xED\x5B\xD7\xA9\x10\x38\x0E\xFE\x8F\x4C\x5B\x9B\x46\xEA\x41\xF5\xB0\x08\x74\xC3\xD0\x88\x33\xB6\x7C\xD7\x74\xDF\xDC\x84\xD1\x43\x0E\x75\x39\xA1\x25\x40\x28\xEA\x78\xCB\x0E\x2C\x2E\x39\x9D\x8C\x8B\x6E\x16\x1C\x2F\x26\x82\x10\xE2\xE3\x65\x94\x0A\x04\xC0\x5E\xF7\x5D\x5B\xF8\x10\xE2\xD0\xBA\x7A\x4B\xFB\xDE\x37\x00\x00\x1A\x5B\x28\xE3\xD2\x9C\x73\x3E\x32\x87\x98\xA1\xC9\x51\x2F\xD7\xDE\xAC\x33\xB3\x4F\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\xC6\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE0\x8C\x9B\xDB\x25\x49\xB3\xF1\x7C\x86\xD6\xB2\x42\x87\x0B\xD0\x6B\xA0\xD9\xE4\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3E\xD2\x1C\x89\x2E\x35\xFC\xF8\x75\xDD\xE6\x7F\x65\x88\xF4\x72\x4C\xC9\x2C\xD7\x32\x4E\xF3\xDD\x19\x79\x47\xBD\x8E\x3B\x5B\x93\x0F\x50\x49\x24\x13\x6B\x14\x06\x72\xEF\x09\xD3\xA1\xA1\xE3\x40\x84\xC9\xE7\x18\x32\x74\x3C\x48\x6E\x0F\x9F\x4B\xD4\xF7\x1E\xD3\x93\x86\x64\x54\x97\x63\x72\x50\xD5\x55\xCF\xFA\x20\x93\x02\xA2\x9B\xC3\x23\x93\x4E\x16\x55\x76\xA0\x70\x79\x6D\xCD\x21\x1F\xCF\x2F\x2D\xBC\x19\xE3\x88\x31\xF8\x59\x1A\x81\x09\xC8\x97\xA6\x74\xC7\x60\xC4\x5B\xCC\x57\x8E\xB2\x75\xFD\x1B\x02\x09\xDB\x59\x6F\x72\x93\x69\xF7\x31\x41\xD6\x88\x38\xBF\x87\xB2\xBD\x16\x79\xF9\xAA\xE4\xBE\x88\x25\xDD\x61\x27\x23\x1C\xB5\x31\x07\x04\x36\xB4\x1A\x90\xBD\xA0\x74\x71\x50\x89\x6D\xBC\x14\xE3\x0F\x86\xAE\xF1\xAB\x3E\xC7\xA0\x09\xCC\xA3\x48\xD1\xE0\xDB\x64\xE7\x92\xB5\xCF\xAF\x72\x43\x70\x8B\xF9\xC3\x84\x3C\x13\xAA\x7E\x92\x9B\x57\x53\x93\xFA\x70\xC2\x91\x0E\x31\xF9\x9B\x67\x5D\xE9\x96\x38\x5E\x5F\xB3\x73\x4E\x88\x15\x67\xDE\x9E\x76\x10\x62\x20\xBE\x55\x69\x95\x43\x00\x39\x4D\xF6\xEE\xB0\x5A\x4E\x49\x44\x54\x58\x5F\x42\x83", - ["CNNIC ROOT"] = "\x30\x82\x03\x55\x30\x82\x02\x3D\xA0\x03\x02\x01\x02\x02\x04\x49\x33\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x32\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0A\x13\x05\x43\x4E\x4E\x49\x43\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x43\x4E\x4E\x49\x43\x20\x52\x4F\x4F\x54\x30\x1E\x17\x0D\x30\x37\x30\x34\x31\x36\x30\x37\x30\x39\x31\x34\x5A\x17\x0D\x32\x37\x30\x34\x31\x36\x30\x37\x30\x39\x31\x34\x5A\x30\x32\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0A\x13\x05\x43\x4E\x4E\x49\x43\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x43\x4E\x4E\x49\x43\x20\x52\x4F\x4F\x54\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\xD3\x35\xF7\x3F\x73\x77\xAD\xE8\x5B\x73\x17\xC2\xD1\x6F\xED\x55\xBC\x6E\xEA\xE8\xA4\x79\xB2\x6C\xC3\xA3\xEF\xE1\x9F\xB1\x3B\x48\x85\xF5\x9A\x5C\x21\x22\x10\x2C\xC5\x82\xCE\xDA\xE3\x9A\x6E\x37\xE1\x87\x2C\xDC\xB9\x0C\x5A\xBA\x88\x55\xDF\xFD\xAA\xDB\x1F\x31\xEA\x01\xF1\xDF\x39\x01\xC1\x13\xFD\x48\x52\x21\xC4\x55\xDF\xDA\xD8\xB3\x54\x76\xBA\x74\xB1\xB7\x7D\xD7\xC0\xE8\xF6\x59\xC5\x4D\xC8\xBD\xAD\x1F\x14\xDA\xDF\x58\x44\x25\x32\x19\x2A\xC7\x7E\x7E\x8E\xAE\x38\xB0\x30\x7B\x47\x72\x09\x31\xF0\x30\xDB\xC3\x1B\x76\x29\xBB\x69\x76\x4E\x57\xF9\x1B\x64\xA2\x93\x56\xB7\x6F\x99\x6E\xDB\x0A\x04\x9C\x11\xE3\x80\x1F\xCB\x63\x94\x10\x0A\xA9\xE1\x64\x82\x31\xF9\x8C\x27\xED\xA6\x99\x00\xF6\x70\x93\x18\xF8\xA1\x34\x86\xA3\xDD\x7A\xC2\x18\x79\xF6\x7A\x65\x35\xCF\x90\xEB\xBD\x33\x93\x9F\x53\xAB\x73\x3B\xE6\x9B\x34\x20\x2F\x1D\xEF\xA9\x1D\x63\x1A\xA0\x80\xDB\x03\x2F\xF9\x26\x1A\x86\xD2\x8D\xBB\xA9\xBE\x52\x3A\x87\x67\x48\x0D\xBF\xB4\xA0\xD8\x26\xBE\x23\x5F\x73\x37\x7F\x26\xE6\x92\x04\xA3\x7F\xCF\x20\xA7\xB7\xF3\x3A\xCA\xCB\x99\xCB\x02\x03\x01\x00\x01\xA3\x73\x30\x71\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x65\xF2\x31\xAD\x2A\xF7\xF7\xDD\x52\x96\x0A\xC7\x02\xC1\x0E\xEF\xA6\xD5\x3B\x11\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\xFE\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x65\xF2\x31\xAD\x2A\xF7\xF7\xDD\x52\x96\x0A\xC7\x02\xC1\x0E\xEF\xA6\xD5\x3B\x11\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x4B\x35\xEE\xCC\xE4\xAE\xBF\xC3\x6E\xAD\x9F\x95\x3B\x4B\x3F\x5B\x1E\xDF\x57\x29\xA2\x59\xCA\x38\xE2\xB9\x1A\xFF\x9E\xE6\x6E\x32\xDD\x1E\xAE\xEA\x35\xB7\xF5\x93\x91\x4E\xDA\x42\xE1\xC3\x17\x60\x50\xF2\xD1\x5C\x26\xB9\x82\xB7\xEA\x6D\xE4\x9C\x84\xE7\x03\x79\x17\xAF\x98\x3D\x94\xDB\xC7\xBA\x00\xE7\xB8\xBF\x01\x57\xC1\x77\x45\x32\x0C\x3B\xF1\xB4\x1C\x08\xB0\xFD\x51\xA0\xA1\xDD\x9A\x1D\x13\x36\x9A\x6D\xB7\xC7\x3C\xB9\xE1\xC5\xD9\x17\xFA\x83\xD5\x3D\x15\xA0\x3C\xBB\x1E\x0B\xE2\xC8\x90\x3F\xA8\x86\x0C\xFC\xF9\x8B\x5E\x85\xCB\x4F\x5B\x4B\x62\x11\x47\xC5\x45\x7C\x05\x2F\x41\xB1\x9E\x10\x69\x1B\x99\x96\xE0\x55\x79\xFB\x4E\x86\x99\xB8\x94\xDA\x86\x38\x6A\x93\xA3\xE7\xCB\x6E\xE5\xDF\xEA\x21\x55\x89\x9C\x7D\x7D\x7F\x98\xF5\x00\x89\xEE\xE3\x84\xC0\x5C\x96\xB5\xC5\x46\xEA\x46\xE0\x85\x55\xB6\x1B\xC9\x12\xD6\xC1\xCD\xCD\x80\xF3\x02\x01\x3C\xC8\x69\xCB\x45\x48\x63\xD8\x94\xD0\xEC\x85\x0E\x3B\x4E\x11\x65\xF4\x82\x8C\xA6\x3D\xAE\x2E\x22\x94\x09\xC8\x5C\xEA\x3C\x81\x5D\x16\x2A\x03\x97\x16\x55\x09\xDB\x8A\x41\x82\x9E\x66\x9B\x11", - ["ApplicationCA - Japanese Government"] = "\x30\x82\x03\xA0\x30\x82\x02\x88\xA0\x03\x02\x01\x02\x02\x01\x31\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x43\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x4A\x61\x70\x61\x6E\x65\x73\x65\x20\x47\x6F\x76\x65\x72\x6E\x6D\x65\x6E\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0B\x13\x0D\x41\x70\x70\x6C\x69\x63\x61\x74\x69\x6F\x6E\x43\x41\x30\x1E\x17\x0D\x30\x37\x31\x32\x31\x32\x31\x35\x30\x30\x30\x30\x5A\x17\x0D\x31\x37\x31\x32\x31\x32\x31\x35\x30\x30\x30\x30\x5A\x30\x43\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x4A\x61\x70\x61\x6E\x65\x73\x65\x20\x47\x6F\x76\x65\x72\x6E\x6D\x65\x6E\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0B\x13\x0D\x41\x70\x70\x6C\x69\x63\x61\x74\x69\x6F\x6E\x43\x41\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\xA7\x6D\xE0\x74\x4E\x87\x8F\xA5\x06\xDE\x68\xA2\xDB\x86\x99\x4B\x64\x0D\x71\xF0\x0A\x05\x9B\x8E\xAA\xE1\xCC\x2E\xD2\x6A\x3B\xC1\x7A\xB4\x97\x61\x8D\x8A\xBE\xC6\x9A\x9C\x06\xB4\x86\x51\xE4\x37\x0E\x74\x78\x7E\x5F\x8A\x7F\x94\xA4\xD7\x47\x08\xFD\x50\x5A\x56\xE4\x68\xAC\x28\x73\xA0\x7B\xE9\x7F\x18\x92\x40\x4F\x2D\x9D\xF5\xAE\x44\x48\x73\x36\x06\x9E\x64\x2C\x3B\x34\x23\xDB\x5C\x26\xE4\x71\x79\x8F\xD4\x6E\x79\x22\xB9\x93\xC1\xCA\xCD\xC1\x56\xED\x88\x6A\xD7\xA0\x39\x21\x04\x57\x2C\xA2\xF5\xBC\x47\x41\x4F\x5E\x34\x22\x95\xB5\x1F\x29\x6D\x5E\x4A\xF3\x4D\x72\xBE\x41\x56\x20\x87\xFC\xE9\x50\x47\xD7\x30\x14\xEE\x5C\x8C\x55\xBA\x59\x8D\x87\xFC\x23\xDE\x93\xD0\x04\x8C\xFD\xEF\x6D\xBD\xD0\x7A\xC9\xA5\x3A\x6A\x72\x33\xC6\x4A\x0D\x05\x17\x2A\x2D\x7B\xB1\xA7\xD8\xD6\xF0\xBE\xF4\x3F\xEA\x0E\x28\x6D\x41\x61\x23\x76\x78\xC3\xB8\x65\xA4\xF3\x5A\xAE\xCC\xC2\xAA\xD9\xE7\x58\xDE\xB6\x7E\x9D\x85\x6E\x9F\x2A\x0A\x6F\x9F\x03\x29\x30\x97\x28\x1D\xBC\xB7\xCF\x54\x29\x4E\x51\x31\xF9\x27\xB6\x28\x26\xFE\xA2\x63\xE6\x41\x16\xF0\x33\x98\x47\x02\x03\x01\x00\x01\xA3\x81\x9E\x30\x81\x9B\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x54\x5A\xCB\x26\x3F\x71\xCC\x94\x46\x0D\x96\x53\xEA\x6B\x48\xD0\x93\xFE\x42\x75\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x59\x06\x03\x55\x1D\x11\x04\x52\x30\x50\xA4\x4E\x30\x4C\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x0C\x0F\xE6\x97\xA5\xE6\x9C\xAC\xE5\x9B\xBD\xE6\x94\xBF\xE5\xBA\x9C\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x0C\x1A\xE3\x82\xA2\xE3\x83\x97\xE3\x83\xAA\xE3\x82\xB1\xE3\x83\xBC\xE3\x82\xB7\xE3\x83\xA7\xE3\x83\xB3\x43\x41\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x39\x6A\x44\x76\x77\x38\x3A\xEC\xA3\x67\x46\x0F\xF9\x8B\x06\xA8\xFB\x6A\x90\x31\xCE\x7E\xEC\xDA\xD1\x89\x7C\x7A\xEB\x2E\x0C\xBD\x99\x32\xE7\xB0\x24\xD6\xC3\xFF\xF5\xB2\x88\x09\x87\x2C\xE3\x54\xE1\xA3\xA6\xB2\x08\x0B\xC0\x85\xA8\xC8\xD2\x9C\x71\xF6\x1D\x9F\x60\xFC\x38\x33\x13\xE1\x9E\xDC\x0B\x5F\xDA\x16\x50\x29\x7B\x2F\x70\x91\x0F\x99\xBA\x34\x34\x8D\x95\x74\xC5\x7E\x78\xA9\x66\x5D\xBD\xCA\x21\x77\x42\x10\xAC\x66\x26\x3D\xDE\x91\xAB\xFD\x15\xF0\x6F\xED\x6C\x5F\x10\xF8\xF3\x16\xF6\x03\x8A\x8F\xA7\x12\x11\x0C\xCB\xFD\x3F\x79\xC1\x9C\xFD\x62\xEE\xA3\xCF\x54\x0C\xD1\x2B\x5F\x17\x3E\xE3\x3E\xBF\xC0\x2B\x3E\x09\x9B\xFE\x88\xA6\x7E\xB4\x92\x17\xFC\x23\x94\x81\xBD\x6E\xA7\xC5\x8C\xC2\xEB\x11\x45\xDB\xF8\x41\xC9\x96\x76\xEA\x70\x5F\x79\x12\x6B\xE4\xA3\x07\x5A\x05\xEF\x27\x49\xCF\x21\x9F\x8A\x4C\x09\x70\x66\xA9\x26\xC1\x2B\x11\x4E\x33\xD2\x0E\xFC\xD6\x6C\xD2\x0E\x32\x64\x68\xFF\xAD\x05\x78\x5F\x03\x1D\xA8\xE3\x90\xAC\x24\xE0\x0F\x40\xA7\x4B\xAE\x8B\x28\xB7\x82\xCA\x18\x07\xE6\xB7\x5B\x74\xE9\x20\x19\x7F\xB2\x1B\x89\x54", - ["GeoTrust Primary Certification Authority - G3"] = "\x30\x82\x03\xFE\x30\x82\x02\xE6\xA0\x03\x02\x01\x02\x02\x10\x15\xAC\x6E\x94\x19\xB2\x79\x4B\x41\xF6\x27\xA9\xC3\x18\x0F\x1F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x98\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x39\x30\x37\x06\x03\x55\x04\x0B\x13\x30\x28\x63\x29\x20\x32\x30\x30\x38\x20\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\x30\x1E\x17\x0D\x30\x38\x30\x34\x30\x32\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x32\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x98\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x39\x30\x37\x06\x03\x55\x04\x0B\x13\x30\x28\x63\x29\x20\x32\x30\x30\x38\x20\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\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\xDC\xE2\x5E\x62\x58\x1D\x33\x57\x39\x32\x33\xFA\xEB\xCB\x87\x8C\xA7\xD4\x4A\xDD\x06\x88\xEA\x64\x8E\x31\x98\xA5\x38\x90\x1E\x98\xCF\x2E\x63\x2B\xF0\x46\xBC\x44\xB2\x89\xA1\xC0\x28\x0C\x49\x70\x21\x95\x9F\x64\xC0\xA6\x93\x12\x02\x65\x26\x86\xC6\xA5\x89\xF0\xFA\xD7\x84\xA0\x70\xAF\x4F\x1A\x97\x3F\x06\x44\xD5\xC9\xEB\x72\x10\x7D\xE4\x31\x28\xFB\x1C\x61\xE6\x28\x07\x44\x73\x92\x22\x69\xA7\x03\x88\x6C\x9D\x63\xC8\x52\xDA\x98\x27\xE7\x08\x4C\x70\x3E\xB4\xC9\x12\xC1\xC5\x67\x83\x5D\x33\xF3\x03\x11\xEC\x6A\xD0\x53\xE2\xD1\xBA\x36\x60\x94\x80\xBB\x61\x63\x6C\x5B\x17\x7E\xDF\x40\x94\x1E\xAB\x0D\xC2\x21\x28\x70\x88\xFF\xD6\x26\x6C\x6C\x60\x04\x25\x4E\x55\x7E\x7D\xEF\xBF\x94\x48\xDE\xB7\x1D\xDD\x70\x8D\x05\x5F\x88\xA5\x9B\xF2\xC2\xEE\xEA\xD1\x40\x41\x6D\x62\x38\x1D\x56\x06\xC5\x03\x47\x51\x20\x19\xFC\x7B\x10\x0B\x0E\x62\xAE\x76\x55\xBF\x5F\x77\xBE\x3E\x49\x01\x53\x3D\x98\x25\x03\x76\x24\x5A\x1D\xB4\xDB\x89\xEA\x79\xE5\xB6\xB3\x3B\x3F\xBA\x4C\x28\x41\x7F\x06\xAC\x6A\x8E\xC1\xD0\xF6\x05\x1D\x7D\xE6\x42\x86\xE3\xA5\xD5\x47\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC4\x79\xCA\x8E\xA1\x4E\x03\x1D\x1C\xDC\x6B\xDB\x31\x5B\x94\x3E\x3F\x30\x7F\x2D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x2D\xC5\x13\xCF\x56\x80\x7B\x7A\x78\xBD\x9F\xAE\x2C\x99\xE7\xEF\xDA\xDF\x94\x5E\x09\x69\xA7\xE7\x6E\x68\x8C\xBD\x72\xBE\x47\xA9\x0E\x97\x12\xB8\x4A\xF1\x64\xD3\x39\xDF\x25\x34\xD4\xC1\xCD\x4E\x81\xF0\x0F\x04\xC4\x24\xB3\x34\x96\xC6\xA6\xAA\x30\xDF\x68\x61\x73\xD7\xF9\x8E\x85\x89\xEF\x0E\x5E\x95\x28\x4A\x2A\x27\x8F\x10\x8E\x2E\x7C\x86\xC4\x02\x9E\xDA\x0C\x77\x65\x0E\x44\x0D\x92\xFD\xFD\xB3\x16\x36\xFA\x11\x0D\x1D\x8C\x0E\x07\x89\x6A\x29\x56\xF7\x72\xF4\xDD\x15\x9C\x77\x35\x66\x57\xAB\x13\x53\xD8\x8E\xC1\x40\xC5\xD7\x13\x16\x5A\x72\xC7\xB7\x69\x01\xC4\x7A\xB1\x83\x01\x68\x7D\x8D\x41\xA1\x94\x18\xC1\x25\x5C\xFC\xF0\xFE\x83\x02\x87\x7C\x0D\x0D\xCF\x2E\x08\x5C\x4A\x40\x0D\x3E\xEC\x81\x61\xE6\x24\xDB\xCA\xE0\x0E\x2D\x07\xB2\x3E\x56\xDC\x8D\xF5\x41\x85\x07\x48\x9B\x0C\x0B\xCB\x49\x3F\x7D\xEC\xB7\xFD\xCB\x8D\x67\x89\x1A\xAB\xED\xBB\x1E\xA3\x00\x08\x08\x17\x2A\x82\x5C\x31\x5D\x46\x8A\x2D\x0F\x86\x9B\x74\xD9\x45\xFB\xD4\x40\xB1\x7A\xAA\x68\x2D\x86\xB2\x99\x22\xE1\xC1\x2B\xC7\x9C\xF8\xF3\x5F\xA8\x82\x12\xEB\x19\x11\x2D", - ["thawte Primary Root CA - G2"] = "\x30\x82\x02\x88\x30\x82\x02\x0D\xA0\x03\x02\x01\x02\x02\x10\x35\xFC\x26\x5C\xD9\x84\x4F\xC9\x3D\x26\x3D\x57\x9B\xAE\xD7\x56\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x30\x81\x84\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x31\x38\x30\x36\x06\x03\x55\x04\x0B\x13\x2F\x28\x63\x29\x20\x32\x30\x30\x37\x20\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1B\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x37\x31\x31\x30\x35\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x38\x30\x31\x31\x38\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x84\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x31\x38\x30\x36\x06\x03\x55\x04\x0B\x13\x2F\x28\x63\x29\x20\x32\x30\x30\x37\x20\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1B\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x76\x30\x10\x06\x07\x2A\x86\x48\xCE\x3D\x02\x01\x06\x05\x2B\x81\x04\x00\x22\x03\x62\x00\x04\xA2\xD5\x9C\x82\x7B\x95\x9D\xF1\x52\x78\x87\xFE\x8A\x16\xBF\x05\xE6\xDF\xA3\x02\x4F\x0D\x07\xC6\x00\x51\xBA\x0C\x02\x52\x2D\x22\xA4\x42\x39\xC4\xFE\x8F\xEA\xC9\xC1\xBE\xD4\x4D\xFF\x9F\x7A\x9E\xE2\xB1\x7C\x9A\xAD\xA7\x86\x09\x73\x87\xD1\xE7\x9A\xE3\x7A\xA5\xAA\x6E\xFB\xBA\xB3\x70\xC0\x67\x88\xA2\x35\xD4\xA3\x9A\xB1\xFD\xAD\xC2\xEF\x31\xFA\xA8\xB9\xF3\xFB\x08\xC6\x91\xD1\xFB\x29\x95\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9A\xD8\x00\x30\x00\xE7\x6B\x7F\x85\x18\xEE\x8B\xB6\xCE\x8A\x0C\xF8\x11\xE1\xBB\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x03\x69\x00\x30\x66\x02\x31\x00\xDD\xF8\xE0\x57\x47\x5B\xA7\xE6\x0A\xC3\xBD\xF5\x80\x8A\x97\x35\x0D\x1B\x89\x3C\x54\x86\x77\x28\xCA\xA1\xF4\x79\xDE\xB5\xE6\x38\xB0\xF0\x65\x70\x8C\x7F\x02\x54\xC2\xBF\xFF\xD8\xA1\x3E\xD9\xCF\x02\x31\x00\xC4\x8D\x94\xFC\xDC\x53\xD2\xDC\x9D\x78\x16\x1F\x15\x33\x23\x53\x52\xE3\x5A\x31\x5D\x9D\xCA\xAE\xBD\x13\x29\x44\x0D\x27\x5B\xA8\xE7\x68\x9C\x12\xF7\x58\x3F\x2E\x72\x02\x57\xA3\x8F\xA1\x14\x2E", - ["thawte Primary Root CA - G3"] = "\x30\x82\x04\x2A\x30\x82\x03\x12\xA0\x03\x02\x01\x02\x02\x10\x60\x01\x97\xB7\x46\xA7\xEA\xB4\xB4\x9A\xD6\x4B\x2F\xF7\x90\xFB\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x38\x30\x36\x06\x03\x55\x04\x0B\x13\x2F\x28\x63\x29\x20\x32\x30\x30\x38\x20\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1B\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x47\x33\x30\x1E\x17\x0D\x30\x38\x30\x34\x30\x32\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x32\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x38\x30\x36\x06\x03\x55\x04\x0B\x13\x2F\x28\x63\x29\x20\x32\x30\x30\x38\x20\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1B\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x47\x33\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\xB2\xBF\x27\x2C\xFB\xDB\xD8\x5B\xDD\x78\x7B\x1B\x9E\x77\x66\x81\xCB\x3E\xBC\x7C\xAE\xF3\xA6\x27\x9A\x34\xA3\x68\x31\x71\x38\x33\x62\xE4\xF3\x71\x66\x79\xB1\xA9\x65\xA3\xA5\x8B\xD5\x8F\x60\x2D\x3F\x42\xCC\xAA\x6B\x32\xC0\x23\xCB\x2C\x41\xDD\xE4\xDF\xFC\x61\x9C\xE2\x73\xB2\x22\x95\x11\x43\x18\x5F\xC4\xB6\x1F\x57\x6C\x0A\x05\x58\x22\xC8\x36\x4C\x3A\x7C\xA5\xD1\xCF\x86\xAF\x88\xA7\x44\x02\x13\x74\x71\x73\x0A\x42\x59\x02\xF8\x1B\x14\x6B\x42\xDF\x6F\x5F\xBA\x6B\x82\xA2\x9D\x5B\xE7\x4A\xBD\x1E\x01\x72\xDB\x4B\x74\xE8\x3B\x7F\x7F\x7D\x1F\x04\xB4\x26\x9B\xE0\xB4\x5A\xAC\x47\x3D\x55\xB8\xD7\xB0\x26\x52\x28\x01\x31\x40\x66\xD8\xD9\x24\xBD\xF6\x2A\xD8\xEC\x21\x49\x5C\x9B\xF6\x7A\xE9\x7F\x55\x35\x7E\x96\x6B\x8D\x93\x93\x27\xCB\x92\xBB\xEA\xAC\x40\xC0\x9F\xC2\xF8\x80\xCF\x5D\xF4\x5A\xDC\xCE\x74\x86\xA6\x3E\x6C\x0B\x53\xCA\xBD\x92\xCE\x19\x06\x72\xE6\x0C\x5C\x38\x69\xC7\x04\xD6\xBC\x6C\xCE\x5B\xF6\xF7\x68\x9C\xDC\x25\x15\x48\x88\xA1\xE9\xA9\xF8\x98\x9C\xE0\xF3\xD5\x31\x28\x61\x11\x6C\x67\x96\x8D\x39\x99\xCB\xC2\x45\x24\x39\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xAD\x6C\xAA\x94\x60\x9C\xED\xE4\xFF\xFA\x3E\x0A\x74\x2B\x63\x03\xF7\xB6\x59\xBF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x1A\x40\xD8\x95\x65\xAC\x09\x92\x89\xC6\x39\xF4\x10\xE5\xA9\x0E\x66\x53\x5D\x78\xDE\xFA\x24\x91\xBB\xE7\x44\x51\xDF\xC6\x16\x34\x0A\xEF\x6A\x44\x51\xEA\x2B\x07\x8A\x03\x7A\xC3\xEB\x3F\x0A\x2C\x52\x16\xA0\x2B\x43\xB9\x25\x90\x3F\x70\xA9\x33\x25\x6D\x45\x1A\x28\x3B\x27\xCF\xAA\xC3\x29\x42\x1B\xDF\x3B\x4C\xC0\x33\x34\x5B\x41\x88\xBF\x6B\x2B\x65\xAF\x28\xEF\xB2\xF5\xC3\xAA\x66\xCE\x7B\x56\xEE\xB7\xC8\xCB\x67\xC1\xC9\x9C\x1A\x18\xB8\xC4\xC3\x49\x03\xF1\x60\x0E\x50\xCD\x46\xC5\xF3\x77\x79\xF7\xB6\x15\xE0\x38\xDB\xC7\x2F\x28\xA0\x0C\x3F\x77\x26\x74\xD9\x25\x12\xDA\x31\xDA\x1A\x1E\xDC\x29\x41\x91\x22\x3C\x69\xA7\xBB\x02\xF2\xB6\x5C\x27\x03\x89\xF4\x06\xEA\x9B\xE4\x72\x82\xE3\xA1\x09\xC1\xE9\x00\x19\xD3\x3E\xD4\x70\x6B\xBA\x71\xA6\xAA\x58\xAE\xF4\xBB\xE9\x6C\xB6\xEF\x87\xCC\x9B\xBB\xFF\x39\xE6\x56\x61\xD3\x0A\xA7\xC4\x5C\x4C\x60\x7B\x05\x77\x26\x7A\xBF\xD8\x07\x52\x2C\x62\xF7\x70\x63\xD9\x39\xBC\x6F\x1C\xC2\x79\xDC\x76\x29\xAF\xCE\xC5\x2C\x64\x04\x5E\x88\x36\x6E\x31\xD4\x40\x1A\x62\x34\x36\x3F\x35\x01\xAE\xAC\x63\xA0", - ["GeoTrust Primary Certification Authority - G2"] = "\x30\x82\x02\xAE\x30\x82\x02\x35\xA0\x03\x02\x01\x02\x02\x10\x3C\xB2\xF4\x48\x0A\x00\xE2\xFE\xEB\x24\x3B\x5E\x60\x3E\xC3\x6B\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x30\x81\x98\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x39\x30\x37\x06\x03\x55\x04\x0B\x13\x30\x28\x63\x29\x20\x32\x30\x30\x37\x20\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x37\x31\x31\x30\x35\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x38\x30\x31\x31\x38\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x98\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x39\x30\x37\x06\x03\x55\x04\x0B\x13\x30\x28\x63\x29\x20\x32\x30\x30\x37\x20\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x30\x76\x30\x10\x06\x07\x2A\x86\x48\xCE\x3D\x02\x01\x06\x05\x2B\x81\x04\x00\x22\x03\x62\x00\x04\x15\xB1\xE8\xFD\x03\x15\x43\xE5\xAC\xEB\x87\x37\x11\x62\xEF\xD2\x83\x36\x52\x7D\x45\x57\x0B\x4A\x8D\x7B\x54\x3B\x3A\x6E\x5F\x15\x02\xC0\x50\xA6\xCF\x25\x2F\x7D\xCA\x48\xB8\xC7\x50\x63\x1C\x2A\x21\x08\x7C\x9A\x36\xD8\x0B\xFE\xD1\x26\xC5\x58\x31\x30\x28\x25\xF3\x5D\x5D\xA3\xB8\xB6\xA5\xB4\x92\xED\x6C\x2C\x9F\xEB\xDD\x43\x89\xA2\x3C\x4B\x48\x91\x1D\x50\xEC\x26\xDF\xD6\x60\x2E\xBD\x21\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x15\x5F\x35\x57\x51\x55\xFB\x25\xB2\xAD\x03\x69\xFC\x01\xA3\xFA\xBE\x11\x55\xD5\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x03\x67\x00\x30\x64\x02\x30\x64\x96\x59\xA6\xE8\x09\xDE\x8B\xBA\xFA\x5A\x88\x88\xF0\x1F\x91\xD3\x46\xA8\xF2\x4A\x4C\x02\x63\xFB\x6C\x5F\x38\xDB\x2E\x41\x93\xA9\x0E\xE6\x9D\xDC\x31\x1C\xB2\xA0\xA7\x18\x1C\x79\xE1\xC7\x36\x02\x30\x3A\x56\xAF\x9A\x74\x6C\xF6\xFB\x83\xE0\x33\xD3\x08\x5F\xA1\x9C\xC2\x5B\x9F\x46\xD6\xB6\xCB\x91\x06\x63\xA2\x06\xE7\x33\xAC\x3E\xA8\x81\x12\xD0\xCB\xBA\xD0\x92\x0B\xB6\x9E\x96\xAA\x04\x0F\x8A", - ["VeriSign Universal Root Certification Authority"] = "\x30\x82\x04\xB9\x30\x82\x03\xA1\xA0\x03\x02\x01\x02\x02\x10\x40\x1A\xC4\x64\x21\xB3\x13\x21\x03\x0E\xBB\xE4\x12\x1A\xC5\x1D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\xBD\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x32\x30\x30\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x38\x30\x36\x06\x03\x55\x04\x03\x13\x2F\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x38\x30\x34\x30\x32\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x32\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xBD\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x32\x30\x30\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x38\x30\x36\x06\x03\x55\x04\x03\x13\x2F\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xC7\x61\x37\x5E\xB1\x01\x34\xDB\x62\xD7\x15\x9B\xFF\x58\x5A\x8C\x23\x23\xD6\x60\x8E\x91\xD7\x90\x98\x83\x7A\xE6\x58\x19\x38\x8C\xC5\xF6\xE5\x64\x85\xB4\xA2\x71\xFB\xED\xBD\xB9\xDA\xCD\x4D\x00\xB4\xC8\x2D\x73\xA5\xC7\x69\x71\x95\x1F\x39\x3C\xB2\x44\x07\x9C\xE8\x0E\xFA\x4D\x4A\xC4\x21\xDF\x29\x61\x8F\x32\x22\x61\x82\xC5\x87\x1F\x6E\x8C\x7C\x5F\x16\x20\x51\x44\xD1\x70\x4F\x57\xEA\xE3\x1C\xE3\xCC\x79\xEE\x58\xD8\x0E\xC2\xB3\x45\x93\xC0\x2C\xE7\x9A\x17\x2B\x7B\x00\x37\x7A\x41\x33\x78\xE1\x33\xE2\xF3\x10\x1A\x7F\x87\x2C\xBE\xF6\xF5\xF7\x42\xE2\xE5\xBF\x87\x62\x89\x5F\x00\x4B\xDF\xC5\xDD\xE4\x75\x44\x32\x41\x3A\x1E\x71\x6E\x69\xCB\x0B\x75\x46\x08\xD1\xCA\xD2\x2B\x95\xD0\xCF\xFB\xB9\x40\x6B\x64\x8C\x57\x4D\xFC\x13\x11\x79\x84\xED\x5E\x54\xF6\x34\x9F\x08\x01\xF3\x10\x25\x06\x17\x4A\xDA\xF1\x1D\x7A\x66\x6B\x98\x60\x66\xA4\xD9\xEF\xD2\x2E\x82\xF1\xF0\xEF\x09\xEA\x44\xC9\x15\x6A\xE2\x03\x6E\x33\xD3\xAC\x9F\x55\x00\xC7\xF6\x08\x6A\x94\xB9\x5F\xDC\xE0\x33\xF1\x84\x60\xF9\x5B\x27\x11\xB4\xFC\x16\xF2\xBB\x56\x6A\x80\x25\x8D\x02\x03\x01\x00\x01\xA3\x81\xB2\x30\x81\xAF\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x6D\x06\x08\x2B\x06\x01\x05\x05\x07\x01\x0C\x04\x61\x30\x5F\xA1\x5D\xA0\x5B\x30\x59\x30\x57\x30\x55\x16\x09\x69\x6D\x61\x67\x65\x2F\x67\x69\x66\x30\x21\x30\x1F\x30\x07\x06\x05\x2B\x0E\x03\x02\x1A\x04\x14\x8F\xE5\xD3\x1A\x86\xAC\x8D\x8E\x6B\xC3\xCF\x80\x6A\xD4\x48\x18\x2C\x7B\x19\x2E\x30\x25\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x6C\x6F\x67\x6F\x2E\x76\x65\x72\x69\x73\x69\x67\x6E\x2E\x63\x6F\x6D\x2F\x76\x73\x6C\x6F\x67\x6F\x2E\x67\x69\x66\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB6\x77\xFA\x69\x48\x47\x9F\x53\x12\xD5\xC2\xEA\x07\x32\x76\x07\xD1\x97\x07\x19\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x4A\xF8\xF8\xB0\x03\xE6\x2C\x67\x7B\xE4\x94\x77\x63\xCC\x6E\x4C\xF9\x7D\x0E\x0D\xDC\xC8\xB9\x35\xB9\x70\x4F\x63\xFA\x24\xFA\x6C\x83\x8C\x47\x9D\x3B\x63\xF3\x9A\xF9\x76\x32\x95\x91\xB1\x77\xBC\xAC\x9A\xBE\xB1\xE4\x31\x21\xC6\x81\x95\x56\x5A\x0E\xB1\xC2\xD4\xB1\xA6\x59\xAC\xF1\x63\xCB\xB8\x4C\x1D\x59\x90\x4A\xEF\x90\x16\x28\x1F\x5A\xAE\x10\xFB\x81\x50\x38\x0C\x6C\xCC\xF1\x3D\xC3\xF5\x63\xE3\xB3\xE3\x21\xC9\x24\x39\xE9\xFD\x15\x66\x46\xF4\x1B\x11\xD0\x4D\x73\xA3\x7D\x46\xF9\x3D\xED\xA8\x5F\x62\xD4\xF1\x3F\xF8\xE0\x74\x57\x2B\x18\x9D\x81\xB4\xC4\x28\xDA\x94\x97\xA5\x70\xEB\xAC\x1D\xBE\x07\x11\xF0\xD5\xDB\xDD\xE5\x8C\xF0\xD5\x32\xB0\x83\xE6\x57\xE2\x8F\xBF\xBE\xA1\xAA\xBF\x3D\x1D\xB5\xD4\x38\xEA\xD7\xB0\x5C\x3A\x4F\x6A\x3F\x8F\xC0\x66\x6C\x63\xAA\xE9\xD9\xA4\x16\xF4\x81\xD1\x95\x14\x0E\x7D\xCD\x95\x34\xD9\xD2\x8F\x70\x73\x81\x7B\x9C\x7E\xBD\x98\x61\xD8\x45\x87\x98\x90\xC5\xEB\x86\x30\xC6\x35\xBF\xF0\xFF\xC3\x55\x88\x83\x4B\xEF\x05\x92\x06\x71\xF2\xB8\x98\x93\xB7\xEC\xCD\x82\x61\xF1\x38\xE6\x4F\x97\x98\x2A\x5A\x8D", - ["VeriSign Class 3 Public Primary Certification Authority - G4"] = "\x30\x82\x03\x84\x30\x82\x03\x0A\xA0\x03\x02\x01\x02\x02\x10\x2F\x80\xFE\x23\x8C\x0E\x22\x0F\x48\x67\x12\x28\x91\x87\xAC\xB3\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x32\x30\x30\x37\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x34\x30\x1E\x17\x0D\x30\x37\x31\x31\x30\x35\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x38\x30\x31\x31\x38\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x32\x30\x30\x37\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x34\x30\x76\x30\x10\x06\x07\x2A\x86\x48\xCE\x3D\x02\x01\x06\x05\x2B\x81\x04\x00\x22\x03\x62\x00\x04\xA7\x56\x7A\x7C\x52\xDA\x64\x9B\x0E\x2D\x5C\xD8\x5E\xAC\x92\x3D\xFE\x01\xE6\x19\x4A\x3D\x14\x03\x4B\xFA\x60\x27\x20\xD9\x83\x89\x69\xFA\x54\xC6\x9A\x18\x5E\x55\x2A\x64\xDE\x06\xF6\x8D\x4A\x3B\xAD\x10\x3C\x65\x3D\x90\x88\x04\x89\xE0\x30\x61\xB3\xAE\x5D\x01\xA7\x7B\xDE\x7C\xB2\xBE\xCA\x65\x61\x00\x86\xAE\xDA\x8F\x7B\xD0\x89\xAD\x4D\x1D\x59\x9A\x41\xB1\xBC\x47\x80\xDC\x9E\x62\xC3\xF9\xA3\x81\xB2\x30\x81\xAF\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x6D\x06\x08\x2B\x06\x01\x05\x05\x07\x01\x0C\x04\x61\x30\x5F\xA1\x5D\xA0\x5B\x30\x59\x30\x57\x30\x55\x16\x09\x69\x6D\x61\x67\x65\x2F\x67\x69\x66\x30\x21\x30\x1F\x30\x07\x06\x05\x2B\x0E\x03\x02\x1A\x04\x14\x8F\xE5\xD3\x1A\x86\xAC\x8D\x8E\x6B\xC3\xCF\x80\x6A\xD4\x48\x18\x2C\x7B\x19\x2E\x30\x25\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x6C\x6F\x67\x6F\x2E\x76\x65\x72\x69\x73\x69\x67\x6E\x2E\x63\x6F\x6D\x2F\x76\x73\x6C\x6F\x67\x6F\x2E\x67\x69\x66\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB3\x16\x91\xFD\xEE\xA6\x6E\xE4\xB5\x2E\x49\x8F\x87\x78\x81\x80\xEC\xE5\xB1\xB5\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x03\x68\x00\x30\x65\x02\x30\x66\x21\x0C\x18\x26\x60\x5A\x38\x7B\x56\x42\xE0\xA7\xFC\x36\x84\x51\x91\x20\x2C\x76\x4D\x43\x3D\xC4\x1D\x84\x23\xD0\xAC\xD6\x7C\x35\x06\xCE\xCD\x69\xBD\x90\x0D\xDB\x6C\x48\x42\x1D\x0E\xAA\x42\x02\x31\x00\x9C\x3D\x48\x39\x23\x39\x58\x1A\x15\x12\x59\x6A\x9E\xEF\xD5\x59\xB2\x1D\x52\x2C\x99\x71\xCD\xC7\x29\xDF\x1B\x2A\x61\x7B\x71\xD1\xDE\xF3\xC0\xE5\x0D\x3A\x4A\xAA\x2D\xA7\xD8\x86\x2A\xDD\x2E\x10", - ["NetLock Arany (Class Gold) Főtanúsítvány"] = "\x30\x82\x04\x15\x30\x82\x02\xFD\xA0\x03\x02\x01\x02\x02\x06\x49\x41\x2C\xE4\x00\x10\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\xA7\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x0C\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x0C\x0C\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x31\x37\x30\x35\x06\x03\x55\x04\x0B\x0C\x2E\x54\x61\x6E\xC3\xBA\x73\xC3\xAD\x74\x76\xC3\xA1\x6E\x79\x6B\x69\x61\x64\xC3\xB3\x6B\x20\x28\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x29\x31\x35\x30\x33\x06\x03\x55\x04\x03\x0C\x2C\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x41\x72\x61\x6E\x79\x20\x28\x43\x6C\x61\x73\x73\x20\x47\x6F\x6C\x64\x29\x20\x46\xC5\x91\x74\x61\x6E\xC3\xBA\x73\xC3\xAD\x74\x76\xC3\xA1\x6E\x79\x30\x1E\x17\x0D\x30\x38\x31\x32\x31\x31\x31\x35\x30\x38\x32\x31\x5A\x17\x0D\x32\x38\x31\x32\x30\x36\x31\x35\x30\x38\x32\x31\x5A\x30\x81\xA7\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x0C\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x0C\x0C\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x31\x37\x30\x35\x06\x03\x55\x04\x0B\x0C\x2E\x54\x61\x6E\xC3\xBA\x73\xC3\xAD\x74\x76\xC3\xA1\x6E\x79\x6B\x69\x61\x64\xC3\xB3\x6B\x20\x28\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x29\x31\x35\x30\x33\x06\x03\x55\x04\x03\x0C\x2C\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x41\x72\x61\x6E\x79\x20\x28\x43\x6C\x61\x73\x73\x20\x47\x6F\x6C\x64\x29\x20\x46\xC5\x91\x74\x61\x6E\xC3\xBA\x73\xC3\xAD\x74\x76\xC3\xA1\x6E\x79\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\xC4\x24\x5E\x73\xBE\x4B\x6D\x14\xC3\xA1\xF4\xE3\x97\x90\x6E\xD2\x30\x45\x1E\x3C\xEE\x67\xD9\x64\xE0\x1A\x8A\x7F\xCA\x30\xCA\x83\xE3\x20\xC1\xE3\xF4\x3A\xD3\x94\x5F\x1A\x7C\x5B\x6D\xBF\x30\x4F\x84\x27\xF6\x9F\x1F\x49\xBC\xC6\x99\x0A\x90\xF2\x0F\xF5\x7F\x43\x84\x37\x63\x51\x8B\x7A\xA5\x70\xFC\x7A\x58\xCD\x8E\x9B\xED\xC3\x46\x6C\x84\x70\x5D\xDA\xF3\x01\x90\x23\xFC\x4E\x30\xA9\x7E\xE1\x27\x63\xE7\xED\x64\x3C\xA0\xB8\xC9\x33\x63\xFE\x16\x90\xFF\xB0\xB8\xFD\xD7\xA8\xC0\xC0\x94\x43\x0B\xB6\xD5\x59\xA6\x9E\x56\xD0\x24\x1F\x70\x79\xAF\xDB\x39\x54\x0D\x65\x75\xD9\x15\x41\x94\x01\xAF\x5E\xEC\xF6\x8D\xF1\xFF\xAD\x64\xFE\x20\x9A\xD7\x5C\xEB\xFE\xA6\x1F\x08\x64\xA3\x8B\x76\x55\xAD\x1E\x3B\x28\x60\x2E\x87\x25\xE8\xAA\xAF\x1F\xC6\x64\x46\x20\xB7\x70\x7F\x3C\xDE\x48\xDB\x96\x53\xB7\x39\x77\xE4\x1A\xE2\xC7\x16\x84\x76\x97\x5B\x2F\xBB\x19\x15\x85\xF8\x69\x85\xF5\x99\xA7\xA9\xF2\x34\xA7\xA9\xB6\xA6\x03\xFC\x6F\x86\x3D\x54\x7C\x76\x04\x9B\x6B\xF9\x40\x5D\x00\x34\xC7\x2E\x99\x75\x9D\xE5\x88\x03\xAA\x4D\xF8\x03\xD2\x42\x76\xC0\x1B\x02\x03\x00\xA8\x8B\xA3\x45\x30\x43\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x04\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xCC\xFA\x67\x93\xF0\xB6\xB8\xD0\xA5\xC0\x1E\xF3\x53\xFD\x8C\x53\xDF\x83\xD7\x96\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\xAB\x7F\xEE\x1C\x16\xA9\x9C\x3C\x51\x00\xA0\xC0\x11\x08\x05\xA7\x99\xE6\x6F\x01\x88\x54\x61\x6E\xF1\xB9\x18\xAD\x4A\xAD\xFE\x81\x40\x23\x94\x2F\xFB\x75\x7C\x2F\x28\x4B\x62\x24\x81\x82\x0B\xF5\x61\xF1\x1C\x6E\xB8\x61\x38\xEB\x81\xFA\x62\xA1\x3B\x5A\x62\xD3\x94\x65\xC4\xE1\xE6\x6D\x82\xF8\x2F\x25\x70\xB2\x21\x26\xC1\x72\x51\x1F\x8C\x2C\xC3\x84\x90\xC3\x5A\x8F\xBA\xCF\xF4\xA7\x65\xA5\xEB\x98\xD1\xFB\x05\xB2\x46\x75\x15\x23\x6A\x6F\x85\x63\x30\x80\xF0\xD5\x9E\x1F\x29\x1C\xC2\x6C\xB0\x50\x59\x5D\x90\x5B\x3B\xA8\x0D\x30\xCF\xBF\x7D\x7F\xCE\xF1\x9D\x83\xBD\xC9\x46\x6E\x20\xA6\xF9\x61\x51\xBA\x21\x2F\x7B\xBE\xA5\x15\x63\xA1\xD4\x95\x87\xF1\x9E\xB9\xF3\x89\xF3\x3D\x85\xB8\xB8\xDB\xBE\xB5\xB9\x29\xF9\xDA\x37\x05\x00\x49\x94\x03\x84\x44\xE7\xBF\x43\x31\xCF\x75\x8B\x25\xD1\xF4\xA6\x64\xF5\x92\xF6\xAB\x05\xEB\x3D\xE9\xA5\x0B\x36\x62\xDA\xCC\x06\x5F\x36\x8B\xB6\x5E\x31\xB8\x2A\xFB\x5E\xF6\x71\xDF\x44\x26\x9E\xC4\xE6\x0D\x91\xB4\x2E\x75\x95\x80\x51\x6A\x4B\x30\xA6\xB0\x62\xA1\x93\xF1\x9B\xD8\xCE\xC4\x63\x75\x3F\x59\x47\xB1", - ["Staat der Nederlanden Root CA - G2"] = "\x30\x82\x05\xCA\x30\x82\x03\xB2\xA0\x03\x02\x01\x02\x02\x04\x00\x98\x96\x8C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4C\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x0C\x15\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x31\x2B\x30\x29\x06\x03\x55\x04\x03\x0C\x22\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x38\x30\x33\x32\x36\x31\x31\x31\x38\x31\x37\x5A\x17\x0D\x32\x30\x30\x33\x32\x35\x31\x31\x30\x33\x31\x30\x5A\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4C\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x0C\x15\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x31\x2B\x30\x29\x06\x03\x55\x04\x03\x0C\x22\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC5\x59\xE7\x6F\x75\xAA\x3E\x4B\x9C\xB5\xB8\xAC\x9E\x0B\xE4\xF9\xD9\xCA\xAB\x5D\x8F\xB5\x39\x10\x82\xD7\xAF\x51\xE0\x3B\xE1\x00\x48\x6A\xCF\xDA\xE1\x06\x43\x11\x99\xAA\x14\x25\x12\xAD\x22\xE8\x00\x6D\x43\xC4\xA9\xB8\xE5\x1F\x89\x4B\x67\xBD\x61\x48\xEF\xFD\xD2\xE0\x60\x88\xE5\xB9\x18\x60\x28\xC3\x77\x2B\xAD\xB0\x37\xAA\x37\xDE\x64\x59\x2A\x46\x57\xE4\x4B\xB9\xF8\x37\x7C\xD5\x36\xE7\x80\xC1\xB6\xF3\xD4\x67\x9B\x96\xE8\xCE\xD7\xC6\x0A\x53\xD0\x6B\x49\x96\xF3\xA3\x0B\x05\x77\x48\xF7\x25\xE5\x70\xAC\x30\x14\x20\x25\xE3\x7F\x75\x5A\xE5\x48\xF8\x4E\x7B\x03\x07\x04\xFA\x82\x61\x87\x6E\xF0\x3B\xC4\xA4\xC7\xD0\xF5\x74\x3E\xA5\x5D\x1A\x08\xF2\x9B\x25\xD2\xF6\xAC\x04\x26\x3E\x55\x3A\x62\x28\xA5\x7B\xB2\x30\xAF\xF8\x37\xC2\xD1\xBA\xD6\x38\xFD\xF4\xEF\x49\x30\x37\x99\x26\x21\x48\x85\x01\xA9\xE5\x16\xE7\xDC\x90\x55\xDF\x0F\xE8\x38\xCD\x99\x37\x21\x4F\x5D\xF5\x22\x6F\x6A\xC5\x12\x16\x60\x17\x55\xF2\x65\x66\xA6\xA7\x30\x91\x38\xC1\x38\x1D\x86\x04\x84\xBA\x1A\x25\x78\x5E\x9D\xAF\xCC\x50\x60\xD6\x13\x87\x52\xED\x63\x1F\x6D\x65\x7D\xC2\x15\x18\x74\xCA\xE1\x7E\x64\x29\x8C\x72\xD8\x16\x13\x7D\x0B\x49\x4A\xF1\x28\x1B\x20\x74\x6B\xC5\x3D\xDD\xB0\xAA\x48\x09\x3D\x2E\x82\x94\xCD\x1A\x65\xD9\x2B\x88\x9A\x99\xBC\x18\x7E\x9F\xEE\x7D\x66\x7C\x3E\xBD\x94\xB8\x81\xCE\xCD\x98\x30\x78\xC1\x6F\x67\xD0\xBE\x5F\xE0\x68\xED\xDE\xE2\xB1\xC9\x2C\x59\x78\x92\xAA\xDF\x2B\x60\x63\xF2\xE5\x5E\xB9\xE3\xCA\xFA\x7F\x50\x86\x3E\xA2\x34\x18\x0C\x09\x68\x28\x11\x1C\xE4\xE1\xB9\x5C\x3E\x47\xBA\x32\x3F\x18\xCC\x5B\x84\xF5\xF3\x6B\x74\xC4\x72\x74\xE1\xE3\x8B\xA0\x4A\xBD\x8D\x66\x2F\xEA\xAD\x35\xDA\x20\xD3\x88\x82\x61\xF0\x12\x22\xB6\xBC\xD0\xD5\xA4\xEC\xAF\x54\x88\x25\x24\x3C\xA7\x6D\xB1\x72\x29\x3F\x3E\x57\xA6\x7F\x55\xAF\x6E\x26\xC6\xFE\xE7\xCC\x40\x5C\x51\x44\x81\x0A\x78\xDE\x4A\xCE\x55\xBF\x1D\xD5\xD9\xB7\x56\xEF\xF0\x76\xFF\x0B\x79\xB5\xAF\xBD\xFB\xA9\x69\x91\x46\x97\x68\x80\x14\x36\x1D\xB3\x7F\xBB\x29\x98\x36\xA5\x20\xFA\x82\x60\x62\x33\xA4\xEC\xD6\xBA\x07\xA7\x6E\xC5\xCF\x14\xA6\xE7\xD6\x92\x34\xD8\x81\xF5\xFC\x1D\x5D\xAA\x5C\x1E\xF6\xA3\x4D\x3B\xB8\xF7\x39\x02\x03\x01\x00\x01\xA3\x81\x97\x30\x81\x94\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x52\x06\x03\x55\x1D\x20\x04\x4B\x30\x49\x30\x47\x06\x04\x55\x1D\x20\x00\x30\x3F\x30\x3D\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x31\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x70\x6B\x69\x6F\x76\x65\x72\x68\x65\x69\x64\x2E\x6E\x6C\x2F\x70\x6F\x6C\x69\x63\x69\x65\x73\x2F\x72\x6F\x6F\x74\x2D\x70\x6F\x6C\x69\x63\x79\x2D\x47\x32\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x91\x68\x32\x87\x15\x1D\x89\xE2\xB5\xF1\xAC\x36\x28\x34\x8D\x0B\x7C\x62\x88\xEB\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\xA8\x41\x4A\x67\x2A\x92\x81\x82\x50\x6E\xE1\xD7\xD8\xB3\x39\x3B\xF3\x02\x15\x09\x50\x51\xEF\x2D\xBD\x24\x7B\x88\x86\x3B\xF9\xB4\xBC\x92\x09\x96\xB9\xF6\xC0\xAB\x23\x60\x06\x79\x8C\x11\x4E\x51\xD2\x79\x80\x33\xFB\x9D\x48\xBE\xEC\x41\x43\x81\x1F\x7E\x47\x40\x1C\xE5\x7A\x08\xCA\xAA\x8B\x75\xAD\x14\xC4\xC2\xE8\x66\x3C\x82\x07\xA7\xE6\x27\x82\x5B\x18\xE6\x0F\x6E\xD9\x50\x3E\x8A\x42\x18\x29\xC6\xB4\x56\xFC\x56\x10\xA0\x05\x17\xBD\x0C\x23\x7F\xF4\x93\xED\x9C\x1A\x51\xBE\xDD\x45\x41\xBF\x91\x24\xB4\x1F\x8C\xE9\x5F\xCF\x7B\x21\x99\x9F\x95\x9F\x39\x3A\x46\x1C\x6C\xF9\xCD\x7B\x9C\x90\xCD\x28\xA9\xC7\xA9\x55\xBB\xAC\x62\x34\x62\x35\x13\x4B\x14\x3A\x55\x83\xB9\x86\x8D\x92\xA6\xC6\xF4\x07\x25\x54\xCC\x16\x57\x12\x4A\x82\x78\xC8\x14\xD9\x17\x82\x26\x2D\x5D\x20\x1F\x79\xAE\xFE\xD4\x70\x16\x16\x95\x83\xD8\x35\x39\xFF\x52\x5D\x75\x1C\x16\xC5\x13\x55\xCF\x47\xCC\x75\x65\x52\x4A\xDE\xF0\xB0\xA7\xE4\x0A\x96\x0B\xFB\xAD\xC2\xE2\x25\x84\xB2\xDD\xE4\xBD\x7E\x59\x6C\x9B\xF0\xF0\xD8\xE7\xCA\xF2\xE9\x97\x38\x7E\x89\xBE\xCC\xFB\x39\x17\x61\x3F\x72\xDB\x3A\x91\xD8\x65\x01\x19\x1D\xAD\x50\xA4\x57\x0A\x7C\x4B\xBC\x9C\x71\x73\x2A\x45\x51\x19\x85\xCC\x8E\xFD\x47\xA7\x74\x95\x1D\xA8\xD1\xAF\x4E\x17\xB1\x69\x26\xC2\xAA\x78\x57\x5B\xC5\x4D\xA7\xE5\x9E\x05\x17\x94\xCA\xB2\x5F\xA0\x49\x18\x8D\x34\xE9\x26\x6C\x48\x1E\xAA\x68\x92\x05\xE1\x82\x73\x5A\x9B\xDC\x07\x5B\x08\x6D\x7D\x9D\xD7\x8D\x21\xD9\xFC\x14\x20\xAA\xC2\x45\xDF\x3F\xE7\x00\xB2\x51\xE4\xC2\xF8\x05\xB9\x79\x1A\x8C\x34\xF3\x9E\x5B\xE4\x37\x5B\x6B\x4A\xDF\x2C\x57\x8A\x40\x5A\x36\xBA\xDD\x75\x44\x08\x37\x42\x70\x0C\xFE\xDC\x5E\x21\xA0\xA3\x8A\xC0\x90\x9C\x68\xDA\x50\xE6\x45\x10\x47\x78\xB6\x4E\xD2\x65\xC9\xC3\x37\xDF\xE1\x42\x63\xB0\x57\x37\x45\x2D\x7B\x8A\x9C\xBF\x05\xEA\x65\x55\x33\xF7\x39\x10\xC5\x28\x2A\x21\x7A\x1B\x8A\xC4\x24\xF9\x3F\x15\xC8\x9A\x15\x20\xF5\x55\x62\x96\xED\x6D\x93\x50\xBC\xE4\xAA\x78\xAD\xD9\xCB\x0A\x65\x87\xA6\x66\xC1\xC4\x81\xA3\x77\x3A\x58\x1E\x0B\xEE\x83\x8B\x9D\x1E\xD2\x52\xA4\xCC\x1D\x6F\xB0\x98\x6D\x94\x31\xB5\xF8\x71\x0A\xDC\xB9\xFC\x7D\x32\x60\xE6\xEB\xAF\x8A\x01", - ["CA Disig"] = "\x30\x82\x04\x0F\x30\x82\x02\xF7\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x4B\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x42\x72\x61\x74\x69\x73\x6C\x61\x76\x61\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x44\x69\x73\x69\x67\x20\x61\x2E\x73\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x03\x13\x08\x43\x41\x20\x44\x69\x73\x69\x67\x30\x1E\x17\x0D\x30\x36\x30\x33\x32\x32\x30\x31\x33\x39\x33\x34\x5A\x17\x0D\x31\x36\x30\x33\x32\x32\x30\x31\x33\x39\x33\x34\x5A\x30\x4A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x4B\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x42\x72\x61\x74\x69\x73\x6C\x61\x76\x61\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x44\x69\x73\x69\x67\x20\x61\x2E\x73\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x03\x13\x08\x43\x41\x20\x44\x69\x73\x69\x67\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\x92\xF6\x31\xC1\x7D\x88\xFD\x99\x01\xA9\xD8\x7B\xF2\x71\x75\xF1\x31\xC6\xF3\x75\x66\xFA\x51\x28\x46\x84\x97\x78\x34\xBC\x6C\xFC\xBC\x45\x59\x88\x26\x18\x4A\xC4\x37\x1F\xA1\x4A\x44\xBD\xE3\x71\x04\xF5\x44\x17\xE2\x3F\xFC\x48\x58\x6F\x5C\x9E\x7A\x09\xBA\x51\x37\x22\x23\x66\x43\x21\xB0\x3C\x64\xA2\xF8\x6A\x15\x0E\x3F\xEB\x51\xE1\x54\xA9\xDD\x06\x99\xD7\x9A\x3C\x54\x8B\x39\x03\x3F\x0F\xC5\xCE\xC6\xEB\x83\x72\x02\xA8\x1F\x71\xF3\x2D\xF8\x75\x08\xDB\x62\x4C\xE8\xFA\xCE\xF9\xE7\x6A\x1F\xB6\x6B\x35\x82\xBA\xE2\x8F\x16\x92\x7D\x05\x0C\x6C\x46\x03\x5D\xC0\xED\x69\xBF\x3A\xC1\x8A\xA0\xE8\x8E\xD9\xB9\x45\x28\x87\x08\xEC\xB4\xCA\x15\xBE\x82\xDD\xB5\x44\x8B\x2D\xAD\x86\x0C\x68\x62\x6D\x85\x56\xF2\xAC\x14\x63\x3A\xC6\xD1\x99\xAC\x34\x78\x56\x4B\xCF\xB6\xAD\x3F\x8C\x8A\xD7\x04\xE5\xE3\x78\x4C\xF5\x86\xAA\xF5\x8F\xFA\x3D\x6C\x71\xA3\x2D\xCA\x67\xEB\x68\x7B\x6E\x33\xA9\x0C\x82\x28\xA8\x4C\x6A\x21\x40\x15\x20\x0C\x26\x5B\x83\xC2\xA9\x16\x15\xC0\x24\x82\x5D\x2B\x16\xAD\xCA\x63\xF6\x74\x00\xB0\xDF\x43\xC4\x10\x60\x56\x67\x63\x45\x02\x03\x01\x00\x01\xA3\x81\xFF\x30\x81\xFC\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x8D\xB2\x49\x68\x9D\x72\x08\x25\xB9\xC0\x27\xF5\x50\x93\x56\x48\x46\x71\xF9\x8F\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x36\x06\x03\x55\x1D\x11\x04\x2F\x30\x2D\x81\x13\x63\x61\x6F\x70\x65\x72\x61\x74\x6F\x72\x40\x64\x69\x73\x69\x67\x2E\x73\x6B\x86\x16\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x64\x69\x73\x69\x67\x2E\x73\x6B\x2F\x63\x61\x30\x66\x06\x03\x55\x1D\x1F\x04\x5F\x30\x5D\x30\x2D\xA0\x2B\xA0\x29\x86\x27\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x64\x69\x73\x69\x67\x2E\x73\x6B\x2F\x63\x61\x2F\x63\x72\x6C\x2F\x63\x61\x5F\x64\x69\x73\x69\x67\x2E\x63\x72\x6C\x30\x2C\xA0\x2A\xA0\x28\x86\x26\x68\x74\x74\x70\x3A\x2F\x2F\x63\x61\x2E\x64\x69\x73\x69\x67\x2E\x73\x6B\x2F\x63\x61\x2F\x63\x72\x6C\x2F\x63\x61\x5F\x64\x69\x73\x69\x67\x2E\x63\x72\x6C\x30\x1A\x06\x03\x55\x1D\x20\x04\x13\x30\x11\x30\x0F\x06\x0D\x2B\x81\x1E\x91\x93\xE6\x0A\x00\x00\x00\x01\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5D\x34\x74\x61\x4C\xAF\x3B\xD8\xFF\x9F\x6D\x58\x36\x1C\x3D\x0B\x81\x0D\x12\x2B\x46\x10\x80\xFD\xE7\x3C\x27\xD0\x7A\xC8\xA9\xB6\x7E\x74\x30\x33\xA3\x3A\x8A\x7B\x74\xC0\x79\x79\x42\x93\x6D\xFF\xB1\x29\x14\x82\xAB\x21\x8C\x2F\x17\xF9\x3F\x26\x2F\xF5\x59\xC6\xEF\x80\x06\xB7\x9A\x49\x29\xEC\xCE\x7E\x71\x3C\x6A\x10\x41\xC0\xF6\xD3\x9A\xB2\x7C\x5A\x91\x9C\xC0\xAC\x5B\xC8\x4D\x5E\xF7\xE1\x53\xFF\x43\x77\xFC\x9E\x4B\x67\x6C\xD7\xF3\x83\xD1\xA0\xE0\x7F\x25\xDF\xB8\x98\x0B\x9A\x32\x38\x6C\x30\xA0\xF3\xFF\x08\x15\x33\xF7\x50\x4A\x7B\x3E\xA3\x3E\x20\xA9\xDC\x2F\x56\x80\x0A\xED\x41\x50\xB0\xC9\xF4\xEC\xB2\xE3\x26\x44\x00\x0E\x6F\x9E\x06\xBC\x22\x96\x53\x70\x65\xC4\x50\x0A\x46\x6B\xA4\x2F\x27\x81\x12\x27\x13\x5F\x10\xA1\x76\xCE\x8A\x7B\x37\xEA\xC3\x39\x61\x03\x95\x98\x3A\xE7\x6C\x88\x25\x08\xFC\x79\x68\x0D\x87\x7D\x62\xF8\xB4\x5F\xFB\xC5\xD8\x4C\xBD\x58\xBC\x3F\x43\x5B\xD4\x1E\x01\x4D\x3C\x63\xBE\x23\xEF\x8C\xCD\x5A\x50\xB8\x68\x54\xF9\x0A\x99\x33\x11\x00\xE1\x9E\xC2\x46\x77\x82\xF5\x59\x06\x8C\x21\x4C\x87\x09\xCD\xE5\xA8", - ["Juur-SK"] = "\x30\x82\x04\xE6\x30\x82\x03\xCE\xA0\x03\x02\x01\x02\x02\x04\x3B\x8E\x4B\xFC\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x5D\x31\x18\x30\x16\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x09\x70\x6B\x69\x40\x73\x6B\x2E\x65\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x45\x31\x22\x30\x20\x06\x03\x55\x04\x0A\x13\x19\x41\x53\x20\x53\x65\x72\x74\x69\x66\x69\x74\x73\x65\x65\x72\x69\x6D\x69\x73\x6B\x65\x73\x6B\x75\x73\x31\x10\x30\x0E\x06\x03\x55\x04\x03\x13\x07\x4A\x75\x75\x72\x2D\x53\x4B\x30\x1E\x17\x0D\x30\x31\x30\x38\x33\x30\x31\x34\x32\x33\x30\x31\x5A\x17\x0D\x31\x36\x30\x38\x32\x36\x31\x34\x32\x33\x30\x31\x5A\x30\x5D\x31\x18\x30\x16\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x09\x70\x6B\x69\x40\x73\x6B\x2E\x65\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x45\x31\x22\x30\x20\x06\x03\x55\x04\x0A\x13\x19\x41\x53\x20\x53\x65\x72\x74\x69\x66\x69\x74\x73\x65\x65\x72\x69\x6D\x69\x73\x6B\x65\x73\x6B\x75\x73\x31\x10\x30\x0E\x06\x03\x55\x04\x03\x13\x07\x4A\x75\x75\x72\x2D\x53\x4B\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\x81\x71\x36\x3E\x33\x07\xD6\xE3\x30\x8D\x13\x7E\x77\x32\x46\xCB\xCF\x19\xB2\x60\x31\x46\x97\x86\xF4\x98\x46\xA4\xC2\x65\x45\xCF\xD3\x40\x7C\xE3\x5A\x22\xA8\x10\x78\x33\xCC\x88\xB1\xD3\x81\x4A\xF6\x62\x17\x7B\x5F\x4D\x0A\x2E\xD0\xCF\x8B\x23\xEE\x4F\x02\x4E\xBB\xEB\x0E\xCA\xBD\x18\x63\xE8\x80\x1C\x8D\xE1\x1C\x8D\x3D\xE0\xFF\x5B\x5F\xEA\x64\xE5\x97\xE8\x3F\x99\x7F\x0C\x0A\x09\x33\x00\x1A\x53\xA7\x21\xE1\x38\x4B\xD6\x83\x1B\xAD\xAF\x64\xC2\xF9\x1C\x7A\x8C\x66\x48\x4D\x66\x1F\x18\x0A\xE2\x3E\xBB\x1F\x07\x65\x93\x85\xB9\x1A\xB0\xB9\xC4\xFB\x0D\x11\xF6\xF5\xD6\xF9\x1B\xC7\x2C\x2B\xB7\x18\x51\xFE\xE0\x7B\xF6\xA8\x48\xAF\x6C\x3B\x4F\x2F\xEF\xF8\xD1\x47\x1E\x26\x57\xF0\x51\x1D\x33\x96\xFF\xEF\x59\x3D\xDA\x4D\xD1\x15\x34\xC7\xEA\x3F\x16\x48\x7B\x91\x1C\x80\x43\x0F\x3D\xB8\x05\x3E\xD1\xB3\x95\xCD\xD8\xCA\x0F\xC2\x43\x67\xDB\xB7\x93\xE0\x22\x82\x2E\xBE\xF5\x68\x28\x83\xB9\xC1\x3B\x69\x7B\x20\xDA\x4E\x9C\x6D\xE1\xBA\xCD\x8F\x7A\x6C\xB0\x09\x22\xD7\x8B\x0B\xDB\x1C\xD5\x5A\x26\x5B\x0D\xC0\xEA\xE5\x60\xD0\x9F\xFE\x35\xDF\x3F\x02\x03\x01\x00\x01\xA3\x82\x01\xAC\x30\x82\x01\xA8\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x82\x01\x16\x06\x03\x55\x1D\x20\x04\x82\x01\x0D\x30\x82\x01\x09\x30\x82\x01\x05\x06\x0A\x2B\x06\x01\x04\x01\xCE\x1F\x01\x01\x01\x30\x81\xF6\x30\x81\xD0\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x81\xC3\x1E\x81\xC0\x00\x53\x00\x65\x00\x65\x00\x20\x00\x73\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x6B\x00\x61\x00\x61\x00\x74\x00\x20\x00\x6F\x00\x6E\x00\x20\x00\x76\x00\xE4\x00\x6C\x00\x6A\x00\x61\x00\x73\x00\x74\x00\x61\x00\x74\x00\x75\x00\x64\x00\x20\x00\x41\x00\x53\x00\x2D\x00\x69\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x74\x00\x73\x00\x65\x00\x65\x00\x72\x00\x69\x00\x6D\x00\x69\x00\x73\x00\x6B\x00\x65\x00\x73\x00\x6B\x00\x75\x00\x73\x00\x20\x00\x61\x00\x6C\x00\x61\x00\x6D\x00\x2D\x00\x53\x00\x4B\x00\x20\x00\x73\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x6B\x00\x61\x00\x61\x00\x74\x00\x69\x00\x64\x00\x65\x00\x20\x00\x6B\x00\x69\x00\x6E\x00\x6E\x00\x69\x00\x74\x00\x61\x00\x6D\x00\x69\x00\x73\x00\x65\x00\x6B\x00\x73\x30\x21\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x15\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x73\x6B\x2E\x65\x65\x2F\x63\x70\x73\x2F\x30\x2B\x06\x03\x55\x1D\x1F\x04\x24\x30\x22\x30\x20\xA0\x1E\xA0\x1C\x86\x1A\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x73\x6B\x2E\x65\x65\x2F\x6A\x75\x75\x72\x2F\x63\x72\x6C\x2F\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x04\xAA\x7A\x47\xA3\xE4\x89\xAF\x1A\xCF\x0A\x40\xA7\x18\x3F\x6F\xEF\xE9\x7D\xBE\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x04\xAA\x7A\x47\xA3\xE4\x89\xAF\x1A\xCF\x0A\x40\xA7\x18\x3F\x6F\xEF\xE9\x7D\xBE\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\xE6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7B\xC1\x18\x94\x53\xA2\x09\xF3\xFE\x26\x67\x9A\x50\xE4\xC3\x05\x2F\x2B\x35\x78\x91\x4C\x7C\xA8\x11\x11\x79\x4C\x49\x59\xAC\xC8\xF7\x85\x65\x5C\x46\xBB\x3B\x10\xA0\x02\xAF\xCD\x4F\xB5\xCC\x36\x2A\xEC\x5D\xFE\xEF\xA0\x91\xC9\xB6\x93\x6F\x7C\x80\x54\xEC\xC7\x08\x70\x0D\x8E\xFB\x82\xEC\x2A\x60\x78\x69\x36\x36\xD1\xC5\x9C\x8B\x69\xB5\x40\xC8\x94\x65\x77\xF2\x57\x21\x66\x3B\xCE\x85\x40\xB6\x33\x63\x1A\xBF\x79\x1E\xFC\x5C\x1D\xD3\x1D\x93\x1B\x8B\x0C\x5D\x85\xBD\x99\x30\x32\x18\x09\x91\x52\xE9\x7C\xA1\xBA\xFF\x64\x92\x9A\xEC\xFE\x35\xEE\x8C\x2F\xAE\xFC\x20\x86\xEC\x4A\xDE\x1B\x78\x32\x37\xA6\x81\xD2\x9D\xAF\x5A\x12\x16\xCA\x99\x5B\xFC\x6F\x6D\x0E\xC5\xA0\x1E\x86\xC9\x91\xD0\x5C\x98\x82\x5F\x63\x0C\x8A\x5A\xAB\xD8\x95\xA6\xCC\xCB\x8A\xD6\xBF\x64\x4B\x8E\xCA\x8A\xB2\xB0\xE9\x21\x32\x9E\xAA\xA8\x85\x98\x34\x81\x39\x21\x3B\xA8\x3A\x52\x32\x3D\xF6\x6B\x37\x86\x06\x5A\x15\x98\xDC\xF0\x11\x66\xFE\x34\x20\xB7\x03\xF4\x41\x10\x7D\x39\x84\x79\x96\x72\x63\xB6\x96\x02\xE5\x6B\xB9\xAD\x19\x4D\xBB\xC6\x44\xDB\x36\xCB\x2A\x9C\x8E", - ["Hongkong Post Root CA 1"] = "\x30\x82\x03\x30\x30\x82\x02\x18\xA0\x03\x02\x01\x02\x02\x02\x03\xE8\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x47\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x4B\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x48\x6F\x6E\x67\x6B\x6F\x6E\x67\x20\x50\x6F\x73\x74\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x48\x6F\x6E\x67\x6B\x6F\x6E\x67\x20\x50\x6F\x73\x74\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x31\x30\x1E\x17\x0D\x30\x33\x30\x35\x31\x35\x30\x35\x31\x33\x31\x34\x5A\x17\x0D\x32\x33\x30\x35\x31\x35\x30\x34\x35\x32\x32\x39\x5A\x30\x47\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x4B\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x48\x6F\x6E\x67\x6B\x6F\x6E\x67\x20\x50\x6F\x73\x74\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x48\x6F\x6E\x67\x6B\x6F\x6E\x67\x20\x50\x6F\x73\x74\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x31\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\xFF\x38\xB6\xE9\x66\x02\x49\xE3\xA2\xB4\xE1\x90\xF9\x40\x8F\x79\xF9\xE2\xBD\x79\xFE\x02\xBD\xEE\x24\x92\x1D\x22\xF6\xDA\x85\x72\x69\xFE\xD7\x3F\x09\xD4\xDD\x91\xB5\x02\x9C\xD0\x8D\x5A\xE1\x55\xC3\x50\x86\xB9\x29\x26\xC2\xE3\xD9\xA0\xF1\x69\x03\x28\x20\x80\x45\x22\x2D\x56\xA7\x3B\x54\x95\x56\x22\x59\x1F\x28\xDF\x1F\x20\x3D\x6D\xA2\x36\xBE\x23\xA0\xB1\x6E\xB5\xB1\x27\x3F\x39\x53\x09\xEA\xAB\x6A\xE8\x74\xB2\xC2\x65\x5C\x8E\xBF\x7C\xC3\x78\x84\xCD\x9E\x16\xFC\xF5\x2E\x4F\x20\x2A\x08\x9F\x77\xF3\xC5\x1E\xC4\x9A\x52\x66\x1E\x48\x5E\xE3\x10\x06\x8F\x22\x98\xE1\x65\x8E\x1B\x5D\x23\x66\x3B\xB8\xA5\x32\x51\xC8\x86\xAA\xA1\xA9\x9E\x7F\x76\x94\xC2\xA6\x6C\xB7\x41\xF0\xD5\xC8\x06\x38\xE6\xD4\x0C\xE2\xF3\x3B\x4C\x6D\x50\x8C\xC4\x83\x27\xC1\x13\x84\x59\x3D\x9E\x75\x74\xB6\xD8\x02\x5E\x3A\x90\x7A\xC0\x42\x36\x72\xEC\x6A\x4D\xDC\xEF\xC4\x00\xDF\x13\x18\x57\x5F\x26\x78\xC8\xD6\x0A\x79\x77\xBF\xF7\xAF\xB7\x76\xB9\xA5\x0B\x84\x17\x5D\x10\xEA\x6F\xE1\xAB\x95\x11\x5F\x6D\x3C\xA3\x5C\x4D\x83\x5B\xF2\xB3\x19\x8A\x80\x8B\x0B\x87\x02\x03\x01\x00\x01\xA3\x26\x30\x24\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x03\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\xC6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x0E\x46\xD5\x3C\xAE\xE2\x87\xD9\x5E\x81\x8B\x02\x98\x41\x08\x8C\x4C\xBC\xDA\xDB\xEE\x27\x1B\x82\xE7\x6A\x45\xEC\x16\x8B\x4F\x85\xA0\xF3\xB2\x70\xBD\x5A\x96\xBA\xCA\x6E\x6D\xEE\x46\x8B\x6E\xE7\x2A\x2E\x96\xB3\x19\x33\xEB\xB4\x9F\xA8\xB2\x37\xEE\x98\xA8\x97\xB6\x2E\xB6\x67\x27\xD4\xA6\x49\xFD\x1C\x93\x65\x76\x9E\x42\x2F\xDC\x22\x6C\x9A\x4F\xF2\x5A\x15\x39\xB1\x71\xD7\x2B\x51\xE8\x6D\x1C\x98\xC0\xD9\x2A\xF4\xA1\x82\x7B\xD5\xC9\x41\xA2\x23\x01\x74\x38\x55\x8B\x0F\xB9\x2E\x67\xA2\x20\x04\x37\xDA\x9C\x0B\xD3\x17\x21\xE0\x8F\x97\x79\x34\x6F\x84\x48\x02\x20\x33\x1B\xE6\x34\x44\x9F\x91\x70\xF4\x80\x5E\x84\x43\xC2\x29\xD2\x6C\x12\x14\xE4\x61\x8D\xAC\x10\x90\x9E\x84\x50\xBB\xF0\x96\x6F\x45\x9F\x8A\xF3\xCA\x6C\x4F\xFA\x11\x3A\x15\x15\x46\xC3\xCD\x1F\x83\x5B\x2D\x41\x12\xED\x50\x67\x41\x13\x3D\x21\xAB\x94\x8A\xAA\x4E\x7C\xC1\xB1\xFB\xA7\xD6\xB5\x27\x2F\x97\xAB\x6E\xE0\x1D\xE2\xD1\x1C\x2C\x1F\x44\xE2\xFC\xBE\x91\xA1\x9C\xFB\xD6\x29\x53\x73\x86\x9F\x53\xD8\x43\x0E\x5D\xD6\x63\x82\x71\x1D\x80\x74\xCA\xF6\xE2\x02\x6B\xD9\x5A", - ["SecureSign RootCA11"] = "\x30\x82\x03\x6D\x30\x82\x02\x55\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x58\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x2B\x30\x29\x06\x03\x55\x04\x0A\x13\x22\x4A\x61\x70\x61\x6E\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x1C\x30\x1A\x06\x03\x55\x04\x03\x13\x13\x53\x65\x63\x75\x72\x65\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x43\x41\x31\x31\x30\x1E\x17\x0D\x30\x39\x30\x34\x30\x38\x30\x34\x35\x36\x34\x37\x5A\x17\x0D\x32\x39\x30\x34\x30\x38\x30\x34\x35\x36\x34\x37\x5A\x30\x58\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x2B\x30\x29\x06\x03\x55\x04\x0A\x13\x22\x4A\x61\x70\x61\x6E\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x1C\x30\x1A\x06\x03\x55\x04\x03\x13\x13\x53\x65\x63\x75\x72\x65\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x43\x41\x31\x31\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\xFD\x77\xAA\xA5\x1C\x90\x05\x3B\xCB\x4C\x9B\x33\x8B\x5A\x14\x45\xA4\xE7\x90\x16\xD1\xDF\x57\xD2\x21\x10\xA4\x17\xFD\xDF\xAC\xD6\x1F\xA7\xE4\xDB\x7C\xF7\xEC\xDF\xB8\x03\xDA\x94\x58\xFD\x5D\x72\x7C\x8C\x3F\x5F\x01\x67\x74\x15\x96\xE3\x02\x3C\x87\xDB\xAE\xCB\x01\x8E\xC2\xF3\x66\xC6\x85\x45\xF4\x02\xC6\x3A\xB5\x62\xB2\xAF\xFA\x9C\xBF\xA4\xE6\xD4\x80\x30\x98\xF3\x0D\xB6\x93\x8F\xA9\xD4\xD8\x36\xF2\xB0\xFC\x8A\xCA\x2C\xA1\x15\x33\x95\x31\xDA\xC0\x1B\xF2\xEE\x62\x99\x86\x63\x3F\xBF\xDD\x93\x2A\x83\xA8\x76\xB9\x13\x1F\xB7\xCE\x4E\x42\x85\x8F\x22\xE7\x2E\x1A\xF2\x95\x09\xB2\x05\xB5\x44\x4E\x77\xA1\x20\xBD\xA9\xF2\x4E\x0A\x7D\x50\xAD\xF5\x05\x0D\x45\x4F\x46\x71\xFD\x28\x3E\x53\xFB\x04\xD8\x2D\xD7\x65\x1D\x4A\x1B\xFA\xCF\x3B\xB0\x31\x9A\x35\x6E\xC8\x8B\x06\xD3\x00\x91\xF2\x94\x08\x65\x4C\xB1\x34\x06\x00\x7A\x89\xE2\xF0\xC7\x03\x59\xCF\xD5\xD6\xE8\xA7\x32\xB3\xE6\x98\x40\x86\xC5\xCD\x27\x12\x8B\xCC\x7B\xCE\xB7\x11\x3C\x62\x60\x07\x23\x3E\x2B\x40\x6E\x94\x80\x09\x6D\xB6\xB3\x6F\x77\x6F\x35\x08\x50\xFB\x02\x87\xC5\x3E\x89\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x5B\xF8\x4D\x4F\xB2\xA5\x86\xD4\x3A\xD2\xF1\x63\x9A\xA0\xBE\x09\xF6\x57\xB7\xDE\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA0\xA1\x38\x16\x66\x2E\xA7\x56\x1F\x21\x9C\x06\xFA\x1D\xED\xB9\x22\xC5\x38\x26\xD8\x4E\x4F\xEC\xA3\x7F\x79\xDE\x46\x21\xA1\x87\x77\x8F\x07\x08\x9A\xB2\xA4\xC5\xAF\x0F\x32\x98\x0B\x7C\x66\x29\xB6\x9B\x7D\x25\x52\x49\x43\xAB\x4C\x2E\x2B\x6E\x7A\x70\xAF\x16\x0E\xE3\x02\x6C\xFB\x42\xE6\x18\x9D\x45\xD8\x55\xC8\xE8\x3B\xDD\xE7\xE1\xF4\x2E\x0B\x1C\x34\x5C\x6C\x58\x4A\xFB\x8C\x88\x50\x5F\x95\x1C\xBF\xED\xAB\x22\xB5\x65\xB3\x85\xBA\x9E\x0F\xB8\xAD\xE5\x7A\x1B\x8A\x50\x3A\x1D\xBD\x0D\xBC\x7B\x54\x50\x0B\xB9\x42\xAF\x55\xA0\x18\x81\xAD\x65\x99\xEF\xBE\xE4\x9C\xBF\xC4\x85\xAB\x41\xB2\x54\x6F\xDC\x25\xCD\xED\x78\xE2\x8E\x0C\x8D\x09\x49\xDD\x63\x7B\x5A\x69\x96\x02\x21\xA8\xBD\x52\x59\xE9\x7D\x35\xCB\xC8\x52\xCA\x7F\x81\xFE\xD9\x6B\xD3\xF7\x11\xED\x25\xDF\xF8\xE7\xF9\xA4\xFA\x72\x97\x84\x53\x0D\xA5\xD0\x32\x18\x51\x76\x59\x14\x6C\x0F\xEB\xEC\x5F\x80\x8C\x75\x43\x83\xC3\x85\x98\xFF\x4C\x9E\x2D\x0D\xE4\x77\x83\x93\x4E\xB5\x96\x07\x8B\x28\x13\x9B\x8C\x19\x8D\x41\x27\x49\x40\xEE\xDE\xE6\x23\x44\x39\xDC\xA1\x22\xD6\xBA\x03\xF2", - ["ACEDICOM Root"] = "\x30\x82\x05\xB5\x30\x82\x03\x9D\xA0\x03\x02\x01\x02\x02\x08\x61\x8D\xC7\x86\x3B\x01\x82\x05\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x44\x31\x16\x30\x14\x06\x03\x55\x04\x03\x0C\x0D\x41\x43\x45\x44\x49\x43\x4F\x4D\x20\x52\x6F\x6F\x74\x31\x0C\x30\x0A\x06\x03\x55\x04\x0B\x0C\x03\x50\x4B\x49\x31\x0F\x30\x0D\x06\x03\x55\x04\x0A\x0C\x06\x45\x44\x49\x43\x4F\x4D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x30\x1E\x17\x0D\x30\x38\x30\x34\x31\x38\x31\x36\x32\x34\x32\x32\x5A\x17\x0D\x32\x38\x30\x34\x31\x33\x31\x36\x32\x34\x32\x32\x5A\x30\x44\x31\x16\x30\x14\x06\x03\x55\x04\x03\x0C\x0D\x41\x43\x45\x44\x49\x43\x4F\x4D\x20\x52\x6F\x6F\x74\x31\x0C\x30\x0A\x06\x03\x55\x04\x0B\x0C\x03\x50\x4B\x49\x31\x0F\x30\x0D\x06\x03\x55\x04\x0A\x0C\x06\x45\x44\x49\x43\x4F\x4D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xFF\x92\x95\xE1\x68\x06\x76\xB4\x2C\xC8\x58\x48\xCA\xFD\x80\x54\x29\x55\x63\x24\xFF\x90\x65\x9B\x10\x75\x7B\xC3\x6A\xDB\x62\x02\x01\xF2\x18\x86\xB5\x7C\x5A\x38\xB1\xE4\x58\xB9\xFB\xD3\xD8\x2D\x9F\xBD\x32\x37\xBF\x2C\x15\x6D\xBE\xB5\xF4\x21\xD2\x13\x91\xD9\x07\xAD\x01\x05\xD6\xF3\xBD\x77\xCE\x5F\x42\x81\x0A\xF9\x6A\xE3\x83\x00\xA8\x2B\x2E\x55\x13\x63\x81\xCA\x47\x1C\x7B\x5C\x16\x57\x7A\x1B\x83\x60\x04\x3A\x3E\x65\xC3\xCD\x01\xDE\xDE\xA4\xD6\x0C\xBA\x8E\xDE\xD9\x04\xEE\x17\x56\x22\x9B\x8F\x63\xFD\x4D\x16\x0B\xB7\x7B\x77\x8C\xF9\x25\xB5\xD1\x6D\x99\x12\x2E\x4F\x1A\xB8\xE6\xEA\x04\x92\xAE\x3D\x11\xB9\x51\x42\x3D\x87\xB0\x31\x85\xAF\x79\x5A\x9C\xFE\xE7\x4E\x5E\x92\x4F\x43\xFC\xAB\x3A\xAD\xA5\x12\x26\x66\xB9\xE2\x0C\xD7\x98\xCE\xD4\x58\xA5\x95\x40\x0A\xB7\x44\x9D\x13\x74\x2B\xC2\xA5\xEB\x22\x15\x98\x10\xD8\x8B\xC5\x04\x9F\x1D\x8F\x60\xE5\x06\x1B\x9B\xCF\xB9\x79\xA0\x3D\xA2\x23\x3F\x42\x3F\x6B\xFA\x1C\x03\x7B\x30\x8D\xCE\x6C\xC0\xBF\xE6\x1B\x5F\xBF\x67\xB8\x84\x19\xD5\x15\xEF\x7B\xCB\x90\x36\x31\x62\xC9\xBC\x02\xAB\x46\x5F\x9B\xFE\x1A\x68\x94\x34\x3D\x90\x8E\xAD\xF6\xE4\x1D\x09\x7F\x4A\x88\x38\x3F\xBE\x67\xFD\x34\x96\xF5\x1D\xBC\x30\x74\xCB\x38\xEE\xD5\x6C\xAB\xD4\xFC\xF4\x00\xB7\x00\x5B\x85\x32\x16\x76\x33\xE9\xD8\xA3\x99\x9D\x05\x00\xAA\x16\xE6\xF3\x81\x7D\x6F\x7D\xAA\x86\x6D\xAD\x15\x74\xD3\xC4\xA2\x71\xAA\xF4\x14\x7D\xE7\x32\xB8\x1F\xBC\xD5\xF1\x4E\xBD\x6F\x17\x02\x39\xD7\x0E\x95\x42\x3A\xC7\x00\x3E\xE9\x26\x63\x11\xEA\x0B\xD1\x4A\xFF\x18\x9D\xB2\xD7\x7B\x2F\x3A\xD9\x96\xFB\xE8\x1E\x92\xAE\x13\x55\xC8\xD9\x27\xF6\xDC\x48\x1B\xB0\x24\xC1\x85\xE3\x77\x9D\x9A\xA4\xF3\x0C\x11\x1D\x0D\xC8\xB4\x14\xEE\xB5\x82\x57\x09\xBF\x20\x58\x7F\x2F\x22\x23\xD8\x70\xCB\x79\x6C\xC9\x4B\xF2\xA9\x2A\xC8\xFC\x87\x2B\xD7\x1A\x50\xF8\x27\xE8\x2F\x43\xE3\x3A\xBD\xD8\x57\x71\xFD\xCE\xA6\x52\x5B\xF9\xDD\x4D\xED\xE5\xF6\x6F\x89\xED\xBB\x93\x9C\x76\x21\x75\xF0\x92\x4C\x29\xF7\x2F\x9C\x01\x2E\xFE\x50\x46\x9E\x64\x0C\x14\xB3\x07\x5B\xC5\xC2\x73\x6C\xF1\x07\x5C\x45\x24\x14\x35\xAE\x83\xF1\x6A\x4D\x89\x7A\xFA\xB3\xD8\x2D\x66\xF0\x36\x87\xF5\x2B\x53\x02\x03\x01\x00\x01\xA3\x81\xAA\x30\x81\xA7\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xA6\xB3\xE1\x2B\x2B\x49\xB6\xD7\x73\xA1\xAA\x94\xF5\x01\xE7\x73\x65\x4C\xAC\x50\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xA6\xB3\xE1\x2B\x2B\x49\xB6\xD7\x73\xA1\xAA\x94\xF5\x01\xE7\x73\x65\x4C\xAC\x50\x30\x44\x06\x03\x55\x1D\x20\x04\x3D\x30\x3B\x30\x39\x06\x04\x55\x1D\x20\x00\x30\x31\x30\x2F\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x61\x63\x65\x64\x69\x63\x6F\x6D\x2E\x65\x64\x69\x63\x6F\x6D\x67\x72\x6F\x75\x70\x2E\x63\x6F\x6D\x2F\x64\x6F\x63\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\xCE\x2C\x0B\x52\x51\x62\x26\x7D\x0C\x27\x83\x8F\xC5\xF6\xDA\xA0\x68\x7B\x4F\x92\x5E\xEA\xA4\x73\x32\x11\x53\x44\xB2\x44\xCB\x9D\xEC\x0F\x79\x42\xB3\x10\xA6\xC7\x0D\x9D\xCB\xB6\xFA\x3F\x3A\x7C\xEA\xBF\x88\x53\x1B\x3C\xF7\x82\xFA\x05\x35\x33\xE1\x35\xA8\x57\xC0\xE7\xFD\x8D\x4F\x3F\x93\x32\x4F\x78\x66\x03\x77\x07\x58\xE9\x95\xC8\x7E\x3E\xD0\x79\x00\x8C\xF2\x1B\x51\x33\x9B\xBC\x94\xE9\x3A\x7B\x6E\x52\x2D\x32\x9E\x23\xA4\x45\xFB\xB6\x2E\x13\xB0\x8B\x18\xB1\xDD\xCE\xD5\x1D\xA7\x42\x7F\x55\xBE\xFB\x5B\xBB\x47\xD4\xFC\x24\xCD\x04\xAE\x96\x05\x15\xD6\xAC\xCE\x30\xF3\xCA\x0B\xC5\xBA\xE2\x22\xE0\xA6\xAD\x22\xE4\x02\xEE\x74\x11\x7F\x4C\xFF\x78\x1D\x35\xDA\xE6\x02\x34\xEB\x18\x12\x61\x77\x06\x09\x16\x63\xEA\x18\xAD\xA2\x87\x1F\xF2\xC7\x80\x09\x09\x75\x4E\x10\xA8\x8F\x3D\x86\xB8\x75\x11\xC0\x24\x62\x8A\x96\x7B\x4A\x45\xE9\xEC\x59\xC5\xBE\x6B\x83\xE6\xE1\xE8\xAC\xB5\x30\x1E\xFE\x05\x07\x80\xF9\xE1\x23\x0D\x50\x8F\x05\x98\xFF\x2C\x5F\xE8\x3B\xB6\xAD\xCF\x81\xB5\x21\x87\xCA\x08\x2A\x23\x27\x30\x20\x2B\xCF\xED\x94\x5B\xAC\xB2\x7A\xD2\xC7\x28\xA1\x8A\x0B\x9B\x4D\x4A\x2C\x6D\x85\x3F\x09\x72\x3C\x67\xE2\xD9\xDC\x07\xBA\xEB\x65\x7B\x5A\x01\x63\xD6\x90\x5B\x4F\x17\x66\x3D\x7F\x0B\x19\xA3\x93\x63\x10\x52\x2A\x9F\x14\x16\x58\xE2\xDC\xA5\xF4\xA1\x16\x8B\x0E\x91\x8B\x81\xCA\x9B\x59\xFA\xD8\x6B\x91\x07\x65\x55\x5F\x52\x1F\xAF\x3A\xFB\x90\xDD\x69\xA5\x5B\x9C\x6D\x0E\x2C\xB6\xFA\xCE\xAC\xA5\x7C\x32\x4A\x67\x40\xDC\x30\x34\x23\xDD\xD7\x04\x23\x66\xF0\xFC\x55\x80\xA7\xFB\x66\x19\x82\x35\x67\x62\x70\x39\x5E\x6F\xC7\xEA\x90\x40\x44\x08\x1E\xB8\xB2\xD6\xDB\xEE\x59\xA7\x0D\x18\x79\x34\xBC\x54\x18\x5E\x53\xCA\x34\x51\xED\x45\x0A\xE6\x8E\xC7\x82\x36\x3E\xA7\x38\x63\xA9\x30\x2C\x17\x10\x60\x92\x9F\x55\x87\x12\x59\x10\xC2\x0F\x67\x69\x11\xCC\x4E\x1E\x7E\x4A\x9A\xAD\xAF\x40\xA8\x75\xAC\x56\x90\x74\xB8\xA0\x9C\xA5\x79\x6F\xDC\xE9\x1A\xC8\x69\x05\xE9\xBA\xFA\x03\xB3\x7C\xE4\xE0\x4E\xC2\xCE\x9D\xE8\xB6\x46\x0D\x6E\x7E\x57\x3A\x67\x94\xC2\xCB\x1F\x9C\x77\x4A\x67\x4E\x69\x86\x43\x93\x38\xFB\xB6\xDB\x4F\x83\x91\xD4\x60\x7E\x4B\x3E\x2B\x38\x07\x55\x98\x5E\xA4", - ["Verisign Class 3 Public Primary Certification Authority 1"] = "\x30\x82\x02\x3C\x30\x82\x01\xA5\x02\x10\x3C\x91\x31\xCB\x1F\xF6\xD0\x1B\x0E\x9A\xB8\xD0\x44\xBF\x12\xBE\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x5F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x37\x30\x35\x06\x03\x55\x04\x0B\x13\x2E\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x39\x36\x30\x31\x32\x39\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x30\x38\x30\x32\x32\x33\x35\x39\x35\x39\x5A\x30\x5F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x37\x30\x35\x06\x03\x55\x04\x0B\x13\x2E\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xC9\x5C\x59\x9E\xF2\x1B\x8A\x01\x14\xB4\x10\xDF\x04\x40\xDB\xE3\x57\xAF\x6A\x45\x40\x8F\x84\x0C\x0B\xD1\x33\xD9\xD9\x11\xCF\xEE\x02\x58\x1F\x25\xF7\x2A\xA8\x44\x05\xAA\xEC\x03\x1F\x78\x7F\x9E\x93\xB9\x9A\x00\xAA\x23\x7D\xD6\xAC\x85\xA2\x63\x45\xC7\x72\x27\xCC\xF4\x4C\xC6\x75\x71\xD2\x39\xEF\x4F\x42\xF0\x75\xDF\x0A\x90\xC6\x8E\x20\x6F\x98\x0F\xF8\xAC\x23\x5F\x70\x29\x36\xA4\xC9\x86\xE7\xB1\x9A\x20\xCB\x53\xA5\x85\xE7\x3D\xBE\x7D\x9A\xFE\x24\x45\x33\xDC\x76\x15\xED\x0F\xA2\x71\x64\x4C\x65\x2E\x81\x68\x45\xA7\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x10\x72\x52\xA9\x05\x14\x19\x32\x08\x41\xF0\xC5\x6B\x0A\xCC\x7E\x0F\x21\x19\xCD\xE4\x67\xDC\x5F\xA9\x1B\xE6\xCA\xE8\x73\x9D\x22\xD8\x98\x6E\x73\x03\x61\x91\xC5\x7C\xB0\x45\x40\x6E\x44\x9D\x8D\xB0\xB1\x96\x74\x61\x2D\x0D\xA9\x45\xD2\xA4\x92\x2A\xD6\x9A\x75\x97\x6E\x3F\x53\xFD\x45\x99\x60\x1D\xA8\x2B\x4C\xF9\x5E\xA7\x09\xD8\x75\x30\xD7\xD2\x65\x60\x3D\x67\xD6\x48\x55\x75\x69\x3F\x91\xF5\x48\x0B\x47\x69\x22\x69\x82\x96\xBE\xC9\xC8\x38\x86\x4A\x7A\x2C\x73\x19\x48\x69\x4E\x6B\x7C\x65\xBF\x0F\xFC\x70\xCE\x88\x90", - ["Microsec e-Szigno Root CA 2009"] = "\x30\x82\x04\x0A\x30\x82\x02\xF2\xA0\x03\x02\x01\x02\x02\x09\x00\xC2\x7E\x43\x04\x4E\x47\x3F\x19\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x0C\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x0C\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4C\x74\x64\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x03\x0C\x1E\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x30\x39\x31\x1F\x30\x1D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x10\x69\x6E\x66\x6F\x40\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x30\x1E\x17\x0D\x30\x39\x30\x36\x31\x36\x31\x31\x33\x30\x31\x38\x5A\x17\x0D\x32\x39\x31\x32\x33\x30\x31\x31\x33\x30\x31\x38\x5A\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x0C\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x0C\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4C\x74\x64\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x03\x0C\x1E\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x30\x39\x31\x1F\x30\x1D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x10\x69\x6E\x66\x6F\x40\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\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\xE9\xF8\x8F\xF3\x63\xAD\xDA\x86\xD8\xA7\xE0\x42\xFB\xCF\x91\xDE\xA6\x26\xF8\x99\xA5\x63\x70\xAD\x9B\xAE\xCA\x33\x40\x7D\x6D\x96\x6E\xA1\x0E\x44\xEE\xE1\x13\x9D\x94\x42\x52\x9A\xBD\x75\x85\x74\x2C\xA8\x0E\x1D\x93\xB6\x18\xB7\x8C\x2C\xA8\xCF\xFB\x5C\x71\xB9\xDA\xEC\xFE\xE8\x7E\x8F\xE4\x2F\x1D\xB2\xA8\x75\x87\xD8\xB7\xA1\xE5\x3B\xCF\x99\x4A\x46\xD0\x83\x19\x7D\xC0\xA1\x12\x1C\x95\x6D\x4A\xF4\xD8\xC7\xA5\x4D\x33\x2E\x85\x39\x40\x75\x7E\x14\x7C\x80\x12\x98\x50\xC7\x41\x67\xB8\xA0\x80\x61\x54\xA6\x6C\x4E\x1F\xE0\x9D\x0E\x07\xE9\xC9\xBA\x33\xE7\xFE\xC0\x55\x28\x2C\x02\x80\xA7\x19\xF5\x9E\xDC\x55\x53\x03\x97\x7B\x07\x48\xFF\x99\xFB\x37\x8A\x24\xC4\x59\xCC\x50\x10\x63\x8E\xAA\xA9\x1A\xB0\x84\x1A\x86\xF9\x5F\xBB\xB1\x50\x6E\xA4\xD1\x0A\xCC\xD5\x71\x7E\x1F\xA7\x1B\x7C\xF5\x53\x6E\x22\x5F\xCB\x2B\xE6\xD4\x7C\x5D\xAE\xD6\xC2\xC6\x4C\xE5\x05\x01\xD9\xED\x57\xFC\xC1\x23\x79\xFC\xFA\xC8\x24\x83\x95\xF3\xB5\x6A\x51\x01\xD0\x77\xD6\xE9\x12\xA1\xF9\x1A\x83\xFB\x82\x1B\xB9\xB0\x97\xF4\x76\x06\x33\x43\x49\xA0\xFF\x0B\xB5\xFA\xB5\x02\x03\x01\x00\x01\xA3\x81\x80\x30\x7E\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xCB\x0F\xC6\xDF\x42\x43\xCC\x3D\xCB\xB5\x48\x23\xA1\x1A\x7A\xA6\x2A\xBB\x34\x68\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xCB\x0F\xC6\xDF\x42\x43\xCC\x3D\xCB\xB5\x48\x23\xA1\x1A\x7A\xA6\x2A\xBB\x34\x68\x30\x1B\x06\x03\x55\x1D\x11\x04\x14\x30\x12\x81\x10\x69\x6E\x66\x6F\x40\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\xC9\xD1\x0E\x5E\x2E\xD5\xCC\xB3\x7C\x3E\xCB\xFC\x3D\xFF\x0D\x28\x95\x93\x04\xC8\xBF\xDA\xCD\x79\xB8\x43\x90\xF0\xA4\xBE\xEF\xF2\xEF\x21\x98\xBC\xD4\xD4\x5D\x06\xF6\xEE\x42\xEC\x30\x6C\xA0\xAA\xA9\xCA\xF1\xAF\x8A\xFA\x3F\x0B\x73\x6A\x3E\xEA\x2E\x40\x7E\x1F\xAE\x54\x61\x79\xEB\x2E\x08\x37\xD7\x23\xF3\x8C\x9F\xBE\x1D\xB1\xE1\xA4\x75\xDB\xA0\xE2\x54\x14\xB1\xBA\x1C\x29\xA4\x18\xF6\x12\xBA\xA2\x14\x14\xE3\x31\x35\xC8\x40\xFF\xB7\xE0\x05\x76\x57\xC1\x1C\x59\xF2\xF8\xBF\xE4\xED\x25\x62\x5C\x84\xF0\x7E\x7E\x1F\xB3\xBE\xF9\xB7\x21\x11\xCC\x03\x01\x56\x70\xA7\x10\x92\x1E\x1B\x34\x81\x1E\xAD\x9C\x1A\xC3\x04\x3C\xED\x02\x61\xD6\x1E\x06\xF3\x5F\x3A\x87\xF2\x2B\xF1\x45\x87\xE5\x3D\xAC\xD1\xC7\x57\x84\xBD\x6B\xAE\xDC\xD8\xF9\xB6\x1B\x62\x70\x0B\x3D\x36\xC9\x42\xF2\x32\xD7\x7A\x61\xE6\xD2\xDB\x3D\xCF\xC8\xA9\xC9\x9B\xDC\xDB\x58\x44\xD7\x6F\x38\xAF\x7F\x78\xD3\xA3\xAD\x1A\x75\xBA\x1C\xC1\x36\x7C\x8F\x1E\x6D\x1C\xC3\x75\x46\xAE\x35\x05\xA6\xF6\x5C\x3D\x21\xEE\x56\xF0\xC9\x82\x22\x2D\x7A\x54\xAB\x70\xC3\x7D\x22\x65\x82\x70\x96", - ["E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi"] = "\x30\x82\x03\xB6\x30\x82\x02\x9E\xA0\x03\x02\x01\x02\x02\x10\x44\x99\x8D\x3C\xC0\x03\x27\xBD\x9C\x76\x95\xB9\xEA\xDB\xAC\xB5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x28\x30\x26\x06\x03\x55\x04\x0A\x13\x1F\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x42\x69\x6C\x67\x69\x20\x47\x75\x76\x65\x6E\x6C\x69\x67\x69\x20\x41\x2E\x53\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x03\x13\x33\x65\x2D\x47\x75\x76\x65\x6E\x20\x4B\x6F\x6B\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\x67\x6C\x61\x79\x69\x63\x69\x73\x69\x30\x1E\x17\x0D\x30\x37\x30\x31\x30\x34\x31\x31\x33\x32\x34\x38\x5A\x17\x0D\x31\x37\x30\x31\x30\x34\x31\x31\x33\x32\x34\x38\x5A\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x28\x30\x26\x06\x03\x55\x04\x0A\x13\x1F\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x42\x69\x6C\x67\x69\x20\x47\x75\x76\x65\x6E\x6C\x69\x67\x69\x20\x41\x2E\x53\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x03\x13\x33\x65\x2D\x47\x75\x76\x65\x6E\x20\x4B\x6F\x6B\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\x67\x6C\x61\x79\x69\x63\x69\x73\x69\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\xC3\x12\x20\x9E\xB0\x5E\x00\x65\x8D\x4E\x46\xBB\x80\x5C\xE9\x2C\x06\x97\xD5\xF3\x72\xC9\x70\xB9\xE7\x4B\x65\x80\xC1\x4B\xBE\x7E\x3C\xD7\x54\x31\x94\xDE\xD5\x12\xBA\x53\x16\x02\xEA\x58\x63\xEF\x5B\xD8\xF3\xED\x2A\x1A\xAA\x71\x48\xA3\xDC\x10\x2D\x5F\x5F\xEB\x5C\x4B\x9C\x96\x08\x42\x25\x28\x11\xCC\x8A\x5A\x62\x01\x50\xD5\xEB\x09\x53\x2F\xF8\xC3\x8F\xFE\xB3\xFC\xFD\x9D\xA2\xE3\x5F\x7D\xBE\xED\x0B\xE0\x60\xEB\x69\xEC\x33\xED\xD8\x8D\xFB\x12\x49\x83\x00\xC9\x8B\x97\x8C\x3B\x73\x2A\x32\xB3\x12\xF7\xB9\x4D\xF2\xF4\x4D\x6D\xC7\xE6\xD6\x26\x37\x08\xF2\xD9\xFD\x6B\x5C\xA3\xE5\x48\x5C\x58\xBC\x42\xBE\x03\x5A\x81\xBA\x1C\x35\x0C\x00\xD3\xF5\x23\x7E\x71\x30\x08\x26\x38\xDC\x25\x11\x47\x2D\xF3\xBA\x23\x10\xA5\xBF\xBC\x02\xF7\x43\x5E\xC7\xFE\xB0\x37\x50\x99\x7B\x0F\x93\xCE\xE6\x43\x2C\xC3\x7E\x0D\xF2\x1C\x43\x66\x60\xCB\x61\x31\x47\x87\xA3\x4F\xAE\xBD\x56\x6C\x4C\xBC\xBC\xF8\x05\xCA\x64\xF4\xE9\x34\xA1\x2C\xB5\x73\xE1\xC2\x3E\xE8\xC8\xC9\x34\x25\x08\x5C\xF3\xED\xA6\xC7\x94\x9F\xAD\x88\x43\x25\xD7\xE1\x39\x60\xFE\xAC\x39\x59\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9F\xEE\x44\xB3\x94\xD5\xFA\x91\x4F\x2E\xD9\x55\x9A\x04\x56\xDB\x2D\xC4\xDB\xA5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7F\x5F\xB9\x53\x5B\x63\x3D\x75\x32\xE7\xFA\xC4\x74\x1A\xCB\x46\xDF\x46\x69\x1C\x52\xCF\xAA\x4F\xC2\x68\xEB\xFF\x80\xA9\x51\xE8\x3D\x62\x77\x89\x3D\x0A\x75\x39\xF1\x6E\x5D\x17\x87\x6F\x68\x05\xC1\x94\x6C\xD9\x5D\xDF\xDA\xB2\x59\xCB\xA5\x10\x8A\xCA\xCC\x39\xCD\x9F\xEB\x4E\xDE\x52\xFF\x0C\xF0\xF4\x92\xA9\xF2\x6C\x53\xAB\x9B\xD2\x47\xA0\x1F\x74\xF7\x9B\x9A\xF1\x2F\x15\x9F\x7A\x64\x30\x18\x07\x3C\x2A\x0F\x67\xCA\xFC\x0F\x89\x61\x9D\x65\xA5\x3C\xE5\xBC\x13\x5B\x08\xDB\xE3\xFF\xED\xBB\x06\xBB\x6A\x06\xB1\x7A\x4F\x65\xC6\x82\xFD\x1E\x9C\x8B\xB5\x0D\xEE\x48\xBB\xB8\xBD\xAA\x08\xB4\xFB\xA3\x7C\xCB\x9F\xCD\x90\x76\x5C\x86\x96\x78\x57\x0A\x66\xF9\x58\x1A\x9D\xFD\x97\x29\x60\xDE\x11\xA6\x90\x1C\x19\x1C\xEE\x01\x96\x22\x34\x34\x2E\x91\xF9\xB7\xC4\x27\xD1\x7B\xE6\xBF\xFB\x80\x44\x5A\x16\xE5\xEB\xE0\xD4\x0A\x38\xBC\xE4\x91\xE3\xD5\xEB\x5C\xC1\xAC\xDF\x1B\x6A\x7C\x9E\xE5\x75\xD2\xB6\x97\x87\xDB\xCC\x87\x2B\x43\x3A\x84\x08\xAF\xAB\x3C\xDB\xF7\x3C\x66\x31\x86\xB0\x9D\x53\x79\xED\xF8\x23\xDE\x42\xE3\x2D\x82\xF1\x0F\xE5\xFA\x97", - ["GlobalSign Root CA - R3"] = "\x30\x82\x03\x5F\x30\x82\x02\x47\xA0\x03\x02\x01\x02\x02\x0B\x04\x00\x00\x00\x00\x01\x21\x58\x53\x08\xA2\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x4C\x31\x20\x30\x1E\x06\x03\x55\x04\x0B\x13\x17\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x52\x33\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x30\x1E\x17\x0D\x30\x39\x30\x33\x31\x38\x31\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x39\x30\x33\x31\x38\x31\x30\x30\x30\x30\x30\x5A\x30\x4C\x31\x20\x30\x1E\x06\x03\x55\x04\x0B\x13\x17\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x52\x33\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\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\xCC\x25\x76\x90\x79\x06\x78\x22\x16\xF5\xC0\x83\xB6\x84\xCA\x28\x9E\xFD\x05\x76\x11\xC5\xAD\x88\x72\xFC\x46\x02\x43\xC7\xB2\x8A\x9D\x04\x5F\x24\xCB\x2E\x4B\xE1\x60\x82\x46\xE1\x52\xAB\x0C\x81\x47\x70\x6C\xDD\x64\xD1\xEB\xF5\x2C\xA3\x0F\x82\x3D\x0C\x2B\xAE\x97\xD7\xB6\x14\x86\x10\x79\xBB\x3B\x13\x80\x77\x8C\x08\xE1\x49\xD2\x6A\x62\x2F\x1F\x5E\xFA\x96\x68\xDF\x89\x27\x95\x38\x9F\x06\xD7\x3E\xC9\xCB\x26\x59\x0D\x73\xDE\xB0\xC8\xE9\x26\x0E\x83\x15\xC6\xEF\x5B\x8B\xD2\x04\x60\xCA\x49\xA6\x28\xF6\x69\x3B\xF6\xCB\xC8\x28\x91\xE5\x9D\x8A\x61\x57\x37\xAC\x74\x14\xDC\x74\xE0\x3A\xEE\x72\x2F\x2E\x9C\xFB\xD0\xBB\xBF\xF5\x3D\x00\xE1\x06\x33\xE8\x82\x2B\xAE\x53\xA6\x3A\x16\x73\x8C\xDD\x41\x0E\x20\x3A\xC0\xB4\xA7\xA1\xE9\xB2\x4F\x90\x2E\x32\x60\xE9\x57\xCB\xB9\x04\x92\x68\x68\xE5\x38\x26\x60\x75\xB2\x9F\x77\xFF\x91\x14\xEF\xAE\x20\x49\xFC\xAD\x40\x15\x48\xD1\x02\x31\x61\x19\x5E\xB8\x97\xEF\xAD\x77\xB7\x64\x9A\x7A\xBF\x5F\xC1\x13\xEF\x9B\x62\xFB\x0D\x6C\xE0\x54\x69\x16\xA9\x03\xDA\x6E\xE9\x83\x93\x71\x76\xC6\x69\x85\x82\x17\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x8F\xF0\x4B\x7F\xA8\x2E\x45\x24\xAE\x4D\x50\xFA\x63\x9A\x8B\xDE\xE2\xDD\x1B\xBC\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x4B\x40\xDB\xC0\x50\xAA\xFE\xC8\x0C\xEF\xF7\x96\x54\x45\x49\xBB\x96\x00\x09\x41\xAC\xB3\x13\x86\x86\x28\x07\x33\xCA\x6B\xE6\x74\xB9\xBA\x00\x2D\xAE\xA4\x0A\xD3\xF5\xF1\xF1\x0F\x8A\xBF\x73\x67\x4A\x83\xC7\x44\x7B\x78\xE0\xAF\x6E\x6C\x6F\x03\x29\x8E\x33\x39\x45\xC3\x8E\xE4\xB9\x57\x6C\xAA\xFC\x12\x96\xEC\x53\xC6\x2D\xE4\x24\x6C\xB9\x94\x63\xFB\xDC\x53\x68\x67\x56\x3E\x83\xB8\xCF\x35\x21\xC3\xC9\x68\xFE\xCE\xDA\xC2\x53\xAA\xCC\x90\x8A\xE9\xF0\x5D\x46\x8C\x95\xDD\x7A\x58\x28\x1A\x2F\x1D\xDE\xCD\x00\x37\x41\x8F\xED\x44\x6D\xD7\x53\x28\x97\x7E\xF3\x67\x04\x1E\x15\xD7\x8A\x96\xB4\xD3\xDE\x4C\x27\xA4\x4C\x1B\x73\x73\x76\xF4\x17\x99\xC2\x1F\x7A\x0E\xE3\x2D\x08\xAD\x0A\x1C\x2C\xFF\x3C\xAB\x55\x0E\x0F\x91\x7E\x36\xEB\xC3\x57\x49\xBE\xE1\x2E\x2D\x7C\x60\x8B\xC3\x41\x51\x13\x23\x9D\xCE\xF7\x32\x6B\x94\x01\xA8\x99\xE7\x2C\x33\x1F\x3A\x3B\x25\xD2\x86\x40\xCE\x3B\x2C\x86\x78\xC9\x61\x2F\x14\xBA\xEE\xDB\x55\x6F\xDF\x84\xEE\x05\x09\x4D\xBD\x28\xD8\x72\xCE\xD3\x62\x50\x65\x1E\xEB\x92\x97\x83\x31\xD9\xB3\xB5\xCA\x47\x58\x3F\x5F", - ["TC TrustCenter Universal CA III"] = "\x30\x82\x03\xE1\x30\x82\x02\xC9\xA0\x03\x02\x01\x02\x02\x0E\x63\x25\x00\x01\x00\x02\x14\x8D\x33\x15\x02\xE4\x6C\xF4\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0B\x13\x1B\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1F\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x49\x49\x49\x30\x1E\x17\x0D\x30\x39\x30\x39\x30\x39\x30\x38\x31\x35\x32\x37\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0B\x13\x1B\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1F\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x49\x49\x49\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\xC2\xDA\x9C\x62\xB0\xB9\x71\x12\xB0\x0B\xC8\x1A\x57\xB2\xAE\x83\x14\x99\xB3\x34\x4B\x9B\x90\xA2\xC5\xE7\xE7\x2F\x02\xA0\x4D\x2D\xA4\xFA\x85\xDA\x9B\x25\x85\x2D\x40\x28\x20\x6D\xEA\xE0\xBD\xB1\x48\x83\x22\x29\x44\x9F\x4E\x83\xEE\x35\x51\x13\x73\x74\xD5\xBC\xF2\x30\x66\x94\x53\xC0\x40\x36\x2F\x0C\x84\x65\xCE\x0F\x6E\xC2\x58\x93\xE8\x2C\x0B\x3A\xE9\xC1\x8E\xFB\xF2\x6B\xCA\x3C\xE2\x9C\x4E\x8E\xE4\xF9\x7D\xD3\x27\x9F\x1B\xD5\x67\x78\x87\x2D\x7F\x0B\x47\xB3\xC7\xE8\xC9\x48\x7C\xAF\x2F\xCC\x0A\xD9\x41\xEF\x9F\xFE\x9A\xE1\xB2\xAE\xF9\x53\xB5\xE5\xE9\x46\x9F\x60\xE3\xDF\x8D\xD3\x7F\xFB\x96\x7E\xB3\xB5\x72\xF8\x4B\xAD\x08\x79\xCD\x69\x89\x40\x27\xF5\x2A\xC1\xAD\x43\xEC\xA4\x53\xC8\x61\xB6\xF7\xD2\x79\x2A\x67\x18\x76\x48\x6D\x5B\x25\x01\xD1\x26\xC5\xB7\x57\x69\x23\x15\x5B\x61\x8A\xAD\xF0\x1B\x2D\xD9\xAF\x5C\xF1\x26\x90\x69\xA9\xD5\x0C\x40\xF5\x33\x80\x43\x8F\x9C\xA3\x76\x2A\x45\xB4\xAF\xBF\x7F\x3E\x87\x3F\x76\xC5\xCD\x2A\xDE\x20\xC5\x16\x58\xCB\xF9\x1B\xF5\x0F\xCB\x0D\x11\x52\x64\xB8\xD2\x76\x62\x77\x83\xF1\x58\x9F\xFF\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x56\xE7\xE1\x5B\x25\x43\x80\xE0\xF6\x8C\xE1\x71\xBC\x8E\xE5\x80\x2F\xC4\x48\xE2\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x56\xE7\xE1\x5B\x25\x43\x80\xE0\xF6\x8C\xE1\x71\xBC\x8E\xE5\x80\x2F\xC4\x48\xE2\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x83\xC7\xAF\xEA\x7F\x4D\x0A\x3C\x39\xB1\x68\xBE\x7B\x6D\x89\x2E\xE9\xB3\x09\xE7\x18\x57\x8D\x85\x9A\x17\xF3\x76\x42\x50\x13\x0F\xC7\x90\x6F\x33\xAD\xC5\x49\x60\x2B\x6C\x49\x58\x19\xD4\xE2\xBE\xB7\xBF\xAB\x49\xBC\x94\xC8\xAB\xBE\x28\x6C\x16\x68\xE0\xC8\x97\x46\x20\xA0\x68\x67\x60\x88\x39\x20\x51\xD8\x68\x01\x11\xCE\xA7\xF6\x11\x07\xF6\xEC\xEC\xAC\x1A\x1F\xB2\x66\x6E\x56\x67\x60\x7A\x74\x5E\xC0\x6D\x97\x36\xAE\xB5\x0D\x5D\x66\x73\xC0\x25\x32\x45\xD8\x4A\x06\x07\x8F\xC4\xB7\x07\xB1\x4D\x06\x0D\xE1\xA5\xEB\xF4\x75\xCA\xBA\x9C\xD0\xBD\xB3\xD3\x32\x24\x4C\xEE\x7E\xE2\x76\x04\x4B\x49\x53\xD8\xF2\xE9\x54\x33\xFC\xE5\x71\x1F\x3D\x14\x5C\x96\x4B\xF1\x3A\xF2\x00\xBB\x6C\xB4\xFA\x96\x55\x08\x88\x09\xC1\xCC\x91\x19\x29\xB0\x20\x2D\xFF\xCB\x38\xA4\x40\xE1\x17\xBE\x79\x61\x80\xFF\x07\x03\x86\x4C\x4E\x7B\x06\x9F\x11\x86\x8D\x89\xEE\x27\xC4\xDB\xE2\xBC\x19\x8E\x0B\xC3\xC3\x13\xC7\x2D\x03\x63\x3B\xD3\xE8\xE4\xA2\x2A\xC2\x82\x08\x94\x16\x54\xF0\xEF\x1F\x27\x90\x25\xB8\x0D\x0E\x28\x1B\x47\x77\x47\xBD\x1C\xA8\x25\xF1\x94\xB4\x66", - ["Autoridad de Certificacion Firmaprofesional CIF A62634068"] = "\x30\x82\x06\x14\x30\x82\x03\xFC\xA0\x03\x02\x01\x02\x02\x08\x53\xEC\x3B\xEE\xFB\xB2\x48\x5F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x51\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x42\x30\x40\x06\x03\x55\x04\x03\x0C\x39\x41\x75\x74\x6F\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x46\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x20\x43\x49\x46\x20\x41\x36\x32\x36\x33\x34\x30\x36\x38\x30\x1E\x17\x0D\x30\x39\x30\x35\x32\x30\x30\x38\x33\x38\x31\x35\x5A\x17\x0D\x33\x30\x31\x32\x33\x31\x30\x38\x33\x38\x31\x35\x5A\x30\x51\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x42\x30\x40\x06\x03\x55\x04\x03\x0C\x39\x41\x75\x74\x6F\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x46\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x20\x43\x49\x46\x20\x41\x36\x32\x36\x33\x34\x30\x36\x38\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xCA\x96\x6B\x8E\xEA\xF8\xFB\xF1\xA2\x35\xE0\x7F\x4C\xDA\xE0\xC3\x52\xD7\x7D\xB6\x10\xC8\x02\x5E\xB3\x43\x2A\xC4\x4F\x6A\xB2\xCA\x1C\x5D\x28\x9A\x78\x11\x1A\x69\x59\x57\xAF\xB5\x20\x42\xE4\x8B\x0F\xE6\xDF\x5B\xA6\x03\x92\x2F\xF5\x11\xE4\x62\xD7\x32\x71\x38\xD9\x04\x0C\x71\xAB\x3D\x51\x7E\x0F\x07\xDF\x63\x05\x5C\xE9\xBF\x94\x6F\xC1\x29\x82\xC0\xB4\xDA\x51\xB0\xC1\x3C\xBB\xAD\x37\x4A\x5C\xCA\xF1\x4B\x36\x0E\x24\xAB\xBF\xC3\x84\x77\xFD\xA8\x50\xF4\xB1\xE7\xC6\x2F\xD2\x2D\x59\x8D\x7A\x0A\x4E\x96\x69\x52\x02\xAA\x36\x98\xEC\xFC\xFA\x14\x83\x0C\x37\x1F\xC9\x92\x37\x7F\xD7\x81\x2D\xE5\xC4\xB9\xE0\x3E\x34\xFE\x67\xF4\x3E\x66\xD1\xD3\xF4\x40\xCF\x5E\x62\x34\x0F\x70\x06\x3E\x20\x18\x5A\xCE\xF7\x72\x1B\x25\x6C\x93\x74\x14\x93\xA3\x73\xB1\x0E\xAA\x87\x10\x23\x59\x5F\x20\x05\x19\x47\xED\x68\x8E\x92\x12\xCA\x5D\xFC\xD6\x2B\xB2\x92\x3C\x20\xCF\xE1\x5F\xAF\x20\xBE\xA0\x76\x7F\x76\xE5\xEC\x1A\x86\x61\x33\x3E\xE7\x7B\xB4\x3F\xA0\x0F\x8E\xA2\xB9\x6A\x6F\xB9\x87\x26\x6F\x41\x6C\x88\xA6\x50\xFD\x6A\x63\x0B\xF5\x93\x16\x1B\x19\x8F\xB2\xED\x9B\x9B\xC9\x90\xF5\x01\x0C\xDF\x19\x3D\x0F\x3E\x38\x23\xC9\x2F\x8F\x0C\xD1\x02\xFE\x1B\x55\xD6\x4E\xD0\x8D\x3C\xAF\x4F\xA4\xF3\xFE\xAF\x2A\xD3\x05\x9D\x79\x08\xA1\xCB\x57\x31\xB4\x9C\xC8\x90\xB2\x67\xF4\x18\x16\x93\x3A\xFC\x47\xD8\xD1\x78\x96\x31\x1F\xBA\x2B\x0C\x5F\x5D\x99\xAD\x63\x89\x5A\x24\x20\x76\xD8\xDF\xFD\xAB\x4E\xA6\x22\xAA\x9D\x5E\xE6\x27\x8A\x7D\x68\x29\xA3\xE7\x8A\xB8\xDA\x11\xBB\x17\x2D\x99\x9D\x13\x24\x46\xF7\xC5\xE2\xD8\x9F\x8E\x7F\xC7\x8F\x74\x6D\x5A\xB2\xE8\x72\xF5\xAC\xEE\x24\x10\xAD\x2F\x14\xDA\xFF\x2D\x9A\x46\x71\x47\xBE\x42\xDF\xBB\x01\xDB\xF4\x7F\xD3\x28\x8F\x31\x59\x5B\xD3\xC9\x02\xA6\xB4\x52\xCA\x6E\x97\xFB\x43\xC5\x08\x26\x6F\x8A\xF4\xBB\xFD\x9F\x28\xAA\x0D\xD5\x45\xF3\x13\x3A\x1D\xD8\xC0\x78\x8F\x41\x67\x3C\x1E\x94\x64\xAE\x7B\x0B\xC5\xE8\xD9\x01\x88\x39\x1A\x97\x86\x64\x41\xD5\x3B\x87\x0C\x6E\xFA\x0F\xC6\xBD\x48\x14\xBF\x39\x4D\xD4\x9E\x41\xB6\x8F\x96\x1D\x63\x96\x93\xD9\x95\x06\x78\x31\x68\x9E\x37\x06\x3B\x80\x89\x45\x61\x39\x23\xC7\x1B\x44\xA3\x15\xE5\x1C\xF8\x92\x30\xBB\x02\x03\x01\x00\x01\xA3\x81\xEF\x30\x81\xEC\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x01\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x65\xCD\xEB\xAB\x35\x1E\x00\x3E\x7E\xD5\x74\xC0\x1C\xB4\x73\x47\x0E\x1A\x64\x2F\x30\x81\xA6\x06\x03\x55\x1D\x20\x04\x81\x9E\x30\x81\x9B\x30\x81\x98\x06\x04\x55\x1D\x20\x00\x30\x81\x8F\x30\x2F\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x66\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x2E\x63\x6F\x6D\x2F\x63\x70\x73\x30\x5C\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x50\x1E\x4E\x00\x50\x00\x61\x00\x73\x00\x65\x00\x6F\x00\x20\x00\x64\x00\x65\x00\x20\x00\x6C\x00\x61\x00\x20\x00\x42\x00\x6F\x00\x6E\x00\x61\x00\x6E\x00\x6F\x00\x76\x00\x61\x00\x20\x00\x34\x00\x37\x00\x20\x00\x42\x00\x61\x00\x72\x00\x63\x00\x65\x00\x6C\x00\x6F\x00\x6E\x00\x61\x00\x20\x00\x30\x00\x38\x00\x30\x00\x31\x00\x37\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x17\x7D\xA0\xF9\xB4\xDD\xC5\xC5\xEB\xAD\x4B\x24\xB5\xA1\x02\xAB\xDD\xA5\x88\x4A\xB2\x0F\x55\x4B\x2B\x57\x8C\x3B\xE5\x31\xDD\xFE\xC4\x32\xF1\xE7\x5B\x64\x96\x36\x32\x18\xEC\xA5\x32\x77\xD7\xE3\x44\xB6\xC0\x11\x2A\x80\xB9\x3D\x6A\x6E\x7C\x9B\xD3\xAD\xFC\xC3\xD6\xA3\xE6\x64\x29\x7C\xD1\xE1\x38\x1E\x82\x2B\xFF\x27\x65\xAF\xFB\x16\x15\xC4\x2E\x71\x84\xE5\xB5\xFF\xFA\xA4\x47\xBD\x64\x32\xBB\xF6\x25\x84\xA2\x27\x42\xF5\x20\xB0\xC2\x13\x10\x11\xCD\x10\x15\xBA\x42\x90\x2A\xD2\x44\xE1\x96\x26\xEB\x31\x48\x12\xFD\x2A\xDA\xC9\x06\xCF\x74\x1E\xA9\x4B\xD5\x87\x28\xF9\x79\x34\x92\x3E\x2E\x44\xE8\xF6\x8F\x4F\x8F\x35\x3F\x25\xB3\x39\xDC\x63\x2A\x90\x6B\x20\x5F\xC4\x52\x12\x4E\x97\x2C\x2A\xAC\x9D\x97\xDE\x48\xF2\xA3\x66\xDB\xC2\xD2\x83\x95\xA6\x66\xA7\x9E\x25\x0F\xE9\x0B\x33\x91\x65\x0A\x5A\xC3\xD9\x54\x12\xDD\xAF\xC3\x4E\x0E\x1F\x26\x5E\x0D\xDC\xB3\x8D\xEC\xD5\x81\x70\xDE\xD2\x4F\x24\x05\xF3\x6C\x4E\xF5\x4C\x49\x66\x8D\xD1\xFF\xD2\x0B\x25\x41\x48\xFE\x51\x84\xC6\x42\xAF\x80\x04\xCF\xD0\x7E\x64\x49\xE4\xF2\xDF\xA2\xEC\xB1\x4C\xC0\x2A\x1D\xE7\xB4\xB1\x65\xA2\xC4\xBC\xF1\x98\xF4\xAA\x70\x07\x63\xB4\xB8\xDA\x3B\x4C\xFA\x40\x22\x30\x5B\x11\xA6\xF0\x05\x0E\xC6\x02\x03\x48\xAB\x86\x9B\x85\xDD\xDB\xDD\xEA\xA2\x76\x80\x73\x7D\xF5\x9C\x04\xC4\x45\x8D\xE7\xB9\x1C\x8B\x9E\xEA\xD7\x75\xD1\x72\xB1\xDE\x75\x44\xE7\x42\x7D\xE2\x57\x6B\x7D\xDC\x99\xBC\x3D\x83\x28\xEA\x80\x93\x8D\xC5\x4C\x65\xC1\x70\x81\xB8\x38\xFC\x43\x31\xB2\xF6\x03\x34\x47\xB2\xAC\xFB\x22\x06\xCB\x1E\xDD\x17\x47\x1C\x5F\x66\xB9\xD3\x1A\xA2\xDA\x11\xB1\xA4\xBC\x23\xC9\xE4\xBE\x87\xFF\xB9\x94\xB6\xF8\x5D\x20\x4A\xD4\x5F\xE7\xBD\x68\x7B\x65\xF2\x15\x1E\xD2\x3A\xA9\x2D\xE9\xD8\x6B\x24\xAC\x97\x58\x44\x47\xAD\x59\x18\xF1\x21\x65\x70\xDE\xCE\x34\x60\xA8\x40\xF1\xF3\x3C\xA4\xC3\x28\x23\x8C\xFE\x27\x33\x43\x40\xA0\x17\x3C\xEB\xEA\x3B\xB0\x72\xA6\xA3\xB9\x4A\x4B\x5E\x16\x48\xF4\xB2\xBC\xC8\x8C\x92\xC5\x9D\x9F\xAC\x72\x36\xBC\x34\x80\x34\x6B\xA9\x8B\x92\xC0\xB8\x17\xED\xEC\x76\x53\xF5\x24\x01\x8C\xB3\x22\xE8\x4B\x7C\x55\xC6\x9D\xFA\xA3\x14\xBB\x65\x85\x6E\x6E\x4F\x12\x7E\x0A\x3C\x9D\x95", - ["Izenpe.com"] = "\x30\x82\x05\xF1\x30\x82\x03\xD9\xA0\x03\x02\x01\x02\x02\x10\x00\xB0\xB7\x5A\x16\x48\x5F\xBF\xE1\xCB\xF5\x8B\xD7\x19\xE6\x7D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x38\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x49\x5A\x45\x4E\x50\x45\x20\x53\x2E\x41\x2E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x0C\x0A\x49\x7A\x65\x6E\x70\x65\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x30\x37\x31\x32\x31\x33\x31\x33\x30\x38\x32\x38\x5A\x17\x0D\x33\x37\x31\x32\x31\x33\x30\x38\x32\x37\x32\x35\x5A\x30\x38\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x49\x5A\x45\x4E\x50\x45\x20\x53\x2E\x41\x2E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x0C\x0A\x49\x7A\x65\x6E\x70\x65\x2E\x63\x6F\x6D\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC9\xD3\x7A\xCA\x0F\x1E\xAC\xA7\x86\xE8\x16\x65\x6A\xB1\xC2\x1B\x45\x32\x71\x95\xD9\xFE\x10\x5B\xCC\xAF\xE7\xA5\x79\x01\x8F\x89\xC3\xCA\xF2\x55\x71\xF7\x77\xBE\x77\x94\xF3\x72\xA4\x2C\x44\xD8\x9E\x92\x9B\x14\x3A\xA1\xE7\x24\x90\x0A\x0A\x56\x8E\xC5\xD8\x26\x94\xE1\xD9\x48\xE1\x2D\x3E\xDA\x0A\x72\xDD\xA3\x99\x15\xDA\x81\xA2\x87\xF4\x7B\x6E\x26\x77\x89\x58\xAD\xD6\xEB\x0C\xB2\x41\x7A\x73\x6E\x6D\xDB\x7A\x78\x41\xE9\x08\x88\x12\x7E\x87\x2E\x66\x11\x63\x6C\x54\xFB\x3C\x9D\x72\xC0\xBC\x2E\xFF\xC2\xB7\xDD\x0D\x76\xE3\x3A\xD7\xF7\xB4\x68\xBE\xA2\xF5\xE3\x81\x6E\xC1\x46\x6F\x5D\x8D\xE0\x4D\xC6\x54\x55\x89\x1A\x33\x31\x0A\xB1\x57\xB9\xA3\x8A\x98\xC3\xEC\x3B\x34\xC5\x95\x41\x69\x7E\x75\xC2\x3C\x20\xC5\x61\xBA\x51\x47\xA0\x20\x90\x93\xA1\x90\x4B\xF3\x4E\x7C\x85\x45\x54\x9A\xD1\x05\x26\x41\xB0\xB5\x4D\x1D\x33\xBE\xC4\x03\xC8\x25\x7C\xC1\x70\xDB\x3B\xF4\x09\x2D\x54\x27\x48\xAC\x2F\xE1\xC4\xAC\x3E\xC8\xCB\x92\x4C\x53\x39\x37\x23\xEC\xD3\x01\xF9\xE0\x09\x44\x4D\x4D\x64\xC0\xE1\x0D\x5A\x87\x22\xBC\xAD\x1B\xA3\xFE\x26\xB5\x15\xF3\xA7\xFC\x84\x19\xE9\xEC\xA1\x88\xB4\x44\x69\x84\x83\xF3\x89\xD1\x74\x06\xA9\xCC\x0B\xD6\xC2\xDE\x27\x85\x50\x26\xCA\x17\xB8\xC9\x7A\x87\x56\x2C\x1A\x01\x1E\x6C\xBE\x13\xAD\x10\xAC\xB5\x24\xF5\x38\x91\xA1\xD6\x4B\xDA\xF1\xBB\xD2\xDE\x47\xB5\xF1\xBC\x81\xF6\x59\x6B\xCF\x19\x53\xE9\x8D\x15\xCB\x4A\xCB\xA9\x6F\x44\xE5\x1B\x41\xCF\xE1\x86\xA7\xCA\xD0\x6A\x9F\xBC\x4C\x8D\x06\x33\x5A\xA2\x85\xE5\x90\x35\xA0\x62\x5C\x16\x4E\xF0\xE3\xA2\xFA\x03\x1A\xB4\x2C\x71\xB3\x58\x2C\xDE\x7B\x0B\xDB\x1A\x0F\xEB\xDE\x21\x1F\x06\x77\x06\x03\xB0\xC9\xEF\x99\xFC\xC0\xB9\x4F\x0B\x86\x28\xFE\xD2\xB9\xEA\xE3\xDA\xA5\xC3\x47\x69\x12\xE0\xDB\xF0\xF6\x19\x8B\xED\x7B\x70\xD7\x02\xD6\xED\x87\x18\x28\x2C\x04\x24\x4C\x77\xE4\x48\x8A\x1A\xC6\x3B\x9A\xD4\x0F\xCA\xFA\x75\xD2\x01\x40\x5A\x8D\x79\xBF\x8B\xCF\x4B\xCF\xAA\x16\xC1\x95\xE4\xAD\x4C\x8A\x3E\x17\x91\xD4\xB1\x62\xE5\x82\xE5\x80\x04\xA4\x03\x7E\x8D\xBF\xDA\x7F\xA2\x0F\x97\x4F\x0C\xD3\x0D\xFB\xD7\xD1\xE5\x72\x7E\x1C\xC8\x77\xFF\x5B\x9A\x0F\xB7\xAE\x05\x46\xE5\xF1\xA8\x16\xEC\x47\xA4\x17\x02\x03\x01\x00\x01\xA3\x81\xF6\x30\x81\xF3\x30\x81\xB0\x06\x03\x55\x1D\x11\x04\x81\xA8\x30\x81\xA5\x81\x0F\x69\x6E\x66\x6F\x40\x69\x7A\x65\x6E\x70\x65\x2E\x63\x6F\x6D\xA4\x81\x91\x30\x81\x8E\x31\x47\x30\x45\x06\x03\x55\x04\x0A\x0C\x3E\x49\x5A\x45\x4E\x50\x45\x20\x53\x2E\x41\x2E\x20\x2D\x20\x43\x49\x46\x20\x41\x30\x31\x33\x33\x37\x32\x36\x30\x2D\x52\x4D\x65\x72\x63\x2E\x56\x69\x74\x6F\x72\x69\x61\x2D\x47\x61\x73\x74\x65\x69\x7A\x20\x54\x31\x30\x35\x35\x20\x46\x36\x32\x20\x53\x38\x31\x43\x30\x41\x06\x03\x55\x04\x09\x0C\x3A\x41\x76\x64\x61\x20\x64\x65\x6C\x20\x4D\x65\x64\x69\x74\x65\x72\x72\x61\x6E\x65\x6F\x20\x45\x74\x6F\x72\x62\x69\x64\x65\x61\x20\x31\x34\x20\x2D\x20\x30\x31\x30\x31\x30\x20\x56\x69\x74\x6F\x72\x69\x61\x2D\x47\x61\x73\x74\x65\x69\x7A\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x1D\x1C\x65\x0E\xA8\xF2\x25\x7B\xB4\x91\xCF\xE4\xB1\xB1\xE6\xBD\x55\x74\x6C\x05\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\x78\xA6\x0C\x16\x4A\x9F\x4C\x88\x3A\xC0\xCB\x0E\xA5\x16\x7D\x9F\xB9\x48\x5F\x18\x8F\x0D\x62\x36\xF6\xCD\x19\x6B\xAC\xAB\xD5\xF6\x91\x7D\xAE\x71\xF3\x3F\xB3\x0E\x78\x85\x9B\x95\xA4\x27\x21\x47\x42\x4A\x7C\x48\x3A\xF5\x45\x7C\xB3\x0C\x8E\x51\x78\xAC\x95\x13\xDE\xC6\xFD\x7D\xB8\x1A\x90\x4C\xAB\x92\x03\xC7\xED\x42\x01\xCE\x0F\xD8\xB1\xFA\xA2\x92\xE1\x60\x6D\xAE\x7A\x6B\x09\xAA\xC6\x29\xEE\x68\x49\x67\x30\x80\x24\x7A\x31\x16\x39\x5B\x7E\xF1\x1C\x2E\xDD\x6C\x09\xAD\xF2\x31\xC1\x82\x4E\xB9\xBB\xF9\xBE\xBF\x2A\x85\x3F\xC0\x40\xA3\x3A\x59\xFC\x59\x4B\x3C\x28\x24\xDB\xB4\x15\x75\xAE\x0D\x88\xBA\x2E\x73\xC0\xBD\x58\x87\xE5\x42\xF2\xEB\x5E\xEE\x1E\x30\x22\x99\xCB\x37\xD1\xC4\x21\x6C\x81\xEC\xBE\x6D\x26\xE6\x1C\xE4\x42\x20\x9E\x47\xB0\xAC\x83\x59\x70\x2C\x35\xD6\xAF\x36\x34\xB4\xCD\x3B\xF8\x32\xA8\xEF\xE3\x78\x89\xFB\x8D\x45\x2C\xDA\x9C\xB8\x7E\x40\x1C\x61\xE7\x3E\xA2\x92\x2C\x4B\xF2\xCD\xFA\x98\xB6\x29\xFF\xF3\xF2\x7B\xA9\x1F\x2E\xA0\x93\x57\x2B\xDE\x85\x03\xF9\x69\x37\xCB\x9E\x78\x6A\x05\xB4\xC5\x31\x78\x89\xEC\x7A\xA7\x85\xE1\xB9\x7B\x3C\xDE\xBE\x1E\x79\x84\xCE\x9F\x70\x0E\x59\xC2\x35\x2E\x90\x2A\x31\xD9\xE4\x45\x7A\x41\xA4\x2E\x13\x9B\x34\x0E\x66\x7B\x49\xAB\x64\x97\xD0\x46\xC3\x79\x9D\x72\x50\x63\xA6\x98\x5B\x06\xBD\x48\x6D\xD8\x39\x83\x70\xE8\x35\xF0\x05\xD1\xAA\xBC\xE3\xDB\xC8\x02\xEA\x7C\xFD\x82\xDA\xC2\x5B\x52\x35\xAE\x98\x3A\xAD\xBA\x35\x93\x23\xA7\x1F\x48\xDD\x35\x46\x98\xB2\x10\x68\xE4\xA5\x31\xC2\x0A\x58\x2E\x19\x81\x10\xC9\x50\x75\xFC\xEA\x5A\x16\xCE\x11\xD7\xEE\xEF\x50\x88\x2D\x61\xFF\x3F\x42\x73\x05\x94\x43\xD5\x8E\x3C\x4E\x01\x3A\x19\xA5\x1F\x46\x4E\x77\xD0\x5D\xE5\x81\x22\x21\x87\xFE\x94\x7D\x84\xD8\x93\xAD\xD6\x68\x43\x48\xB2\xDB\xEB\x73\x24\xE7\x91\x7F\x54\xA4\xB6\x80\x3E\x9D\xA3\x3C\x4C\x72\xC2\x57\xC4\xA0\xD4\xCC\x38\x27\xCE\xD5\x06\x9E\xA2\x48\xD9\xE9\x9F\xCE\x82\x70\x36\x93\x9A\x3B\xDF\x96\x21\xE3\x59\xB7\x0C\xDA\x91\x37\xF0\xFD\x59\x5A\xB3\x99\xC8\x69\x6C\x43\x26\x01\x35\x63\x60\x55\x89\x03\x3A\x75\xD8\xBA\x4A\xD9\x54\xFF\xEE\xDE\x80\xD8\x2D\xD1\x38\xD5\x5E\x2D\x0B\x98\x7D\x3E\x6C\xDB\xFC\x26\x88\xC7", - ["Chambers of Commerce Root - 2008"] = "\x30\x82\x07\x4F\x30\x82\x05\x37\xA0\x03\x02\x01\x02\x02\x09\x00\xA3\xDA\x42\x7E\xA4\xB1\xAE\xDA\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x30\x1E\x17\x0D\x30\x38\x30\x38\x30\x31\x31\x32\x32\x39\x35\x30\x5A\x17\x0D\x33\x38\x30\x37\x33\x31\x31\x32\x32\x39\x35\x30\x5A\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xAF\x00\xCB\x70\x37\x2B\x80\x5A\x4A\x3A\x6C\x78\x94\x7D\xA3\x7F\x1A\x1F\xF6\x35\xD5\xBD\xDB\xCB\x0D\x44\x72\x3E\x26\xB2\x90\x52\xBA\x63\x3B\x28\x58\x6F\xA5\xB3\x6D\x94\xA6\xF3\xDD\x64\x0C\x55\xF6\xF6\xE7\xF2\x22\x22\x80\x5E\xE1\x62\xC6\xB6\x29\xE1\x81\x6C\xF2\xBF\xE5\x7D\x32\x6A\x54\xA0\x32\x19\x59\xFE\x1F\x8B\xD7\x3D\x60\x86\x85\x24\x6F\xE3\x11\xB3\x77\x3E\x20\x96\x35\x21\x6B\xB3\x08\xD9\x70\x2E\x64\xF7\x84\x92\x53\xD6\x0E\xB0\x90\x8A\x8A\xE3\x87\x8D\x06\xD3\xBD\x90\x0E\xE2\x99\xA1\x1B\x86\x0E\xDA\x9A\x0A\xBB\x0B\x61\x50\x06\x52\xF1\x9E\x7F\x76\xEC\xCB\x0F\xD0\x1E\x0D\xCF\x99\x30\x3D\x1C\xC4\x45\x10\x58\xAC\xD6\xD3\xE8\xD7\xE5\xEA\xC5\x01\x07\x77\xD6\x51\xE6\x03\x7F\x8A\x48\xA5\x4D\x68\x75\xB9\xE9\xBC\x9E\x4E\x19\x71\xF5\x32\x4B\x9C\x6D\x60\x19\x0B\xFB\xCC\x9D\x75\xDC\xBF\x26\xCD\x8F\x93\x78\x39\x79\x73\x5E\x25\x0E\xCA\x5C\xEB\x77\x12\x07\xCB\x64\x41\x47\x72\x93\xAB\x50\xC3\xEB\x09\x76\x64\x34\xD2\x39\xB7\x76\x11\x09\x0D\x76\x45\xC4\xA9\xAE\x3D\x6A\xAF\xB5\x7D\x65\x2F\x94\x58\x10\xEC\x5C\x7C\xAF\x7E\xE2\xB6\x18\xD9\xD0\x9B\x4E\x5A\x49\xDF\xA9\x66\x0B\xCC\x3C\xC6\x78\x7C\xA7\x9C\x1D\xE3\xCE\x8E\x53\xBE\x05\xDE\x60\x0F\x6B\xE5\x1A\xDB\x3F\xE3\xE1\x21\xC9\x29\xC1\xF1\xEB\x07\x9C\x52\x1B\x01\x44\x51\x3C\x7B\x25\xD7\xC4\xE5\x52\x54\x5D\x25\x07\xCA\x16\x20\xB8\xAD\xE4\x41\xEE\x7A\x08\xFE\x99\x6F\x83\xA6\x91\x02\xB0\x6C\x36\x55\x6A\xE7\x7D\xF5\x96\xE6\xCA\x81\xD6\x97\xF1\x94\x83\xE9\xED\xB0\xB1\x6B\x12\x69\x1E\xAC\xFB\x5D\xA9\xC5\x98\xE9\xB4\x5B\x58\x7A\xBE\x3D\xA2\x44\x3A\x63\x59\xD4\x0B\x25\xDE\x1B\x4F\xBD\xE5\x01\x9E\xCD\xD2\x29\xD5\x9F\x17\x19\x0A\x6F\xBF\x0C\x90\xD3\x09\x5F\xD9\xE3\x8A\x35\xCC\x79\x5A\x4D\x19\x37\x92\xB7\xC4\xC1\xAD\xAF\xF4\x79\x24\x9A\xB2\x01\x0B\xB1\xAF\x5C\x96\xF3\x80\x32\xFB\x5C\x3D\x98\xF1\xA0\x3F\x4A\xDE\xBE\xAF\x94\x2E\xD9\x55\x9A\x17\x6E\x60\x9D\x63\x6C\xB8\x63\xC9\xAE\x81\x5C\x18\x35\xE0\x90\xBB\xBE\x3C\x4F\x37\x22\xB9\x7E\xEB\xCF\x9E\x77\x21\xA6\x3D\x38\x81\xFB\x48\xDA\x31\x3D\x2B\xE3\x89\xF5\xD0\xB5\xBD\x7E\xE0\x50\xC4\x12\x89\xB3\x23\x9A\x10\x31\x85\xDB\xAE\x6F\xEF\x38\x33\x18\x76\x11\x02\x03\x01\x00\x01\xA3\x82\x01\x6C\x30\x82\x01\x68\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x0C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xF9\x24\xAC\x0F\xB2\xB5\xF8\x79\xC0\xFA\x60\x88\x1B\xC4\xD9\x4D\x02\x9E\x17\x19\x30\x81\xE3\x06\x03\x55\x1D\x23\x04\x81\xDB\x30\x81\xD8\x80\x14\xF9\x24\xAC\x0F\xB2\xB5\xF8\x79\xC0\xFA\x60\x88\x1B\xC4\xD9\x4D\x02\x9E\x17\x19\xA1\x81\xB4\xA4\x81\xB1\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x82\x09\x00\xA3\xDA\x42\x7E\xA4\xB1\xAE\xDA\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x3D\x06\x03\x55\x1D\x20\x04\x36\x30\x34\x30\x32\x06\x04\x55\x1D\x20\x00\x30\x2A\x30\x28\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x1C\x68\x74\x74\x70\x3A\x2F\x2F\x70\x6F\x6C\x69\x63\x79\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x90\x12\xAF\x22\x35\xC2\xA3\x39\xF0\x2E\xDE\xE9\xB5\xE9\x78\x7C\x48\xBE\x3F\x7D\x45\x92\x5E\xE9\xDA\xB1\x19\xFC\x16\x3C\x9F\xB4\x5B\x66\x9E\x6A\xE7\xC3\xB9\x5D\x88\xE8\x0F\xAD\xCF\x23\x0F\xDE\x25\x3A\x5E\xCC\x4F\xA5\xC1\xB5\x2D\xAC\x24\xD2\x58\x07\xDE\xA2\xCF\x69\x84\x60\x33\xE8\x10\x0D\x13\xA9\x23\xD0\x85\xE5\x8E\x7B\xA6\x9E\x3D\x72\x13\x72\x33\xF5\xAA\x7D\xC6\x63\x1F\x08\xF4\xFE\x01\x7F\x24\xCF\x2B\x2C\x54\x09\xDE\xE2\x2B\x6D\x92\xC6\x39\x4F\x16\xEA\x3C\x7E\x7A\x46\xD4\x45\x6A\x46\xA8\xEB\x75\x82\x56\xA7\xAB\xA0\x7C\x68\x13\x33\xF6\x9D\x30\xF0\x6F\x27\x39\x24\x23\x2A\x90\xFD\x90\x29\x35\xF2\x93\xDF\x34\xA5\xC6\xF7\xF8\xEF\x8C\x0F\x62\x4A\x7C\xAE\xD3\xF5\x54\xF8\x8D\xB6\x9A\x56\x87\x16\x82\x3A\x33\xAB\x5A\x22\x08\xF7\x82\xBA\xEA\x2E\xE0\x47\x9A\xB4\xB5\x45\xA3\x05\x3B\xD9\xDC\x2E\x45\x40\x3B\xEA\xDC\x7F\xE8\x3B\xEB\xD1\xEC\x26\xD8\x35\xA4\x30\xC5\x3A\xAC\x57\x9E\xB3\x76\xA5\x20\x7B\xF9\x1E\x4A\x05\x62\x01\xA6\x28\x75\x60\x97\x92\x0D\x6E\x3E\x4D\x37\x43\x0D\x92\x15\x9C\x18\x22\xCD\x51\x99\xA0\x29\x1A\x3C\x5F\x8A\x32\x33\x5B\x30\xC7\x89\x2F\x47\x98\x0F\xA3\x03\xC6\xF6\xF1\xAC\xDF\x32\xF0\xD9\x81\x1A\xE4\x9C\xBD\xF6\x80\x14\xF0\xD1\x2C\xB9\x85\xF5\xD8\xA3\xB1\xC8\xA5\x21\xE5\x1C\x13\x97\xEE\x0E\xBD\xDF\x29\xA9\xEF\x34\x53\x5B\xD3\xE4\x6A\x13\x84\x06\xB6\x32\x02\xC4\x52\xAE\x22\xD2\xDC\xB2\x21\x42\x1A\xDA\x40\xF0\x29\xC9\xEC\x0A\x0C\x5C\xE2\xD0\xBA\xCC\x48\xD3\x37\x0A\xCC\x12\x0A\x8A\x79\xB0\x3D\x03\x7F\x69\x4B\xF4\x34\x20\x7D\xB3\x34\xEA\x8E\x4B\x64\xF5\x3E\xFD\xB3\x23\x67\x15\x0D\x04\xB8\xF0\x2D\xC1\x09\x51\x3C\xB2\x6C\x15\xF0\xA5\x23\xD7\x83\x74\xE4\xE5\x2E\xC9\xFE\x98\x27\x42\xC6\xAB\xC6\x9E\xB0\xD0\x5B\x38\xA5\x9B\x50\xDE\x7E\x18\x98\xB5\x45\x3B\xF6\x79\xB4\xE8\xF7\x1A\x7B\x06\x83\xFB\xD0\x8B\xDA\xBB\xC7\xBD\x18\xAB\x08\x6F\x3C\x80\x6B\x40\x3F\x19\x19\xBA\x65\x8A\xE6\xBE\xD5\x5C\xD3\x36\xD7\xEF\x40\x52\x24\x60\x38\x67\x04\x31\xEC\x8F\xF3\x82\xC6\xDE\xB9\x55\xF3\x3B\x31\x91\x5A\xDC\xB5\x08\x15\xAD\x76\x25\x0A\x0D\x7B\x2E\x87\xE2\x0C\xA6\x06\xBC\x26\x10\x6D\x37\x9D\xEC\xDD\x78\x8C\x7C\x80\xC5\xF0\xD9\x77\x48\xD0", - ["Global Chambersign Root - 2008"] = "\x30\x82\x07\x49\x30\x82\x05\x31\xA0\x03\x02\x01\x02\x02\x09\x00\xC9\xCD\xD3\xE9\xD5\x7D\x23\xCE\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xAC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x47\x6C\x6F\x62\x61\x6C\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x30\x1E\x17\x0D\x30\x38\x30\x38\x30\x31\x31\x32\x33\x31\x34\x30\x5A\x17\x0D\x33\x38\x30\x37\x33\x31\x31\x32\x33\x31\x34\x30\x5A\x30\x81\xAC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x47\x6C\x6F\x62\x61\x6C\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC0\xDF\x56\xD3\xE4\x3A\x9B\x76\x45\xB4\x13\xDB\xFF\xC1\xB6\x19\x8B\x37\x41\x18\x95\x52\x47\xEB\x17\x9D\x29\x88\x8E\x35\x6C\x06\x32\x2E\x47\x62\xF3\x49\x04\xBF\x7D\x44\x36\xB1\x71\xCC\xBD\x5A\x09\x73\xD5\xD9\x85\x44\xFF\x91\x57\x25\xDF\x5E\x36\x8E\x70\xD1\x5C\x71\x43\x1D\xD9\xDA\xEF\x5C\xD2\xFB\x1B\xBD\x3A\xB5\xCB\xAD\xA3\xCC\x44\xA7\x0D\xAE\x21\x15\x3F\xB9\x7A\x5B\x92\x75\xD8\xA4\x12\x38\x89\x19\x8A\xB7\x80\xD2\xE2\x32\x6F\x56\x9C\x91\xD6\x88\x10\x0B\xB3\x74\x64\x92\x74\x60\xF3\xF6\xCF\x18\x4F\x60\xB2\x23\xD0\xC7\x3B\xCE\x61\x4B\x99\x8F\xC2\x0C\xD0\x40\xB2\x98\xDC\x0D\xA8\x4E\xA3\xB9\x0A\xAE\x60\xA0\xAD\x45\x52\x63\xBA\x66\xBD\x68\xE0\xF9\xBE\x1A\xA8\x81\xBB\x1E\x41\x78\x75\xD3\xC1\xFE\x00\x55\xB0\x87\x54\xE8\x27\x90\x35\x1D\x4C\x33\xAD\x97\xFC\x97\x2E\x98\x84\xBF\x2C\xC9\xA3\xBF\xD1\x98\x11\x14\xED\x63\xF8\xCA\x98\x88\x58\x17\x99\xED\x45\x03\x97\x7E\x3C\x86\x1E\x88\x8C\xBE\xF2\x91\x84\x8F\x65\x34\xD8\x00\x4C\x7D\xB7\x31\x17\x5A\x29\x7A\x0A\x18\x24\x30\xA3\x37\xB5\x7A\xA9\x01\x7D\x26\xD6\xF9\x0E\x8E\x59\xF1\xFD\x1B\x33\xB5\x29\x3B\x17\x3B\x41\xB6\x21\xDD\xD4\xC0\x3D\xA5\x9F\x9F\x1F\x43\x50\xC9\xBB\xBC\x6C\x7A\x97\x98\xEE\xCD\x8C\x1F\xFB\x9C\x51\xAE\x8B\x70\xBD\x27\x9F\x71\xC0\x6B\xAC\x7D\x90\x66\xE8\xD7\x5D\x3A\x0D\xB0\xD5\xC2\x8D\xD5\xC8\x9D\x9D\xC1\x6D\xD0\xD0\xBF\x51\xE4\xE3\xF8\xC3\x38\x36\xAE\xD6\xA7\x75\xE6\xAF\x84\x43\x5D\x93\x92\x0C\x6A\x07\xDE\x3B\x1D\x98\x22\xD6\xAC\xC1\x35\xDB\xA3\xA0\x25\xFF\x72\xB5\x76\x1D\xDE\x6D\xE9\x2C\x66\x2C\x52\x84\xD0\x45\x92\xCE\x1C\xE5\xE5\x33\x1D\xDC\x07\x53\x54\xA3\xAA\x82\x3B\x9A\x37\x2F\xDC\xDD\xA0\x64\xE9\xE6\xDD\xBD\xAE\xFC\x64\x85\x1D\x3C\xA7\xC9\x06\xDE\x84\xFF\x6B\xE8\x6B\x1A\x3C\xC5\xA2\xB3\x42\xFB\x8B\x09\x3E\x5F\x08\x52\xC7\x62\xC4\xD4\x05\x71\xBF\xC4\x64\xE4\xF8\xA1\x83\xE8\x3E\x12\x9B\xA8\x1E\xD4\x36\x4D\x2F\x71\xF6\x8D\x28\xF6\x83\xA9\x13\xD2\x61\xC1\x91\xBB\x48\xC0\x34\x8F\x41\x8C\x4B\x4C\xDB\x69\x12\xFF\x50\x94\x9C\x20\x83\x59\x73\xED\x7C\xA1\xF2\xF1\xFD\xDD\xF7\x49\xD3\x43\x58\xA0\x56\x63\xCA\x3D\x3D\xE5\x35\x56\x59\xE9\x0E\xCA\x20\xCC\x2B\x4B\x93\x29\x0F\x02\x03\x01\x00\x01\xA3\x82\x01\x6A\x30\x82\x01\x66\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x0C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB9\x09\xCA\x9C\x1E\xDB\xD3\x6C\x3A\x6B\xAE\xED\x54\xF1\x5B\x93\x06\x35\x2E\x5E\x30\x81\xE1\x06\x03\x55\x1D\x23\x04\x81\xD9\x30\x81\xD6\x80\x14\xB9\x09\xCA\x9C\x1E\xDB\xD3\x6C\x3A\x6B\xAE\xED\x54\xF1\x5B\x93\x06\x35\x2E\x5E\xA1\x81\xB2\xA4\x81\xAF\x30\x81\xAC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x47\x6C\x6F\x62\x61\x6C\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x82\x09\x00\xC9\xCD\xD3\xE9\xD5\x7D\x23\xCE\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x3D\x06\x03\x55\x1D\x20\x04\x36\x30\x34\x30\x32\x06\x04\x55\x1D\x20\x00\x30\x2A\x30\x28\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x1C\x68\x74\x74\x70\x3A\x2F\x2F\x70\x6F\x6C\x69\x63\x79\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x80\x88\x7F\x70\xDE\x92\x28\xD9\x05\x94\x46\xFF\x90\x57\xA9\xF1\x2F\xDF\x1A\x0D\x6B\xFA\x7C\x0E\x1C\x49\x24\x79\x27\xD8\x46\xAA\x6F\x29\x59\x52\x88\x70\x12\xEA\xDD\x3D\xF5\x9B\x53\x54\x6F\xE1\x60\xA2\xA8\x09\xB9\xEC\xEB\x59\x7C\xC6\x35\xF1\xDC\x18\xE9\xF1\x67\xE5\xAF\xBA\x45\xE0\x09\xDE\xCA\x44\x0F\xC2\x17\x0E\x77\x91\x45\x7A\x33\x5F\x5F\x96\x2C\x68\x8B\xC1\x47\x8F\x98\x9B\x3D\xC0\xEC\xCB\xF5\xD5\x82\x92\x84\x35\xD1\xBE\x36\x38\x56\x72\x31\x5B\x47\x2D\xAA\x17\xA4\x63\x51\xEB\x0A\x01\xAD\x7F\xEC\x75\x9E\xCB\xA1\x1F\xF1\x7F\x12\xB1\xB9\xE4\x64\x7F\x67\xD6\x23\x2A\xF4\xB8\x39\x5D\x98\xE8\x21\xA7\xE1\xBD\x3D\x42\x1A\x74\x9A\x70\xAF\x68\x6C\x50\x5D\x49\xCF\xFF\xFB\x0E\x5D\xE6\x2C\x47\xD7\x81\x3A\x59\x00\xB5\x73\x6B\x63\x20\xF6\x31\x45\x08\x39\x0E\xF4\x70\x7E\x40\x70\x5A\x3F\xD0\x6B\x42\xA9\x74\x3D\x28\x2F\x02\x6D\x75\x72\x95\x09\x8D\x48\x63\xC6\xC6\x23\x57\x92\x93\x5E\x35\xC1\x8D\xF9\x0A\xF7\x2C\x9D\x62\x1C\xF6\xAD\x7C\xDD\xA6\x31\x1E\xB6\xB1\xC7\x7E\x85\x26\xFA\xA4\x6A\xB5\xDA\x63\x30\xD1\xEF\x93\x37\xB2\x66\x2F\x7D\x05\xF7\xE7\xB7\x4B\x98\x94\x35\xC0\xD9\x3A\x29\xC1\x9D\xB2\x50\x33\x1D\x4A\xA9\x5A\xA6\xC9\x03\xEF\xED\xF4\xE7\xA8\x6E\x8A\xB4\x57\x84\xEB\xA4\x3F\xD0\xEE\xAA\xAA\x87\x5B\x63\xE8\x93\xE2\x6B\xA8\xD4\xB8\x72\x78\x6B\x1B\xED\x39\xE4\x5D\xCB\x9B\xAA\x87\xD5\x4F\x4E\x00\xFE\xD9\x6A\x9F\x3C\x31\x0F\x28\x02\x01\x7D\x98\xE8\xA7\xB0\xA2\x64\x9E\x79\xF8\x48\xF2\x15\xA9\xCC\xE6\xC8\x44\xEB\x3F\x78\x99\xF2\x7B\x71\x3E\x3C\xF1\x98\xA7\xC5\x18\x12\x3F\xE6\xBB\x28\x33\x42\xE9\x45\x0A\x7C\x6D\xF2\x86\x79\x2F\xC5\x82\x19\x7D\x09\x89\x7C\xB2\x54\x76\x88\xAE\xDE\xC1\xF3\xCC\xE1\x6E\xDB\x31\xD6\x93\xAE\x99\xA0\xEF\x25\x6A\x73\x98\x89\x5B\x3A\x2E\x13\x88\x1E\xBF\xC0\x92\x94\x34\x1B\xE3\x27\xB7\x8B\x1E\x6F\x42\xFF\xE7\xE9\x37\x9B\x50\x1D\x2D\xA2\xF9\x02\xEE\xCB\x58\x58\x3A\x71\xBC\x68\xE3\xAA\xC1\xAF\x1C\x28\x1F\xA2\xDC\x23\x65\x3F\x81\xEA\xAE\x99\xD3\xD8\x30\xCF\x13\x0D\x4F\x15\xC9\x84\xBC\xA7\x48\x2D\xF8\x30\x23\x77\xD8\x46\x4B\x79\x6D\xF6\x8C\xED\x3A\x7F\x60\x11\x78\xF4\xE9\x9B\xAE\xD5\x54\xC0\x74\x80\xD1\x0B\x42\x9F\xC1", - ["Go Daddy Root Certificate Authority - G2"] = "\x30\x82\x03\xC5\x30\x82\x02\xAD\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x83\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7A\x6F\x6E\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x53\x63\x6F\x74\x74\x73\x64\x61\x6C\x65\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x13\x11\x47\x6F\x44\x61\x64\x64\x79\x2E\x63\x6F\x6D\x2C\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x03\x13\x28\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x39\x30\x39\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x83\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7A\x6F\x6E\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x53\x63\x6F\x74\x74\x73\x64\x61\x6C\x65\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x13\x11\x47\x6F\x44\x61\x64\x64\x79\x2E\x63\x6F\x6D\x2C\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x03\x13\x28\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\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\x71\x62\x08\xF1\xFA\x59\x34\xF7\x1B\xC9\x18\xA3\xF7\x80\x49\x58\xE9\x22\x83\x13\xA6\xC5\x20\x43\x01\x3B\x84\xF1\xE6\x85\x49\x9F\x27\xEA\xF6\x84\x1B\x4E\xA0\xB4\xDB\x70\x98\xC7\x32\x01\xB1\x05\x3E\x07\x4E\xEE\xF4\xFA\x4F\x2F\x59\x30\x22\xE7\xAB\x19\x56\x6B\xE2\x80\x07\xFC\xF3\x16\x75\x80\x39\x51\x7B\xE5\xF9\x35\xB6\x74\x4E\xA9\x8D\x82\x13\xE4\xB6\x3F\xA9\x03\x83\xFA\xA2\xBE\x8A\x15\x6A\x7F\xDE\x0B\xC3\xB6\x19\x14\x05\xCA\xEA\xC3\xA8\x04\x94\x3B\x46\x7C\x32\x0D\xF3\x00\x66\x22\xC8\x8D\x69\x6D\x36\x8C\x11\x18\xB7\xD3\xB2\x1C\x60\xB4\x38\xFA\x02\x8C\xCE\xD3\xDD\x46\x07\xDE\x0A\x3E\xEB\x5D\x7C\xC8\x7C\xFB\xB0\x2B\x53\xA4\x92\x62\x69\x51\x25\x05\x61\x1A\x44\x81\x8C\x2C\xA9\x43\x96\x23\xDF\xAC\x3A\x81\x9A\x0E\x29\xC5\x1C\xA9\xE9\x5D\x1E\xB6\x9E\x9E\x30\x0A\x39\xCE\xF1\x88\x80\xFB\x4B\x5D\xCC\x32\xEC\x85\x62\x43\x25\x34\x02\x56\x27\x01\x91\xB4\x3B\x70\x2A\x3F\x6E\xB1\xE8\x9C\x88\x01\x7D\x9F\xD4\xF9\xDB\x53\x6D\x60\x9D\xBF\x2C\xE7\x58\xAB\xB8\x5F\x46\xFC\xCE\xC4\x1B\x03\x3C\x09\xEB\x49\x31\x5C\x69\x46\xB3\xE0\x47\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x3A\x9A\x85\x07\x10\x67\x28\xB6\xEF\xF6\xBD\x05\x41\x6E\x20\xC1\x94\xDA\x0F\xDE\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x99\xDB\x5D\x79\xD5\xF9\x97\x59\x67\x03\x61\xF1\x7E\x3B\x06\x31\x75\x2D\xA1\x20\x8E\x4F\x65\x87\xB4\xF7\xA6\x9C\xBC\xD8\xE9\x2F\xD0\xDB\x5A\xEE\xCF\x74\x8C\x73\xB4\x38\x42\xDA\x05\x7B\xF8\x02\x75\xB8\xFD\xA5\xB1\xD7\xAE\xF6\xD7\xDE\x13\xCB\x53\x10\x7E\x8A\x46\xD1\x97\xFA\xB7\x2E\x2B\x11\xAB\x90\xB0\x27\x80\xF9\xE8\x9F\x5A\xE9\x37\x9F\xAB\xE4\xDF\x6C\xB3\x85\x17\x9D\x3D\xD9\x24\x4F\x79\x91\x35\xD6\x5F\x04\xEB\x80\x83\xAB\x9A\x02\x2D\xB5\x10\xF4\xD8\x90\xC7\x04\x73\x40\xED\x72\x25\xA0\xA9\x9F\xEC\x9E\xAB\x68\x12\x99\x57\xC6\x8F\x12\x3A\x09\xA4\xBD\x44\xFD\x06\x15\x37\xC1\x9B\xE4\x32\xA3\xED\x38\xE8\xD8\x64\xF3\x2C\x7E\x14\xFC\x02\xEA\x9F\xCD\xFF\x07\x68\x17\xDB\x22\x90\x38\x2D\x7A\x8D\xD1\x54\xF1\x69\xE3\x5F\x33\xCA\x7A\x3D\x7B\x0A\xE3\xCA\x7F\x5F\x39\xE5\xE2\x75\xBA\xC5\x76\x18\x33\xCE\x2C\xF0\x2F\x4C\xAD\xF7\xB1\xE7\xCE\x4F\xA8\xC4\x9B\x4A\x54\x06\xC5\x7F\x7D\xD5\x08\x0F\xE2\x1C\xFE\x7E\x17\xB8\xAC\x5E\xF6\xD4\x16\xB2\x43\x09\x0C\x4D\xF6\xA7\x6B\xB4\x99\x84\x65\xCA\x7A\x88\xE2\xE2\x44\xBE\x5C\xF7\xEA\x1C\xF5", - ["Starfield Root Certificate Authority - G2"] = "\x30\x82\x03\xDD\x30\x82\x02\xC5\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x8F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7A\x6F\x6E\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x53\x63\x6F\x74\x74\x73\x64\x61\x6C\x65\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x39\x30\x39\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x8F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7A\x6F\x6E\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x53\x63\x6F\x74\x74\x73\x64\x61\x6C\x65\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\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\xBD\xED\xC1\x03\xFC\xF6\x8F\xFC\x02\xB1\x6F\x5B\x9F\x48\xD9\x9D\x79\xE2\xA2\xB7\x03\x61\x56\x18\xC3\x47\xB6\xD7\xCA\x3D\x35\x2E\x89\x43\xF7\xA1\x69\x9B\xDE\x8A\x1A\xFD\x13\x20\x9C\xB4\x49\x77\x32\x29\x56\xFD\xB9\xEC\x8C\xDD\x22\xFA\x72\xDC\x27\x61\x97\xEE\xF6\x5A\x84\xEC\x6E\x19\xB9\x89\x2C\xDC\x84\x5B\xD5\x74\xFB\x6B\x5F\xC5\x89\xA5\x10\x52\x89\x46\x55\xF4\xB8\x75\x1C\xE6\x7F\xE4\x54\xAE\x4B\xF8\x55\x72\x57\x02\x19\xF8\x17\x71\x59\xEB\x1E\x28\x07\x74\xC5\x9D\x48\xBE\x6C\xB4\xF4\xA4\xB0\xF3\x64\x37\x79\x92\xC0\xEC\x46\x5E\x7F\xE1\x6D\x53\x4C\x62\xAF\xCD\x1F\x0B\x63\xBB\x3A\x9D\xFB\xFC\x79\x00\x98\x61\x74\xCF\x26\x82\x40\x63\xF3\xB2\x72\x6A\x19\x0D\x99\xCA\xD4\x0E\x75\xCC\x37\xFB\x8B\x89\xC1\x59\xF1\x62\x7F\x5F\xB3\x5F\x65\x30\xF8\xA7\xB7\x4D\x76\x5A\x1E\x76\x5E\x34\xC0\xE8\x96\x56\x99\x8A\xB3\xF0\x7F\xA4\xCD\xBD\xDC\x32\x31\x7C\x91\xCF\xE0\x5F\x11\xF8\x6B\xAA\x49\x5C\xD1\x99\x94\xD1\xA2\xE3\x63\x5B\x09\x76\xB5\x56\x62\xE1\x4B\x74\x1D\x96\xD4\x26\xD4\x08\x04\x59\xD0\x98\x0E\x0E\xE6\xDE\xFC\xC3\xEC\x1F\x90\xF1\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x7C\x0C\x32\x1F\xA7\xD9\x30\x7F\xC4\x7D\x68\xA3\x62\xA8\xA1\xCE\xAB\x07\x5B\x27\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x11\x59\xFA\x25\x4F\x03\x6F\x94\x99\x3B\x9A\x1F\x82\x85\x39\xD4\x76\x05\x94\x5E\xE1\x28\x93\x6D\x62\x5D\x09\xC2\xA0\xA8\xD4\xB0\x75\x38\xF1\x34\x6A\x9D\xE4\x9F\x8A\x86\x26\x51\xE6\x2C\xD1\xC6\x2D\x6E\x95\x20\x4A\x92\x01\xEC\xB8\x8A\x67\x7B\x31\xE2\x67\x2E\x8C\x95\x03\x26\x2E\x43\x9D\x4A\x31\xF6\x0E\xB5\x0C\xBB\xB7\xE2\x37\x7F\x22\xBA\x00\xA3\x0E\x7B\x52\xFB\x6B\xBB\x3B\xC4\xD3\x79\x51\x4E\xCD\x90\xF4\x67\x07\x19\xC8\x3C\x46\x7A\x0D\x01\x7D\xC5\x58\xE7\x6D\xE6\x85\x30\x17\x9A\x24\xC4\x10\xE0\x04\xF7\xE0\xF2\x7F\xD4\xAA\x0A\xFF\x42\x1D\x37\xED\x94\xE5\x64\x59\x12\x20\x77\x38\xD3\x32\x3E\x38\x81\x75\x96\x73\xFA\x68\x8F\xB1\xCB\xCE\x1F\xC5\xEC\xFA\x9C\x7E\xCF\x7E\xB1\xF1\x07\x2D\xB6\xFC\xBF\xCA\xA4\xBF\xD0\x97\x05\x4A\xBC\xEA\x18\x28\x02\x90\xBD\x54\x78\x09\x21\x71\xD3\xD1\x7D\x1D\xD9\x16\xB0\xA9\x61\x3D\xD0\x0A\x00\x22\xFC\xC7\x7B\xCB\x09\x64\x45\x0B\x3B\x40\x81\xF7\x7D\x7C\x32\xF5\x98\xCA\x58\x8E\x7D\x2A\xEE\x90\x59\x73\x64\xF9\x36\x74\x5E\x25\xA1\xF5\x66\x05\x2E\x7F\x39\x15\xA9\x2A\xFB\x50\x8B\x8E\x85\x69\xF4", - ["Starfield Services Root Certificate Authority - G2"] = "\x30\x82\x03\xEF\x30\x82\x02\xD7\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x98\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7A\x6F\x6E\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x53\x63\x6F\x74\x74\x73\x64\x61\x6C\x65\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x3B\x30\x39\x06\x03\x55\x04\x03\x13\x32\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x39\x30\x39\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x98\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7A\x6F\x6E\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x53\x63\x6F\x74\x74\x73\x64\x61\x6C\x65\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x3B\x30\x39\x06\x03\x55\x04\x03\x13\x32\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\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\xD5\x0C\x3A\xC4\x2A\xF9\x4E\xE2\xF5\xBE\x19\x97\x5F\x8E\x88\x53\xB1\x1F\x3F\xCB\xCF\x9F\x20\x13\x6D\x29\x3A\xC8\x0F\x7D\x3C\xF7\x6B\x76\x38\x63\xD9\x36\x60\xA8\x9B\x5E\x5C\x00\x80\xB2\x2F\x59\x7F\xF6\x87\xF9\x25\x43\x86\xE7\x69\x1B\x52\x9A\x90\xE1\x71\xE3\xD8\x2D\x0D\x4E\x6F\xF6\xC8\x49\xD9\xB6\xF3\x1A\x56\xAE\x2B\xB6\x74\x14\xEB\xCF\xFB\x26\xE3\x1A\xBA\x1D\x96\x2E\x6A\x3B\x58\x94\x89\x47\x56\xFF\x25\xA0\x93\x70\x53\x83\xDA\x84\x74\x14\xC3\x67\x9E\x04\x68\x3A\xDF\x8E\x40\x5A\x1D\x4A\x4E\xCF\x43\x91\x3B\xE7\x56\xD6\x00\x70\xCB\x52\xEE\x7B\x7D\xAE\x3A\xE7\xBC\x31\xF9\x45\xF6\xC2\x60\xCF\x13\x59\x02\x2B\x80\xCC\x34\x47\xDF\xB9\xDE\x90\x65\x6D\x02\xCF\x2C\x91\xA6\xA6\xE7\xDE\x85\x18\x49\x7C\x66\x4E\xA3\x3A\x6D\xA9\xB5\xEE\x34\x2E\xBA\x0D\x03\xB8\x33\xDF\x47\xEB\xB1\x6B\x8D\x25\xD9\x9B\xCE\x81\xD1\x45\x46\x32\x96\x70\x87\xDE\x02\x0E\x49\x43\x85\xB6\x6C\x73\xBB\x64\xEA\x61\x41\xAC\xC9\xD4\x54\xDF\x87\x2F\xC7\x22\xB2\x26\xCC\x9F\x59\x54\x68\x9F\xFC\xBE\x2A\x2F\xC4\x55\x1C\x75\x40\x60\x17\x85\x02\x55\x39\x8B\x7F\x05\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9C\x5F\x00\xDF\xAA\x01\xD7\x30\x2B\x38\x88\xA2\xB8\x6D\x4A\x9C\xF2\x11\x91\x83\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x4B\x36\xA6\x84\x77\x69\xDD\x3B\x19\x9F\x67\x23\x08\x6F\x0E\x61\xC9\xFD\x84\xDC\x5F\xD8\x36\x81\xCD\xD8\x1B\x41\x2D\x9F\x60\xDD\xC7\x1A\x68\xD9\xD1\x6E\x86\xE1\x88\x23\xCF\x13\xDE\x43\xCF\xE2\x34\xB3\x04\x9D\x1F\x29\xD5\xBF\xF8\x5E\xC8\xD5\xC1\xBD\xEE\x92\x6F\x32\x74\xF2\x91\x82\x2F\xBD\x82\x42\x7A\xAD\x2A\xB7\x20\x7D\x4D\xBC\x7A\x55\x12\xC2\x15\xEA\xBD\xF7\x6A\x95\x2E\x6C\x74\x9F\xCF\x1C\xB4\xF2\xC5\x01\xA3\x85\xD0\x72\x3E\xAD\x73\xAB\x0B\x9B\x75\x0C\x6D\x45\xB7\x8E\x94\xAC\x96\x37\xB5\xA0\xD0\x8F\x15\x47\x0E\xE3\xE8\x83\xDD\x8F\xFD\xEF\x41\x01\x77\xCC\x27\xA9\x62\x85\x33\xF2\x37\x08\xEF\x71\xCF\x77\x06\xDE\xC8\x19\x1D\x88\x40\xCF\x7D\x46\x1D\xFF\x1E\xC7\xE1\xCE\xFF\x23\xDB\xC6\xFA\x8D\x55\x4E\xA9\x02\xE7\x47\x11\x46\x3E\xF4\xFD\xBD\x7B\x29\x26\xBB\xA9\x61\x62\x37\x28\xB6\x2D\x2A\xF6\x10\x86\x64\xC9\x70\xA7\xD2\xAD\xB7\x29\x70\x79\xEA\x3C\xDA\x63\x25\x9F\xFD\x68\xB7\x30\xEC\x70\xFB\x75\x8A\xB7\x6D\x60\x67\xB2\x1E\xC8\xB9\xE9\xD8\xA8\x6F\x02\x8B\x67\x0D\x4D\x26\x57\x71\xDA\x20\xFC\xC1\x4A\x50\x8D\xB1\x28\xBA", - ["AffirmTrust Commercial"] = "\x30\x82\x03\x4C\x30\x82\x02\x34\xA0\x03\x02\x01\x02\x02\x08\x77\x77\x06\x27\x26\xA9\xB1\x7C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x44\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x0C\x16\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x43\x6F\x6D\x6D\x65\x72\x63\x69\x61\x6C\x30\x1E\x17\x0D\x31\x30\x30\x31\x32\x39\x31\x34\x30\x36\x30\x36\x5A\x17\x0D\x33\x30\x31\x32\x33\x31\x31\x34\x30\x36\x30\x36\x5A\x30\x44\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x0C\x16\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x43\x6F\x6D\x6D\x65\x72\x63\x69\x61\x6C\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\xF6\x1B\x4F\x67\x07\x2B\xA1\x15\xF5\x06\x22\xCB\x1F\x01\xB2\xE3\x73\x45\x06\x44\x49\x2C\xBB\x49\x25\x14\xD6\xCE\xC3\xB7\xAB\x2C\x4F\xC6\x41\x32\x94\x57\xFA\x12\xA7\x5B\x0E\xE2\x8F\x1F\x1E\x86\x19\xA7\xAA\xB5\x2D\xB9\x5F\x0D\x8A\xC2\xAF\x85\x35\x79\x32\x2D\xBB\x1C\x62\x37\xF2\xB1\x5B\x4A\x3D\xCA\xCD\x71\x5F\xE9\x42\xBE\x94\xE8\xC8\xDE\xF9\x22\x48\x64\xC6\xE5\xAB\xC6\x2B\x6D\xAD\x05\xF0\xFA\xD5\x0B\xCF\x9A\xE5\xF0\x50\xA4\x8B\x3B\x47\xA5\x23\x5B\x7A\x7A\xF8\x33\x3F\xB8\xEF\x99\x97\xE3\x20\xC1\xD6\x28\x89\xCF\x94\xFB\xB9\x45\xED\xE3\x40\x17\x11\xD4\x74\xF0\x0B\x31\xE2\x2B\x26\x6A\x9B\x4C\x57\xAE\xAC\x20\x3E\xBA\x45\x7A\x05\xF3\xBD\x9B\x69\x15\xAE\x7D\x4E\x20\x63\xC4\x35\x76\x3A\x07\x02\xC9\x37\xFD\xC7\x47\xEE\xE8\xF1\x76\x1D\x73\x15\xF2\x97\xA4\xB5\xC8\x7A\x79\xD9\x42\xAA\x2B\x7F\x5C\xFE\xCE\x26\x4F\xA3\x66\x81\x35\xAF\x44\xBA\x54\x1E\x1C\x30\x32\x65\x9D\xE6\x3C\x93\x5E\x50\x4E\x7A\xE3\x3A\xD4\x6E\xCC\x1A\xFB\xF9\xD2\x37\xAE\x24\x2A\xAB\x57\x03\x22\x28\x0D\x49\x75\x7F\xB7\x28\xDA\x75\xBF\x8E\xE3\xDC\x0E\x79\x31\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9D\x93\xC6\x53\x8B\x5E\xCA\xAF\x3F\x9F\x1E\x0F\xE5\x99\x95\xBC\x24\xF6\x94\x8F\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x58\xAC\xF4\x04\x0E\xCD\xC0\x0D\xFF\x0A\xFD\xD4\xBA\x16\x5F\x29\xBD\x7B\x68\x99\x58\x49\xD2\xB4\x1D\x37\x4D\x7F\x27\x7D\x46\x06\x5D\x43\xC6\x86\x2E\x3E\x73\xB2\x26\x7D\x4F\x93\xA9\xB6\xC4\x2A\x9A\xAB\x21\x97\x14\xB1\xDE\x8C\xD3\xAB\x89\x15\xD8\x6B\x24\xD4\xF1\x16\xAE\xD8\xA4\x5C\xD4\x7F\x51\x8E\xED\x18\x01\xB1\x93\x63\xBD\xBC\xF8\x61\x80\x9A\x9E\xB1\xCE\x42\x70\xE2\xA9\x7D\x06\x25\x7D\x27\xA1\xFE\x6F\xEC\xB3\x1E\x24\xDA\xE3\x4B\x55\x1A\x00\x3B\x35\xB4\x3B\xD9\xD7\x5D\x30\xFD\x81\x13\x89\xF2\xC2\x06\x2B\xED\x67\xC4\x8E\xC9\x43\xB2\x5C\x6B\x15\x89\x02\xBC\x62\xFC\x4E\xF2\xB5\x33\xAA\xB2\x6F\xD3\x0A\xA2\x50\xE3\xF6\x3B\xE8\x2E\x44\xC2\xDB\x66\x38\xA9\x33\x56\x48\xF1\x6D\x1B\x33\x8D\x0D\x8C\x3F\x60\x37\x9D\xD3\xCA\x6D\x7E\x34\x7E\x0D\x9F\x72\x76\x8B\x1B\x9F\x72\xFD\x52\x35\x41\x45\x02\x96\x2F\x1C\xB2\x9A\x73\x49\x21\xB1\x49\x47\x45\x47\xB4\xEF\x6A\x34\x11\xC9\x4D\x9A\xCC\x59\xB7\xD6\x02\x9E\x5A\x4E\x65\xB5\x94\xAE\x1B\xDF\x29\xB0\x16\xF1\xBF\x00\x9E\x07\x3A\x17\x64\xB5\x04\xB5\x23\x21\x99\x0A\x95\x3B\x97\x7C\xEF", - ["AffirmTrust Networking"] = "\x30\x82\x03\x4C\x30\x82\x02\x34\xA0\x03\x02\x01\x02\x02\x08\x7C\x4F\x04\x39\x1C\xD4\x99\x2D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x44\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x0C\x16\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x69\x6E\x67\x30\x1E\x17\x0D\x31\x30\x30\x31\x32\x39\x31\x34\x30\x38\x32\x34\x5A\x17\x0D\x33\x30\x31\x32\x33\x31\x31\x34\x30\x38\x32\x34\x5A\x30\x44\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x0C\x16\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x69\x6E\x67\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\xB4\x84\xCC\x33\x17\x2E\x6B\x94\x6C\x6B\x61\x52\xA0\xEB\xA3\xCF\x79\x94\x4C\xE5\x94\x80\x99\xCB\x55\x64\x44\x65\x8F\x67\x64\xE2\x06\xE3\x5C\x37\x49\xF6\x2F\x9B\x84\x84\x1E\x2D\xF2\x60\x9D\x30\x4E\xCC\x84\x85\xE2\x2C\xCF\x1E\x9E\xFE\x36\xAB\x33\x77\x35\x44\xD8\x35\x96\x1A\x3D\x36\xE8\x7A\x0E\xD8\xD5\x47\xA1\x6A\x69\x8B\xD9\xFC\xBB\x3A\xAE\x79\x5A\xD5\xF4\xD6\x71\xBB\x9A\x90\x23\x6B\x9A\xB7\x88\x74\x87\x0C\x1E\x5F\xB9\x9E\x2D\xFA\xAB\x53\x2B\xDC\xBB\x76\x3E\x93\x4C\x08\x08\x8C\x1E\xA2\x23\x1C\xD4\x6A\xAD\x22\xBA\x99\x01\x2E\x6D\x65\xCB\xBE\x24\x66\x55\x24\x4B\x40\x44\xB1\x1B\xD7\xE1\xC2\x85\xC0\xDE\x10\x3F\x3D\xED\xB8\xFC\xF1\xF1\x23\x53\xDC\xBF\x65\x97\x6F\xD9\xF9\x40\x71\x8D\x7D\xBD\x95\xD4\xCE\xBE\xA0\x5E\x27\x23\xDE\xFD\xA6\xD0\x26\x0E\x00\x29\xEB\x3C\x46\xF0\x3D\x60\xBF\x3F\x50\xD2\xDC\x26\x41\x51\x9E\x14\x37\x42\x04\xA3\x70\x57\xA8\x1B\x87\xED\x2D\xFA\x7B\xEE\x8C\x0A\xE3\xA9\x66\x89\x19\xCB\x41\xF9\xDD\x44\x36\x61\xCF\xE2\x77\x46\xC8\x7D\xF6\xF4\x92\x81\x36\xFD\xDB\x34\xF1\x72\x7E\xF3\x0C\x16\xBD\xB4\x15\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x07\x1F\xD2\xE7\x9C\xDA\xC2\x6E\xA2\x40\xB4\xB0\x7A\x50\x10\x50\x74\xC4\xC8\xBD\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x89\x57\xB2\x16\x7A\xA8\xC2\xFD\xD6\xD9\x9B\x9B\x34\xC2\x9C\xB4\x32\x14\x4D\xA7\xA4\xDF\xEC\xBE\xA7\xBE\xF8\x43\xDB\x91\x37\xCE\xB4\x32\x2E\x50\x55\x1A\x35\x4E\x76\x43\x71\x20\xEF\x93\x77\x4E\x15\x70\x2E\x87\xC3\xC1\x1D\x6D\xDC\xCB\xB5\x27\xD4\x2C\x56\xD1\x52\x53\x3A\x44\xD2\x73\xC8\xC4\x1B\x05\x65\x5A\x62\x92\x9C\xEE\x41\x8D\x31\xDB\xE7\x34\xEA\x59\x21\xD5\x01\x7A\xD7\x64\xB8\x64\x39\xCD\xC9\xED\xAF\xED\x4B\x03\x48\xA7\xA0\x99\x01\x80\xDC\x65\xA3\x36\xAE\x65\x59\x48\x4F\x82\x4B\xC8\x65\xF1\x57\x1D\xE5\x59\x2E\x0A\x3F\x6C\xD8\xD1\xF5\xE5\x09\xB4\x6C\x54\x00\x0A\xE0\x15\x4D\x87\x75\x6D\xB7\x58\x96\x5A\xDD\x6D\xD2\x00\xA0\xF4\x9B\x48\xBE\xC3\x37\xA4\xBA\x36\xE0\x7C\x87\x85\x97\x1A\x15\xA2\xDE\x2E\xA2\x5B\xBD\xAF\x18\xF9\x90\x50\xCD\x70\x59\xF8\x27\x67\x47\xCB\xC7\xA0\x07\x3A\x7D\xD1\x2C\x5D\x6C\x19\x3A\x66\xB5\x7D\xFD\x91\x6F\x82\xB1\xBE\x08\x93\xDB\x14\x47\xF1\xA2\x37\xC7\x45\x9E\x3C\xC7\x77\xAF\x64\xA8\x93\xDF\xF6\x69\x83\x82\x60\xF2\x49\x42\x34\xED\x5A\x00\x54\x85\x1C\x16\x36\x92\x0C\x5C\xFA\xA6\xAD\xBF\xDB", - ["AffirmTrust Premium"] = "\x30\x82\x05\x46\x30\x82\x03\x2E\xA0\x03\x02\x01\x02\x02\x08\x6D\x8C\x14\x46\xB1\xA6\x0A\xEE\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0C\x05\x00\x30\x41\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x1C\x30\x1A\x06\x03\x55\x04\x03\x0C\x13\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x50\x72\x65\x6D\x69\x75\x6D\x30\x1E\x17\x0D\x31\x30\x30\x31\x32\x39\x31\x34\x31\x30\x33\x36\x5A\x17\x0D\x34\x30\x31\x32\x33\x31\x31\x34\x31\x30\x33\x36\x5A\x30\x41\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x1C\x30\x1A\x06\x03\x55\x04\x03\x0C\x13\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x50\x72\x65\x6D\x69\x75\x6D\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC4\x12\xDF\xA9\x5F\xFE\x41\xDD\xDD\xF5\x9F\x8A\xE3\xF6\xAC\xE1\x3C\x78\x9A\xBC\xD8\xF0\x7F\x7A\xA0\x33\x2A\xDC\x8D\x20\x5B\xAE\x2D\x6F\xE7\x93\xD9\x36\x70\x6A\x68\xCF\x8E\x51\xA3\x85\x5B\x67\x04\xA0\x10\x24\x6F\x5D\x28\x82\xC1\x97\x57\xD8\x48\x29\x13\xB6\xE1\xBE\x91\x4D\xDF\x85\x0C\x53\x18\x9A\x1E\x24\xA2\x4F\x8F\xF0\xA2\x85\x0B\xCB\xF4\x29\x7F\xD2\xA4\x58\xEE\x26\x4D\xC9\xAA\xA8\x7B\x9A\xD9\xFA\x38\xDE\x44\x57\x15\xE5\xF8\x8C\xC8\xD9\x48\xE2\x0D\x16\x27\x1D\x1E\xC8\x83\x85\x25\xB7\xBA\xAA\x55\x41\xCC\x03\x22\x4B\x2D\x91\x8D\x8B\xE6\x89\xAF\x66\xC7\xE9\xFF\x2B\xE9\x3C\xAC\xDA\xD2\xB3\xC3\xE1\x68\x9C\x89\xF8\x7A\x00\x56\xDE\xF4\x55\x95\x6C\xFB\xBA\x64\xDD\x62\x8B\xDF\x0B\x77\x32\xEB\x62\xCC\x26\x9A\x9B\xBB\xAA\x62\x83\x4C\xB4\x06\x7A\x30\xC8\x29\xBF\xED\x06\x4D\x97\xB9\x1C\xC4\x31\x2B\xD5\x5F\xBC\x53\x12\x17\x9C\x99\x57\x29\x66\x77\x61\x21\x31\x07\x2E\x25\x49\x9D\x18\xF2\xEE\xF3\x2B\x71\x8C\xB5\xBA\x39\x07\x49\x77\xFC\xEF\x2E\x92\x90\x05\x8D\x2D\x2F\x77\x7B\xEF\x43\xBF\x35\xBB\x9A\xD8\xF9\x73\xA7\x2C\xF2\xD0\x57\xEE\x28\x4E\x26\x5F\x8F\x90\x68\x09\x2F\xB8\xF8\xDC\x06\xE9\x2E\x9A\x3E\x51\xA7\xD1\x22\xC4\x0A\xA7\x38\x48\x6C\xB3\xF9\xFF\x7D\xAB\x86\x57\xE3\xBA\xD6\x85\x78\x77\xBA\x43\xEA\x48\x7F\xF6\xD8\xBE\x23\x6D\x1E\xBF\xD1\x36\x6C\x58\x5C\xF1\xEE\xA4\x19\x54\x1A\xF5\x03\xD2\x76\xE6\xE1\x8C\xBD\x3C\xB3\xD3\x48\x4B\xE2\xC8\xF8\x7F\x92\xA8\x76\x46\x9C\x42\x65\x3E\xA4\x1E\xC1\x07\x03\x5A\x46\x2D\xB8\x97\xF3\xB7\xD5\xB2\x55\x21\xEF\xBA\xDC\x4C\x00\x97\xFB\x14\x95\x27\x33\xBF\xE8\x43\x47\x46\xD2\x08\x99\x16\x60\x3B\x9A\x7E\xD2\xE6\xED\x38\xEA\xEC\x01\x1E\x3C\x48\x56\x49\x09\xC7\x4C\x37\x00\x9E\x88\x0E\xC0\x73\xE1\x6F\x66\xE9\x72\x47\x30\x3E\x10\xE5\x0B\x03\xC9\x9A\x42\x00\x6C\xC5\x94\x7E\x61\xC4\x8A\xDF\x7F\x82\x1A\x0B\x59\xC4\x59\x32\x77\xB3\xBC\x60\x69\x56\x39\xFD\xB4\x06\x7B\x2C\xD6\x64\x36\xD9\xBD\x48\xED\x84\x1F\x7E\xA5\x22\x8F\x2A\xB8\x42\xF4\x82\xB7\xD4\x53\x90\x78\x4E\x2D\x1A\xFD\x81\x6F\x44\xD7\x3B\x01\x74\x96\x42\xE0\x00\xE2\x2E\x6B\xEA\xC5\xEE\x72\xAC\xBB\xBF\xFE\xEA\xAA\xA8\xF8\xDC\xF6\xB2\x79\x8A\xB6\x67\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9D\xC0\x67\xA6\x0C\x22\xD9\x26\xF5\x45\xAB\xA6\x65\x52\x11\x27\xD8\x45\xAC\x63\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0C\x05\x00\x03\x82\x02\x01\x00\xB3\x57\x4D\x10\x62\x4E\x3A\xE4\xAC\xEA\xB8\x1C\xAF\x32\x23\xC8\xB3\x49\x5A\x51\x9C\x76\x28\x8D\x79\xAA\x57\x46\x17\xD5\xF5\x52\xF6\xB7\x44\xE8\x08\x44\xBF\x18\x84\xD2\x0B\x80\xCD\xC5\x12\xFD\x00\x55\x05\x61\x87\x41\xDC\xB5\x24\x9E\x3C\xC4\xD8\xC8\xFB\x70\x9E\x2F\x78\x96\x83\x20\x36\xDE\x7C\x0F\x69\x13\x88\xA5\x75\x36\x98\x08\xA6\xC6\xDF\xAC\xCE\xE3\x58\xD6\xB7\x3E\xDE\xBA\xF3\xEB\x34\x40\xD8\xA2\x81\xF5\x78\x3F\x2F\xD5\xA5\xFC\xD9\xA2\xD4\x5E\x04\x0E\x17\xAD\xFE\x41\xF0\xE5\xB2\x72\xFA\x44\x82\x33\x42\xE8\x2D\x58\xF7\x56\x8C\x62\x3F\xBA\x42\xB0\x9C\x0C\x5C\x7E\x2E\x65\x26\x5C\x53\x4F\x00\xB2\x78\x7E\xA1\x0D\x99\x2D\x8D\xB8\x1D\x8E\xA2\xC4\xB0\xFD\x60\xD0\x30\xA4\x8E\xC8\x04\x62\xA9\xC4\xED\x35\xDE\x7A\x97\xED\x0E\x38\x5E\x92\x2F\x93\x70\xA5\xA9\x9C\x6F\xA7\x7D\x13\x1D\x7E\xC6\x08\x48\xB1\x5E\x67\xEB\x51\x08\x25\xE9\xE6\x25\x6B\x52\x29\x91\x9C\xD2\x39\x73\x08\x57\xDE\x99\x06\xB4\x5B\x9D\x10\x06\xE1\xC2\x00\xA8\xB8\x1C\x4A\x02\x0A\x14\xD0\xC1\x41\xCA\xFB\x8C\x35\x21\x7D\x82\x38\xF2\xA9\x54\x91\x19\x35\x93\x94\x6D\x6A\x3A\xC5\xB2\xD0\xBB\x89\x86\x93\xE8\x9B\xC9\x0F\x3A\xA7\x7A\xB8\xA1\xF0\x78\x46\xFA\xFC\x37\x2F\xE5\x8A\x84\xF3\xDF\xFE\x04\xD9\xA1\x68\xA0\x2F\x24\xE2\x09\x95\x06\xD5\x95\xCA\xE1\x24\x96\xEB\x7C\xF6\x93\x05\xBB\xED\x73\xE9\x2D\xD1\x75\x39\xD7\xE7\x24\xDB\xD8\x4E\x5F\x43\x8F\x9E\xD0\x14\x39\xBF\x55\x70\x48\x99\x57\x31\xB4\x9C\xEE\x4A\x98\x03\x96\x30\x1F\x60\x06\xEE\x1B\x23\xFE\x81\x60\x23\x1A\x47\x62\x85\xA5\xCC\x19\x34\x80\x6F\xB3\xAC\x1A\xE3\x9F\xF0\x7B\x48\xAD\xD5\x01\xD9\x67\xB6\xA9\x72\x93\xEA\x2D\x66\xB5\xB2\xB8\xE4\x3D\x3C\xB2\xEF\x4C\x8C\xEA\xEB\x07\xBF\xAB\x35\x9A\x55\x86\xBC\x18\xA6\xB5\xA8\x5E\xB4\x83\x6C\x6B\x69\x40\xD3\x9F\xDC\xF1\xC3\x69\x6B\xB9\xE1\x6D\x09\xF4\xF1\xAA\x50\x76\x0A\x7A\x7D\x7A\x17\xA1\x55\x96\x42\x99\x31\x09\xDD\x60\x11\x8D\x05\x30\x7E\xE6\x8E\x46\xD1\x9D\x14\xDA\xC7\x17\xE4\x05\x96\x8C\xC4\x24\xB5\x1B\xCF\x14\x07\xB2\x40\xF8\xA3\x9E\x41\x86\xBC\x04\xD0\x6B\x96\xC8\x2A\x80\x34\xFD\xBF\xEF\x06\xA3\xDD\x58\xC5\x85\x3D\x3E\x8F\xFE\x9E\x29\xE0\xB6\xB8\x09\x68\x19\x1C\x18\x43", - ["AffirmTrust Premium ECC"] = "\x30\x82\x01\xFE\x30\x82\x01\x85\xA0\x03\x02\x01\x02\x02\x08\x74\x97\x25\x8A\xC7\x3F\x7A\x54\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x0C\x17\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x50\x72\x65\x6D\x69\x75\x6D\x20\x45\x43\x43\x30\x1E\x17\x0D\x31\x30\x30\x31\x32\x39\x31\x34\x32\x30\x32\x34\x5A\x17\x0D\x34\x30\x31\x32\x33\x31\x31\x34\x32\x30\x32\x34\x5A\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x0C\x17\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x50\x72\x65\x6D\x69\x75\x6D\x20\x45\x43\x43\x30\x76\x30\x10\x06\x07\x2A\x86\x48\xCE\x3D\x02\x01\x06\x05\x2B\x81\x04\x00\x22\x03\x62\x00\x04\x0D\x30\x5E\x1B\x15\x9D\x03\xD0\xA1\x79\x35\xB7\x3A\x3C\x92\x7A\xCA\x15\x1C\xCD\x62\xF3\x9C\x26\x5C\x07\x3D\xE5\x54\xFA\xA3\xD6\xCC\x12\xEA\xF4\x14\x5F\xE8\x8E\x19\xAB\x2F\x2E\x48\xE6\xAC\x18\x43\x78\xAC\xD0\x37\xC3\xBD\xB2\xCD\x2C\xE6\x47\xE2\x1A\xE6\x63\xB8\x3D\x2E\x2F\x78\xC4\x4F\xDB\xF4\x0F\xA4\x68\x4C\x55\x72\x6B\x95\x1D\x4E\x18\x42\x95\x78\xCC\x37\x3C\x91\xE2\x9B\x65\x2B\x29\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9A\xAF\x29\x7A\xC0\x11\x35\x35\x26\x51\x30\x00\xC3\x6A\xFE\x40\xD5\xAE\xD6\x3C\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x03\x67\x00\x30\x64\x02\x30\x17\x09\xF3\x87\x88\x50\x5A\xAF\xC8\xC0\x42\xBF\x47\x5F\xF5\x6C\x6A\x86\xE0\xC4\x27\x74\xE4\x38\x53\xD7\x05\x7F\x1B\x34\xE3\xC6\x2F\xB3\xCA\x09\x3C\x37\x9D\xD7\xE7\xB8\x46\xF1\xFD\xA1\xE2\x71\x02\x30\x42\x59\x87\x43\xD4\x51\xDF\xBA\xD3\x09\x32\x5A\xCE\x88\x7E\x57\x3D\x9C\x5F\x42\x6B\xF5\x07\x2D\xB5\xF0\x82\x93\xF9\x59\x6F\xAE\x64\xFA\x58\xE5\x8B\x1E\xE3\x63\xBE\xB5\x81\xCD\x6F\x02\x8C\x79", - ["Certum Trusted Network CA"] = "\x30\x82\x03\xBB\x30\x82\x02\xA3\xA0\x03\x02\x01\x02\x02\x03\x04\x44\xC0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x50\x4C\x31\x22\x30\x20\x06\x03\x55\x04\x0A\x13\x19\x55\x6E\x69\x7A\x65\x74\x6F\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x20\x53\x2E\x41\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x0B\x13\x1E\x43\x65\x72\x74\x75\x6D\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x43\x65\x72\x74\x75\x6D\x20\x54\x72\x75\x73\x74\x65\x64\x20\x4E\x65\x74\x77\x6F\x72\x6B\x20\x43\x41\x30\x1E\x17\x0D\x30\x38\x31\x30\x32\x32\x31\x32\x30\x37\x33\x37\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x31\x32\x30\x37\x33\x37\x5A\x30\x7E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x50\x4C\x31\x22\x30\x20\x06\x03\x55\x04\x0A\x13\x19\x55\x6E\x69\x7A\x65\x74\x6F\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x20\x53\x2E\x41\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x0B\x13\x1E\x43\x65\x72\x74\x75\x6D\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x43\x65\x72\x74\x75\x6D\x20\x54\x72\x75\x73\x74\x65\x64\x20\x4E\x65\x74\x77\x6F\x72\x6B\x20\x43\x41\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\xE3\xFB\x7D\xA3\x72\xBA\xC2\xF0\xC9\x14\x87\xF5\x6B\x01\x4E\xE1\x6E\x40\x07\xBA\x6D\x27\x5D\x7F\xF7\x5B\x2D\xB3\x5A\xC7\x51\x5F\xAB\xA4\x32\xA6\x61\x87\xB6\x6E\x0F\x86\xD2\x30\x02\x97\xF8\xD7\x69\x57\xA1\x18\x39\x5D\x6A\x64\x79\xC6\x01\x59\xAC\x3C\x31\x4A\x38\x7C\xD2\x04\xD2\x4B\x28\xE8\x20\x5F\x3B\x07\xA2\xCC\x4D\x73\xDB\xF3\xAE\x4F\xC7\x56\xD5\x5A\xA7\x96\x89\xFA\xF3\xAB\x68\xD4\x23\x86\x59\x27\xCF\x09\x27\xBC\xAC\x6E\x72\x83\x1C\x30\x72\xDF\xE0\xA2\xE9\xD2\xE1\x74\x75\x19\xBD\x2A\x9E\x7B\x15\x54\x04\x1B\xD7\x43\x39\xAD\x55\x28\xC5\xE2\x1A\xBB\xF4\xC0\xE4\xAE\x38\x49\x33\xCC\x76\x85\x9F\x39\x45\xD2\xA4\x9E\xF2\x12\x8C\x51\xF8\x7C\xE4\x2D\x7F\xF5\xAC\x5F\xEB\x16\x9F\xB1\x2D\xD1\xBA\xCC\x91\x42\x77\x4C\x25\xC9\x90\x38\x6F\xDB\xF0\xCC\xFB\x8E\x1E\x97\x59\x3E\xD5\x60\x4E\xE6\x05\x28\xED\x49\x79\x13\x4B\xBA\x48\xDB\x2F\xF9\x72\xD3\x39\xCA\xFE\x1F\xD8\x34\x72\xF5\xB4\x40\xCF\x31\x01\xC3\xEC\xDE\x11\x2D\x17\x5D\x1F\xB8\x50\xD1\x5E\x19\xA7\x69\xDE\x07\x33\x28\xCA\x50\x95\xF9\xA7\x54\xCB\x54\x86\x50\x45\xA9\xF9\x49\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x08\x76\xCD\xCB\x07\xFF\x24\xF6\xC5\xCD\xED\xBB\x90\xBC\xE2\x84\x37\x46\x75\xF7\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA6\xA8\xAD\x22\xCE\x01\x3D\xA6\xA3\xFF\x62\xD0\x48\x9D\x8B\x5E\x72\xB0\x78\x44\xE3\xDC\x1C\xAF\x09\xFD\x23\x48\xFA\xBD\x2A\xC4\xB9\x55\x04\xB5\x10\xA3\x8D\x27\xDE\x0B\x82\x63\xD0\xEE\xDE\x0C\x37\x79\x41\x5B\x22\xB2\xB0\x9A\x41\x5C\xA6\x70\xE0\xD4\xD0\x77\xCB\x23\xD3\x00\xE0\x6C\x56\x2F\xE1\x69\x0D\x0D\xD9\xAA\xBF\x21\x81\x50\xD9\x06\xA5\xA8\xFF\x95\x37\xD0\xAA\xFE\xE2\xB3\xF5\x99\x2D\x45\x84\x8A\xE5\x42\x09\xD7\x74\x02\x2F\xF7\x89\xD8\x99\xE9\xBC\x27\xD4\x47\x8D\xBA\x0D\x46\x1C\x77\xCF\x14\xA4\x1C\xB9\xA4\x31\xC4\x9C\x28\x74\x03\x34\xFF\x33\x19\x26\xA5\xE9\x0D\x74\xB7\x3E\x97\xC6\x76\xE8\x27\x96\xA3\x66\xDD\xE1\xAE\xF2\x41\x5B\xCA\x98\x56\x83\x73\x70\xE4\x86\x1A\xD2\x31\x41\xBA\x2F\xBE\x2D\x13\x5A\x76\x6F\x4E\xE8\x4E\x81\x0E\x3F\x5B\x03\x22\xA0\x12\xBE\x66\x58\x11\x4A\xCB\x03\xC4\xB4\x2A\x2A\x2D\x96\x17\xE0\x39\x54\xBC\x48\xD3\x76\x27\x9D\x9A\x2D\x06\xA6\xC9\xEC\x39\xD2\xAB\xDB\x9F\x9A\x0B\x27\x02\x35\x29\xB1\x40\x95\xE7\xF9\xE8\x9C\x55\x88\x19\x46\xD6\xB7\x34\xF5\x7E\xCE\x39\x9A\xD9\x38\xF1\x51\xF7\x4F\x2C", + ["CN=GTE CyberTrust Global Root,OU=GTE CyberTrust Solutions\, Inc.,O=GTE Corporation,C=US"] = "\x30\x82\x02\x5A\x30\x82\x01\xC3\x02\x02\x01\xA5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x13\x0F\x47\x54\x45\x20\x43\x6F\x72\x70\x6F\x72\x61\x74\x69\x6F\x6E\x31\x27\x30\x25\x06\x03\x55\x04\x0B\x13\x1E\x47\x54\x45\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x2C\x20\x49\x6E\x63\x2E\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x47\x54\x45\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x39\x38\x30\x38\x31\x33\x30\x30\x32\x39\x30\x30\x5A\x17\x0D\x31\x38\x30\x38\x31\x33\x32\x33\x35\x39\x30\x30\x5A\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x13\x0F\x47\x54\x45\x20\x43\x6F\x72\x70\x6F\x72\x61\x74\x69\x6F\x6E\x31\x27\x30\x25\x06\x03\x55\x04\x0B\x13\x1E\x47\x54\x45\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x2C\x20\x49\x6E\x63\x2E\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x47\x54\x45\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\x95\x0F\xA0\xB6\xF0\x50\x9C\xE8\x7A\xC7\x88\xCD\xDD\x17\x0E\x2E\xB0\x94\xD0\x1B\x3D\x0E\xF6\x94\xC0\x8A\x94\xC7\x06\xC8\x90\x97\xC8\xB8\x64\x1A\x7A\x7E\x6C\x3C\x53\xE1\x37\x28\x73\x60\x7F\xB2\x97\x53\x07\x9F\x53\xF9\x6D\x58\x94\xD2\xAF\x8D\x6D\x88\x67\x80\xE6\xED\xB2\x95\xCF\x72\x31\xCA\xA5\x1C\x72\xBA\x5C\x02\xE7\x64\x42\xE7\xF9\xA9\x2C\xD6\x3A\x0D\xAC\x8D\x42\xAA\x24\x01\x39\xE6\x9C\x3F\x01\x85\x57\x0D\x58\x87\x45\xF8\xD3\x85\xAA\x93\x69\x26\x85\x70\x48\x80\x3F\x12\x15\xC7\x79\xB4\x1F\x05\x2F\x3B\x62\x99\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x6D\xEB\x1B\x09\xE9\x5E\xD9\x51\xDB\x67\x22\x61\xA4\x2A\x3C\x48\x77\xE3\xA0\x7C\xA6\xDE\x73\xA2\x14\x03\x85\x3D\xFB\xAB\x0E\x30\xC5\x83\x16\x33\x81\x13\x08\x9E\x7B\x34\x4E\xDF\x40\xC8\x74\xD7\xB9\x7D\xDC\xF4\x76\x55\x7D\x9B\x63\x54\x18\xE9\xF0\xEA\xF3\x5C\xB1\xD9\x8B\x42\x1E\xB9\xC0\x95\x4E\xBA\xFA\xD5\xE2\x7C\xF5\x68\x61\xBF\x8E\xEC\x05\x97\x5F\x5B\xB0\xD7\xA3\x85\x34\xC4\x24\xA7\x0D\x0F\x95\x93\xEF\xCB\x94\xD8\x9E\x1F\x9D\x5C\x85\x6D\xC7\xAA\xAE\x4F\x1F\x22\xB5\xCD\x95\xAD\xBA\xA7\xCC\xF9\xAB\x0B\x7A\x7F", + ["emailAddress=server-certs@thawte.com,CN=Thawte Server CA,OU=Certification Services Division,O=Thawte Consulting cc,L=Cape Town,ST=Western Cape,C=ZA"] = "\x30\x82\x03\x13\x30\x82\x02\x7C\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\xC4\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5A\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0C\x57\x65\x73\x74\x65\x72\x6E\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6F\x77\x6E\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6F\x6E\x73\x75\x6C\x74\x69\x6E\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x54\x68\x61\x77\x74\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x26\x30\x24\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x17\x73\x65\x72\x76\x65\x72\x2D\x63\x65\x72\x74\x73\x40\x74\x68\x61\x77\x74\x65\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x39\x36\x30\x38\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x30\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xC4\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5A\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0C\x57\x65\x73\x74\x65\x72\x6E\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6F\x77\x6E\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6F\x6E\x73\x75\x6C\x74\x69\x6E\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x54\x68\x61\x77\x74\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x26\x30\x24\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x17\x73\x65\x72\x76\x65\x72\x2D\x63\x65\x72\x74\x73\x40\x74\x68\x61\x77\x74\x65\x2E\x63\x6F\x6D\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xD3\xA4\x50\x6E\xC8\xFF\x56\x6B\xE6\xCF\x5D\xB6\xEA\x0C\x68\x75\x47\xA2\xAA\xC2\xDA\x84\x25\xFC\xA8\xF4\x47\x51\xDA\x85\xB5\x20\x74\x94\x86\x1E\x0F\x75\xC9\xE9\x08\x61\xF5\x06\x6D\x30\x6E\x15\x19\x02\xE9\x52\xC0\x62\xDB\x4D\x99\x9E\xE2\x6A\x0C\x44\x38\xCD\xFE\xBE\xE3\x64\x09\x70\xC5\xFE\xB1\x6B\x29\xB6\x2F\x49\xC8\x3B\xD4\x27\x04\x25\x10\x97\x2F\xE7\x90\x6D\xC0\x28\x42\x99\xD7\x4C\x43\xDE\xC3\xF5\x21\x6D\x54\x9F\x5D\xC3\x58\xE1\xC0\xE4\xD9\x5B\xB0\xB8\xDC\xB4\x7B\xDF\x36\x3A\xC2\xB5\x66\x22\x12\xD6\x87\x0D\x02\x03\x01\x00\x01\xA3\x13\x30\x11\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x07\xFA\x4C\x69\x5C\xFB\x95\xCC\x46\xEE\x85\x83\x4D\x21\x30\x8E\xCA\xD9\xA8\x6F\x49\x1A\xE6\xDA\x51\xE3\x60\x70\x6C\x84\x61\x11\xA1\x1A\xC8\x48\x3E\x59\x43\x7D\x4F\x95\x3D\xA1\x8B\xB7\x0B\x62\x98\x7A\x75\x8A\xDD\x88\x4E\x4E\x9E\x40\xDB\xA8\xCC\x32\x74\xB9\x6F\x0D\xC6\xE3\xB3\x44\x0B\xD9\x8A\x6F\x9A\x29\x9B\x99\x18\x28\x3B\xD1\xE3\x40\x28\x9A\x5A\x3C\xD5\xB5\xE7\x20\x1B\x8B\xCA\xA4\xAB\x8D\xE9\x51\xD9\xE2\x4C\x2C\x59\xA9\xDA\xB9\xB2\x75\x1B\xF6\x42\xF2\xEF\xC7\xF2\x18\xF9\x89\xBC\xA3\xFF\x8A\x23\x2E\x70\x47", + ["emailAddress=premium-server@thawte.com,CN=Thawte Premium Server CA,OU=Certification Services Division,O=Thawte Consulting cc,L=Cape Town,ST=Western Cape,C=ZA"] = "\x30\x82\x03\x27\x30\x82\x02\x90\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\xCE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5A\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0C\x57\x65\x73\x74\x65\x72\x6E\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6F\x77\x6E\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6F\x6E\x73\x75\x6C\x74\x69\x6E\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x72\x65\x6D\x69\x75\x6D\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x19\x70\x72\x65\x6D\x69\x75\x6D\x2D\x73\x65\x72\x76\x65\x72\x40\x74\x68\x61\x77\x74\x65\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x39\x36\x30\x38\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x30\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x5A\x41\x31\x15\x30\x13\x06\x03\x55\x04\x08\x13\x0C\x57\x65\x73\x74\x65\x72\x6E\x20\x43\x61\x70\x65\x31\x12\x30\x10\x06\x03\x55\x04\x07\x13\x09\x43\x61\x70\x65\x20\x54\x6F\x77\x6E\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x13\x14\x54\x68\x61\x77\x74\x65\x20\x43\x6F\x6E\x73\x75\x6C\x74\x69\x6E\x67\x20\x63\x63\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x54\x68\x61\x77\x74\x65\x20\x50\x72\x65\x6D\x69\x75\x6D\x20\x53\x65\x72\x76\x65\x72\x20\x43\x41\x31\x28\x30\x26\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x19\x70\x72\x65\x6D\x69\x75\x6D\x2D\x73\x65\x72\x76\x65\x72\x40\x74\x68\x61\x77\x74\x65\x2E\x63\x6F\x6D\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xD2\x36\x36\x6A\x8B\xD7\xC2\x5B\x9E\xDA\x81\x41\x62\x8F\x38\xEE\x49\x04\x55\xD6\xD0\xEF\x1C\x1B\x95\x16\x47\xEF\x18\x48\x35\x3A\x52\xF4\x2B\x6A\x06\x8F\x3B\x2F\xEA\x56\xE3\xAF\x86\x8D\x9E\x17\xF7\x9E\xB4\x65\x75\x02\x4D\xEF\xCB\x09\xA2\x21\x51\xD8\x9B\xD0\x67\xD0\xBA\x0D\x92\x06\x14\x73\xD4\x93\xCB\x97\x2A\x00\x9C\x5C\x4E\x0C\xBC\xFA\x15\x52\xFC\xF2\x44\x6E\xDA\x11\x4A\x6E\x08\x9F\x2F\x2D\xE3\xF9\xAA\x3A\x86\x73\xB6\x46\x53\x58\xC8\x89\x05\xBD\x83\x11\xB8\x73\x3F\xAA\x07\x8D\xF4\x42\x4D\xE7\x40\x9D\x1C\x37\x02\x03\x01\x00\x01\xA3\x13\x30\x11\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x26\x48\x2C\x16\xC2\x58\xFA\xE8\x16\x74\x0C\xAA\xAA\x5F\x54\x3F\xF2\xD7\xC9\x78\x60\x5E\x5E\x6E\x37\x63\x22\x77\x36\x7E\xB2\x17\xC4\x34\xB9\xF5\x08\x85\xFC\xC9\x01\x38\xFF\x4D\xBE\xF2\x16\x42\x43\xE7\xBB\x5A\x46\xFB\xC1\xC6\x11\x1F\xF1\x4A\xB0\x28\x46\xC9\xC3\xC4\x42\x7D\xBC\xFA\xAB\x59\x6E\xD5\xB7\x51\x88\x11\xE3\xA4\x85\x19\x6B\x82\x4C\xA4\x0C\x12\xAD\xE9\xA4\xAE\x3F\xF1\xC3\x49\x65\x9A\x8C\xC5\xC8\x3E\x25\xB7\x94\x99\xBB\x92\x32\x71\x07\xF0\x86\x5E\xED\x50\x27\xA6\x0D\xA6\x23\xF9\xBB\xCB\xA6\x07\x14\x42", + ["OU=Equifax Secure Certificate Authority,O=Equifax,C=US"] = "\x30\x82\x03\x20\x30\x82\x02\x89\xA0\x03\x02\x01\x02\x02\x04\x35\xDE\xF4\xCF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x45\x71\x75\x69\x66\x61\x78\x31\x2D\x30\x2B\x06\x03\x55\x04\x0B\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x39\x38\x30\x38\x32\x32\x31\x36\x34\x31\x35\x31\x5A\x17\x0D\x31\x38\x30\x38\x32\x32\x31\x36\x34\x31\x35\x31\x5A\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x45\x71\x75\x69\x66\x61\x78\x31\x2D\x30\x2B\x06\x03\x55\x04\x0B\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xC1\x5D\xB1\x58\x67\x08\x62\xEE\xA0\x9A\x2D\x1F\x08\x6D\x91\x14\x68\x98\x0A\x1E\xFE\xDA\x04\x6F\x13\x84\x62\x21\xC3\xD1\x7C\xCE\x9F\x05\xE0\xB8\x01\xF0\x4E\x34\xEC\xE2\x8A\x95\x04\x64\xAC\xF1\x6B\x53\x5F\x05\xB3\xCB\x67\x80\xBF\x42\x02\x8E\xFE\xDD\x01\x09\xEC\xE1\x00\x14\x4F\xFC\xFB\xF0\x0C\xDD\x43\xBA\x5B\x2B\xE1\x1F\x80\x70\x99\x15\x57\x93\x16\xF1\x0F\x97\x6A\xB7\xC2\x68\x23\x1C\xCC\x4D\x59\x30\xAC\x51\x1E\x3B\xAF\x2B\xD6\xEE\x63\x45\x7B\xC5\xD9\x5F\x50\xD2\xE3\x50\x0F\x3A\x88\xE7\xBF\x14\xFD\xE0\xC7\xB9\x02\x03\x01\x00\x01\xA3\x82\x01\x09\x30\x82\x01\x05\x30\x70\x06\x03\x55\x1D\x1F\x04\x69\x30\x67\x30\x65\xA0\x63\xA0\x61\xA4\x5F\x30\x5D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x45\x71\x75\x69\x66\x61\x78\x31\x2D\x30\x2B\x06\x03\x55\x04\x0B\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x1A\x06\x03\x55\x1D\x10\x04\x13\x30\x11\x81\x0F\x32\x30\x31\x38\x30\x38\x32\x32\x31\x36\x34\x31\x35\x31\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x48\xE6\x68\xF9\x2B\xD2\xB2\x95\xD7\x47\xD8\x23\x20\x10\x4F\x33\x98\x90\x9F\xD4\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x48\xE6\x68\xF9\x2B\xD2\xB2\x95\xD7\x47\xD8\x23\x20\x10\x4F\x33\x98\x90\x9F\xD4\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x1A\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0D\x30\x0B\x1B\x05\x56\x33\x2E\x30\x63\x03\x02\x06\xC0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x58\xCE\x29\xEA\xFC\xF7\xDE\xB5\xCE\x02\xB9\x17\xB5\x85\xD1\xB9\xE3\xE0\x95\xCC\x25\x31\x0D\x00\xA6\x92\x6E\x7F\xB6\x92\x63\x9E\x50\x95\xD1\x9A\x6F\xE4\x11\xDE\x63\x85\x6E\x98\xEE\xA8\xFF\x5A\xC8\xD3\x55\xB2\x66\x71\x57\xDE\xC0\x21\xEB\x3D\x2A\xA7\x23\x49\x01\x04\x86\x42\x7B\xFC\xEE\x7F\xA2\x16\x52\xB5\x67\x67\xD3\x40\xDB\x3B\x26\x58\xB2\x28\x77\x3D\xAE\x14\x77\x61\xD6\xFA\x2A\x66\x27\xA0\x0D\xFA\xA7\x73\x5C\xEA\x70\xF1\x94\x21\x65\x44\x5F\xFA\xFC\xEF\x29\x68\xA9\xA2\x87\x79\xEF\x79\xEF\x4F\xAC\x07\x77\x38", + ["OU=DSTCA E1,O=Digital Signature Trust Co.,C=US"] = "\x30\x82\x03\x29\x30\x82\x02\x92\xA0\x03\x02\x01\x02\x02\x04\x36\x70\x15\x96\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x46\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x31\x30\x1E\x17\x0D\x39\x38\x31\x32\x31\x30\x31\x38\x31\x30\x32\x33\x5A\x17\x0D\x31\x38\x31\x32\x31\x30\x31\x38\x34\x30\x32\x33\x5A\x30\x46\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x31\x30\x81\x9D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8B\x00\x30\x81\x87\x02\x81\x81\x00\xA0\x6C\x81\xA9\xCF\x34\x1E\x24\xDD\xFE\x86\x28\xCC\xDE\x83\x2F\xF9\x5E\xD4\x42\xD2\xE8\x74\x60\x66\x13\x98\x06\x1C\xA9\x51\x12\x69\x6F\x31\x55\xB9\x49\x72\x00\x08\x7E\xD3\xA5\x62\x44\x37\x24\x99\x8F\xD9\x83\x48\x8F\x99\x6D\x95\x13\xBB\x43\x3B\x2E\x49\x4E\x88\x37\xC1\xBB\x58\x7F\xFE\xE1\xBD\xF8\xBB\x61\xCD\xF3\x47\xC0\x99\xA6\xF1\xF3\x91\xE8\x78\x7C\x00\xCB\x61\xC9\x44\x27\x71\x69\x55\x4A\x7E\x49\x4D\xED\xA2\xA3\xBE\x02\x4C\x00\xCA\x02\xA8\xEE\x01\x02\x31\x64\x0F\x52\x2D\x13\x74\x76\x36\xB5\x7A\xB4\x2D\x71\x02\x01\x03\xA3\x82\x01\x24\x30\x82\x01\x20\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x68\x06\x03\x55\x1D\x1F\x04\x61\x30\x5F\x30\x5D\xA0\x5B\xA0\x59\xA4\x57\x30\x55\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x31\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x31\x39\x39\x38\x31\x32\x31\x30\x31\x38\x31\x30\x32\x33\x5A\x81\x0F\x32\x30\x31\x38\x31\x32\x31\x30\x31\x38\x31\x30\x32\x33\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x6A\x79\x7E\x91\x69\x46\x18\x13\x0A\x02\x77\xA5\x59\x5B\x60\x98\x25\x0E\xA2\xF8\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x6A\x79\x7E\x91\x69\x46\x18\x13\x0A\x02\x77\xA5\x59\x5B\x60\x98\x25\x0E\xA2\xF8\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x19\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0C\x30\x0A\x1B\x04\x56\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x22\x12\xD8\x7A\x1D\xDC\x81\x06\xB6\x09\x65\xB2\x87\xC8\x1F\x5E\xB4\x2F\xE9\xC4\x1E\xF2\x3C\xC1\xBB\x04\x90\x11\x4A\x83\x4E\x7E\x93\xB9\x4D\x42\xC7\x92\x26\xA0\x5C\x34\x9A\x38\x72\xF8\xFD\x6B\x16\x3E\x20\xEE\x82\x8B\x31\x2A\x93\x36\x85\x23\x88\x8A\x3C\x03\x68\xD3\xC9\x09\x0F\x4D\xFC\x6C\xA4\xDA\x28\x72\x93\x0E\x89\x80\xB0\x7D\xFE\x80\x6F\x65\x6D\x18\x33\x97\x8B\xC2\x6B\x89\xEE\x60\x3D\xC8\x9B\xEF\x7F\x2B\x32\x62\x73\x93\xCB\x3C\xE3\x7B\xE2\x76\x78\x45\xBC\xA1\x93\x04\xBB\x86\x9F\x3A\x5B\x43\x7A\xC3\x8A\x65", + ["OU=DSTCA E2,O=Digital Signature Trust Co.,C=US"] = "\x30\x82\x03\x29\x30\x82\x02\x92\xA0\x03\x02\x01\x02\x02\x04\x36\x6E\xD3\xCE\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x46\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x32\x30\x1E\x17\x0D\x39\x38\x31\x32\x30\x39\x31\x39\x31\x37\x32\x36\x5A\x17\x0D\x31\x38\x31\x32\x30\x39\x31\x39\x34\x37\x32\x36\x5A\x30\x46\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x32\x30\x81\x9D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8B\x00\x30\x81\x87\x02\x81\x81\x00\xBF\x93\x8F\x17\x92\xEF\x33\x13\x18\xEB\x10\x7F\x4E\x16\xBF\xFF\x06\x8F\x2A\x85\xBC\x5E\xF9\x24\xA6\x24\x88\xB6\x03\xB7\xC1\xC3\x5F\x03\x5B\xD1\x6F\xAE\x7E\x42\xEA\x66\x23\xB8\x63\x83\x56\xFB\x28\x2D\xE1\x38\x8B\xB4\xEE\xA8\x01\xE1\xCE\x1C\xB6\x88\x2A\x22\x46\x85\xFB\x9F\xA7\x70\xA9\x47\x14\x3F\xCE\xDE\x65\xF0\xA8\x71\xF7\x4F\x26\x6C\x8C\xBC\xC6\xB5\xEF\xDE\x49\x27\xFF\x48\x2A\x7D\xE8\x4D\x03\xCC\xC7\xB2\x52\xC6\x17\x31\x13\x3B\xB5\x4D\xDB\xC8\xC4\xF6\xC3\x0F\x24\x2A\xDA\x0C\x9D\xE7\x91\x5B\x80\xCD\x94\x9D\x02\x01\x03\xA3\x82\x01\x24\x30\x82\x01\x20\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x68\x06\x03\x55\x1D\x1F\x04\x61\x30\x5F\x30\x5D\xA0\x5B\xA0\x59\xA4\x57\x30\x55\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x43\x41\x20\x45\x32\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x31\x39\x39\x38\x31\x32\x30\x39\x31\x39\x31\x37\x32\x36\x5A\x81\x0F\x32\x30\x31\x38\x31\x32\x30\x39\x31\x39\x31\x37\x32\x36\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x1E\x82\x4D\x28\x65\x80\x3C\xC9\x41\x6E\xAC\x35\x2E\x5A\xCB\xDE\xEE\xF8\x39\x5B\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x1E\x82\x4D\x28\x65\x80\x3C\xC9\x41\x6E\xAC\x35\x2E\x5A\xCB\xDE\xEE\xF8\x39\x5B\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x19\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0C\x30\x0A\x1B\x04\x56\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x47\x8D\x83\xAD\x62\xF2\xDB\xB0\x9E\x45\x22\x05\xB9\xA2\xD6\x03\x0E\x38\x72\xE7\x9E\xFC\x7B\xE6\x93\xB6\x9A\xA5\xA2\x94\xC8\x34\x1D\x91\xD1\xC5\xD7\xF4\x0A\x25\x0F\x3D\x78\x81\x9E\x0F\xB1\x67\xC4\x90\x4C\x63\xDD\x5E\xA7\xE2\xBA\x9F\xF5\xF7\x4D\xA5\x31\x7B\x9C\x29\x2D\x4C\xFE\x64\x3E\xEC\xB6\x53\xFE\xEA\x9B\xED\x82\xDB\x74\x75\x4B\x07\x79\x6E\x1E\xD8\x19\x83\x73\xDE\xF5\x3E\xD0\xB5\xDE\xE7\x4B\x68\x7D\x43\x2E\x2A\x20\xE1\x7E\xA0\x78\x44\x9E\x08\xF5\x98\xF9\xC7\x7F\x1B\x1B\xD6\x06\x20\x02\x58\xA1\xC3\xA2\x03", + ["OU=Class 3 Public Primary Certification Authority,O=VeriSign\, Inc.,C=US"] = "\x30\x82\x02\x3C\x30\x82\x01\xA5\x02\x10\x70\xBA\xE4\x1D\x10\xD9\x29\x34\xB6\x38\xCA\x7B\x03\xCC\xBA\xBF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x02\x05\x00\x30\x5F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x37\x30\x35\x06\x03\x55\x04\x0B\x13\x2E\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x39\x36\x30\x31\x32\x39\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x5F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x37\x30\x35\x06\x03\x55\x04\x0B\x13\x2E\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xC9\x5C\x59\x9E\xF2\x1B\x8A\x01\x14\xB4\x10\xDF\x04\x40\xDB\xE3\x57\xAF\x6A\x45\x40\x8F\x84\x0C\x0B\xD1\x33\xD9\xD9\x11\xCF\xEE\x02\x58\x1F\x25\xF7\x2A\xA8\x44\x05\xAA\xEC\x03\x1F\x78\x7F\x9E\x93\xB9\x9A\x00\xAA\x23\x7D\xD6\xAC\x85\xA2\x63\x45\xC7\x72\x27\xCC\xF4\x4C\xC6\x75\x71\xD2\x39\xEF\x4F\x42\xF0\x75\xDF\x0A\x90\xC6\x8E\x20\x6F\x98\x0F\xF8\xAC\x23\x5F\x70\x29\x36\xA4\xC9\x86\xE7\xB1\x9A\x20\xCB\x53\xA5\x85\xE7\x3D\xBE\x7D\x9A\xFE\x24\x45\x33\xDC\x76\x15\xED\x0F\xA2\x71\x64\x4C\x65\x2E\x81\x68\x45\xA7\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x02\x05\x00\x03\x81\x81\x00\xBB\x4C\x12\x2B\xCF\x2C\x26\x00\x4F\x14\x13\xDD\xA6\xFB\xFC\x0A\x11\x84\x8C\xF3\x28\x1C\x67\x92\x2F\x7C\xB6\xC5\xFA\xDF\xF0\xE8\x95\xBC\x1D\x8F\x6C\x2C\xA8\x51\xCC\x73\xD8\xA4\xC0\x53\xF0\x4E\xD6\x26\xC0\x76\x01\x57\x81\x92\x5E\x21\xF1\xD1\xB1\xFF\xE7\xD0\x21\x58\xCD\x69\x17\xE3\x44\x1C\x9C\x19\x44\x39\x89\x5C\xDC\x9C\x00\x0F\x56\x8D\x02\x99\xED\xA2\x90\x45\x4C\xE4\xBB\x10\xA4\x3D\xF0\x32\x03\x0E\xF1\xCE\xF8\xE8\xC9\x51\x8C\xE6\x62\x9F\xE6\x9F\xC0\x7D\xB7\x72\x9C\xC9\x36\x3A\x6B\x9F\x4E\xA8\xFF\x64\x0D\x64", + ["OU=VeriSign Trust Network,OU=(c) 1998 VeriSign\, Inc. - For authorized use only,OU=Class 3 Public Primary Certification Authority - G2,O=VeriSign\, Inc.,C=US"] = "\x30\x82\x03\x02\x30\x82\x02\x6B\x02\x10\x7D\xD9\xFE\x07\xCF\xA8\x1E\xB7\x10\x79\x67\xFB\xA7\x89\x34\xC6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xC1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x0B\x13\x33\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x30\x1E\x17\x0D\x39\x38\x30\x35\x31\x38\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xC1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x0B\x13\x33\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xCC\x5E\xD1\x11\x5D\x5C\x69\xD0\xAB\xD3\xB9\x6A\x4C\x99\x1F\x59\x98\x30\x8E\x16\x85\x20\x46\x6D\x47\x3F\xD4\x85\x20\x84\xE1\x6D\xB3\xF8\xA4\xED\x0C\xF1\x17\x0F\x3B\xF9\xA7\xF9\x25\xD7\xC1\xCF\x84\x63\xF2\x7C\x63\xCF\xA2\x47\xF2\xC6\x5B\x33\x8E\x64\x40\x04\x68\xC1\x80\xB9\x64\x1C\x45\x77\xC7\xD8\x6E\xF5\x95\x29\x3C\x50\xE8\x34\xD7\x78\x1F\xA8\xBA\x6D\x43\x91\x95\x8F\x45\x57\x5E\x7E\xC5\xFB\xCA\xA4\x04\xEB\xEA\x97\x37\x54\x30\x6F\xBB\x01\x47\x32\x33\xCD\xDC\x57\x9B\x64\x69\x61\xF8\x9B\x1D\x1C\x89\x4F\x5C\x67\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x51\x4D\xCD\xBE\x5C\xCB\x98\x19\x9C\x15\xB2\x01\x39\x78\x2E\x4D\x0F\x67\x70\x70\x99\xC6\x10\x5A\x94\xA4\x53\x4D\x54\x6D\x2B\xAF\x0D\x5D\x40\x8B\x64\xD3\xD7\xEE\xDE\x56\x61\x92\x5F\xA6\xC4\x1D\x10\x61\x36\xD3\x2C\x27\x3C\xE8\x29\x09\xB9\x11\x64\x74\xCC\xB5\x73\x9F\x1C\x48\xA9\xBC\x61\x01\xEE\xE2\x17\xA6\x0C\xE3\x40\x08\x3B\x0E\xE7\xEB\x44\x73\x2A\x9A\xF1\x69\x92\xEF\x71\x14\xC3\x39\xAC\x71\xA7\x91\x09\x6F\xE4\x71\x06\xB3\xBA\x59\x57\x26\x79\x00\xF6\xF8\x0D\xA2\x33\x30\x28\xD4\xAA\x58\xA0\x9D\x9D\x69\x91\xFD", + ["OU=VeriSign Trust Network,OU=(c) 1998 VeriSign\, Inc. - For authorized use only,OU=Class 4 Public Primary Certification Authority - G2,O=VeriSign\, Inc.,C=US"] = "\x30\x82\x03\x02\x30\x82\x02\x6B\x02\x10\x32\x88\x8E\x9A\xD2\xF5\xEB\x13\x47\xF8\x7F\xC4\x20\x37\x25\xF8\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xC1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x0B\x13\x33\x43\x6C\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x30\x1E\x17\x0D\x39\x38\x30\x35\x31\x38\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x30\x38\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xC1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x0B\x13\x33\x43\x6C\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xBA\xF0\xE4\xCF\xF9\xC4\xAE\x85\x54\xB9\x07\x57\xF9\x8F\xC5\x7F\x68\x11\xF8\xC4\x17\xB0\x44\xDC\xE3\x30\x73\xD5\x2A\x62\x2A\xB8\xD0\xCC\x1C\xED\x28\x5B\x7E\xBD\x6A\xDC\xB3\x91\x24\xCA\x41\x62\x3C\xFC\x02\x01\xBF\x1C\x16\x31\x94\x05\x97\x76\x6E\xA2\xAD\xBD\x61\x17\x6C\x4E\x30\x86\xF0\x51\x37\x2A\x50\xC7\xA8\x62\x81\xDC\x5B\x4A\xAA\xC1\xA0\xB4\x6E\xEB\x2F\xE5\x57\xC5\xB1\x2B\x40\x70\xDB\x5A\x4D\xA1\x8E\x1F\xBD\x03\x1F\xD8\x03\xD4\x8F\x4C\x99\x71\xBC\xE2\x82\xCC\x58\xE8\x98\x3A\x86\xD3\x86\x38\xF3\x00\x29\x1F\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x85\x8C\x12\xC1\xA7\xB9\x50\x15\x7A\xCB\x3E\xAC\xB8\x43\x8A\xDC\xAA\xDD\x14\xBA\x89\x81\x7E\x01\x3C\x23\x71\x21\x88\x2F\x82\xDC\x63\xFA\x02\x45\xAC\x45\x59\xD7\x2A\x58\x44\x5B\xB7\x9F\x81\x3B\x92\x68\x3D\xE2\x37\x24\xF5\x7B\x6C\x8F\x76\x35\x96\x09\xA8\x59\x9D\xB9\xCE\x23\xAB\x74\xD6\x83\xFD\x32\x73\x27\xD8\x69\x3E\x43\x74\xF6\xAE\xC5\x89\x9A\xE7\x53\x7C\xE9\x7B\xF6\x4B\xF3\xC1\x65\x83\xDE\x8D\x8A\x9C\x3C\x88\x8D\x39\x59\xFC\xAA\x3F\x22\x8D\xA1\xC1\x66\x50\x81\x72\x4C\xED\x22\x64\x4F\x4F\xCA\x80\x91\xB6\x29", + ["CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE"] = "\x30\x82\x03\x75\x30\x82\x02\x5D\xA0\x03\x02\x01\x02\x02\x0B\x04\x00\x00\x00\x00\x01\x15\x4B\x5A\xC3\x94\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x57\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x6E\x76\x2D\x73\x61\x31\x10\x30\x0E\x06\x03\x55\x04\x0B\x13\x07\x52\x6F\x6F\x74\x20\x43\x41\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x39\x38\x30\x39\x30\x31\x31\x32\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x30\x31\x32\x38\x31\x32\x30\x30\x30\x30\x5A\x30\x57\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x45\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x6E\x76\x2D\x73\x61\x31\x10\x30\x0E\x06\x03\x55\x04\x0B\x13\x07\x52\x6F\x6F\x74\x20\x43\x41\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xDA\x0E\xE6\x99\x8D\xCE\xA3\xE3\x4F\x8A\x7E\xFB\xF1\x8B\x83\x25\x6B\xEA\x48\x1F\xF1\x2A\xB0\xB9\x95\x11\x04\xBD\xF0\x63\xD1\xE2\x67\x66\xCF\x1C\xDD\xCF\x1B\x48\x2B\xEE\x8D\x89\x8E\x9A\xAF\x29\x80\x65\xAB\xE9\xC7\x2D\x12\xCB\xAB\x1C\x4C\x70\x07\xA1\x3D\x0A\x30\xCD\x15\x8D\x4F\xF8\xDD\xD4\x8C\x50\x15\x1C\xEF\x50\xEE\xC4\x2E\xF7\xFC\xE9\x52\xF2\x91\x7D\xE0\x6D\xD5\x35\x30\x8E\x5E\x43\x73\xF2\x41\xE9\xD5\x6A\xE3\xB2\x89\x3A\x56\x39\x38\x6F\x06\x3C\x88\x69\x5B\x2A\x4D\xC5\xA7\x54\xB8\x6C\x89\xCC\x9B\xF9\x3C\xCA\xE5\xFD\x89\xF5\x12\x3C\x92\x78\x96\xD6\xDC\x74\x6E\x93\x44\x61\xD1\x8D\xC7\x46\xB2\x75\x0E\x86\xE8\x19\x8A\xD5\x6D\x6C\xD5\x78\x16\x95\xA2\xE9\xC8\x0A\x38\xEB\xF2\x24\x13\x4F\x73\x54\x93\x13\x85\x3A\x1B\xBC\x1E\x34\xB5\x8B\x05\x8C\xB9\x77\x8B\xB1\xDB\x1F\x20\x91\xAB\x09\x53\x6E\x90\xCE\x7B\x37\x74\xB9\x70\x47\x91\x22\x51\x63\x16\x79\xAE\xB1\xAE\x41\x26\x08\xC8\x19\x2B\xD1\x46\xAA\x48\xD6\x64\x2A\xD7\x83\x34\xFF\x2C\x2A\xC1\x6C\x19\x43\x4A\x07\x85\xE7\xD3\x7C\xF6\x21\x68\xEF\xEA\xF2\x52\x9F\x7F\x93\x90\xCF\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x60\x7B\x66\x1A\x45\x0D\x97\xCA\x89\x50\x2F\x7D\x04\xCD\x34\xA8\xFF\xFC\xFD\x4B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xD6\x73\xE7\x7C\x4F\x76\xD0\x8D\xBF\xEC\xBA\xA2\xBE\x34\xC5\x28\x32\xB5\x7C\xFC\x6C\x9C\x2C\x2B\xBD\x09\x9E\x53\xBF\x6B\x5E\xAA\x11\x48\xB6\xE5\x08\xA3\xB3\xCA\x3D\x61\x4D\xD3\x46\x09\xB3\x3E\xC3\xA0\xE3\x63\x55\x1B\xF2\xBA\xEF\xAD\x39\xE1\x43\xB9\x38\xA3\xE6\x2F\x8A\x26\x3B\xEF\xA0\x50\x56\xF9\xC6\x0A\xFD\x38\xCD\xC4\x0B\x70\x51\x94\x97\x98\x04\xDF\xC3\x5F\x94\xD5\x15\xC9\x14\x41\x9C\xC4\x5D\x75\x64\x15\x0D\xFF\x55\x30\xEC\x86\x8F\xFF\x0D\xEF\x2C\xB9\x63\x46\xF6\xAA\xFC\xDF\xBC\x69\xFD\x2E\x12\x48\x64\x9A\xE0\x95\xF0\xA6\xEF\x29\x8F\x01\xB1\x15\xB5\x0C\x1D\xA5\xFE\x69\x2C\x69\x24\x78\x1E\xB3\xA7\x1C\x71\x62\xEE\xCA\xC8\x97\xAC\x17\x5D\x8A\xC2\xF8\x47\x86\x6E\x2A\xC4\x56\x31\x95\xD0\x67\x89\x85\x2B\xF9\x6C\xA6\x5D\x46\x9D\x0C\xAA\x82\xE4\x99\x51\xDD\x70\xB7\xDB\x56\x3D\x61\xE4\x6A\xE1\x5C\xD6\xF6\xFE\x3D\xDE\x41\xCC\x07\xAE\x63\x52\xBF\x53\x53\xF4\x2B\xE9\xC7\xFD\xB6\xF7\x82\x5F\x85\xD2\x41\x18\xDB\x81\xB3\x04\x1C\xC5\x1F\xA4\x80\x6F\x15\x20\xC9\xDE\x0C\x88\x0A\x1D\xD6\x66\x55\xE2\xFC\x48\xC9\x29\x26\x69\xE0", + ["CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R2"] = "\x30\x82\x03\xBA\x30\x82\x02\xA2\xA0\x03\x02\x01\x02\x02\x0B\x04\x00\x00\x00\x00\x01\x0F\x86\x26\xE6\x0D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4C\x31\x20\x30\x1E\x06\x03\x55\x04\x0B\x13\x17\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x52\x32\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x30\x1E\x17\x0D\x30\x36\x31\x32\x31\x35\x30\x38\x30\x30\x30\x30\x5A\x17\x0D\x32\x31\x31\x32\x31\x35\x30\x38\x30\x30\x30\x30\x5A\x30\x4C\x31\x20\x30\x1E\x06\x03\x55\x04\x0B\x13\x17\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x52\x32\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\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\xA6\xCF\x24\x0E\xBE\x2E\x6F\x28\x99\x45\x42\xC4\xAB\x3E\x21\x54\x9B\x0B\xD3\x7F\x84\x70\xFA\x12\xB3\xCB\xBF\x87\x5F\xC6\x7F\x86\xD3\xB2\x30\x5C\xD6\xFD\xAD\xF1\x7B\xDC\xE5\xF8\x60\x96\x09\x92\x10\xF5\xD0\x53\xDE\xFB\x7B\x7E\x73\x88\xAC\x52\x88\x7B\x4A\xA6\xCA\x49\xA6\x5E\xA8\xA7\x8C\x5A\x11\xBC\x7A\x82\xEB\xBE\x8C\xE9\xB3\xAC\x96\x25\x07\x97\x4A\x99\x2A\x07\x2F\xB4\x1E\x77\xBF\x8A\x0F\xB5\x02\x7C\x1B\x96\xB8\xC5\xB9\x3A\x2C\xBC\xD6\x12\xB9\xEB\x59\x7D\xE2\xD0\x06\x86\x5F\x5E\x49\x6A\xB5\x39\x5E\x88\x34\xEC\xBC\x78\x0C\x08\x98\x84\x6C\xA8\xCD\x4B\xB4\xA0\x7D\x0C\x79\x4D\xF0\xB8\x2D\xCB\x21\xCA\xD5\x6C\x5B\x7D\xE1\xA0\x29\x84\xA1\xF9\xD3\x94\x49\xCB\x24\x62\x91\x20\xBC\xDD\x0B\xD5\xD9\xCC\xF9\xEA\x27\x0A\x2B\x73\x91\xC6\x9D\x1B\xAC\xC8\xCB\xE8\xE0\xA0\xF4\x2F\x90\x8B\x4D\xFB\xB0\x36\x1B\xF6\x19\x7A\x85\xE0\x6D\xF2\x61\x13\x88\x5C\x9F\xE0\x93\x0A\x51\x97\x8A\x5A\xCE\xAF\xAB\xD5\xF7\xAA\x09\xAA\x60\xBD\xDC\xD9\x5F\xDF\x72\xA9\x60\x13\x5E\x00\x01\xC9\x4A\xFA\x3F\xA4\xEA\x07\x03\x21\x02\x8E\x82\xCA\x03\xC2\x9B\x8F\x02\x03\x01\x00\x01\xA3\x81\x9C\x30\x81\x99\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9B\xE2\x07\x57\x67\x1C\x1E\xC0\x6A\x06\xDE\x59\xB4\x9A\x2D\xDF\xDC\x19\x86\x2E\x30\x36\x06\x03\x55\x1D\x1F\x04\x2F\x30\x2D\x30\x2B\xA0\x29\xA0\x27\x86\x25\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x67\x6C\x6F\x62\x61\x6C\x73\x69\x67\x6E\x2E\x6E\x65\x74\x2F\x72\x6F\x6F\x74\x2D\x72\x32\x2E\x63\x72\x6C\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x9B\xE2\x07\x57\x67\x1C\x1E\xC0\x6A\x06\xDE\x59\xB4\x9A\x2D\xDF\xDC\x19\x86\x2E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x99\x81\x53\x87\x1C\x68\x97\x86\x91\xEC\xE0\x4A\xB8\x44\x0B\xAB\x81\xAC\x27\x4F\xD6\xC1\xB8\x1C\x43\x78\xB3\x0C\x9A\xFC\xEA\x2C\x3C\x6E\x61\x1B\x4D\x4B\x29\xF5\x9F\x05\x1D\x26\xC1\xB8\xE9\x83\x00\x62\x45\xB6\xA9\x08\x93\xB9\xA9\x33\x4B\x18\x9A\xC2\xF8\x87\x88\x4E\xDB\xDD\x71\x34\x1A\xC1\x54\xDA\x46\x3F\xE0\xD3\x2A\xAB\x6D\x54\x22\xF5\x3A\x62\xCD\x20\x6F\xBA\x29\x89\xD7\xDD\x91\xEE\xD3\x5C\xA2\x3E\xA1\x5B\x41\xF5\xDF\xE5\x64\x43\x2D\xE9\xD5\x39\xAB\xD2\xA2\xDF\xB7\x8B\xD0\xC0\x80\x19\x1C\x45\xC0\x2D\x8C\xE8\xF8\x2D\xA4\x74\x56\x49\xC5\x05\xB5\x4F\x15\xDE\x6E\x44\x78\x39\x87\xA8\x7E\xBB\xF3\x79\x18\x91\xBB\xF4\x6F\x9D\xC1\xF0\x8C\x35\x8C\x5D\x01\xFB\xC3\x6D\xB9\xEF\x44\x6D\x79\x46\x31\x7E\x0A\xFE\xA9\x82\xC1\xFF\xEF\xAB\x6E\x20\xC4\x50\xC9\x5F\x9D\x4D\x9B\x17\x8C\x0C\xE5\x01\xC9\xA0\x41\x6A\x73\x53\xFA\xA5\x50\xB4\x6E\x25\x0F\xFB\x4C\x18\xF4\xFD\x52\xD9\x8E\x69\xB1\xE8\x11\x0F\xDE\x88\xD8\xFB\x1D\x49\xF7\xAA\xDE\x95\xCF\x20\x78\xC2\x60\x12\xDB\x25\x40\x8C\x6A\xFC\x7E\x42\x38\x40\x64\x12\xF7\x9E\x81\xE1\x93\x2E", + ["emailAddress=info@valicert.com,CN=http://www.valicert.com/,OU=ValiCert Class 1 Policy Validation Authority,O=ValiCert\, Inc.,L=ValiCert Validation Network"] = "\x30\x82\x02\xE7\x30\x82\x02\x50\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xBB\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1B\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x61\x6C\x69\x43\x65\x72\x74\x2C\x20\x49\x6E\x63\x2E\x31\x35\x30\x33\x06\x03\x55\x04\x0B\x13\x2C\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x50\x6F\x6C\x69\x63\x79\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x2F\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x35\x32\x32\x32\x33\x34\x38\x5A\x17\x0D\x31\x39\x30\x36\x32\x35\x32\x32\x32\x33\x34\x38\x5A\x30\x81\xBB\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1B\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x61\x6C\x69\x43\x65\x72\x74\x2C\x20\x49\x6E\x63\x2E\x31\x35\x30\x33\x06\x03\x55\x04\x0B\x13\x2C\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x50\x6F\x6C\x69\x63\x79\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x2F\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xD8\x59\x82\x7A\x89\xB8\x96\xBA\xA6\x2F\x68\x6F\x58\x2E\xA7\x54\x1C\x06\x6E\xF4\xEA\x8D\x48\xBC\x31\x94\x17\xF0\xF3\x4E\xBC\xB2\xB8\x35\x92\x76\xB0\xD0\xA5\xA5\x01\xD7\x00\x03\x12\x22\x19\x08\xF8\xFF\x11\x23\x9B\xCE\x07\xF5\xBF\x69\x1A\x26\xFE\x4E\xE9\xD1\x7F\x9D\x2C\x40\x1D\x59\x68\x6E\xA6\xF8\x58\xB0\x9D\x1A\x8F\xD3\x3F\xF1\xDC\x19\x06\x81\xA8\x0E\xE0\x3A\xDD\xC8\x53\x45\x09\x06\xE6\x0F\x70\xC3\xFA\x40\xA6\x0E\xE2\x56\x05\x0F\x18\x4D\xFC\x20\x82\xD1\x73\x55\x74\x8D\x76\x72\xA0\x1D\x9D\x1D\xC0\xDD\x3F\x71\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x50\x68\x3D\x49\xF4\x2C\x1C\x06\x94\xDF\x95\x60\x7F\x96\x7B\x17\xFE\x4F\x71\xAD\x64\xC8\xDD\x77\xD2\xEF\x59\x55\xE8\x3F\xE8\x8E\x05\x2A\x21\xF2\x07\xD2\xB5\xA7\x52\xFE\x9C\xB1\xB6\xE2\x5B\x77\x17\x40\xEA\x72\xD6\x23\xCB\x28\x81\x32\xC3\x00\x79\x18\xEC\x59\x17\x89\xC9\xC6\x6A\x1E\x71\xC9\xFD\xB7\x74\xA5\x25\x45\x69\xC5\x48\xAB\x19\xE1\x45\x8A\x25\x6B\x19\xEE\xE5\xBB\x12\xF5\x7F\xF7\xA6\x8D\x51\xC3\xF0\x9D\x74\xB7\xA9\x3E\xA0\xA5\xFF\xB6\x49\x03\x13\xDA\x22\xCC\xED\x71\x82\x2B\x99\xCF\x3A\xB7\xF5\x2D\x72\xC8", + ["emailAddress=info@valicert.com,CN=http://www.valicert.com/,OU=ValiCert Class 2 Policy Validation Authority,O=ValiCert\, Inc.,L=ValiCert Validation Network"] = "\x30\x82\x02\xE7\x30\x82\x02\x50\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xBB\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1B\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x61\x6C\x69\x43\x65\x72\x74\x2C\x20\x49\x6E\x63\x2E\x31\x35\x30\x33\x06\x03\x55\x04\x0B\x13\x2C\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x50\x6F\x6C\x69\x63\x79\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x2F\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x36\x30\x30\x31\x39\x35\x34\x5A\x17\x0D\x31\x39\x30\x36\x32\x36\x30\x30\x31\x39\x35\x34\x5A\x30\x81\xBB\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1B\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x61\x6C\x69\x43\x65\x72\x74\x2C\x20\x49\x6E\x63\x2E\x31\x35\x30\x33\x06\x03\x55\x04\x0B\x13\x2C\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x50\x6F\x6C\x69\x63\x79\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x2F\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xCE\x3A\x71\xCA\xE5\xAB\xC8\x59\x92\x55\xD7\xAB\xD8\x74\x0E\xF9\xEE\xD9\xF6\x55\x47\x59\x65\x47\x0E\x05\x55\xDC\xEB\x98\x36\x3C\x5C\x53\x5D\xD3\x30\xCF\x38\xEC\xBD\x41\x89\xED\x25\x42\x09\x24\x6B\x0A\x5E\xB3\x7C\xDD\x52\x2D\x4C\xE6\xD4\xD6\x7D\x5A\x59\xA9\x65\xD4\x49\x13\x2D\x24\x4D\x1C\x50\x6F\xB5\xC1\x85\x54\x3B\xFE\x71\xE4\xD3\x5C\x42\xF9\x80\xE0\x91\x1A\x0A\x5B\x39\x36\x67\xF3\x3F\x55\x7C\x1B\x3F\xB4\x5F\x64\x73\x34\xE3\xB4\x12\xBF\x87\x64\xF8\xDA\x12\xFF\x37\x27\xC1\xB3\x43\xBB\xEF\x7B\x6E\x2E\x69\xF7\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x3B\x7F\x50\x6F\x6F\x50\x94\x99\x49\x62\x38\x38\x1F\x4B\xF8\xA5\xC8\x3E\xA7\x82\x81\xF6\x2B\xC7\xE8\xC5\xCE\xE8\x3A\x10\x82\xCB\x18\x00\x8E\x4D\xBD\xA8\x58\x7F\xA1\x79\x00\xB5\xBB\xE9\x8D\xAF\x41\xD9\x0F\x34\xEE\x21\x81\x19\xA0\x32\x49\x28\xF4\xC4\x8E\x56\xD5\x52\x33\xFD\x50\xD5\x7E\x99\x6C\x03\xE4\xC9\x4C\xFC\xCB\x6C\xAB\x66\xB3\x4A\x21\x8C\xE5\xB5\x0C\x32\x3E\x10\xB2\xCC\x6C\xA1\xDC\x9A\x98\x4C\x02\x5B\xF3\xCE\xB9\x9E\xA5\x72\x0E\x4A\xB7\x3F\x3C\xE6\x16\x68\xF8\xBE\xED\x74\x4C\xBC\x5B\xD5\x62\x1F\x43\xDD", + ["emailAddress=info@valicert.com,CN=http://www.valicert.com/,OU=ValiCert Class 3 Policy Validation Authority,O=ValiCert\, Inc.,L=ValiCert Validation Network"] = "\x30\x82\x02\xE7\x30\x82\x02\x50\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xBB\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1B\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x61\x6C\x69\x43\x65\x72\x74\x2C\x20\x49\x6E\x63\x2E\x31\x35\x30\x33\x06\x03\x55\x04\x0B\x13\x2C\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x6F\x6C\x69\x63\x79\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x2F\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x36\x30\x30\x32\x32\x33\x33\x5A\x17\x0D\x31\x39\x30\x36\x32\x36\x30\x30\x32\x32\x33\x33\x5A\x30\x81\xBB\x31\x24\x30\x22\x06\x03\x55\x04\x07\x13\x1B\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x61\x6C\x69\x43\x65\x72\x74\x2C\x20\x49\x6E\x63\x2E\x31\x35\x30\x33\x06\x03\x55\x04\x0B\x13\x2C\x56\x61\x6C\x69\x43\x65\x72\x74\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x6F\x6C\x69\x63\x79\x20\x56\x61\x6C\x69\x64\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x2F\x31\x20\x30\x1E\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x11\x69\x6E\x66\x6F\x40\x76\x61\x6C\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xE3\x98\x51\x96\x1C\xE8\xD5\xB1\x06\x81\x6A\x57\xC3\x72\x75\x93\xAB\xCF\x9E\xA6\xFC\xF3\x16\x52\xD6\x2D\x4D\x9F\x35\x44\xA8\x2E\x04\x4D\x07\x49\x8A\x38\x29\xF5\x77\x37\xE7\xB7\xAB\x5D\xDF\x36\x71\x14\x99\x8F\xDC\xC2\x92\xF1\xE7\x60\x92\x97\xEC\xD8\x48\xDC\xBF\xC1\x02\x20\xC6\x24\xA4\x28\x4C\x30\x5A\x76\x6D\xB1\x5C\xF3\xDD\xDE\x9E\x10\x71\xA1\x88\xC7\x5B\x9B\x41\x6D\xCA\xB0\xB8\x8E\x15\xEE\xAD\x33\x2B\xCF\x47\x04\x5C\x75\x71\x0A\x98\x24\x98\x29\xA7\x49\x59\xA5\xDD\xF8\xB7\x43\x62\x61\xF3\xD3\xE2\xD0\x55\x3F\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x56\xBB\x02\x58\x84\x67\x08\x2C\xDF\x1F\xDB\x7B\x49\x33\xF5\xD3\x67\x9D\xF4\xB4\x0A\x10\xB3\xC9\xC5\x2C\xE2\x92\x6A\x71\x78\x27\xF2\x70\x83\x42\xD3\x3E\xCF\xA9\x54\xF4\xF1\xD8\x92\x16\x8C\xD1\x04\xCB\x4B\xAB\xC9\x9F\x45\xAE\x3C\x8A\xA9\xB0\x71\x33\x5D\xC8\xC5\x57\xDF\xAF\xA8\x35\xB3\x7F\x89\x87\xE9\xE8\x25\x92\xB8\x7F\x85\x7A\xAE\xD6\xBC\x1E\x37\x58\x2A\x67\xC9\x91\xCF\x2A\x81\x3E\xED\xC6\x39\xDF\xC0\x3E\x19\x9C\x19\xCC\x13\x4D\x82\x41\xB5\x8C\xDE\xE0\x3D\x60\x08\x20\x0F\x45\x7E\x6B\xA2\x7F\xA3\x8C\x15\xEE", + ["CN=VeriSign Class 3 Public Primary Certification Authority - G3,OU=(c) 1999 VeriSign\, Inc. - For authorized use only,OU=VeriSign Trust Network,O=VeriSign\, Inc.,C=US"] = "\x30\x82\x04\x1A\x30\x82\x03\x02\x02\x11\x00\x9B\x7E\x06\x49\xA3\x3E\x62\xB9\xD5\xEE\x90\x48\x71\x29\xEF\x57\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\x30\x1E\x17\x0D\x39\x39\x31\x30\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\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\xCB\xBA\x9C\x52\xFC\x78\x1F\x1A\x1E\x6F\x1B\x37\x73\xBD\xF8\xC9\x6B\x94\x12\x30\x4F\xF0\x36\x47\xF5\xD0\x91\x0A\xF5\x17\xC8\xA5\x61\xC1\x16\x40\x4D\xFB\x8A\x61\x90\xE5\x76\x20\xC1\x11\x06\x7D\xAB\x2C\x6E\xA6\xF5\x11\x41\x8E\xFA\x2D\xAD\x2A\x61\x59\xA4\x67\x26\x4C\xD0\xE8\xBC\x52\x5B\x70\x20\x04\x58\xD1\x7A\xC9\xA4\x69\xBC\x83\x17\x64\xAD\x05\x8B\xBC\xD0\x58\xCE\x8D\x8C\xF5\xEB\xF0\x42\x49\x0B\x9D\x97\x27\x67\x32\x6E\xE1\xAE\x93\x15\x1C\x70\xBC\x20\x4D\x2F\x18\xDE\x92\x88\xE8\x6C\x85\x57\x11\x1A\xE9\x7E\xE3\x26\x11\x54\xA2\x45\x96\x55\x83\xCA\x30\x89\xE8\xDC\xD8\xA3\xED\x2A\x80\x3F\x7F\x79\x65\x57\x3E\x15\x20\x66\x08\x2F\x95\x93\xBF\xAA\x47\x2F\xA8\x46\x97\xF0\x12\xE2\xFE\xC2\x0A\x2B\x51\xE6\x76\xE6\xB7\x46\xB7\xE2\x0D\xA6\xCC\xA8\xC3\x4C\x59\x55\x89\xE6\xE8\x53\x5C\x1C\xEA\x9D\xF0\x62\x16\x0B\xA7\xC9\x5F\x0C\xF0\xDE\xC2\x76\xCE\xAF\xF7\x6A\xF2\xFA\x41\xA6\xA2\x33\x14\xC9\xE5\x7A\x63\xD3\x9E\x62\x37\xD5\x85\x65\x9E\x0E\xE6\x53\x24\x74\x1B\x5E\x1D\x12\x53\x5B\xC7\x2C\xE7\x83\x49\x3B\x15\xAE\x8A\x68\xB9\x57\x97\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x11\x14\x96\xC1\xAB\x92\x08\xF7\x3F\x2F\xC9\xB2\xFE\xE4\x5A\x9F\x64\xDE\xDB\x21\x4F\x86\x99\x34\x76\x36\x57\xDD\xD0\x15\x2F\xC5\xAD\x7F\x15\x1F\x37\x62\x73\x3E\xD4\xE7\x5F\xCE\x17\x03\xDB\x35\xFA\x2B\xDB\xAE\x60\x09\x5F\x1E\x5F\x8F\x6E\xBB\x0B\x3D\xEA\x5A\x13\x1E\x0C\x60\x6F\xB5\xC0\xB5\x23\x22\x2E\x07\x0B\xCB\xA9\x74\xCB\x47\xBB\x1D\xC1\xD7\xA5\x6B\xCC\x2F\xD2\x42\xFD\x49\xDD\xA7\x89\xCF\x53\xBA\xDA\x00\x5A\x28\xBF\x82\xDF\xF8\xBA\x13\x1D\x50\x86\x82\xFD\x8E\x30\x8F\x29\x46\xB0\x1E\x3D\x35\xDA\x38\x62\x16\x18\x4A\xAD\xE6\xB6\x51\x6C\xDE\xAF\x62\xEB\x01\xD0\x1E\x24\xFE\x7A\x8F\x12\x1A\x12\x68\xB8\xFB\x66\x99\x14\x14\x45\x5C\xAE\xE7\xAE\x69\x17\x81\x2B\x5A\x37\xC9\x5E\x2A\xF4\xC6\xE2\xA1\x5C\x54\x9B\xA6\x54\x00\xCF\xF0\xF1\xC1\xC7\x98\x30\x1A\x3B\x36\x16\xDB\xA3\x6E\xEA\xFD\xAD\xB2\xC2\xDA\xEF\x02\x47\x13\x8A\xC0\xF1\xB3\x31\xAD\x4F\x1C\xE1\x4F\x9C\xAF\x0F\x0C\x9D\xF7\x78\x0D\xD8\xF4\x35\x56\x80\xDA\xB7\x6D\x17\x8F\x9D\x1E\x81\x64\xE1\xFE\xC5\x45\xBA\xAD\x6B\xB9\x0A\x7A\x4E\x4F\x4B\x84\xEE\x4B\xF1\x7D\xDD\x11", + ["CN=VeriSign Class 4 Public Primary Certification Authority - G3,OU=(c) 1999 VeriSign\, Inc. - For authorized use only,OU=VeriSign Trust Network,O=VeriSign\, Inc.,C=US"] = "\x30\x82\x04\x1A\x30\x82\x03\x02\x02\x11\x00\xEC\xA0\xA7\x8B\x6E\x75\x6A\x01\xCF\xC4\x7C\xCC\x2F\x94\x5E\xD7\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\x30\x1E\x17\x0D\x39\x39\x31\x30\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x31\x39\x39\x39\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x34\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\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\xAD\xCB\xA5\x11\x69\xC6\x59\xAB\xF1\x8F\xB5\x19\x0F\x56\xCE\xCC\xB5\x1F\x20\xE4\x9E\x26\x25\x4B\xE0\x73\x65\x89\x59\xDE\xD0\x83\xE4\xF5\x0F\xB5\xBB\xAD\xF1\x7C\xE8\x21\xFC\xE4\xE8\x0C\xEE\x7C\x45\x22\x19\x76\x92\xB4\x13\xB7\x20\x5B\x09\xFA\x61\xAE\xA8\xF2\xA5\x8D\x85\xC2\x2A\xD6\xDE\x66\x36\xD2\x9B\x02\xF4\xA8\x92\x60\x7C\x9C\x69\xB4\x8F\x24\x1E\xD0\x86\x52\xF6\x32\x9C\x41\x58\x1E\x22\xBD\xCD\x45\x62\x95\x08\x6E\xD0\x66\xDD\x53\xA2\xCC\xF0\x10\xDC\x54\x73\x8B\x04\xA1\x46\x33\x33\x5C\x17\x40\xB9\x9E\x4D\xD3\xF3\xBE\x55\x83\xE8\xB1\x89\x8E\x5A\x7C\x9A\x96\x22\x90\x3B\x88\x25\xF2\xD2\x53\x88\x02\x0C\x0B\x78\xF2\xE6\x37\x17\x4B\x30\x46\x07\xE4\x80\x6D\xA6\xD8\x96\x2E\xE8\x2C\xF8\x11\xB3\x38\x0D\x66\xA6\x9B\xEA\xC9\x23\x5B\xDB\x8E\xE2\xF3\x13\x8E\x1A\x59\x2D\xAA\x02\xF0\xEC\xA4\x87\x66\xDC\xC1\x3F\xF5\xD8\xB9\xF4\xEC\x82\xC6\xD2\x3D\x95\x1D\xE5\xC0\x4F\x84\xC9\xD9\xA3\x44\x28\x06\x6A\xD7\x45\xAC\xF0\x6B\x6A\xEF\x4E\x5F\xF8\x11\x82\x1E\x38\x63\x34\x66\x50\xD4\x3E\x93\x73\xFA\x30\xC3\x66\xAD\xFF\x93\x2D\x97\xEF\x03\x02\x03\x01\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x8F\xFA\x25\x6B\x4F\x5B\xE4\xA4\x4E\x27\x55\xAB\x22\x15\x59\x3C\xCA\xB5\x0A\xD4\x4A\xDB\xAB\xDD\xA1\x5F\x53\xC5\xA0\x57\x39\xC2\xCE\x47\x2B\xBE\x3A\xC8\x56\xBF\xC2\xD9\x27\x10\x3A\xB1\x05\x3C\xC0\x77\x31\xBB\x3A\xD3\x05\x7B\x6D\x9A\x1C\x30\x8C\x80\xCB\x93\x93\x2A\x83\xAB\x05\x51\x82\x02\x00\x11\x67\x6B\xF3\x88\x61\x47\x5F\x03\x93\xD5\x5B\x0D\xE0\xF1\xD4\xA1\x32\x35\x85\xB2\x3A\xDB\xB0\x82\xAB\xD1\xCB\x0A\xBC\x4F\x8C\x5B\xC5\x4B\x00\x3B\x1F\x2A\x82\xA6\x7E\x36\x85\xDC\x7E\x3C\x67\x00\xB5\xE4\x3B\x52\xE0\xA8\xEB\x5D\x15\xF9\xC6\x6D\xF0\xAD\x1D\x0E\x85\xB7\xA9\x9A\x73\x14\x5A\x5B\x8F\x41\x28\xC0\xD5\xE8\x2D\x4D\xA4\x5E\xCD\xAA\xD9\xED\xCE\xDC\xD8\xD5\x3C\x42\x1D\x17\xC1\x12\x5D\x45\x38\xC3\x38\xF3\xFC\x85\x2E\x83\x46\x48\xB2\xD7\x20\x5F\x92\x36\x8F\xE7\x79\x0F\x98\x5E\x99\xE8\xF0\xD0\xA4\xBB\xF5\x53\xBD\x2A\xCE\x59\xB0\xAF\x6E\x7F\x6C\xBB\xD2\x1E\x00\xB0\x21\xED\xF8\x41\x62\x82\xB9\xD8\xB2\xC4\xBB\x46\x50\xF3\x31\xC5\x8F\x01\xA8\x74\xEB\xF5\x78\x27\xDA\xE7\xF7\x66\x43\xF3\x9E\x83\x3E\x20\xAA\xC3\x35\x60\x91\xCE", + ["CN=Entrust.net Secure Server Certification Authority,OU=(c) 1999 Entrust.net Limited,OU=www.entrust.net/CPS incorp. by ref. (limits liab.),O=Entrust.net,C=US"] = "\x30\x82\x04\xD8\x30\x82\x04\x41\xA0\x03\x02\x01\x02\x02\x04\x37\x4A\xD2\x43\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xC3\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x3B\x30\x39\x06\x03\x55\x04\x0B\x13\x32\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x3A\x30\x38\x06\x03\x55\x04\x03\x13\x31\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x53\x65\x63\x75\x72\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x39\x39\x30\x35\x32\x35\x31\x36\x30\x39\x34\x30\x5A\x17\x0D\x31\x39\x30\x35\x32\x35\x31\x36\x33\x39\x34\x30\x5A\x30\x81\xC3\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x3B\x30\x39\x06\x03\x55\x04\x0B\x13\x32\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x3A\x30\x38\x06\x03\x55\x04\x03\x13\x31\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x53\x65\x63\x75\x72\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x81\x9D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8B\x00\x30\x81\x87\x02\x81\x81\x00\xCD\x28\x83\x34\x54\x1B\x89\xF3\x0F\xAF\x37\x91\x31\xFF\xAF\x31\x60\xC9\xA8\xE8\xB2\x10\x68\xED\x9F\xE7\x93\x36\xF1\x0A\x64\xBB\x47\xF5\x04\x17\x3F\x23\x47\x4D\xC5\x27\x19\x81\x26\x0C\x54\x72\x0D\x88\x2D\xD9\x1F\x9A\x12\x9F\xBC\xB3\x71\xD3\x80\x19\x3F\x47\x66\x7B\x8C\x35\x28\xD2\xB9\x0A\xDF\x24\xDA\x9C\xD6\x50\x79\x81\x7A\x5A\xD3\x37\xF7\xC2\x4A\xD8\x29\x92\x26\x64\xD1\xE4\x98\x6C\x3A\x00\x8A\xF5\x34\x9B\x65\xF8\xED\xE3\x10\xFF\xFD\xB8\x49\x58\xDC\xA0\xDE\x82\x39\x6B\x81\xB1\x16\x19\x61\xB9\x54\xB6\xE6\x43\x02\x01\x03\xA3\x82\x01\xD7\x30\x82\x01\xD3\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x01\x19\x06\x03\x55\x1D\x1F\x04\x82\x01\x10\x30\x82\x01\x0C\x30\x81\xDE\xA0\x81\xDB\xA0\x81\xD8\xA4\x81\xD5\x30\x81\xD2\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x3B\x30\x39\x06\x03\x55\x04\x0B\x13\x32\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x3A\x30\x38\x06\x03\x55\x04\x03\x13\x31\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x53\x65\x63\x75\x72\x65\x20\x53\x65\x72\x76\x65\x72\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x29\xA0\x27\xA0\x25\x86\x23\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x52\x4C\x2F\x6E\x65\x74\x31\x2E\x63\x72\x6C\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x31\x39\x39\x39\x30\x35\x32\x35\x31\x36\x30\x39\x34\x30\x5A\x81\x0F\x32\x30\x31\x39\x30\x35\x32\x35\x31\x36\x30\x39\x34\x30\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xF0\x17\x62\x13\x55\x3D\xB3\xFF\x0A\x00\x6B\xFB\x50\x84\x97\xF3\xED\x62\xD0\x1A\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xF0\x17\x62\x13\x55\x3D\xB3\xFF\x0A\x00\x6B\xFB\x50\x84\x97\xF3\xED\x62\xD0\x1A\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x19\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0C\x30\x0A\x1B\x04\x56\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x90\xDC\x30\x02\xFA\x64\x74\xC2\xA7\x0A\xA5\x7C\x21\x8D\x34\x17\xA8\xFB\x47\x0E\xFF\x25\x7C\x8D\x13\x0A\xFB\xE4\x98\xB5\xEF\x8C\xF8\xC5\x10\x0D\xF7\x92\xBE\xF1\xC3\xD5\xD5\x95\x6A\x04\xBB\x2C\xCE\x26\x36\x65\xC8\x31\xC6\xE7\xEE\x3F\xE3\x57\x75\x84\x7A\x11\xEF\x46\x4F\x18\xF4\xD3\x98\xBB\xA8\x87\x32\xBA\x72\xF6\x3C\xE2\x3D\x9F\xD7\x1D\xD9\xC3\x60\x43\x8C\x58\x0E\x22\x96\x2F\x62\xA3\x2C\x1F\xBA\xAD\x05\xEF\xAB\x32\x78\x87\xA0\x54\x73\x19\xB5\x5C\x05\xF9\x52\x3E\x6D\x2D\x45\x0B\xF7\x0A\x93\xEA\xED\x06\xF9\xB2", + ["CN=Entrust.net Certification Authority (2048),OU=(c) 1999 Entrust.net Limited,OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.),O=Entrust.net"] = "\x30\x82\x04\x5C\x30\x82\x03\x44\xA0\x03\x02\x01\x02\x02\x04\x38\x63\xB9\x66\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xB4\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x40\x30\x3E\x06\x03\x55\x04\x0B\x14\x37\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x5F\x32\x30\x34\x38\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2A\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x28\x32\x30\x34\x38\x29\x30\x1E\x17\x0D\x39\x39\x31\x32\x32\x34\x31\x37\x35\x30\x35\x31\x5A\x17\x0D\x31\x39\x31\x32\x32\x34\x31\x38\x32\x30\x35\x31\x5A\x30\x81\xB4\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x40\x30\x3E\x06\x03\x55\x04\x0B\x14\x37\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x5F\x32\x30\x34\x38\x20\x69\x6E\x63\x6F\x72\x70\x2E\x20\x62\x79\x20\x72\x65\x66\x2E\x20\x28\x6C\x69\x6D\x69\x74\x73\x20\x6C\x69\x61\x62\x2E\x29\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x28\x63\x29\x20\x31\x39\x39\x39\x20\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x33\x30\x31\x06\x03\x55\x04\x03\x13\x2A\x45\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x28\x32\x30\x34\x38\x29\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\xAD\x4D\x4B\xA9\x12\x86\xB2\xEA\xA3\x20\x07\x15\x16\x64\x2A\x2B\x4B\xD1\xBF\x0B\x4A\x4D\x8E\xED\x80\x76\xA5\x67\xB7\x78\x40\xC0\x73\x42\xC8\x68\xC0\xDB\x53\x2B\xDD\x5E\xB8\x76\x98\x35\x93\x8B\x1A\x9D\x7C\x13\x3A\x0E\x1F\x5B\xB7\x1E\xCF\xE5\x24\x14\x1E\xB1\x81\xA9\x8D\x7D\xB8\xCC\x6B\x4B\x03\xF1\x02\x0C\xDC\xAB\xA5\x40\x24\x00\x7F\x74\x94\xA1\x9D\x08\x29\xB3\x88\x0B\xF5\x87\x77\x9D\x55\xCD\xE4\xC3\x7E\xD7\x6A\x64\xAB\x85\x14\x86\x95\x5B\x97\x32\x50\x6F\x3D\xC8\xBA\x66\x0C\xE3\xFC\xBD\xB8\x49\xC1\x76\x89\x49\x19\xFD\xC0\xA8\xBD\x89\xA3\x67\x2F\xC6\x9F\xBC\x71\x19\x60\xB8\x2D\xE9\x2C\xC9\x90\x76\x66\x7B\x94\xE2\xAF\x78\xD6\x65\x53\x5D\x3C\xD6\x9C\xB2\xCF\x29\x03\xF9\x2F\xA4\x50\xB2\xD4\x48\xCE\x05\x32\x55\x8A\xFD\xB2\x64\x4C\x0E\xE4\x98\x07\x75\xDB\x7F\xDF\xB9\x08\x55\x60\x85\x30\x29\xF9\x7B\x48\xA4\x69\x86\xE3\x35\x3F\x1E\x86\x5D\x7A\x7A\x15\xBD\xEF\x00\x8E\x15\x22\x54\x17\x00\x90\x26\x93\xBC\x0E\x49\x68\x91\xBF\xF8\x47\xD3\x9D\x95\x42\xC1\x0E\x4D\xDF\x6F\x26\xCF\xC3\x18\x21\x62\x66\x43\x70\xD6\xD5\xC0\x07\xE1\x02\x03\x01\x00\x01\xA3\x74\x30\x72\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x55\xE4\x81\xD1\x11\x80\xBE\xD8\x89\xB9\x08\xA3\x31\xF9\xA1\x24\x09\x16\xB9\x70\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x55\xE4\x81\xD1\x11\x80\xBE\xD8\x89\xB9\x08\xA3\x31\xF9\xA1\x24\x09\x16\xB9\x70\x30\x1D\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x10\x30\x0E\x1B\x08\x56\x35\x2E\x30\x3A\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x59\x47\xAC\x21\x84\x8A\x17\xC9\x9C\x89\x53\x1E\xBA\x80\x85\x1A\xC6\x3C\x4E\x3E\xB1\x9C\xB6\x7C\xC6\x92\x5D\x18\x64\x02\xE3\xD3\x06\x08\x11\x61\x7C\x63\xE3\x2B\x9D\x31\x03\x70\x76\xD2\xA3\x28\xA0\xF4\xBB\x9A\x63\x73\xED\x6D\xE5\x2A\xDB\xED\x14\xA9\x2B\xC6\x36\x11\xD0\x2B\xEB\x07\x8B\xA5\xDA\x9E\x5C\x19\x9D\x56\x12\xF5\x54\x29\xC8\x05\xED\xB2\x12\x2A\x8D\xF4\x03\x1B\xFF\xE7\x92\x10\x87\xB0\x3A\xB5\xC3\x9D\x05\x37\x12\xA3\xC7\xF4\x15\xB9\xD5\xA4\x39\x16\x9B\x53\x3A\x23\x91\xF1\xA8\x82\xA2\x6A\x88\x68\xC1\x79\x02\x22\xBC\xAA\xA6\xD6\xAE\xDF\xB0\x14\x5F\xB8\x87\xD0\xDD\x7C\x7F\x7B\xFF\xAF\x1C\xCF\xE6\xDB\x07\xAD\x5E\xDB\x85\x9D\xD0\x2B\x0D\x33\xDB\x04\xD1\xE6\x49\x40\x13\x2B\x76\xFB\x3E\xE9\x9C\x89\x0F\x15\xCE\x18\xB0\x85\x78\x21\x4F\x6B\x4F\x0E\xFA\x36\x67\xCD\x07\xF2\xFF\x08\xD0\xE2\xDE\xD9\xBF\x2A\xAF\xB8\x87\x86\x21\x3C\x04\xCA\xB7\x94\x68\x7F\xCF\x3C\xE9\x98\xD7\x38\xFF\xEC\xC0\xD9\x50\xF0\x2E\x4B\x58\xAE\x46\x6F\xD0\x2E\xC3\x60\xDA\x72\x55\x72\xBD\x4C\x45\x9E\x61\xBA\xBF\x84\x81\x92\x03\xD1\xD2\x69\x7C\xC5", + ["CN=Baltimore CyberTrust Root,OU=CyberTrust,O=Baltimore,C=IE"] = "\x30\x82\x03\x77\x30\x82\x02\x5F\xA0\x03\x02\x01\x02\x02\x04\x02\x00\x00\xB9\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x45\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x13\x09\x42\x61\x6C\x74\x69\x6D\x6F\x72\x65\x31\x13\x30\x11\x06\x03\x55\x04\x0B\x13\x0A\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x42\x61\x6C\x74\x69\x6D\x6F\x72\x65\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x31\x32\x31\x38\x34\x36\x30\x30\x5A\x17\x0D\x32\x35\x30\x35\x31\x32\x32\x33\x35\x39\x30\x30\x5A\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x45\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x13\x09\x42\x61\x6C\x74\x69\x6D\x6F\x72\x65\x31\x13\x30\x11\x06\x03\x55\x04\x0B\x13\x0A\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x42\x61\x6C\x74\x69\x6D\x6F\x72\x65\x20\x43\x79\x62\x65\x72\x54\x72\x75\x73\x74\x20\x52\x6F\x6F\x74\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\xA3\x04\xBB\x22\xAB\x98\x3D\x57\xE8\x26\x72\x9A\xB5\x79\xD4\x29\xE2\xE1\xE8\x95\x80\xB1\xB0\xE3\x5B\x8E\x2B\x29\x9A\x64\xDF\xA1\x5D\xED\xB0\x09\x05\x6D\xDB\x28\x2E\xCE\x62\xA2\x62\xFE\xB4\x88\xDA\x12\xEB\x38\xEB\x21\x9D\xC0\x41\x2B\x01\x52\x7B\x88\x77\xD3\x1C\x8F\xC7\xBA\xB9\x88\xB5\x6A\x09\xE7\x73\xE8\x11\x40\xA7\xD1\xCC\xCA\x62\x8D\x2D\xE5\x8F\x0B\xA6\x50\xD2\xA8\x50\xC3\x28\xEA\xF5\xAB\x25\x87\x8A\x9A\x96\x1C\xA9\x67\xB8\x3F\x0C\xD5\xF7\xF9\x52\x13\x2F\xC2\x1B\xD5\x70\x70\xF0\x8F\xC0\x12\xCA\x06\xCB\x9A\xE1\xD9\xCA\x33\x7A\x77\xD6\xF8\xEC\xB9\xF1\x68\x44\x42\x48\x13\xD2\xC0\xC2\xA4\xAE\x5E\x60\xFE\xB6\xA6\x05\xFC\xB4\xDD\x07\x59\x02\xD4\x59\x18\x98\x63\xF5\xA5\x63\xE0\x90\x0C\x7D\x5D\xB2\x06\x7A\xF3\x85\xEA\xEB\xD4\x03\xAE\x5E\x84\x3E\x5F\xFF\x15\xED\x69\xBC\xF9\x39\x36\x72\x75\xCF\x77\x52\x4D\xF3\xC9\x90\x2C\xB9\x3D\xE5\xC9\x23\x53\x3F\x1F\x24\x98\x21\x5C\x07\x99\x29\xBD\xC6\x3A\xEC\xE7\x6E\x86\x3A\x6B\x97\x74\x63\x33\xBD\x68\x18\x31\xF0\x78\x8D\x76\xBF\xFC\x9E\x8E\x5D\x2A\x86\xA7\x4D\x90\xDC\x27\x1A\x39\x02\x03\x01\x00\x01\xA3\x45\x30\x43\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE5\x9D\x59\x30\x82\x47\x58\xCC\xAC\xFA\x08\x54\x36\x86\x7B\x3A\xB5\x04\x4D\xF0\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x03\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x85\x0C\x5D\x8E\xE4\x6F\x51\x68\x42\x05\xA0\xDD\xBB\x4F\x27\x25\x84\x03\xBD\xF7\x64\xFD\x2D\xD7\x30\xE3\xA4\x10\x17\xEB\xDA\x29\x29\xB6\x79\x3F\x76\xF6\x19\x13\x23\xB8\x10\x0A\xF9\x58\xA4\xD4\x61\x70\xBD\x04\x61\x6A\x12\x8A\x17\xD5\x0A\xBD\xC5\xBC\x30\x7C\xD6\xE9\x0C\x25\x8D\x86\x40\x4F\xEC\xCC\xA3\x7E\x38\xC6\x37\x11\x4F\xED\xDD\x68\x31\x8E\x4C\xD2\xB3\x01\x74\xEE\xBE\x75\x5E\x07\x48\x1A\x7F\x70\xFF\x16\x5C\x84\xC0\x79\x85\xB8\x05\xFD\x7F\xBE\x65\x11\xA3\x0F\xC0\x02\xB4\xF8\x52\x37\x39\x04\xD5\xA9\x31\x7A\x18\xBF\xA0\x2A\xF4\x12\x99\xF7\xA3\x45\x82\xE3\x3C\x5E\xF5\x9D\x9E\xB5\xC8\x9E\x7C\x2E\xC8\xA4\x9E\x4E\x08\x14\x4B\x6D\xFD\x70\x6D\x6B\x1A\x63\xBD\x64\xE6\x1F\xB7\xCE\xF0\xF2\x9F\x2E\xBB\x1B\xB7\xF2\x50\x88\x73\x92\xC2\xE2\xE3\x16\x8D\x9A\x32\x02\xAB\x8E\x18\xDD\xE9\x10\x11\xEE\x7E\x35\xAB\x90\xAF\x3E\x30\x94\x7A\xD0\x33\x3D\xA7\x65\x0F\xF5\xFC\x8E\x9E\x62\xCF\x47\x44\x2C\x01\x5D\xBB\x1D\xB5\x32\xD2\x47\xD2\x38\x2E\xD0\xFE\x81\xDC\x32\x6A\x1E\xB5\xEE\x3C\xD5\xFC\xE7\x81\x1D\x19\xC3\x24\x42\xEA\x63\x39\xA9", + ["CN=Equifax Secure Global eBusiness CA-1,O=Equifax Secure Inc.,C=US"] = "\x30\x82\x02\x90\x30\x82\x01\xF9\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6E\x63\x2E\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x47\x6C\x6F\x62\x61\x6C\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x31\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x17\x0D\x32\x30\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6E\x63\x2E\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x47\x6C\x6F\x62\x61\x6C\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x31\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xBA\xE7\x17\x90\x02\x65\xB1\x34\x55\x3C\x49\xC2\x51\xD5\xDF\xA7\xD1\x37\x8F\xD1\xE7\x81\x73\x41\x52\x60\x9B\x9D\xA1\x17\x26\x78\xAD\xC7\xB1\xE8\x26\x94\x32\xB5\xDE\x33\x8D\x3A\x2F\xDB\xF2\x9A\x7A\x5A\x73\x98\xA3\x5C\xE9\xFB\x8A\x73\x1B\x5C\xE7\xC3\xBF\x80\x6C\xCD\xA9\xF4\xD6\x2B\xC0\xF7\xF9\x99\xAA\x63\xA2\xB1\x47\x02\x0F\xD4\xE4\x51\x3A\x12\x3C\x6C\x8A\x5A\x54\x84\x70\xDB\xC1\xC5\x90\xCF\x72\x45\xCB\xA8\x59\xC0\xCD\x33\x9D\x3F\xA3\x96\xEB\x85\x33\x21\x1C\x3E\x1E\x3E\x60\x6E\x76\x9C\x67\x85\xC5\xC8\xC3\x61\x02\x03\x01\x00\x01\xA3\x66\x30\x64\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xBE\xA8\xA0\x74\x72\x50\x6B\x44\xB7\xC9\x23\xD8\xFB\xA8\xFF\xB3\x57\x6B\x68\x6C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xBE\xA8\xA0\x74\x72\x50\x6B\x44\xB7\xC9\x23\xD8\xFB\xA8\xFF\xB3\x57\x6B\x68\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x30\xE2\x01\x51\xAA\xC7\xEA\x5F\xDA\xB9\xD0\x65\x0F\x30\xD6\x3E\xDA\x0D\x14\x49\x6E\x91\x93\x27\x14\x31\xEF\xC4\xF7\x2D\x45\xF8\xEC\xC7\xBF\xA2\x41\x0D\x23\xB4\x92\xF9\x19\x00\x67\xBD\x01\xAF\xCD\xE0\x71\xFC\x5A\xCF\x64\xC4\xE0\x96\x98\xD0\xA3\x40\xE2\x01\x8A\xEF\x27\x07\xF1\x65\x01\x8A\x44\x2D\x06\x65\x75\x52\xC0\x86\x10\x20\x21\x5F\x6C\x6B\x0F\x6C\xAE\x09\x1C\xAF\xF2\xA2\x18\x34\xC4\x75\xA4\x73\x1C\xF1\x8D\xDC\xEF\xAD\xF9\xB3\x76\xB4\x92\xBF\xDC\x95\x10\x1E\xBE\xCB\xC8\x3B\x5A\x84\x60\x19\x56\x94\xA9\x55", + ["CN=Equifax Secure eBusiness CA-1,O=Equifax Secure Inc.,C=US"] = "\x30\x82\x02\x82\x30\x82\x01\xEB\xA0\x03\x02\x01\x02\x02\x01\x04\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6E\x63\x2E\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x31\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x17\x0D\x32\x30\x30\x36\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x30\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x49\x6E\x63\x2E\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x31\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xCE\x2F\x19\xBC\x17\xB7\x77\xDE\x93\xA9\x5F\x5A\x0D\x17\x4F\x34\x1A\x0C\x98\xF4\x22\xD9\x59\xD4\xC4\x68\x46\xF0\xB4\x35\xC5\x85\x03\x20\xC6\xAF\x45\xA5\x21\x51\x45\x41\xEB\x16\x58\x36\x32\x6F\xE2\x50\x62\x64\xF9\xFD\x51\x9C\xAA\x24\xD9\xF4\x9D\x83\x2A\x87\x0A\x21\xD3\x12\x38\x34\x6C\x8D\x00\x6E\x5A\xA0\xD9\x42\xEE\x1A\x21\x95\xF9\x52\x4C\x55\x5A\xC5\x0F\x38\x4F\x46\xFA\x6D\xF8\x2E\x35\xD6\x1D\x7C\xEB\xE2\xF0\xB0\x75\x80\xC8\xA9\x13\xAC\xBE\x88\xEF\x3A\x6E\xAB\x5F\x2A\x38\x62\x02\xB0\x12\x7B\xFE\x8F\xA6\x03\x02\x03\x01\x00\x01\xA3\x66\x30\x64\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x4A\x78\x32\x52\x11\xDB\x59\x16\x36\x5E\xDF\xC1\x14\x36\x40\x6A\x47\x7C\x4C\xA1\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x4A\x78\x32\x52\x11\xDB\x59\x16\x36\x5E\xDF\xC1\x14\x36\x40\x6A\x47\x7C\x4C\xA1\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x75\x5B\xA8\x9B\x03\x11\xE6\xE9\x56\x4C\xCD\xF9\xA9\x4C\xC0\x0D\x9A\xF3\xCC\x65\x69\xE6\x25\x76\xCC\x59\xB7\xD6\x54\xC3\x1D\xCD\x99\xAC\x19\xDD\xB4\x85\xD5\xE0\x3D\xFC\x62\x20\xA7\x84\x4B\x58\x65\xF1\xE2\xF9\x95\x21\x3F\xF5\xD4\x7E\x58\x1E\x47\x87\x54\x3E\x58\xA1\xB5\xB5\xF8\x2A\xEF\x71\xE7\xBC\xC3\xF6\xB1\x49\x46\xE2\xD7\xA0\x6B\xE5\x56\x7A\x9A\x27\x98\x7C\x46\x62\x14\xE7\xC9\xFC\x6E\x03\x12\x79\x80\x38\x1D\x48\x82\x8D\xFC\x17\xFE\x2A\x96\x2B\xB5\x62\xA6\xA6\x3D\xBD\x7F\x92\x59\xCD\x5A\x2A\x82\xB2\x37\x79", + ["OU=Equifax Secure eBusiness CA-2,O=Equifax Secure,C=US"] = "\x30\x82\x03\x20\x30\x82\x02\x89\xA0\x03\x02\x01\x02\x02\x04\x37\x70\xCF\xB5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x32\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x33\x31\x32\x31\x34\x34\x35\x5A\x17\x0D\x31\x39\x30\x36\x32\x33\x31\x32\x31\x34\x34\x35\x5A\x30\x4E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x32\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xE4\x39\x39\x93\x1E\x52\x06\x1B\x28\x36\xF8\xB2\xA3\x29\xC5\xED\x8E\xB2\x11\xBD\xFE\xEB\xE7\xB4\x74\xC2\x8F\xFF\x05\xE7\xD9\x9D\x06\xBF\x12\xC8\x3F\x0E\xF2\xD6\xD1\x24\xB2\x11\xDE\xD1\x73\x09\x8A\xD4\xB1\x2C\x98\x09\x0D\x1E\x50\x46\xB2\x83\xA6\x45\x8D\x62\x68\xBB\x85\x1B\x20\x70\x32\xAA\x40\xCD\xA6\x96\x5F\xC4\x71\x37\x3F\x04\xF3\xB7\x41\x24\x39\x07\x1A\x1E\x2E\x61\x58\xA0\x12\x0B\xE5\xA5\xDF\xC5\xAB\xEA\x37\x71\xCC\x1C\xC8\x37\x3A\xB9\x97\x52\xA7\xAC\xC5\x6A\x24\x94\x4E\x9C\x7B\xCF\xC0\x6A\xD6\xDF\x21\xBD\x02\x03\x01\x00\x01\xA3\x82\x01\x09\x30\x82\x01\x05\x30\x70\x06\x03\x55\x1D\x1F\x04\x69\x30\x67\x30\x65\xA0\x63\xA0\x61\xA4\x5F\x30\x5D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x45\x71\x75\x69\x66\x61\x78\x20\x53\x65\x63\x75\x72\x65\x20\x65\x42\x75\x73\x69\x6E\x65\x73\x73\x20\x43\x41\x2D\x32\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x1A\x06\x03\x55\x1D\x10\x04\x13\x30\x11\x81\x0F\x32\x30\x31\x39\x30\x36\x32\x33\x31\x32\x31\x34\x34\x35\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x50\x9E\x0B\xEA\xAF\x5E\xB9\x20\x48\xA6\x50\x6A\xCB\xFD\xD8\x20\x7A\xA7\x82\x76\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x50\x9E\x0B\xEA\xAF\x5E\xB9\x20\x48\xA6\x50\x6A\xCB\xFD\xD8\x20\x7A\xA7\x82\x76\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x1A\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x0D\x30\x0B\x1B\x05\x56\x33\x2E\x30\x63\x03\x02\x06\xC0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x81\x81\x00\x0C\x86\x82\xAD\xE8\x4E\x1A\xF5\x8E\x89\x27\xE2\x35\x58\x3D\x29\xB4\x07\x8F\x36\x50\x95\xBF\x6E\xC1\x9E\xEB\xC4\x90\xB2\x85\xA8\xBB\xB7\x42\xE0\x0F\x07\x39\xDF\xFB\x9E\x90\xB2\xD1\xC1\x3E\x53\x9F\x03\x44\xB0\x7E\x4B\xF4\x6F\xE4\x7C\x1F\xE7\xE2\xB1\xE4\xB8\x9A\xEF\xC3\xBD\xCE\xDE\x0B\x32\x34\xD9\xDE\x28\xED\x33\x6B\xC4\xD4\xD7\x3D\x12\x58\xAB\x7D\x09\x2D\xCB\x70\xF5\x13\x8A\x94\xA1\x27\xA4\xD6\x70\xC5\x6D\x94\xB5\xC9\x7D\x9D\xA0\xD2\xC6\x08\x49\xD9\x66\x9B\xA6\xD3\xF4\x0B\xDC\xC5\x26\x57\xE1\x91\x30\xEA\xCD", + ["CN=AddTrust Class 1 CA Root,OU=AddTrust TTP Network,O=AddTrust AB,C=SE"] = "\x30\x82\x04\x18\x30\x82\x03\x00\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x41\x64\x64\x54\x72\x75\x73\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x33\x30\x31\x30\x33\x38\x33\x31\x5A\x17\x0D\x32\x30\x30\x35\x33\x30\x31\x30\x33\x38\x33\x31\x5A\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x41\x64\x64\x54\x72\x75\x73\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x43\x41\x20\x52\x6F\x6F\x74\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\x96\x96\xD4\x21\x49\x60\xE2\x6B\xE8\x41\x07\x0C\xDE\xC4\xE0\xDC\x13\x23\xCD\xC1\x35\xC7\xFB\xD6\x4E\x11\x0A\x67\x5E\xF5\x06\x5B\x6B\xA5\x08\x3B\x5B\x29\x16\x3A\xE7\x87\xB2\x34\x06\xC5\xBC\x05\xA5\x03\x7C\x82\xCB\x29\x10\xAE\xE1\x88\x81\xBD\xD6\x9E\xD3\xFE\x2D\x56\xC1\x15\xCE\xE3\x26\x9D\x15\x2E\x10\xFB\x06\x8F\x30\x04\xDE\xA7\xB4\x63\xB4\xFF\xB1\x9C\xAE\x3C\xAF\x77\xB6\x56\xC5\xB5\xAB\xA2\xE9\x69\x3A\x3D\x0E\x33\x79\x32\x3F\x70\x82\x92\x99\x61\x6D\x8D\x30\x08\x8F\x71\x3F\xA6\x48\x57\x19\xF8\x25\xDC\x4B\x66\x5C\xA5\x74\x8F\x98\xAE\xC8\xF9\xC0\x06\x22\xE7\xAC\x73\xDF\xA5\x2E\xFB\x52\xDC\xB1\x15\x65\x20\xFA\x35\x66\x69\xDE\xDF\x2C\xF1\x6E\xBC\x30\xDB\x2C\x24\x12\xDB\xEB\x35\x35\x68\x90\xCB\x00\xB0\x97\x21\x3D\x74\x21\x23\x65\x34\x2B\xBB\x78\x59\xA3\xD6\xE1\x76\x39\x9A\xA4\x49\x8E\x8C\x74\xAF\x6E\xA4\x9A\xA3\xD9\x9B\xD2\x38\x5C\x9B\xA2\x18\xCC\x75\x23\x84\xBE\xEB\xE2\x4D\x33\x71\x8E\x1A\xF0\xC2\xF8\xC7\x1D\xA2\xAD\x03\x97\x2C\xF8\xCF\x25\xC6\xF6\xB8\x24\x31\xB1\x63\x5D\x92\x7F\x63\xF0\x25\xC9\x53\x2E\x1F\xBF\x4D\x02\x03\x01\x00\x01\xA3\x81\xD2\x30\x81\xCF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x95\xB1\xB4\xF0\x94\xB6\xBD\xC7\xDA\xD1\x11\x09\x21\xBE\xC1\xAF\x49\xFD\x10\x7B\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x8F\x06\x03\x55\x1D\x23\x04\x81\x87\x30\x81\x84\x80\x14\x95\xB1\xB4\xF0\x94\xB6\xBD\xC7\xDA\xD1\x11\x09\x21\xBE\xC1\xAF\x49\xFD\x10\x7B\xA1\x69\xA4\x67\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x41\x64\x64\x54\x72\x75\x73\x74\x20\x43\x6C\x61\x73\x73\x20\x31\x20\x43\x41\x20\x52\x6F\x6F\x74\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x2C\x6D\x64\x1B\x1F\xCD\x0D\xDD\xB9\x01\xFA\x96\x63\x34\x32\x48\x47\x99\xAE\x97\xED\xFD\x72\x16\xA6\x73\x47\x5A\xF4\xEB\xDD\xE9\xF5\xD6\xFB\x45\xCC\x29\x89\x44\x5D\xBF\x46\x39\x3D\xE8\xEE\xBC\x4D\x54\x86\x1E\x1D\x6C\xE3\x17\x27\x43\xE1\x89\x56\x2B\xA9\x6F\x72\x4E\x49\x33\xE3\x72\x7C\x2A\x23\x9A\xBC\x3E\xFF\x28\x2A\xED\xA3\xFF\x1C\x23\xBA\x43\x57\x09\x67\x4D\x4B\x62\x06\x2D\xF8\xFF\x6C\x9D\x60\x1E\xD8\x1C\x4B\x7D\xB5\x31\x2F\xD9\xD0\x7C\x5D\xF8\xDE\x6B\x83\x18\x78\x37\x57\x2F\xE8\x33\x07\x67\xDF\x1E\xC7\x6B\x2A\x95\x76\xAE\x8F\x57\xA3\xF0\xF4\x52\xB4\xA9\x53\x08\xCF\xE0\x4F\xD3\x7A\x53\x8B\xFD\xBB\x1C\x56\x36\xF2\xFE\xB2\xB6\xE5\x76\xBB\xD5\x22\x65\xA7\x3F\xFE\xD1\x66\xAD\x0B\xBC\x6B\x99\x86\xEF\x3F\x7D\xF3\x18\x32\xCA\x7B\xC6\xE3\xAB\x64\x46\x95\xF8\x26\x69\xD9\x55\x83\x7B\x2C\x96\x07\xFF\x59\x2C\x44\xA3\xC6\xE5\xE9\xA9\xDC\xA1\x63\x80\x5A\x21\x5E\x21\xCF\x53\x54\xF0\xBA\x6F\x89\xDB\xA8\xAA\x95\xCF\x8B\xE3\x71\xCC\x1E\x1B\x20\x44\x08\xC0\x7A\xB6\x40\xFD\xC4\xE4\x35\xE1\x1D\x16\x1C\xD0\xBC\x2B\x8E\xD6\x71\xD9", + ["CN=AddTrust External CA Root,OU=AddTrust External TTP Network,O=AddTrust AB,C=SE"] = "\x30\x82\x04\x36\x30\x82\x03\x1E\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x6F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x33\x30\x31\x30\x34\x38\x33\x38\x5A\x17\x0D\x32\x30\x30\x35\x33\x30\x31\x30\x34\x38\x33\x38\x5A\x30\x6F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x43\x41\x20\x52\x6F\x6F\x74\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\xB7\xF7\x1A\x33\xE6\xF2\x00\x04\x2D\x39\xE0\x4E\x5B\xED\x1F\xBC\x6C\x0F\xCD\xB5\xFA\x23\xB6\xCE\xDE\x9B\x11\x33\x97\xA4\x29\x4C\x7D\x93\x9F\xBD\x4A\xBC\x93\xED\x03\x1A\xE3\x8F\xCF\xE5\x6D\x50\x5A\xD6\x97\x29\x94\x5A\x80\xB0\x49\x7A\xDB\x2E\x95\xFD\xB8\xCA\xBF\x37\x38\x2D\x1E\x3E\x91\x41\xAD\x70\x56\xC7\xF0\x4F\x3F\xE8\x32\x9E\x74\xCA\xC8\x90\x54\xE9\xC6\x5F\x0F\x78\x9D\x9A\x40\x3C\x0E\xAC\x61\xAA\x5E\x14\x8F\x9E\x87\xA1\x6A\x50\xDC\xD7\x9A\x4E\xAF\x05\xB3\xA6\x71\x94\x9C\x71\xB3\x50\x60\x0A\xC7\x13\x9D\x38\x07\x86\x02\xA8\xE9\xA8\x69\x26\x18\x90\xAB\x4C\xB0\x4F\x23\xAB\x3A\x4F\x84\xD8\xDF\xCE\x9F\xE1\x69\x6F\xBB\xD7\x42\xD7\x6B\x44\xE4\xC7\xAD\xEE\x6D\x41\x5F\x72\x5A\x71\x08\x37\xB3\x79\x65\xA4\x59\xA0\x94\x37\xF7\x00\x2F\x0D\xC2\x92\x72\xDA\xD0\x38\x72\xDB\x14\xA8\x45\xC4\x5D\x2A\x7D\xB7\xB4\xD6\xC4\xEE\xAC\xCD\x13\x44\xB7\xC9\x2B\xDD\x43\x00\x25\xFA\x61\xB9\x69\x6A\x58\x23\x11\xB7\xA7\x33\x8F\x56\x75\x59\xF5\xCD\x29\xD7\x46\xB7\x0A\x2B\x65\xB6\xD3\x42\x6F\x15\xB2\xB8\x7B\xFB\xEF\xE9\x5D\x53\xD5\x34\x5A\x27\x02\x03\x01\x00\x01\xA3\x81\xDC\x30\x81\xD9\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xAD\xBD\x98\x7A\x34\xB4\x26\xF7\xFA\xC4\x26\x54\xEF\x03\xBD\xE0\x24\xCB\x54\x1A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x99\x06\x03\x55\x1D\x23\x04\x81\x91\x30\x81\x8E\x80\x14\xAD\xBD\x98\x7A\x34\xB4\x26\xF7\xFA\xC4\x26\x54\xEF\x03\xBD\xE0\x24\xCB\x54\x1A\xA1\x73\xA4\x71\x30\x6F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x26\x30\x24\x06\x03\x55\x04\x0B\x13\x1D\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x41\x64\x64\x54\x72\x75\x73\x74\x20\x45\x78\x74\x65\x72\x6E\x61\x6C\x20\x43\x41\x20\x52\x6F\x6F\x74\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xB0\x9B\xE0\x85\x25\xC2\xD6\x23\xE2\x0F\x96\x06\x92\x9D\x41\x98\x9C\xD9\x84\x79\x81\xD9\x1E\x5B\x14\x07\x23\x36\x65\x8F\xB0\xD8\x77\xBB\xAC\x41\x6C\x47\x60\x83\x51\xB0\xF9\x32\x3D\xE7\xFC\xF6\x26\x13\xC7\x80\x16\xA5\xBF\x5A\xFC\x87\xCF\x78\x79\x89\x21\x9A\xE2\x4C\x07\x0A\x86\x35\xBC\xF2\xDE\x51\xC4\xD2\x96\xB7\xDC\x7E\x4E\xEE\x70\xFD\x1C\x39\xEB\x0C\x02\x51\x14\x2D\x8E\xBD\x16\xE0\xC1\xDF\x46\x75\xE7\x24\xAD\xEC\xF4\x42\xB4\x85\x93\x70\x10\x67\xBA\x9D\x06\x35\x4A\x18\xD3\x2B\x7A\xCC\x51\x42\xA1\x7A\x63\xD1\xE6\xBB\xA1\xC5\x2B\xC2\x36\xBE\x13\x0D\xE6\xBD\x63\x7E\x79\x7B\xA7\x09\x0D\x40\xAB\x6A\xDD\x8F\x8A\xC3\xF6\xF6\x8C\x1A\x42\x05\x51\xD4\x45\xF5\x9F\xA7\x62\x21\x68\x15\x20\x43\x3C\x99\xE7\x7C\xBD\x24\xD8\xA9\x91\x17\x73\x88\x3F\x56\x1B\x31\x38\x18\xB4\x71\x0F\x9A\xCD\xC8\x0E\x9E\x8E\x2E\x1B\xE1\x8C\x98\x83\xCB\x1F\x31\xF1\x44\x4C\xC6\x04\x73\x49\x76\x60\x0F\xC7\xF8\xBD\x17\x80\x6B\x2E\xE9\xCC\x4C\x0E\x5A\x9A\x79\x0F\x20\x0A\x2E\xD5\x9E\x63\x26\x1E\x55\x92\x94\xD8\x82\x17\x5A\x7B\xD0\xBC\xC7\x8F\x4E\x86\x04", + ["CN=AddTrust Public CA Root,OU=AddTrust TTP Network,O=AddTrust AB,C=SE"] = "\x30\x82\x04\x15\x30\x82\x02\xFD\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x41\x64\x64\x54\x72\x75\x73\x74\x20\x50\x75\x62\x6C\x69\x63\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x33\x30\x31\x30\x34\x31\x35\x30\x5A\x17\x0D\x32\x30\x30\x35\x33\x30\x31\x30\x34\x31\x35\x30\x5A\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x41\x64\x64\x54\x72\x75\x73\x74\x20\x50\x75\x62\x6C\x69\x63\x20\x43\x41\x20\x52\x6F\x6F\x74\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\xE9\x1A\x30\x8F\x83\x88\x14\xC1\x20\xD8\x3C\x9B\x8F\x1B\x7E\x03\x74\xBB\xDA\x69\xD3\x46\xA5\xF8\x8E\xC2\x0C\x11\x90\x51\xA5\x2F\x66\x54\x40\x55\xEA\xDB\x1F\x4A\x56\xEE\x9F\x23\x6E\xF4\x39\xCB\xA1\xB9\x6F\xF2\x7E\xF9\x5D\x87\x26\x61\x9E\x1C\xF8\xE2\xEC\xA6\x81\xF8\x21\xC5\x24\xCC\x11\x0C\x3F\xDB\x26\x72\x7A\xC7\x01\x97\x07\x17\xF9\xD7\x18\x2C\x30\x7D\x0E\x7A\x1E\x62\x1E\xC6\x4B\xC0\xFD\x7D\x62\x77\xD3\x44\x1E\x27\xF6\x3F\x4B\x44\xB3\xB7\x38\xD9\x39\x1F\x60\xD5\x51\x92\x73\x03\xB4\x00\x69\xE3\xF3\x14\x4E\xEE\xD1\xDC\x09\xCF\x77\x34\x46\x50\xB0\xF8\x11\xF2\xFE\x38\x79\xF7\x07\x39\xFE\x51\x92\x97\x0B\x5B\x08\x5F\x34\x86\x01\xAD\x88\x97\xEB\x66\xCD\x5E\xD1\xFF\xDC\x7D\xF2\x84\xDA\xBA\x77\xAD\xDC\x80\x08\xC7\xA7\x87\xD6\x55\x9F\x97\x6A\xE8\xC8\x11\x64\xBA\xE7\x19\x29\x3F\x11\xB3\x78\x90\x84\x20\x52\x5B\x11\xEF\x78\xD0\x83\xF6\xD5\x48\x90\xD0\x30\x1C\xCF\x80\xF9\x60\xFE\x79\xE4\x88\xF2\xDD\x00\xEB\x94\x45\xEB\x65\x94\x69\x40\xBA\xC0\xD5\xB4\xB8\xBA\x7D\x04\x11\xA8\xEB\x31\x05\x96\x94\x4E\x58\x21\x8E\x9F\xD0\x60\xFD\x02\x03\x01\x00\x01\xA3\x81\xD1\x30\x81\xCE\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x81\x3E\x37\xD8\x92\xB0\x1F\x77\x9F\x5C\xB4\xAB\x73\xAA\xE7\xF6\x34\x60\x2F\xFA\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x8E\x06\x03\x55\x1D\x23\x04\x81\x86\x30\x81\x83\x80\x14\x81\x3E\x37\xD8\x92\xB0\x1F\x77\x9F\x5C\xB4\xAB\x73\xAA\xE7\xF6\x34\x60\x2F\xFA\xA1\x68\xA4\x66\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x41\x64\x64\x54\x72\x75\x73\x74\x20\x50\x75\x62\x6C\x69\x63\x20\x43\x41\x20\x52\x6F\x6F\x74\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x03\xF7\x15\x4A\xF8\x24\xDA\x23\x56\x16\x93\x76\xDD\x36\x28\xB9\xAE\x1B\xB8\xC3\xF1\x64\xBA\x20\x18\x78\x95\x29\x27\x57\x05\xBC\x7C\x2A\xF4\xB9\x51\x55\xDA\x87\x02\xDE\x0F\x16\x17\x31\xF8\xAA\x79\x2E\x09\x13\xBB\xAF\xB2\x20\x19\x12\xE5\x93\xF9\x4B\xF9\x83\xE8\x44\xD5\xB2\x41\x25\xBF\x88\x75\x6F\xFF\x10\xFC\x4A\x54\xD0\x5F\xF0\xFA\xEF\x36\x73\x7D\x1B\x36\x45\xC6\x21\x6D\xB4\x15\xB8\x4E\xCF\x9C\x5C\xA5\x3D\x5A\x00\x8E\x06\xE3\x3C\x6B\x32\x7B\xF2\x9F\xF0\xB6\xFD\xDF\xF0\x28\x18\x48\xF0\xC6\xBC\xD0\xBF\x34\x80\x96\xC2\x4A\xB1\x6D\x8E\xC7\x90\x45\xDE\x2F\x67\xAC\x45\x04\xA3\x7A\xDC\x55\x92\xC9\x47\x66\xD8\x1A\x8C\xC7\xED\x9C\x4E\x9A\xE0\x12\xBB\xB5\x6A\x4C\x84\xE1\xE1\x22\x0D\x87\x00\x64\xFE\x8C\x7D\x62\x39\x65\xA6\xEF\x42\xB6\x80\x25\x12\x61\x01\xA8\x24\x13\x70\x00\x11\x26\x5F\xFA\x35\x50\xC5\x48\xCC\x06\x47\xE8\x27\xD8\x70\x8D\x5F\x64\xE6\xA1\x44\x26\x5E\x22\xEC\x92\xCD\xFF\x42\x9A\x44\x21\x6D\x5C\xC5\xE3\x22\x1D\x5F\x47\x12\xE7\xCE\x5F\x5D\xFA\xD8\xAA\xB1\x33\x2D\xD9\x76\xF2\x4E\x3A\x33\x0C\x2B\xB3\x2D\x90\x06", + ["CN=AddTrust Qualified CA Root,OU=AddTrust TTP Network,O=AddTrust AB,C=SE"] = "\x30\x82\x04\x1E\x30\x82\x03\x06\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x67\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x41\x64\x64\x54\x72\x75\x73\x74\x20\x51\x75\x61\x6C\x69\x66\x69\x65\x64\x20\x43\x41\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x30\x30\x35\x33\x30\x31\x30\x34\x34\x35\x30\x5A\x17\x0D\x32\x30\x30\x35\x33\x30\x31\x30\x34\x34\x35\x30\x5A\x30\x67\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x41\x64\x64\x54\x72\x75\x73\x74\x20\x51\x75\x61\x6C\x69\x66\x69\x65\x64\x20\x43\x41\x20\x52\x6F\x6F\x74\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\xE4\x1E\x9A\xFE\xDC\x09\x5A\x87\xA4\x9F\x47\xBE\x11\x5F\xAF\x84\x34\xDB\x62\x3C\x79\x78\xB7\xE9\x30\xB5\xEC\x0C\x1C\x2A\xC4\x16\xFF\xE0\xEC\x71\xEB\x8A\xF5\x11\x6E\xED\x4F\x0D\x91\xD2\x12\x18\x2D\x49\x15\x01\xC2\xA4\x22\x13\xC7\x11\x64\xFF\x22\x12\x9A\xB9\x8E\x5C\x2F\x08\xCF\x71\x6A\xB3\x67\x01\x59\xF1\x5D\x46\xF3\xB0\x78\xA5\xF6\x0E\x42\x7A\xE3\x7F\x1B\xCC\xD0\xF0\xB7\x28\xFD\x2A\xEA\x9E\xB3\xB0\xB9\x04\xAA\xFD\xF6\xC7\xB4\xB1\xB8\x2A\xA0\xFB\x58\xF1\x19\xA0\x6F\x70\x25\x7E\x3E\x69\x4A\x7F\x0F\x22\xD8\xEF\xAD\x08\x11\x9A\x29\x99\xE1\xAA\x44\x45\x9A\x12\x5E\x3E\x9D\x6D\x52\xFC\xE7\xA0\x3D\x68\x2F\xF0\x4B\x70\x7C\x13\x38\xAD\xBC\x15\x25\xF1\xD6\xCE\xAB\xA2\xC0\x31\xD6\x2F\x9F\xE0\xFF\x14\x59\xFC\x84\x93\xD9\x87\x7C\x4C\x54\x13\xEB\x9F\xD1\x2D\x11\xF8\x18\x3A\x3A\xDE\x25\xD9\xF7\xD3\x40\xED\xA4\x06\x12\xC4\x3B\xE1\x91\xC1\x56\x35\xF0\x14\xDC\x65\x36\x09\x6E\xAB\xA4\x07\xC7\x35\xD1\xC2\x03\x33\x36\x5B\x75\x26\x6D\x42\xF1\x12\x6B\x43\x6F\x4B\x71\x94\xFA\x34\x1D\xED\x13\x6E\xCA\x80\x7F\x98\x2F\x6C\xB9\x65\xD8\xE9\x02\x03\x01\x00\x01\xA3\x81\xD4\x30\x81\xD1\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x39\x95\x8B\x62\x8B\x5C\xC9\xD4\x80\xBA\x58\x0F\x97\x3F\x15\x08\x43\xCC\x98\xA7\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x91\x06\x03\x55\x1D\x23\x04\x81\x89\x30\x81\x86\x80\x14\x39\x95\x8B\x62\x8B\x5C\xC9\xD4\x80\xBA\x58\x0F\x97\x3F\x15\x08\x43\xCC\x98\xA7\xA1\x6B\xA4\x69\x30\x67\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x45\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x41\x64\x64\x54\x72\x75\x73\x74\x20\x41\x42\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x41\x64\x64\x54\x72\x75\x73\x74\x20\x54\x54\x50\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x41\x64\x64\x54\x72\x75\x73\x74\x20\x51\x75\x61\x6C\x69\x66\x69\x65\x64\x20\x43\x41\x20\x52\x6F\x6F\x74\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x19\xAB\x75\xEA\xF8\x8B\x65\x61\x95\x13\xBA\x69\x04\xEF\x86\xCA\x13\xA0\xC7\xAA\x4F\x64\x1B\x3F\x18\xF6\xA8\x2D\x2C\x55\x8F\x05\xB7\x30\xEA\x42\x6A\x1D\xC0\x25\x51\x2D\xA7\xBF\x0C\xB3\xED\xEF\x08\x7F\x6C\x3C\x46\x1A\xEA\x18\x43\xDF\x76\xCC\xF9\x66\x86\x9C\x2C\x68\xF5\xE9\x17\xF8\x31\xB3\x18\xC4\xD6\x48\x7D\x23\x4C\x68\xC1\x7E\xBB\x01\x14\x6F\xC5\xD9\x6E\xDE\xBB\x04\x42\x6A\xF8\xF6\x5C\x7D\xE5\xDA\xFA\x87\xEB\x0D\x35\x52\x67\xD0\x9E\x97\x76\x05\x93\x3F\x95\xC7\x01\xE6\x69\x55\x38\x7F\x10\x61\x99\xC9\xE3\x5F\xA6\xCA\x3E\x82\x63\x48\xAA\xE2\x08\x48\x3E\xAA\xF2\xB2\x85\x62\xA6\xB4\xA7\xD9\xBD\x37\x9C\x68\xB5\x2D\x56\x7D\xB0\xB7\x3F\xA0\xB1\x07\xD6\xE9\x4F\xDC\xDE\x45\x71\x30\x32\x7F\x1B\x2E\x09\xF9\xBF\x52\xA1\xEE\xC2\x80\x3E\x06\x5C\x2E\x55\x40\xC1\x1B\xF5\x70\x45\xB0\xDC\x5D\xFA\xF6\x72\x5A\x77\xD2\x63\xCD\xCF\x58\x89\x00\x42\x63\x3F\x79\x39\xD0\x44\xB0\x82\x6E\x41\x19\xE8\xDD\xE0\xC1\x88\x5A\xD1\x1E\x71\x93\x1F\x24\x30\x74\xE5\x1E\xA8\xDE\x3C\x27\x37\x7F\x83\xAE\x9E\x77\xCF\xF0\x30\xB1\xFF\x4B\x99\xE8\xC6\xA1", + ["CN=Entrust Root Certification Authority,OU=(c) 2006 Entrust\, Inc.,OU=www.entrust.net/CPS is incorporated by reference,O=Entrust\, Inc.,C=US"] = "\x30\x82\x04\x91\x30\x82\x03\x79\xA0\x03\x02\x01\x02\x02\x04\x45\x6B\x50\x54\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xB0\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x45\x6E\x74\x72\x75\x73\x74\x2C\x20\x49\x6E\x63\x2E\x31\x39\x30\x37\x06\x03\x55\x04\x0B\x13\x30\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x73\x20\x69\x6E\x63\x6F\x72\x70\x6F\x72\x61\x74\x65\x64\x20\x62\x79\x20\x72\x65\x66\x65\x72\x65\x6E\x63\x65\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x28\x63\x29\x20\x32\x30\x30\x36\x20\x45\x6E\x74\x72\x75\x73\x74\x2C\x20\x49\x6E\x63\x2E\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x45\x6E\x74\x72\x75\x73\x74\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x36\x31\x31\x32\x37\x32\x30\x32\x33\x34\x32\x5A\x17\x0D\x32\x36\x31\x31\x32\x37\x32\x30\x35\x33\x34\x32\x5A\x30\x81\xB0\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x45\x6E\x74\x72\x75\x73\x74\x2C\x20\x49\x6E\x63\x2E\x31\x39\x30\x37\x06\x03\x55\x04\x0B\x13\x30\x77\x77\x77\x2E\x65\x6E\x74\x72\x75\x73\x74\x2E\x6E\x65\x74\x2F\x43\x50\x53\x20\x69\x73\x20\x69\x6E\x63\x6F\x72\x70\x6F\x72\x61\x74\x65\x64\x20\x62\x79\x20\x72\x65\x66\x65\x72\x65\x6E\x63\x65\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x28\x63\x29\x20\x32\x30\x30\x36\x20\x45\x6E\x74\x72\x75\x73\x74\x2C\x20\x49\x6E\x63\x2E\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x45\x6E\x74\x72\x75\x73\x74\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xB6\x95\xB6\x43\x42\xFA\xC6\x6D\x2A\x6F\x48\xDF\x94\x4C\x39\x57\x05\xEE\xC3\x79\x11\x41\x68\x36\xED\xEC\xFE\x9A\x01\x8F\xA1\x38\x28\xFC\xF7\x10\x46\x66\x2E\x4D\x1E\x1A\xB1\x1A\x4E\xC6\xD1\xC0\x95\x88\xB0\xC9\xFF\x31\x8B\x33\x03\xDB\xB7\x83\x7B\x3E\x20\x84\x5E\xED\xB2\x56\x28\xA7\xF8\xE0\xB9\x40\x71\x37\xC5\xCB\x47\x0E\x97\x2A\x68\xC0\x22\x95\x62\x15\xDB\x47\xD9\xF5\xD0\x2B\xFF\x82\x4B\xC9\xAD\x3E\xDE\x4C\xDB\x90\x80\x50\x3F\x09\x8A\x84\x00\xEC\x30\x0A\x3D\x18\xCD\xFB\xFD\x2A\x59\x9A\x23\x95\x17\x2C\x45\x9E\x1F\x6E\x43\x79\x6D\x0C\x5C\x98\xFE\x48\xA7\xC5\x23\x47\x5C\x5E\xFD\x6E\xE7\x1E\xB4\xF6\x68\x45\xD1\x86\x83\x5B\xA2\x8A\x8D\xB1\xE3\x29\x80\xFE\x25\x71\x88\xAD\xBE\xBC\x8F\xAC\x52\x96\x4B\xAA\x51\x8D\xE4\x13\x31\x19\xE8\x4E\x4D\x9F\xDB\xAC\xB3\x6A\xD5\xBC\x39\x54\x71\xCA\x7A\x7A\x7F\x90\xDD\x7D\x1D\x80\xD9\x81\xBB\x59\x26\xC2\x11\xFE\xE6\x93\xE2\xF7\x80\xE4\x65\xFB\x34\x37\x0E\x29\x80\x70\x4D\xAF\x38\x86\x2E\x9E\x7F\x57\xAF\x9E\x17\xAE\xEB\x1C\xCB\x28\x21\x5F\xB6\x1C\xD8\xE7\xA2\x04\x22\xF9\xD3\xDA\xD8\xCB\x02\x03\x01\x00\x01\xA3\x81\xB0\x30\x81\xAD\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x32\x30\x30\x36\x31\x31\x32\x37\x32\x30\x32\x33\x34\x32\x5A\x81\x0F\x32\x30\x32\x36\x31\x31\x32\x37\x32\x30\x35\x33\x34\x32\x5A\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x68\x90\xE4\x67\xA4\xA6\x53\x80\xC7\x86\x66\xA4\xF1\xF7\x4B\x43\xFB\x84\xBD\x6D\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x68\x90\xE4\x67\xA4\xA6\x53\x80\xC7\x86\x66\xA4\xF1\xF7\x4B\x43\xFB\x84\xBD\x6D\x30\x1D\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x10\x30\x0E\x1B\x08\x56\x37\x2E\x31\x3A\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x93\xD4\x30\xB0\xD7\x03\x20\x2A\xD0\xF9\x63\xE8\x91\x0C\x05\x20\xA9\x5F\x19\xCA\x7B\x72\x4E\xD4\xB1\xDB\xD0\x96\xFB\x54\x5A\x19\x2C\x0C\x08\xF7\xB2\xBC\x85\xA8\x9D\x7F\x6D\x3B\x52\xB3\x2A\xDB\xE7\xD4\x84\x8C\x63\xF6\x0F\xCB\x26\x01\x91\x50\x6C\xF4\x5F\x14\xE2\x93\x74\xC0\x13\x9E\x30\x3A\x50\xE3\xB4\x60\xC5\x1C\xF0\x22\x44\x8D\x71\x47\xAC\xC8\x1A\xC9\xE9\x9B\x9A\x00\x60\x13\xFF\x70\x7E\x5F\x11\x4D\x49\x1B\xB3\x15\x52\x7B\xC9\x54\xDA\xBF\x9D\x95\xAF\x6B\x9A\xD8\x9E\xE9\xF1\xE4\x43\x8D\xE2\x11\x44\x3A\xBF\xAF\xBD\x83\x42\x73\x52\x8B\xAA\xBB\xA7\x29\xCF\xF5\x64\x1C\x0A\x4D\xD1\xBC\xAA\xAC\x9F\x2A\xD0\xFF\x7F\x7F\xDA\x7D\xEA\xB1\xED\x30\x25\xC1\x84\xDA\x34\xD2\x5B\x78\x83\x56\xEC\x9C\x36\xC3\x26\xE2\x11\xF6\x67\x49\x1D\x92\xAB\x8C\xFB\xEB\xFF\x7A\xEE\x85\x4A\xA7\x50\x80\xF0\xA7\x5C\x4A\x94\x2E\x5F\x05\x99\x3C\x52\x41\xE0\xCD\xB4\x63\xCF\x01\x43\xBA\x9C\x83\xDC\x8F\x60\x3B\xF3\x5A\xB4\xB4\x7B\xAE\xDA\x0B\x90\x38\x75\xEF\x81\x1D\x66\xD2\xF7\x57\x70\x36\xB3\xBF\xFC\x28\xAF\x71\x25\x85\x5B\x13\xFE\x1E\x7F\x5A\xB4\x3C", + ["OU=RSA Security 2048 V3,O=RSA Security Inc"] = "\x30\x82\x03\x61\x30\x82\x02\x49\xA0\x03\x02\x01\x02\x02\x10\x0A\x01\x01\x01\x00\x00\x02\x7C\x00\x00\x00\x0A\x00\x00\x00\x02\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3A\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x52\x53\x41\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x49\x6E\x63\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x52\x53\x41\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x32\x30\x34\x38\x20\x56\x33\x30\x1E\x17\x0D\x30\x31\x30\x32\x32\x32\x32\x30\x33\x39\x32\x33\x5A\x17\x0D\x32\x36\x30\x32\x32\x32\x32\x30\x33\x39\x32\x33\x5A\x30\x3A\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x52\x53\x41\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x49\x6E\x63\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x52\x53\x41\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x32\x30\x34\x38\x20\x56\x33\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\xB7\x8F\x55\x71\xD2\x80\xDD\x7B\x69\x79\xA7\xF0\x18\x50\x32\x3C\x62\x67\xF6\x0A\x95\x07\xDD\xE6\x1B\xF3\x9E\xD9\xD2\x41\x54\x6B\xAD\x9F\x7C\xBE\x19\xCD\xFB\x46\xAB\x41\x68\x1E\x18\xEA\x55\xC8\x2F\x91\x78\x89\x28\xFB\x27\x29\x60\xFF\xDF\x8F\x8C\x3B\xC9\x49\x9B\xB5\xA4\x94\xCE\x01\xEA\x3E\xB5\x63\x7B\x7F\x26\xFD\x19\xDD\xC0\x21\xBD\x84\xD1\x2D\x4F\x46\xC3\x4E\xDC\xD8\x37\x39\x3B\x28\xAF\xCB\x9D\x1A\xEA\x2B\xAF\x21\xA5\xC1\x23\x22\xB8\xB8\x1B\x5A\x13\x87\x57\x83\xD1\xF0\x20\xE7\xE8\x4F\x23\x42\xB0\x00\xA5\x7D\x89\xE9\xE9\x61\x73\x94\x98\x71\x26\xBC\x2D\x6A\xE0\xF7\x4D\xF0\xF1\xB6\x2A\x38\x31\x81\x0D\x29\xE1\x00\xC1\x51\x0F\x4C\x52\xF8\x04\x5A\xAA\x7D\x72\xD3\xB8\x87\x2A\xBB\x63\x10\x03\x2A\xB3\xA1\x4F\x0D\x5A\x5E\x46\xB7\x3D\x0E\xF5\x74\xEC\x99\x9F\xF9\x3D\x24\x81\x88\xA6\xDD\x60\x54\xE8\x95\x36\x3D\xC6\x09\x93\x9A\xA3\x12\x80\x00\x55\x99\x19\x47\xBD\xD0\xA5\x7C\xC3\xBA\xFB\x1F\xF7\xF5\x0F\xF8\xAC\xB9\xB5\xF4\x37\x98\x13\x18\xDE\x85\x5B\xB7\x0C\x82\x3B\x87\x6F\x95\x39\x58\x30\xDA\x6E\x01\x68\x17\x22\xCC\xC0\x0B\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x07\xC3\x51\x30\xA4\xAA\xE9\x45\xAE\x35\x24\xFA\xFF\x24\x2C\x33\xD0\xB1\x9D\x8C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x07\xC3\x51\x30\xA4\xAA\xE9\x45\xAE\x35\x24\xFA\xFF\x24\x2C\x33\xD0\xB1\x9D\x8C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5F\x3E\x86\x76\x6E\xB8\x35\x3C\x4E\x36\x1C\x1E\x79\x98\xBF\xFD\xD5\x12\x11\x79\x52\x0E\xEE\x31\x89\xBC\xDD\x7F\xF9\xD1\xC6\x15\x21\xE8\x8A\x01\x54\x0D\x3A\xFB\x54\xB9\xD6\x63\xD4\xB1\xAA\x96\x4D\xA2\x42\x4D\xD4\x53\x1F\x8B\x10\xDE\x7F\x65\xBE\x60\x13\x27\x71\x88\xA4\x73\xE3\x84\x63\xD1\xA4\x55\xE1\x50\x93\xE6\x1B\x0E\x79\xD0\x67\xBC\x46\xC8\xBF\x3F\x17\x0D\x95\xE6\xC6\x90\x69\xDE\xE7\xB4\x2F\xDE\x95\x7D\xD0\x12\x3F\x3D\x3E\x7F\x4D\x3F\x14\x68\xF5\x11\x50\xD5\xC1\xF4\x90\xA5\x08\x1D\x31\x60\xFF\x60\x8C\x23\x54\x0A\xAF\xFE\xA1\x6E\xC5\xD1\x7A\x2A\x68\x78\xCF\x1E\x82\x0A\x20\xB4\x1F\xAD\xE5\x85\xB2\x6A\x68\x75\x4E\xAD\x25\x37\x94\x85\xBE\xBD\xA1\xD4\xEA\xB7\x0C\x4B\x3C\x9D\xE8\x12\x00\xF0\x5F\xAC\x0D\xE1\xAC\x70\x63\x73\xF7\x7F\x79\x9F\x32\x25\x42\x74\x05\x80\x28\xBF\xBD\xC1\x24\x96\x58\x15\xB1\x17\x21\xE9\x89\x4B\xDB\x07\x88\x67\xF4\x15\xAD\x70\x3E\x2F\x4D\x85\x3B\xC2\xB7\xDB\xFE\x98\x68\x23\x89\xE1\x74\x0F\xDE\xF4\xC5\x84\x63\x29\x1B\xCC\xCB\x07\xC9\x00\xA4\xA9\xD7\xC2\x22\x4F\x67\xD7\x77\xEC\x20\x05\x61\xDE", + ["CN=GeoTrust Global CA,O=GeoTrust Inc.,C=US"] = "\x30\x82\x03\x54\x30\x82\x02\x3C\xA0\x03\x02\x01\x02\x02\x03\x02\x34\x56\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x42\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x41\x30\x1E\x17\x0D\x30\x32\x30\x35\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x17\x0D\x32\x32\x30\x35\x32\x31\x30\x34\x30\x30\x30\x30\x5A\x30\x42\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x41\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\xDA\xCC\x18\x63\x30\xFD\xF4\x17\x23\x1A\x56\x7E\x5B\xDF\x3C\x6C\x38\xE4\x71\xB7\x78\x91\xD4\xBC\xA1\xD8\x4C\xF8\xA8\x43\xB6\x03\xE9\x4D\x21\x07\x08\x88\xDA\x58\x2F\x66\x39\x29\xBD\x05\x78\x8B\x9D\x38\xE8\x05\xB7\x6A\x7E\x71\xA4\xE6\xC4\x60\xA6\xB0\xEF\x80\xE4\x89\x28\x0F\x9E\x25\xD6\xED\x83\xF3\xAD\xA6\x91\xC7\x98\xC9\x42\x18\x35\x14\x9D\xAD\x98\x46\x92\x2E\x4F\xCA\xF1\x87\x43\xC1\x16\x95\x57\x2D\x50\xEF\x89\x2D\x80\x7A\x57\xAD\xF2\xEE\x5F\x6B\xD2\x00\x8D\xB9\x14\xF8\x14\x15\x35\xD9\xC0\x46\xA3\x7B\x72\xC8\x91\xBF\xC9\x55\x2B\xCD\xD0\x97\x3E\x9C\x26\x64\xCC\xDF\xCE\x83\x19\x71\xCA\x4E\xE6\xD4\xD5\x7B\xA9\x19\xCD\x55\xDE\xC8\xEC\xD2\x5E\x38\x53\xE5\x5C\x4F\x8C\x2D\xFE\x50\x23\x36\xFC\x66\xE6\xCB\x8E\xA4\x39\x19\x00\xB7\x95\x02\x39\x91\x0B\x0E\xFE\x38\x2E\xD1\x1D\x05\x9A\xF6\x4D\x3E\x6F\x0F\x07\x1D\xAF\x2C\x1E\x8F\x60\x39\xE2\xFA\x36\x53\x13\x39\xD4\x5E\x26\x2B\xDB\x3D\xA8\x14\xBD\x32\xEB\x18\x03\x28\x52\x04\x71\xE5\xAB\x33\x3D\xE1\x38\xBB\x07\x36\x84\x62\x9C\x79\xEA\x16\x30\xF4\x5F\xC0\x2B\xE8\x71\x6B\xE4\xF9\x02\x03\x01\x00\x01\xA3\x53\x30\x51\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC0\x7A\x98\x68\x8D\x89\xFB\xAB\x05\x64\x0C\x11\x7D\xAA\x7D\x65\xB8\xCA\xCC\x4E\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xC0\x7A\x98\x68\x8D\x89\xFB\xAB\x05\x64\x0C\x11\x7D\xAA\x7D\x65\xB8\xCA\xCC\x4E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x35\xE3\x29\x6A\xE5\x2F\x5D\x54\x8E\x29\x50\x94\x9F\x99\x1A\x14\xE4\x8F\x78\x2A\x62\x94\xA2\x27\x67\x9E\xD0\xCF\x1A\x5E\x47\xE9\xC1\xB2\xA4\xCF\xDD\x41\x1A\x05\x4E\x9B\x4B\xEE\x4A\x6F\x55\x52\xB3\x24\xA1\x37\x0A\xEB\x64\x76\x2A\x2E\x2C\xF3\xFD\x3B\x75\x90\xBF\xFA\x71\xD8\xC7\x3D\x37\xD2\xB5\x05\x95\x62\xB9\xA6\xDE\x89\x3D\x36\x7B\x38\x77\x48\x97\xAC\xA6\x20\x8F\x2E\xA6\xC9\x0C\xC2\xB2\x99\x45\x00\xC7\xCE\x11\x51\x22\x22\xE0\xA5\xEA\xB6\x15\x48\x09\x64\xEA\x5E\x4F\x74\xF7\x05\x3E\xC7\x8A\x52\x0C\xDB\x15\xB4\xBD\x6D\x9B\xE5\xC6\xB1\x54\x68\xA9\xE3\x69\x90\xB6\x9A\xA5\x0F\xB8\xB9\x3F\x20\x7D\xAE\x4A\xB5\xB8\x9C\xE4\x1D\xB6\xAB\xE6\x94\xA5\xC1\xC7\x83\xAD\xDB\xF5\x27\x87\x0E\x04\x6C\xD5\xFF\xDD\xA0\x5D\xED\x87\x52\xB7\x2B\x15\x02\xAE\x39\xA6\x6A\x74\xE9\xDA\xC4\xE7\xBC\x4D\x34\x1E\xA9\x5C\x4D\x33\x5F\x92\x09\x2F\x88\x66\x5D\x77\x97\xC7\x1D\x76\x13\xA9\xD5\xE5\xF1\x16\x09\x11\x35\xD5\xAC\xDB\x24\x71\x70\x2C\x98\x56\x0B\xD9\x17\xB4\xD1\xE3\x51\x2B\x5E\x75\xE8\xD5\xD0\xDC\x4F\x34\xED\xC2\x05\x66\x80\xA1\xCB\xE6\x33", + ["CN=GeoTrust Global CA 2,O=GeoTrust Inc.,C=US"] = "\x30\x82\x03\x66\x30\x82\x02\x4E\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x44\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x1D\x30\x1B\x06\x03\x55\x04\x03\x13\x14\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x41\x20\x32\x30\x1E\x17\x0D\x30\x34\x30\x33\x30\x34\x30\x35\x30\x30\x30\x30\x5A\x17\x0D\x31\x39\x30\x33\x30\x34\x30\x35\x30\x30\x30\x30\x5A\x30\x44\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x1D\x30\x1B\x06\x03\x55\x04\x03\x13\x14\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x41\x20\x32\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\xEF\x3C\x4D\x40\x3D\x10\xDF\x3B\x53\x00\xE1\x67\xFE\x94\x60\x15\x3E\x85\x88\xF1\x89\x0D\x90\xC8\x28\x23\x99\x05\xE8\x2B\x20\x9D\xC6\xF3\x60\x46\xD8\xC1\xB2\xD5\x8C\x31\xD9\xDC\x20\x79\x24\x81\xBF\x35\x32\xFC\x63\x69\xDB\xB1\x2A\x6B\xEE\x21\x58\xF2\x08\xE9\x78\xCB\x6F\xCB\xFC\x16\x52\xC8\x91\xC4\xFF\x3D\x73\xDE\xB1\x3E\xA7\xC2\x7D\x66\xC1\xF5\x7E\x52\x24\x1A\xE2\xD5\x67\x91\xD0\x82\x10\xD7\x78\x4B\x4F\x2B\x42\x39\xBD\x64\x2D\x40\xA0\xB0\x10\xD3\x38\x48\x46\x88\xA1\x0C\xBB\x3A\x33\x2A\x62\x98\xFB\x00\x9D\x13\x59\x7F\x6F\x3B\x72\xAA\xEE\xA6\x0F\x86\xF9\x05\x61\xEA\x67\x7F\x0C\x37\x96\x8B\xE6\x69\x16\x47\x11\xC2\x27\x59\x03\xB3\xA6\x60\xC2\x21\x40\x56\xFA\xA0\xC7\x7D\x3A\x13\xE3\xEC\x57\xC7\xB3\xD6\xAE\x9D\x89\x80\xF7\x01\xE7\x2C\xF6\x96\x2B\x13\x0D\x79\x2C\xD9\xC0\xE4\x86\x7B\x4B\x8C\x0C\x72\x82\x8A\xFB\x17\xCD\x00\x6C\x3A\x13\x3C\xB0\x84\x87\x4B\x16\x7A\x29\xB2\x4F\xDB\x1D\xD4\x0B\xF3\x66\x37\xBD\xD8\xF6\x57\xBB\x5E\x24\x7A\xB8\x3C\x8B\xB9\xFA\x92\x1A\x1A\x84\x9E\xD8\x74\x8F\xAA\x1B\x7F\x5E\xF4\xFE\x45\x22\x21\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x71\x38\x36\xF2\x02\x31\x53\x47\x2B\x6E\xBA\x65\x46\xA9\x10\x15\x58\x20\x05\x09\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x71\x38\x36\xF2\x02\x31\x53\x47\x2B\x6E\xBA\x65\x46\xA9\x10\x15\x58\x20\x05\x09\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x03\xF7\xB5\x2B\xAB\x5D\x10\xFC\x7B\xB2\xB2\x5E\xAC\x9B\x0E\x7E\x53\x78\x59\x3E\x42\x04\xFE\x75\xA3\xAD\xAC\x81\x4E\xD7\x02\x8B\x5E\xC4\x2D\xC8\x52\x76\xC7\x2C\x1F\xFC\x81\x32\x98\xD1\x4B\xC6\x92\x93\x33\x35\x31\x2F\xFC\xD8\x1D\x44\xDD\xE0\x81\x7F\x9D\xE9\x8B\xE1\x64\x91\x62\x0B\x39\x08\x8C\xAC\x74\x9D\x59\xD9\x7A\x59\x52\x97\x11\xB9\x16\x7B\x6F\x45\xD3\x96\xD9\x31\x7D\x02\x36\x0F\x9C\x3B\x6E\xCF\x2C\x0D\x03\x46\x45\xEB\xA0\xF4\x7F\x48\x44\xC6\x08\x40\xCC\xDE\x1B\x70\xB5\x29\xAD\xBA\x8B\x3B\x34\x65\x75\x1B\x71\x21\x1D\x2C\x14\x0A\xB0\x96\x95\xB8\xD6\xEA\xF2\x65\xFB\x29\xBA\x4F\xEA\x91\x93\x74\x69\xB6\xF2\xFF\xE1\x1A\xD0\x0C\xD1\x76\x85\xCB\x8A\x25\xBD\x97\x5E\x2C\x6F\x15\x99\x26\xE7\xB6\x29\xFF\x22\xEC\xC9\x02\xC7\x56\x00\xCD\x49\xB9\xB3\x6C\x7B\x53\x04\x1A\xE2\xA8\xC9\xAA\x12\x05\x23\xC2\xCE\xE7\xBB\x04\x02\xCC\xC0\x47\xA2\xE4\xC4\x29\x2F\x5B\x45\x57\x89\x51\xEE\x3C\xEB\x52\x08\xFF\x07\x35\x1E\x9F\x35\x6A\x47\x4A\x56\x98\xD1\x5A\x85\x1F\x8C\xF5\x22\xBF\xAB\xCE\x83\xF3\xE2\x22\x29\xAE\x7D\x83\x40\xA8\xBA\x6C", + ["CN=GeoTrust Universal CA,O=GeoTrust Inc.,C=US"] = "\x30\x82\x05\x68\x30\x82\x03\x50\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x1E\x30\x1C\x06\x03\x55\x04\x03\x13\x15\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x30\x1E\x17\x0D\x30\x34\x30\x33\x30\x34\x30\x35\x30\x30\x30\x30\x5A\x17\x0D\x32\x39\x30\x33\x30\x34\x30\x35\x30\x30\x30\x30\x5A\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x1E\x30\x1C\x06\x03\x55\x04\x03\x13\x15\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xA6\x15\x55\xA0\xA3\xC6\xE0\x1F\x8C\x9D\x21\x50\xD7\xC1\xBE\x2B\x5B\xB5\xA4\x9E\xA1\xD9\x72\x58\xBD\x00\x1B\x4C\xBF\x61\xC9\x14\x1D\x45\x82\xAB\xC6\x1D\x80\xD6\x3D\xEB\x10\x9C\x3A\xAF\x6D\x24\xF8\xBC\x71\x01\x9E\x06\xF5\x7C\x5F\x1E\xC1\x0E\x55\xCA\x83\x9A\x59\x30\xAE\x19\xCB\x30\x48\x95\xED\x22\x37\x8D\xF4\x4A\x9A\x72\x66\x3E\xAD\x95\xC0\xE0\x16\x00\xE0\x10\x1F\x2B\x31\x0E\xD7\x94\x54\xD3\x42\x33\xA0\x34\x1D\x1E\x45\x76\xDD\x4F\xCA\x18\x37\xEC\x85\x15\x7A\x19\x08\xFC\xD5\xC7\x9C\xF0\xF2\xA9\x2E\x10\xA9\x92\xE6\x3D\x58\x3D\xA9\x16\x68\x3C\x2F\x75\x21\x18\x7F\x28\x77\xA5\xE1\x61\x17\xB7\xA6\xE9\xF8\x1E\x99\xDB\x73\x6E\xF4\x0A\xA2\x21\x6C\xEE\xDA\xAA\x85\x92\x66\xAF\xF6\x7A\x6B\x82\xDA\xBA\x22\x08\x35\x0F\xCF\x42\xF1\x35\xFA\x6A\xEE\x7E\x2B\x25\xCC\x3A\x11\xE4\x6D\xAF\x73\xB2\x76\x1D\xAD\xD0\xB2\x78\x67\x1A\xA4\x39\x1C\x51\x0B\x67\x56\x83\xFD\x38\x5D\x0D\xCE\xDD\xF0\xBB\x2B\x96\x1F\xDE\x7B\x32\x52\xFD\x1D\xBB\xB5\x06\xA1\xB2\x21\x5E\xA5\xD6\x95\x68\x7F\xF0\x99\x9E\xDC\x45\x08\x3E\xE7\xD2\x09\x0D\x35\x94\xDD\x80\x4E\x53\x97\xD7\xB5\x09\x44\x20\x64\x16\x17\x03\x02\x4C\x53\x0D\x68\xDE\xD5\xAA\x72\x4D\x93\x6D\x82\x0E\xDB\x9C\xBD\xCF\xB4\xF3\x5C\x5D\x54\x7A\x69\x09\x96\xD6\xDB\x11\xC1\x8D\x75\xA8\xB4\xCF\x39\xC8\xCE\x3C\xBC\x24\x7C\xE6\x62\xCA\xE1\xBD\x7D\xA7\xBD\x57\x65\x0B\xE4\xFE\x25\xED\xB6\x69\x10\xDC\x28\x1A\x46\xBD\x01\x1D\xD0\x97\xB5\xE1\x98\x3B\xC0\x37\x64\xD6\x3D\x94\xEE\x0B\xE1\xF5\x28\xAE\x0B\x56\xBF\x71\x8B\x23\x29\x41\x8E\x86\xC5\x4B\x52\x7B\xD8\x71\xAB\x1F\x8A\x15\xA6\x3B\x83\x5A\xD7\x58\x01\x51\xC6\x4C\x41\xD9\x7F\xD8\x41\x67\x72\xA2\x28\xDF\x60\x83\xA9\x9E\xC8\x7B\xFC\x53\x73\x72\x59\xF5\x93\x7A\x17\x76\x0E\xCE\xF7\xE5\x5C\xD9\x0B\x55\x34\xA2\xAA\x5B\xB5\x6A\x54\xE7\x13\xCA\x57\xEC\x97\x6D\xF4\x5E\x06\x2F\x45\x8B\x58\xD4\x23\x16\x92\xE4\x16\x6E\x28\x63\x59\x30\xDF\x50\x01\x9C\x63\x89\x1A\x9F\xDB\x17\x94\x82\x70\x37\xC3\x24\x9E\x9A\x47\xD6\x5A\xCA\x4E\xA8\x69\x89\x72\x1F\x91\x6C\xDB\x7E\x9E\x1B\xAD\xC7\x1F\x73\xDD\x2C\x4F\x19\x65\xFD\x7F\x93\x40\x10\x2E\xD2\xF0\xED\x3C\x9E\x2E\x28\x3E\x69\x26\x33\xC5\x7B\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xDA\xBB\x2E\xAA\xB0\x0C\xB8\x88\x26\x51\x74\x5C\x6D\x03\xD3\xC0\xD8\x8F\x7A\xD6\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xDA\xBB\x2E\xAA\xB0\x0C\xB8\x88\x26\x51\x74\x5C\x6D\x03\xD3\xC0\xD8\x8F\x7A\xD6\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x31\x78\xE6\xC7\xB5\xDF\xB8\x94\x40\xC9\x71\xC4\xA8\x35\xEC\x46\x1D\xC2\x85\xF3\x28\x58\x86\xB0\x0B\xFC\x8E\xB2\x39\x8F\x44\x55\xAB\x64\x84\x5C\x69\xA9\xD0\x9A\x38\x3C\xFA\xE5\x1F\x35\xE5\x44\xE3\x80\x79\x94\x68\xA4\xBB\xC4\x9F\x3D\xE1\x34\xCD\x30\x46\x8B\x54\x2B\x95\xA5\xEF\xF7\x3F\x99\x84\xFD\x35\xE6\xCF\x31\xC6\xDC\x6A\xBF\xA7\xD7\x23\x08\xE1\x98\x5E\xC3\x5A\x08\x76\xA9\xA6\xAF\x77\x2F\xB7\x60\xBD\x44\x46\x6A\xEF\x97\xFF\x73\x95\xC1\x8E\xE8\x93\xFB\xFD\x31\xB7\xEC\x57\x11\x11\x45\x9B\x30\xF1\x1A\x88\x39\xC1\x4F\x3C\xA7\x00\xD5\xC7\xFC\xAB\x6D\x80\x22\x70\xA5\x0C\xE0\x5D\x04\x29\x02\xFB\xCB\xA0\x91\xD1\x7C\xD6\xC3\x7E\x50\xD5\x9D\x58\xBE\x41\x38\xEB\xB9\x75\x3C\x15\xD9\x9B\xC9\x4A\x83\x59\xC0\xDA\x53\xFD\x33\xBB\x36\x18\x9B\x85\x0F\x15\xDD\xEE\x2D\xAC\x76\x93\xB9\xD9\x01\x8D\x48\x10\xA8\xFB\xF5\x38\x86\xF1\xDB\x0A\xC6\xBD\x84\xA3\x23\x41\xDE\xD6\x77\x6F\x85\xD4\x85\x1C\x50\xE0\xAE\x51\x8A\xBA\x8D\x3E\x76\xE2\xB9\xCA\x27\xF2\x5F\x9F\xEF\x6E\x59\x0D\x06\xD8\x2B\x17\xA4\xD2\x7C\x6B\xBB\x5F\x14\x1A\x48\x8F\x1A\x4C\xE7\xB3\x47\x1C\x8E\x4C\x45\x2B\x20\xEE\x48\xDF\xE7\xDD\x09\x8E\x18\xA8\xDA\x40\x8D\x92\x26\x11\x53\x61\x73\x5D\xEB\xBD\xE7\xC4\x4D\x29\x37\x61\xEB\xAC\x39\x2D\x67\x2E\x16\xD6\xF5\x00\x83\x85\xA1\xCC\x7F\x76\xC4\x7D\xE4\xB7\x4B\x66\xEF\x03\x45\x60\x69\xB6\x0C\x52\x96\x92\x84\x5E\xA6\xA3\xB5\xA4\x3E\x2B\xD9\xCC\xD8\x1B\x47\xAA\xF2\x44\xDA\x4F\xF9\x03\xE8\xF0\x14\xCB\x3F\xF3\x83\xDE\xD0\xC1\x54\xE3\xB7\xE8\x0A\x37\x4D\x8B\x20\x59\x03\x30\x19\xA1\x2C\xC8\xBD\x11\x1F\xDF\xAE\xC9\x4A\xC5\xF3\x27\x66\x66\x86\xAC\x68\x91\xFF\xD9\xE6\x53\x1C\x0F\x8B\x5C\x69\x65\x0A\x26\xC8\x1E\x34\xC3\x5D\x51\x7B\xD7\xA9\x9C\x06\xA1\x36\xDD\xD5\x89\x94\xBC\xD9\xE4\x2D\x0C\x5E\x09\x6C\x08\x97\x7C\xA3\x3D\x7C\x93\xFF\x3F\xA1\x14\xA7\xCF\xB5\x5D\xEB\xDB\xDB\x1C\xC4\x76\xDF\x88\xB9\xBD\x45\x05\x95\x1B\xAE\xFC\x46\x6A\x4C\xAF\x48\xE3\xCE\xAE\x0F\xD2\x7E\xEB\xE6\x6C\x9C\x4F\x81\x6A\x7A\x64\xAC\xBB\x3E\xD5\xE7\xCB\x76\x2E\xC5\xA7\x48\xC1\x5C\x90\x0F\xCB\xC8\x3F\xFA\xE6\x32\xE1\x8D\x1B\x6F\xA4\xE6\x8E\xD8\xF9\x29\x48\x8A\xCE\x73\xFE\x2C", + ["CN=GeoTrust Universal CA 2,O=GeoTrust Inc.,C=US"] = "\x30\x82\x05\x6C\x30\x82\x03\x54\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x47\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x32\x30\x1E\x17\x0D\x30\x34\x30\x33\x30\x34\x30\x35\x30\x30\x30\x30\x5A\x17\x0D\x32\x39\x30\x33\x30\x34\x30\x35\x30\x30\x30\x30\x5A\x30\x47\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xB3\x54\x52\xC1\xC9\x3E\xF2\xD9\xDC\xB1\x53\x1A\x59\x29\xE7\xB1\xC3\x45\x28\xE5\xD7\xD1\xED\xC5\xC5\x4B\xA1\xAA\x74\x7B\x57\xAF\x4A\x26\xFC\xD8\xF5\x5E\xA7\x6E\x19\xDB\x74\x0C\x4F\x35\x5B\x32\x0B\x01\xE3\xDB\xEB\x7A\x77\x35\xEA\xAA\x5A\xE0\xD6\xE8\xA1\x57\x94\xF0\x90\xA3\x74\x56\x94\x44\x30\x03\x1E\x5C\x4E\x2B\x85\x26\x74\x82\x7A\x0C\x76\xA0\x6F\x4D\xCE\x41\x2D\xA0\x15\x06\x14\x5F\xB7\x42\xCD\x7B\x8F\x58\x61\x34\xDC\x2A\x08\xF9\x2E\xC3\x01\xA6\x22\x44\x1C\x4C\x07\x82\xE6\x5B\xCE\xD0\x4A\x7C\x04\xD3\x19\x73\x27\xF0\xAA\x98\x7F\x2E\xAF\x4E\xEB\x87\x1E\x24\x77\x6A\x5D\xB6\xE8\x5B\x45\xBA\xDC\xC3\xA1\x05\x6F\x56\x8E\x8F\x10\x26\xA5\x49\xC3\x2E\xD7\x41\x87\x22\xE0\x4F\x86\xCA\x60\xB5\xEA\xA1\x63\xC0\x01\x97\x10\x79\xBD\x00\x3C\x12\x6D\x2B\x15\xB1\xAC\x4B\xB1\xEE\x18\xB9\x4E\x96\xDC\xDC\x76\xFF\x3B\xBE\xCF\x5F\x03\xC0\xFC\x3B\xE8\xBE\x46\x1B\xFF\xDA\x40\xC2\x52\xF7\xFE\xE3\x3A\xF7\x6A\x77\x35\xD0\xDA\x8D\xEB\x5E\x18\x6A\x31\xC7\x1E\xBA\x3C\x1B\x28\xD6\x6B\x54\xC6\xAA\x5B\xD7\xA2\x2C\x1B\x19\xCC\xA2\x02\xF6\x9B\x59\xBD\x37\x6B\x86\xB5\x6D\x82\xBA\xD8\xEA\xC9\x56\xBC\xA9\x36\x58\xFD\x3E\x19\xF3\xED\x0C\x26\xA9\x93\x38\xF8\x4F\xC1\x5D\x22\x06\xD0\x97\xEA\xE1\xAD\xC6\x55\xE0\x81\x2B\x28\x83\x3A\xFA\xF4\x7B\x21\x51\x00\xBE\x52\x38\xCE\xCD\x66\x79\xA8\xF4\x81\x56\xE2\xD0\x83\x09\x47\x51\x5B\x50\x6A\xCF\xDB\x48\x1A\x5D\x3E\xF7\xCB\xF6\x65\xF7\x6C\xF1\x95\xF8\x02\x3B\x32\x56\x82\x39\x7A\x5B\xBD\x2F\x89\x1B\xBF\xA1\xB4\xE8\xFF\x7F\x8D\x8C\xDF\x03\xF1\x60\x4E\x58\x11\x4C\xEB\xA3\x3F\x10\x2B\x83\x9A\x01\x73\xD9\x94\x6D\x84\x00\x27\x66\xAC\xF0\x70\x40\x09\x42\x92\xAD\x4F\x93\x0D\x61\x09\x51\x24\xD8\x92\xD5\x0B\x94\x61\xB2\x87\xB2\xED\xFF\x9A\x35\xFF\x85\x54\xCA\xED\x44\x43\xAC\x1B\x3C\x16\x6B\x48\x4A\x0A\x1C\x40\x88\x1F\x92\xC2\x0B\x00\x05\xFF\xF2\xC8\x02\x4A\xA4\xAA\xA9\xCC\x99\x96\x9C\x2F\x58\xE0\x7D\xE1\xBE\xBB\x07\xDC\x5F\x04\x72\x5C\x31\x34\xC3\xEC\x5F\x2D\xE0\x3D\x64\x90\x22\xE6\xD1\xEC\xB8\x2E\xDD\x59\xAE\xD9\xA1\x37\xBF\x54\x35\xDC\x73\x32\x4F\x8C\x04\x1E\x33\xB2\xC9\x46\xF1\xD8\x5C\xC8\x55\x50\xC9\x68\xBD\xA8\xBA\x36\x09\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x76\xF3\x55\xE1\xFA\xA4\x36\xFB\xF0\x9F\x5C\x62\x71\xED\x3C\xF4\x47\x38\x10\x2B\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x76\xF3\x55\xE1\xFA\xA4\x36\xFB\xF0\x9F\x5C\x62\x71\xED\x3C\xF4\x47\x38\x10\x2B\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x66\xC1\xC6\x23\xF3\xD9\xE0\x2E\x6E\x5F\xE8\xCF\xAE\xB0\xB0\x25\x4D\x2B\xF8\x3B\x58\x9B\x40\x24\x37\x5A\xCB\xAB\x16\x49\xFF\xB3\x75\x79\x33\xA1\x2F\x6D\x70\x17\x34\x91\xFE\x67\x7E\x8F\xEC\x9B\xE5\x5E\x82\xA9\x55\x1F\x2F\xDC\xD4\x51\x07\x12\xFE\xAC\x16\x3E\x2C\x35\xC6\x63\xFC\xDC\x10\xEB\x0D\xA3\xAA\xD0\x7C\xCC\xD1\xD0\x2F\x51\x2E\xC4\x14\x5A\xDE\xE8\x19\xE1\x3E\xC6\xCC\xA4\x29\xE7\x2E\x84\xAA\x06\x30\x78\x76\x54\x73\x28\x98\x59\x38\xE0\x00\x0D\x62\xD3\x42\x7D\x21\x9F\xAE\x3D\x3A\x8C\xD5\xFA\x77\x0D\x18\x2B\x16\x0E\x5F\x36\xE1\xFC\x2A\xB5\x30\x24\xCF\xE0\x63\x0C\x7B\x58\x1A\xFE\x99\xBA\x42\x12\xB1\x91\xF4\x7C\x68\xE2\xC8\xE8\xAF\x2C\xEA\xC9\x7E\xAE\xBB\x2A\x3D\x0D\x15\xDC\x34\x95\xB6\x18\x74\xA8\x6A\x0F\xC7\xB4\xF4\x13\xC4\xE4\x5B\xED\x0A\xD2\xA4\x97\x4C\x2A\xED\x2F\x6C\x12\x89\x3D\xF1\x27\x70\xAA\x6A\x03\x52\x21\x9F\x40\xA8\x67\x50\xF2\xF3\x5A\x1F\xDF\xDF\x23\xF6\xDC\x78\x4E\xE6\x98\x4F\x55\x3A\x53\xE3\xEF\xF2\xF4\x9F\xC7\x7C\xD8\x58\xAF\x29\x22\x97\xB8\xE0\xBD\x91\x2E\xB0\x76\xEC\x57\x11\xCF\xEF\x29\x44\xF3\xE9\x85\x7A\x60\x63\xE4\x5D\x33\x89\x17\xD9\x31\xAA\xDA\xD6\xF3\x18\x35\x72\xCF\x87\x2B\x2F\x63\x23\x84\x5D\x84\x8C\x3F\x57\xA0\x88\xFC\x99\x91\x28\x26\x69\x99\xD4\x8F\x97\x44\xBE\x8E\xD5\x48\xB1\xA4\x28\x29\xF1\x15\xB4\xE1\xE5\x9E\xDD\xF8\x8F\xA6\x6F\x26\xD7\x09\x3C\x3A\x1C\x11\x0E\xA6\x6C\x37\xF7\xAD\x44\x87\x2C\x28\xC7\xD8\x74\x82\xB3\xD0\x6F\x4A\x57\xBB\x35\x29\x27\xA0\x8B\xE8\x21\xA7\x87\x64\x36\x5D\xCC\xD8\x16\xAC\xC7\xB2\x27\x40\x92\x55\x38\x28\x8D\x51\x6E\xDD\x14\x67\x53\x6C\x71\x5C\x26\x84\x4D\x75\x5A\xB6\x7E\x60\x56\xA9\x4D\xAD\xFB\x9B\x1E\x97\xF3\x0D\xD9\xD2\x97\x54\x77\xDA\x3D\x12\xB7\xE0\x1E\xEF\x08\x06\xAC\xF9\x85\x87\xE9\xA2\xDC\xAF\x7E\x18\x12\x83\xFD\x56\x17\x41\x2E\xD5\x29\x82\x7D\x99\xF4\x31\xF6\x71\xA9\xCF\x2C\x01\x27\xA5\x05\xB9\xAA\xB2\x48\x4E\x2A\xEF\x9F\x93\x52\x51\x95\x3C\x52\x73\x8E\x56\x4C\x17\x40\xC0\x09\x28\xE4\x8B\x6A\x48\x53\xDB\xEC\xCD\x55\x55\xF1\xC6\xF8\xE9\xA2\x2C\x4C\xA6\xD1\x26\x5F\x7E\xAF\x5A\x4C\xDA\x1F\xA6\xF2\x1C\x2C\x7E\xAE\x02\x16\xD2\x56\xD0\x2F\x57\x53\x47\xE8\x92", + ["CN=America Online Root Certification Authority 1,O=America Online Inc.,C=US"] = "\x30\x82\x03\xA4\x30\x82\x02\x8C\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x49\x6E\x63\x2E\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x31\x30\x1E\x17\x0D\x30\x32\x30\x35\x32\x38\x30\x36\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x31\x31\x39\x32\x30\x34\x33\x30\x30\x5A\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x49\x6E\x63\x2E\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x31\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\xA8\x2F\xE8\xA4\x69\x06\x03\x47\xC3\xE9\x2A\x98\xFF\x19\xA2\x70\x9A\xC6\x50\xB2\x7E\xA5\xDF\x68\x4D\x1B\x7C\x0F\xB6\x97\x68\x7D\x2D\xA6\x8B\x97\xE9\x64\x86\xC9\xA3\xEF\xA0\x86\xBF\x60\x65\x9C\x4B\x54\x88\xC2\x48\xC5\x4A\x39\xBF\x14\xE3\x59\x55\xE5\x19\xB4\x74\xC8\xB4\x05\x39\x5C\x16\xA5\xE2\x95\x05\xE0\x12\xAE\x59\x8B\xA2\x33\x68\x58\x1C\xA6\xD4\x15\xB7\xD8\x9F\xD7\xDC\x71\xAB\x7E\x9A\xBF\x9B\x8E\x33\x0F\x22\xFD\x1F\x2E\xE7\x07\x36\xEF\x62\x39\xC5\xDD\xCB\xBA\x25\x14\x23\xDE\x0C\xC6\x3D\x3C\xCE\x82\x08\xE6\x66\x3E\xDA\x51\x3B\x16\x3A\xA3\x05\x7F\xA0\xDC\x87\xD5\x9C\xFC\x72\xA9\xA0\x7D\x78\xE4\xB7\x31\x55\x1E\x65\xBB\xD4\x61\xB0\x21\x60\xED\x10\x32\x72\xC5\x92\x25\x1E\xF8\x90\x4A\x18\x78\x47\xDF\x7E\x30\x37\x3E\x50\x1B\xDB\x1C\xD3\x6B\x9A\x86\x53\x07\xB0\xEF\xAC\x06\x78\xF8\x84\x99\xFE\x21\x8D\x4C\x80\xB6\x0C\x82\xF6\x66\x70\x79\x1A\xD3\x4F\xA3\xCF\xF1\xCF\x46\xB0\x4B\x0F\x3E\xDD\x88\x62\xB8\x8C\xA9\x09\x28\x3B\x7A\xC7\x97\xE1\x1E\xE5\xF4\x9F\xC0\xC0\xAE\x24\xA0\xC8\xA1\xD9\x0F\xD6\x7B\x26\x82\x69\x32\x3D\xA7\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x00\xAD\xD9\xA3\xF6\x79\xF6\x6E\x74\xA9\x7F\x33\x3D\x81\x17\xD7\x4C\xCF\x33\xDE\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x00\xAD\xD9\xA3\xF6\x79\xF6\x6E\x74\xA9\x7F\x33\x3D\x81\x17\xD7\x4C\xCF\x33\xDE\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7C\x8A\xD1\x1F\x18\x37\x82\xE0\xB8\xB0\xA3\xED\x56\x95\xC8\x62\x61\x9C\x05\xA2\xCD\xC2\x62\x26\x61\xCD\x10\x16\xD7\xCC\xB4\x65\x34\xD0\x11\x8A\xAD\xA8\xA9\x05\x66\xEF\x74\xF3\x6D\x5F\x9D\x99\xAF\xF6\x8B\xFB\xEB\x52\xB2\x05\x98\xA2\x6F\x2A\xC5\x54\xBD\x25\xBD\x5F\xAE\xC8\x86\xEA\x46\x2C\xC1\xB3\xBD\xC1\xE9\x49\x70\x18\x16\x97\x08\x13\x8C\x20\xE0\x1B\x2E\x3A\x47\xCB\x1E\xE4\x00\x30\x95\x5B\xF4\x45\xA3\xC0\x1A\xB0\x01\x4E\xAB\xBD\xC0\x23\x6E\x63\x3F\x80\x4A\xC5\x07\xED\xDC\xE2\x6F\xC7\xC1\x62\xF1\xE3\x72\xD6\x04\xC8\x74\x67\x0B\xFA\x88\xAB\xA1\x01\xC8\x6F\xF0\x14\xAF\xD2\x99\xCD\x51\x93\x7E\xED\x2E\x38\xC7\xBD\xCE\x46\x50\x3D\x72\xE3\x79\x25\x9D\x9B\x88\x2B\x10\x20\xDD\xA5\xB8\x32\x9F\x8D\xE0\x29\xDF\x21\x74\x86\x82\xDB\x2F\x82\x30\xC6\xC7\x35\x86\xB3\xF9\x96\x5F\x46\xDB\x0C\x45\xFD\xF3\x50\xC3\x6F\xC6\xC3\x48\xAD\x46\xA6\xE1\x27\x47\x0A\x1D\x0E\x9B\xB6\xC2\x77\x7F\x63\xF2\xE0\x7D\x1A\xBE\xFC\xE0\xDF\xD7\xC7\xA7\x6C\xB0\xF9\xAE\xBA\x3C\xFD\x74\xB4\x11\xE8\x58\x0D\x80\xBC\xD3\xA8\x80\x3A\x99\xED\x75\xCC\x46\x7B", + ["CN=America Online Root Certification Authority 2,O=America Online Inc.,C=US"] = "\x30\x82\x05\xA4\x30\x82\x03\x8C\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x49\x6E\x63\x2E\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x32\x30\x1E\x17\x0D\x30\x32\x30\x35\x32\x38\x30\x36\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x30\x39\x32\x39\x31\x34\x30\x38\x30\x30\x5A\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x49\x6E\x63\x2E\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x41\x6D\x65\x72\x69\x63\x61\x20\x4F\x6E\x6C\x69\x6E\x65\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xCC\x41\x45\x1D\xE9\x3D\x4D\x10\xF6\x8C\xB1\x41\xC9\xE0\x5E\xCB\x0D\xB7\xBF\x47\x73\xD3\xF0\x55\x4D\xDD\xC6\x0C\xFA\xB1\x66\x05\x6A\xCD\x78\xB4\xDC\x02\xDB\x4E\x81\xF3\xD7\xA7\x7C\x71\xBC\x75\x63\xA0\x5D\xE3\x07\x0C\x48\xEC\x25\xC4\x03\x20\xF4\xFF\x0E\x3B\x12\xFF\x9B\x8D\xE1\xC6\xD5\x1B\xB4\x6D\x22\xE3\xB1\xDB\x7F\x21\x64\xAF\x86\xBC\x57\x22\x2A\xD6\x47\x81\x57\x44\x82\x56\x53\xBD\x86\x14\x01\x0B\xFC\x7F\x74\xA4\x5A\xAE\xF1\xBA\x11\xB5\x9B\x58\x5A\x80\xB4\x37\x78\x09\x33\x7C\x32\x47\x03\x5C\xC4\xA5\x83\x48\xF4\x57\x56\x6E\x81\x36\x27\x18\x4F\xEC\x9B\x28\xC2\xD4\xB4\xD7\x7C\x0C\x3E\x0C\x2B\xDF\xCA\x04\xD7\xC6\x8E\xEA\x58\x4E\xA8\xA4\xA5\x18\x1C\x6C\x45\x98\xA3\x41\xD1\x2D\xD2\xC7\x6D\x8D\x19\xF1\xAD\x79\xB7\x81\x3F\xBD\x06\x82\x27\x2D\x10\x58\x05\xB5\x78\x05\xB9\x2F\xDB\x0C\x6B\x90\x90\x7E\x14\x59\x38\xBB\x94\x24\x13\xE5\xD1\x9D\x14\xDF\xD3\x82\x4D\x46\xF0\x80\x39\x52\x32\x0F\xE3\x84\xB2\x7A\x43\xF2\x5E\xDE\x5F\x3F\x1D\xDD\xE3\xB2\x1B\xA0\xA1\x2A\x23\x03\x6E\x2E\x01\x15\x87\x5C\xA6\x75\x75\xC7\x97\x61\xBE\xDE\x86\xDC\xD4\x48\xDB\xBD\x2A\xBF\x4A\x55\xDA\xE8\x7D\x50\xFB\xB4\x80\x17\xB8\x94\xBF\x01\x3D\xEA\xDA\xBA\x7C\xE0\x58\x67\x17\xB9\x58\xE0\x88\x86\x46\x67\x6C\x9D\x10\x47\x58\x32\xD0\x35\x7C\x79\x2A\x90\xA2\x5A\x10\x11\x23\x35\xAD\x2F\xCC\xE4\x4A\x5B\xA7\xC8\x27\xF2\x83\xDE\x5E\xBB\x5E\x77\xE7\xE8\xA5\x6E\x63\xC2\x0D\x5D\x61\xD0\x8C\xD2\x6C\x5A\x21\x0E\xCA\x28\xA3\xCE\x2A\xE9\x95\xC7\x48\xCF\x96\x6F\x1D\x92\x25\xC8\xC6\xC6\xC1\xC1\x0C\x05\xAC\x26\xC4\xD2\x75\xD2\xE1\x2A\x67\xC0\x3D\x5B\xA5\x9A\xEB\xCF\x7B\x1A\xA8\x9D\x14\x45\xE5\x0F\xA0\x9A\x65\xDE\x2F\x28\xBD\xCE\x6F\x94\x66\x83\x48\x29\xD8\xEA\x65\x8C\xAF\x93\xD9\x64\x9F\x55\x57\x26\xBF\x6F\xCB\x37\x31\x99\xA3\x60\xBB\x1C\xAD\x89\x34\x32\x62\xB8\x43\x21\x06\x72\x0C\xA1\x5C\x6D\x46\xC5\xFA\x29\xCF\x30\xDE\x89\xDC\x71\x5B\xDD\xB6\x37\x3E\xDF\x50\xF5\xB8\x07\x25\x26\xE5\xBC\xB5\xFE\x3C\x02\xB3\xB7\xF8\xBE\x43\xC1\x87\x11\x94\x9E\x23\x6C\x17\x8A\xB8\x8A\x27\x0C\x54\x47\xF0\xA9\xB3\xC0\x80\x8C\xA0\x27\xEB\x1D\x19\xE3\x07\x8E\x77\x70\xCA\x2B\xF4\x7D\x76\xE0\x78\x67\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x4D\x45\xC1\x68\x38\xBB\x73\xA9\x69\xA1\x20\xE7\xED\xF5\x22\xA1\x23\x14\xD7\x9E\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x4D\x45\xC1\x68\x38\xBB\x73\xA9\x69\xA1\x20\xE7\xED\xF5\x22\xA1\x23\x14\xD7\x9E\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x67\x6B\x06\xB9\x5F\x45\x3B\x2A\x4B\x33\xB3\xE6\x1B\x6B\x59\x4E\x22\xCC\xB9\xB7\xA4\x25\xC9\xA7\xC4\xF0\x54\x96\x0B\x64\xF3\xB1\x58\x4F\x5E\x51\xFC\xB2\x97\x7B\x27\x65\xC2\xE5\xCA\xE7\x0D\x0C\x25\x7B\x62\xE3\xFA\x9F\xB4\x87\xB7\x45\x46\xAF\x83\xA5\x97\x48\x8C\xA5\xBD\xF1\x16\x2B\x9B\x76\x2C\x7A\x35\x60\x6C\x11\x80\x97\xCC\xA9\x92\x52\xE6\x2B\xE6\x69\xED\xA9\xF8\x36\x2D\x2C\x77\xBF\x61\x48\xD1\x63\x0B\xB9\x5B\x52\xED\x18\xB0\x43\x42\x22\xA6\xB1\x77\xAE\xDE\x69\xC5\xCD\xC7\x1C\xA1\xB1\xA5\x1C\x10\xFB\x18\xBE\x1A\x70\xDD\xC1\x92\x4B\xBE\x29\x5A\x9D\x3F\x35\xBE\xE5\x7D\x51\xF8\x55\xE0\x25\x75\x23\x87\x1E\x5C\xDC\xBA\x9D\xB0\xAC\xB3\x69\xDB\x17\x83\xC9\xF7\xDE\x0C\xBC\x08\xDC\x91\x9E\xA8\xD0\xD7\x15\x37\x73\xA5\x35\xB8\xFC\x7E\xC5\x44\x40\x06\xC3\xEB\xF8\x22\x80\x5C\x47\xCE\x02\xE3\x11\x9F\x44\xFF\xFD\x9A\x32\xCC\x7D\x64\x51\x0E\xEB\x57\x26\x76\x3A\xE3\x1E\x22\x3C\xC2\xA6\x36\xDD\x19\xEF\xA7\xFC\x12\xF3\x26\xC0\x59\x31\x85\x4C\x9C\xD8\xCF\xDF\xA4\xCC\xCC\x29\x93\xFF\x94\x6D\x76\x5C\x13\x08\x97\xF2\xED\xA5\x0B\x4D\xDD\xE8\xC9\x68\x0E\x66\xD3\x00\x0E\x33\x12\x5B\xBC\x95\xE5\x32\x90\xA8\xB3\xC6\x6C\x83\xAD\x77\xEE\x8B\x7E\x7E\xB1\xA9\xAB\xD3\xE1\xF1\xB6\xC0\xB1\xEA\x88\xC0\xE7\xD3\x90\xE9\x28\x92\x94\x7B\x68\x7B\x97\x2A\x0A\x67\x2D\x85\x02\x38\x10\xE4\x03\x61\xD4\xDA\x25\x36\xC7\x08\x58\x2D\xA1\xA7\x51\xAF\x30\x0A\x49\xF5\xA6\x69\x87\x07\x2D\x44\x46\x76\x8E\x2A\xE5\x9A\x3B\xD7\x18\xA2\xFC\x9C\x38\x10\xCC\xC6\x3B\xD2\xB5\x17\x3A\x6F\xFD\xAE\x25\xBD\xF5\x72\x59\x64\xB1\x74\x2A\x38\x5F\x18\x4C\xDF\xCF\x71\x04\x5A\x36\xD4\xBF\x2F\x99\x9C\xE8\xD9\xBA\xB1\x95\xE6\x02\x4B\x21\xA1\x5B\xD5\xC1\x4F\x8F\xAE\x69\x6D\x53\xDB\x01\x93\xB5\x5C\x1E\x18\xDD\x64\x5A\xCA\x18\x28\x3E\x63\x04\x11\xFD\x1C\x8D\x00\x0F\xB8\x37\xDF\x67\x8A\x9D\x66\xA9\x02\x6A\x91\xFF\x13\xCA\x2F\x5D\x83\xBC\x87\x93\x6C\xDC\x24\x51\x16\x04\x25\x66\xFA\xB3\xD9\xC2\xBA\x29\xBE\x9A\x48\x38\x82\x99\xF4\xBF\x3B\x4A\x31\x19\xF9\xBF\x8E\x21\x33\x14\xCA\x4F\x54\x5F\xFB\xCE\xFB\x8F\x71\x7F\xFD\x5E\x19\xA0\x0F\x4B\x91\xB8\xC4\x54\xBC\x06\xB0\x45\x8F\x26\x91\xA2\x8E\xFE\xA9", + ["CN=Visa eCommerce Root,OU=Visa International Service Association,O=VISA,C=US"] = "\x30\x82\x03\xA2\x30\x82\x02\x8A\xA0\x03\x02\x01\x02\x02\x10\x13\x86\x35\x4D\x1D\x3F\x06\xF2\xC1\xF9\x65\x05\xD5\x90\x1C\x62\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x6B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0D\x30\x0B\x06\x03\x55\x04\x0A\x13\x04\x56\x49\x53\x41\x31\x2F\x30\x2D\x06\x03\x55\x04\x0B\x13\x26\x56\x69\x73\x61\x20\x49\x6E\x74\x65\x72\x6E\x61\x74\x69\x6F\x6E\x61\x6C\x20\x53\x65\x72\x76\x69\x63\x65\x20\x41\x73\x73\x6F\x63\x69\x61\x74\x69\x6F\x6E\x31\x1C\x30\x1A\x06\x03\x55\x04\x03\x13\x13\x56\x69\x73\x61\x20\x65\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x32\x30\x36\x32\x36\x30\x32\x31\x38\x33\x36\x5A\x17\x0D\x32\x32\x30\x36\x32\x34\x30\x30\x31\x36\x31\x32\x5A\x30\x6B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0D\x30\x0B\x06\x03\x55\x04\x0A\x13\x04\x56\x49\x53\x41\x31\x2F\x30\x2D\x06\x03\x55\x04\x0B\x13\x26\x56\x69\x73\x61\x20\x49\x6E\x74\x65\x72\x6E\x61\x74\x69\x6F\x6E\x61\x6C\x20\x53\x65\x72\x76\x69\x63\x65\x20\x41\x73\x73\x6F\x63\x69\x61\x74\x69\x6F\x6E\x31\x1C\x30\x1A\x06\x03\x55\x04\x03\x13\x13\x56\x69\x73\x61\x20\x65\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\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\xAF\x57\xDE\x56\x1E\x6E\xA1\xDA\x60\xB1\x94\x27\xCB\x17\xDB\x07\x3F\x80\x85\x4F\xC8\x9C\xB6\xD0\xF4\x6F\x4F\xCF\x99\xD8\xE1\xDB\xC2\x48\x5C\x3A\xAC\x39\x33\xC7\x1F\x6A\x8B\x26\x3D\x2B\x35\xF5\x48\xB1\x91\xC1\x02\x4E\x04\x96\x91\x7B\xB0\x33\xF0\xB1\x14\x4E\x11\x6F\xB5\x40\xAF\x1B\x45\xA5\x4A\xEF\x7E\xB6\xAC\xF2\xA0\x1F\x58\x3F\x12\x46\x60\x3C\x8D\xA1\xE0\x7D\xCF\x57\x3E\x33\x1E\xFB\x47\xF1\xAA\x15\x97\x07\x55\x66\xA5\xB5\x2D\x2E\xD8\x80\x59\xB2\xA7\x0D\xB7\x46\xEC\x21\x63\xFF\x35\xAB\xA5\x02\xCF\x2A\xF4\x4C\xFE\x7B\xF5\x94\x5D\x84\x4D\xA8\xF2\x60\x8F\xDB\x0E\x25\x3C\x9F\x73\x71\xCF\x94\xDF\x4A\xEA\xDB\xDF\x72\x38\x8C\xF3\x96\xBD\xF1\x17\xBC\xD2\xBA\x3B\x45\x5A\xC6\xA7\xF6\xC6\x17\x8B\x01\x9D\xFC\x19\xA8\x2A\x83\x16\xB8\x3A\x48\xFE\x4E\x3E\xA0\xAB\x06\x19\xE9\x53\xF3\x80\x13\x07\xED\x2D\xBF\x3F\x0A\x3C\x55\x20\x39\x2C\x2C\x00\x69\x74\x95\x4A\xBC\x20\xB2\xA9\x79\xE5\x18\x89\x91\xA8\xDC\x1C\x4D\xEF\xBB\x7E\x37\x0B\x5D\xFE\x39\xA5\x88\x52\x8C\x00\x6C\xEC\x18\x7C\x41\xBD\xF6\x8B\x75\x77\xBA\x60\x9D\x84\xE7\xFE\x2D\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x15\x38\x83\x0F\x3F\x2C\x3F\x70\x33\x1E\xCD\x46\xFE\x07\x8C\x20\xE0\xD7\xC3\xB7\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5F\xF1\x41\x7D\x7C\x5C\x08\xB9\x2B\xE0\xD5\x92\x47\xFA\x67\x5C\xA5\x13\xC3\x03\x21\x9B\x2B\x4C\x89\x46\xCF\x59\x4D\xC9\xFE\xA5\x40\xB6\x63\xCD\xDD\x71\x28\x95\x67\x11\xCC\x24\xAC\xD3\x44\x6C\x71\xAE\x01\x20\x6B\x03\xA2\x8F\x18\xB7\x29\x3A\x7D\xE5\x16\x60\x53\x78\x3C\xC0\xAF\x15\x83\xF7\x8F\x52\x33\x24\xBD\x64\x93\x97\xEE\x8B\xF7\xDB\x18\xA8\x6D\x71\xB3\xF7\x2C\x17\xD0\x74\x25\x69\xF7\xFE\x6B\x3C\x94\xBE\x4D\x4B\x41\x8C\x4E\xE2\x73\xD0\xE3\x90\x22\x73\x43\xCD\xF3\xEF\xEA\x73\xCE\x45\x8A\xB0\xA6\x49\xFF\x4C\x7D\x9D\x71\x88\xC4\x76\x1D\x90\x5B\x1D\xEE\xFD\xCC\xF7\xEE\xFD\x60\xA5\xB1\x7A\x16\x71\xD1\x16\xD0\x7C\x12\x3C\x6C\x69\x97\xDB\xAE\x5F\x39\x9A\x70\x2F\x05\x3C\x19\x46\x04\x99\x20\x36\xD0\x60\x6E\x61\x06\xBB\x16\x42\x8C\x70\xF7\x30\xFB\xE0\xDB\x66\xA3\x00\x01\xBD\xE6\x2C\xDA\x91\x5F\xA0\x46\x8B\x4D\x6A\x9C\x3D\x3D\xDD\x05\x46\xFE\x76\xBF\xA0\x0A\x3C\xE4\x00\xE6\x27\xB7\xFF\x84\x2D\xDE\xBA\x22\x27\x96\x10\x71\xEB\x22\xED\xDF\xDF\x33\x9C\xCF\xE3\xAD\xAE\x8E\xD4\x8E\xE6\x4F\x51\xAF\x16\x92\xE0\x5C\xF6\x07\x0F", + ["emailAddress=certificate@trustcenter.de,OU=TC TrustCenter Class 2 CA,O=TC TrustCenter for Security in Data Networks GmbH,L=Hamburg,ST=Hamburg,C=DE"] = "\x30\x82\x03\x5C\x30\x82\x02\xC5\xA0\x03\x02\x01\x02\x02\x02\x03\xEA\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\xBC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x3A\x30\x38\x06\x03\x55\x04\x0A\x13\x31\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x66\x6F\x72\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x69\x6E\x20\x44\x61\x74\x61\x20\x4E\x65\x74\x77\x6F\x72\x6B\x73\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x31\x29\x30\x27\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x1A\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x40\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x30\x1E\x17\x0D\x39\x38\x30\x33\x30\x39\x31\x31\x35\x39\x35\x39\x5A\x17\x0D\x31\x31\x30\x31\x30\x31\x31\x31\x35\x39\x35\x39\x5A\x30\x81\xBC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x3A\x30\x38\x06\x03\x55\x04\x0A\x13\x31\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x66\x6F\x72\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x69\x6E\x20\x44\x61\x74\x61\x20\x4E\x65\x74\x77\x6F\x72\x6B\x73\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x31\x29\x30\x27\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x1A\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x40\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xDA\x38\xE8\xED\x32\x00\x29\x71\x83\x01\x0D\xBF\x8C\x01\xDC\xDA\xC6\xAD\x39\xA4\xA9\x8A\x2F\xD5\x8B\x5C\x68\x5F\x50\xC6\x62\xF5\x66\xBD\xCA\x91\x22\xEC\xAA\x1D\x51\xD7\x3D\xB3\x51\xB2\x83\x4E\x5D\xCB\x49\xB0\xF0\x4C\x55\xE5\x6B\x2D\xC7\x85\x0B\x30\x1C\x92\x4E\x82\xD4\xCA\x02\xED\xF7\x6F\xBE\xDC\xE0\xE3\x14\xB8\x05\x53\xF2\x9A\xF4\x56\x8B\x5A\x9E\x85\x93\xD1\xB4\x82\x56\xAE\x4D\xBB\xA8\x4B\x57\x16\xBC\xFE\xF8\x58\x9E\xF8\x29\x8D\xB0\x7B\xCD\x78\xC9\x4F\xAC\x8B\x67\x0C\xF1\x9C\xFB\xFC\x57\x9B\x57\x5C\x4F\x0D\x02\x03\x01\x00\x01\xA3\x6B\x30\x69\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x33\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x08\x04\x26\x16\x24\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x2F\x67\x75\x69\x64\x65\x6C\x69\x6E\x65\x73\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x84\x52\xFB\x28\xDF\xFF\x1F\x75\x01\xBC\x01\xBE\x04\x56\x97\x6A\x74\x42\x24\x31\x83\xF9\x46\xB1\x06\x8A\x89\xCF\x96\x2C\x33\xBF\x8C\xB5\x5F\x7A\x72\xA1\x85\x06\xCE\x86\xF8\x05\x8E\xE8\xF9\x25\xCA\xDA\x83\x8C\x06\xAC\xEB\x36\x6D\x85\x91\x34\x04\x36\xF4\x42\xF0\xF8\x79\x2E\x0A\x48\x5C\xAB\xCC\x51\x4F\x78\x76\xA0\xD9\xAC\x19\xBD\x2A\xD1\x69\x04\x28\x91\xCA\x36\x10\x27\x80\x57\x5B\xD2\x5C\xF5\xC2\x5B\xAB\x64\x81\x63\x74\x51\xF4\x97\xBF\xCD\x12\x28\xF7\x4D\x66\x7F\xA7\xF0\x1C\x01\x26\x78\xB2\x66\x47\x70\x51\x64", + ["emailAddress=certificate@trustcenter.de,OU=TC TrustCenter Class 3 CA,O=TC TrustCenter for Security in Data Networks GmbH,L=Hamburg,ST=Hamburg,C=DE"] = "\x30\x82\x03\x5C\x30\x82\x02\xC5\xA0\x03\x02\x01\x02\x02\x02\x03\xEB\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\xBC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x3A\x30\x38\x06\x03\x55\x04\x0A\x13\x31\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x66\x6F\x72\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x69\x6E\x20\x44\x61\x74\x61\x20\x4E\x65\x74\x77\x6F\x72\x6B\x73\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x31\x29\x30\x27\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x1A\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x40\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x30\x1E\x17\x0D\x39\x38\x30\x33\x30\x39\x31\x31\x35\x39\x35\x39\x5A\x17\x0D\x31\x31\x30\x31\x30\x31\x31\x31\x35\x39\x35\x39\x5A\x30\x81\xBC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x48\x61\x6D\x62\x75\x72\x67\x31\x3A\x30\x38\x06\x03\x55\x04\x0A\x13\x31\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x66\x6F\x72\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x69\x6E\x20\x44\x61\x74\x61\x20\x4E\x65\x74\x77\x6F\x72\x6B\x73\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x31\x29\x30\x27\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x1A\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x40\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xB6\xB4\xC1\x35\x05\x2E\x0D\x8D\xEC\xA0\x40\x6A\x1C\x0E\x27\xA6\x50\x92\x6B\x50\x1B\x07\xDE\x2E\xE7\x76\xCC\xE0\xDA\xFC\x84\xA8\x5E\x8C\x63\x6A\x2B\x4D\xD9\x4E\x02\x76\x11\xC1\x0B\xF2\x8D\x79\xCA\x00\xB6\xF1\xB0\x0E\xD7\xFB\xA4\x17\x3D\xAF\xAB\x69\x7A\x96\x27\xBF\xAF\x33\xA1\x9A\x2A\x59\xAA\xC4\xB5\x37\x08\xF2\x12\xA5\x31\xB6\x43\xF5\x32\x96\x71\x28\x28\xAB\x8D\x28\x86\xDF\xBB\xEE\xE3\x0C\x7D\x30\xD6\xC3\x52\xAB\x8F\x5D\x27\x9C\x6B\xC0\xA3\xE7\x05\x6B\x57\x49\x44\xB3\x6E\xEA\x64\xCF\xD2\x8E\x7A\x50\x77\x77\x02\x03\x01\x00\x01\xA3\x6B\x30\x69\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x33\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x08\x04\x26\x16\x24\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x2F\x67\x75\x69\x64\x65\x6C\x69\x6E\x65\x73\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x16\x3D\xC6\xCD\xC1\xBB\x85\x71\x85\x46\x9F\x3E\x20\x8F\x51\x28\x99\xEC\x2D\x45\x21\x63\x23\x5B\x04\xBB\x4C\x90\xB8\x88\x92\x04\x4D\xBD\x7D\x01\xA3\x3F\xF6\xEC\xCE\xF1\xDE\xFE\x7D\xE5\xE1\x3E\xBB\xC6\xAB\x5E\x0B\xDD\x3D\x96\xC4\xCB\xA9\xD4\xF9\x26\xE6\x06\x4E\x9E\x0C\xA5\x7A\xBA\x6E\xC3\x7C\x82\x19\xD1\xC7\xB1\xB1\xC3\xDB\x0D\x8E\x9B\x40\x7C\x37\x0B\xF1\x5D\xE8\xFD\x1F\x90\x88\xA5\x0E\x4E\x37\x64\x21\xA8\x4E\x8D\xB4\x9F\xF1\xDE\x48\xAD\xD5\x56\x18\x52\x29\x8B\x47\x34\x12\x09\xD4\xBB\x92\x35\xEF\x0F\xDB\x34", + ["CN=Certum CA,O=Unizeto Sp. z o.o.,C=PL"] = "\x30\x82\x03\x0C\x30\x82\x01\xF4\xA0\x03\x02\x01\x02\x02\x03\x01\x00\x20\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x50\x4C\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x55\x6E\x69\x7A\x65\x74\x6F\x20\x53\x70\x2E\x20\x7A\x20\x6F\x2E\x6F\x2E\x31\x12\x30\x10\x06\x03\x55\x04\x03\x13\x09\x43\x65\x72\x74\x75\x6D\x20\x43\x41\x30\x1E\x17\x0D\x30\x32\x30\x36\x31\x31\x31\x30\x34\x36\x33\x39\x5A\x17\x0D\x32\x37\x30\x36\x31\x31\x31\x30\x34\x36\x33\x39\x5A\x30\x3E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x50\x4C\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x55\x6E\x69\x7A\x65\x74\x6F\x20\x53\x70\x2E\x20\x7A\x20\x6F\x2E\x6F\x2E\x31\x12\x30\x10\x06\x03\x55\x04\x03\x13\x09\x43\x65\x72\x74\x75\x6D\x20\x43\x41\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\xCE\xB1\xC1\x2E\xD3\x4F\x7C\xCD\x25\xCE\x18\x3E\x4F\xC4\x8C\x6F\x80\x6A\x73\xC8\x5B\x51\xF8\x9B\xD2\xDC\xBB\x00\x5C\xB1\xA0\xFC\x75\x03\xEE\x81\xF0\x88\xEE\x23\x52\xE9\xE6\x15\x33\x8D\xAC\x2D\x09\xC5\x76\xF9\x2B\x39\x80\x89\xE4\x97\x4B\x90\xA5\xA8\x78\xF8\x73\x43\x7B\xA4\x61\xB0\xD8\x58\xCC\xE1\x6C\x66\x7E\x9C\xF3\x09\x5E\x55\x63\x84\xD5\xA8\xEF\xF3\xB1\x2E\x30\x68\xB3\xC4\x3C\xD8\xAC\x6E\x8D\x99\x5A\x90\x4E\x34\xDC\x36\x9A\x8F\x81\x88\x50\xB7\x6D\x96\x42\x09\xF3\xD7\x95\x83\x0D\x41\x4B\xB0\x6A\x6B\xF8\xFC\x0F\x7E\x62\x9F\x67\xC4\xED\x26\x5F\x10\x26\x0F\x08\x4F\xF0\xA4\x57\x28\xCE\x8F\xB8\xED\x45\xF6\x6E\xEE\x25\x5D\xAA\x6E\x39\xBE\xE4\x93\x2F\xD9\x47\xA0\x72\xEB\xFA\xA6\x5B\xAF\xCA\x53\x3F\xE2\x0E\xC6\x96\x56\x11\x6E\xF7\xE9\x66\xA9\x26\xD8\x7F\x95\x53\xED\x0A\x85\x88\xBA\x4F\x29\xA5\x42\x8C\x5E\xB6\xFC\x85\x20\x00\xAA\x68\x0B\xA1\x1A\x85\x01\x9C\xC4\x46\x63\x82\x88\xB6\x22\xB1\xEE\xFE\xAA\x46\x59\x7E\xCF\x35\x2C\xD5\xB6\xDA\x5D\xF7\x48\x33\x14\x54\xB6\xEB\xD9\x6F\xCE\xCD\x88\xD6\xAB\x1B\xDA\x96\x3B\x1D\x59\x02\x03\x01\x00\x01\xA3\x13\x30\x11\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xB8\x8D\xCE\xEF\xE7\x14\xBA\xCF\xEE\xB0\x44\x92\x6C\xB4\x39\x3E\xA2\x84\x6E\xAD\xB8\x21\x77\xD2\xD4\x77\x82\x87\xE6\x20\x41\x81\xEE\xE2\xF8\x11\xB7\x63\xD1\x17\x37\xBE\x19\x76\x24\x1C\x04\x1A\x4C\xEB\x3D\xAA\x67\x6F\x2D\xD4\xCD\xFE\x65\x31\x70\xC5\x1B\xA6\x02\x0A\xBA\x60\x7B\x6D\x58\xC2\x9A\x49\xFE\x63\x32\x0B\x6B\xE3\x3A\xC0\xAC\xAB\x3B\xB0\xE8\xD3\x09\x51\x8C\x10\x83\xC6\x34\xE0\xC5\x2B\xE0\x1A\xB6\x60\x14\x27\x6C\x32\x77\x8C\xBC\xB2\x72\x98\xCF\xCD\xCC\x3F\xB9\xC8\x24\x42\x14\xD6\x57\xFC\xE6\x26\x43\xA9\x1D\xE5\x80\x90\xCE\x03\x54\x28\x3E\xF7\x3F\xD3\xF8\x4D\xED\x6A\x0A\x3A\x93\x13\x9B\x3B\x14\x23\x13\x63\x9C\x3F\xD1\x87\x27\x79\xE5\x4C\x51\xE3\x01\xAD\x85\x5D\x1A\x3B\xB1\xD5\x73\x10\xA4\xD3\xF2\xBC\x6E\x64\xF5\x5A\x56\x90\xA8\xC7\x0E\x4C\x74\x0F\x2E\x71\x3B\xF7\xC8\x47\xF4\x69\x6F\x15\xF2\x11\x5E\x83\x1E\x9C\x7C\x52\xAE\xFD\x02\xDA\x12\xA8\x59\x67\x18\xDB\xBC\x70\xDD\x9B\xB1\x69\xED\x80\xCE\x89\x40\x48\x6A\x0E\x35\xCA\x29\x66\x15\x21\x94\x2C\xE8\x60\x2A\x9B\x85\x4A\x40\xF3\x6B\x8A\x24\xEC\x06\x16\x2C\x73", + ["CN=AAA Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB"] = "\x30\x82\x04\x32\x30\x82\x03\x1A\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x0C\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x0C\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x0C\x11\x43\x6F\x6D\x6F\x64\x6F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x0C\x18\x41\x41\x41\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x30\x1E\x17\x0D\x30\x34\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x0C\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x0C\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x0C\x11\x43\x6F\x6D\x6F\x64\x6F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x0C\x18\x41\x41\x41\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\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\xBE\x40\x9D\xF4\x6E\xE1\xEA\x76\x87\x1C\x4D\x45\x44\x8E\xBE\x46\xC8\x83\x06\x9D\xC1\x2A\xFE\x18\x1F\x8E\xE4\x02\xFA\xF3\xAB\x5D\x50\x8A\x16\x31\x0B\x9A\x06\xD0\xC5\x70\x22\xCD\x49\x2D\x54\x63\xCC\xB6\x6E\x68\x46\x0B\x53\xEA\xCB\x4C\x24\xC0\xBC\x72\x4E\xEA\xF1\x15\xAE\xF4\x54\x9A\x12\x0A\xC3\x7A\xB2\x33\x60\xE2\xDA\x89\x55\xF3\x22\x58\xF3\xDE\xDC\xCF\xEF\x83\x86\xA2\x8C\x94\x4F\x9F\x68\xF2\x98\x90\x46\x84\x27\xC7\x76\xBF\xE3\xCC\x35\x2C\x8B\x5E\x07\x64\x65\x82\xC0\x48\xB0\xA8\x91\xF9\x61\x9F\x76\x20\x50\xA8\x91\xC7\x66\xB5\xEB\x78\x62\x03\x56\xF0\x8A\x1A\x13\xEA\x31\xA3\x1E\xA0\x99\xFD\x38\xF6\xF6\x27\x32\x58\x6F\x07\xF5\x6B\xB8\xFB\x14\x2B\xAF\xB7\xAA\xCC\xD6\x63\x5F\x73\x8C\xDA\x05\x99\xA8\x38\xA8\xCB\x17\x78\x36\x51\xAC\xE9\x9E\xF4\x78\x3A\x8D\xCF\x0F\xD9\x42\xE2\x98\x0C\xAB\x2F\x9F\x0E\x01\xDE\xEF\x9F\x99\x49\xF1\x2D\xDF\xAC\x74\x4D\x1B\x98\xB5\x47\xC5\xE5\x29\xD1\xF9\x90\x18\xC7\x62\x9C\xBE\x83\xC7\x26\x7B\x3E\x8A\x25\xC7\xC0\xDD\x9D\xE6\x35\x68\x10\x20\x9D\x8F\xD8\xDE\xD2\xC3\x84\x9C\x0D\x5E\xE8\x2F\xC9\x02\x03\x01\x00\x01\xA3\x81\xC0\x30\x81\xBD\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xA0\x11\x0A\x23\x3E\x96\xF1\x07\xEC\xE2\xAF\x29\xEF\x82\xA5\x7F\xD0\x30\xA4\xB4\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x7B\x06\x03\x55\x1D\x1F\x04\x74\x30\x72\x30\x38\xA0\x36\xA0\x34\x86\x32\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x63\x61\x2E\x63\x6F\x6D\x2F\x41\x41\x41\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2E\x63\x72\x6C\x30\x36\xA0\x34\xA0\x32\x86\x30\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x2E\x6E\x65\x74\x2F\x41\x41\x41\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x08\x56\xFC\x02\xF0\x9B\xE8\xFF\xA4\xFA\xD6\x7B\xC6\x44\x80\xCE\x4F\xC4\xC5\xF6\x00\x58\xCC\xA6\xB6\xBC\x14\x49\x68\x04\x76\xE8\xE6\xEE\x5D\xEC\x02\x0F\x60\xD6\x8D\x50\x18\x4F\x26\x4E\x01\xE3\xE6\xB0\xA5\xEE\xBF\xBC\x74\x54\x41\xBF\xFD\xFC\x12\xB8\xC7\x4F\x5A\xF4\x89\x60\x05\x7F\x60\xB7\x05\x4A\xF3\xF6\xF1\xC2\xBF\xC4\xB9\x74\x86\xB6\x2D\x7D\x6B\xCC\xD2\xF3\x46\xDD\x2F\xC6\xE0\x6A\xC3\xC3\x34\x03\x2C\x7D\x96\xDD\x5A\xC2\x0E\xA7\x0A\x99\xC1\x05\x8B\xAB\x0C\x2F\xF3\x5C\x3A\xCF\x6C\x37\x55\x09\x87\xDE\x53\x40\x6C\x58\xEF\xFC\xB6\xAB\x65\x6E\x04\xF6\x1B\xDC\x3C\xE0\x5A\x15\xC6\x9E\xD9\xF1\x59\x48\x30\x21\x65\x03\x6C\xEC\xE9\x21\x73\xEC\x9B\x03\xA1\xE0\x37\xAD\xA0\x15\x18\x8F\xFA\xBA\x02\xCE\xA7\x2C\xA9\x10\x13\x2C\xD4\xE5\x08\x26\xAB\x22\x97\x60\xF8\x90\x5E\x74\xD4\xA2\x9A\x53\xBD\xF2\xA9\x68\xE0\xA2\x6E\xC2\xD7\x6C\xB1\xA3\x0F\x9E\xBF\xEB\x68\xE7\x56\xF2\xAE\xF2\xE3\x2B\x38\x3A\x09\x81\xB5\x6B\x85\xD7\xBE\x2D\xED\x3F\x1A\xB7\xB2\x63\xE2\xF5\x62\x2C\x82\xD4\x6A\x00\x41\x50\xF1\x39\x83\x9F\x95\xE9\x36\x96\x98\x6E", + ["CN=Secure Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB"] = "\x30\x82\x04\x3F\x30\x82\x03\x27\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x0C\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x0C\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x0C\x11\x43\x6F\x6D\x6F\x64\x6F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x24\x30\x22\x06\x03\x55\x04\x03\x0C\x1B\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x30\x1E\x17\x0D\x30\x34\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x7E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x0C\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x0C\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x0C\x11\x43\x6F\x6D\x6F\x64\x6F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x24\x30\x22\x06\x03\x55\x04\x03\x0C\x1B\x53\x65\x63\x75\x72\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\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\xC0\x71\x33\x82\x8A\xD0\x70\xEB\x73\x87\x82\x40\xD5\x1D\xE4\xCB\xC9\x0E\x42\x90\xF9\xDE\x34\xB9\xA1\xBA\x11\xF4\x25\x85\xF3\xCC\x72\x6D\xF2\x7B\x97\x6B\xB3\x07\xF1\x77\x24\x91\x5F\x25\x8F\xF6\x74\x3D\xE4\x80\xC2\xF8\x3C\x0D\xF3\xBF\x40\xEA\xF7\xC8\x52\xD1\x72\x6F\xEF\xC8\xAB\x41\xB8\x6E\x2E\x17\x2A\x95\x69\x0C\xCD\xD2\x1E\x94\x7B\x2D\x94\x1D\xAA\x75\xD7\xB3\x98\xCB\xAC\xBC\x64\x53\x40\xBC\x8F\xAC\xAC\x36\xCB\x5C\xAD\xBB\xDD\xE0\x94\x17\xEC\xD1\x5C\xD0\xBF\xEF\xA5\x95\xC9\x90\xC5\xB0\xAC\xFB\x1B\x43\xDF\x7A\x08\x5D\xB7\xB8\xF2\x40\x1B\x2B\x27\x9E\x50\xCE\x5E\x65\x82\x88\x8C\x5E\xD3\x4E\x0C\x7A\xEA\x08\x91\xB6\x36\xAA\x2B\x42\xFB\xEA\xC2\xA3\x39\xE5\xDB\x26\x38\xAD\x8B\x0A\xEE\x19\x63\xC7\x1C\x24\xDF\x03\x78\xDA\xE6\xEA\xC1\x47\x1A\x0B\x0B\x46\x09\xDD\x02\xFC\xDE\xCB\x87\x5F\xD7\x30\x63\x68\xA1\xAE\xDC\x32\xA1\xBA\xBE\xFE\x44\xAB\x68\xB6\xA5\x17\x15\xFD\xBD\xD5\xA7\xA7\x9A\xE4\x44\x33\xE9\x88\x8E\xFC\xED\x51\xEB\x93\x71\x4E\xAD\x01\xE7\x44\x8E\xAB\x2D\xCB\xA8\xFE\x01\x49\x48\xF0\xC0\xDD\xC7\x68\xD8\x92\xFE\x3D\x02\x03\x01\x00\x01\xA3\x81\xC7\x30\x81\xC4\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x3C\xD8\x93\x88\xC2\xC0\x82\x09\xCC\x01\x99\x06\x93\x20\xE9\x9E\x70\x09\x63\x4F\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x81\x06\x03\x55\x1D\x1F\x04\x7A\x30\x78\x30\x3B\xA0\x39\xA0\x37\x86\x35\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x63\x61\x2E\x63\x6F\x6D\x2F\x53\x65\x63\x75\x72\x65\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2E\x63\x72\x6C\x30\x39\xA0\x37\xA0\x35\x86\x33\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x2E\x6E\x65\x74\x2F\x53\x65\x63\x75\x72\x65\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x87\x01\x6D\x23\x1D\x7E\x5B\x17\x7D\xC1\x61\x32\xCF\x8F\xE7\xF3\x8A\x94\x59\x66\xE0\x9E\x28\xA8\x5E\xD3\xB7\xF4\x34\xE6\xAA\x39\xB2\x97\x16\xC5\x82\x6F\x32\xA4\xE9\x8C\xE7\xAF\xFD\xEF\xC2\xE8\xB9\x4B\xAA\xA3\xF4\xE6\xDA\x8D\x65\x21\xFB\xBA\x80\xEB\x26\x28\x85\x1A\xFE\x39\x8C\xDE\x5B\x04\x04\xB4\x54\xF9\xA3\x67\x9E\x41\xFA\x09\x52\xCC\x05\x48\xA8\xC9\x3F\x21\x04\x1E\xCE\x48\x6B\xFC\x85\xE8\xC2\x7B\xAF\x7F\xB7\xCC\xF8\x5F\x3A\xFD\x35\xC6\x0D\xEF\x97\xDC\x4C\xAB\x11\xE1\x6B\xCB\x31\xD1\x6C\xFB\x48\x80\xAB\xDC\x9C\x37\xB8\x21\x14\x4B\x0D\x71\x3D\xEC\x83\x33\x6E\xD1\x6E\x32\x16\xEC\x98\xC7\x16\x8B\x59\xA6\x34\xAB\x05\x57\x2D\x93\xF7\xAA\x13\xCB\xD2\x13\xE2\xB7\x2E\x3B\xCD\x6B\x50\x17\x09\x68\x3E\xB5\x26\x57\xEE\xB6\xE0\xB6\xDD\xB9\x29\x80\x79\x7D\x8F\xA3\xF0\xA4\x28\xA4\x15\xC4\x85\xF4\x27\xD4\x6B\xBF\xE5\x5C\xE4\x65\x02\x76\x54\xB4\xE3\x37\x66\x24\xD3\x19\x61\xC8\x52\x10\xE5\x8B\x37\x9A\xB9\xA9\xF9\x1D\xBF\xEA\x99\x92\x61\x96\xFF\x01\xCD\xA1\x5F\x0D\xBC\x71\xBC\x0E\xAC\x0B\x1D\x47\x45\x1D\xC1\xEC\x7C\xEC\xFD\x29", + ["CN=Trusted Certificate Services,O=Comodo CA Limited,L=Salford,ST=Greater Manchester,C=GB"] = "\x30\x82\x04\x43\x30\x82\x03\x2B\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x0C\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x0C\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x0C\x11\x43\x6F\x6D\x6F\x64\x6F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x03\x0C\x1C\x54\x72\x75\x73\x74\x65\x64\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x30\x1E\x17\x0D\x30\x34\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x38\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x0C\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x0C\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x0C\x11\x43\x6F\x6D\x6F\x64\x6F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x03\x0C\x1C\x54\x72\x75\x73\x74\x65\x64\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\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\xDF\x71\x6F\x36\x58\x53\x5A\xF2\x36\x54\x57\x80\xC4\x74\x08\x20\xED\x18\x7F\x2A\x1D\xE6\x35\x9A\x1E\x25\xAC\x9C\xE5\x96\x7E\x72\x52\xA0\x15\x42\xDB\x59\xDD\x64\x7A\x1A\xD0\xB8\x7B\xDD\x39\x15\xBC\x55\x48\xC4\xED\x3A\x00\xEA\x31\x11\xBA\xF2\x71\x74\x1A\x67\xB8\xCF\x33\xCC\xA8\x31\xAF\xA3\xE3\xD7\x7F\xBF\x33\x2D\x4C\x6A\x3C\xEC\x8B\xC3\x92\xD2\x53\x77\x24\x74\x9C\x07\x6E\x70\xFC\xBD\x0B\x5B\x76\xBA\x5F\xF2\xFF\xD7\x37\x4B\x4A\x60\x78\xF7\xF0\xFA\xCA\x70\xB4\xEA\x59\xAA\xA3\xCE\x48\x2F\xA9\xC3\xB2\x0B\x7E\x17\x72\x16\x0C\xA6\x07\x0C\x1B\x38\xCF\xC9\x62\xB7\x3F\xA0\x93\xA5\x87\x41\xF2\xB7\x70\x40\x77\xD8\xBE\x14\x7C\xE3\xA8\xC0\x7A\x8E\xE9\x63\x6A\xD1\x0F\x9A\xC6\xD2\xF4\x8B\x3A\x14\x04\x56\xD4\xED\xB8\xCC\x6E\xF5\xFB\xE2\x2C\x58\xBD\x7F\x4F\x6B\x2B\xF7\x60\x24\x58\x24\xCE\x26\xEF\x34\x91\x3A\xD5\xE3\x81\xD0\xB2\xF0\x04\x02\xD7\x5B\xB7\x3E\x92\xAC\x6B\x12\x8A\xF9\xE4\x05\xB0\x3B\x91\x49\x5C\xB2\xEB\x53\xEA\xF8\x9F\x47\x86\xEE\xBF\x95\xC0\xC0\x06\x9F\xD2\x5B\x5E\x11\x1B\xF4\xC7\x04\x35\x29\xD2\x55\x5C\xE4\xED\xEB\x02\x03\x01\x00\x01\xA3\x81\xC9\x30\x81\xC6\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC5\x7B\x58\xBD\xED\xDA\x25\x69\xD2\xF7\x59\x16\xA8\xB3\x32\xC0\x7B\x27\x5B\xF4\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\x83\x06\x03\x55\x1D\x1F\x04\x7C\x30\x7A\x30\x3C\xA0\x3A\xA0\x38\x86\x36\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x63\x61\x2E\x63\x6F\x6D\x2F\x54\x72\x75\x73\x74\x65\x64\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2E\x63\x72\x6C\x30\x3A\xA0\x38\xA0\x36\x86\x34\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x2E\x6E\x65\x74\x2F\x54\x72\x75\x73\x74\x65\x64\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x53\x65\x72\x76\x69\x63\x65\x73\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xC8\x93\x81\x3B\x89\xB4\xAF\xB8\x84\x12\x4C\x8D\xD2\xF0\xDB\x70\xBA\x57\x86\x15\x34\x10\xB9\x2F\x7F\x1E\xB0\xA8\x89\x60\xA1\x8A\xC2\x77\x0C\x50\x4A\x9B\x00\x8B\xD8\x8B\xF4\x41\xE2\xD0\x83\x8A\x4A\x1C\x14\x06\xB0\xA3\x68\x05\x70\x31\x30\xA7\x53\x9B\x0E\xE9\x4A\xA0\x58\x69\x67\x0E\xAE\x9D\xF6\xA5\x2C\x41\xBF\x3C\x06\x6B\xE4\x59\xCC\x6D\x10\xF1\x96\x6F\x1F\xDF\xF4\x04\x02\xA4\x9F\x45\x3E\xC8\xD8\xFA\x36\x46\x44\x50\x3F\x82\x97\x91\x1F\x28\xDB\x18\x11\x8C\x2A\xE4\x65\x83\x57\x12\x12\x8C\x17\x3F\x94\x36\xFE\x5D\xB0\xC0\x04\x77\x13\xB8\xF4\x15\xD5\x3F\x38\xCC\x94\x3A\x55\xD0\xAC\x98\xF5\xBA\x00\x5F\xE0\x86\x19\x81\x78\x2F\x28\xC0\x7E\xD3\xCC\x42\x0A\xF5\xAE\x50\xA0\xD1\x3E\xC6\xA1\x71\xEC\x3F\xA0\x20\x8C\x66\x3A\x89\xB4\x8E\xD4\xD8\xB1\x4D\x25\x47\xEE\x2F\x88\xC8\xB5\xE1\x05\x45\xC0\xBE\x14\x71\xDE\x7A\xFD\x8E\x7B\x7D\x4D\x08\x96\xA5\x12\x73\xF0\x2D\xCA\x37\x27\x74\x12\x27\x4C\xCB\xB6\x97\xE9\xD9\xAE\x08\x6D\x5A\x39\x40\xDD\x05\x47\x75\x6A\x5A\x21\xB3\xA3\x18\xCF\x4E\xF7\x2E\x57\xB7\x98\x70\x5E\xC8\xC4\x78\xB0\x62", + ["CN=QuoVadis Root Certification Authority,OU=Root Certification Authority,O=QuoVadis Limited,C=BM"] = "\x30\x82\x05\xD0\x30\x82\x04\xB8\xA0\x03\x02\x01\x02\x02\x04\x3A\xB6\x50\x8B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x2E\x30\x2C\x06\x03\x55\x04\x03\x13\x25\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x31\x30\x33\x31\x39\x31\x38\x33\x33\x33\x33\x5A\x17\x0D\x32\x31\x30\x33\x31\x37\x31\x38\x33\x33\x33\x33\x5A\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x2E\x30\x2C\x06\x03\x55\x04\x03\x13\x25\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\x61\xB5\x95\x53\xBA\x57\xFC\xFA\xF2\x67\x0B\x3A\x1A\xDF\x11\x80\x64\x95\xB4\xD1\xBC\xCD\x7A\xCF\xF6\x29\x96\x2E\x24\x54\x40\x24\x38\xF7\x1A\x85\xDC\x58\x4C\xCB\xA4\x27\x42\x97\xD0\x9F\x83\x8A\xC3\xE4\x06\x03\x5B\x00\xA5\x51\x1E\x70\x04\x74\xE2\xC1\xD4\x3A\xAB\xD7\xAD\x3B\x07\x18\x05\x8E\xFD\x83\xAC\xEA\x66\xD9\x18\x1B\x68\x8A\xF5\x57\x1A\x98\xBA\xF5\xED\x76\x3D\x7C\xD9\xDE\x94\x6A\x3B\x4B\x17\xC1\xD5\x8F\xBD\x65\x38\x3A\x95\xD0\x3D\x55\x36\x4E\xDF\x79\x57\x31\x2A\x1E\xD8\x59\x65\x49\x58\x20\x98\x7E\xAB\x5F\x7E\x9F\xE9\xD6\x4D\xEC\x83\x74\xA9\xC7\x6C\xD8\xEE\x29\x4A\x85\x2A\x06\x14\xF9\x54\xE6\xD3\xDA\x65\x07\x8B\x63\x37\x12\xD7\xD0\xEC\xC3\x7B\x20\x41\x44\xA3\xED\xCB\xA0\x17\xE1\x71\x65\xCE\x1D\x66\x31\xF7\x76\x01\x19\xC8\x7D\x03\x58\xB6\x95\x49\x1D\xA6\x12\x26\xE8\xC6\x0C\x76\xE0\xE3\x66\xCB\xEA\x5D\xA6\x26\xEE\xE5\xCC\x5F\xBD\x67\xA7\x01\x27\x0E\xA2\xCA\x54\xC5\xB1\x7A\x95\x1D\x71\x1E\x4A\x29\x8A\x03\xDC\x6A\x45\xC1\xA4\x19\x5E\x6F\x36\xCD\xC3\xA2\xB0\xB7\xFE\x5C\x38\xE2\x52\xBC\xF8\x44\x43\xE6\x90\xBB\x02\x03\x01\x00\x01\xA3\x82\x02\x52\x30\x82\x02\x4E\x30\x3D\x06\x08\x2B\x06\x01\x05\x05\x07\x01\x01\x04\x31\x30\x2F\x30\x2D\x06\x08\x2B\x06\x01\x05\x05\x07\x30\x01\x86\x21\x68\x74\x74\x70\x73\x3A\x2F\x2F\x6F\x63\x73\x70\x2E\x71\x75\x6F\x76\x61\x64\x69\x73\x6F\x66\x66\x73\x68\x6F\x72\x65\x2E\x63\x6F\x6D\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x82\x01\x1A\x06\x03\x55\x1D\x20\x04\x82\x01\x11\x30\x82\x01\x0D\x30\x82\x01\x09\x06\x09\x2B\x06\x01\x04\x01\xBE\x58\x00\x01\x30\x81\xFB\x30\x81\xD4\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x81\xC7\x1A\x81\xC4\x52\x65\x6C\x69\x61\x6E\x63\x65\x20\x6F\x6E\x20\x74\x68\x65\x20\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x62\x79\x20\x61\x6E\x79\x20\x70\x61\x72\x74\x79\x20\x61\x73\x73\x75\x6D\x65\x73\x20\x61\x63\x63\x65\x70\x74\x61\x6E\x63\x65\x20\x6F\x66\x20\x74\x68\x65\x20\x74\x68\x65\x6E\x20\x61\x70\x70\x6C\x69\x63\x61\x62\x6C\x65\x20\x73\x74\x61\x6E\x64\x61\x72\x64\x20\x74\x65\x72\x6D\x73\x20\x61\x6E\x64\x20\x63\x6F\x6E\x64\x69\x74\x69\x6F\x6E\x73\x20\x6F\x66\x20\x75\x73\x65\x2C\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x70\x72\x61\x63\x74\x69\x63\x65\x73\x2C\x20\x61\x6E\x64\x20\x74\x68\x65\x20\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x50\x6F\x6C\x69\x63\x79\x2E\x30\x22\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x16\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x71\x75\x6F\x76\x61\x64\x69\x73\x2E\x62\x6D\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x8B\x4B\x6D\xED\xD3\x29\xB9\x06\x19\xEC\x39\x39\xA9\xF0\x97\x84\x6A\xCB\xEF\xDF\x30\x81\xAE\x06\x03\x55\x1D\x23\x04\x81\xA6\x30\x81\xA3\x80\x14\x8B\x4B\x6D\xED\xD3\x29\xB9\x06\x19\xEC\x39\x39\xA9\xF0\x97\x84\x6A\xCB\xEF\xDF\xA1\x81\x84\xA4\x81\x81\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x2E\x30\x2C\x06\x03\x55\x04\x03\x13\x25\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x82\x04\x3A\xB6\x50\x8B\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x8A\xD4\x14\xB5\xFE\xF4\x9A\x92\xA7\x19\xD4\xA4\x7E\x72\x18\x8F\xD9\x68\x7C\x52\x24\xDD\x67\x6F\x39\x7A\xC4\xAA\x5E\x3D\xE2\x58\xB0\x4D\x70\x98\x84\x61\xE8\x1B\xE3\x69\x18\x0E\xCE\xFB\x47\x50\xA0\x4E\xFF\xF0\x24\x1F\xBD\xB2\xCE\xF5\x27\xFC\xEC\x2F\x53\xAA\x73\x7B\x03\x3D\x74\x6E\xE6\x16\x9E\xEB\xA5\x2E\xC4\xBF\x56\x27\x50\x2B\x62\xBA\xBE\x4B\x1C\x3C\x55\x5C\x41\x1D\x24\xBE\x82\x20\x47\x5D\xD5\x44\x7E\x7A\x16\x68\xDF\x7D\x4D\x51\x70\x78\x57\x1D\x33\x1E\xFD\x02\x99\x9C\x0C\xCD\x0A\x05\x4F\xC7\xBB\x8E\xA4\x75\xFA\x4A\x6D\xB1\x80\x8E\x09\x56\xB9\x9C\x1A\x60\xFE\x5D\xC1\xD7\x7A\xDC\x11\x78\xD0\xD6\x5D\xC1\xB7\xD5\xAD\x32\x99\x03\x3A\x8A\xCC\x54\x25\x39\x31\x81\x7B\x13\x22\x51\xBA\x46\x6C\xA1\xBB\x9E\xFA\x04\x6C\x49\x26\x74\x8F\xD2\x73\xEB\xCC\x30\xA2\xE6\xEA\x59\x22\x87\xF8\x97\xF5\x0E\xFD\xEA\xCC\x92\xA4\x16\xC4\x52\x18\xEA\x21\xCE\xB1\xF1\xE6\x84\x81\xE5\xBA\xA9\x86\x28\xF2\x43\x5A\x5D\x12\x9D\xAC\x1E\xD9\xA8\xE5\x0A\x6A\xA7\x7F\xA0\x87\x29\xCF\xF2\x89\x4D\xD4\xEC\xC5\xE2\xE6\x7A\xD0\x36\x23\x8A\x4A\x74\x36\xF9", + ["CN=QuoVadis Root CA 2,O=QuoVadis Limited,C=BM"] = "\x30\x82\x05\xB7\x30\x82\x03\x9F\xA0\x03\x02\x01\x02\x02\x02\x05\x09\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x1E\x17\x0D\x30\x36\x31\x31\x32\x34\x31\x38\x32\x37\x30\x30\x5A\x17\x0D\x33\x31\x31\x31\x32\x34\x31\x38\x32\x33\x33\x33\x5A\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\x9A\x18\xCA\x4B\x94\x0D\x00\x2D\xAF\x03\x29\x8A\xF0\x0F\x81\xC8\xAE\x4C\x19\x85\x1D\x08\x9F\xAB\x29\x44\x85\xF3\x2F\x81\xAD\x32\x1E\x90\x46\xBF\xA3\x86\x26\x1A\x1E\xFE\x7E\x1C\x18\x3A\x5C\x9C\x60\x17\x2A\x3A\x74\x83\x33\x30\x7D\x61\x54\x11\xCB\xED\xAB\xE0\xE6\xD2\xA2\x7E\xF5\x6B\x6F\x18\xB7\x0A\x0B\x2D\xFD\xE9\x3E\xEF\x0A\xC6\xB3\x10\xE9\xDC\xC2\x46\x17\xF8\x5D\xFD\xA4\xDA\xFF\x9E\x49\x5A\x9C\xE6\x33\xE6\x24\x96\xF7\x3F\xBA\x5B\x2B\x1C\x7A\x35\xC2\xD6\x67\xFE\xAB\x66\x50\x8B\x6D\x28\x60\x2B\xEF\xD7\x60\xC3\xC7\x93\xBC\x8D\x36\x91\xF3\x7F\xF8\xDB\x11\x13\xC4\x9C\x77\x76\xC1\xAE\xB7\x02\x6A\x81\x7A\xA9\x45\x83\xE2\x05\xE6\xB9\x56\xC1\x94\x37\x8F\x48\x71\x63\x22\xEC\x17\x65\x07\x95\x8A\x4B\xDF\x8F\xC6\x5A\x0A\xE5\xB0\xE3\x5F\x5E\x6B\x11\xAB\x0C\xF9\x85\xEB\x44\xE9\xF8\x04\x73\xF2\xE9\xFE\x5C\x98\x8C\xF5\x73\xAF\x6B\xB4\x7E\xCD\xD4\x5C\x02\x2B\x4C\x39\xE1\xB2\x95\x95\x2D\x42\x87\xD7\xD5\xB3\x90\x43\xB7\x6C\x13\xF1\xDE\xDD\xF6\xC4\xF8\x89\x3F\xD1\x75\xF5\x92\xC3\x91\xD5\x8A\x88\xD0\x90\xEC\xDC\x6D\xDE\x89\xC2\x65\x71\x96\x8B\x0D\x03\xFD\x9C\xBF\x5B\x16\xAC\x92\xDB\xEA\xFE\x79\x7C\xAD\xEB\xAF\xF7\x16\xCB\xDB\xCD\x25\x2B\xE5\x1F\xFB\x9A\x9F\xE2\x51\xCC\x3A\x53\x0C\x48\xE6\x0E\xBD\xC9\xB4\x76\x06\x52\xE6\x11\x13\x85\x72\x63\x03\x04\xE0\x04\x36\x2B\x20\x19\x02\xE8\x74\xA7\x1F\xB6\xC9\x56\x66\xF0\x75\x25\xDC\x67\xC1\x0E\x61\x60\x88\xB3\x3E\xD1\xA8\xFC\xA3\xDA\x1D\xB0\xD1\xB1\x23\x54\xDF\x44\x76\x6D\xED\x41\xD8\xC1\xB2\x22\xB6\x53\x1C\xDF\x35\x1D\xDC\xA1\x77\x2A\x31\xE4\x2D\xF5\xE5\xE5\xDB\xC8\xE0\xFF\xE5\x80\xD7\x0B\x63\xA0\xFF\x33\xA1\x0F\xBA\x2C\x15\x15\xEA\x97\xB3\xD2\xA2\xB5\xBE\xF2\x8C\x96\x1E\x1A\x8F\x1D\x6C\xA4\x61\x37\xB9\x86\x73\x33\xD7\x97\x96\x9E\x23\x7D\x82\xA4\x4C\x81\xE2\xA1\xD1\xBA\x67\x5F\x95\x07\xA3\x27\x11\xEE\x16\x10\x7B\xBC\x45\x4A\x4C\xB2\x04\xD2\xAB\xEF\xD5\xFD\x0C\x51\xCE\x50\x6A\x08\x31\xF9\x91\xDA\x0C\x8F\x64\x5C\x03\xC3\x3A\x8B\x20\x3F\x6E\x8D\x67\x3D\x3A\xD6\xFE\x7D\x5B\x88\xC9\x5E\xFB\xCC\x61\xDC\x8B\x33\x77\xD3\x44\x32\x35\x09\x62\x04\x92\x16\x10\xD8\x9E\x27\x47\xFB\x3B\x21\xE3\xF8\xEB\x1D\x5B\x02\x03\x01\x00\x01\xA3\x81\xB0\x30\x81\xAD\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x1A\x84\x62\xBC\x48\x4C\x33\x25\x04\xD4\xEE\xD0\xF6\x03\xC4\x19\x46\xD1\x94\x6B\x30\x6E\x06\x03\x55\x1D\x23\x04\x67\x30\x65\x80\x14\x1A\x84\x62\xBC\x48\x4C\x33\x25\x04\xD4\xEE\xD0\xF6\x03\xC4\x19\x46\xD1\x94\x6B\xA1\x49\xA4\x47\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x82\x02\x05\x09\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x3E\x0A\x16\x4D\x9F\x06\x5B\xA8\xAE\x71\x5D\x2F\x05\x2F\x67\xE6\x13\x45\x83\xC4\x36\xF6\xF3\xC0\x26\x0C\x0D\xB5\x47\x64\x5D\xF8\xB4\x72\xC9\x46\xA5\x03\x18\x27\x55\x89\x78\x7D\x76\xEA\x96\x34\x80\x17\x20\xDC\xE7\x83\xF8\x8D\xFC\x07\xB8\xDA\x5F\x4D\x2E\x67\xB2\x84\xFD\xD9\x44\xFC\x77\x50\x81\xE6\x7C\xB4\xC9\x0D\x0B\x72\x53\xF8\x76\x07\x07\x41\x47\x96\x0C\xFB\xE0\x82\x26\x93\x55\x8C\xFE\x22\x1F\x60\x65\x7C\x5F\xE7\x26\xB3\xF7\x32\x90\x98\x50\xD4\x37\x71\x55\xF6\x92\x21\x78\xF7\x95\x79\xFA\xF8\x2D\x26\x87\x66\x56\x30\x77\xA6\x37\x78\x33\x52\x10\x58\xAE\x3F\x61\x8E\xF2\x6A\xB1\xEF\x18\x7E\x4A\x59\x63\xCA\x8D\xA2\x56\xD5\xA7\x2F\xBC\x56\x1F\xCF\x39\xC1\xE2\xFB\x0A\xA8\x15\x2C\x7D\x4D\x7A\x63\xC6\x6C\x97\x44\x3C\xD2\x6F\xC3\x4A\x17\x0A\xF8\x90\xD2\x57\xA2\x19\x51\xA5\x2D\x97\x41\xDA\x07\x4F\xA9\x50\xDA\x90\x8D\x94\x46\xE1\x3E\xF0\x94\xFD\x10\x00\x38\xF5\x3B\xE8\x40\xE1\xB4\x6E\x56\x1A\x20\xCC\x6F\x58\x8D\xED\x2E\x45\x8F\xD6\xE9\x93\x3F\xE7\xB1\x2C\xDF\x3A\xD6\x22\x8C\xDC\x84\xBB\x22\x6F\xD0\xF8\xE4\xC6\x39\xE9\x04\x88\x3C\xC3\xBA\xEB\x55\x7A\x6D\x80\x99\x24\xF5\x6C\x01\xFB\xF8\x97\xB0\x94\x5B\xEB\xFD\xD2\x6F\xF1\x77\x68\x0D\x35\x64\x23\xAC\xB8\x55\xA1\x03\xD1\x4D\x42\x19\xDC\xF8\x75\x59\x56\xA3\xF9\xA8\x49\x79\xF8\xAF\x0E\xB9\x11\xA0\x7C\xB7\x6A\xED\x34\xD0\xB6\x26\x62\x38\x1A\x87\x0C\xF8\xE8\xFD\x2E\xD3\x90\x7F\x07\x91\x2A\x1D\xD6\x7E\x5C\x85\x83\x99\xB0\x38\x08\x3F\xE9\x5E\xF9\x35\x07\xE4\xC9\x62\x6E\x57\x7F\xA7\x50\x95\xF7\xBA\xC8\x9B\xE6\x8E\xA2\x01\xC5\xD6\x66\xBF\x79\x61\xF3\x3C\x1C\xE1\xB9\x82\x5C\x5D\xA0\xC3\xE9\xD8\x48\xBD\x19\xA2\x11\x14\x19\x6E\xB2\x86\x1B\x68\x3E\x48\x37\x1A\x88\xB7\x5D\x96\x5E\x9C\xC7\xEF\x27\x62\x08\xE2\x91\x19\x5C\xD2\xF1\x21\xDD\xBA\x17\x42\x82\x97\x71\x81\x53\x31\xA9\x9F\xF6\x7D\x62\xBF\x72\xE1\xA3\x93\x1D\xCC\x8A\x26\x5A\x09\x38\xD0\xCE\xD7\x0D\x80\x16\xB4\x78\xA5\x3A\x87\x4C\x8D\x8A\xA5\xD5\x46\x97\xF2\x2C\x10\xB9\xBC\x54\x22\xC0\x01\x50\x69\x43\x9E\xF4\xB2\xEF\x6D\xF8\xEC\xDA\xF1\xE3\xB1\xEF\xDF\x91\x8F\x54\x2A\x0B\x25\xC1\x26\x19\xC4\x52\x10\x05\x65\xD5\x82\x10\xEA\xC2\x31\xCD\x2E", + ["CN=QuoVadis Root CA 3,O=QuoVadis Limited,C=BM"] = "\x30\x82\x06\x9D\x30\x82\x04\x85\xA0\x03\x02\x01\x02\x02\x02\x05\xC6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x33\x30\x1E\x17\x0D\x30\x36\x31\x31\x32\x34\x31\x39\x31\x31\x32\x33\x5A\x17\x0D\x33\x31\x31\x31\x32\x34\x31\x39\x30\x36\x34\x34\x5A\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x33\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xCC\x57\x42\x16\x54\x9C\xE6\x98\xD3\xD3\x4D\xEE\xFE\xED\xC7\x9F\x43\x39\x4A\x65\xB3\xE8\x16\x88\x34\xDB\x0D\x59\x91\x74\xCF\x92\xB8\x04\x40\xAD\x02\x4B\x31\xAB\xBC\x8D\x91\x68\xD8\x20\x0E\x1A\x01\xE2\x1A\x7B\x4E\x17\x5D\xE2\x8A\xB7\x3F\x99\x1A\xCD\xEB\x61\xAB\xC2\x65\xA6\x1F\xB7\xB7\xBD\xB7\x8F\xFC\xFD\x70\x8F\x0B\xA0\x67\xBE\x01\xA2\x59\xCF\x71\xE6\x0F\x29\x76\xFF\xB1\x56\x79\x45\x2B\x1F\x9E\x7A\x54\xE8\xA3\x29\x35\x68\xA4\x01\x4F\x0F\xA4\x2E\x37\xEF\x1B\xBF\xE3\x8F\x10\xA8\x72\xAB\x58\x57\xE7\x54\x86\xC8\xC9\xF3\x5B\xDA\x2C\xDA\x5D\x8E\x6E\x3C\xA3\x3E\xDA\xFB\x82\xE5\xDD\xF2\x5C\xB2\x05\x33\x6F\x8A\x36\xCE\xD0\x13\x4E\xFF\xBF\x4A\x0C\x34\x4C\xA6\xC3\x21\xBD\x50\x04\x55\xEB\xB1\xBB\x9D\xFB\x45\x1E\x64\x15\xDE\x55\x01\x8C\x02\x76\xB5\xCB\xA1\x3F\x42\x69\xBC\x2F\xBD\x68\x43\x16\x56\x89\x2A\x37\x61\x91\xFD\xA6\xAE\x4E\xC0\xCB\x14\x65\x94\x37\x4B\x92\x06\xEF\x04\xD0\xC8\x9C\x88\xDB\x0B\x7B\x81\xAF\xB1\x3D\x2A\xC4\x65\x3A\x78\xB6\xEE\xDC\x80\xB1\xD2\xD3\x99\x9C\x3A\xEE\x6B\x5A\x6B\xB3\x8D\xB7\xD5\xCE\x9C\xC2\xBE\xA5\x4B\x2F\x16\xB1\x9E\x68\x3B\x06\x6F\xAE\x7D\x9F\xF8\xDE\xEC\xCC\x29\xA7\x98\xA3\x25\x43\x2F\xEF\xF1\x5F\x26\xE1\x88\x4D\xF8\x5E\x6E\xD7\xD9\x14\x6E\x19\x33\x69\xA7\x3B\x84\x89\x93\xC4\x53\x55\x13\xA1\x51\x78\x40\xF8\xB8\xC9\xA2\xEE\x7B\xBA\x52\x42\x83\x9E\x14\xED\x05\x52\x5A\x59\x56\xA7\x97\xFC\x9D\x3F\x0A\x29\xD8\xDC\x4F\x91\x0E\x13\xBC\xDE\x95\xA4\xDF\x8B\x99\xBE\xAC\x9B\x33\x88\xEF\xB5\x81\xAF\x1B\xC6\x22\x53\xC8\xF6\xC7\xEE\x97\x14\xB0\xC5\x7C\x78\x52\xC8\xF0\xCE\x6E\x77\x60\x84\xA6\xE9\x2A\x76\x20\xED\x58\x01\x17\x30\x93\xE9\x1A\x8B\xE0\x73\x63\xD9\x6A\x92\x94\x49\x4E\xB4\xAD\x4A\x85\xC4\xA3\x22\x30\xFC\x09\xED\x68\x22\x73\xA6\x88\x0C\x55\x21\x58\xC5\xE1\x3A\x9F\x2A\xDD\xCA\xE1\x90\xE0\xD9\x73\xAB\x6C\x80\xB8\xE8\x0B\x64\x93\xA0\x9C\x8C\x19\xFF\xB3\xD2\x0C\xEC\x91\x26\x87\x8A\xB3\xA2\xE1\x70\x8F\x2C\x0A\xE5\xCD\x6D\x68\x51\xEB\xDA\x3F\x05\x7F\x8B\x32\xE6\x13\x5C\x6B\xFE\x5F\x40\xE2\x22\xC8\xB4\xB4\x64\x4F\xD6\xBA\x7D\x48\x3E\xA8\x69\x0C\xD7\xBB\x86\x71\xC9\x73\xB8\x3F\x3B\x9D\x25\x4B\xDA\xFF\x40\xEB\x02\x03\x01\x00\x01\xA3\x82\x01\x95\x30\x82\x01\x91\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x81\xE1\x06\x03\x55\x1D\x20\x04\x81\xD9\x30\x81\xD6\x30\x81\xD3\x06\x09\x2B\x06\x01\x04\x01\xBE\x58\x00\x03\x30\x81\xC5\x30\x81\x93\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x81\x86\x1A\x81\x83\x41\x6E\x79\x20\x75\x73\x65\x20\x6F\x66\x20\x74\x68\x69\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x63\x6F\x6E\x73\x74\x69\x74\x75\x74\x65\x73\x20\x61\x63\x63\x65\x70\x74\x61\x6E\x63\x65\x20\x6F\x66\x20\x74\x68\x65\x20\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x33\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x50\x6F\x6C\x69\x63\x79\x20\x2F\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x50\x72\x61\x63\x74\x69\x63\x65\x20\x53\x74\x61\x74\x65\x6D\x65\x6E\x74\x2E\x30\x2D\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x21\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x71\x75\x6F\x76\x61\x64\x69\x73\x67\x6C\x6F\x62\x61\x6C\x2E\x63\x6F\x6D\x2F\x63\x70\x73\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xF2\xC0\x13\xE0\x82\x43\x3E\xFB\xEE\x2F\x67\x32\x96\x35\x5C\xDB\xB8\xCB\x02\xD0\x30\x6E\x06\x03\x55\x1D\x23\x04\x67\x30\x65\x80\x14\xF2\xC0\x13\xE0\x82\x43\x3E\xFB\xEE\x2F\x67\x32\x96\x35\x5C\xDB\xB8\xCB\x02\xD0\xA1\x49\xA4\x47\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x42\x4D\x31\x19\x30\x17\x06\x03\x55\x04\x0A\x13\x10\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x51\x75\x6F\x56\x61\x64\x69\x73\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x33\x82\x02\x05\xC6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x4F\xAD\xA0\x2C\x4C\xFA\xC0\xF2\x6F\xF7\x66\x55\xAB\x23\x34\xEE\xE7\x29\xDA\xC3\x5B\xB6\xB0\x83\xD9\xD0\xD0\xE2\x21\xFB\xF3\x60\xA7\x3B\x5D\x60\x53\x27\xA2\x9B\xF6\x08\x22\x2A\xE7\xBF\xA0\x72\xE5\x9C\x24\x6A\x31\xB1\x90\x7A\x27\xDB\x84\x11\x89\x27\xA6\x77\x5A\x38\xD7\xBF\xAC\x86\xFC\xEE\x5D\x83\xBC\x06\xC6\xD1\x77\x6B\x0F\x6D\x24\x2F\x4B\x7A\x6C\xA7\x07\x96\xCA\xE3\x84\x9F\xAD\x88\x8B\x1D\xAB\x16\x8D\x5B\x66\x17\xD9\x16\xF4\x8B\x80\xD2\xDD\xF8\xB2\x76\xC3\xFC\x38\x13\xAA\x0C\xDE\x42\x69\x2B\x6E\xF3\x3C\xEB\x80\x27\xDB\xF5\xA6\x44\x0D\x9F\x5A\x55\x59\x0B\xD5\x0D\x52\x48\xC5\xAE\x9F\xF2\x2F\x80\xC5\xEA\x32\x50\x35\x12\x97\x2E\xC1\xE1\xFF\xF1\x23\x88\x51\x38\x9F\xF2\x66\x56\x76\xE7\x0F\x51\x97\xA5\x52\x0C\x4D\x49\x51\x95\x36\x3D\xBF\xA2\x4B\x0C\x10\x1D\x86\x99\x4C\xAA\xF3\x72\x11\x93\xE4\xEA\xF6\x9B\xDA\xA8\x5D\xA7\x4D\xB7\x9E\x02\xAE\x73\x00\xC8\xDA\x23\x03\xE8\xF9\xEA\x19\x74\x62\x00\x94\xCB\x22\x20\xBE\x94\xA7\x59\xB5\x82\x6A\xBE\x99\x79\x7A\xA9\xF2\x4A\x24\x52\xF7\x74\xFD\xBA\x4E\xE6\xA8\x1D\x02\x6E\xB1\x0D\x80\x44\xC1\xAE\xD3\x23\x37\x5F\xBB\x85\x7C\x2B\x92\x2E\xE8\x7E\xA5\x8B\xDD\x99\xE1\xBF\x27\x6F\x2D\x5D\xAA\x7B\x87\xFE\x0A\xDD\x4B\xFC\x8E\xF5\x26\xE4\x6E\x70\x42\x6E\x33\xEC\x31\x9E\x7B\x93\xC1\xE4\xC9\x69\x1A\x3D\xC0\x6B\x4E\x22\x6D\xEE\xAB\x58\x4D\xC6\xD0\x41\xC1\x2B\xEA\x4F\x12\x87\x5E\xEB\x45\xD8\x6C\xF5\x98\x02\xD3\xA0\xD8\x55\x8A\x06\x99\x19\xA2\xA0\x77\xD1\x30\x9E\xAC\xCC\x75\xEE\x83\xF5\xB0\x62\x39\xCF\x6C\x57\xE2\x4C\xD2\x91\x0B\x0E\x75\x28\x1B\x9A\xBF\xFD\x1A\x43\xF1\xCA\x77\xFB\x3B\x8F\x61\xB8\x69\x28\x16\x42\x04\x5E\x70\x2A\x1C\x21\xD8\x8F\xE1\xBD\x23\x5B\x2D\x74\x40\x92\xD9\x63\x19\x0D\x73\xDD\x69\xBC\x62\x47\xBC\xE0\x74\x2B\xB2\xEB\x7D\xBE\x41\x1B\xB5\xC0\x46\xC5\xA1\x22\xCB\x5F\x4E\xC1\x28\x92\xDE\x18\xBA\xD5\x2A\x28\xBB\x11\x8B\x17\x93\x98\x99\x60\x94\x5C\x23\xCF\x5A\x27\x97\x5E\x0B\x05\x06\x93\x37\x1E\x3B\x69\x36\xEB\xA9\x9E\x61\x1D\x8F\x32\xDA\x8E\x0C\xD6\x74\x3E\x7B\x09\x24\xDA\x01\x77\x47\xC4\x3B\xCD\x34\x8C\x99\xF5\xCA\xE1\x25\x61\x33\xB2\x59\x1B\xE2\x6E\xD7\x37\x57\xB6\x0D\xA9\x12\xDA", + ["OU=Security Communication RootCA1,O=SECOM Trust.net,C=JP"] = "\x30\x82\x03\x5A\x30\x82\x02\x42\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x50\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x13\x0F\x53\x45\x43\x4F\x4D\x20\x54\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0B\x13\x1E\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6F\x6D\x6D\x75\x6E\x69\x63\x61\x74\x69\x6F\x6E\x20\x52\x6F\x6F\x74\x43\x41\x31\x30\x1E\x17\x0D\x30\x33\x30\x39\x33\x30\x30\x34\x32\x30\x34\x39\x5A\x17\x0D\x32\x33\x30\x39\x33\x30\x30\x34\x32\x30\x34\x39\x5A\x30\x50\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x13\x0F\x53\x45\x43\x4F\x4D\x20\x54\x72\x75\x73\x74\x2E\x6E\x65\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0B\x13\x1E\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6F\x6D\x6D\x75\x6E\x69\x63\x61\x74\x69\x6F\x6E\x20\x52\x6F\x6F\x74\x43\x41\x31\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\xB3\xB3\xFE\x7F\xD3\x6D\xB1\xEF\x16\x7C\x57\xA5\x0C\x6D\x76\x8A\x2F\x4B\xBF\x64\xFB\x4C\xEE\x8A\xF0\xF3\x29\x7C\xF5\xFF\xEE\x2A\xE0\xE9\xE9\xBA\x5B\x64\x22\x9A\x9A\x6F\x2C\x3A\x26\x69\x51\x05\x99\x26\xDC\xD5\x1C\x6A\x71\xC6\x9A\x7D\x1E\x9D\xDD\x7C\x6C\xC6\x8C\x67\x67\x4A\x3E\xF8\x71\xB0\x19\x27\xA9\x09\x0C\xA6\x95\xBF\x4B\x8C\x0C\xFA\x55\x98\x3B\xD8\xE8\x22\xA1\x4B\x71\x38\x79\xAC\x97\x92\x69\xB3\x89\x7E\xEA\x21\x68\x06\x98\x14\x96\x87\xD2\x61\x36\xBC\x6D\x27\x56\x9E\x57\xEE\xC0\xC0\x56\xFD\x32\xCF\xA4\xD9\x8E\xC2\x23\xD7\x8D\xA8\xF3\xD8\x25\xAC\x97\xE4\x70\x38\xF4\xB6\x3A\xB4\x9D\x3B\x97\x26\x43\xA3\xA1\xBC\x49\x59\x72\x4C\x23\x30\x87\x01\x58\xF6\x4E\xBE\x1C\x68\x56\x66\xAF\xCD\x41\x5D\xC8\xB3\x4D\x2A\x55\x46\xAB\x1F\xDA\x1E\xE2\x40\x3D\xDB\xCD\x7D\xB9\x92\x80\x9C\x37\xDD\x0C\x96\x64\x9D\xDC\x22\xF7\x64\x8B\xDF\x61\xDE\x15\x94\x52\x15\xA0\x7D\x52\xC9\x4B\xA8\x21\xC9\xC6\xB1\xED\xCB\xC3\x95\x60\xD1\x0F\xF0\xAB\x70\xF8\xDF\xCB\x4D\x7E\xEC\xD6\xFA\xAB\xD9\xBD\x7F\x54\xF2\xA5\xE9\x79\xFA\xD9\xD6\x76\x24\x28\x73\x02\x03\x01\x00\x01\xA3\x3F\x30\x3D\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xA0\x73\x49\x99\x68\xDC\x85\x5B\x65\xE3\x9B\x28\x2F\x57\x9F\xBD\x33\xBC\x07\x48\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x68\x40\xA9\xA8\xBB\xE4\x4F\x5D\x79\xB3\x05\xB5\x17\xB3\x60\x13\xEB\xC6\x92\x5D\xE0\xD1\xD3\x6A\xFE\xFB\xBE\x9B\x6D\xBF\xC7\x05\x6D\x59\x20\xC4\x1C\xF0\xB7\xDA\x84\x58\x02\x63\xFA\x48\x16\xEF\x4F\xA5\x0B\xF7\x4A\x98\xF2\x3F\x9E\x1B\xAD\x47\x6B\x63\xCE\x08\x47\xEB\x52\x3F\x78\x9C\xAF\x4D\xAE\xF8\xD5\x4F\xCF\x9A\x98\x2A\x10\x41\x39\x52\xC4\xDD\xD9\x9B\x0E\xEF\x93\x01\xAE\xB2\x2E\xCA\x68\x42\x24\x42\x6C\xB0\xB3\x3A\x3E\xCD\xE9\xDA\x48\xC4\x15\xCB\xE9\xF9\x07\x0F\x92\x50\x49\x8A\xDD\x31\x97\x5F\xC9\xE9\x37\xAA\x3B\x59\x65\x97\x94\x32\xC9\xB3\x9F\x3E\x3A\x62\x58\xC5\x49\xAD\x62\x0E\x71\xA5\x32\xAA\x2F\xC6\x89\x76\x43\x40\x13\x13\x67\x3D\xA2\x54\x25\x10\xCB\xF1\x3A\xF2\xD9\xFA\xDB\x49\x56\xBB\xA6\xFE\xA7\x41\x35\xC3\xE0\x88\x61\xC9\x88\xC7\xDF\x36\x10\x22\x98\x59\xEA\xB0\x4A\xFB\x56\x16\x73\x6E\xAC\x4D\xF7\x22\xA1\x4F\xAD\x1D\x7A\x2D\x45\x27\xE5\x30\xC1\x5E\xF2\xDA\x13\xCB\x25\x42\x51\x95\x47\x03\x8C\x6C\x21\xCC\x74\x42\xED\x53\xFF\x33\x8B\x8F\x0F\x57\x01\x16\x2F\xCF\xA6\xEE\xC9\x70\x22\x14\xBD\xFD\xBE\x6C\x0B\x03", + ["CN=Sonera Class2 CA,O=Sonera,C=FI"] = "\x30\x82\x03\x20\x30\x82\x02\x08\xA0\x03\x02\x01\x02\x02\x01\x1D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x39\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x49\x31\x0F\x30\x0D\x06\x03\x55\x04\x0A\x13\x06\x53\x6F\x6E\x65\x72\x61\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x6F\x6E\x65\x72\x61\x20\x43\x6C\x61\x73\x73\x32\x20\x43\x41\x30\x1E\x17\x0D\x30\x31\x30\x34\x30\x36\x30\x37\x32\x39\x34\x30\x5A\x17\x0D\x32\x31\x30\x34\x30\x36\x30\x37\x32\x39\x34\x30\x5A\x30\x39\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x49\x31\x0F\x30\x0D\x06\x03\x55\x04\x0A\x13\x06\x53\x6F\x6E\x65\x72\x61\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x6F\x6E\x65\x72\x61\x20\x43\x6C\x61\x73\x73\x32\x20\x43\x41\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\x90\x17\x4A\x35\x9D\xCA\xF0\x0D\x96\xC7\x44\xFA\x16\x37\xFC\x48\xBD\xBD\x7F\x80\x2D\x35\x3B\xE1\x6F\xA8\x67\xA9\xBF\x03\x1C\x4D\x8C\x6F\x32\x47\xD5\x41\x68\xA4\x13\x04\xC1\x35\x0C\x9A\x84\x43\xFC\x5C\x1D\xFF\x89\xB3\xE8\x17\x18\xCD\x91\x5F\xFB\x89\xE3\xEA\xBF\x4E\x5D\x7C\x1B\x26\xD3\x75\x79\xED\xE6\x84\xE3\x57\xE5\xAD\x29\xC4\xF4\x3A\x28\xE7\xA5\x7B\x84\x36\x69\xB3\xFD\x5E\x76\xBD\xA3\x2D\x99\xD3\x90\x4E\x23\x28\x7D\x18\x63\xF1\x54\x3B\x26\x9D\x76\x5B\x97\x42\xB2\xFF\xAE\xF0\x4E\xEC\xDD\x39\x95\x4E\x83\x06\x7F\xE7\x49\x40\xC8\xC5\x01\xB2\x54\x5A\x66\x1D\x3D\xFC\xF9\xE9\x3C\x0A\x9E\x81\xB8\x70\xF0\x01\x8B\xE4\x23\x54\x7C\xC8\xAE\xF8\x90\x1E\x00\x96\x72\xD4\x54\xCF\x61\x23\xBC\xEA\xFB\x9D\x02\x95\xD1\xB6\xB9\x71\x3A\x69\x08\x3F\x0F\xB4\xE1\x42\xC7\x88\xF5\x3F\x98\xA8\xA7\xBA\x1C\xE0\x71\x71\xEF\x58\x57\x81\x50\x7A\x5C\x6B\x74\x46\x0E\x83\x03\x98\xC3\x8E\xA8\x6E\xF2\x76\x32\x6E\x27\x83\xC2\x73\xF3\xDC\x18\xE8\xB4\x93\xEA\x75\x44\x6B\x04\x60\x20\x71\x57\x87\x9D\xF3\xBE\xA0\x90\x23\x3D\x8A\x24\xE1\xDA\x21\xDB\xC3\x02\x03\x01\x00\x01\xA3\x33\x30\x31\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x11\x06\x03\x55\x1D\x0E\x04\x0A\x04\x08\x4A\xA0\xAA\x58\x84\xD3\x5E\x3C\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5A\xCE\x87\xF9\x16\x72\x15\x57\x4B\x1D\xD9\x9B\xE7\xA2\x26\x30\xEC\x93\x67\xDF\xD6\x2D\xD2\x34\xAF\xF7\x38\xA5\xCE\xAB\x16\xB9\xAB\x2F\x7C\x35\xCB\xAC\xD0\x0F\xB4\x4C\x2B\xFC\x80\xEF\x6B\x8C\x91\x5F\x36\x76\xF7\xDB\xB3\x1B\x19\xEA\xF4\xB2\x11\xFD\x61\x71\x44\xBF\x28\xB3\x3A\x1D\xBF\xB3\x43\xE8\x9F\xBF\xDC\x31\x08\x71\xB0\x9D\x8D\xD6\x34\x47\x32\x90\xC6\x65\x24\xF7\xA0\x4A\x7C\x04\x73\x8F\x39\x6F\x17\x8C\x72\xB5\xBD\x4B\xC8\x7A\xF8\x7B\x83\xC3\x28\x4E\x9C\x09\xEA\x67\x3F\xB2\x67\x04\x1B\xC3\x14\xDA\xF8\xE7\x49\x24\x91\xD0\x1D\x6A\xFA\x61\x39\xEF\x6B\xE7\x21\x75\x06\x07\xD8\x12\xB4\x21\x20\x70\x42\x71\x81\xDA\x3C\x9A\x36\xBE\xA6\x5B\x0D\x6A\x6C\x9A\x1F\x91\x7B\xF9\xF9\xEF\x42\xBA\x4E\x4E\x9E\xCC\x0C\x8D\x94\xDC\xD9\x45\x9C\x5E\xEC\x42\x50\x63\xAE\xF4\x5D\xC4\xB1\x12\xDC\xCA\x3B\xA8\x2E\x9D\x14\x5A\x05\x75\xB7\xEC\xD7\x63\xE2\xBA\x35\xB6\x04\x08\x91\xE8\xDA\x9D\x9C\xF6\x66\xB5\x18\xAC\x0A\xA6\x54\x26\x34\x33\xD2\x1B\xC1\xD4\x7F\x1A\x3A\x8E\x0B\xAA\x32\x6E\xDB\xFC\x4F\x25\x9F\xD9\x32\xC7\x96\x5A\x70\xAC\xDF\x4C", + ["CN=Staat der Nederlanden Root CA,O=Staat der Nederlanden,C=NL"] = "\x30\x82\x03\xBA\x30\x82\x02\xA2\xA0\x03\x02\x01\x02\x02\x04\x00\x98\x96\x8A\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x55\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4C\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x13\x15\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x32\x31\x32\x31\x37\x30\x39\x32\x33\x34\x39\x5A\x17\x0D\x31\x35\x31\x32\x31\x36\x30\x39\x31\x35\x33\x38\x5A\x30\x55\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4C\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x13\x15\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\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\x98\xD2\xB5\x51\x11\x7A\x81\xA6\x14\x98\x71\x6D\xBE\xCC\xE7\x13\x1B\xD6\x27\x0E\x7A\xB3\x6A\x18\x1C\xB6\x61\x5A\xD5\x61\x09\xBF\xDE\x90\x13\xC7\x67\xEE\xDD\xF3\xDA\xC5\x0C\x12\x9E\x35\x55\x3E\x2C\x27\x88\x40\x6B\xF7\xDC\xDD\x22\x61\xF5\xC2\xC7\x0E\xF5\xF6\xD5\x76\x53\x4D\x8F\x8C\xBC\x18\x76\x37\x85\x9D\xE8\xCA\x49\xC7\xD2\x4F\x98\x13\x09\xA2\x3E\x22\x88\x9C\x7F\xD6\xF2\x10\x65\xB4\xEE\x5F\x18\xD5\x17\xE3\xF8\xC5\xFD\xE2\x9D\xA2\xEF\x53\x0E\x85\x77\xA2\x0F\xE1\x30\x47\xEE\x00\xE7\x33\x7D\x44\x67\x1A\x0B\x51\xE8\x8B\xA0\x9E\x50\x98\x68\x34\x52\x1F\x2E\x6D\x01\xF2\x60\x45\xF2\x31\xEB\xA9\x31\x68\x29\xBB\x7A\x41\x9E\xC6\x19\x7F\x94\xB4\x51\x39\x03\x7F\xB2\xDE\xA7\x32\x9B\xB4\x47\x8E\x6F\xB4\x4A\xAE\xE5\xAF\xB1\xDC\xB0\x1B\x61\xBC\x99\x72\xDE\xE4\x89\xB7\x7A\x26\x5D\xDA\x33\x49\x5B\x52\x9C\x0E\xF5\x8A\xAD\xC3\xB8\x3D\xE8\x06\x6A\xC2\xD5\x2A\x0B\x6C\x7B\x84\xBD\x56\x05\xCB\x86\x65\x92\xEC\x44\x2B\xB0\x8E\xB9\xDC\x70\x0B\x46\xDA\xAD\xBC\x63\x88\x39\xFA\xDB\x6A\xFE\x23\xFA\xBC\xE4\x48\xF4\x67\x2B\x6A\x11\x10\x21\x49\x02\x03\x01\x00\x01\xA3\x81\x91\x30\x81\x8E\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x4F\x06\x03\x55\x1D\x20\x04\x48\x30\x46\x30\x44\x06\x04\x55\x1D\x20\x00\x30\x3C\x30\x3A\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x2E\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x70\x6B\x69\x6F\x76\x65\x72\x68\x65\x69\x64\x2E\x6E\x6C\x2F\x70\x6F\x6C\x69\x63\x69\x65\x73\x2F\x72\x6F\x6F\x74\x2D\x70\x6F\x6C\x69\x63\x79\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xA8\x7D\xEB\xBC\x63\xA4\x74\x13\x74\x00\xEC\x96\xE0\xD3\x34\xC1\x2C\xBF\x6C\xF8\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x05\x84\x87\x55\x74\x36\x61\xC1\xBB\xD1\xD4\xC6\x15\xA8\x13\xB4\x9F\xA4\xFE\xBB\xEE\x15\xB4\x2F\x06\x0C\x29\xF2\xA8\x92\xA4\x61\x0D\xFC\xAB\x5C\x08\x5B\x51\x13\x2B\x4D\xC2\x2A\x61\xC8\xF8\x09\x58\xFC\x2D\x02\xB2\x39\x7D\x99\x66\x81\xBF\x6E\x5C\x95\x45\x20\x6C\xE6\x79\xA7\xD1\xD8\x1C\x29\xFC\xC2\x20\x27\x51\xC8\xF1\x7C\x5D\x34\x67\x69\x85\x11\x30\xC6\x00\xD2\xD7\xF3\xD3\x7C\xB6\xF0\x31\x57\x28\x12\x82\x73\xE9\x33\x2F\xA6\x55\xB4\x0B\x91\x94\x47\x9C\xFA\xBB\x7A\x42\x32\xE8\xAE\x7E\x2D\xC8\xBC\xAC\x14\xBF\xD9\x0F\xD9\x5B\xFC\xC1\xF9\x7A\x95\xE1\x7D\x7E\x96\xFC\x71\xB0\xC2\x4C\xC8\xDF\x45\x34\xC9\xCE\x0D\xF2\x9C\x64\x08\xD0\x3B\xC3\x29\xC5\xB2\xED\x90\x04\xC1\xB1\x29\x91\xC5\x30\x6F\xC1\xA9\x72\x33\xCC\xFE\x5D\x16\x17\x2C\x11\x69\xE7\x7E\xFE\xC5\x83\x08\xDF\xBC\xDC\x22\x3A\x2E\x20\x69\x23\x39\x56\x60\x67\x90\x8B\x2E\x76\x39\xFB\x11\x88\x97\xF6\x7C\xBD\x4B\xB8\x20\x16\x67\x05\x8D\xE2\x3B\xC1\x72\x3F\x94\x95\x37\xC7\x5D\xB9\x9E\xD8\x93\xA1\x17\x8F\xFF\x0C\x66\x15\xC1\x24\x7C\x32\x7C\x03\x1D\x3B\xA1\x58\x45\x32\x93", + ["OU=TDC Internet Root CA,O=TDC Internet,C=DK"] = "\x30\x82\x04\x2B\x30\x82\x03\x13\xA0\x03\x02\x01\x02\x02\x04\x3A\xCC\xA5\x4C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x43\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4B\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x54\x44\x43\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x54\x44\x43\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x31\x30\x34\x30\x35\x31\x36\x33\x33\x31\x37\x5A\x17\x0D\x32\x31\x30\x34\x30\x35\x31\x37\x30\x33\x31\x37\x5A\x30\x43\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4B\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x54\x44\x43\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x54\x44\x43\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xC4\xB8\x40\xBC\x91\xD5\x63\x1F\xD7\x99\xA0\x8B\x0C\x40\x1E\x74\xB7\x48\x9D\x46\x8C\x02\xB2\xE0\x24\x5F\xF0\x19\x13\xA7\x37\x83\x6B\x5D\xC7\x8E\xF9\x84\x30\xCE\x1A\x3B\xFA\xFB\xCE\x8B\x6D\x23\xC6\xC3\x6E\x66\x9F\x89\xA5\xDF\xE0\x42\x50\x67\xFA\x1F\x6C\x1E\xF4\xD0\x05\xD6\xBF\xCA\xD6\x4E\xE4\x68\x60\x6C\x46\xAA\x1C\x5D\x63\xE1\x07\x86\x0E\x65\x00\xA7\x2E\xA6\x71\xC6\xBC\xB9\x81\xA8\x3A\x7D\x1A\xD2\xF9\xD1\xAC\x4B\xCB\xCE\x75\xAF\xDC\x7B\xFA\x81\x73\xD4\xFC\xBA\xBD\x41\x88\xD4\x74\xB3\xF9\x5E\x38\x3A\x3C\x43\xA8\xD2\x95\x4E\x77\x6D\x13\x0C\x9D\x8F\x78\x01\xB7\x5A\x20\x1F\x03\x37\x35\xE2\x2C\xDB\x4B\x2B\x2C\x78\xB9\x49\xDB\xC4\xD0\xC7\x9C\x9C\xE4\x8A\x20\x09\x21\x16\x56\x66\xFF\x05\xEC\x5B\xE3\xF0\xCF\xAB\x24\x24\x5E\xC3\x7F\x70\x7A\x12\xC4\xD2\xB5\x10\xA0\xB6\x21\xE1\x8D\x78\x69\x55\x44\x69\xF5\xCA\x96\x1C\x34\x85\x17\x25\x77\xE2\xF6\x2F\x27\x98\x78\xFD\x79\x06\x3A\xA2\xD6\x5A\x43\xC1\xFF\xEC\x04\x3B\xEE\x13\xEF\xD3\x58\x5A\xFF\x92\xEB\xEC\xAE\xDA\xF2\x37\x03\x47\x41\xB6\x97\xC9\x2D\x0A\x41\x22\xBB\xBB\xE6\xA7\x02\x03\x01\x00\x01\xA3\x82\x01\x25\x30\x82\x01\x21\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x65\x06\x03\x55\x1D\x1F\x04\x5E\x30\x5C\x30\x5A\xA0\x58\xA0\x56\xA4\x54\x30\x52\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4B\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x54\x44\x43\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x31\x1D\x30\x1B\x06\x03\x55\x04\x0B\x13\x14\x54\x44\x43\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x52\x6F\x6F\x74\x20\x43\x41\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x32\x30\x30\x31\x30\x34\x30\x35\x31\x36\x33\x33\x31\x37\x5A\x81\x0F\x32\x30\x32\x31\x30\x34\x30\x35\x31\x37\x30\x33\x31\x37\x5A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x6C\x64\x01\xC7\xFD\x85\x6D\xAC\xC8\xDA\x9E\x50\x08\x85\x08\xB5\x3C\x56\xA8\x50\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x6C\x64\x01\xC7\xFD\x85\x6D\xAC\xC8\xDA\x9E\x50\x08\x85\x08\xB5\x3C\x56\xA8\x50\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x10\x30\x0E\x1B\x08\x56\x35\x2E\x30\x3A\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x4E\x43\xCC\xD1\xDD\x1D\x10\x1B\x06\x7F\xB7\xA4\xFA\xD3\xD9\x4D\xFB\x23\x9F\x23\x54\x5B\xE6\x8B\x2F\x04\x28\x8B\xB5\x27\x6D\x89\xA1\xEC\x98\x69\xDC\xE7\x8D\x26\x83\x05\x79\x74\xEC\xB4\xB9\xA3\x97\xC1\x35\x00\xFD\x15\xDA\x39\x81\x3A\x95\x31\x90\xDE\x97\xE9\x86\xA8\x99\x77\x0C\xE5\x5A\xA0\x84\xFF\x12\x16\xAC\x6E\xB8\x8D\xC3\x7B\x92\xC2\xAC\x2E\xD0\x7D\x28\xEC\xB6\xF3\x60\x38\x69\x6F\x3E\xD8\x04\x55\x3E\x9E\xCC\x55\xD2\xBA\xFE\xBB\x47\x04\xD7\x0A\xD9\x16\x0A\x34\x29\xF5\x58\x13\xD5\x4F\xCF\x8F\x56\x4B\xB3\x1E\xEE\xD3\x98\x79\xDA\x08\x1E\x0C\x6F\xB8\xF8\x16\x27\xEF\xC2\x6F\x3D\xF6\xA3\x4B\x3E\x0E\xE4\x6D\x6C\xDB\x3B\x41\x12\x9B\xBD\x0D\x47\x23\x7F\x3C\x4A\xD0\xAF\xC0\xAF\xF6\xEF\x1B\xB5\x15\xC4\xEB\x83\xC4\x09\x5F\x74\x8B\xD9\x11\xFB\xC2\x56\xB1\x3C\xF8\x70\xCA\x34\x8D\x43\x40\x13\x8C\xFD\x99\x03\x54\x79\xC6\x2E\xEA\x86\xA1\xF6\x3A\xD4\x09\xBC\xF4\xBC\x66\xCC\x3D\x58\xD0\x57\x49\x0A\xEE\x25\xE2\x41\xEE\x13\xF9\x9B\x38\x34\xD1\x00\xF5\x7E\xE7\x94\x1D\xFC\x69\x03\x62\xB8\x99\x05\x05\x3D\x6B\x78\x12\xBD\xB0\x6F\x65", + ["CN=TDC OCES CA,O=TDC,C=DK"] = "\x30\x82\x05\x19\x30\x82\x04\x01\xA0\x03\x02\x01\x02\x02\x04\x3E\x48\xBD\xC4\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x31\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4B\x31\x0C\x30\x0A\x06\x03\x55\x04\x0A\x13\x03\x54\x44\x43\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0B\x54\x44\x43\x20\x4F\x43\x45\x53\x20\x43\x41\x30\x1E\x17\x0D\x30\x33\x30\x32\x31\x31\x30\x38\x33\x39\x33\x30\x5A\x17\x0D\x33\x37\x30\x32\x31\x31\x30\x39\x30\x39\x33\x30\x5A\x30\x31\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4B\x31\x0C\x30\x0A\x06\x03\x55\x04\x0A\x13\x03\x54\x44\x43\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0B\x54\x44\x43\x20\x4F\x43\x45\x53\x20\x43\x41\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\x62\xF6\x61\x20\xB2\xCF\xC0\xC6\x85\xD7\xE3\x79\xE6\xCC\xED\xF2\x39\x92\xA4\x97\x2E\x64\xA3\x84\x5B\x87\x9C\x4C\xFD\xA4\xF3\xC4\x5F\x21\xBD\x56\x10\xEB\xDB\x2E\x61\xEC\x93\x69\xE3\xA3\xCC\xBD\x99\xC3\x05\xFC\x06\xB8\xCA\x36\x1C\xFE\x90\x8E\x49\x4C\xC4\x56\x9A\x2F\x56\xBC\xCF\x7B\x0C\xF1\x6F\x47\xA6\x0D\x43\x4D\xE2\xE9\x1D\x39\x34\xCD\x8D\x2C\xD9\x12\x98\xF9\xE3\xE1\xC1\x4A\x7C\x86\x38\xC4\xA9\xC4\x61\x88\xD2\x5E\xAF\x1A\x26\x4D\xD5\xE4\xA0\x22\x47\x84\xD9\x64\xB7\x19\x96\xFC\xEC\x19\xE4\xB2\x97\x26\x4E\x4A\x4C\xCB\x8F\x24\x8B\x54\x18\x1C\x48\x61\x7B\xD5\x88\x68\xDA\x5D\xB5\xEA\xCD\x1A\x30\xC1\x80\x83\x76\x50\xAA\x4F\xD1\xD4\xDD\x38\xF0\xEF\x16\xF4\xE1\x0C\x50\x06\xBF\xEA\xFB\x7A\x49\xA1\x28\x2B\x1C\xF6\xFC\x15\x32\xA3\x74\x6A\x8F\xA9\xC3\x62\x29\x71\x31\xE5\x3B\xA4\x60\x17\x5E\x74\xE6\xDA\x13\xED\xE9\x1F\x1F\x1B\xD1\xB2\x68\x73\xC6\x10\x34\x75\x46\x10\x10\xE3\x90\x00\x76\x40\xCB\x8B\xB7\x43\x09\x21\xFF\xAB\x4E\x93\xC6\x58\xE9\xA5\x82\xDB\x77\xC4\x3A\x99\xB1\x72\x95\x49\x04\xF0\xB7\x2B\xFA\x7B\x59\x8E\xDD\x02\x03\x01\x00\x01\xA3\x82\x02\x37\x30\x82\x02\x33\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x81\xEC\x06\x03\x55\x1D\x20\x04\x81\xE4\x30\x81\xE1\x30\x81\xDE\x06\x08\x2A\x81\x50\x81\x29\x01\x01\x01\x30\x81\xD1\x30\x2F\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x65\x72\x74\x69\x66\x69\x6B\x61\x74\x2E\x64\x6B\x2F\x72\x65\x70\x6F\x73\x69\x74\x6F\x72\x79\x30\x81\x9D\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x81\x90\x30\x0A\x16\x03\x54\x44\x43\x30\x03\x02\x01\x01\x1A\x81\x81\x43\x65\x72\x74\x69\x66\x69\x6B\x61\x74\x65\x72\x20\x66\x72\x61\x20\x64\x65\x6E\x6E\x65\x20\x43\x41\x20\x75\x64\x73\x74\x65\x64\x65\x73\x20\x75\x6E\x64\x65\x72\x20\x4F\x49\x44\x20\x31\x2E\x32\x2E\x32\x30\x38\x2E\x31\x36\x39\x2E\x31\x2E\x31\x2E\x31\x2E\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x73\x20\x66\x72\x6F\x6D\x20\x74\x68\x69\x73\x20\x43\x41\x20\x61\x72\x65\x20\x69\x73\x73\x75\x65\x64\x20\x75\x6E\x64\x65\x72\x20\x4F\x49\x44\x20\x31\x2E\x32\x2E\x32\x30\x38\x2E\x31\x36\x39\x2E\x31\x2E\x31\x2E\x31\x2E\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x81\x81\x06\x03\x55\x1D\x1F\x04\x7A\x30\x78\x30\x48\xA0\x46\xA0\x44\xA4\x42\x30\x40\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x4B\x31\x0C\x30\x0A\x06\x03\x55\x04\x0A\x13\x03\x54\x44\x43\x31\x14\x30\x12\x06\x03\x55\x04\x03\x13\x0B\x54\x44\x43\x20\x4F\x43\x45\x53\x20\x43\x41\x31\x0D\x30\x0B\x06\x03\x55\x04\x03\x13\x04\x43\x52\x4C\x31\x30\x2C\xA0\x2A\xA0\x28\x86\x26\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x6F\x63\x65\x73\x2E\x63\x65\x72\x74\x69\x66\x69\x6B\x61\x74\x2E\x64\x6B\x2F\x6F\x63\x65\x73\x2E\x63\x72\x6C\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x32\x30\x30\x33\x30\x32\x31\x31\x30\x38\x33\x39\x33\x30\x5A\x81\x0F\x32\x30\x33\x37\x30\x32\x31\x31\x30\x39\x30\x39\x33\x30\x5A\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x60\xB5\x85\xEC\x56\x64\x7E\x12\x19\x27\x67\x1D\x50\x15\x4B\x73\xAE\x3B\xF9\x12\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x60\xB5\x85\xEC\x56\x64\x7E\x12\x19\x27\x67\x1D\x50\x15\x4B\x73\xAE\x3B\xF9\x12\x30\x1D\x06\x09\x2A\x86\x48\x86\xF6\x7D\x07\x41\x00\x04\x10\x30\x0E\x1B\x08\x56\x36\x2E\x30\x3A\x34\x2E\x30\x03\x02\x04\x90\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x0A\xBA\x26\x26\x46\xD3\x73\xA8\x09\xF3\x6B\x0B\x30\x99\xFD\x8A\xE1\x57\x7A\x11\xD3\xB8\x94\xD7\x09\x10\x6E\xA3\xB1\x38\x03\xD1\xB6\xF2\x43\x41\x29\x62\xA7\x72\xD8\xFB\x7C\x05\xE6\x31\x70\x27\x54\x18\x4E\x8A\x7C\x4E\xE5\xD1\xCA\x8C\x78\x88\xCF\x1B\xD3\x90\x8B\xE6\x23\xF8\x0B\x0E\x33\x43\x7D\x9C\xE2\x0A\x19\x8F\xC9\x01\x3E\x74\x5D\x74\xC9\x8B\x1C\x03\xE5\x18\xC8\x01\x4C\x3F\xCB\x97\x05\x5D\x98\x71\xA6\x98\x6F\xB6\x7C\xBD\x37\x7F\xBE\xE1\x93\x25\x6D\x6F\xF0\x0A\xAD\x17\x18\xE1\x03\xBC\x07\x29\xC8\xAD\x26\xE8\xF8\x61\xF0\xFD\x21\x09\x7E\x9A\x8E\xA9\x68\x7D\x48\x62\x72\xBD\x00\xEA\x01\x99\xB8\x06\x82\x51\x81\x4E\xF1\xF5\xB4\x91\x54\xB9\x23\x7A\x00\x9A\x9F\x5D\x8D\xE0\x3C\x64\xB9\x1A\x12\x92\x2A\xC7\x82\x44\x72\x39\xDC\xE2\x3C\xC6\xD8\x55\xF5\x15\x4E\xC8\x05\x0E\xDB\xC6\xD0\x62\xA6\xEC\x15\xB4\xB5\x02\x82\xDB\xAC\x8C\xA2\x81\xF0\x9B\x99\x31\xF5\x20\x20\xA8\x88\x61\x0A\x07\x9F\x94\xFC\xD0\xD7\x1B\xCC\x2E\x17\xF3\x04\x27\x76\x67\xEB\x54\x83\xFD\xA4\x90\x7E\x06\x3D\x04\xA3\x43\x2D\xDA\xFC\x0B\x62\xEA\x2F\x5F\x62\x53", + ["CN=UTN - DATACorp SGC,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US"] = "\x30\x82\x04\x5E\x30\x82\x03\x46\xA0\x03\x02\x01\x02\x02\x10\x44\xBE\x0C\x8B\x50\x00\x21\xB4\x11\xD3\x2A\x68\x06\xA9\xAD\x69\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x93\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0E\x53\x61\x6C\x74\x20\x4C\x61\x6B\x65\x20\x43\x69\x74\x79\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x0B\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x55\x54\x4E\x20\x2D\x20\x44\x41\x54\x41\x43\x6F\x72\x70\x20\x53\x47\x43\x30\x1E\x17\x0D\x39\x39\x30\x36\x32\x34\x31\x38\x35\x37\x32\x31\x5A\x17\x0D\x31\x39\x30\x36\x32\x34\x31\x39\x30\x36\x33\x30\x5A\x30\x81\x93\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0E\x53\x61\x6C\x74\x20\x4C\x61\x6B\x65\x20\x43\x69\x74\x79\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x0B\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x55\x54\x4E\x20\x2D\x20\x44\x41\x54\x41\x43\x6F\x72\x70\x20\x53\x47\x43\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\xDF\xEE\x58\x10\xA2\x2B\x6E\x55\xC4\x8E\xBF\x2E\x46\x09\xE7\xE0\x08\x0F\x2E\x2B\x7A\x13\x94\x1B\xBD\xF6\xB6\x80\x8E\x65\x05\x93\x00\x1E\xBC\xAF\xE2\x0F\x8E\x19\x0D\x12\x47\xEC\xAC\xAD\xA3\xFA\x2E\x70\xF8\xDE\x6E\xFB\x56\x42\x15\x9E\x2E\x5C\xEF\x23\xDE\x21\xB9\x05\x76\x27\x19\x0F\x4F\xD6\xC3\x9C\xB4\xBE\x94\x19\x63\xF2\xA6\x11\x0A\xEB\x53\x48\x9C\xBE\xF2\x29\x3B\x16\xE8\x1A\xA0\x4C\xA6\xC9\xF4\x18\x59\x68\xC0\x70\xF2\x53\x00\xC0\x5E\x50\x82\xA5\x56\x6F\x36\xF9\x4A\xE0\x44\x86\xA0\x4D\x4E\xD6\x47\x6E\x49\x4A\xCB\x67\xD7\xA6\xC4\x05\xB9\x8E\x1E\xF4\xFC\xFF\xCD\xE7\x36\xE0\x9C\x05\x6C\xB2\x33\x22\x15\xD0\xB4\xE0\xCC\x17\xC0\xB2\xC0\xF4\xFE\x32\x3F\x29\x2A\x95\x7B\xD8\xF2\xA7\x4E\x0F\x54\x7C\xA1\x0D\x80\xB3\x09\x03\xC1\xFF\x5C\xDD\x5E\x9A\x3E\xBC\xAE\xBC\x47\x8A\x6A\xAE\x71\xCA\x1F\xB1\x2A\xB8\x5F\x42\x05\x0B\xEC\x46\x30\xD1\x72\x0B\xCA\xE9\x56\x6D\xF5\xEF\xDF\x78\xBE\x61\xBA\xB2\xA5\xAE\x04\x4C\xBC\xA8\xAC\x69\x15\x97\xBD\xEF\xEB\xB4\x8C\xBF\x35\xF8\xD4\xC3\xD1\x28\x0E\x5C\x3A\x9F\x70\x18\x33\x20\x77\xC4\xA2\xAF\x02\x03\x01\x00\x01\xA3\x81\xAB\x30\x81\xA8\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\xC6\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x53\x32\xD1\xB3\xCF\x7F\xFA\xE0\xF1\xA0\x5D\x85\x4E\x92\xD2\x9E\x45\x1D\xB4\x4F\x30\x3D\x06\x03\x55\x1D\x1F\x04\x36\x30\x34\x30\x32\xA0\x30\xA0\x2E\x86\x2C\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x2F\x55\x54\x4E\x2D\x44\x41\x54\x41\x43\x6F\x72\x70\x53\x47\x43\x2E\x63\x72\x6C\x30\x2A\x06\x03\x55\x1D\x25\x04\x23\x30\x21\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x01\x06\x0A\x2B\x06\x01\x04\x01\x82\x37\x0A\x03\x03\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x04\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x27\x35\x97\x00\x8A\x8B\x28\xBD\xC6\x33\x30\x1E\x29\xFC\xE2\xF7\xD5\x98\xD4\x40\xBB\x60\xCA\xBF\xAB\x17\x2C\x09\x36\x7F\x50\xFA\x41\xDC\xAE\x96\x3A\x0A\x23\x3E\x89\x59\xC9\xA3\x07\xED\x1B\x37\xAD\xFC\x7C\xBE\x51\x49\x5A\xDE\x3A\x0A\x54\x08\x16\x45\xC2\x99\xB1\x87\xCD\x8C\x68\xE0\x69\x03\xE9\xC4\x4E\x98\xB2\x3B\x8C\x16\xB3\x0E\xA0\x0C\x98\x50\x9B\x93\xA9\x70\x09\xC8\x2C\xA3\x8F\xDF\x02\xE4\xE0\x71\x3A\xF1\xB4\x23\x72\xA0\xAA\x01\xDF\xDF\x98\x3E\x14\x50\xA0\x31\x26\xBD\x28\xE9\x5A\x30\x26\x75\xF9\x7B\x60\x1C\x8D\xF3\xCD\x50\x26\x6D\x04\x27\x9A\xDF\xD5\x0D\x45\x47\x29\x6B\x2C\xE6\x76\xD9\xA9\x29\x7D\x32\xDD\xC9\x36\x3C\xBD\xAE\x35\xF1\x11\x9E\x1D\xBB\x90\x3F\x12\x47\x4E\x8E\xD7\x7E\x0F\x62\x73\x1D\x52\x26\x38\x1C\x18\x49\xFD\x30\x74\x9A\xC4\xE5\x22\x2F\xD8\xC0\x8D\xED\x91\x7A\x4C\x00\x8F\x72\x7F\x5D\xDA\xDD\x1B\x8B\x45\x6B\xE7\xDD\x69\x97\xA8\xC5\x56\x4C\x0F\x0C\xF6\x9F\x7A\x91\x37\xF6\x97\x82\xE0\xDD\x71\x69\xFF\x76\x3F\x60\x4D\x3C\xCF\xF7\x99\xF9\xC6\x57\xF4\xC9\x55\x39\x78\xBA\x2C\x79\xC9\xA6\x88\x2B\xF4\x08", + ["CN=UTN-USERFirst-Hardware,OU=http://www.usertrust.com,O=The USERTRUST Network,L=Salt Lake City,ST=UT,C=US"] = "\x30\x82\x04\x74\x30\x82\x03\x5C\xA0\x03\x02\x01\x02\x02\x10\x44\xBE\x0C\x8B\x50\x00\x24\xB4\x11\xD3\x36\x2A\xFE\x65\x0A\xFD\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x97\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0E\x53\x61\x6C\x74\x20\x4C\x61\x6B\x65\x20\x43\x69\x74\x79\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x0B\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x55\x54\x4E\x2D\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2D\x48\x61\x72\x64\x77\x61\x72\x65\x30\x1E\x17\x0D\x39\x39\x30\x37\x30\x39\x31\x38\x31\x30\x34\x32\x5A\x17\x0D\x31\x39\x30\x37\x30\x39\x31\x38\x31\x39\x32\x32\x5A\x30\x81\x97\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x0B\x30\x09\x06\x03\x55\x04\x08\x13\x02\x55\x54\x31\x17\x30\x15\x06\x03\x55\x04\x07\x13\x0E\x53\x61\x6C\x74\x20\x4C\x61\x6B\x65\x20\x43\x69\x74\x79\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x13\x15\x54\x68\x65\x20\x55\x53\x45\x52\x54\x52\x55\x53\x54\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x21\x30\x1F\x06\x03\x55\x04\x0B\x13\x18\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x55\x54\x4E\x2D\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2D\x48\x61\x72\x64\x77\x61\x72\x65\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\xB1\xF7\xC3\x38\x3F\xB4\xA8\x7F\xCF\x39\x82\x51\x67\xD0\x6D\x9F\xD2\xFF\x58\xF3\xE7\x9F\x2B\xEC\x0D\x89\x54\x99\xB9\x38\x99\x16\xF7\xE0\x21\x79\x48\xC2\xBB\x61\x74\x12\x96\x1D\x3C\x6A\x72\xD5\x3C\x10\x67\x3A\x39\xED\x2B\x13\xCD\x66\xEB\x95\x09\x33\xA4\x6C\x97\xB1\xE8\xC6\xEC\xC1\x75\x79\x9C\x46\x5E\x8D\xAB\xD0\x6A\xFD\xB9\x2A\x55\x17\x10\x54\xB3\x19\xF0\x9A\xF6\xF1\xB1\x5D\xB6\xA7\x6D\xFB\xE0\x71\x17\x6B\xA2\x88\xFB\x00\xDF\xFE\x1A\x31\x77\x0C\x9A\x01\x7A\xB1\x32\xE3\x2B\x01\x07\x38\x6E\xC3\xA5\x5E\x23\xBC\x45\x9B\x7B\x50\xC1\xC9\x30\x8F\xDB\xE5\x2B\x7A\xD3\x5B\xFB\x33\x40\x1E\xA0\xD5\x98\x17\xBC\x8B\x87\xC3\x89\xD3\x5D\xA0\x8E\xB2\xAA\xAA\xF6\x8E\x69\x88\x06\xC5\xFA\x89\x21\xF3\x08\x9D\x69\x2E\x09\x33\x9B\x29\x0D\x46\x0F\x8C\xCC\x49\x34\xB0\x69\x51\xBD\xF9\x06\xCD\x68\xAD\x66\x4C\xBC\x3E\xAC\x61\xBD\x0A\x88\x0E\xC8\xDF\x3D\xEE\x7C\x04\x4C\x9D\x0A\x5E\x6B\x91\xD6\xEE\xC7\xED\x28\x8D\xAB\x4D\x87\x89\x73\xD0\x6E\xA4\xD0\x1E\x16\x8B\x14\xE1\x76\x44\x03\x7F\x63\xAC\xE4\xCD\x49\x9C\xC5\x92\xF4\xAB\x32\xA1\x48\x5B\x02\x03\x01\x00\x01\xA3\x81\xB9\x30\x81\xB6\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\xC6\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xA1\x72\x5F\x26\x1B\x28\x98\x43\x95\x5D\x07\x37\xD5\x85\x96\x9D\x4B\xD2\xC3\x45\x30\x44\x06\x03\x55\x1D\x1F\x04\x3D\x30\x3B\x30\x39\xA0\x37\xA0\x35\x86\x33\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x75\x73\x65\x72\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x2F\x55\x54\x4E\x2D\x55\x53\x45\x52\x46\x69\x72\x73\x74\x2D\x48\x61\x72\x64\x77\x61\x72\x65\x2E\x63\x72\x6C\x30\x31\x06\x03\x55\x1D\x25\x04\x2A\x30\x28\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x01\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x05\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x06\x06\x08\x2B\x06\x01\x05\x05\x07\x03\x07\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x47\x19\x0F\xDE\x74\xC6\x99\x97\xAF\xFC\xAD\x28\x5E\x75\x8E\xEB\x2D\x67\xEE\x4E\x7B\x2B\xD7\x0C\xFF\xF6\xDE\xCB\x55\xA2\x0A\xE1\x4C\x54\x65\x93\x60\x6B\x9F\x12\x9C\xAD\x5E\x83\x2C\xEB\x5A\xAE\xC0\xE4\x2D\xF4\x00\x63\x1D\xB8\xC0\x6C\xF2\xCF\x49\xBB\x4D\x93\x6F\x06\xA6\x0A\x22\xB2\x49\x62\x08\x4E\xFF\xC8\xC8\x14\xB2\x88\x16\x5D\xE7\x01\xE4\x12\x95\xE5\x45\x34\xB3\x8B\x69\xBD\xCF\xB4\x85\x8F\x75\x51\x9E\x7D\x3A\x38\x3A\x14\x48\x12\xC6\xFB\xA7\x3B\x1A\x8D\x0D\x82\x40\x07\xE8\x04\x08\x90\xA1\x89\xCB\x19\x50\xDF\xCA\x1C\x01\xBC\x1D\x04\x19\x7B\x10\x76\x97\x3B\xEE\x90\x90\xCA\xC4\x0E\x1F\x16\x6E\x75\xEF\x33\xF8\xD3\x6F\x5B\x1E\x96\xE3\xE0\x74\x77\x74\x7B\x8A\xA2\x6E\x2D\xDD\x76\xD6\x39\x30\x82\xF0\xAB\x9C\x52\xF2\x2A\xC7\xAF\x49\x5E\x7E\xC7\x68\xE5\x82\x81\xC8\x6A\x27\xF9\x27\x88\x2A\xD5\x58\x50\x95\x1F\xF0\x3B\x1C\x57\xBB\x7D\x14\x39\x62\x2B\x9A\xC9\x94\x92\x2A\xA3\x22\x0C\xFF\x89\x26\x7D\x5F\x23\x2B\x47\xD7\x15\x1D\xA9\x6A\x9E\x51\x0D\x2A\x51\x9E\x81\xF9\xD4\x3B\x5E\x70\x12\x7F\x10\x32\x9C\x1E\xBB\x9D\xF8\x66\xA8", + ["CN=Chambers of Commerce Root,OU=http://www.chambersign.org,O=AC Camerfirma SA CIF A82743287,C=EU"] = "\x30\x82\x04\xBD\x30\x82\x03\xA5\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x41\x20\x43\x49\x46\x20\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x13\x1A\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x33\x30\x39\x33\x30\x31\x36\x31\x33\x34\x33\x5A\x17\x0D\x33\x37\x30\x39\x33\x30\x31\x36\x31\x33\x34\x34\x5A\x30\x7F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x41\x20\x43\x49\x46\x20\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x13\x1A\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x30\x82\x01\x20\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0D\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xB7\x36\x55\xE5\xA5\x5D\x18\x30\xE0\xDA\x89\x54\x91\xFC\xC8\xC7\x52\xF8\x2F\x50\xD9\xEF\xB1\x75\x73\x65\x47\x7D\x1B\x5B\xBA\x75\xC5\xFC\xA1\x88\x24\xFA\x2F\xED\xCA\x08\x4A\x39\x54\xC4\x51\x7A\xB5\xDA\x60\xEA\x38\x3C\x81\xB2\xCB\xF1\xBB\xD9\x91\x23\x3F\x48\x01\x70\x75\xA9\x05\x2A\xAD\x1F\x71\xF3\xC9\x54\x3D\x1D\x06\x6A\x40\x3E\xB3\x0C\x85\xEE\x5C\x1B\x79\xC2\x62\xC4\xB8\x36\x8E\x35\x5D\x01\x0C\x23\x04\x47\x35\xAA\x9B\x60\x4E\xA0\x66\x3D\xCB\x26\x0A\x9C\x40\xA1\xF4\x5D\x98\xBF\x71\xAB\xA5\x00\x68\x2A\xED\x83\x7A\x0F\xA2\x14\xB5\xD4\x22\xB3\x80\xB0\x3C\x0C\x5A\x51\x69\x2D\x58\x18\x8F\xED\x99\x9E\xF1\xAE\xE2\x95\xE6\xF6\x47\xA8\xD6\x0C\x0F\xB0\x58\x58\xDB\xC3\x66\x37\x9E\x9B\x91\x54\x33\x37\xD2\x94\x1C\x6A\x48\xC9\xC9\xF2\xA5\xDA\xA5\x0C\x23\xF7\x23\x0E\x9C\x32\x55\x5E\x71\x9C\x84\x05\x51\x9A\x2D\xFD\xE6\x4E\x2A\x34\x5A\xDE\xCA\x40\x37\x67\x0C\x54\x21\x55\x77\xDA\x0A\x0C\xCC\x97\xAE\x80\xDC\x94\x36\x4A\xF4\x3E\xCE\x36\x13\x1E\x53\xE4\xAC\x4E\x3A\x05\xEC\xDB\xAE\x72\x9C\x38\x8B\xD0\x39\x3B\x89\x0A\x3E\x77\xFE\x75\x02\x01\x03\xA3\x82\x01\x44\x30\x82\x01\x40\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x0C\x30\x3C\x06\x03\x55\x1D\x1F\x04\x35\x30\x33\x30\x31\xA0\x2F\xA0\x2D\x86\x2B\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x2F\x63\x68\x61\x6D\x62\x65\x72\x73\x72\x6F\x6F\x74\x2E\x63\x72\x6C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE3\x94\xF5\xB1\x4D\xE9\xDB\xA1\x29\x5B\x57\x8B\x4D\x76\x06\x76\xE1\xD1\xA2\x8A\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x27\x06\x03\x55\x1D\x11\x04\x20\x30\x1E\x81\x1C\x63\x68\x61\x6D\x62\x65\x72\x73\x72\x6F\x6F\x74\x40\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x30\x27\x06\x03\x55\x1D\x12\x04\x20\x30\x1E\x81\x1C\x63\x68\x61\x6D\x62\x65\x72\x73\x72\x6F\x6F\x74\x40\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x30\x58\x06\x03\x55\x1D\x20\x04\x51\x30\x4F\x30\x4D\x06\x0B\x2B\x06\x01\x04\x01\x81\x87\x2E\x0A\x03\x01\x30\x3E\x30\x3C\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x30\x68\x74\x74\x70\x3A\x2F\x2F\x63\x70\x73\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x2F\x63\x70\x73\x2F\x63\x68\x61\x6D\x62\x65\x72\x73\x72\x6F\x6F\x74\x2E\x68\x74\x6D\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x0C\x41\x97\xC2\x1A\x86\xC0\x22\x7C\x9F\xFB\x90\xF3\x1A\xD1\x03\xB1\xEF\x13\xF9\x21\x5F\x04\x9C\xDA\xC9\xA5\x8D\x27\x6C\x96\x87\x91\xBE\x41\x90\x01\x72\x93\xE7\x1E\x7D\x5F\xF6\x89\xC6\x5D\xA7\x40\x09\x3D\xAC\x49\x45\x45\xDC\x2E\x8D\x30\x68\xB2\x09\xBA\xFB\xC3\x2F\xCC\xBA\x0B\xDF\x3F\x77\x7B\x46\x7D\x3A\x12\x24\x8E\x96\x8F\x3C\x05\x0A\x6F\xD2\x94\x28\x1D\x6D\x0C\xC0\x2E\x88\x22\xD5\xD8\xCF\x1D\x13\xC7\xF0\x48\xD7\xD7\x05\xA7\xCF\xC7\x47\x9E\x3B\x3C\x34\xC8\x80\x4F\xD4\x14\xBB\xFC\x0D\x50\xF7\xFA\xB3\xEC\x42\x5F\xA9\xDD\x6D\xC8\xF4\x75\xCF\x7B\xC1\x72\x26\xB1\x01\x1C\x5C\x2C\xFD\x7A\x4E\xB4\x01\xC5\x05\x57\xB9\xE7\x3C\xAA\x05\xD9\x88\xE9\x07\x46\x41\xCE\xEF\x41\x81\xAE\x58\xDF\x83\xA2\xAE\xCA\xD7\x77\x1F\xE7\x00\x3C\x9D\x6F\x8E\xE4\x32\x09\x1D\x4D\x78\x34\x78\x34\x3C\x94\x9B\x26\xED\x4F\x71\xC6\x19\x7A\xBD\x20\x22\x48\x5A\xFE\x4B\x7D\x03\xB7\xE7\x58\xBE\xC6\x32\x4E\x74\x1E\x68\xDD\xA8\x68\x5B\xB3\x3E\xEE\x62\x7D\xD9\x80\xE8\x0A\x75\x7A\xB7\xEE\xB4\x65\x9A\x21\x90\xE0\xAA\xD0\x98\xBC\x38\xB5\x73\x3C\x8B\xF8\xDC", + ["CN=Global Chambersign Root,OU=http://www.chambersign.org,O=AC Camerfirma SA CIF A82743287,C=EU"] = "\x30\x82\x04\xC5\x30\x82\x03\xAD\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x41\x20\x43\x49\x46\x20\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x13\x1A\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x47\x6C\x6F\x62\x61\x6C\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x33\x30\x39\x33\x30\x31\x36\x31\x34\x31\x38\x5A\x17\x0D\x33\x37\x30\x39\x33\x30\x31\x36\x31\x34\x31\x38\x5A\x30\x7D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x41\x20\x43\x49\x46\x20\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x13\x1A\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x47\x6C\x6F\x62\x61\x6C\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x20\x52\x6F\x6F\x74\x30\x82\x01\x20\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0D\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xA2\x70\xA2\xD0\x9F\x42\xAE\x5B\x17\xC7\xD8\x7D\xCF\x14\x83\xFC\x4F\xC9\xA1\xB7\x13\xAF\x8A\xD7\x9E\x3E\x04\x0A\x92\x8B\x60\x56\xFA\xB4\x32\x2F\x88\x4D\xA1\x60\x08\xF4\xB7\x09\x4E\xA0\x49\x2F\x49\xD6\xD3\xDF\x9D\x97\x5A\x9F\x94\x04\x70\xEC\x3F\x59\xD9\xB7\xCC\x66\x8B\x98\x52\x28\x09\x02\xDF\xC5\x2F\x84\x8D\x7A\x97\x77\xBF\xEC\x40\x9D\x25\x72\xAB\xB5\x3F\x32\x98\xFB\xB7\xB7\xFC\x72\x84\xE5\x35\x87\xF9\x55\xFA\xA3\x1F\x0E\x6F\x2E\x28\xDD\x69\xA0\xD9\x42\x10\xC6\xF8\xB5\x44\xC2\xD0\x43\x7F\xDB\xBC\xE4\xA2\x3C\x6A\x55\x78\x0A\x77\xA9\xD8\xEA\x19\x32\xB7\x2F\xFE\x5C\x3F\x1B\xEE\xB1\x98\xEC\xCA\xAD\x7A\x69\x45\xE3\x96\x0F\x55\xF6\xE6\xED\x75\xEA\x65\xE8\x32\x56\x93\x46\x89\xA8\x25\x8A\x65\x06\xEE\x6B\xBF\x79\x07\xD0\xF1\xB7\xAF\xED\x2C\x4D\x92\xBB\xC0\xA8\x5F\xA7\x67\x7D\x04\xF2\x15\x08\x70\xAC\x92\xD6\x7D\x04\xD2\x33\xFB\x4C\xB6\x0B\x0B\xFB\x1A\xC9\xC4\x8D\x03\xA9\x7E\x5C\xF2\x50\xAB\x12\xA5\xA1\xCF\x48\x50\xA5\xEF\xD2\xC8\x1A\x13\xFA\xB0\x7F\xB1\x82\x1C\x77\x6A\x0F\x5F\xDC\x0B\x95\x8F\xEF\x43\x7E\xE6\x45\x09\x25\x02\x01\x03\xA3\x82\x01\x50\x30\x82\x01\x4C\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x0C\x30\x3F\x06\x03\x55\x1D\x1F\x04\x38\x30\x36\x30\x34\xA0\x32\xA0\x30\x86\x2E\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x2F\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x72\x6F\x6F\x74\x2E\x63\x72\x6C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x43\x9C\x36\x9F\xB0\x9E\x30\x4D\xC6\xCE\x5F\xAD\x10\xAB\xE5\x03\xA5\xFA\xA9\x14\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x2A\x06\x03\x55\x1D\x11\x04\x23\x30\x21\x81\x1F\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x72\x6F\x6F\x74\x40\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x30\x2A\x06\x03\x55\x1D\x12\x04\x23\x30\x21\x81\x1F\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x72\x6F\x6F\x74\x40\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x30\x5B\x06\x03\x55\x1D\x20\x04\x54\x30\x52\x30\x50\x06\x0B\x2B\x06\x01\x04\x01\x81\x87\x2E\x0A\x01\x01\x30\x41\x30\x3F\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x33\x68\x74\x74\x70\x3A\x2F\x2F\x63\x70\x73\x2E\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x2E\x6F\x72\x67\x2F\x63\x70\x73\x2F\x63\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x72\x6F\x6F\x74\x2E\x68\x74\x6D\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3C\x3B\x70\x91\xF9\x04\x54\x27\x91\xE1\xED\xED\xFE\x68\x7F\x61\x5D\xE5\x41\x65\x4F\x32\xF1\x18\x05\x94\x6A\x1C\xDE\x1F\x70\xDB\x3E\x7B\x32\x02\x34\xB5\x0C\x6C\xA1\x8A\x7C\xA5\xF4\x8F\xFF\xD4\xD8\xAD\x17\xD5\x2D\x04\xD1\x3F\x58\x80\xE2\x81\x59\x88\xBE\xC0\xE3\x46\x93\x24\xFE\x90\xBD\x26\xA2\x30\x2D\xE8\x97\x26\x57\x35\x89\x74\x96\x18\xF6\x15\xE2\xAF\x24\x19\x56\x02\x02\xB2\xBA\x0F\x14\xEA\xC6\x8A\x66\xC1\x86\x45\x55\x8B\xBE\x92\xBE\x9C\xA4\x04\xC7\x49\x3C\x9E\xE8\x29\x7A\x89\xD7\xFE\xAF\xFF\x68\xF5\xA5\x17\x90\xBD\xAC\x99\xCC\xA5\x86\x57\x09\x67\x46\xDB\xD6\x16\xC2\x46\xF1\xE4\xA9\x50\xF5\x8F\xD1\x92\x15\xD3\x5F\x3E\xC6\x00\x49\x3A\x6E\x58\xB2\xD1\xD1\x27\x0D\x25\xC8\x32\xF8\x20\x11\xCD\x7D\x32\x33\x48\x94\x54\x4C\xDD\xDC\x79\xC4\x30\x9F\xEB\x8E\xB8\x55\xB5\xD7\x88\x5C\xC5\x6A\x24\x3D\xB2\xD3\x05\x03\x51\xC6\x07\xEF\xCC\x14\x72\x74\x3D\x6E\x72\xCE\x18\x28\x8C\x4A\xA0\x77\xE5\x09\x2B\x45\x44\x47\xAC\xB7\x67\x7F\x01\x8A\x05\x5A\x93\xBE\xA1\xC1\xFF\xF8\xE7\x0E\x67\xA4\x47\x49\x76\x5D\x75\x90\x1A\xF5\x26\x8F\xF0", + ["CN=NetLock Kozjegyzoi (Class A) Tanusitvanykiado,OU=Tanusitvanykiadok,O=NetLock Halozatbiztonsagi Kft.,L=Budapest,ST=Hungary,C=HU"] = "\x30\x82\x06\x7D\x30\x82\x05\x65\xA0\x03\x02\x01\x02\x02\x02\x01\x03\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\xAF\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x48\x75\x6E\x67\x61\x72\x79\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x48\x61\x6C\x6F\x7A\x61\x74\x62\x69\x7A\x74\x6F\x6E\x73\x61\x67\x69\x20\x4B\x66\x74\x2E\x31\x1A\x30\x18\x06\x03\x55\x04\x0B\x13\x11\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x6B\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x6F\x7A\x6A\x65\x67\x79\x7A\x6F\x69\x20\x28\x43\x6C\x61\x73\x73\x20\x41\x29\x20\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x30\x1E\x17\x0D\x39\x39\x30\x32\x32\x34\x32\x33\x31\x34\x34\x37\x5A\x17\x0D\x31\x39\x30\x32\x31\x39\x32\x33\x31\x34\x34\x37\x5A\x30\x81\xAF\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x48\x75\x6E\x67\x61\x72\x79\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x48\x61\x6C\x6F\x7A\x61\x74\x62\x69\x7A\x74\x6F\x6E\x73\x61\x67\x69\x20\x4B\x66\x74\x2E\x31\x1A\x30\x18\x06\x03\x55\x04\x0B\x13\x11\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x6B\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x6F\x7A\x6A\x65\x67\x79\x7A\x6F\x69\x20\x28\x43\x6C\x61\x73\x73\x20\x41\x29\x20\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\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\xBC\x74\x8C\x0F\xBB\x4C\xF4\x37\x1E\xA9\x05\x82\xD8\xE6\xE1\x6C\x70\xEA\x78\xB5\x6E\xD1\x38\x44\x0D\xA8\x83\xCE\x5D\xD2\xD6\xD5\x81\xC5\xD4\x4B\xE7\x5B\x94\x70\x26\xDB\x3B\x9D\x6A\x4C\x62\xF7\x71\xF3\x64\xD6\x61\x3B\x3D\xEB\x73\xA3\x37\xD9\xCF\xEA\x8C\x92\x3B\xCD\xF7\x07\xDC\x66\x74\x97\xF4\x45\x22\xDD\xF4\x5C\xE0\xBF\x6D\xF3\xBE\x65\x33\xE4\x15\x3A\xBF\xDB\x98\x90\x55\x38\xC4\xED\xA6\x55\x63\x0B\xB0\x78\x04\xF4\xE3\x6E\xC1\x3F\x8E\xFC\x51\x78\x1F\x92\x9E\x83\xC2\xFE\xD9\xB0\xA9\xC9\xBC\x5A\x00\xFF\xA9\xA8\x98\x74\xFB\xF6\x2C\x3E\x15\x39\x0D\xB6\x04\x55\xA8\x0E\x98\x20\x42\xB3\xB1\x25\xAD\x7E\x9A\x6F\x5D\x53\xB1\xAB\x0C\xFC\xEB\xE0\xF3\x7A\xB3\xA8\xB3\xFF\x46\xF6\x63\xA2\xD8\x3A\x98\x7B\xB6\xAC\x85\xFF\xB0\x25\x4F\x74\x63\xE7\x13\x07\xA5\x0A\x8F\x05\xF7\xC0\x64\x6F\x7E\xA7\x27\x80\x96\xDE\xD4\x2E\x86\x60\xC7\x6B\x2B\x5E\x73\x7B\x17\xE7\x91\x3F\x64\x0C\xD8\x4B\x22\x34\x2B\x9B\x32\xF2\x48\x1F\x9F\xA1\x0A\x84\x7A\xE2\xC2\xAD\x97\x3D\x8E\xD5\xC1\xF9\x56\xA3\x50\xE9\xC6\xB4\xFA\x98\xA2\xEE\x95\xE6\x2A\x03\x8C\xDF\x02\x03\x01\x00\x01\xA3\x82\x02\x9F\x30\x82\x02\x9B\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x00\x06\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x04\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x02\x60\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x0D\x04\x82\x02\x51\x16\x82\x02\x4D\x46\x49\x47\x59\x45\x4C\x45\x4D\x21\x20\x45\x7A\x65\x6E\x20\x74\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x41\x6C\x74\x61\x6C\x61\x6E\x6F\x73\x20\x53\x7A\x6F\x6C\x67\x61\x6C\x74\x61\x74\x61\x73\x69\x20\x46\x65\x6C\x74\x65\x74\x65\x6C\x65\x69\x62\x65\x6E\x20\x6C\x65\x69\x72\x74\x20\x65\x6C\x6A\x61\x72\x61\x73\x6F\x6B\x20\x61\x6C\x61\x70\x6A\x61\x6E\x20\x6B\x65\x73\x7A\x75\x6C\x74\x2E\x20\x41\x20\x68\x69\x74\x65\x6C\x65\x73\x69\x74\x65\x73\x20\x66\x6F\x6C\x79\x61\x6D\x61\x74\x61\x74\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x74\x65\x72\x6D\x65\x6B\x66\x65\x6C\x65\x6C\x6F\x73\x73\x65\x67\x2D\x62\x69\x7A\x74\x6F\x73\x69\x74\x61\x73\x61\x20\x76\x65\x64\x69\x2E\x20\x41\x20\x64\x69\x67\x69\x74\x61\x6C\x69\x73\x20\x61\x6C\x61\x69\x72\x61\x73\x20\x65\x6C\x66\x6F\x67\x61\x64\x61\x73\x61\x6E\x61\x6B\x20\x66\x65\x6C\x74\x65\x74\x65\x6C\x65\x20\x61\x7A\x20\x65\x6C\x6F\x69\x72\x74\x20\x65\x6C\x6C\x65\x6E\x6F\x72\x7A\x65\x73\x69\x20\x65\x6C\x6A\x61\x72\x61\x73\x20\x6D\x65\x67\x74\x65\x74\x65\x6C\x65\x2E\x20\x41\x7A\x20\x65\x6C\x6A\x61\x72\x61\x73\x20\x6C\x65\x69\x72\x61\x73\x61\x20\x6D\x65\x67\x74\x61\x6C\x61\x6C\x68\x61\x74\x6F\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x68\x6F\x6E\x6C\x61\x70\x6A\x61\x6E\x20\x61\x20\x68\x74\x74\x70\x73\x3A\x2F\x2F\x77\x77\x77\x2E\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2F\x64\x6F\x63\x73\x20\x63\x69\x6D\x65\x6E\x20\x76\x61\x67\x79\x20\x6B\x65\x72\x68\x65\x74\x6F\x20\x61\x7A\x20\x65\x6C\x6C\x65\x6E\x6F\x72\x7A\x65\x73\x40\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x20\x65\x2D\x6D\x61\x69\x6C\x20\x63\x69\x6D\x65\x6E\x2E\x20\x49\x4D\x50\x4F\x52\x54\x41\x4E\x54\x21\x20\x54\x68\x65\x20\x69\x73\x73\x75\x61\x6E\x63\x65\x20\x61\x6E\x64\x20\x74\x68\x65\x20\x75\x73\x65\x20\x6F\x66\x20\x74\x68\x69\x73\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x20\x73\x75\x62\x6A\x65\x63\x74\x20\x74\x6F\x20\x74\x68\x65\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x43\x50\x53\x20\x61\x76\x61\x69\x6C\x61\x62\x6C\x65\x20\x61\x74\x20\x68\x74\x74\x70\x73\x3A\x2F\x2F\x77\x77\x77\x2E\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2F\x64\x6F\x63\x73\x20\x6F\x72\x20\x62\x79\x20\x65\x2D\x6D\x61\x69\x6C\x20\x61\x74\x20\x63\x70\x73\x40\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x82\x01\x01\x00\x48\x24\x46\xF7\xBA\x56\x6F\xFA\xC8\x28\x03\x40\x4E\xE5\x31\x39\x6B\x26\x6B\x53\x7F\xDB\xDF\xDF\xF3\x71\x3D\x26\xC0\x14\x0E\xC6\x67\x7B\x23\xA8\x0C\x73\xDD\x01\xBB\xC6\xCA\x6E\x37\x39\x55\xD5\xC7\x8C\x56\x20\x0E\x28\x0A\x0E\xD2\x2A\xA4\xB0\x49\x52\xC6\x38\x07\xFE\xBE\x0A\x09\x8C\xD1\x98\xCF\xCA\xDA\x14\x31\xA1\x4F\xD2\x39\xFC\x0F\x11\x2C\x43\xC3\xDD\xAB\x93\xC7\x55\x3E\x47\x7C\x18\x1A\x00\xDC\xF3\x7B\xD8\xF2\x7F\x52\x6C\x20\xF4\x0B\x5F\x69\x52\xF4\xEE\xF8\xB2\x29\x60\xEB\xE3\x49\x31\x21\x0D\xD6\xB5\x10\x41\xE2\x41\x09\x6C\xE2\x1A\x9A\x56\x4B\x77\x02\xF6\xA0\x9B\x9A\x27\x87\xE8\x55\x29\x71\xC2\x90\x9F\x45\x78\x1A\xE1\x15\x64\x3D\xD0\x0E\xD8\xA0\x76\x9F\xAE\xC5\xD0\x2E\xEA\xD6\x0F\x56\xEC\x64\x7F\x5A\x9B\x14\x58\x01\x27\x7E\x13\x50\xC7\x6B\x2A\xE6\x68\x3C\xBF\x5C\xA0\x0A\x1B\xE1\x0E\x7A\xE9\xE2\x80\xC3\xE9\xE9\xF6\xFD\x6C\x11\x9E\xD0\xE5\x28\x27\x2B\x54\x32\x42\x14\x82\x75\xE6\x4A\xF0\x2B\x66\x75\x63\x8C\xA2\xFB\x04\x3E\x83\x0E\x9B\x36\xF0\x18\xE4\x26\x20\xC3\x8C\xF0\x28\x07\xAD\x3C\x17\x66\x88\xB5\xFD\xB6\x88", + ["CN=NetLock Uzleti (Class B) Tanusitvanykiado,OU=Tanusitvanykiadok,O=NetLock Halozatbiztonsagi Kft.,L=Budapest,C=HU"] = "\x30\x82\x05\x4B\x30\x82\x04\xB4\xA0\x03\x02\x01\x02\x02\x01\x69\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\x99\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x48\x61\x6C\x6F\x7A\x61\x74\x62\x69\x7A\x74\x6F\x6E\x73\x61\x67\x69\x20\x4B\x66\x74\x2E\x31\x1A\x30\x18\x06\x03\x55\x04\x0B\x13\x11\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x6B\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x55\x7A\x6C\x65\x74\x69\x20\x28\x43\x6C\x61\x73\x73\x20\x42\x29\x20\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x30\x1E\x17\x0D\x39\x39\x30\x32\x32\x35\x31\x34\x31\x30\x32\x32\x5A\x17\x0D\x31\x39\x30\x32\x32\x30\x31\x34\x31\x30\x32\x32\x5A\x30\x81\x99\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x48\x61\x6C\x6F\x7A\x61\x74\x62\x69\x7A\x74\x6F\x6E\x73\x61\x67\x69\x20\x4B\x66\x74\x2E\x31\x1A\x30\x18\x06\x03\x55\x04\x0B\x13\x11\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x6B\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x55\x7A\x6C\x65\x74\x69\x20\x28\x43\x6C\x61\x73\x73\x20\x42\x29\x20\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xB1\xEA\x04\xEC\x20\xA0\x23\xC2\x8F\x38\x60\xCF\xC7\x46\xB3\xD5\x1B\xFE\xFB\xB9\x99\x9E\x04\xDC\x1C\x7F\x8C\x4A\x81\x98\xEE\xA4\xD4\xCA\x8A\x17\xB9\x22\x7F\x83\x0A\x75\x4C\x9B\xC0\x69\xD8\x64\x39\xA3\xED\x92\xA3\xFD\x5B\x5C\x74\x1A\xC0\x47\xCA\x3A\x69\x76\x9A\xBA\xE2\x44\x17\xFC\x4C\xA3\xD5\xFE\xB8\x97\x88\xAF\x88\x03\x89\x1F\xA4\xF2\x04\x3E\xC8\x07\x0B\xE6\xF9\xB3\x2F\x7A\x62\x14\x09\x46\x14\xCA\x64\xF5\x8B\x80\xB5\x62\xA8\xD8\x6B\xD6\x71\x93\x2D\xB3\xBF\x09\x54\x58\xED\x06\xEB\xA8\x7B\xDC\x43\xB1\xA1\x69\x02\x03\x01\x00\x01\xA3\x82\x02\x9F\x30\x82\x02\x9B\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x04\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x00\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x02\x60\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x0D\x04\x82\x02\x51\x16\x82\x02\x4D\x46\x49\x47\x59\x45\x4C\x45\x4D\x21\x20\x45\x7A\x65\x6E\x20\x74\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x41\x6C\x74\x61\x6C\x61\x6E\x6F\x73\x20\x53\x7A\x6F\x6C\x67\x61\x6C\x74\x61\x74\x61\x73\x69\x20\x46\x65\x6C\x74\x65\x74\x65\x6C\x65\x69\x62\x65\x6E\x20\x6C\x65\x69\x72\x74\x20\x65\x6C\x6A\x61\x72\x61\x73\x6F\x6B\x20\x61\x6C\x61\x70\x6A\x61\x6E\x20\x6B\x65\x73\x7A\x75\x6C\x74\x2E\x20\x41\x20\x68\x69\x74\x65\x6C\x65\x73\x69\x74\x65\x73\x20\x66\x6F\x6C\x79\x61\x6D\x61\x74\x61\x74\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x74\x65\x72\x6D\x65\x6B\x66\x65\x6C\x65\x6C\x6F\x73\x73\x65\x67\x2D\x62\x69\x7A\x74\x6F\x73\x69\x74\x61\x73\x61\x20\x76\x65\x64\x69\x2E\x20\x41\x20\x64\x69\x67\x69\x74\x61\x6C\x69\x73\x20\x61\x6C\x61\x69\x72\x61\x73\x20\x65\x6C\x66\x6F\x67\x61\x64\x61\x73\x61\x6E\x61\x6B\x20\x66\x65\x6C\x74\x65\x74\x65\x6C\x65\x20\x61\x7A\x20\x65\x6C\x6F\x69\x72\x74\x20\x65\x6C\x6C\x65\x6E\x6F\x72\x7A\x65\x73\x69\x20\x65\x6C\x6A\x61\x72\x61\x73\x20\x6D\x65\x67\x74\x65\x74\x65\x6C\x65\x2E\x20\x41\x7A\x20\x65\x6C\x6A\x61\x72\x61\x73\x20\x6C\x65\x69\x72\x61\x73\x61\x20\x6D\x65\x67\x74\x61\x6C\x61\x6C\x68\x61\x74\x6F\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x68\x6F\x6E\x6C\x61\x70\x6A\x61\x6E\x20\x61\x20\x68\x74\x74\x70\x73\x3A\x2F\x2F\x77\x77\x77\x2E\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2F\x64\x6F\x63\x73\x20\x63\x69\x6D\x65\x6E\x20\x76\x61\x67\x79\x20\x6B\x65\x72\x68\x65\x74\x6F\x20\x61\x7A\x20\x65\x6C\x6C\x65\x6E\x6F\x72\x7A\x65\x73\x40\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x20\x65\x2D\x6D\x61\x69\x6C\x20\x63\x69\x6D\x65\x6E\x2E\x20\x49\x4D\x50\x4F\x52\x54\x41\x4E\x54\x21\x20\x54\x68\x65\x20\x69\x73\x73\x75\x61\x6E\x63\x65\x20\x61\x6E\x64\x20\x74\x68\x65\x20\x75\x73\x65\x20\x6F\x66\x20\x74\x68\x69\x73\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x20\x73\x75\x62\x6A\x65\x63\x74\x20\x74\x6F\x20\x74\x68\x65\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x43\x50\x53\x20\x61\x76\x61\x69\x6C\x61\x62\x6C\x65\x20\x61\x74\x20\x68\x74\x74\x70\x73\x3A\x2F\x2F\x77\x77\x77\x2E\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2F\x64\x6F\x63\x73\x20\x6F\x72\x20\x62\x79\x20\x65\x2D\x6D\x61\x69\x6C\x20\x61\x74\x20\x63\x70\x73\x40\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x04\xDB\xAE\x8C\x17\xAF\xF8\x0E\x90\x31\x4E\xCD\x3E\x09\xC0\x6D\x3A\xB0\xF8\x33\x4C\x47\x4C\xE3\x75\x88\x10\x97\xAC\xB0\x38\x15\x91\xC6\x29\x96\xCC\x21\xC0\x6D\x3C\xA5\x74\xCF\xD8\x82\xA5\x39\xC3\x65\xE3\x42\x70\xBB\x22\x90\xE3\x7D\xDB\x35\x76\xE1\xA0\xB5\xDA\x9F\x70\x6E\x93\x1A\x30\x39\x1D\x30\xDB\x2E\xE3\x7C\xB2\x91\xB2\xD1\x37\x29\xFA\xB9\xD6\x17\x5C\x47\x4F\xE3\x1D\x38\xEB\x9F\xD5\x7B\x95\xA8\x28\x9E\x15\x4A\xD1\xD1\xD0\x2B\x00\x97\xA0\xE2\x92\x36\x2B\x63\xAC\x58\x01\x6B\x33\x29\x50\x86\x83\xF1\x01\x48", + ["CN=NetLock Expressz (Class C) Tanusitvanykiado,OU=Tanusitvanykiadok,O=NetLock Halozatbiztonsagi Kft.,L=Budapest,C=HU"] = "\x30\x82\x05\x4F\x30\x82\x04\xB8\xA0\x03\x02\x01\x02\x02\x01\x68\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x30\x81\x9B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x48\x61\x6C\x6F\x7A\x61\x74\x62\x69\x7A\x74\x6F\x6E\x73\x61\x67\x69\x20\x4B\x66\x74\x2E\x31\x1A\x30\x18\x06\x03\x55\x04\x0B\x13\x11\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x6B\x31\x34\x30\x32\x06\x03\x55\x04\x03\x13\x2B\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x45\x78\x70\x72\x65\x73\x73\x7A\x20\x28\x43\x6C\x61\x73\x73\x20\x43\x29\x20\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x30\x1E\x17\x0D\x39\x39\x30\x32\x32\x35\x31\x34\x30\x38\x31\x31\x5A\x17\x0D\x31\x39\x30\x32\x32\x30\x31\x34\x30\x38\x31\x31\x5A\x30\x81\x9B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x27\x30\x25\x06\x03\x55\x04\x0A\x13\x1E\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x48\x61\x6C\x6F\x7A\x61\x74\x62\x69\x7A\x74\x6F\x6E\x73\x61\x67\x69\x20\x4B\x66\x74\x2E\x31\x1A\x30\x18\x06\x03\x55\x04\x0B\x13\x11\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x6B\x31\x34\x30\x32\x06\x03\x55\x04\x03\x13\x2B\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x45\x78\x70\x72\x65\x73\x73\x7A\x20\x28\x43\x6C\x61\x73\x73\x20\x43\x29\x20\x54\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x6B\x69\x61\x64\x6F\x30\x81\x9F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x81\x8D\x00\x30\x81\x89\x02\x81\x81\x00\xEB\xEC\xB0\x6C\x61\x8A\x23\x25\xAF\x60\x20\xE3\xD9\x9F\xFC\x93\x0B\xDB\x5D\x8D\xB0\xA1\xB3\x40\x3A\x82\xCE\xFD\x75\xE0\x78\x32\x03\x86\x5A\x86\x95\x91\xED\x53\xFA\x9D\x40\xFC\xE6\xE8\xDD\xD9\x5B\x7A\x03\xBD\x5D\xF3\x3B\x0C\xC3\x51\x79\x9B\xAD\x55\xA0\xE9\xD0\x03\x10\xAF\x0A\xBA\x14\x42\xD9\x52\x26\x11\x22\xC7\xD2\x20\xCC\x82\xA4\x9A\xA9\xFE\xB8\x81\x76\x9D\x6A\xB7\xD2\x36\x75\x3E\xB1\x86\x09\xF6\x6E\x6D\x7E\x4E\xB7\x7A\xEC\xAE\x71\x84\xF6\x04\x33\x08\x25\x32\xEB\x74\xAC\x16\x44\xC6\xE4\x40\x93\x1D\x7F\xAD\x02\x03\x01\x00\x01\xA3\x82\x02\x9F\x30\x82\x02\x9B\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x04\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x00\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x82\x02\x60\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x0D\x04\x82\x02\x51\x16\x82\x02\x4D\x46\x49\x47\x59\x45\x4C\x45\x4D\x21\x20\x45\x7A\x65\x6E\x20\x74\x61\x6E\x75\x73\x69\x74\x76\x61\x6E\x79\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x41\x6C\x74\x61\x6C\x61\x6E\x6F\x73\x20\x53\x7A\x6F\x6C\x67\x61\x6C\x74\x61\x74\x61\x73\x69\x20\x46\x65\x6C\x74\x65\x74\x65\x6C\x65\x69\x62\x65\x6E\x20\x6C\x65\x69\x72\x74\x20\x65\x6C\x6A\x61\x72\x61\x73\x6F\x6B\x20\x61\x6C\x61\x70\x6A\x61\x6E\x20\x6B\x65\x73\x7A\x75\x6C\x74\x2E\x20\x41\x20\x68\x69\x74\x65\x6C\x65\x73\x69\x74\x65\x73\x20\x66\x6F\x6C\x79\x61\x6D\x61\x74\x61\x74\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x74\x65\x72\x6D\x65\x6B\x66\x65\x6C\x65\x6C\x6F\x73\x73\x65\x67\x2D\x62\x69\x7A\x74\x6F\x73\x69\x74\x61\x73\x61\x20\x76\x65\x64\x69\x2E\x20\x41\x20\x64\x69\x67\x69\x74\x61\x6C\x69\x73\x20\x61\x6C\x61\x69\x72\x61\x73\x20\x65\x6C\x66\x6F\x67\x61\x64\x61\x73\x61\x6E\x61\x6B\x20\x66\x65\x6C\x74\x65\x74\x65\x6C\x65\x20\x61\x7A\x20\x65\x6C\x6F\x69\x72\x74\x20\x65\x6C\x6C\x65\x6E\x6F\x72\x7A\x65\x73\x69\x20\x65\x6C\x6A\x61\x72\x61\x73\x20\x6D\x65\x67\x74\x65\x74\x65\x6C\x65\x2E\x20\x41\x7A\x20\x65\x6C\x6A\x61\x72\x61\x73\x20\x6C\x65\x69\x72\x61\x73\x61\x20\x6D\x65\x67\x74\x61\x6C\x61\x6C\x68\x61\x74\x6F\x20\x61\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x20\x49\x6E\x74\x65\x72\x6E\x65\x74\x20\x68\x6F\x6E\x6C\x61\x70\x6A\x61\x6E\x20\x61\x20\x68\x74\x74\x70\x73\x3A\x2F\x2F\x77\x77\x77\x2E\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2F\x64\x6F\x63\x73\x20\x63\x69\x6D\x65\x6E\x20\x76\x61\x67\x79\x20\x6B\x65\x72\x68\x65\x74\x6F\x20\x61\x7A\x20\x65\x6C\x6C\x65\x6E\x6F\x72\x7A\x65\x73\x40\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x20\x65\x2D\x6D\x61\x69\x6C\x20\x63\x69\x6D\x65\x6E\x2E\x20\x49\x4D\x50\x4F\x52\x54\x41\x4E\x54\x21\x20\x54\x68\x65\x20\x69\x73\x73\x75\x61\x6E\x63\x65\x20\x61\x6E\x64\x20\x74\x68\x65\x20\x75\x73\x65\x20\x6F\x66\x20\x74\x68\x69\x73\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x69\x73\x20\x73\x75\x62\x6A\x65\x63\x74\x20\x74\x6F\x20\x74\x68\x65\x20\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x43\x50\x53\x20\x61\x76\x61\x69\x6C\x61\x62\x6C\x65\x20\x61\x74\x20\x68\x74\x74\x70\x73\x3A\x2F\x2F\x77\x77\x77\x2E\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2F\x64\x6F\x63\x73\x20\x6F\x72\x20\x62\x79\x20\x65\x2D\x6D\x61\x69\x6C\x20\x61\x74\x20\x63\x70\x73\x40\x6E\x65\x74\x6C\x6F\x63\x6B\x2E\x6E\x65\x74\x2E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x04\x05\x00\x03\x81\x81\x00\x10\xAD\x7F\xD7\x0C\x32\x80\x0A\xD8\x86\xF1\x79\x98\xB5\xAD\xD4\xCD\xB3\x36\xC4\x96\x48\xC1\x5C\xCD\x9A\xD9\x05\x2E\x9F\xBE\x50\xEB\xF4\x26\x14\x10\x2D\xD4\x66\x17\xF8\x9E\xC1\x27\xFD\xF1\xED\xE4\x7B\x4B\xA0\x6C\xB5\xAB\x9A\x57\x70\xA6\xED\xA0\xA4\xED\x2E\xF5\xFD\xFC\xBD\xFE\x4D\x37\x08\x0C\xBC\xE3\x96\x83\x22\xF5\x49\x1B\x7F\x4B\x2B\xB4\x54\xC1\x80\x7C\x99\x4E\x1D\xD0\x8C\xEE\xD0\xAC\xE5\x92\xFA\x75\x56\xFE\x64\xA0\x13\x8F\xB8\xB8\x16\x9D\x61\x05\x67\x80\xC8\xD0\xD8\xA5\x07\x02\x34\x98\x04\x8D\x33\x04\xD4", + ["CN=XRamp Global Certification Authority,O=XRamp Security Services Inc,OU=www.xrampsecurity.com,C=US"] = "\x30\x82\x04\x30\x30\x82\x03\x18\xA0\x03\x02\x01\x02\x02\x10\x50\x94\x6C\xEC\x18\xEA\xD5\x9C\x4D\xD5\x97\xEF\x75\x8F\xA0\xAD\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1E\x30\x1C\x06\x03\x55\x04\x0B\x13\x15\x77\x77\x77\x2E\x78\x72\x61\x6D\x70\x73\x65\x63\x75\x72\x69\x74\x79\x2E\x63\x6F\x6D\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x58\x52\x61\x6D\x70\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x49\x6E\x63\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x58\x52\x61\x6D\x70\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x34\x31\x31\x30\x31\x31\x37\x31\x34\x30\x34\x5A\x17\x0D\x33\x35\x30\x31\x30\x31\x30\x35\x33\x37\x31\x39\x5A\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x1E\x30\x1C\x06\x03\x55\x04\x0B\x13\x15\x77\x77\x77\x2E\x78\x72\x61\x6D\x70\x73\x65\x63\x75\x72\x69\x74\x79\x2E\x63\x6F\x6D\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x58\x52\x61\x6D\x70\x20\x53\x65\x63\x75\x72\x69\x74\x79\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x49\x6E\x63\x31\x2D\x30\x2B\x06\x03\x55\x04\x03\x13\x24\x58\x52\x61\x6D\x70\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\x98\x24\x1E\xBD\x15\xB4\xBA\xDF\xC7\x8C\xA5\x27\xB6\x38\x0B\x69\xF3\xB6\x4E\xA8\x2C\x2E\x21\x1D\x5C\x44\xDF\x21\x5D\x7E\x23\x74\xFE\x5E\x7E\xB4\x4A\xB7\xA6\xAD\x1F\xAE\xE0\x06\x16\xE2\x9B\x5B\xD9\x67\x74\x6B\x5D\x80\x8F\x29\x9D\x86\x1B\xD9\x9C\x0D\x98\x6D\x76\x10\x28\x58\xE4\x65\xB0\x7F\x4A\x98\x79\x9F\xE0\xC3\x31\x7E\x80\x2B\xB5\x8C\xC0\x40\x3B\x11\x86\xD0\xCB\xA2\x86\x36\x60\xA4\xD5\x30\x82\x6D\xD9\x6E\xD0\x0F\x12\x04\x33\x97\x5F\x4F\x61\x5A\xF0\xE4\xF9\x91\xAB\xE7\x1D\x3B\xBC\xE8\xCF\xF4\x6B\x2D\x34\x7C\xE2\x48\x61\x1C\x8E\xF3\x61\x44\xCC\x6F\xA0\x4A\xA9\x94\xB0\x4D\xDA\xE7\xA9\x34\x7A\x72\x38\xA8\x41\xCC\x3C\x94\x11\x7D\xEB\xC8\xA6\x8C\xB7\x86\xCB\xCA\x33\x3B\xD9\x3D\x37\x8B\xFB\x7A\x3E\x86\x2C\xE7\x73\xD7\x0A\x57\xAC\x64\x9B\x19\xEB\xF4\x0F\x04\x08\x8A\xAC\x03\x17\x19\x64\xF4\x5A\x25\x22\x8D\x34\x2C\xB2\xF6\x68\x1D\x12\x6D\xD3\x8A\x1E\x14\xDA\xC4\x8F\xA6\xE2\x23\x85\xD5\x7A\x0D\xBD\x6A\xE0\xE9\xEC\xEC\x17\xBB\x42\x1B\x67\xAA\x25\xED\x45\x83\x21\xFC\xC1\xC9\x7C\xD5\x62\x3E\xFA\xF2\xC5\x2D\xD3\xFD\xD4\x65\x02\x03\x01\x00\x01\xA3\x81\x9F\x30\x81\x9C\x30\x13\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x14\x02\x04\x06\x1E\x04\x00\x43\x00\x41\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC6\x4F\xA2\x3D\x06\x63\x84\x09\x9C\xCE\x62\xE4\x04\xAC\x8D\x5C\xB5\xE9\xB6\x1B\x30\x36\x06\x03\x55\x1D\x1F\x04\x2F\x30\x2D\x30\x2B\xA0\x29\xA0\x27\x86\x25\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x78\x72\x61\x6D\x70\x73\x65\x63\x75\x72\x69\x74\x79\x2E\x63\x6F\x6D\x2F\x58\x47\x43\x41\x2E\x63\x72\x6C\x30\x10\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x91\x15\x39\x03\x01\x1B\x67\xFB\x4A\x1C\xF9\x0A\x60\x5B\xA1\xDA\x4D\x97\x62\xF9\x24\x53\x27\xD7\x82\x64\x4E\x90\x2E\xC3\x49\x1B\x2B\x9A\xDC\xFC\xA8\x78\x67\x35\xF1\x1D\xF0\x11\xBD\xB7\x48\xE3\x10\xF6\x0D\xDF\x3F\xD2\xC9\xB6\xAA\x55\xA4\x48\xBA\x02\xDB\xDE\x59\x2E\x15\x5B\x3B\x9D\x16\x7D\x47\xD7\x37\xEA\x5F\x4D\x76\x12\x36\xBB\x1F\xD7\xA1\x81\x04\x46\x20\xA3\x2C\x6D\xA9\x9E\x01\x7E\x3F\x29\xCE\x00\x93\xDF\xFD\xC9\x92\x73\x89\x89\x64\x9E\xE7\x2B\xE4\x1C\x91\x2C\xD2\xB9\xCE\x7D\xCE\x6F\x31\x99\xD3\xE6\xBE\xD2\x1E\x90\xF0\x09\x14\x79\x5C\x23\xAB\x4D\xD2\xDA\x21\x1F\x4D\x99\x79\x9D\xE1\xCF\x27\x9F\x10\x9B\x1C\x88\x0D\xB0\x8A\x64\x41\x31\xB8\x0E\x6C\x90\x24\xA4\x9B\x5C\x71\x8F\xBA\xBB\x7E\x1C\x1B\xDB\x6A\x80\x0F\x21\xBC\xE9\xDB\xA6\xB7\x40\xF4\xB2\x8B\xA9\xB1\xE4\xEF\x9A\x1A\xD0\x3D\x69\x99\xEE\xA8\x28\xA3\xE1\x3C\xB3\xF0\xB2\x11\x9C\xCF\x7C\x40\xE6\xDD\xE7\x43\x7D\xA2\xD8\x3A\xB5\xA9\x8D\xF2\x34\x99\xC4\xD4\x10\xE1\x06\xFD\x09\x84\x10\x3B\xEE\xC4\x4C\xF4\xEC\x27\x7C\x42\xC2\x74\x7C\x82\x8A\x09\xC9\xB4\x03\x25\xBC", + ["OU=Go Daddy Class 2 Certification Authority,O=The Go Daddy Group\, Inc.,C=US"] = "\x30\x82\x04\x00\x30\x82\x02\xE8\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1F\x06\x03\x55\x04\x0A\x13\x18\x54\x68\x65\x20\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x47\x72\x6F\x75\x70\x2C\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x0B\x13\x28\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x34\x30\x36\x32\x39\x31\x37\x30\x36\x32\x30\x5A\x17\x0D\x33\x34\x30\x36\x32\x39\x31\x37\x30\x36\x32\x30\x5A\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1F\x06\x03\x55\x04\x0A\x13\x18\x54\x68\x65\x20\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x47\x72\x6F\x75\x70\x2C\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x0B\x13\x28\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x82\x01\x20\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0D\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xDE\x9D\xD7\xEA\x57\x18\x49\xA1\x5B\xEB\xD7\x5F\x48\x86\xEA\xBE\xDD\xFF\xE4\xEF\x67\x1C\xF4\x65\x68\xB3\x57\x71\xA0\x5E\x77\xBB\xED\x9B\x49\xE9\x70\x80\x3D\x56\x18\x63\x08\x6F\xDA\xF2\xCC\xD0\x3F\x7F\x02\x54\x22\x54\x10\xD8\xB2\x81\xD4\xC0\x75\x3D\x4B\x7F\xC7\x77\xC3\x3E\x78\xAB\x1A\x03\xB5\x20\x6B\x2F\x6A\x2B\xB1\xC5\x88\x7E\xC4\xBB\x1E\xB0\xC1\xD8\x45\x27\x6F\xAA\x37\x58\xF7\x87\x26\xD7\xD8\x2D\xF6\xA9\x17\xB7\x1F\x72\x36\x4E\xA6\x17\x3F\x65\x98\x92\xDB\x2A\x6E\x5D\xA2\xFE\x88\xE0\x0B\xDE\x7F\xE5\x8D\x15\xE1\xEB\xCB\x3A\xD5\xE2\x12\xA2\x13\x2D\xD8\x8E\xAF\x5F\x12\x3D\xA0\x08\x05\x08\xB6\x5C\xA5\x65\x38\x04\x45\x99\x1E\xA3\x60\x60\x74\xC5\x41\xA5\x72\x62\x1B\x62\xC5\x1F\x6F\x5F\x1A\x42\xBE\x02\x51\x65\xA8\xAE\x23\x18\x6A\xFC\x78\x03\xA9\x4D\x7F\x80\xC3\xFA\xAB\x5A\xFC\xA1\x40\xA4\xCA\x19\x16\xFE\xB2\xC8\xEF\x5E\x73\x0D\xEE\x77\xBD\x9A\xF6\x79\x98\xBC\xB1\x07\x67\xA2\x15\x0D\xDD\xA0\x58\xC6\x44\x7B\x0A\x3E\x62\x28\x5F\xBA\x41\x07\x53\x58\xCF\x11\x7E\x38\x74\xC5\xF8\xFF\xB5\x69\x90\x8F\x84\x74\xEA\x97\x1B\xAF\x02\x01\x03\xA3\x81\xC0\x30\x81\xBD\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xD2\xC4\xB0\xD2\x91\xD4\x4C\x11\x71\xB3\x61\xCB\x3D\xA1\xFE\xDD\xA8\x6A\xD4\xE3\x30\x81\x8D\x06\x03\x55\x1D\x23\x04\x81\x85\x30\x81\x82\x80\x14\xD2\xC4\xB0\xD2\x91\xD4\x4C\x11\x71\xB3\x61\xCB\x3D\xA1\xFE\xDD\xA8\x6A\xD4\xE3\xA1\x67\xA4\x65\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1F\x06\x03\x55\x04\x0A\x13\x18\x54\x68\x65\x20\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x47\x72\x6F\x75\x70\x2C\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x0B\x13\x28\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x82\x01\x00\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x32\x4B\xF3\xB2\xCA\x3E\x91\xFC\x12\xC6\xA1\x07\x8C\x8E\x77\xA0\x33\x06\x14\x5C\x90\x1E\x18\xF7\x08\xA6\x3D\x0A\x19\xF9\x87\x80\x11\x6E\x69\xE4\x96\x17\x30\xFF\x34\x91\x63\x72\x38\xEE\xCC\x1C\x01\xA3\x1D\x94\x28\xA4\x31\xF6\x7A\xC4\x54\xD7\xF6\xE5\x31\x58\x03\xA2\xCC\xCE\x62\xDB\x94\x45\x73\xB5\xBF\x45\xC9\x24\xB5\xD5\x82\x02\xAD\x23\x79\x69\x8D\xB8\xB6\x4D\xCE\xCF\x4C\xCA\x33\x23\xE8\x1C\x88\xAA\x9D\x8B\x41\x6E\x16\xC9\x20\xE5\x89\x9E\xCD\x3B\xDA\x70\xF7\x7E\x99\x26\x20\x14\x54\x25\xAB\x6E\x73\x85\xE6\x9B\x21\x9D\x0A\x6C\x82\x0E\xA8\xF8\xC2\x0C\xFA\x10\x1E\x6C\x96\xEF\x87\x0D\xC4\x0F\x61\x8B\xAD\xEE\x83\x2B\x95\xF8\x8E\x92\x84\x72\x39\xEB\x20\xEA\x83\xED\x83\xCD\x97\x6E\x08\xBC\xEB\x4E\x26\xB6\x73\x2B\xE4\xD3\xF6\x4C\xFE\x26\x71\xE2\x61\x11\x74\x4A\xFF\x57\x1A\x87\x0F\x75\x48\x2E\xCF\x51\x69\x17\xA0\x02\x12\x61\x95\xD5\xD1\x40\xB2\x10\x4C\xEE\xC4\xAC\x10\x43\xA6\xA5\x9E\x0A\xD5\x95\x62\x9A\x0D\xCF\x88\x82\xC5\x32\x0C\xE4\x2B\x9F\x45\xE6\x0D\x9F\x28\x9C\xB1\xB9\x2A\x5A\x57\xAD\x37\x0F\xAF\x1D\x7F\xDB\xBD\x9F", + ["OU=Starfield Class 2 Certification Authority,O=Starfield Technologies\, Inc.,C=US"] = "\x30\x82\x04\x0F\x30\x82\x02\xF7\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x68\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x32\x30\x30\x06\x03\x55\x04\x0B\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x34\x30\x36\x32\x39\x31\x37\x33\x39\x31\x36\x5A\x17\x0D\x33\x34\x30\x36\x32\x39\x31\x37\x33\x39\x31\x36\x5A\x30\x68\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x32\x30\x30\x06\x03\x55\x04\x0B\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x82\x01\x20\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x01\x0D\x00\x30\x82\x01\x08\x02\x82\x01\x01\x00\xB7\x32\xC8\xFE\xE9\x71\xA6\x04\x85\xAD\x0C\x11\x64\xDF\xCE\x4D\xEF\xC8\x03\x18\x87\x3F\xA1\xAB\xFB\x3C\xA6\x9F\xF0\xC3\xA1\xDA\xD4\xD8\x6E\x2B\x53\x90\xFB\x24\xA4\x3E\x84\xF0\x9E\xE8\x5F\xEC\xE5\x27\x44\xF5\x28\xA6\x3F\x7B\xDE\xE0\x2A\xF0\xC8\xAF\x53\x2F\x9E\xCA\x05\x01\x93\x1E\x8F\x66\x1C\x39\xA7\x4D\xFA\x5A\xB6\x73\x04\x25\x66\xEB\x77\x7F\xE7\x59\xC6\x4A\x99\x25\x14\x54\xEB\x26\xC7\xF3\x7F\x19\xD5\x30\x70\x8F\xAF\xB0\x46\x2A\xFF\xAD\xEB\x29\xED\xD7\x9F\xAA\x04\x87\xA3\xD4\xF9\x89\xA5\x34\x5F\xDB\x43\x91\x82\x36\xD9\x66\x3C\xB1\xB8\xB9\x82\xFD\x9C\x3A\x3E\x10\xC8\x3B\xEF\x06\x65\x66\x7A\x9B\x19\x18\x3D\xFF\x71\x51\x3C\x30\x2E\x5F\xBE\x3D\x77\x73\xB2\x5D\x06\x6C\xC3\x23\x56\x9A\x2B\x85\x26\x92\x1C\xA7\x02\xB3\xE4\x3F\x0D\xAF\x08\x79\x82\xB8\x36\x3D\xEA\x9C\xD3\x35\xB3\xBC\x69\xCA\xF5\xCC\x9D\xE8\xFD\x64\x8D\x17\x80\x33\x6E\x5E\x4A\x5D\x99\xC9\x1E\x87\xB4\x9D\x1A\xC0\xD5\x6E\x13\x35\x23\x5E\xDF\x9B\x5F\x3D\xEF\xD6\xF7\x76\xC2\xEA\x3E\xBB\x78\x0D\x1C\x42\x67\x6B\x04\xD8\xF8\xD6\xDA\x6F\x8B\xF2\x44\xA0\x01\xAB\x02\x01\x03\xA3\x81\xC5\x30\x81\xC2\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xBF\x5F\xB7\xD1\xCE\xDD\x1F\x86\xF4\x5B\x55\xAC\xDC\xD7\x10\xC2\x0E\xA9\x88\xE7\x30\x81\x92\x06\x03\x55\x1D\x23\x04\x81\x8A\x30\x81\x87\x80\x14\xBF\x5F\xB7\xD1\xCE\xDD\x1F\x86\xF4\x5B\x55\xAC\xDC\xD7\x10\xC2\x0E\xA9\x88\xE7\xA1\x6C\xA4\x6A\x30\x68\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x32\x30\x30\x06\x03\x55\x04\x0B\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x82\x01\x00\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x05\x9D\x3F\x88\x9D\xD1\xC9\x1A\x55\xA1\xAC\x69\xF3\xF3\x59\xDA\x9B\x01\x87\x1A\x4F\x57\xA9\xA1\x79\x09\x2A\xDB\xF7\x2F\xB2\x1E\xCC\xC7\x5E\x6A\xD8\x83\x87\xA1\x97\xEF\x49\x35\x3E\x77\x06\x41\x58\x62\xBF\x8E\x58\xB8\x0A\x67\x3F\xEC\xB3\xDD\x21\x66\x1F\xC9\x54\xFA\x72\xCC\x3D\x4C\x40\xD8\x81\xAF\x77\x9E\x83\x7A\xBB\xA2\xC7\xF5\x34\x17\x8E\xD9\x11\x40\xF4\xFC\x2C\x2A\x4D\x15\x7F\xA7\x62\x5D\x2E\x25\xD3\x00\x0B\x20\x1A\x1D\x68\xF9\x17\xB8\xF4\xBD\x8B\xED\x28\x59\xDD\x4D\x16\x8B\x17\x83\xC8\xB2\x65\xC7\x2D\x7A\xA5\xAA\xBC\x53\x86\x6D\xDD\x57\xA4\xCA\xF8\x20\x41\x0B\x68\xF0\xF4\xFB\x74\xBE\x56\x5D\x7A\x79\xF5\xF9\x1D\x85\xE3\x2D\x95\xBE\xF5\x71\x90\x43\xCC\x8D\x1F\x9A\x00\x0A\x87\x29\xE9\x55\x22\x58\x00\x23\xEA\xE3\x12\x43\x29\x5B\x47\x08\xDD\x8C\x41\x6A\x65\x06\xA8\xE5\x21\xAA\x41\xB4\x95\x21\x95\xB9\x7D\xD1\x34\xAB\x13\xD6\xAD\xBC\xDC\xE2\x3D\x39\xCD\xBD\x3E\x75\x70\xA1\x18\x59\x03\xC9\x22\xB4\x8F\x9C\xD5\x5E\x2A\xD7\xA5\xB6\xD4\x0A\x6D\xF8\xB7\x40\x11\x46\x9A\x1F\x79\x0E\x62\xBF\x0F\x97\xEC\xE0\x2F\x1F\x17\x94", + ["CN=StartCom Certification Authority,OU=Secure Digital Certificate Signing,O=StartCom Ltd.,C=IL"] = "\x30\x82\x07\xC9\x30\x82\x05\xB1\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4C\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x4C\x74\x64\x2E\x31\x2B\x30\x29\x06\x03\x55\x04\x0B\x13\x22\x53\x65\x63\x75\x72\x65\x20\x44\x69\x67\x69\x74\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x69\x67\x6E\x69\x6E\x67\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x36\x30\x39\x31\x37\x31\x39\x34\x36\x33\x36\x5A\x17\x0D\x33\x36\x30\x39\x31\x37\x31\x39\x34\x36\x33\x36\x5A\x30\x7D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4C\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x4C\x74\x64\x2E\x31\x2B\x30\x29\x06\x03\x55\x04\x0B\x13\x22\x53\x65\x63\x75\x72\x65\x20\x44\x69\x67\x69\x74\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x69\x67\x6E\x69\x6E\x67\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC1\x88\xDB\x09\xBC\x6C\x46\x7C\x78\x9F\x95\x7B\xB5\x33\x90\xF2\x72\x62\xD6\xC1\x36\x20\x22\x24\x5E\xCE\xE9\x77\xF2\x43\x0A\xA2\x06\x64\xA4\xCC\x8E\x36\xF8\x38\xE6\x23\xF0\x6E\x6D\xB1\x3C\xDD\x72\xA3\x85\x1C\xA1\xD3\x3D\xB4\x33\x2B\xD3\x2F\xAF\xFE\xEA\xB0\x41\x59\x67\xB6\xC4\x06\x7D\x0A\x9E\x74\x85\xD6\x79\x4C\x80\x37\x7A\xDF\x39\x05\x52\x59\xF7\xF4\x1B\x46\x43\xA4\xD2\x85\x85\xD2\xC3\x71\xF3\x75\x62\x34\xBA\x2C\x8A\x7F\x1E\x8F\xEE\xED\x34\xD0\x11\xC7\x96\xCD\x52\x3D\xBA\x33\xD6\xDD\x4D\xDE\x0B\x3B\x4A\x4B\x9F\xC2\x26\x2F\xFA\xB5\x16\x1C\x72\x35\x77\xCA\x3C\x5D\xE6\xCA\xE1\x26\x8B\x1A\x36\x76\x5C\x01\xDB\x74\x14\x25\xFE\xED\xB5\xA0\x88\x0F\xDD\x78\xCA\x2D\x1F\x07\x97\x30\x01\x2D\x72\x79\xFA\x46\xD6\x13\x2A\xA8\xB9\xA6\xAB\x83\x49\x1D\xE5\xF2\xEF\xDD\xE4\x01\x8E\x18\x0A\x8F\x63\x53\x16\x85\x62\xA9\x0E\x19\x3A\xCC\xB5\x66\xA6\xC2\x6B\x74\x07\xE4\x2B\xE1\x76\x3E\xB4\x6D\xD8\xF6\x44\xE1\x73\x62\x1F\x3B\xC4\xBE\xA0\x53\x56\x25\x6C\x51\x09\xF7\xAA\xAB\xCA\xBF\x76\xFD\x6D\x9B\xF3\x9D\xDB\xBF\x3D\x66\xBC\x0C\x56\xAA\xAF\x98\x48\x95\x3A\x4B\xDF\xA7\x58\x50\xD9\x38\x75\xA9\x5B\xEA\x43\x0C\x02\xFF\x99\xEB\xE8\x6C\x4D\x70\x5B\x29\x65\x9C\xDD\xAA\x5D\xCC\xAF\x01\x31\xEC\x0C\xEB\xD2\x8D\xE8\xEA\x9C\x7B\xE6\x6E\xF7\x27\x66\x0C\x1A\x48\xD7\x6E\x42\xE3\x3F\xDE\x21\x3E\x7B\xE1\x0D\x70\xFB\x63\xAA\xA8\x6C\x1A\x54\xB4\x5C\x25\x7A\xC9\xA2\xC9\x8B\x16\xA6\xBB\x2C\x7E\x17\x5E\x05\x4D\x58\x6E\x12\x1D\x01\xEE\x12\x10\x0D\xC6\x32\x7F\x18\xFF\xFC\xF4\xFA\xCD\x6E\x91\xE8\x36\x49\xBE\x1A\x48\x69\x8B\xC2\x96\x4D\x1A\x12\xB2\x69\x17\xC1\x0A\x90\xD6\xFA\x79\x22\x48\xBF\xBA\x7B\x69\xF8\x70\xC7\xFA\x7A\x37\xD8\xD8\x0D\xD2\x76\x4F\x57\xFF\x90\xB7\xE3\x91\xD2\xDD\xEF\xC2\x60\xB7\x67\x3A\xDD\xFE\xAA\x9C\xF0\xD4\x8B\x7F\x72\x22\xCE\xC6\x9F\x97\xB6\xF8\xAF\x8A\xA0\x10\xA8\xD9\xFB\x18\xC6\xB6\xB5\x5C\x52\x3C\x89\xB6\x19\x2A\x73\x01\x0A\x0F\x03\xB3\x12\x60\xF2\x7A\x2F\x81\xDB\xA3\x6E\xFF\x26\x30\x97\xF5\x8B\xDD\x89\x57\xB6\xAD\x3D\xB3\xAF\x2B\xC5\xB7\x76\x02\xF0\xA5\xD6\x2B\x9A\x86\x14\x2A\x72\xF6\xE3\x33\x8C\x5D\x09\x4B\x13\xDF\xBB\x8C\x74\x13\x52\x4B\x02\x03\x01\x00\x01\xA3\x82\x02\x52\x30\x82\x02\x4E\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\xAE\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x4E\x0B\xEF\x1A\xA4\x40\x5B\xA5\x17\x69\x87\x30\xCA\x34\x68\x43\xD0\x41\xAE\xF2\x30\x64\x06\x03\x55\x1D\x1F\x04\x5D\x30\x5B\x30\x2C\xA0\x2A\xA0\x28\x86\x26\x68\x74\x74\x70\x3A\x2F\x2F\x63\x65\x72\x74\x2E\x73\x74\x61\x72\x74\x63\x6F\x6D\x2E\x6F\x72\x67\x2F\x73\x66\x73\x63\x61\x2D\x63\x72\x6C\x2E\x63\x72\x6C\x30\x2B\xA0\x29\xA0\x27\x86\x25\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x73\x74\x61\x72\x74\x63\x6F\x6D\x2E\x6F\x72\x67\x2F\x73\x66\x73\x63\x61\x2D\x63\x72\x6C\x2E\x63\x72\x6C\x30\x82\x01\x5D\x06\x03\x55\x1D\x20\x04\x82\x01\x54\x30\x82\x01\x50\x30\x82\x01\x4C\x06\x0B\x2B\x06\x01\x04\x01\x81\xB5\x37\x01\x01\x01\x30\x82\x01\x3B\x30\x2F\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x63\x65\x72\x74\x2E\x73\x74\x61\x72\x74\x63\x6F\x6D\x2E\x6F\x72\x67\x2F\x70\x6F\x6C\x69\x63\x79\x2E\x70\x64\x66\x30\x35\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x29\x68\x74\x74\x70\x3A\x2F\x2F\x63\x65\x72\x74\x2E\x73\x74\x61\x72\x74\x63\x6F\x6D\x2E\x6F\x72\x67\x2F\x69\x6E\x74\x65\x72\x6D\x65\x64\x69\x61\x74\x65\x2E\x70\x64\x66\x30\x81\xD0\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x81\xC3\x30\x27\x16\x20\x53\x74\x61\x72\x74\x20\x43\x6F\x6D\x6D\x65\x72\x63\x69\x61\x6C\x20\x28\x53\x74\x61\x72\x74\x43\x6F\x6D\x29\x20\x4C\x74\x64\x2E\x30\x03\x02\x01\x01\x1A\x81\x97\x4C\x69\x6D\x69\x74\x65\x64\x20\x4C\x69\x61\x62\x69\x6C\x69\x74\x79\x2C\x20\x72\x65\x61\x64\x20\x74\x68\x65\x20\x73\x65\x63\x74\x69\x6F\x6E\x20\x2A\x4C\x65\x67\x61\x6C\x20\x4C\x69\x6D\x69\x74\x61\x74\x69\x6F\x6E\x73\x2A\x20\x6F\x66\x20\x74\x68\x65\x20\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x50\x6F\x6C\x69\x63\x79\x20\x61\x76\x61\x69\x6C\x61\x62\x6C\x65\x20\x61\x74\x20\x68\x74\x74\x70\x3A\x2F\x2F\x63\x65\x72\x74\x2E\x73\x74\x61\x72\x74\x63\x6F\x6D\x2E\x6F\x72\x67\x2F\x70\x6F\x6C\x69\x63\x79\x2E\x70\x64\x66\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x38\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x0D\x04\x2B\x16\x29\x53\x74\x61\x72\x74\x43\x6F\x6D\x20\x46\x72\x65\x65\x20\x53\x53\x4C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x16\x6C\x99\xF4\x66\x0C\x34\xF5\xD0\x85\x5E\x7D\x0A\xEC\xDA\x10\x4E\x38\x1C\x5E\xDF\xA6\x25\x05\x4B\x91\x32\xC1\xE8\x3B\xF1\x3D\xDD\x44\x09\x5B\x07\x49\x8A\x29\xCB\x66\x02\xB7\xB1\x9A\xF7\x25\x98\x09\x3C\x8E\x1B\xE1\xDD\x36\x87\x2B\x4B\xBB\x68\xD3\x39\x66\x3D\xA0\x26\xC7\xF2\x39\x91\x1D\x51\xAB\x82\x7B\x7E\xD5\xCE\x5A\xE4\xE2\x03\x57\x70\x69\x97\x08\xF9\x5E\x58\xA6\x0A\xDF\x8C\x06\x9A\x45\x16\x16\x38\x0A\x5E\x57\xF6\x62\xC7\x7A\x02\x05\xE6\xBC\x1E\xB5\xF2\x9E\xF4\xA9\x29\x83\xF8\xB2\x14\xE3\x6E\x28\x87\x44\xC3\x90\x1A\xDE\x38\xA9\x3C\xAC\x43\x4D\x64\x45\xCE\xDD\x28\xA9\x5C\xF2\x73\x7B\x04\xF8\x17\xE8\xAB\xB1\xF3\x2E\x5C\x64\x6E\x73\x31\x3A\x12\xB8\xBC\xB3\x11\xE4\x7D\x8F\x81\x51\x9A\x3B\x8D\x89\xF4\x4D\x93\x66\x7B\x3C\x03\xED\xD3\x9A\x1D\x9A\xF3\x65\x50\xF5\xA0\xD0\x75\x9F\x2F\xAF\xF0\xEA\x82\x43\x98\xF8\x69\x9C\x89\x79\xC4\x43\x8E\x46\x72\xE3\x64\x36\x12\xAF\xF7\x25\x1E\x38\x89\x90\x77\x7E\xC3\x6B\x6A\xB9\xC3\xCB\x44\x4B\xAC\x78\x90\x8B\xE7\xC7\x2C\x1E\x4B\x11\x44\xC8\x34\x52\x27\xCD\x0A\x5D\x9F\x85\xC1\x89\xD5\x1A\x78\xF2\x95\x10\x53\x32\xDD\x80\x84\x66\x75\xD9\xB5\x68\x28\xFB\x61\x2E\xBE\x84\xA8\x38\xC0\x99\x12\x86\xA5\x1E\x67\x64\xAD\x06\x2E\x2F\xA9\x70\x85\xC7\x96\x0F\x7C\x89\x65\xF5\x8E\x43\x54\x0E\xAB\xDD\xA5\x80\x39\x94\x60\xC0\x34\xC9\x96\x70\x2C\xA3\x12\xF5\x1F\x48\x7B\xBD\x1C\x7E\x6B\xB7\x9D\x90\xF4\x22\x3B\xAE\xF8\xFC\x2A\xCA\xFA\x82\x52\xA0\xEF\xAF\x4B\x55\x93\xEB\xC1\xB5\xF0\x22\x8B\xAC\x34\x4E\x26\x22\x04\xA1\x87\x2C\x75\x4A\xB7\xE5\x7D\x13\xD7\xB8\x0C\x64\xC0\x36\xD2\xC9\x2F\x86\x12\x8C\x23\x09\xC1\x1B\x82\x3B\x73\x49\xA3\x6A\x57\x87\x94\xE5\xD6\x78\xC5\x99\x43\x63\xE3\x4D\xE0\x77\x2D\xE1\x65\x99\x72\x69\x04\x1A\x47\x09\xE6\x0F\x01\x56\x24\xFB\x1F\xBF\x0E\x79\xA9\x58\x2E\xB9\xC4\x09\x01\x7E\x95\xBA\x6D\x00\x06\x3E\xB2\xEA\x4A\x10\x39\xD8\xD0\x2B\xF5\xBF\xEC\x75\xBF\x97\x02\xC5\x09\x1B\x08\xDC\x55\x37\xE2\x81\xFB\x37\x84\x43\x62\x20\xCA\xE7\x56\x4B\x65\xEA\xFE\x6C\xC1\x24\x93\x24\xA1\x34\xEB\x05\xFF\x9A\x22\xAE\x9B\x7D\x3F\xF1\x65\x51\x0A\xA6\x30\x6A\xB3\xF4\x88\x1C\x80\x0D\xFC\x72\x8A\xE8\x83\x5E", + ["O=Government Root Certification Authority,C=TW"] = "\x30\x82\x05\x72\x30\x82\x03\x5A\xA0\x03\x02\x01\x02\x02\x10\x1F\x9D\x59\x5A\xD7\x2F\xC2\x06\x44\xA5\x80\x08\x69\xE3\x5E\xF6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x30\x30\x2E\x06\x03\x55\x04\x0A\x0C\x27\x47\x6F\x76\x65\x72\x6E\x6D\x65\x6E\x74\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x32\x31\x32\x30\x35\x31\x33\x32\x33\x33\x33\x5A\x17\x0D\x33\x32\x31\x32\x30\x35\x31\x33\x32\x33\x33\x33\x5A\x30\x3F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x30\x30\x2E\x06\x03\x55\x04\x0A\x0C\x27\x47\x6F\x76\x65\x72\x6E\x6D\x65\x6E\x74\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\x9A\x25\xB8\xEC\xCC\xA2\x75\xA8\x7B\xF7\xCE\x5B\x59\x8A\xC9\xD1\x86\x12\x08\x54\xEC\x9C\xF2\xE7\x46\xF6\x88\xF3\x7C\xE9\xA5\xDF\x4C\x47\x36\xA4\x1B\x01\x1C\x7F\x1E\x57\x8A\x8D\xC3\xC5\xD1\x21\xE3\xDA\x24\x3F\x48\x2B\xFB\x9F\x2E\xA1\x94\xE7\x2C\x1C\x93\xD1\xBF\x1B\x01\x87\x53\x99\xCE\xA7\xF5\x0A\x21\x76\x77\xFF\xA9\xB7\xC6\x73\x94\x4F\x46\xF7\x10\x49\x37\xFA\xA8\x59\x49\x5D\x6A\x81\x07\x56\xF2\x8A\xF9\x06\xD0\xF7\x70\x22\x4D\xB4\xB7\x41\xB9\x32\xB8\xB1\xF0\xB1\xC3\x9C\x3F\x70\xFD\x53\xDD\x81\xAA\xD8\x63\x78\xF6\xD8\x53\x6E\xA1\xAC\x6A\x84\x24\x72\x54\x86\xC6\xD2\xB2\xCA\x1C\x0E\x79\x81\xD6\xB5\x70\x62\x08\x01\x2E\x4E\x4F\x0E\xD5\x11\xAF\xA9\xAF\xE5\x9A\xBF\xDC\xCC\x87\x6D\x26\xE4\xC9\x57\xA2\xFB\x96\xF9\xCC\xE1\x3F\x53\x8C\x6C\x4C\x7E\x9B\x53\x08\x0B\x6C\x17\xFB\x67\xC8\xC2\xAD\xB1\xCD\x80\xB4\x97\xDC\x76\x01\x16\x15\xE9\x6A\xD7\xA4\xE1\x78\x47\xCE\x86\xD5\xFB\x31\xF3\xFA\x31\xBE\x34\xAA\x28\xFB\x70\x4C\x1D\x49\xC7\xAF\x2C\x9D\x6D\x66\xA6\xB6\x8D\x64\x7E\xB5\x20\x6A\x9D\x3B\x81\xB6\x8F\x40\x00\x67\x4B\x89\x86\xB8\xCC\x65\xFE\x15\x53\xE9\x04\xC1\xD6\x5F\x1D\x44\xD7\x0A\x2F\x27\x9A\x46\x7D\xA1\x0D\x75\xAD\x54\x86\x15\xDC\x49\x3B\xF1\x96\xCE\x0F\x9B\xA0\xEC\xA3\x7A\x5D\xBE\xD5\x2A\x75\x42\xE5\x7B\xDE\xA5\xB6\xAA\xAF\x28\xAC\xAC\x90\xAC\x38\xB7\xD5\x68\x35\x26\x7A\xDC\xF7\x3B\xF3\xFD\x45\x9B\xD1\xBB\x43\x78\x6E\x6F\xF1\x42\x54\x6A\x98\xF0\x0D\xAD\x97\xE9\x52\x5E\xE9\xD5\x6A\x72\xDE\x6A\xF7\x1B\x60\x14\xF4\xA5\xE4\xB6\x71\x67\xAA\x1F\xEA\xE2\x4D\xC1\x42\x40\xFE\x67\x46\x17\x38\x2F\x47\x3F\x71\x9C\xAE\xE5\x21\xCA\x61\x2D\x6D\x07\xA8\x84\x7C\x2D\xEE\x51\x25\xF1\x63\x90\x9E\xFD\xE1\x57\x88\x6B\xEF\x8A\x23\x6D\xB1\xE6\xBD\x3F\xAD\xD1\x3D\x96\x0B\x85\x8D\xCD\x6B\x27\xBB\xB7\x05\x9B\xEC\xBB\x91\xA9\x0A\x07\x12\x02\x97\x4E\x20\x90\xF0\xFF\x0D\x1E\xE2\x41\x3B\xD3\x40\x3A\xE7\x8D\x5D\xDA\x66\xE4\x02\xB0\x07\x52\x98\x5C\x0E\x8E\x33\x9C\xC2\xA6\x95\xFB\x55\x19\x6E\x4C\x8E\xAE\x4B\x0F\xBD\xC1\x38\x4D\x5E\x8F\x84\x1D\x66\xCD\xC5\x60\x96\xB4\x52\x5A\x05\x89\x8E\x95\x7A\x98\xC1\x91\x3C\x95\x23\xB2\x0E\xF4\x79\xB4\xC9\x7C\xC1\x4A\x21\x02\x03\x01\x00\x01\xA3\x6A\x30\x68\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xCC\xCC\xEF\xCC\x29\x60\xA4\x3B\xB1\x92\xB6\x3C\xFA\x32\x62\x8F\xAC\x25\x15\x3B\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x39\x06\x04\x67\x2A\x07\x00\x04\x31\x30\x2F\x30\x2D\x02\x01\x00\x30\x09\x06\x05\x2B\x0E\x03\x02\x1A\x05\x00\x30\x07\x06\x05\x67\x2A\x03\x00\x00\x04\x14\x03\x9B\xF0\x22\x13\xFF\x95\x28\x36\xD3\xDC\x9E\xC0\x32\xFB\x31\x3A\x8A\x51\x65\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x40\x80\x4A\xFA\x26\xC9\xCE\x5E\x30\xDD\x4F\x86\x74\x76\x58\xF5\xAE\xB3\x83\x33\x78\xA4\x7A\x74\x17\x19\x4E\xE9\x52\xB5\xB9\xE0\x0A\x74\x62\xAA\x68\xCA\x78\xA0\x4C\x9A\x8E\x2C\x23\x2E\xD5\x6A\x12\x24\xBF\xD4\x68\xD3\x8A\xD0\xD8\x9C\x9F\xB4\x1F\x0C\xDE\x38\x7E\x57\x38\xFC\x8D\xE2\x4F\x5E\x0C\x9F\xAB\x3B\xD2\xFF\x75\x97\xCB\xA4\xE3\x67\x08\xFF\xE5\xC0\x16\xB5\x48\x01\x7D\xE9\xF9\x0A\xFF\x1B\xE5\x6A\x69\xBF\x78\x21\xA8\xC2\xA7\x23\xA9\x86\xAB\x76\x56\xE8\x0E\x0C\xF6\x13\xDD\x2A\x66\x8A\x64\x49\x3D\x1A\x18\x87\x90\x04\x9F\x42\x52\xB7\x4F\xCB\xFE\x47\x41\x76\x35\xEF\xFF\x00\x76\x36\x45\x32\x9B\xC6\x46\x85\x5D\xE2\x24\xB0\x1E\xE3\x48\x96\x98\x57\x47\x94\x55\x7A\x0F\x41\xB1\x44\x24\xF3\xC1\xFE\x1A\x6B\xBF\x88\xFD\xC1\xA6\xDA\x93\x60\x5E\x81\x4A\x99\x20\x9C\x48\x66\x19\xB5\x00\x79\x54\x0F\xB8\x2C\x2F\x4B\xBC\xA9\x5D\x5B\x60\x7F\x8C\x87\xA5\xE0\x52\x63\x2A\xBE\xD8\x3B\x85\x40\x15\xFE\x1E\xB6\x65\x3F\xC5\x4B\xDA\x7E\xB5\x7A\x35\x29\xA3\x2E\x7A\x98\x60\x22\xA3\xF4\x7D\x27\x4E\x2D\xEA\xB4\x74\x3C\xE9\x0F\xA4\x33\x0F\x10\x11\xBC\x13\x01\xD6\xE5\x0E\xD3\xBF\xB5\x12\xA2\xE1\x45\x23\xC0\xCC\x08\x6E\x61\xB7\x89\xAB\x83\xE3\x24\x1E\xE6\x5D\x07\xE7\x1F\x20\x3E\xCF\x67\xC8\xE7\xAC\x30\x6D\x27\x4B\x68\x6E\x4B\x2A\x5C\x02\x08\x34\xDB\xF8\x76\xE4\x67\xA3\x26\x9C\x3F\xA2\x32\xC2\x4A\xC5\x81\x18\x31\x10\x56\xAA\x84\xEF\x2D\x0A\xFF\xB8\x1F\x77\xD2\xBF\xA5\x58\xA0\x62\xE4\xD7\x4B\x91\x75\x8D\x89\x80\x98\x7E\x6D\xCB\x53\x4E\x5E\xAF\xF6\xB2\x97\x85\x97\xB9\xDA\x55\x06\xB9\x24\xEE\xD7\xC6\x38\x1E\x63\x1B\x12\x3B\x95\xE1\x58\xAC\xF2\xDF\x84\xD5\x5F\x99\x2F\x0D\x55\x5B\xE6\x38\xDB\x2E\x3F\x72\xE9\x48\x85\xCB\xBB\x29\x13\x8F\x1E\x38\x55\xB9\xF3\xB2\xC4\x30\x99\x23\x4E\x5D\xF2\x48\xA1\x12\x0C\xDC\x12\x90\x09\x90\x54\x91\x03\x3C\x47\xE5\xD5\xC9\x65\xE0\xB7\x4B\x7D\xEC\x47\xD3\xB3\x0B\x3E\xAD\x9E\xD0\x74\x00\x0E\xEB\xBD\x51\xAD\xC0\xDE\x2C\xC0\xC3\x6A\xFE\xEF\xDC\x0B\xA7\xFA\x46\xDF\x60\xDB\x9C\xA6\x59\x50\x75\x23\x69\x73\x93\xB2\xF9\xFC\x02\xD3\x47\xE6\x71\xCE\x10\x02\xEE\x27\x8C\x84\xFF\xAC\x45\x0D\x13\x5C\x83\x32\xE0\x25\xA5\x86\x2C\x7C\xF4\x12", + ["emailAddress=ca@firmaprofesional.com,CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,L=C/ Muntaner 244 Barcelona,C=ES"] = "\x30\x82\x04\x57\x30\x82\x03\x3F\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x9D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x22\x30\x20\x06\x03\x55\x04\x07\x13\x19\x43\x2F\x20\x4D\x75\x6E\x74\x61\x6E\x65\x72\x20\x32\x34\x34\x20\x42\x61\x72\x63\x65\x6C\x6F\x6E\x61\x31\x42\x30\x40\x06\x03\x55\x04\x03\x13\x39\x41\x75\x74\x6F\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x46\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x20\x43\x49\x46\x20\x41\x36\x32\x36\x33\x34\x30\x36\x38\x31\x26\x30\x24\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x17\x63\x61\x40\x66\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x30\x31\x31\x30\x32\x34\x32\x32\x30\x30\x30\x30\x5A\x17\x0D\x31\x33\x31\x30\x32\x34\x32\x32\x30\x30\x30\x30\x5A\x30\x81\x9D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x22\x30\x20\x06\x03\x55\x04\x07\x13\x19\x43\x2F\x20\x4D\x75\x6E\x74\x61\x6E\x65\x72\x20\x32\x34\x34\x20\x42\x61\x72\x63\x65\x6C\x6F\x6E\x61\x31\x42\x30\x40\x06\x03\x55\x04\x03\x13\x39\x41\x75\x74\x6F\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x46\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x20\x43\x49\x46\x20\x41\x36\x32\x36\x33\x34\x30\x36\x38\x31\x26\x30\x24\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x17\x63\x61\x40\x66\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x2E\x63\x6F\x6D\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\xE7\x23\x03\x6F\x6F\x23\xA5\x5E\x78\xCE\x95\x2C\xED\x94\x1E\x6E\x0A\x9E\x01\xC7\xEA\x30\xD1\x2C\x9D\xDD\x37\xE8\x9B\x98\x79\x56\xD3\xFC\x73\xDF\xD0\x8A\xDE\x55\x8F\x51\xF9\x5A\xEA\xDE\xB5\x70\xC4\xED\xA4\xED\xFF\xA3\x0D\x6E\x0F\x64\x50\x31\xAF\x01\x27\x58\xAE\xFE\x6C\xA7\x4A\x2F\x17\x2D\xD3\x73\xD5\x13\x1C\x8F\x59\xA5\x34\x2C\x1D\x54\x04\x45\xCD\x68\xB8\xA0\xC0\x03\xA5\xCF\x85\x42\x47\x95\x28\x5B\xCF\xEF\x80\x6C\xE0\x90\x97\x8A\x01\x3C\x1D\xF3\x87\x10\x30\x26\x48\x7D\xD7\xFC\xE9\x9D\x91\x71\xFF\x41\x9A\xA9\x40\xB5\x37\x9C\x29\x20\x4F\x1F\x52\xE3\xA0\x7D\x13\x6D\x54\xB7\x0A\xDE\xE9\x6A\x4E\x07\xAC\xAC\x19\x5F\xDC\x7E\x62\x74\xF6\xB2\x05\x00\xBA\x85\xA0\xFD\x1D\x38\x6E\xCB\x5A\xBB\x86\xBC\x94\x67\x33\x35\x83\x2C\x1F\x23\xCD\xF8\xC8\x91\x71\xCC\x97\x8B\xEF\xAE\x0F\xDC\x29\x03\x1B\xC0\x39\xEB\x70\xED\xC1\x6E\x0E\xD8\x67\x0B\x89\xA9\xBC\x35\xE4\xEF\xB6\x34\xB4\xA5\xB6\xC4\x2D\xA5\xBE\xD0\xC3\x94\x24\x48\xDB\xDF\x96\xD3\x00\xB5\x66\x1A\x8B\x66\x05\x0F\xDD\x3F\x3F\xCB\x3F\xAA\x5E\x9A\x4A\xF8\xB4\x4A\xEF\x95\x37\x1B\x02\x03\x01\x00\x01\xA3\x81\x9F\x30\x81\x9C\x30\x2A\x06\x03\x55\x1D\x11\x04\x23\x30\x21\x86\x1F\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x66\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x2E\x63\x6F\x6D\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x01\x30\x2B\x06\x03\x55\x1D\x10\x04\x24\x30\x22\x80\x0F\x32\x30\x30\x31\x31\x30\x32\x34\x32\x32\x30\x30\x30\x30\x5A\x81\x0F\x32\x30\x31\x33\x31\x30\x32\x34\x32\x32\x30\x30\x30\x30\x5A\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x33\x0B\xA0\x66\xD1\xEA\xDA\xCE\xDE\x62\x93\x04\x28\x52\xB5\x14\x7F\x38\x68\xB7\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x47\x73\xFE\x8D\x27\x54\xF0\xF5\xD4\x77\x9C\x27\x79\x57\x57\xB7\x15\x56\xEC\xC7\xD8\x58\xB7\x01\x02\xF4\x33\xED\x93\x50\x88\x9E\x7C\x46\xB1\xBD\x3F\x14\x6F\xF1\xB3\x47\x48\x8B\x8C\x97\x06\xD7\xEA\x7E\xA3\x5C\x2A\xBB\x4D\x2F\x47\xE2\xF8\x39\x06\xC9\x9C\x2E\x31\x1A\x03\x78\xF4\xBC\x38\xC6\x22\x8B\x33\x31\xF0\x16\x04\x04\x7D\xF9\x76\xE4\x4B\xD7\xC0\xE6\x83\xEC\x59\xCC\x3F\xDE\xFF\x4F\x6B\xB7\x67\x7E\xA6\x86\x81\x32\x23\x03\x9D\xC8\xF7\x5F\xC1\x4A\x60\xA5\x92\xA9\xB1\xA4\xA0\x60\xC3\x78\x87\xB3\x22\xF3\x2A\xEB\x5B\xA9\xED\x05\xAB\x37\x0F\xB1\xE2\xD3\x95\x76\x63\x56\x74\x8C\x58\x72\x1B\x37\xE5\x64\xA1\xBE\x4D\x0C\x93\x98\x0C\x97\xF6\x87\x6D\xB3\x3F\xE7\xCB\x80\xA6\xED\x88\xC7\x5F\x50\x62\x02\xE8\x99\x74\x16\xD0\xE6\xB4\x39\xF1\x27\xCB\xC8\x40\xD6\xE3\x86\x10\xA9\x23\x12\x92\xE0\x69\x41\x63\xA7\xAF\x25\x0B\xC0\xC5\x92\xCB\x1E\x98\xA3\x5A\xBA\xC5\x33\x0F\xA0\x97\x01\xDD\x7F\xE0\x7B\xD6\x06\x54\xCF\xA1\xE2\x4D\x38\xEB\x4B\x50\xB5\xCB\x26\xF4\xCA\xDA\x70\x4A\x6A\xA1\xE2\x79\xAA\xE1\xA7\x33\xF6\xFD\x4A\x1F\xF6\xD9\x60", + ["CN=Wells Fargo Root Certificate Authority,OU=Wells Fargo Certification Authority,O=Wells Fargo,C=US"] = "\x30\x82\x03\xE5\x30\x82\x02\xCD\xA0\x03\x02\x01\x02\x02\x04\x39\xE4\x97\x9E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x31\x2C\x30\x2A\x06\x03\x55\x04\x0B\x13\x23\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x2F\x30\x2D\x06\x03\x55\x04\x03\x13\x26\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x30\x31\x30\x31\x31\x31\x36\x34\x31\x32\x38\x5A\x17\x0D\x32\x31\x30\x31\x31\x34\x31\x36\x34\x31\x32\x38\x5A\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x13\x0B\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x31\x2C\x30\x2A\x06\x03\x55\x04\x0B\x13\x23\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x2F\x30\x2D\x06\x03\x55\x04\x03\x13\x26\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xD5\xA8\x33\x3B\x26\xF9\x34\xFF\xCD\x9B\x7E\xE5\x04\x47\xCE\x00\xE2\x7D\x77\xE7\x31\xC2\x2E\x27\xA5\x4D\x68\xB9\x31\xBA\x8D\x43\x59\x97\xC7\x73\xAA\x7F\x3D\x5C\x40\x9E\x05\xE5\xA1\xE2\x89\xD9\x4C\xB8\x3F\x9B\xF9\x0C\xB4\xC8\x62\x19\x2C\x45\xAE\x91\x1E\x73\x71\x41\xC4\x4B\x13\xFD\x70\xC2\x25\xAC\x22\xF5\x75\x0B\xB7\x53\xE4\xA5\x2B\xDD\xCE\xBD\x1C\x3A\x7A\xC3\xF7\x13\x8F\x26\x54\x9C\x16\x6B\x6B\xAF\xFB\xD8\x96\xB1\x60\x9A\x48\xE0\x25\x22\x24\x79\x34\xCE\x0E\x26\x00\x0B\x4E\xAB\xFD\x8B\xCE\x82\xD7\x2F\x08\x70\x68\xC1\xA8\x0A\xF9\x74\x4F\x07\xAB\xA4\xF9\xE2\x83\x7E\x27\x73\x74\x3E\xB8\xF9\x38\x42\xFC\xA5\xA8\x5B\x48\x23\xB3\xEB\xE3\x25\xB2\x80\xAE\x96\xD4\x0A\x9C\xC2\x78\x9A\xC6\x68\x18\xAE\x37\x62\x37\x5E\x51\x75\xA8\x58\x63\xC0\x51\xEE\x40\x78\x7E\xA8\xAF\x1A\xA0\xE1\xB0\x78\x9D\x50\x8C\x7B\xE7\xB3\xFC\x8E\x23\xB0\xDB\x65\x00\x70\x84\x01\x08\x00\x14\x6E\x54\x86\x9A\xBA\xCC\xF9\x37\x10\xF6\xE0\xDE\x84\x2D\x9D\xA4\x85\x37\xD3\x87\xE3\x15\xD0\xC1\x17\x90\x7E\x19\x21\x6A\x12\xA9\x76\xFD\x12\x02\xE9\x4F\x21\x5E\x17\x02\x03\x01\x00\x01\xA3\x61\x30\x5F\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x4C\x06\x03\x55\x1D\x20\x04\x45\x30\x43\x30\x41\x06\x0B\x60\x86\x48\x01\x86\xFB\x7B\x87\x07\x01\x0B\x30\x32\x30\x30\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x24\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x77\x65\x6C\x6C\x73\x66\x61\x72\x67\x6F\x2E\x63\x6F\x6D\x2F\x63\x65\x72\x74\x70\x6F\x6C\x69\x63\x79\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xD2\x27\xDD\x9C\x0A\x77\x2B\xBB\x22\xF2\x02\xB5\x4A\x4A\x91\xF9\xD1\x2D\xBE\xE4\xBB\x1A\x68\xEF\x0E\xA4\x00\xE9\xEE\xE7\xEF\xEE\xF6\xF9\xE5\x74\xA4\xC2\xD8\x52\x58\xC4\x74\xFB\xCE\x6B\xB5\x3B\x29\x79\x18\x5A\xEF\x9B\xED\x1F\x6B\x36\xEE\x48\x25\x25\x14\xB6\x56\xA2\x10\xE8\xEE\xA7\x7F\xD0\x3F\xA3\xD0\xC3\x5D\x26\xEE\x07\xCC\xC3\xC1\x24\x21\x87\x1E\xDF\x2A\x12\x53\x6F\x41\x16\xE7\xED\xAE\x94\xFA\x8C\x72\xFA\x13\x47\xF0\x3C\x7E\xAE\x7D\x11\x3A\x13\xEC\xED\xFA\x6F\x72\x64\x7B\x9D\x7D\x7F\x26\xFD\x7A\xFB\x25\xAD\xEA\x3E\x29\x7F\x4C\xE3\x00\x57\x32\xB0\xB3\xE9\xED\x53\x17\xD9\x8B\xB2\x14\x0E\x30\xE8\xE5\xD5\x13\xC6\x64\xAF\xC4\x00\xD5\xD8\x58\x24\xFC\xF5\x8F\xEC\xF1\xC7\x7D\xA5\xDB\x0F\x27\xD1\xC6\xF2\x40\x88\xE6\x1F\xF6\x61\xA8\xF4\x42\xC8\xB9\x37\xD3\xA9\xBE\x2C\x56\x78\xC2\x72\x9B\x59\x5D\x35\x40\x8A\xE8\x4E\x63\x1A\xB6\xE9\x20\x6A\x51\xE2\xCE\xA4\x90\xDF\x76\x70\x99\x5C\x70\x43\x4D\xB7\xB6\xA7\x19\x64\x4E\x92\xB7\xC5\x91\x3C\x7F\x48\x16\x65\x7B\x16\xFD\xCB\xFC\xFB\xD9\xD5\xD6\x4F\x21\x65\x3B\x4A\x7F\x47\xA3\xFB", + ["CN=Swisscom Root CA 1,OU=Digital Certificate Services,O=Swisscom,C=ch"] = "\x30\x82\x05\xD9\x30\x82\x03\xC1\xA0\x03\x02\x01\x02\x02\x10\x5C\x0B\x85\x5C\x0B\xE7\x59\x41\xDF\x57\xCC\x3F\x7F\x9D\xA8\x36\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x53\x77\x69\x73\x73\x63\x6F\x6D\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x44\x69\x67\x69\x74\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x53\x77\x69\x73\x73\x63\x6F\x6D\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x31\x30\x1E\x17\x0D\x30\x35\x30\x38\x31\x38\x31\x32\x30\x36\x32\x30\x5A\x17\x0D\x32\x35\x30\x38\x31\x38\x32\x32\x30\x36\x32\x30\x5A\x30\x64\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x63\x68\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x53\x77\x69\x73\x73\x63\x6F\x6D\x31\x25\x30\x23\x06\x03\x55\x04\x0B\x13\x1C\x44\x69\x67\x69\x74\x61\x6C\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x53\x65\x72\x76\x69\x63\x65\x73\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x53\x77\x69\x73\x73\x63\x6F\x6D\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x31\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xD0\xB9\xB0\xA8\x0C\xD9\xBB\x3F\x21\xF8\x1B\xD5\x33\x93\x80\x16\x65\x20\x75\xB2\x3D\x9B\x60\x6D\x46\xC8\x8C\x31\x6F\x17\xC3\xFA\x9A\x6C\x56\xED\x3C\xC5\x91\x57\xC3\xCD\xAB\x96\x49\x90\x2A\x19\x4B\x1E\xA3\x6D\x57\xDD\xF1\x2B\x62\x28\x75\x45\x5E\xAA\xD6\x5B\xFA\x0B\x25\xD8\xA1\x16\xF9\x1C\xC4\x2E\xE6\x95\x2A\x67\xCC\xD0\x29\x6E\x3C\x85\x34\x38\x61\x49\xB1\x00\x9F\xD6\x3A\x71\x5F\x4D\x6D\xCE\x5F\xB9\xA9\xE4\x89\x7F\x6A\x52\xFA\xCA\x9B\xF2\xDC\xA9\xF9\x9D\x99\x47\x3F\x4E\x29\x5F\xB4\xA6\x8D\x5D\x7B\x0B\x99\x11\x03\x03\xFE\xE7\xDB\xDB\xA3\xFF\x1D\xA5\xCD\x90\x1E\x01\x1F\x35\xB0\x7F\x00\xDB\x90\x6F\xC6\x7E\x7B\xD1\xEE\x7A\x7A\xA7\xAA\x0C\x57\x6F\xA4\x6D\xC5\x13\x3B\xB0\xA5\xD9\xED\x32\x1C\xB4\x5E\x67\x8B\x54\xDC\x73\x87\xE5\xD3\x17\x7C\x66\x50\x72\x5D\xD4\x1A\x58\xC1\xD9\xCF\xD8\x89\x02\x6F\xA7\x49\xB4\x36\x5D\xD0\xA4\xDE\x07\x2C\xB6\x75\xB7\x28\x91\xD6\x97\xBE\x28\xF5\x98\x1E\xEA\x5B\x26\xC9\xBD\xB0\x97\x73\xDA\xAE\x91\x26\xEB\x68\xC1\xF9\x39\x15\xD6\x67\x4B\x0A\x6D\x4F\xCB\xCF\xB0\xE4\x42\x71\x8C\x53\x79\xE7\xEE\xE1\xDB\x1D\xA0\x6E\x1D\x8C\x1A\x77\x35\x5C\x16\x1E\x2B\x53\x1F\x34\x8B\xD1\x6C\xFC\xF2\x67\x07\x7A\xF5\xAD\xED\xD6\x9A\xAB\xA1\xB1\x4B\xE1\xCC\x37\x5F\xFD\x7F\xCD\x4D\xAE\xB8\x1F\x9C\x43\xF9\x2A\x58\x55\x43\x45\xBC\x96\xCD\x70\x0E\xFC\xC9\xE3\x66\xBA\x4E\x8D\x3B\x81\xCB\x15\x64\x7B\xB9\x94\xE8\x5D\x33\x52\x85\x71\x2E\x4F\x8E\xA2\x06\x11\x51\xC9\xE3\xCB\xA1\x6E\x31\x08\x64\x0C\xC2\xD2\x3C\xF5\x36\xE8\xD7\xD0\x0E\x78\x23\x20\x91\xC9\x24\x2A\x65\x29\x5B\x22\xF7\x21\xCE\x83\x5E\xA4\xF3\xDE\x4B\xD3\x68\x8F\x46\x75\x5C\x83\x09\x6E\x29\x6B\xC4\x70\x8C\xF5\x9D\xD7\x20\x2F\xFF\x46\xD2\x2B\x38\xC2\x2F\x75\x1C\x3D\x7E\xDA\xA5\xEF\x1E\x60\x85\x69\x42\xD3\xCC\xF8\x63\xFE\x1E\x43\x39\x85\xA6\xB6\x63\x41\x10\xB3\x73\x1E\xBC\xD3\xFA\xCA\x7D\x16\x47\xE2\xA7\xD5\xD0\xA3\x8A\x0A\x08\x96\x62\x56\x6E\x34\xDB\xD9\x02\xB9\x30\x75\xE3\x04\xD2\xE7\x8F\xC2\xB0\x11\x40\x0A\xAC\xD5\x71\x02\x62\x8B\x31\xBE\xDD\xC6\x23\x58\x31\x42\x43\x2D\x74\xF9\xC6\x9E\xA6\x8A\x0F\xE9\xFE\xBF\x83\xE6\x43\x57\x24\xBA\xEF\x46\x34\xAA\xD7\x12\x01\x38\xED\x02\x03\x01\x00\x01\xA3\x81\x86\x30\x81\x83\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x1D\x06\x03\x55\x1D\x21\x04\x16\x30\x14\x30\x12\x06\x07\x60\x85\x74\x01\x53\x00\x01\x06\x07\x60\x85\x74\x01\x53\x00\x01\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x07\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x03\x25\x2F\xDE\x6F\x82\x01\x3A\x5C\x2C\xDC\x2B\xA1\x69\xB5\x67\xD4\x8C\xD3\xFD\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x03\x25\x2F\xDE\x6F\x82\x01\x3A\x5C\x2C\xDC\x2B\xA1\x69\xB5\x67\xD4\x8C\xD3\xFD\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x35\x10\xCB\xEC\xA6\x04\x0D\x0D\x0F\xCD\xC0\xDB\xAB\xA8\xF2\x88\x97\x0C\xDF\x93\x2F\x4D\x7C\x40\x56\x31\x7A\xEB\xA4\x0F\x60\xCD\x7A\xF3\xBE\xC3\x27\x8E\x03\x3E\xA4\xDD\x12\xEF\x7E\x1E\x74\x06\x3C\x3F\x31\xF2\x1C\x7B\x91\x31\x21\xB4\xF0\xD0\x6C\x97\xD4\xE9\x97\xB2\x24\x56\x1E\x56\xC3\x35\xBD\x88\x05\x0F\x5B\x10\x1A\x64\xE1\xC7\x82\x30\xF9\x32\xAD\x9E\x50\x2C\xE7\x78\x05\xD0\x31\xB1\x5A\x98\x8A\x75\x4E\x90\x5C\x6A\x14\x2A\xE0\x52\x47\x82\x60\xE6\x1E\xDA\x81\xB1\xFB\x14\x0B\x5A\xF1\x9F\xD2\x95\xBA\x3E\xD0\x1B\xD6\x15\x1D\xA3\xBE\x86\xD5\xDB\x0F\xC0\x49\x64\xBB\x2E\x50\x19\x4B\xD2\x24\xF8\xDD\x1E\x07\x56\xD0\x38\xA0\x95\x70\x20\x76\x8C\xD7\xDD\x1E\xDE\x9F\x71\xC4\x23\xEF\x83\x13\x5C\xA3\x24\x15\x4D\x29\x40\x3C\x6A\xC4\xA9\xD8\xB7\xA6\x44\xA5\x0D\xF4\xE0\x9D\x77\x1E\x40\x70\x26\xFC\xDA\xD9\x36\xE4\x79\xE4\xB5\x3F\xBC\x9B\x65\xBE\xBB\x11\x96\xCF\xDB\xC6\x28\x39\x3A\x08\xCE\x47\x5B\x53\x5A\xC5\x99\xFE\x5D\xA9\xDD\xEF\x4C\xD4\xC6\xA5\xAD\x02\xE6\x8C\x07\x12\x1E\x6F\x03\xD1\x6F\xA0\xA3\xF3\x29\xBD\x12\xC7\x50\xA2\xB0\x7F\x88\xA9\x99\x77\x9A\xB1\xC0\xA5\x39\x2E\x5C\x7C\x69\xE2\x2C\xB0\xEA\x37\x6A\xA4\xE1\x5A\xE1\xF5\x50\xE5\x83\xEF\xA5\xBB\x2A\x88\xE7\x8C\xDB\xFD\x6D\x5E\x97\x19\xA8\x7E\x66\x75\x6B\x71\xEA\xBF\xB1\xC7\x6F\xA0\xF4\x8E\xA4\xEC\x34\x51\x5B\x8C\x26\x03\x70\xA1\x77\xD5\x01\x12\x57\x00\x35\xDB\x23\xDE\x0E\x8A\x28\x99\xFD\xB1\x10\x6F\x4B\xFF\x38\x2D\x60\x4E\x2C\x9C\xEB\x67\xB5\xAD\x49\xEE\x4B\x1F\xAC\xAF\xFB\x0D\x90\x5A\x66\x60\x70\x5D\xAA\xCD\x78\xD4\x24\xEE\xC8\x41\xA0\x93\x01\x92\x9C\x6A\x9E\xFC\xB9\x24\xC5\xB3\x15\x82\x7E\xBE\xAE\x95\x2B\xEB\xB1\xC0\xDA\xE3\x01\x60\x0B\x5E\x69\xAC\x84\x56\x61\xBE\x71\x17\xFE\x1D\x13\x0F\xFE\xC6\x87\x45\xE9\xFE\x32\xA0\x1A\x0D\x13\xA4\x94\x55\x71\xA5\x16\x8B\xBA\xCA\x89\xB0\xB2\xC7\xFC\x8F\xD8\x54\xB5\x93\x62\x9D\xCE\xCF\x59\xFB\x3D\x18\xCE\x2A\xCB\x35\x15\x82\x5D\xFF\x54\x22\x5B\x71\x52\xFB\xB7\xC9\xFE\x60\x9B\x00\x41\x64\xF0\xAA\x2A\xEC\xB6\x42\x43\xCE\x89\x66\x81\xC8\x8B\x9F\x39\x54\x03\x25\xD3\x16\x35\x8E\x84\xD0\x5F\xFA\x30\x1A\xF5\x9A\x6C\xF4\x0E\x53\xF9\x3A\x5B\xD1\x1C", + ["CN=DigiCert Assured ID Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US"] = "\x30\x82\x03\xB7\x30\x82\x02\x9F\xA0\x03\x02\x01\x02\x02\x10\x0C\xE7\xE0\xE5\x17\xD8\x46\xFE\x8F\xE5\x60\xFC\x1B\xF0\x30\x39\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6E\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x77\x77\x77\x2E\x64\x69\x67\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1B\x44\x69\x67\x69\x43\x65\x72\x74\x20\x41\x73\x73\x75\x72\x65\x64\x20\x49\x44\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x31\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5A\x30\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6E\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x77\x77\x77\x2E\x64\x69\x67\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1B\x44\x69\x67\x69\x43\x65\x72\x74\x20\x41\x73\x73\x75\x72\x65\x64\x20\x49\x44\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xAD\x0E\x15\xCE\xE4\x43\x80\x5C\xB1\x87\xF3\xB7\x60\xF9\x71\x12\xA5\xAE\xDC\x26\x94\x88\xAA\xF4\xCE\xF5\x20\x39\x28\x58\x60\x0C\xF8\x80\xDA\xA9\x15\x95\x32\x61\x3C\xB5\xB1\x28\x84\x8A\x8A\xDC\x9F\x0A\x0C\x83\x17\x7A\x8F\x90\xAC\x8A\xE7\x79\x53\x5C\x31\x84\x2A\xF6\x0F\x98\x32\x36\x76\xCC\xDE\xDD\x3C\xA8\xA2\xEF\x6A\xFB\x21\xF2\x52\x61\xDF\x9F\x20\xD7\x1F\xE2\xB1\xD9\xFE\x18\x64\xD2\x12\x5B\x5F\xF9\x58\x18\x35\xBC\x47\xCD\xA1\x36\xF9\x6B\x7F\xD4\xB0\x38\x3E\xC1\x1B\xC3\x8C\x33\xD9\xD8\x2F\x18\xFE\x28\x0F\xB3\xA7\x83\xD6\xC3\x6E\x44\xC0\x61\x35\x96\x16\xFE\x59\x9C\x8B\x76\x6D\xD7\xF1\xA2\x4B\x0D\x2B\xFF\x0B\x72\xDA\x9E\x60\xD0\x8E\x90\x35\xC6\x78\x55\x87\x20\xA1\xCF\xE5\x6D\x0A\xC8\x49\x7C\x31\x98\x33\x6C\x22\xE9\x87\xD0\x32\x5A\xA2\xBA\x13\x82\x11\xED\x39\x17\x9D\x99\x3A\x72\xA1\xE6\xFA\xA4\xD9\xD5\x17\x31\x75\xAE\x85\x7D\x22\xAE\x3F\x01\x46\x86\xF6\x28\x79\xC8\xB1\xDA\xE4\x57\x17\xC4\x7E\x1C\x0E\xB0\xB4\x92\xA6\x56\xB3\xBD\xB2\x97\xED\xAA\xA7\xF0\xB7\xC5\xA8\x3F\x95\x16\xD0\xFF\xA1\x96\xEB\x08\x5F\x18\x77\x4F\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x45\xEB\xA2\xAF\xF4\x92\xCB\x82\x31\x2D\x51\x8B\xA7\xA7\x21\x9D\xF3\x6D\xC8\x0F\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x45\xEB\xA2\xAF\xF4\x92\xCB\x82\x31\x2D\x51\x8B\xA7\xA7\x21\x9D\xF3\x6D\xC8\x0F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA2\x0E\xBC\xDF\xE2\xED\xF0\xE3\x72\x73\x7A\x64\x94\xBF\xF7\x72\x66\xD8\x32\xE4\x42\x75\x62\xAE\x87\xEB\xF2\xD5\xD9\xDE\x56\xB3\x9F\xCC\xCE\x14\x28\xB9\x0D\x97\x60\x5C\x12\x4C\x58\xE4\xD3\x3D\x83\x49\x45\x58\x97\x35\x69\x1A\xA8\x47\xEA\x56\xC6\x79\xAB\x12\xD8\x67\x81\x84\xDF\x7F\x09\x3C\x94\xE6\xB8\x26\x2C\x20\xBD\x3D\xB3\x28\x89\xF7\x5F\xFF\x22\xE2\x97\x84\x1F\xE9\x65\xEF\x87\xE0\xDF\xC1\x67\x49\xB3\x5D\xEB\xB2\x09\x2A\xEB\x26\xED\x78\xBE\x7D\x3F\x2B\xF3\xB7\x26\x35\x6D\x5F\x89\x01\xB6\x49\x5B\x9F\x01\x05\x9B\xAB\x3D\x25\xC1\xCC\xB6\x7F\xC2\xF1\x6F\x86\xC6\xFA\x64\x68\xEB\x81\x2D\x94\xEB\x42\xB7\xFA\x8C\x1E\xDD\x62\xF1\xBE\x50\x67\xB7\x6C\xBD\xF3\xF1\x1F\x6B\x0C\x36\x07\x16\x7F\x37\x7C\xA9\x5B\x6D\x7A\xF1\x12\x46\x60\x83\xD7\x27\x04\xBE\x4B\xCE\x97\xBE\xC3\x67\x2A\x68\x11\xDF\x80\xE7\x0C\x33\x66\xBF\x13\x0D\x14\x6E\xF3\x7F\x1F\x63\x10\x1E\xFA\x8D\x1B\x25\x6D\x6C\x8F\xA5\xB7\x61\x01\xB1\xD2\xA3\x26\xA1\x10\x71\x9D\xAD\xE2\xC3\xF9\xC3\x99\x51\xB7\x2B\x07\x08\xCE\x2E\xE6\x50\xB2\xA7\xFA\x0A\x45\x2F\xA2\xF0\xF2", + ["CN=DigiCert Global Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US"] = "\x30\x82\x03\xAF\x30\x82\x02\x97\xA0\x03\x02\x01\x02\x02\x10\x08\x3B\xE0\x56\x90\x42\x46\xB1\xA1\x75\x6A\xC9\x59\x91\xC7\x4A\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x61\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6E\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x77\x77\x77\x2E\x64\x69\x67\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x44\x69\x67\x69\x43\x65\x72\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x31\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5A\x30\x61\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6E\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x77\x77\x77\x2E\x64\x69\x67\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x44\x69\x67\x69\x43\x65\x72\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xE2\x3B\xE1\x11\x72\xDE\xA8\xA4\xD3\xA3\x57\xAA\x50\xA2\x8F\x0B\x77\x90\xC9\xA2\xA5\xEE\x12\xCE\x96\x5B\x01\x09\x20\xCC\x01\x93\xA7\x4E\x30\xB7\x53\xF7\x43\xC4\x69\x00\x57\x9D\xE2\x8D\x22\xDD\x87\x06\x40\x00\x81\x09\xCE\xCE\x1B\x83\xBF\xDF\xCD\x3B\x71\x46\xE2\xD6\x66\xC7\x05\xB3\x76\x27\x16\x8F\x7B\x9E\x1E\x95\x7D\xEE\xB7\x48\xA3\x08\xDA\xD6\xAF\x7A\x0C\x39\x06\x65\x7F\x4A\x5D\x1F\xBC\x17\xF8\xAB\xBE\xEE\x28\xD7\x74\x7F\x7A\x78\x99\x59\x85\x68\x6E\x5C\x23\x32\x4B\xBF\x4E\xC0\xE8\x5A\x6D\xE3\x70\xBF\x77\x10\xBF\xFC\x01\xF6\x85\xD9\xA8\x44\x10\x58\x32\xA9\x75\x18\xD5\xD1\xA2\xBE\x47\xE2\x27\x6A\xF4\x9A\x33\xF8\x49\x08\x60\x8B\xD4\x5F\xB4\x3A\x84\xBF\xA1\xAA\x4A\x4C\x7D\x3E\xCF\x4F\x5F\x6C\x76\x5E\xA0\x4B\x37\x91\x9E\xDC\x22\xE6\x6D\xCE\x14\x1A\x8E\x6A\xCB\xFE\xCD\xB3\x14\x64\x17\xC7\x5B\x29\x9E\x32\xBF\xF2\xEE\xFA\xD3\x0B\x42\xD4\xAB\xB7\x41\x32\xDA\x0C\xD4\xEF\xF8\x81\xD5\xBB\x8D\x58\x3F\xB5\x1B\xE8\x49\x28\xA2\x70\xDA\x31\x04\xDD\xF7\xB2\x16\xF2\x4C\x0A\x4E\x07\xA8\xED\x4A\x3D\x5E\xB5\x7F\xA3\x90\xC3\xAF\x27\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x03\xDE\x50\x35\x56\xD1\x4C\xBB\x66\xF0\xA3\xE2\x1B\x1B\xC3\x97\xB2\x3D\xD1\x55\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x03\xDE\x50\x35\x56\xD1\x4C\xBB\x66\xF0\xA3\xE2\x1B\x1B\xC3\x97\xB2\x3D\xD1\x55\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xCB\x9C\x37\xAA\x48\x13\x12\x0A\xFA\xDD\x44\x9C\x4F\x52\xB0\xF4\xDF\xAE\x04\xF5\x79\x79\x08\xA3\x24\x18\xFC\x4B\x2B\x84\xC0\x2D\xB9\xD5\xC7\xFE\xF4\xC1\x1F\x58\xCB\xB8\x6D\x9C\x7A\x74\xE7\x98\x29\xAB\x11\xB5\xE3\x70\xA0\xA1\xCD\x4C\x88\x99\x93\x8C\x91\x70\xE2\xAB\x0F\x1C\xBE\x93\xA9\xFF\x63\xD5\xE4\x07\x60\xD3\xA3\xBF\x9D\x5B\x09\xF1\xD5\x8E\xE3\x53\xF4\x8E\x63\xFA\x3F\xA7\xDB\xB4\x66\xDF\x62\x66\xD6\xD1\x6E\x41\x8D\xF2\x2D\xB5\xEA\x77\x4A\x9F\x9D\x58\xE2\x2B\x59\xC0\x40\x23\xED\x2D\x28\x82\x45\x3E\x79\x54\x92\x26\x98\xE0\x80\x48\xA8\x37\xEF\xF0\xD6\x79\x60\x16\xDE\xAC\xE8\x0E\xCD\x6E\xAC\x44\x17\x38\x2F\x49\xDA\xE1\x45\x3E\x2A\xB9\x36\x53\xCF\x3A\x50\x06\xF7\x2E\xE8\xC4\x57\x49\x6C\x61\x21\x18\xD5\x04\xAD\x78\x3C\x2C\x3A\x80\x6B\xA7\xEB\xAF\x15\x14\xE9\xD8\x89\xC1\xB9\x38\x6C\xE2\x91\x6C\x8A\xFF\x64\xB9\x77\x25\x57\x30\xC0\x1B\x24\xA3\xE1\xDC\xE9\xDF\x47\x7C\xB5\xB4\x24\x08\x05\x30\xEC\x2D\xBD\x0B\xBF\x45\xBF\x50\xB9\xA9\xF3\xEB\x98\x01\x12\xAD\xC8\x88\xC6\x98\x34\x5F\x8D\x0A\x3C\xC6\xE9\xD5\x95\x95\x6D\xDE", + ["CN=DigiCert High Assurance EV Root CA,OU=www.digicert.com,O=DigiCert Inc,C=US"] = "\x30\x82\x03\xC5\x30\x82\x02\xAD\xA0\x03\x02\x01\x02\x02\x10\x02\xAC\x5C\x26\x6A\x0B\x40\x9B\x8F\x0B\x79\xF2\xAE\x46\x25\x77\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x6C\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6E\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x77\x77\x77\x2E\x64\x69\x67\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x31\x2B\x30\x29\x06\x03\x55\x04\x03\x13\x22\x44\x69\x67\x69\x43\x65\x72\x74\x20\x48\x69\x67\x68\x20\x41\x73\x73\x75\x72\x61\x6E\x63\x65\x20\x45\x56\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x31\x31\x31\x31\x30\x30\x30\x30\x30\x30\x30\x5A\x30\x6C\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x44\x69\x67\x69\x43\x65\x72\x74\x20\x49\x6E\x63\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x77\x77\x77\x2E\x64\x69\x67\x69\x63\x65\x72\x74\x2E\x63\x6F\x6D\x31\x2B\x30\x29\x06\x03\x55\x04\x03\x13\x22\x44\x69\x67\x69\x43\x65\x72\x74\x20\x48\x69\x67\x68\x20\x41\x73\x73\x75\x72\x61\x6E\x63\x65\x20\x45\x56\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xC6\xCC\xE5\x73\xE6\xFB\xD4\xBB\xE5\x2D\x2D\x32\xA6\xDF\xE5\x81\x3F\xC9\xCD\x25\x49\xB6\x71\x2A\xC3\xD5\x94\x34\x67\xA2\x0A\x1C\xB0\x5F\x69\xA6\x40\xB1\xC4\xB7\xB2\x8F\xD0\x98\xA4\xA9\x41\x59\x3A\xD3\xDC\x94\xD6\x3C\xDB\x74\x38\xA4\x4A\xCC\x4D\x25\x82\xF7\x4A\xA5\x53\x12\x38\xEE\xF3\x49\x6D\x71\x91\x7E\x63\xB6\xAB\xA6\x5F\xC3\xA4\x84\xF8\x4F\x62\x51\xBE\xF8\xC5\xEC\xDB\x38\x92\xE3\x06\xE5\x08\x91\x0C\xC4\x28\x41\x55\xFB\xCB\x5A\x89\x15\x7E\x71\xE8\x35\xBF\x4D\x72\x09\x3D\xBE\x3A\x38\x50\x5B\x77\x31\x1B\x8D\xB3\xC7\x24\x45\x9A\xA7\xAC\x6D\x00\x14\x5A\x04\xB7\xBA\x13\xEB\x51\x0A\x98\x41\x41\x22\x4E\x65\x61\x87\x81\x41\x50\xA6\x79\x5C\x89\xDE\x19\x4A\x57\xD5\x2E\xE6\x5D\x1C\x53\x2C\x7E\x98\xCD\x1A\x06\x16\xA4\x68\x73\xD0\x34\x04\x13\x5C\xA1\x71\xD3\x5A\x7C\x55\xDB\x5E\x64\xE1\x37\x87\x30\x56\x04\xE5\x11\xB4\x29\x80\x12\xF1\x79\x39\x88\xA2\x02\x11\x7C\x27\x66\xB7\x88\xB7\x78\xF2\xCA\x0A\xA8\x38\xAB\x0A\x64\xC2\xBF\x66\x5D\x95\x84\xC1\xA1\x25\x1E\x87\x5D\x1A\x50\x0B\x20\x12\xCC\x41\xBB\x6E\x0B\x51\x38\xB8\x4B\xCB\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB1\x3E\xC3\x69\x03\xF8\xBF\x47\x01\xD4\x98\x26\x1A\x08\x02\xEF\x63\x64\x2B\xC3\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xB1\x3E\xC3\x69\x03\xF8\xBF\x47\x01\xD4\x98\x26\x1A\x08\x02\xEF\x63\x64\x2B\xC3\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x1C\x1A\x06\x97\xDC\xD7\x9C\x9F\x3C\x88\x66\x06\x08\x57\x21\xDB\x21\x47\xF8\x2A\x67\xAA\xBF\x18\x32\x76\x40\x10\x57\xC1\x8A\xF3\x7A\xD9\x11\x65\x8E\x35\xFA\x9E\xFC\x45\xB5\x9E\xD9\x4C\x31\x4B\xB8\x91\xE8\x43\x2C\x8E\xB3\x78\xCE\xDB\xE3\x53\x79\x71\xD6\xE5\x21\x94\x01\xDA\x55\x87\x9A\x24\x64\xF6\x8A\x66\xCC\xDE\x9C\x37\xCD\xA8\x34\xB1\x69\x9B\x23\xC8\x9E\x78\x22\x2B\x70\x43\xE3\x55\x47\x31\x61\x19\xEF\x58\xC5\x85\x2F\x4E\x30\xF6\xA0\x31\x16\x23\xC8\xE7\xE2\x65\x16\x33\xCB\xBF\x1A\x1B\xA0\x3D\xF8\xCA\x5E\x8B\x31\x8B\x60\x08\x89\x2D\x0C\x06\x5C\x52\xB7\xC4\xF9\x0A\x98\xD1\x15\x5F\x9F\x12\xBE\x7C\x36\x63\x38\xBD\x44\xA4\x7F\xE4\x26\x2B\x0A\xC4\x97\x69\x0D\xE9\x8C\xE2\xC0\x10\x57\xB8\xC8\x76\x12\x91\x55\xF2\x48\x69\xD8\xBC\x2A\x02\x5B\x0F\x44\xD4\x20\x31\xDB\xF4\xBA\x70\x26\x5D\x90\x60\x9E\xBC\x4B\x17\x09\x2F\xB4\xCB\x1E\x43\x68\xC9\x07\x27\xC1\xD2\x5C\xF7\xEA\x21\xB9\x68\x12\x9C\x3C\x9C\xBF\x9E\xFC\x80\x5C\x9B\x63\xCD\xEC\x47\xAA\x25\x27\x67\xA0\x37\xF3\x00\x82\x7D\x54\xD7\xA9\xF8\xE9\x2E\x13\xA3\x77\xE8\x1F\x4A", + ["CN=Class 2 Primary CA,O=Certplus,C=FR"] = "\x30\x82\x03\x92\x30\x82\x02\x7A\xA0\x03\x02\x01\x02\x02\x11\x00\x85\xBD\x4B\xF3\xD8\xDA\xE3\x69\xF6\x94\xD7\x5F\xC3\xA5\x44\x23\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x43\x65\x72\x74\x70\x6C\x75\x73\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x43\x6C\x61\x73\x73\x20\x32\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x41\x30\x1E\x17\x0D\x39\x39\x30\x37\x30\x37\x31\x37\x30\x35\x30\x30\x5A\x17\x0D\x31\x39\x30\x37\x30\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x3D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x43\x65\x72\x74\x70\x6C\x75\x73\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x43\x6C\x61\x73\x73\x20\x32\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x41\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\xDC\x50\x96\xD0\x12\xF8\x35\xD2\x08\x78\x7A\xB6\x52\x70\xFD\x6F\xEE\xCF\xB9\x11\xCB\x5D\x77\xE1\xEC\xE9\x7E\x04\x8D\xD6\xCC\x6F\x73\x43\x57\x60\xAC\x33\x0A\x44\xEC\x03\x5F\x1C\x80\x24\x91\xE5\xA8\x91\x56\x12\x82\xF7\xE0\x2B\xF4\xDB\xAE\x61\x2E\x89\x10\x8D\x6B\x6C\xBA\xB3\x02\xBD\xD5\x36\xC5\x48\x37\x23\xE2\xF0\x5A\x37\x52\x33\x17\x12\xE2\xD1\x60\x4D\xBE\x2F\x41\x11\xE3\xF6\x17\x25\x0C\x8B\x91\xC0\x1B\x99\x7B\x99\x56\x0D\xAF\xEE\xD2\xBC\x47\x57\xE3\x79\x49\x7B\x34\x89\x27\x24\x84\xDE\xB1\xEC\xE9\x58\x4E\xFE\x4E\xDF\x5A\xBE\x41\xAD\xAC\x08\xC5\x18\x0E\xEF\xD2\x53\xEE\x6C\xD0\x9D\x12\x01\x13\x8D\xDC\x80\x62\xF7\x95\xA9\x44\x88\x4A\x71\x4E\x60\x55\x9E\xDB\x23\x19\x79\x56\x07\x0C\x3F\x63\x0B\x5C\xB0\xE2\xBE\x7E\x15\xFC\x94\x33\x58\x41\x38\x74\xC4\xE1\x8F\x8B\xDF\x26\xAC\x1F\xB5\x8B\x3B\xB7\x43\x59\x6B\xB0\x24\xA6\x6D\x90\x8B\xC4\x72\xEA\x5D\x33\x98\xB7\xCB\xDE\x5E\x7B\xEF\x94\xF1\x1B\x3E\xCA\xC9\x21\xC1\xC5\x98\x02\xAA\xA2\xF6\x5B\x77\x9B\xF5\x7E\x96\x55\x34\x1C\x67\x69\xC0\xF1\x42\xE3\x47\xAC\xFC\x28\x1C\x66\x55\x02\x03\x01\x00\x01\xA3\x81\x8C\x30\x81\x89\x30\x0F\x06\x03\x55\x1D\x13\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x0A\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE3\x73\x2D\xDF\xCB\x0E\x28\x0C\xDE\xDD\xB3\xA4\xCA\x79\xB8\x8E\xBB\xE8\x30\x89\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x01\x06\x30\x37\x06\x03\x55\x1D\x1F\x04\x30\x30\x2E\x30\x2C\xA0\x2A\xA0\x28\x86\x26\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x65\x72\x74\x70\x6C\x75\x73\x2E\x63\x6F\x6D\x2F\x43\x52\x4C\x2F\x63\x6C\x61\x73\x73\x32\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA7\x54\xCF\x88\x44\x19\xCB\xDF\xD4\x7F\x00\xDF\x56\x33\x62\xB5\xF7\x51\x01\x90\xEB\xC3\x3F\xD1\x88\x44\xE9\x24\x5D\xEF\xE7\x14\xBD\x20\xB7\x9A\x3C\x00\xFE\x6D\x9F\xDB\x90\xDC\xD7\xF4\x62\xD6\x8B\x70\x5D\xE7\xE5\x04\x48\xA9\x68\x7C\xC9\xF1\x42\xF3\x6C\x7F\xC5\x7A\x7C\x1D\x51\x88\xBA\xD2\x0A\x3E\x27\x5D\xDE\x2D\x51\x4E\xD3\x13\x64\x69\xE4\x2E\xE3\xD3\xE7\x9B\x09\x99\xA6\xE0\x95\x9B\xCE\x1A\xD7\x7F\xBE\x3C\xCE\x52\xB3\x11\x15\xC1\x0F\x17\xCD\x03\xBB\x9C\x25\x15\xBA\xA2\x76\x89\xFC\x06\xF1\x18\xD0\x93\x4B\x0E\x7C\x82\xB7\xA5\xF4\xF6\x5F\xFE\xED\x40\xA6\x9D\x84\x74\x39\xB9\xDC\x1E\x85\x16\xDA\x29\x1B\x86\x23\x00\xC9\xBB\x89\x7E\x6E\x80\x88\x1E\x2F\x14\xB4\x03\x24\xA8\x32\x6F\x03\x9A\x47\x2C\x30\xBE\x56\xC6\xA7\x42\x02\x70\x1B\xEA\x40\xD8\xBA\x05\x03\x70\x07\xA4\x96\xFF\xFD\x48\x33\x0A\xE1\xDC\xA5\x81\x90\x9B\x4D\xDD\x7D\xE7\xE7\xB2\xCD\x5C\xC8\x6A\x95\xF8\xA5\xF6\x8D\xC4\x5D\x78\x08\xBE\x7B\x06\xD6\x49\xCF\x19\x36\x50\x23\x2E\x08\xE6\x9E\x05\x4D\x47\x18\xD5\x16\xE9\xB1\xD6\xB6\x10\xD5\xBB\x97\xBF\xA2\x8E\xB4\x54", + ["CN=DST Root CA X3,O=Digital Signature Trust Co."] = "\x30\x82\x03\x4A\x30\x82\x02\x32\xA0\x03\x02\x01\x02\x02\x10\x44\xAF\xB0\x80\xD6\xA3\x27\xBA\x89\x30\x39\x86\x2E\xF8\x40\x6B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3F\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0E\x44\x53\x54\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x58\x33\x30\x1E\x17\x0D\x30\x30\x30\x39\x33\x30\x32\x31\x31\x32\x31\x39\x5A\x17\x0D\x32\x31\x30\x39\x33\x30\x31\x34\x30\x31\x31\x35\x5A\x30\x3F\x31\x24\x30\x22\x06\x03\x55\x04\x0A\x13\x1B\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x20\x43\x6F\x2E\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0E\x44\x53\x54\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x58\x33\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\xDF\xAF\xE9\x97\x50\x08\x83\x57\xB4\xCC\x62\x65\xF6\x90\x82\xEC\xC7\xD3\x2C\x6B\x30\xCA\x5B\xEC\xD9\xC3\x7D\xC7\x40\xC1\x18\x14\x8B\xE0\xE8\x33\x76\x49\x2A\xE3\x3F\x21\x49\x93\xAC\x4E\x0E\xAF\x3E\x48\xCB\x65\xEE\xFC\xD3\x21\x0F\x65\xD2\x2A\xD9\x32\x8F\x8C\xE5\xF7\x77\xB0\x12\x7B\xB5\x95\xC0\x89\xA3\xA9\xBA\xED\x73\x2E\x7A\x0C\x06\x32\x83\xA2\x7E\x8A\x14\x30\xCD\x11\xA0\xE1\x2A\x38\xB9\x79\x0A\x31\xFD\x50\xBD\x80\x65\xDF\xB7\x51\x63\x83\xC8\xE2\x88\x61\xEA\x4B\x61\x81\xEC\x52\x6B\xB9\xA2\xE2\x4B\x1A\x28\x9F\x48\xA3\x9E\x0C\xDA\x09\x8E\x3E\x17\x2E\x1E\xDD\x20\xDF\x5B\xC6\x2A\x8A\xAB\x2E\xBD\x70\xAD\xC5\x0B\x1A\x25\x90\x74\x72\xC5\x7B\x6A\xAB\x34\xD6\x30\x89\xFF\xE5\x68\x13\x7B\x54\x0B\xC8\xD6\xAE\xEC\x5A\x9C\x92\x1E\x3D\x64\xB3\x8C\xC6\xDF\xBF\xC9\x41\x70\xEC\x16\x72\xD5\x26\xEC\x38\x55\x39\x43\xD0\xFC\xFD\x18\x5C\x40\xF1\x97\xEB\xD5\x9A\x9B\x8D\x1D\xBA\xDA\x25\xB9\xC6\xD8\xDF\xC1\x15\x02\x3A\xAB\xDA\x6E\xF1\x3E\x2E\xF5\x5C\x08\x9C\x3C\xD6\x83\x69\xE4\x10\x9B\x19\x2A\xB6\x29\x57\xE3\xE5\x3D\x9B\x9F\xF0\x02\x5D\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC4\xA7\xB1\xA4\x7B\x2C\x71\xFA\xDB\xE1\x4B\x90\x75\xFF\xC4\x15\x60\x85\x89\x10\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA3\x1A\x2C\x9B\x17\x00\x5C\xA9\x1E\xEE\x28\x66\x37\x3A\xBF\x83\xC7\x3F\x4B\xC3\x09\xA0\x95\x20\x5D\xE3\xD9\x59\x44\xD2\x3E\x0D\x3E\xBD\x8A\x4B\xA0\x74\x1F\xCE\x10\x82\x9C\x74\x1A\x1D\x7E\x98\x1A\xDD\xCB\x13\x4B\xB3\x20\x44\xE4\x91\xE9\xCC\xFC\x7D\xA5\xDB\x6A\xE5\xFE\xE6\xFD\xE0\x4E\xDD\xB7\x00\x3A\xB5\x70\x49\xAF\xF2\xE5\xEB\x02\xF1\xD1\x02\x8B\x19\xCB\x94\x3A\x5E\x48\xC4\x18\x1E\x58\x19\x5F\x1E\x02\x5A\xF0\x0C\xF1\xB1\xAD\xA9\xDC\x59\x86\x8B\x6E\xE9\x91\xF5\x86\xCA\xFA\xB9\x66\x33\xAA\x59\x5B\xCE\xE2\xA7\x16\x73\x47\xCB\x2B\xCC\x99\xB0\x37\x48\xCF\xE3\x56\x4B\xF5\xCF\x0F\x0C\x72\x32\x87\xC6\xF0\x44\xBB\x53\x72\x6D\x43\xF5\x26\x48\x9A\x52\x67\xB7\x58\xAB\xFE\x67\x76\x71\x78\xDB\x0D\xA2\x56\x14\x13\x39\x24\x31\x85\xA2\xA8\x02\x5A\x30\x47\xE1\xDD\x50\x07\xBC\x02\x09\x90\x00\xEB\x64\x63\x60\x9B\x16\xBC\x88\xC9\x12\xE6\xD2\x7D\x91\x8B\xF9\x3D\x32\x8D\x65\xB4\xE9\x7C\xB1\x57\x76\xEA\xC5\xB6\x28\x39\xBF\x15\x65\x1C\xC8\xF6\x77\x96\x6A\x0A\x8D\x77\x0B\xD8\x91\x0B\x04\x8E\x07\xDB\x29\xB6\x0A\xEE\x9D\x82\x35\x35\x10", + ["CN=DST ACES CA X6,OU=DST ACES,O=Digital Signature Trust,C=US"] = "\x30\x82\x04\x09\x30\x82\x02\xF1\xA0\x03\x02\x01\x02\x02\x10\x0D\x5E\x99\x0A\xD6\x9D\xB7\x78\xEC\xD8\x07\x56\x3B\x86\x15\xD9\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x5B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x13\x17\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x20\x41\x43\x45\x53\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0E\x44\x53\x54\x20\x41\x43\x45\x53\x20\x43\x41\x20\x58\x36\x30\x1E\x17\x0D\x30\x33\x31\x31\x32\x30\x32\x31\x31\x39\x35\x38\x5A\x17\x0D\x31\x37\x31\x31\x32\x30\x32\x31\x31\x39\x35\x38\x5A\x30\x5B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x13\x17\x44\x69\x67\x69\x74\x61\x6C\x20\x53\x69\x67\x6E\x61\x74\x75\x72\x65\x20\x54\x72\x75\x73\x74\x31\x11\x30\x0F\x06\x03\x55\x04\x0B\x13\x08\x44\x53\x54\x20\x41\x43\x45\x53\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0E\x44\x53\x54\x20\x41\x43\x45\x53\x20\x43\x41\x20\x58\x36\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\xB9\x3D\xF5\x2C\xC9\x94\xDC\x75\x8A\x95\x5D\x63\xE8\x84\x77\x76\x66\xB9\x59\x91\x5C\x46\xDD\x92\x3E\x9F\xF9\x0E\x03\xB4\x3D\x61\x92\xBD\x23\x26\xB5\x63\xEE\x92\xD2\x9E\xD6\x3C\xC8\x0D\x90\x5F\x64\x81\xB1\xA8\x08\x0D\x4C\xD8\xF9\xD3\x05\x28\x52\xB4\x01\x25\xC5\x95\x1C\x0C\x7E\x3E\x10\x84\x75\xCF\xC1\x19\x91\x63\xCF\xE8\xA8\x91\x88\xB9\x43\x52\xBB\x80\xB1\x55\x89\x8B\x31\xFA\xD0\xB7\x76\xBE\x41\x3D\x30\x9A\xA4\x22\x25\x17\x73\xE8\x1E\xE2\xD3\xAC\x2A\xBD\x5B\x38\x21\xD5\x2A\x4B\xD7\x55\x7D\xE3\x3A\x55\xBD\xD7\x6D\x6B\x02\x57\x6B\xE6\x47\x7C\x08\xC8\x82\xBA\xDE\xA7\x87\x3D\xA1\x6D\xB8\x30\x56\xC2\xB3\x02\x81\x5F\x2D\xF5\xE2\x9A\x30\x18\x28\xB8\x66\xD3\xCB\x01\x96\x6F\xEA\x8A\x45\x55\xD6\xE0\x9D\xFF\x67\x2B\x17\x02\xA6\x4E\x1A\x6A\x11\x0B\x7E\xB7\x7B\xE7\x98\xD6\x8C\x76\x6F\xC1\x3B\xDB\x50\x93\x7E\xE5\xD0\x8E\x1F\x37\xB8\xBD\xBA\xC6\x9F\x6C\xE9\x7C\x33\xF2\x32\x3C\x26\x47\xFA\x27\x24\x02\xC9\x7E\x1D\x5B\x88\x42\x13\x6A\x35\x7C\x7D\x35\xE9\x2E\x66\x91\x72\x93\xD5\x32\x26\xC4\x74\xF5\x53\xA3\xB3\x5D\x9A\xF6\x09\xCB\x02\x03\x01\x00\x01\xA3\x81\xC8\x30\x81\xC5\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\xC6\x30\x1F\x06\x03\x55\x1D\x11\x04\x18\x30\x16\x81\x14\x70\x6B\x69\x2D\x6F\x70\x73\x40\x74\x72\x75\x73\x74\x64\x73\x74\x2E\x63\x6F\x6D\x30\x62\x06\x03\x55\x1D\x20\x04\x5B\x30\x59\x30\x57\x06\x0A\x60\x86\x48\x01\x65\x03\x02\x01\x01\x01\x30\x49\x30\x47\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x3B\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x64\x73\x74\x2E\x63\x6F\x6D\x2F\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x73\x2F\x70\x6F\x6C\x69\x63\x79\x2F\x41\x43\x45\x53\x2D\x69\x6E\x64\x65\x78\x2E\x68\x74\x6D\x6C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x09\x72\x06\x4E\x18\x43\x0F\xE5\xD6\xCC\xC3\x6A\x8B\x31\x7B\x78\x8F\xA8\x83\xB8\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA3\xD8\x8E\xD6\xB2\xDB\xCE\x05\xE7\x32\xCD\x01\xD3\x04\x03\xE5\x76\xE4\x56\x2B\x9C\x99\x90\xE8\x08\x30\x6C\xDF\x7D\x3D\xEE\xE5\xBF\xB5\x24\x40\x84\x49\xE1\xD1\x28\xAE\xC4\xC2\x3A\x53\x30\x88\xF1\xF5\x77\x6E\x51\xCA\xFA\xFF\x99\xAF\x24\x5F\x1B\xA0\xFD\xF2\xAC\x84\xCA\xDF\xA9\xF0\x5F\x04\x2E\xAD\x16\xBF\x21\x97\x10\x81\x3D\xE3\xFF\x87\x8D\x32\xDC\x94\xE5\x47\x8A\x5E\x6A\x13\xC9\x94\x95\x3D\xD2\xEE\xC8\x34\x95\xD0\x80\xD4\xAD\x32\x08\x80\x54\x3C\xE0\xBD\x52\x53\xD7\x52\x7C\xB2\x69\x3F\x7F\x7A\xCF\x6A\x74\xCA\xFA\x04\x2A\x9C\x4C\x5A\x06\xA5\xE9\x20\xAD\x45\x66\x0F\x69\xF1\xDD\xBF\xE9\xE3\x32\x8B\xFA\xE0\xC1\x86\x4D\x72\x3C\x2E\xD8\x93\x78\x0A\x2A\xF8\xD8\xD2\x27\x3D\x19\x89\x5F\x5A\x7B\x8A\x3B\xCC\x0C\xDA\x51\xAE\xC7\x0B\xF7\x2B\xB0\x37\x05\xEC\xBC\x57\x23\xE2\x38\xD2\x9B\x68\xF3\x56\x12\x88\x4F\x42\x7C\xB8\x31\xC4\xB5\xDB\xE4\xC8\x21\x34\xE9\x48\x11\x35\xEE\xFA\xC7\x92\x57\xC5\x9F\x34\xE4\xC7\xF6\xF7\x0E\x0B\x4C\x9C\x68\x78\x7B\x71\x31\xC7\xEB\x1E\xE0\x67\x41\xF3\xB7\xA0\xA7\xCD\xE5\x7A\x33\x36\x6A\xFA\x9A\x2B", + ["O=(c) 2005 T\C3\9CRKTRUST Bilgi \C4\B0leti\C5\9Fim ve Bili\C5\9Fim G\C3\BCvenli\C4\9Fi Hizmetleri A.\C5\9E.,L=ANKARA,C=TR,CN=T\C3\9CRKTRUST Elektronik Sertifika Hizmet Sa\C4\9Flay\C4\B1c\C4\B1s\C4\B1"] = "\x30\x82\x03\xFB\x30\x82\x02\xE3\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xB7\x31\x3F\x30\x3D\x06\x03\x55\x04\x03\x0C\x36\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x0C\x02\x54\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x07\x0C\x06\x41\x4E\x4B\x41\x52\x41\x31\x56\x30\x54\x06\x03\x55\x04\x0A\x0C\x4D\x28\x63\x29\x20\x32\x30\x30\x35\x20\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x42\x69\x6C\x67\x69\x20\xC4\xB0\x6C\x65\x74\x69\xC5\x9F\x69\x6D\x20\x76\x65\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x47\xC3\xBC\x76\x65\x6E\x6C\x69\xC4\x9F\x69\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\x30\x1E\x17\x0D\x30\x35\x30\x35\x31\x33\x31\x30\x32\x37\x31\x37\x5A\x17\x0D\x31\x35\x30\x33\x32\x32\x31\x30\x32\x37\x31\x37\x5A\x30\x81\xB7\x31\x3F\x30\x3D\x06\x03\x55\x04\x03\x0C\x36\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x0C\x02\x54\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x07\x0C\x06\x41\x4E\x4B\x41\x52\x41\x31\x56\x30\x54\x06\x03\x55\x04\x0A\x0C\x4D\x28\x63\x29\x20\x32\x30\x30\x35\x20\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x42\x69\x6C\x67\x69\x20\xC4\xB0\x6C\x65\x74\x69\xC5\x9F\x69\x6D\x20\x76\x65\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x47\xC3\xBC\x76\x65\x6E\x6C\x69\xC4\x9F\x69\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\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\xCA\x52\x05\xD6\x63\x03\xD8\x1C\x5F\xDD\xD2\x7B\x5D\xF2\x0C\x60\x61\x5B\x6B\x3B\x74\x2B\x78\x0D\x7D\x45\xBD\x22\x74\xE8\x8C\x03\xC1\xC6\x11\x2A\x3D\x95\xBC\xA9\x94\xB0\xBB\x91\x97\xC8\x69\x7C\x84\xC5\xB4\x91\x6C\x6C\x13\x6A\xA4\x55\xAD\xA4\x85\xE8\x95\x7E\xB3\x00\xAF\x00\xC2\x05\x18\xF5\x70\x9D\x36\x8B\xAE\xCB\xE4\x1B\x81\x7F\x93\x88\xFB\x6A\x55\xBB\x7D\x85\x92\xCE\xBA\x58\x9F\xDB\x32\xC5\xBD\x5D\xEF\x22\x4A\x2F\x41\x07\x7E\x49\x61\xB3\x86\xEC\x4E\xA6\x41\x6E\x84\xBC\x03\xEC\xF5\x3B\x1C\xC8\x1F\xC2\xEE\xA8\xEE\xEA\x12\x4A\x8D\x14\xCF\xF3\x0A\xE0\x50\x39\xF9\x08\x35\xF8\x11\x59\xAD\xE7\x22\xEA\x4B\xCA\x14\x06\xDE\x42\xBA\xB2\x99\xF3\x2D\x54\x88\x10\x06\xEA\xE1\x1A\x3E\x3D\x67\x1F\xFB\xCE\xFB\x7C\x82\xE8\x11\x5D\x4A\xC1\xB9\x14\xEA\x54\xD9\x66\x9B\x7C\x89\x7D\x04\x9A\x62\xC9\xE9\x52\x3C\x9E\x9C\xEF\xD2\xF5\x26\xE4\xE6\xE5\x18\x7C\x8B\x6E\xDF\x6C\xCC\x78\x5B\x4F\x72\xB2\xCB\x5C\x3F\x8C\x05\x8D\xD1\x4C\x8C\xAD\x92\xC7\xE1\x78\x7F\x65\x6C\x49\x06\x50\x2C\x9E\x32\xC2\xD7\x4A\xC6\x75\x8A\x59\x4E\x75\x6F\x47\x5E\xC1\x02\x03\x01\x00\x01\xA3\x10\x30\x0E\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x15\xF5\x55\xFF\x37\x96\x80\x59\x21\xA4\xFC\xA1\x15\x4C\x20\xF6\xD4\x5F\xDA\x03\x24\xFC\xCF\x90\x1A\xF4\x21\x0A\x9A\xEE\x3A\xB1\x6A\xEF\xEF\xF8\x60\xD1\x4C\x36\x66\x45\x1D\xF3\x66\x02\x74\x04\x7B\x92\x30\xA8\xDE\x0A\x76\x0F\xEF\x95\x6E\xBD\xC9\x37\xE6\x1A\x0D\xAC\x89\x48\x5B\xCC\x83\x36\xC2\xF5\x46\x5C\x59\x82\x56\xB4\xD5\xFE\x23\xB4\xD8\x54\x1C\x44\xAB\xC4\xA7\xE5\x14\xCE\x3C\x41\x61\x7C\x43\xE6\xCD\xC4\x81\x09\x8B\x24\xFB\x54\x25\xD6\x16\xA8\x96\x0C\x67\x07\x6F\xB3\x50\x47\xE3\x1C\x24\x28\xDD\x2A\x98\xA4\x61\xFE\xDB\xEA\x12\x37\xBC\x01\x1A\x34\x85\xBD\x6E\x4F\xE7\x91\x72\x07\x44\x85\x1E\x58\xCA\x54\x44\xDD\xF7\xAC\xB9\xCB\x89\x21\x72\xDB\x8F\xC0\x69\x29\x97\x2A\xA3\xAE\x18\x23\x97\x1C\x41\x2A\x8B\x7C\x2A\xC1\x7C\x90\xE8\xA9\x28\xC0\xD3\x91\xC6\xAD\x28\x87\x40\x68\xB5\xFF\xEC\xA7\xD2\xD3\x38\x18\x9C\xD3\x7D\x69\x5D\xF0\xC6\xA5\x1E\x24\x1B\xA3\x47\xFC\x69\x07\x68\xE7\xE4\x9A\xB4\xED\x0F\xA1\x87\x87\x02\xCE\x87\xD2\x48\x4E\xE1\xBC\xFF\xCB\xF1\x72\x92\x44\x64\x03\x25\xEA\xDE\x5B\x6E\x9F\xC9\xF2\x4E\xAC\xDD\xC7", + ["O=T\C3\9CRKTRUST Bilgi \C4\B0leti\C5\9Fim ve Bili\C5\9Fim G\C3\BCvenli\C4\9Fi Hizmetleri A.\C5\9E. (c) Kas\C4\B1m 2005,L=Ankara,C=TR,CN=T\C3\9CRKTRUST Elektronik Sertifika Hizmet Sa\C4\9Flay\C4\B1c\C4\B1s\C4\B1"] = "\x30\x82\x04\x3C\x30\x82\x03\x24\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xBE\x31\x3F\x30\x3D\x06\x03\x55\x04\x03\x0C\x36\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x07\x0C\x06\x41\x6E\x6B\x61\x72\x61\x31\x5D\x30\x5B\x06\x03\x55\x04\x0A\x0C\x54\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x42\x69\x6C\x67\x69\x20\xC4\xB0\x6C\x65\x74\x69\xC5\x9F\x69\x6D\x20\x76\x65\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x47\xC3\xBC\x76\x65\x6E\x6C\x69\xC4\x9F\x69\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\x20\x28\x63\x29\x20\x4B\x61\x73\xC4\xB1\x6D\x20\x32\x30\x30\x35\x30\x1E\x17\x0D\x30\x35\x31\x31\x30\x37\x31\x30\x30\x37\x35\x37\x5A\x17\x0D\x31\x35\x30\x39\x31\x36\x31\x30\x30\x37\x35\x37\x5A\x30\x81\xBE\x31\x3F\x30\x3D\x06\x03\x55\x04\x03\x0C\x36\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x07\x0C\x06\x41\x6E\x6B\x61\x72\x61\x31\x5D\x30\x5B\x06\x03\x55\x04\x0A\x0C\x54\x54\xC3\x9C\x52\x4B\x54\x52\x55\x53\x54\x20\x42\x69\x6C\x67\x69\x20\xC4\xB0\x6C\x65\x74\x69\xC5\x9F\x69\x6D\x20\x76\x65\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x47\xC3\xBC\x76\x65\x6E\x6C\x69\xC4\x9F\x69\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\x20\x28\x63\x29\x20\x4B\x61\x73\xC4\xB1\x6D\x20\x32\x30\x30\x35\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\xA9\x36\x7E\xC3\x91\x43\x4C\xC3\x19\x98\x08\xC8\xC7\x58\x7B\x4F\x16\x8C\xA5\xCE\x49\x01\x1F\x73\x0E\xAC\x75\x13\xA6\xFA\x9E\x2C\x20\xDE\xD8\x90\x0E\x0A\xD1\x69\xD2\x27\xFB\xAA\x77\x9F\x27\x52\x25\xE2\xCB\x5D\xD8\xD8\x83\x50\x17\x7D\x8A\xB5\x82\x3F\x04\x8E\xB4\xD5\xF0\x49\xA7\x64\xB7\x1E\x2E\x5F\x20\x9C\x50\x75\x4F\xAF\xE1\xB5\x41\x14\xF4\x98\x92\x88\xC7\xE5\xE5\x64\x47\x61\x47\x79\xFD\xC0\x51\xF1\xC1\x99\xE7\xDC\xCE\x6A\xFB\xAF\xB5\x01\x30\xDC\x46\x1C\xEF\x8A\xEC\x95\xEF\xDC\xFF\xAF\x10\x1C\xEB\x9D\xD8\xB0\xAA\x6A\x85\x18\x0D\x17\xC9\x3E\xBF\xF1\x9B\xD0\x09\x89\x42\xFD\xA0\x42\xB4\x9D\x89\x51\x55\x29\xCF\x1B\x70\xBC\x84\x54\xAD\xC1\x13\x1F\x98\xF4\x2E\x76\x60\x8B\x5D\x3F\x9A\xAD\xCA\x0C\xBF\xA7\x56\x5B\x8F\x77\xB8\xD5\x9E\x79\x49\x92\x3F\xE0\xF1\x97\x24\x7A\x6C\x9B\x17\x0F\x6D\xEF\x53\x98\x91\x2B\xE4\x0F\xBE\x59\x79\x07\x78\xBB\x97\x95\xF4\x9F\x69\xD4\x58\x87\x0A\xA9\xE3\xCC\xB6\x58\x19\x9F\x26\x21\xB1\xC4\x59\x8D\xB2\x41\x75\xC0\xAD\x69\xCE\x9C\x00\x08\xF2\x36\xFF\x3E\xF0\xA1\x0F\x1A\xAC\x14\xFD\xA6\x60\x0F\x02\x03\x01\x00\x01\xA3\x43\x30\x41\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xD9\x37\xB3\x4E\x05\xFD\xD9\xCF\x9F\x12\x16\xAE\xB6\x89\x2F\xEB\x25\x3A\x88\x1C\x30\x0F\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x05\x03\x03\x07\x06\x00\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x72\x60\x96\xB7\xC9\xDC\xD8\x29\x5E\x23\x85\x5F\xB2\xB3\x2D\x76\xFB\x88\xD7\x17\xFE\x7B\x6D\x45\xB8\xF6\x85\x6C\x9F\x22\xFC\x2A\x10\x22\xEC\xAA\xB9\x30\xF6\xAB\x58\xD6\x39\x10\x31\x99\x29\x00\xBD\x89\x66\x41\xFB\x74\xDE\x91\xC1\x18\x0B\x9F\xB5\x61\xCB\x9D\x3A\xBE\xF5\xA8\x94\xA3\x22\x55\x6E\x17\x49\xFF\xD2\x29\xF1\x38\x26\x5D\xEF\xA5\xAA\x3A\xF9\x71\x7B\xE6\xDA\x58\x1D\xD3\x74\xC2\x01\xFA\x3E\x69\x58\x5F\xAD\xCB\x68\xBE\x14\x2E\x9B\x6C\xC0\xB6\xDC\xA0\x26\xFA\x77\x1A\xE2\x24\xDA\x1A\x37\xE0\x67\xAD\xD1\x73\x83\x0D\xA5\x1A\x1D\x6E\x12\x92\x7E\x84\x62\x00\x17\xBD\xBC\x25\x18\x57\xF2\xD7\xA9\x6F\x59\x88\xBC\x34\xB7\x2E\x85\x78\x9D\x96\xDC\x14\xC3\x2C\x8A\x52\x9B\x96\x8C\x52\x66\x3D\x86\x16\x8B\x47\xB8\x51\x09\x8C\xEA\x7D\xCD\x88\x72\xB3\x60\x33\xB1\xF0\x0A\x44\xEF\x0F\xF5\x09\x37\x88\x24\x0E\x2C\x6B\x20\x3A\xA2\xFA\x11\xF2\x40\x35\x9C\x44\x68\x63\x3B\xAC\x33\x6F\x63\xBC\x2C\xBB\xF2\xD2\xCB\x76\x7D\x7D\x88\xD8\x1D\xC8\x05\x1D\x6E\xBC\x94\xA9\x66\x8C\x77\x71\xC7\xFA\x91\xFA\x2F\x51\x9E\xE9\x39\x52\xB6\xE7\x04\x42", + ["CN=SwissSign Gold CA - G2,O=SwissSign AG,C=CH"] = "\x30\x82\x05\xBA\x30\x82\x03\xA2\xA0\x03\x02\x01\x02\x02\x09\x00\xBB\x40\x1C\x43\xF5\x5E\x4F\xB0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x41\x47\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x47\x6F\x6C\x64\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x36\x31\x30\x32\x35\x30\x38\x33\x30\x33\x35\x5A\x17\x0D\x33\x36\x31\x30\x32\x35\x30\x38\x33\x30\x33\x35\x5A\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x41\x47\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x47\x6F\x6C\x64\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xAF\xE4\xEE\x7E\x8B\x24\x0E\x12\x6E\xA9\x50\x2D\x16\x44\x3B\x92\x92\x5C\xCA\xB8\x5D\x84\x92\x42\x13\x2A\xBC\x65\x57\x82\x40\x3E\x57\x24\xCD\x50\x8B\x25\x2A\xB7\x6F\xFC\xEF\xA2\xD0\xC0\x1F\x02\x24\x4A\x13\x96\x8F\x23\x13\xE6\x28\x58\x00\xA3\x47\xC7\x06\xA7\x84\x23\x2B\xBB\xBD\x96\x2B\x7F\x55\xCC\x8B\xC1\x57\x1F\x0E\x62\x65\x0F\xDD\x3D\x56\x8A\x73\xDA\xAE\x7E\x6D\xBA\x81\x1C\x7E\x42\x8C\x20\x35\xD9\x43\x4D\x84\xFA\x84\xDB\x52\x2C\xF3\x0E\x27\x77\x0B\x6B\xBF\x11\x2F\x72\x78\x9F\x2E\xD8\x3E\xE6\x18\x37\x5A\x2A\x72\xF9\xDA\x62\x90\x92\x95\xCA\x1F\x9C\xE9\xB3\x3C\x2B\xCB\xF3\x01\x13\xBF\x5A\xCF\xC1\xB5\x0A\x60\xBD\xDD\xB5\x99\x64\x53\xB8\xA0\x96\xB3\x6F\xE2\x26\x77\x91\x8C\xE0\x62\x10\x02\x9F\x34\x0F\xA4\xD5\x92\x33\x51\xDE\xBE\x8D\xBA\x84\x7A\x60\x3C\x6A\xDB\x9F\x2B\xEC\xDE\xDE\x01\x3F\x6E\x4D\xE5\x50\x86\xCB\xB4\xAF\xED\x44\x40\xC5\xCA\x5A\x8C\xDA\xD2\x2B\x7C\xA8\xEE\xBE\xA6\xE5\x0A\xAA\x0E\xA5\xDF\x05\x52\xB7\x55\xC7\x22\x5D\x32\x6A\x97\x97\x63\x13\xDB\xC9\xDB\x79\x36\x7B\x85\x3A\x4A\xC5\x52\x89\xF9\x24\xE7\x9D\x77\xA9\x82\xFF\x55\x1C\xA5\x71\x69\x2B\xD1\x02\x24\xF2\xB3\x26\xD4\x6B\xDA\x04\x55\xE5\xC1\x0A\xC7\x6D\x30\x37\x90\x2A\xE4\x9E\x14\x33\x5E\x16\x17\x55\xC5\x5B\xB5\xCB\x34\x89\x92\xF1\x9D\x26\x8F\xA1\x07\xD4\xC6\xB2\x78\x50\xDB\x0C\x0C\x0B\x7C\x0B\x8C\x41\xD7\xB9\xE9\xDD\x8C\x88\xF7\xA3\x4D\xB2\x32\xCC\xD8\x17\xDA\xCD\xB7\xCE\x66\x9D\xD4\xFD\x5E\xFF\xBD\x97\x3E\x29\x75\xE7\x7E\xA7\x62\x58\xAF\x25\x34\xA5\x41\xC7\x3D\xBC\x0D\x50\xCA\x03\x03\x0F\x08\x5A\x1F\x95\x73\x78\x62\xBF\xAF\x72\x14\x69\x0E\xA5\xE5\x03\x0E\x78\x8E\x26\x28\x42\xF0\x07\x0B\x62\x20\x10\x67\x39\x46\xFA\xA9\x03\xCC\x04\x38\x7A\x66\xEF\x20\x83\xB5\x8C\x4A\x56\x8E\x91\x00\xFC\x8E\x5C\x82\xDE\x88\xA0\xC3\xE2\x68\x6E\x7D\x8D\xEF\x3C\xDD\x65\xF4\x5D\xAC\x51\xEF\x24\x80\xAE\xAA\x56\x97\x6F\xF9\xAD\x7D\xDA\x61\x3F\x98\x77\x3C\xA5\x91\xB6\x1C\x8C\x26\xDA\x65\xA2\x09\x6D\xC1\xE2\x54\xE3\xB9\xCA\x4C\x4C\x80\x8F\x77\x7B\x60\x9A\x1E\xDF\xB6\xF2\x48\x1E\x0E\xBA\x4E\x54\x6D\x98\xE0\xE1\xA2\x1A\xA2\x77\x50\xCF\xC4\x63\x92\xEC\x47\x19\x9D\xEB\xE6\x6B\xCE\xC1\x02\x03\x01\x00\x01\xA3\x81\xAC\x30\x81\xA9\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x5B\x25\x7B\x96\xA4\x65\x51\x7E\xB8\x39\xF3\xC0\x78\x66\x5E\xE8\x3A\xE7\xF0\xEE\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x5B\x25\x7B\x96\xA4\x65\x51\x7E\xB8\x39\xF3\xC0\x78\x66\x5E\xE8\x3A\xE7\xF0\xEE\x30\x46\x06\x03\x55\x1D\x20\x04\x3F\x30\x3D\x30\x3B\x06\x09\x60\x85\x74\x01\x59\x01\x02\x01\x01\x30\x2E\x30\x2C\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x20\x68\x74\x74\x70\x3A\x2F\x2F\x72\x65\x70\x6F\x73\x69\x74\x6F\x72\x79\x2E\x73\x77\x69\x73\x73\x73\x69\x67\x6E\x2E\x63\x6F\x6D\x2F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x27\xBA\xE3\x94\x7C\xF1\xAE\xC0\xDE\x17\xE6\xE5\xD8\xD5\xF5\x54\xB0\x83\xF4\xBB\xCD\x5E\x05\x7B\x4F\x9F\x75\x66\xAF\x3C\xE8\x56\x7E\xFC\x72\x78\x38\x03\xD9\x2B\x62\x1B\x00\xB9\xF8\xE9\x60\xCD\xCC\xCE\x51\x8A\xC7\x50\x31\x6E\xE1\x4A\x7E\x18\x2F\x69\x59\xB6\x3D\x64\x81\x2B\xE3\x83\x84\xE6\x22\x87\x8E\x7D\xE0\xEE\x02\x99\x61\xB8\x1E\xF4\xB8\x2B\x88\x12\x16\x84\xC2\x31\x93\x38\x96\x31\xA6\xB9\x3B\x53\x3F\xC3\x24\x93\x56\x5B\x69\x92\xEC\xC5\xC1\xBB\x38\x00\xE3\xEC\x17\xA9\xB8\xDC\xC7\x7C\x01\x83\x9F\x32\x47\xBA\x52\x22\x34\x1D\x32\x7A\x09\x56\xA7\x7C\x25\x36\xA9\x3D\x4B\xDA\xC0\x82\x6F\x0A\xBB\x12\xC8\x87\x4B\x27\x11\xF9\x1E\x2D\xC7\x93\x3F\x9E\xDB\x5F\x26\x6B\x52\xD9\x2E\x8A\xF1\x14\xC6\x44\x8D\x15\xA9\xB7\xBF\xBD\xDE\xA6\x1A\xEE\xAE\x2D\xFB\x48\x77\x17\xFE\xBB\xEC\xAF\x18\xF5\x2A\x51\xF0\x39\x84\x97\x95\x6C\x6E\x1B\xC3\x2B\xC4\x74\x60\x79\x25\xB0\x0A\x27\xDF\xDF\x5E\xD2\x39\xCF\x45\x7D\x42\x4B\xDF\xB3\x2C\x1E\xC5\xC6\x5D\xCA\x55\x3A\xA0\x9C\x69\x9A\x8F\xDA\xEF\xB2\xB0\x3C\x9F\x87\x6C\x12\x2B\x65\x70\x15\x52\x31\x1A\x24\xCF\x6F\x31\x23\x50\x1F\x8C\x4F\x8F\x23\xC3\x74\x41\x63\x1C\x55\xA8\x14\xDD\x3E\xE0\x51\x50\xCF\xF1\x1B\x30\x56\x0E\x92\xB0\x82\x85\xD8\x83\xCB\x22\x64\xBC\x2D\xB8\x25\xD5\x54\xA2\xB8\x06\xEA\xAD\x92\xA4\x24\xA0\xC1\x86\xB5\x4A\x13\x6A\x47\xCF\x2E\x0B\x56\x95\x54\xCB\xCE\x9A\xDB\x6A\xB4\xA6\xB2\xDB\x41\x08\x86\x27\x77\xF7\x6A\xA0\x42\x6C\x0B\x38\xCE\xD7\x75\x50\x32\x92\xC2\xDF\x2B\x30\x22\x48\xD0\xD5\x41\x38\x25\x5D\xA4\xE9\x5D\x9F\xC6\x94\x75\xD0\x45\xFD\x30\x97\x43\x8F\x90\xAB\x0A\xC7\x86\x73\x60\x4A\x69\x2D\xDE\xA5\x78\xD7\x06\xDA\x6A\x9E\x4B\x3E\x77\x3A\x20\x13\x22\x01\xD0\xBF\x68\x9E\x63\x60\x6B\x35\x4D\x0B\x6D\xBA\xA1\x3D\xC0\x93\xE0\x7F\x23\xB3\x55\xAD\x72\x25\x4E\x46\xF9\xD2\x16\xEF\xB0\x64\xC1\x01\x9E\xE9\xCA\xA0\x6A\x98\x0E\xCF\xD8\x60\xF2\x2F\x49\xB8\xE4\x42\xE1\x38\x35\x16\xF4\xC8\x6E\x4F\xF7\x81\x56\xE8\xBA\xA3\xBE\x23\xAF\xAE\xFD\x6F\x03\xE0\x02\x3B\x30\x76\xFA\x1B\x6D\x41\xCF\x01\xB1\xE9\xB8\xC9\x66\xF4\xDB\x26\xF3\x3A\xA4\x74\xF2\x49\x24\x5B\xC9\xB0\xD0\x57\xC1\xFA\x3E\x7A\xE1\x97\xC9", + ["CN=SwissSign Silver CA - G2,O=SwissSign AG,C=CH"] = "\x30\x82\x05\xBD\x30\x82\x03\xA5\xA0\x03\x02\x01\x02\x02\x08\x4F\x1B\xD4\x2F\x54\xBB\x2F\x4B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x47\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x41\x47\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x53\x69\x6C\x76\x65\x72\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x36\x31\x30\x32\x35\x30\x38\x33\x32\x34\x36\x5A\x17\x0D\x33\x36\x31\x30\x32\x35\x30\x38\x33\x32\x34\x36\x5A\x30\x47\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x41\x47\x31\x21\x30\x1F\x06\x03\x55\x04\x03\x13\x18\x53\x77\x69\x73\x73\x53\x69\x67\x6E\x20\x53\x69\x6C\x76\x65\x72\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC4\xF1\x87\x7F\xD3\x78\x31\xF7\x38\xC9\xF8\xC3\x99\x43\xBC\xC7\xF7\xBC\x37\xE7\x4E\x71\xBA\x4B\x8F\xA5\x73\x1D\x5C\x6E\x98\xAE\x03\x57\xAE\x38\x37\x43\x2F\x17\x3D\x1F\xC8\xCE\x68\x10\xC1\x78\xAE\x19\x03\x2B\x10\xFA\x2C\x79\x83\xF6\xE8\xB9\x68\xB9\x55\xF2\x04\x44\xA7\x39\xF9\xFC\x04\x8B\x1E\xF1\xA2\x4D\x27\xF9\x61\x7B\xBA\xB7\xE5\xA2\x13\xB6\xEB\x61\x3E\xD0\x6C\xD1\xE6\xFB\xFA\x5E\xED\x1D\xB4\x9E\xA0\x35\x5B\xA1\x92\xCB\xF0\x49\x92\xFE\x85\x0A\x05\x3E\xE6\xD9\x0B\xE2\x4F\xBB\xDC\x95\x37\xFC\x91\xE9\x32\x35\x22\xD1\x1F\x3A\x4E\x27\x85\x9D\xB0\x15\x94\x32\xDA\x61\x0D\x47\x4D\x60\x42\xAE\x92\x47\xE8\x83\x5A\x50\x58\xE9\x8A\x8B\xB9\x5D\xA1\xDC\xDD\x99\x4A\x1F\x36\x67\xBB\x48\xE4\x83\xB6\x37\xEB\x48\x3A\xAF\x0F\x67\x8F\x17\x07\xE8\x04\xCA\xEF\x6A\x31\x87\xD4\xC0\xB6\xF9\x94\x71\x7B\x67\x64\xB8\xB6\x91\x4A\x42\x7B\x65\x2E\x30\x6A\x0C\xF5\x90\xEE\x95\xE6\xF2\xCD\x82\xEC\xD9\xA1\x4A\xEC\xF6\xB2\x4B\xE5\x45\x85\xE6\x6D\x78\x93\x04\x2E\x9C\x82\x6D\x36\xA9\xC4\x31\x64\x1F\x86\x83\x0B\x2A\xF4\x35\x0A\x78\xC9\x55\xCF\x41\xB0\x47\xE9\x30\x9F\x99\xBE\x61\xA8\x06\x84\xB9\x28\x7A\x5F\x38\xD9\x1B\xA9\x38\xB0\x83\x7F\x73\xC1\xC3\x3B\x48\x2A\x82\x0F\x21\x9B\xB8\xCC\xA8\x35\xC3\x84\x1B\x83\xB3\x3E\xBE\xA4\x95\x69\x01\x3A\x89\x00\x78\x04\xD9\xC9\xF4\x99\x19\xAB\x56\x7E\x5B\x8B\x86\x39\x15\x91\xA4\x10\x2C\x09\x32\x80\x60\xB3\x93\xC0\x2A\xB6\x18\x0B\x9D\x7E\x8D\x49\xF2\x10\x4A\x7F\xF9\xD5\x46\x2F\x19\x92\xA3\x99\xA7\x26\xAC\xBB\x8C\x3C\xE6\x0E\xBC\x47\x07\xDC\x73\x51\xF1\x70\x64\x2F\x08\xF9\xB4\x47\x1D\x30\x6C\x44\xEA\x29\x37\x85\x92\x68\x66\xBC\x83\x38\xFE\x7B\x39\x2E\xD3\x50\xF0\x1F\xFB\x5E\x60\xB6\xA9\xA6\xFA\x27\x41\xF1\x9B\x18\x72\xF2\xF5\x84\x74\x4A\xC9\x67\xC4\x54\xAE\x48\x64\xDF\x8C\xD1\x6E\xB0\x1D\xE1\x07\x8F\x08\x1E\x99\x9C\x71\xE9\x4C\xD8\xA5\xF7\x47\x12\x1F\x74\xD1\x51\x9E\x86\xF3\xC2\xA2\x23\x40\x0B\x73\xDB\x4B\xA6\xE7\x73\x06\x8C\xC1\xA0\xE9\xC1\x59\xAC\x46\xFA\xE6\x2F\xF8\xCF\x71\x9C\x46\x6D\xB9\xC4\x15\x8D\x38\x79\x03\x45\x48\xEF\xC4\x5D\xD7\x08\xEE\x87\x39\x22\x86\xB2\x0D\x0F\x58\x43\xF7\x71\xA9\x48\x2E\xFD\xEA\xD6\x1F\x02\x03\x01\x00\x01\xA3\x81\xAC\x30\x81\xA9\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x17\xA0\xCD\xC1\xE4\x41\xB6\x3A\x5B\x3B\xCB\x45\x9D\xBD\x1C\xC2\x98\xFA\x86\x58\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x17\xA0\xCD\xC1\xE4\x41\xB6\x3A\x5B\x3B\xCB\x45\x9D\xBD\x1C\xC2\x98\xFA\x86\x58\x30\x46\x06\x03\x55\x1D\x20\x04\x3F\x30\x3D\x30\x3B\x06\x09\x60\x85\x74\x01\x59\x01\x03\x01\x01\x30\x2E\x30\x2C\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x20\x68\x74\x74\x70\x3A\x2F\x2F\x72\x65\x70\x6F\x73\x69\x74\x6F\x72\x79\x2E\x73\x77\x69\x73\x73\x73\x69\x67\x6E\x2E\x63\x6F\x6D\x2F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x73\xC6\x81\xE0\x27\xD2\x2D\x0F\xE0\x95\x30\xE2\x9A\x41\x7F\x50\x2C\x5F\x5F\x62\x61\xA9\x86\x6A\x69\x18\x0C\x74\x49\xD6\x5D\x84\xEA\x41\x52\x18\x6F\x58\xAD\x50\x56\x20\x6A\xC6\xBD\x28\x69\x58\x91\xDC\x91\x11\x35\xA9\x3A\x1D\xBC\x1A\xA5\x60\x9E\xD8\x1F\x7F\x45\x91\x69\xD9\x7E\xBB\x78\x72\xC1\x06\x0F\x2A\xCE\x8F\x85\x70\x61\xAC\xA0\xCD\x0B\xB8\x39\x29\x56\x84\x32\x4E\x86\xBB\x3D\xC4\x2A\xD9\xD7\x1F\x72\xEE\xFE\x51\xA1\x22\x41\xB1\x71\x02\x63\x1A\x82\xB0\x62\xAB\x5E\x57\x12\x1F\xDF\xCB\xDD\x75\xA0\xC0\x5D\x79\x90\x8C\x1B\xE0\x50\xE6\xDE\x31\xFE\x98\x7B\x70\x5F\xA5\x90\xD8\xAD\xF8\x02\xB6\x6F\xD3\x60\xDD\x40\x4B\x22\xC5\x3D\xAD\x3A\x7A\x9F\x1A\x1A\x47\x91\x79\x33\xBA\x82\xDC\x32\x69\x03\x96\x6E\x1F\x4B\xF0\x71\xFE\xE3\x67\x72\xA0\xB1\xBF\x5C\x8B\xE4\xFA\x99\x22\xC7\x84\xB9\x1B\x8D\x23\x97\x3F\xED\x25\xE0\xCF\x65\xBB\xF5\x61\x04\xEF\xDD\x1E\xB2\x5A\x41\x22\x5A\xA1\x9F\x5D\x2C\xE8\x5B\xC9\x6D\xA9\x0C\x0C\x78\xAA\x60\xC6\x56\x8F\x01\x5A\x0C\x68\xBC\x69\x19\x79\xC4\x1F\x7E\x97\x05\xBF\xC5\xE9\x24\x51\x5E\xD4\xD5\x4B\x53\xED\xD9\x23\x5A\x36\x03\x65\xA3\xC1\x03\xAD\x41\x30\xF3\x46\x1B\x85\x90\xAF\x65\xB5\xD5\xB1\xE4\x16\x5B\x78\x75\x1D\x97\x7A\x6D\x59\xA9\x2A\x8F\x7B\xDE\xC3\x87\x89\x10\x99\x49\x73\x78\xC8\x3D\xBD\x51\x35\x74\x2A\xD5\xF1\x7E\x69\x1B\x2A\xBB\x3B\xBD\x25\xB8\x9A\x5A\x3D\x72\x61\x90\x66\x87\xEE\x0C\xD6\x4D\xD4\x11\x74\x0B\x6A\xFE\x0B\x03\xFC\xA3\x55\x57\x89\xFE\x4A\xCB\xAE\x5B\x17\x05\xC8\xF2\x8D\x23\x31\x53\x38\xD2\x2D\x6A\x3F\x82\xB9\x8D\x08\x6A\xF7\x5E\x41\x74\x6E\xC3\x11\x7E\x07\xAC\x29\x60\x91\x3F\x38\xCA\x57\x10\x0D\xBD\x30\x2F\xC7\xA5\xE6\x41\xA0\xDA\xAE\x05\x87\x9A\xA0\xA4\x65\x6C\x4C\x09\x0C\x89\xBA\xB8\xD3\xB9\xC0\x93\x8A\x30\xFA\x8D\xE5\x9A\x6B\x15\x01\x4E\x67\xAA\xDA\x62\x56\x3E\x84\x08\x66\xD2\xC4\x36\x7D\xA7\x3E\x10\xFC\x88\xE0\xD4\x80\xE5\x00\xBD\xAA\xF3\x4E\x06\xA3\x7A\x6A\xF9\x62\x72\xE3\x09\x4F\xEB\x9B\x0E\x01\x23\xF1\x9F\xBB\x7C\xDC\xDC\x6C\x11\x97\x25\xB2\xF2\xB4\x63\x14\xD2\x06\x2A\x67\x8C\x83\xF5\xCE\xEA\x07\xD8\x9A\x6A\x1E\xEC\xE4\x0A\xBB\x2A\x4C\xEB\x09\x60\x39\xCE\xCA\x62\xD8\x2E\x6E", + ["CN=GeoTrust Primary Certification Authority,O=GeoTrust Inc.,C=US"] = "\x30\x82\x03\x7C\x30\x82\x02\x64\xA0\x03\x02\x01\x02\x02\x10\x18\xAC\xB5\x6A\xFD\x69\xB6\x15\x3A\x63\x6C\xAF\xDA\xFA\xC4\xA1\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x58\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x03\x13\x28\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x36\x31\x31\x32\x37\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x58\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x03\x13\x28\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xBE\xB8\x15\x7B\xFF\xD4\x7C\x7D\x67\xAD\x83\x64\x7B\xC8\x42\x53\x2D\xDF\xF6\x84\x08\x20\x61\xD6\x01\x59\x6A\x9C\x44\x11\xAF\xEF\x76\xFD\x95\x7E\xCE\x61\x30\xBB\x7A\x83\x5F\x02\xBD\x01\x66\xCA\xEE\x15\x8D\x6F\xA1\x30\x9C\xBD\xA1\x85\x9E\x94\x3A\xF3\x56\x88\x00\x31\xCF\xD8\xEE\x6A\x96\x02\xD9\xED\x03\x8C\xFB\x75\x6D\xE7\xEA\xB8\x55\x16\x05\x16\x9A\xF4\xE0\x5E\xB1\x88\xC0\x64\x85\x5C\x15\x4D\x88\xC7\xB7\xBA\xE0\x75\xE9\xAD\x05\x3D\x9D\xC7\x89\x48\xE0\xBB\x28\xC8\x03\xE1\x30\x93\x64\x5E\x52\xC0\x59\x70\x22\x35\x57\x88\x8A\xF1\x95\x0A\x83\xD7\xBC\x31\x73\x01\x34\xED\xEF\x46\x71\xE0\x6B\x02\xA8\x35\x72\x6B\x97\x9B\x66\xE0\xCB\x1C\x79\x5F\xD8\x1A\x04\x68\x1E\x47\x02\xE6\x9D\x60\xE2\x36\x97\x01\xDF\xCE\x35\x92\xDF\xBE\x67\xC7\x6D\x77\x59\x3B\x8F\x9D\xD6\x90\x15\x94\xBC\x42\x34\x10\xC1\x39\xF9\xB1\x27\x3E\x7E\xD6\x8A\x75\xC5\xB2\xAF\x96\xD3\xA2\xDE\x9B\xE4\x98\xBE\x7D\xE1\xE9\x81\xAD\xB6\x6F\xFC\xD7\x0E\xDA\xE0\x34\xB0\x0D\x1A\x77\xE7\xE3\x08\x98\xEF\x58\xFA\x9C\x84\xB7\x36\xAF\xC2\xDF\xAC\xD2\xF4\x10\x06\x70\x71\x35\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x2C\xD5\x50\x41\x97\x15\x8B\xF0\x8F\x36\x61\x5B\x4A\xFB\x6B\xD9\x99\xC9\x33\x92\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5A\x70\x7F\x2C\xDD\xB7\x34\x4F\xF5\x86\x51\xA9\x26\xBE\x4B\xB8\xAA\xF1\x71\x0D\xDC\x61\xC7\xA0\xEA\x34\x1E\x7A\x77\x0F\x04\x35\xE8\x27\x8F\x6C\x90\xBF\x91\x16\x24\x46\x3E\x4A\x4E\xCE\x2B\x16\xD5\x0B\x52\x1D\xFC\x1F\x67\xA2\x02\x45\x31\x4F\xCE\xF3\xFA\x03\xA7\x79\x9D\x53\x6A\xD9\xDA\x63\x3A\xF8\x80\xD7\xD3\x99\xE1\xA5\xE1\xBE\xD4\x55\x71\x98\x35\x3A\xBE\x93\xEA\xAE\xAD\x42\xB2\x90\x6F\xE0\xFC\x21\x4D\x35\x63\x33\x89\x49\xD6\x9B\x4E\xCA\xC7\xE7\x4E\x09\x00\xF7\xDA\xC7\xEF\x99\x62\x99\x77\xB6\x95\x22\x5E\x8A\xA0\xAB\xF4\xB8\x78\x98\xCA\x38\x19\x99\xC9\x72\x9E\x78\xCD\x4B\xAC\xAF\x19\xA0\x73\x12\x2D\xFC\xC2\x41\xBA\x81\x91\xDA\x16\x5A\x31\xB7\xF9\xB4\x71\x80\x12\x48\x99\x72\x73\x5A\x59\x53\xC1\x63\x52\x33\xED\xA7\xC9\xD2\x39\x02\x70\xFA\xE0\xB1\x42\x66\x29\xAA\x9B\x51\xED\x30\x54\x22\x14\x5F\xD9\xAB\x1D\xC1\xE4\x94\xF0\xF8\xF5\x2B\xF7\xEA\xCA\x78\x46\xD6\xB8\x91\xFD\xA6\x0D\x2B\x1A\x14\x01\x3E\x80\xF0\x42\xA0\x95\x07\x5E\x6D\xCD\xCC\x4B\xA4\x45\x8D\xAB\x12\xE8\xB3\xDE\x5A\xE5\xA0\x7C\xE8\x0F\x22\x1D\x5A\xE9\x59", + ["CN=thawte Primary Root CA,OU=(c) 2006 thawte\, Inc. - For authorized use only,OU=Certification Services Division,O=thawte\, Inc.,C=US"] = "\x30\x82\x04\x20\x30\x82\x03\x08\xA0\x03\x02\x01\x02\x02\x10\x34\x4E\xD5\x57\x20\xD5\xED\xEC\x49\xF4\x2F\xCE\x37\xDB\x2B\x6D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xA9\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x38\x30\x36\x06\x03\x55\x04\x0B\x13\x2F\x28\x63\x29\x20\x32\x30\x30\x36\x20\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x31\x31\x31\x37\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xA9\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x38\x30\x36\x06\x03\x55\x04\x0B\x13\x2F\x28\x63\x29\x20\x32\x30\x30\x36\x20\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xA0\xF0\xFB\x80\x59\xD4\x9C\xC7\xA4\xCF\x9D\xA1\x59\x73\x09\x10\x45\x0C\x0D\x2C\x6E\x68\xF1\x6C\x5B\x48\x68\x49\x59\x37\xFC\x0B\x33\x19\xC2\x77\x7F\xCC\x10\x2D\x95\x34\x1C\xE6\xEB\x4D\x09\xA7\x1C\xD2\xB8\xC9\x97\x36\x02\xB7\x89\xD4\x24\x5F\x06\xC0\xCC\x44\x94\x94\x8D\x02\x62\x6F\xEB\x5A\xDD\x11\x8D\x28\x9A\x5C\x84\x90\x10\x7A\x0D\xBD\x74\x66\x2F\x6A\x38\xA0\xE2\xD5\x54\x44\xEB\x1D\x07\x9F\x07\xBA\x6F\xEE\xE9\xFD\x4E\x0B\x29\xF5\x3E\x84\xA0\x01\xF1\x9C\xAB\xF8\x1C\x7E\x89\xA4\xE8\xA1\xD8\x71\x65\x0D\xA3\x51\x7B\xEE\xBC\xD2\x22\x60\x0D\xB9\x5B\x9D\xDF\xBA\xFC\x51\x5B\x0B\xAF\x98\xB2\xE9\x2E\xE9\x04\xE8\x62\x87\xDE\x2B\xC8\xD7\x4E\xC1\x4C\x64\x1E\xDD\xCF\x87\x58\xBA\x4A\x4F\xCA\x68\x07\x1D\x1C\x9D\x4A\xC6\xD5\x2F\x91\xCC\x7C\x71\x72\x1C\xC5\xC0\x67\xEB\x32\xFD\xC9\x92\x5C\x94\xDA\x85\xC0\x9B\xBF\x53\x7D\x2B\x09\xF4\x8C\x9D\x91\x1F\x97\x6A\x52\xCB\xDE\x09\x36\xA4\x77\xD8\x7B\x87\x50\x44\xD5\x3E\x6E\x29\x69\xFB\x39\x49\x26\x1E\x09\xA5\x80\x7B\x40\x2D\xEB\xE8\x27\x85\xC9\xFE\x61\xFD\x7E\xE6\x7C\x97\x1D\xD5\x9D\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x7B\x5B\x45\xCF\xAF\xCE\xCB\x7A\xFD\x31\x92\x1A\x6A\xB6\xF3\x46\xEB\x57\x48\x50\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x79\x11\xC0\x4B\xB3\x91\xB6\xFC\xF0\xE9\x67\xD4\x0D\x6E\x45\xBE\x55\xE8\x93\xD2\xCE\x03\x3F\xED\xDA\x25\xB0\x1D\x57\xCB\x1E\x3A\x76\xA0\x4C\xEC\x50\x76\xE8\x64\x72\x0C\xA4\xA9\xF1\xB8\x8B\xD6\xD6\x87\x84\xBB\x32\xE5\x41\x11\xC0\x77\xD9\xB3\x60\x9D\xEB\x1B\xD5\xD1\x6E\x44\x44\xA9\xA6\x01\xEC\x55\x62\x1D\x77\xB8\x5C\x8E\x48\x49\x7C\x9C\x3B\x57\x11\xAC\xAD\x73\x37\x8E\x2F\x78\x5C\x90\x68\x47\xD9\x60\x60\xE6\xFC\x07\x3D\x22\x20\x17\xC4\xF7\x16\xE9\xC4\xD8\x72\xF9\xC8\x73\x7C\xDF\x16\x2F\x15\xA9\x3E\xFD\x6A\x27\xB6\xA1\xEB\x5A\xBA\x98\x1F\xD5\xE3\x4D\x64\x0A\x9D\x13\xC8\x61\xBA\xF5\x39\x1C\x87\xBA\xB8\xBD\x7B\x22\x7F\xF6\xFE\xAC\x40\x79\xE5\xAC\x10\x6F\x3D\x8F\x1B\x79\x76\x8B\xC4\x37\xB3\x21\x18\x84\xE5\x36\x00\xEB\x63\x20\x99\xB9\xE9\xFE\x33\x04\xBB\x41\xC8\xC1\x02\xF9\x44\x63\x20\x9E\x81\xCE\x42\xD3\xD6\x3F\x2C\x76\xD3\x63\x9C\x59\xDD\x8F\xA6\xE1\x0E\xA0\x2E\x41\xF7\x2E\x95\x47\xCF\xBC\xFD\x33\xF3\xF6\x0B\x61\x7E\x7E\x91\x2B\x81\x47\xC2\x27\x30\xEE\xA7\x10\x5D\x37\x8F\x5C\x39\x2B\xE4\x04\xF0\x7B\x8D\x56\x8C\x68", + ["CN=VeriSign Class 3 Public Primary Certification Authority - G5,OU=(c) 2006 VeriSign\, Inc. - For authorized use only,OU=VeriSign Trust Network,O=VeriSign\, Inc.,C=US"] = "\x30\x82\x04\xD3\x30\x82\x03\xBB\xA0\x03\x02\x01\x02\x02\x10\x18\xDA\xD1\x9E\x26\x7D\xE8\xBB\x4A\x21\x58\xCD\xCC\x6B\x3B\x4A\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x32\x30\x30\x36\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x35\x30\x1E\x17\x0D\x30\x36\x31\x31\x30\x38\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x36\x30\x37\x31\x36\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x32\x30\x30\x36\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x35\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\xAF\x24\x08\x08\x29\x7A\x35\x9E\x60\x0C\xAA\xE7\x4B\x3B\x4E\xDC\x7C\xBC\x3C\x45\x1C\xBB\x2B\xE0\xFE\x29\x02\xF9\x57\x08\xA3\x64\x85\x15\x27\xF5\xF1\xAD\xC8\x31\x89\x5D\x22\xE8\x2A\xAA\xA6\x42\xB3\x8F\xF8\xB9\x55\xB7\xB1\xB7\x4B\xB3\xFE\x8F\x7E\x07\x57\xEC\xEF\x43\xDB\x66\x62\x15\x61\xCF\x60\x0D\xA4\xD8\xDE\xF8\xE0\xC3\x62\x08\x3D\x54\x13\xEB\x49\xCA\x59\x54\x85\x26\xE5\x2B\x8F\x1B\x9F\xEB\xF5\xA1\x91\xC2\x33\x49\xD8\x43\x63\x6A\x52\x4B\xD2\x8F\xE8\x70\x51\x4D\xD1\x89\x69\x7B\xC7\x70\xF6\xB3\xDC\x12\x74\xDB\x7B\x5D\x4B\x56\xD3\x96\xBF\x15\x77\xA1\xB0\xF4\xA2\x25\xF2\xAF\x1C\x92\x67\x18\xE5\xF4\x06\x04\xEF\x90\xB9\xE4\x00\xE4\xDD\x3A\xB5\x19\xFF\x02\xBA\xF4\x3C\xEE\xE0\x8B\xEB\x37\x8B\xEC\xF4\xD7\xAC\xF2\xF6\xF0\x3D\xAF\xDD\x75\x91\x33\x19\x1D\x1C\x40\xCB\x74\x24\x19\x21\x93\xD9\x14\xFE\xAC\x2A\x52\xC7\x8F\xD5\x04\x49\xE4\x8D\x63\x47\x88\x3C\x69\x83\xCB\xFE\x47\xBD\x2B\x7E\x4F\xC5\x95\xAE\x0E\x9D\xD4\xD1\x43\xC0\x67\x73\xE3\x14\x08\x7E\xE5\x3F\x9F\x73\xB8\x33\x0A\xCF\x5D\x3F\x34\x87\x96\x8A\xEE\x53\xE8\x25\x15\x02\x03\x01\x00\x01\xA3\x81\xB2\x30\x81\xAF\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x6D\x06\x08\x2B\x06\x01\x05\x05\x07\x01\x0C\x04\x61\x30\x5F\xA1\x5D\xA0\x5B\x30\x59\x30\x57\x30\x55\x16\x09\x69\x6D\x61\x67\x65\x2F\x67\x69\x66\x30\x21\x30\x1F\x30\x07\x06\x05\x2B\x0E\x03\x02\x1A\x04\x14\x8F\xE5\xD3\x1A\x86\xAC\x8D\x8E\x6B\xC3\xCF\x80\x6A\xD4\x48\x18\x2C\x7B\x19\x2E\x30\x25\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x6C\x6F\x67\x6F\x2E\x76\x65\x72\x69\x73\x69\x67\x6E\x2E\x63\x6F\x6D\x2F\x76\x73\x6C\x6F\x67\x6F\x2E\x67\x69\x66\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x7F\xD3\x65\xA7\xC2\xDD\xEC\xBB\xF0\x30\x09\xF3\x43\x39\xFA\x02\xAF\x33\x31\x33\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x93\x24\x4A\x30\x5F\x62\xCF\xD8\x1A\x98\x2F\x3D\xEA\xDC\x99\x2D\xBD\x77\xF6\xA5\x79\x22\x38\xEC\xC4\xA7\xA0\x78\x12\xAD\x62\x0E\x45\x70\x64\xC5\xE7\x97\x66\x2D\x98\x09\x7E\x5F\xAF\xD6\xCC\x28\x65\xF2\x01\xAA\x08\x1A\x47\xDE\xF9\xF9\x7C\x92\x5A\x08\x69\x20\x0D\xD9\x3E\x6D\x6E\x3C\x0D\x6E\xD8\xE6\x06\x91\x40\x18\xB9\xF8\xC1\xED\xDF\xDB\x41\xAA\xE0\x96\x20\xC9\xCD\x64\x15\x38\x81\xC9\x94\xEE\xA2\x84\x29\x0B\x13\x6F\x8E\xDB\x0C\xDD\x25\x02\xDB\xA4\x8B\x19\x44\xD2\x41\x7A\x05\x69\x4A\x58\x4F\x60\xCA\x7E\x82\x6A\x0B\x02\xAA\x25\x17\x39\xB5\xDB\x7F\xE7\x84\x65\x2A\x95\x8A\xBD\x86\xDE\x5E\x81\x16\x83\x2D\x10\xCC\xDE\xFD\xA8\x82\x2A\x6D\x28\x1F\x0D\x0B\xC4\xE5\xE7\x1A\x26\x19\xE1\xF4\x11\x6F\x10\xB5\x95\xFC\xE7\x42\x05\x32\xDB\xCE\x9D\x51\x5E\x28\xB6\x9E\x85\xD3\x5B\xEF\xA5\x7D\x45\x40\x72\x8E\xB7\x0E\x6B\x0E\x06\xFB\x33\x35\x48\x71\xB8\x9D\x27\x8B\xC4\x65\x5F\x0D\x86\x76\x9C\x44\x7A\xF6\x95\x5C\xF6\x5D\x32\x08\x33\xA4\x54\xB6\x18\x3F\x68\x5C\xF2\x42\x4A\x85\x38\x54\x83\x5F\xD1\xE8\x2C\xF2\xAC\x11\xD6\xA8\xED\x63\x6A", + ["CN=SecureTrust CA,O=SecureTrust Corporation,C=US"] = "\x30\x82\x03\xB8\x30\x82\x02\xA0\xA0\x03\x02\x01\x02\x02\x10\x0C\xF0\x8E\x5C\x08\x16\xA5\xAD\x42\x7F\xF0\xEB\x27\x18\x59\xD0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x48\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x13\x17\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x6F\x72\x70\x6F\x72\x61\x74\x69\x6F\x6E\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0E\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x31\x31\x30\x37\x31\x39\x33\x31\x31\x38\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x31\x39\x34\x30\x35\x35\x5A\x30\x48\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x13\x17\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x6F\x72\x70\x6F\x72\x61\x74\x69\x6F\x6E\x31\x17\x30\x15\x06\x03\x55\x04\x03\x13\x0E\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x41\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\xAB\xA4\x81\xE5\x95\xCD\xF5\xF6\x14\x8E\xC2\x4F\xCA\xD4\xE2\x78\x95\x58\x9C\x41\xE1\x0D\x99\x40\x24\x17\x39\x91\x33\x66\xE9\xBE\xE1\x83\xAF\x62\x5C\x89\xD1\xFC\x24\x5B\x61\xB3\xE0\x11\x11\x41\x1C\x1D\x6E\xF0\xB8\xBB\xF8\xDE\xA7\x81\xBA\xA6\x48\xC6\x9F\x1D\xBD\xBE\x8E\xA9\x41\x3E\xB8\x94\xED\x29\x1A\xD4\x8E\xD2\x03\x1D\x03\xEF\x6D\x0D\x67\x1C\x57\xD7\x06\xAD\xCA\xC8\xF5\xFE\x0E\xAF\x66\x25\x48\x04\x96\x0B\x5D\xA3\xBA\x16\xC3\x08\x4F\xD1\x46\xF8\x14\x5C\xF2\xC8\x5E\x01\x99\x6D\xFD\x88\xCC\x86\xA8\xC1\x6F\x31\x42\x6C\x52\x3E\x68\xCB\xF3\x19\x34\xDF\xBB\x87\x18\x56\x80\x26\xC4\xD0\xDC\xC0\x6F\xDF\xDE\xA0\xC2\x91\x16\xA0\x64\x11\x4B\x44\xBC\x1E\xF6\xE7\xFA\x63\xDE\x66\xAC\x76\xA4\x71\xA3\xEC\x36\x94\x68\x7A\x77\xA4\xB1\xE7\x0E\x2F\x81\x7A\xE2\xB5\x72\x86\xEF\xA2\x6B\x8B\xF0\x0F\xDB\xD3\x59\x3F\xBA\x72\xBC\x44\x24\x9C\xE3\x73\xB3\xF7\xAF\x57\x2F\x42\x26\x9D\xA9\x74\xBA\x00\x52\xF2\x4B\xCD\x53\x7C\x47\x0B\x36\x85\x0E\x66\xA9\x08\x97\x16\x34\x57\xC1\x66\xF7\x80\xE3\xED\x70\x54\xC7\x93\xE0\x2E\x28\x15\x59\x87\xBA\xBB\x02\x03\x01\x00\x01\xA3\x81\x9D\x30\x81\x9A\x30\x13\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x14\x02\x04\x06\x1E\x04\x00\x43\x00\x41\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x42\x32\xB6\x16\xFA\x04\xFD\xFE\x5D\x4B\x7A\xC3\xFD\xF7\x4C\x40\x1D\x5A\x43\xAF\x30\x34\x06\x03\x55\x1D\x1F\x04\x2D\x30\x2B\x30\x29\xA0\x27\xA0\x25\x86\x23\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x73\x65\x63\x75\x72\x65\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x2F\x53\x54\x43\x41\x2E\x63\x72\x6C\x30\x10\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x30\xED\x4F\x4A\xE1\x58\x3A\x52\x72\x5B\xB5\xA6\xA3\x65\x18\xA6\xBB\x51\x3B\x77\xE9\x9D\xEA\xD3\x9F\x5C\xE0\x45\x65\x7B\x0D\xCA\x5B\xE2\x70\x50\xB2\x94\x05\x14\xAE\x49\xC7\x8D\x41\x07\x12\x73\x94\x7E\x0C\x23\x21\xFD\xBC\x10\x7F\x60\x10\x5A\x72\xF5\x98\x0E\xAC\xEC\xB9\x7F\xDD\x7A\x6F\x5D\xD3\x1C\xF4\xFF\x88\x05\x69\x42\xA9\x05\x71\xC8\xB7\xAC\x26\xE8\x2E\xB4\x8C\x6A\xFF\x71\xDC\xB8\xB1\xDF\x99\xBC\x7C\x21\x54\x2B\xE4\x58\xA2\xBB\x57\x29\xAE\x9E\xA9\xA3\x19\x26\x0F\x99\x2E\x08\xB0\xEF\xFD\x69\xCF\x99\x1A\x09\x8D\xE3\xA7\x9F\x2B\xC9\x36\x34\x7B\x24\xB3\x78\x4C\x95\x17\xA4\x06\x26\x1E\xB6\x64\x52\x36\x5F\x60\x67\xD9\x9C\xC5\x05\x74\x0B\xE7\x67\x23\xD2\x08\xFC\x88\xE9\xAE\x8B\x7F\xE1\x30\xF4\x37\x7E\xFD\xC6\x32\xDA\x2D\x9E\x44\x30\x30\x6C\xEE\x07\xDE\xD2\x34\xFC\xD2\xFF\x40\xF6\x4B\xF4\x66\x46\x06\x54\xA6\xF2\x32\x0A\x63\x26\x30\x6B\x9B\xD1\xDC\x8B\x47\xBA\xE1\xB9\xD5\x62\xD0\xA2\xA0\xF4\x67\x05\x78\x29\x63\x1A\x6F\x04\xD6\xF8\xC6\x4C\xA3\x9A\xB1\x37\xB4\x8D\xE5\x28\x4B\x1D\x9E\x2C\xC2\xB8\x68\xBC\xED\x02\xEE\x31", + ["CN=Secure Global CA,O=SecureTrust Corporation,C=US"] = "\x30\x82\x03\xBC\x30\x82\x02\xA4\xA0\x03\x02\x01\x02\x02\x10\x07\x56\x22\xA4\xE8\xD4\x8A\x89\x4D\xF4\x13\xC8\xF0\xF8\xEA\xA5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x13\x17\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x6F\x72\x70\x6F\x72\x61\x74\x69\x6F\x6E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x65\x63\x75\x72\x65\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x31\x31\x30\x37\x31\x39\x34\x32\x32\x38\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x31\x39\x35\x32\x30\x36\x5A\x30\x4A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x13\x17\x53\x65\x63\x75\x72\x65\x54\x72\x75\x73\x74\x20\x43\x6F\x72\x70\x6F\x72\x61\x74\x69\x6F\x6E\x31\x19\x30\x17\x06\x03\x55\x04\x03\x13\x10\x53\x65\x63\x75\x72\x65\x20\x47\x6C\x6F\x62\x61\x6C\x20\x43\x41\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\xAF\x35\x2E\xD8\xAC\x6C\x55\x69\x06\x71\xE5\x13\x68\x24\xB3\x4F\xD8\xCC\x21\x47\xF8\xF1\x60\x38\x89\x89\x03\xE9\xBD\xEA\x5E\x46\x53\x09\xDC\x5C\xF5\x5A\xE8\xF7\x45\x2A\x02\xEB\x31\x61\xD7\x29\x33\x4C\xCE\xC7\x7C\x0A\x37\x7E\x0F\xBA\x32\x98\xE1\x1D\x97\xAF\x8F\xC7\xDC\xC9\x38\x96\xF3\xDB\x1A\xFC\x51\xED\x68\xC6\xD0\x6E\xA4\x7C\x24\xD1\xAE\x42\xC8\x96\x50\x63\x2E\xE0\xFE\x75\xFE\x98\xA7\x5F\x49\x2E\x95\xE3\x39\x33\x64\x8E\x1E\xA4\x5F\x90\xD2\x67\x3C\xB2\xD9\xFE\x41\xB9\x55\xA7\x09\x8E\x72\x05\x1E\x8B\xDD\x44\x85\x82\x42\xD0\x49\xC0\x1D\x60\xF0\xD1\x17\x2C\x95\xEB\xF6\xA5\xC1\x92\xA3\xC5\xC2\xA7\x08\x60\x0D\x60\x04\x10\x96\x79\x9E\x16\x34\xE6\xA9\xB6\xFA\x25\x45\x39\xC8\x1E\x65\xF9\x93\xF5\xAA\xF1\x52\xDC\x99\x98\x3D\xA5\x86\x1A\x0C\x35\x33\xFA\x4B\xA5\x04\x06\x15\x1C\x31\x80\xEF\xAA\x18\x6B\xC2\x7B\xD7\xDA\xCE\xF9\x33\x20\xD5\xF5\xBD\x6A\x33\x2D\x81\x04\xFB\xB0\x5C\xD4\x9C\xA3\xE2\x5C\x1D\xE3\xA9\x42\x75\x5E\x7B\xD4\x77\xEF\x39\x54\xBA\xC9\x0A\x18\x1B\x12\x99\x49\x2F\x88\x4B\xFD\x50\x62\xD1\x73\xE7\x8F\x7A\x43\x02\x03\x01\x00\x01\xA3\x81\x9D\x30\x81\x9A\x30\x13\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x14\x02\x04\x06\x1E\x04\x00\x43\x00\x41\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xAF\x44\x04\xC2\x41\x7E\x48\x83\xDB\x4E\x39\x02\xEC\xEC\x84\x7A\xE6\xCE\xC9\xA4\x30\x34\x06\x03\x55\x1D\x1F\x04\x2D\x30\x2B\x30\x29\xA0\x27\xA0\x25\x86\x23\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x73\x65\x63\x75\x72\x65\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x2F\x53\x47\x43\x41\x2E\x63\x72\x6C\x30\x10\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x63\x1A\x08\x40\x7D\xA4\x5E\x53\x0D\x77\xD8\x7A\xAE\x1F\x0D\x0B\x51\x16\x03\xEF\x18\x7C\xC8\xE3\xAF\x6A\x58\x93\x14\x60\x91\xB2\x84\xDC\x88\x4E\xBE\x39\x8A\x3A\xF3\xE6\x82\x89\x5D\x01\x37\xB3\xAB\x24\xA4\x15\x0E\x92\x35\x5A\x4A\x44\x5E\x4E\x57\xFA\x75\xCE\x1F\x48\xCE\x66\xF4\x3C\x40\x26\x92\x98\x6C\x1B\xEE\x24\x46\x0C\x17\xB3\x52\xA5\xDB\xA5\x91\x91\xCF\x37\xD3\x6F\xE7\x27\x08\x3A\x4E\x19\x1F\x3A\xA7\x58\x5C\x17\xCF\x79\x3F\x8B\xE4\xA7\xD3\x26\x23\x9D\x26\x0F\x58\x69\xFC\x47\x7E\xB2\xD0\x8D\x8B\x93\xBF\x29\x4F\x43\x69\x74\x76\x67\x4B\xCF\x07\x8C\xE6\x02\xF7\xB5\xE1\xB4\x43\xB5\x4B\x2D\x14\x9F\xF9\xDC\x26\x0D\xBF\xA6\x47\x74\x06\xD8\x88\xD1\x3A\x29\x30\x84\xCE\xD2\x39\x80\x62\x1B\xA8\xC7\x57\x49\xBC\x6A\x55\x51\x67\x15\x4A\xBE\x35\x07\xE4\xD5\x75\x98\x37\x79\x30\x14\xDB\x29\x9D\x6C\xC5\x69\xCC\x47\x55\xA2\x30\xF7\xCC\x5C\x7F\xC2\xC3\x98\x1C\x6B\x4E\x16\x80\xEB\x7A\x78\x65\x45\xA2\x00\x1A\xAF\x0C\x0D\x55\x64\x34\x48\xB8\x92\xB9\xF1\xB4\x50\x29\xF2\x4F\x23\x1F\xDA\x6C\xAC\x1F\x44\xE1\xDD\x23\x78\x51\x5B\xC7\x16", + ["CN=COMODO Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB"] = "\x30\x82\x04\x1D\x30\x82\x03\x05\xA0\x03\x02\x01\x02\x02\x10\x4E\x81\x2D\x8A\x82\x65\xE0\x0B\x02\xEE\x3E\x35\x02\x46\xE5\x3D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x81\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x13\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x13\x11\x43\x4F\x4D\x4F\x44\x4F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x43\x4F\x4D\x4F\x44\x4F\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x36\x31\x32\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x81\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x13\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x13\x11\x43\x4F\x4D\x4F\x44\x4F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x43\x4F\x4D\x4F\x44\x4F\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xD0\x40\x8B\x8B\x72\xE3\x91\x1B\xF7\x51\xC1\x1B\x54\x04\x98\xD3\xA9\xBF\xC1\xE6\x8A\x5D\x3B\x87\xFB\xBB\x88\xCE\x0D\xE3\x2F\x3F\x06\x96\xF0\xA2\x29\x50\x99\xAE\xDB\x3B\xA1\x57\xB0\x74\x51\x71\xCD\xED\x42\x91\x4D\x41\xFE\xA9\xC8\xD8\x6A\x86\x77\x44\xBB\x59\x66\x97\x50\x5E\xB4\xD4\x2C\x70\x44\xCF\xDA\x37\x95\x42\x69\x3C\x30\xC4\x71\xB3\x52\xF0\x21\x4D\xA1\xD8\xBA\x39\x7C\x1C\x9E\xA3\x24\x9D\xF2\x83\x16\x98\xAA\x16\x7C\x43\x9B\x15\x5B\xB7\xAE\x34\x91\xFE\xD4\x62\x26\x18\x46\x9A\x3F\xEB\xC1\xF9\xF1\x90\x57\xEB\xAC\x7A\x0D\x8B\xDB\x72\x30\x6A\x66\xD5\xE0\x46\xA3\x70\xDC\x68\xD9\xFF\x04\x48\x89\x77\xDE\xB5\xE9\xFB\x67\x6D\x41\xE9\xBC\x39\xBD\x32\xD9\x62\x02\xF1\xB1\xA8\x3D\x6E\x37\x9C\xE2\x2F\xE2\xD3\xA2\x26\x8B\xC6\xB8\x55\x43\x88\xE1\x23\x3E\xA5\xD2\x24\x39\x6A\x47\xAB\x00\xD4\xA1\xB3\xA9\x25\xFE\x0D\x3F\xA7\x1D\xBA\xD3\x51\xC1\x0B\xA4\xDA\xAC\x38\xEF\x55\x50\x24\x05\x65\x46\x93\x34\x4F\x2D\x8D\xAD\xC6\xD4\x21\x19\xD2\x8E\xCA\x05\x61\x71\x07\x73\x47\xE5\x8A\x19\x12\xBD\x04\x4D\xCE\x4E\x9C\xA5\x48\xAC\xBB\x26\xF7\x02\x03\x01\x00\x01\xA3\x81\x8E\x30\x81\x8B\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x0B\x58\xE5\x8B\xC6\x4C\x15\x37\xA4\x40\xA9\x30\xA9\x21\xBE\x47\x36\x5A\x56\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x49\x06\x03\x55\x1D\x1F\x04\x42\x30\x40\x30\x3E\xA0\x3C\xA0\x3A\x86\x38\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x63\x6F\x6D\x6F\x64\x6F\x63\x61\x2E\x63\x6F\x6D\x2F\x43\x4F\x4D\x4F\x44\x4F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3E\x98\x9E\x9B\xF6\x1B\xE9\xD7\x39\xB7\x78\xAE\x1D\x72\x18\x49\xD3\x87\xE4\x43\x82\xEB\x3F\xC9\xAA\xF5\xA8\xB5\xEF\x55\x7C\x21\x52\x65\xF9\xD5\x0D\xE1\x6C\xF4\x3E\x8C\x93\x73\x91\x2E\x02\xC4\x4E\x07\x71\x6F\xC0\x8F\x38\x61\x08\xA8\x1E\x81\x0A\xC0\x2F\x20\x2F\x41\x8B\x91\xDC\x48\x45\xBC\xF1\xC6\xDE\xBA\x76\x6B\x33\xC8\x00\x2D\x31\x46\x4C\xED\xE7\x9D\xCF\x88\x94\xFF\x33\xC0\x56\xE8\x24\x86\x26\xB8\xD8\x38\x38\xDF\x2A\x6B\xDD\x12\xCC\xC7\x3F\x47\x17\x4C\xA2\xC2\x06\x96\x09\xD6\xDB\xFE\x3F\x3C\x46\x41\xDF\x58\xE2\x56\x0F\x3C\x3B\xC1\x1C\x93\x35\xD9\x38\x52\xAC\xEE\xC8\xEC\x2E\x30\x4E\x94\x35\xB4\x24\x1F\x4B\x78\x69\xDA\xF2\x02\x38\xCC\x95\x52\x93\xF0\x70\x25\x59\x9C\x20\x67\xC4\xEE\xF9\x8B\x57\x61\xF4\x92\x76\x7D\x3F\x84\x8D\x55\xB7\xE8\xE5\xAC\xD5\xF1\xF5\x19\x56\xA6\x5A\xFB\x90\x1C\xAF\x93\xEB\xE5\x1C\xD4\x67\x97\x5D\x04\x0E\xBE\x0B\x83\xA6\x17\x83\xB9\x30\x12\xA0\xC5\x33\x15\x05\xB9\x0D\xFB\xC7\x05\x76\xE3\xD8\x4A\x8D\xFC\x34\x17\xA3\xC6\x21\x28\xBE\x30\x45\x31\x1E\xC7\x78\xBE\x58\x61\x38\xAC\x3B\xE2\x01\x65", + ["CN=Network Solutions Certificate Authority,O=Network Solutions L.L.C.,C=US"] = "\x30\x82\x03\xE6\x30\x82\x02\xCE\xA0\x03\x02\x01\x02\x02\x10\x57\xCB\x33\x6F\xC2\x5C\x16\xE6\x47\x16\x17\xE3\x90\x31\x68\xE0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x62\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1F\x06\x03\x55\x04\x0A\x13\x18\x4E\x65\x74\x77\x6F\x72\x6B\x20\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x20\x4C\x2E\x4C\x2E\x43\x2E\x31\x30\x30\x2E\x06\x03\x55\x04\x03\x13\x27\x4E\x65\x74\x77\x6F\x72\x6B\x20\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x36\x31\x32\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x62\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x21\x30\x1F\x06\x03\x55\x04\x0A\x13\x18\x4E\x65\x74\x77\x6F\x72\x6B\x20\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x20\x4C\x2E\x4C\x2E\x43\x2E\x31\x30\x30\x2E\x06\x03\x55\x04\x03\x13\x27\x4E\x65\x74\x77\x6F\x72\x6B\x20\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xE4\xBC\x7E\x92\x30\x6D\xC6\xD8\x8E\x2B\x0B\xBC\x46\xCE\xE0\x27\x96\xDE\xDE\xF9\xFA\x12\xD3\x3C\x33\x73\xB3\x04\x2F\xBC\x71\x8C\xE5\x9F\xB6\x22\x60\x3E\x5F\x5D\xCE\x09\xFF\x82\x0C\x1B\x9A\x51\x50\x1A\x26\x89\xDD\xD5\x61\x5D\x19\xDC\x12\x0F\x2D\x0A\xA2\x43\x5D\x17\xD0\x34\x92\x20\xEA\x73\xCF\x38\x2C\x06\x26\x09\x7A\x72\xF7\xFA\x50\x32\xF8\xC2\x93\xD3\x69\xA2\x23\xCE\x41\xB1\xCC\xE4\xD5\x1F\x36\xD1\x8A\x3A\xF8\x8C\x63\xE2\x14\x59\x69\xED\x0D\xD3\x7F\x6B\xE8\xB8\x03\xE5\x4F\x6A\xE5\x98\x63\x69\x48\x05\xBE\x2E\xFF\x33\xB6\xE9\x97\x59\x69\xF8\x67\x19\xAE\x93\x61\x96\x44\x15\xD3\x72\xB0\x3F\xBC\x6A\x7D\xEC\x48\x7F\x8D\xC3\xAB\xAA\x71\x2B\x53\x69\x41\x53\x34\xB5\xB0\xB9\xC5\x06\x0A\xC4\xB0\x45\xF5\x41\x5D\x6E\x89\x45\x7B\x3D\x3B\x26\x8C\x74\xC2\xE5\xD2\xD1\x7D\xB2\x11\xD4\xFB\x58\x32\x22\x9A\x80\xC9\xDC\xFD\x0C\xE9\x7F\x5E\x03\x97\xCE\x3B\x00\x14\x87\x27\x70\x38\xA9\x8E\x6E\xB3\x27\x76\x98\x51\xE0\x05\xE3\x21\xAB\x1A\xD5\x85\x22\x3C\x29\xB5\x9A\x16\xC5\x80\xA8\xF4\xBB\x6B\x30\x8F\x2F\x46\x02\xA2\xB1\x0C\x22\xE0\xD3\x02\x03\x01\x00\x01\xA3\x81\x97\x30\x81\x94\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x21\x30\xC9\xFB\x00\xD7\x4E\x98\xDA\x87\xAA\x2A\xD0\xA7\x2E\xB1\x40\x31\xA7\x4C\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x52\x06\x03\x55\x1D\x1F\x04\x4B\x30\x49\x30\x47\xA0\x45\xA0\x43\x86\x41\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x6E\x65\x74\x73\x6F\x6C\x73\x73\x6C\x2E\x63\x6F\x6D\x2F\x4E\x65\x74\x77\x6F\x72\x6B\x53\x6F\x6C\x75\x74\x69\x6F\x6E\x73\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x2E\x63\x72\x6C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xBB\xAE\x4B\xE7\xB7\x57\xEB\x7F\xAA\x2D\xB7\x73\x47\x85\x6A\xC1\xE4\xA5\x1D\xE4\xE7\x3C\xE9\xF4\x59\x65\x77\xB5\x7A\x5B\x5A\x8D\x25\x36\xE0\x7A\x97\x2E\x38\xC0\x57\x60\x83\x98\x06\x83\x9F\xB9\x76\x7A\x6E\x50\xE0\xBA\x88\x2C\xFC\x45\xCC\x18\xB0\x99\x95\x51\x0E\xEC\x1D\xB8\x88\xFF\x87\x50\x1C\x82\xC2\xE3\xE0\x32\x80\xBF\xA0\x0B\x47\xC8\xC3\x31\xEF\x99\x67\x32\x80\x4F\x17\x21\x79\x0C\x69\x5C\xDE\x5E\x34\xAE\x02\xB5\x26\xEA\x50\xDF\x7F\x18\x65\x2C\xC9\xF2\x63\xE1\xA9\x07\xFE\x7C\x71\x1F\x6B\x33\x24\x6A\x1E\x05\xF7\x05\x68\xC0\x6A\x12\xCB\x2E\x5E\x61\xCB\xAE\x28\xD3\x7E\xC2\xB4\x66\x91\x26\x5F\x3C\x2E\x24\x5F\xCB\x58\x0F\xEB\x28\xEC\xAF\x11\x96\xF3\xDC\x7B\x6F\xC0\xA7\x88\xF2\x53\x77\xB3\x60\x5E\xAE\xAE\x28\xDA\x35\x2C\x6F\x34\x45\xD3\x26\xE1\xDE\xEC\x5B\x4F\x27\x6B\x16\x7C\xBD\x44\x04\x18\x82\xB3\x89\x79\x17\x10\x71\x3D\x7A\xA2\x16\x4E\xF5\x01\xCD\xA4\x6C\x65\x68\xA1\x49\x76\x5C\x43\xC9\xD8\xBC\x36\x67\x6C\xA5\x94\xB5\xD4\xCC\xB9\xBD\x6A\x35\x56\x21\xDE\xD8\xC3\xEB\xFB\xCB\xA4\x60\x4C\xB0\x55\xA0\xA0\x7B\x57\xB2", + ["CN=WellsSecure Public Root Certificate Authority,OU=Wells Fargo Bank NA,O=Wells Fargo WellsSecure,C=US"] = "\x30\x82\x04\xBD\x30\x82\x03\xA5\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x0C\x17\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x57\x65\x6C\x6C\x73\x53\x65\x63\x75\x72\x65\x31\x1C\x30\x1A\x06\x03\x55\x04\x0B\x0C\x13\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x42\x61\x6E\x6B\x20\x4E\x41\x31\x36\x30\x34\x06\x03\x55\x04\x03\x0C\x2D\x57\x65\x6C\x6C\x73\x53\x65\x63\x75\x72\x65\x20\x50\x75\x62\x6C\x69\x63\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x37\x31\x32\x31\x33\x31\x37\x30\x37\x35\x34\x5A\x17\x0D\x32\x32\x31\x32\x31\x34\x30\x30\x30\x37\x35\x34\x5A\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x0C\x17\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x57\x65\x6C\x6C\x73\x53\x65\x63\x75\x72\x65\x31\x1C\x30\x1A\x06\x03\x55\x04\x0B\x0C\x13\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x42\x61\x6E\x6B\x20\x4E\x41\x31\x36\x30\x34\x06\x03\x55\x04\x03\x0C\x2D\x57\x65\x6C\x6C\x73\x53\x65\x63\x75\x72\x65\x20\x50\x75\x62\x6C\x69\x63\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xEE\x6F\xB4\xBD\x79\xE2\x8F\x08\x21\x9E\x38\x04\x41\x25\xEF\xAB\x5B\x1C\x53\x92\xAC\x6D\x9E\xDD\xC2\xC4\x2E\x45\x94\x03\x35\x88\x67\x74\x57\xE3\xDF\x8C\xB8\xA7\x76\x8F\x3B\xF7\xA8\xC4\xDB\x29\x63\x0E\x91\x68\x36\x8A\x97\x8E\x8A\x71\x68\x09\x07\xE4\xE8\xD4\x0E\x4F\xF8\xD6\x2B\x4C\xA4\x16\xF9\xEF\x43\x98\x8F\xB3\x9E\x52\xDF\x6D\x91\x39\x8F\x38\xBD\x77\x8B\x43\x63\xEB\xB7\x93\xFC\x30\x4C\x1C\x01\x93\xB6\x13\xFB\xF7\xA1\x1F\xBF\x25\xE1\x74\x37\x2C\x1E\xA4\x5E\x3C\x68\xF8\x4B\xBF\x0D\xB9\x1E\x2E\x36\xE8\xA9\xE4\xA7\xF8\x0F\xCB\x82\x75\x7C\x35\x2D\x22\xD6\xC2\xBF\x0B\xF3\xB4\xFC\x6C\x95\x61\x1E\x57\xD7\x04\x81\x32\x83\x52\x79\xE6\x83\x63\xCF\xB7\xCB\x63\x8B\x11\xE2\xBD\x5E\xEB\xF6\x8D\xED\x95\x72\x28\xB4\xAC\x12\x62\xE9\x4A\x33\xE6\x83\x32\xAE\x05\x75\x95\xBD\x84\x95\xDB\x2A\x5C\x9B\x8E\x2E\x0C\xB8\x81\x2B\x41\xE6\x38\x56\x9F\x49\x9B\x6C\x76\xFA\x8A\x5D\xF7\x01\x79\x81\x7C\xC1\x83\x40\x05\xFE\x71\xFD\x0C\x3F\xCC\x4E\x60\x09\x0E\x65\x47\x10\x2F\x01\xC0\x05\x3F\x8F\xF8\xB3\x41\xEF\x5A\x42\x7E\x59\xEF\xD2\x97\x0C\x65\x02\x03\x01\x00\x01\xA3\x82\x01\x34\x30\x82\x01\x30\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x39\x06\x03\x55\x1D\x1F\x04\x32\x30\x30\x30\x2E\xA0\x2C\xA0\x2A\x86\x28\x68\x74\x74\x70\x3A\x2F\x2F\x63\x72\x6C\x2E\x70\x6B\x69\x2E\x77\x65\x6C\x6C\x73\x66\x61\x72\x67\x6F\x2E\x63\x6F\x6D\x2F\x77\x73\x70\x72\x63\x61\x2E\x63\x72\x6C\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\xC6\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x26\x95\x19\x10\xD9\xE8\xA1\x97\x91\xFF\xDC\x19\xD9\xB5\x04\x3E\xD2\x73\x0A\x6A\x30\x81\xB2\x06\x03\x55\x1D\x23\x04\x81\xAA\x30\x81\xA7\x80\x14\x26\x95\x19\x10\xD9\xE8\xA1\x97\x91\xFF\xDC\x19\xD9\xB5\x04\x3E\xD2\x73\x0A\x6A\xA1\x81\x8B\xA4\x81\x88\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x20\x30\x1E\x06\x03\x55\x04\x0A\x0C\x17\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x57\x65\x6C\x6C\x73\x53\x65\x63\x75\x72\x65\x31\x1C\x30\x1A\x06\x03\x55\x04\x0B\x0C\x13\x57\x65\x6C\x6C\x73\x20\x46\x61\x72\x67\x6F\x20\x42\x61\x6E\x6B\x20\x4E\x41\x31\x36\x30\x34\x06\x03\x55\x04\x03\x0C\x2D\x57\x65\x6C\x6C\x73\x53\x65\x63\x75\x72\x65\x20\x50\x75\x62\x6C\x69\x63\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x82\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xB9\x15\xB1\x44\x91\xCC\x23\xC8\x2B\x4D\x77\xE3\xF8\x9A\x7B\x27\x0D\xCD\x72\xBB\x99\x00\xCA\x7C\x66\x19\x50\xC6\xD5\x98\xED\xAB\xBF\x03\x5A\xE5\x4D\xE5\x1E\xC8\x4F\x71\x97\x86\xD5\xE3\x1D\xFD\x90\xC9\x3C\x75\x77\x57\x7A\x7D\xF8\xDE\xF4\xD4\xD5\xF7\x95\xE6\x74\x6E\x1D\x3C\xAE\x7C\x9D\xDB\x02\x03\x05\x2C\x71\x4B\x25\x3E\x07\xE3\x5E\x9A\xF5\x66\x17\x29\x88\x1A\x38\x9F\xCF\xAA\x41\x03\x84\x97\x6B\x93\x38\x7A\xCA\x30\x44\x1B\x24\x44\x33\xD0\xE4\xD1\xDC\x28\x38\xF4\x13\x43\x35\x35\x29\x63\xA8\x7C\xA2\xB5\xAD\x38\xA4\xED\xAD\xFD\xC6\x9A\x1F\xFF\x97\x73\xFE\xFB\xB3\x35\xA7\x93\x86\xC6\x76\x91\x00\xE6\xAC\x51\x16\xC4\x27\x32\x5C\xDB\x73\xDA\xA5\x93\x57\x8E\x3E\x6D\x35\x26\x08\x59\xD5\xE7\x44\xD7\x76\x20\x63\xE7\xAC\x13\x67\xC3\x6D\xB1\x70\x46\x7C\xD5\x96\x11\x3D\x89\x6F\x5D\xA8\xA1\xEB\x8D\x0A\xDA\xC3\x1D\x33\x6C\xA3\xEA\x67\x19\x9A\x99\x7F\x4B\x3D\x83\x51\x2A\x1D\xCA\x2F\x86\x0C\xA2\x7E\x10\x2D\x2B\xD4\x16\x95\x0B\x07\xAA\x2E\x14\x92\x49\xB7\x29\x6F\xD8\x6D\x31\x7D\xF5\xFC\xA1\x10\x07\x87\xCE\x2F\x59\xDC\x3E\x58\xDB", + ["CN=COMODO ECC Certification Authority,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB"] = "\x30\x82\x02\x89\x30\x82\x02\x0F\xA0\x03\x02\x01\x02\x02\x10\x1F\x47\xAF\xAA\x62\x00\x70\x50\x54\x4C\x01\x9E\x9B\x63\x99\x2A\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x13\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x13\x11\x43\x4F\x4D\x4F\x44\x4F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x2B\x30\x29\x06\x03\x55\x04\x03\x13\x22\x43\x4F\x4D\x4F\x44\x4F\x20\x45\x43\x43\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x38\x30\x33\x30\x36\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x38\x30\x31\x31\x38\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x47\x42\x31\x1B\x30\x19\x06\x03\x55\x04\x08\x13\x12\x47\x72\x65\x61\x74\x65\x72\x20\x4D\x61\x6E\x63\x68\x65\x73\x74\x65\x72\x31\x10\x30\x0E\x06\x03\x55\x04\x07\x13\x07\x53\x61\x6C\x66\x6F\x72\x64\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x13\x11\x43\x4F\x4D\x4F\x44\x4F\x20\x43\x41\x20\x4C\x69\x6D\x69\x74\x65\x64\x31\x2B\x30\x29\x06\x03\x55\x04\x03\x13\x22\x43\x4F\x4D\x4F\x44\x4F\x20\x45\x43\x43\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x76\x30\x10\x06\x07\x2A\x86\x48\xCE\x3D\x02\x01\x06\x05\x2B\x81\x04\x00\x22\x03\x62\x00\x04\x03\x47\x7B\x2F\x75\xC9\x82\x15\x85\xFB\x75\xE4\x91\x16\xD4\xAB\x62\x99\xF5\x3E\x52\x0B\x06\xCE\x41\x00\x7F\x97\xE1\x0A\x24\x3C\x1D\x01\x04\xEE\x3D\xD2\x8D\x09\x97\x0C\xE0\x75\xE4\xFA\xFB\x77\x8A\x2A\xF5\x03\x60\x4B\x36\x8B\x16\x23\x16\xAD\x09\x71\xF4\x4A\xF4\x28\x50\xB4\xFE\x88\x1C\x6E\x3F\x6C\x2F\x2F\x09\x59\x5B\xA5\x5B\x0B\x33\x99\xE2\xC3\x3D\x89\xF9\x6A\x2C\xEF\xB2\xD3\x06\xE9\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x75\x71\xA7\x19\x48\x19\xBC\x9D\x9D\xEA\x41\x47\xDF\x94\xC4\x48\x77\x99\xD3\x79\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x03\x68\x00\x30\x65\x02\x31\x00\xEF\x03\x5B\x7A\xAC\xB7\x78\x0A\x72\xB7\x88\xDF\xFF\xB5\x46\x14\x09\x0A\xFA\xA0\xE6\x7D\x08\xC6\x1A\x87\xBD\x18\xA8\x73\xBD\x26\xCA\x60\x0C\x9D\xCE\x99\x9F\xCF\x5C\x0F\x30\xE1\xBE\x14\x31\xEA\x02\x30\x14\xF4\x93\x3C\x49\xA7\x33\x7A\x90\x46\x47\xB3\x63\x7D\x13\x9B\x4E\xB7\x6F\x18\x37\x80\x53\xFE\xDD\x20\xE0\x35\x9A\x36\xD1\xC7\x01\xB9\xE6\xDC\xDD\xF3\xFF\x1D\x2C\x3A\x16\x57\xD9\x92\x39\xD6", + ["emailAddress=igca@sgdn.pm.gouv.fr,CN=IGC/A,OU=DCSSI,O=PM/SGDN,L=Paris,ST=France,C=FR"] = "\x30\x82\x04\x02\x30\x82\x02\xEA\xA0\x03\x02\x01\x02\x02\x05\x39\x11\x45\x10\x94\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x08\x13\x06\x46\x72\x61\x6E\x63\x65\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05\x50\x61\x72\x69\x73\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x50\x4D\x2F\x53\x47\x44\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13\x05\x44\x43\x53\x53\x49\x31\x0E\x30\x0C\x06\x03\x55\x04\x03\x13\x05\x49\x47\x43\x2F\x41\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x14\x69\x67\x63\x61\x40\x73\x67\x64\x6E\x2E\x70\x6D\x2E\x67\x6F\x75\x76\x2E\x66\x72\x30\x1E\x17\x0D\x30\x32\x31\x32\x31\x33\x31\x34\x32\x39\x32\x33\x5A\x17\x0D\x32\x30\x31\x30\x31\x37\x31\x34\x32\x39\x32\x32\x5A\x30\x81\x85\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x0F\x30\x0D\x06\x03\x55\x04\x08\x13\x06\x46\x72\x61\x6E\x63\x65\x31\x0E\x30\x0C\x06\x03\x55\x04\x07\x13\x05\x50\x61\x72\x69\x73\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x50\x4D\x2F\x53\x47\x44\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0B\x13\x05\x44\x43\x53\x53\x49\x31\x0E\x30\x0C\x06\x03\x55\x04\x03\x13\x05\x49\x47\x43\x2F\x41\x31\x23\x30\x21\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x14\x69\x67\x63\x61\x40\x73\x67\x64\x6E\x2E\x70\x6D\x2E\x67\x6F\x75\x76\x2E\x66\x72\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\xB2\x1F\xD1\xD0\x62\xC5\x33\x3B\xC0\x04\x86\x88\xB3\xDC\xF8\x88\xF7\xFD\xDF\x43\xDF\x7A\x8D\x9A\x49\x5C\xF6\x4E\xAA\xCC\x1C\xB9\xA1\xEB\x27\x89\xF2\x46\xE9\x3B\x4A\x71\xD5\x1D\x8E\x2D\xCF\xE6\xAD\xAB\x63\x50\xC7\x54\x0B\x6E\x12\xC9\x90\x36\xC6\xD8\x2F\xDA\x91\xAA\x68\xC5\x72\xFE\x17\x0A\xB2\x17\x7E\x79\xB5\x32\x88\x70\xCA\x70\xC0\x96\x4A\x8E\xE4\x55\xCD\x1D\x27\x94\xBF\xCE\x72\x2A\xEC\x5C\xF9\x73\x20\xFE\xBD\xF7\x2E\x89\x67\xB8\xBB\x47\x73\x12\xF7\xD1\x35\x69\x3A\xF2\x0A\xB9\xAE\xFF\x46\x42\x46\xA2\xBF\xA1\x85\x1A\xF9\xBF\xE4\xFF\x49\x85\xF7\xA3\x70\x86\x32\x1C\x5D\x9F\x60\xF7\xA9\xAD\xA5\xFF\xCF\xD1\x34\xF9\x7D\x5B\x17\xC6\xDC\xD6\x0E\x28\x6B\xC2\xDD\xF1\xF5\x33\x68\x9D\x4E\xFC\x87\x7C\x36\x12\xD6\xA3\x80\xE8\x43\x0D\x55\x61\x94\xEA\x64\x37\x47\xEA\x77\xCA\xD0\xB2\x58\x05\xC3\x5D\x7E\xB1\xA8\x46\x90\x31\x56\xCE\x70\x2A\x96\xB2\x30\xB8\x77\xE6\x79\xC0\xBD\x29\x3B\xFD\x94\x77\x4C\xBD\x20\xCD\x41\x25\xE0\x2E\xC7\x1B\xBB\xEE\xA4\x04\x41\xD2\x5D\xAD\x12\x6A\x8A\x9B\x47\xFB\xC9\xDD\x46\x40\xE1\x9D\x3C\x33\xD0\xB5\x02\x03\x01\x00\x01\xA3\x77\x30\x75\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x46\x30\x15\x06\x03\x55\x1D\x20\x04\x0E\x30\x0C\x30\x0A\x06\x08\x2A\x81\x7A\x01\x79\x01\x01\x01\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xA3\x05\x2F\x18\x60\x50\xC2\x89\x0A\xDD\x2B\x21\x4F\xFF\x8E\x4E\xA8\x30\x31\x36\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xA3\x05\x2F\x18\x60\x50\xC2\x89\x0A\xDD\x2B\x21\x4F\xFF\x8E\x4E\xA8\x30\x31\x36\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x05\xDC\x26\xD8\xFA\x77\x15\x44\x68\xFC\x2F\x66\x3A\x74\xE0\x5D\xE4\x29\xFF\x06\x07\x13\x84\x4A\xAB\xCF\x6D\xA0\x1F\x51\x94\xF8\x49\xCB\x74\x36\x14\xBC\x15\xDD\xDB\x89\x2F\xDD\x8F\xA0\x5D\x7C\xF5\x12\xEB\x9F\x9E\x38\xA4\x47\xCC\xB3\x96\xD9\xBE\x9C\x25\xAB\x03\x7E\x33\x0F\x95\x81\x0D\xFD\x16\xE0\x88\xBE\x37\xF0\x6C\x5D\xD0\x31\x9B\x32\x2B\x5D\x17\x65\x93\x98\x60\xBC\x6E\x8F\xB1\xA8\x3C\x1E\xD9\x1C\xF3\xA9\x26\x42\xF9\x64\x1D\xC2\xE7\x92\xF6\xF4\x1E\x5A\xAA\x19\x52\x5D\xAF\xE8\xA2\xF7\x60\xA0\xF6\x8D\xF0\x89\xF5\x6E\xE0\x0A\x05\x01\x95\xC9\x8B\x20\x0A\xBA\x5A\xFC\x9A\x2C\x3C\xBD\xC3\xB7\xC9\x5D\x78\x25\x05\x3F\x56\x14\x9B\x0C\xDA\xFB\x3A\x48\xFE\x97\x69\x5E\xCA\x10\x86\xF7\x4E\x96\x04\x08\x4D\xEC\xB0\xBE\x5D\xDC\x3B\x8E\x4F\xC1\xFD\x9A\x36\x34\x9A\x4C\x54\x7E\x17\x03\x48\x95\x08\x11\x1C\x07\x6F\x85\x08\x7E\x5D\x4D\xC4\x9D\xDB\xFB\xAE\xCE\xB2\xD1\xB3\xB8\x83\x6C\x1D\xB2\xB3\x79\xF1\xD8\x70\x99\x7E\xF0\x13\x02\xCE\x5E\xDD\x51\xD3\xDF\x36\x81\xA1\x1B\x78\x2F\x71\xB3\xF1\x59\x4C\x46\x18\x28\xAB\x85\xD2\x60\x56\x5A", + ["OU=Security Communication EV RootCA1,O=SECOM Trust Systems CO.\,LTD.,C=JP"] = "\x30\x82\x03\x7D\x30\x82\x02\x65\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x60\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x45\x43\x4F\x4D\x20\x54\x72\x75\x73\x74\x20\x53\x79\x73\x74\x65\x6D\x73\x20\x43\x4F\x2E\x2C\x4C\x54\x44\x2E\x31\x2A\x30\x28\x06\x03\x55\x04\x0B\x13\x21\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6F\x6D\x6D\x75\x6E\x69\x63\x61\x74\x69\x6F\x6E\x20\x45\x56\x20\x52\x6F\x6F\x74\x43\x41\x31\x30\x1E\x17\x0D\x30\x37\x30\x36\x30\x36\x30\x32\x31\x32\x33\x32\x5A\x17\x0D\x33\x37\x30\x36\x30\x36\x30\x32\x31\x32\x33\x32\x5A\x30\x60\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x45\x43\x4F\x4D\x20\x54\x72\x75\x73\x74\x20\x53\x79\x73\x74\x65\x6D\x73\x20\x43\x4F\x2E\x2C\x4C\x54\x44\x2E\x31\x2A\x30\x28\x06\x03\x55\x04\x0B\x13\x21\x53\x65\x63\x75\x72\x69\x74\x79\x20\x43\x6F\x6D\x6D\x75\x6E\x69\x63\x61\x74\x69\x6F\x6E\x20\x45\x56\x20\x52\x6F\x6F\x74\x43\x41\x31\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\xBC\x7F\xEC\x57\x9B\x24\xE0\xFE\x9C\xBA\x42\x79\xA9\x88\x8A\xFA\x80\xE0\xF5\x07\x29\x43\xEA\x8E\x0A\x34\x36\x8D\x1C\xFA\xA7\xB5\x39\x78\xFF\x97\x75\xF7\x2F\xE4\xAA\x6B\x04\x84\x44\xCA\xA6\xE2\x68\x8E\xFD\x55\x50\x62\x0F\xA4\x71\x0E\xCE\x07\x38\x2D\x42\x85\x50\xAD\x3C\x96\x6F\x8B\xD5\xA2\x0E\xCF\xDE\x49\x89\x3D\xD6\x64\x2E\x38\xE5\x1E\x6C\xB5\x57\x8A\x9E\xEF\x48\x0E\xCD\x7A\x69\x16\x87\x44\xB5\x90\xE4\x06\x9D\xAE\xA1\x04\x97\x58\x79\xEF\x20\x4A\x82\x6B\x8C\x22\xBF\xEC\x1F\x0F\xE9\x84\x71\xED\xF1\x0E\xE4\xB8\x18\x13\xCC\x56\x36\x5D\xD1\x9A\x1E\x51\x6B\x39\x6E\x60\x76\x88\x34\x0B\xF3\xB3\xD1\xB0\x9D\xCA\x61\xE2\x64\x1D\xC1\x46\x07\xB8\x63\xDD\x1E\x33\x65\xB3\x8E\x09\x55\x52\x3D\xB5\xBD\xFF\x07\xEB\xAD\x61\x55\x18\x2C\xA9\x69\x98\x4A\xAA\x40\xC5\x33\x14\x65\x74\x00\xF9\x91\xDE\xAF\x03\x48\xC5\x40\x54\xDC\x0F\x84\x90\x68\x20\xC5\x92\x96\xDC\x2E\xE5\x02\x45\xAA\xC0\x5F\x54\xF8\x6D\xEA\x49\xCF\x5D\x6C\x4B\xAF\xEF\x9A\xC2\x56\x5C\xC6\x35\x56\x42\x6A\x30\x5F\xC2\xAB\xF6\xE2\x3D\x3F\xB3\xC9\x11\x8F\x31\x4C\xD7\x9F\x49\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x35\x4A\xF5\x4D\xAF\x3F\xD7\x82\x38\xAC\xAB\x71\x65\x17\x75\x8C\x9D\x55\x93\xE6\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA8\x87\xE9\xEC\xF8\x40\x67\x5D\xC3\xC1\x66\xC7\x40\x4B\x97\xFC\x87\x13\x90\x5A\xC4\xEF\xA0\xCA\x5F\x8B\xB7\xA7\xB7\xF1\xD6\xB5\x64\xB7\x8A\xB3\xB8\x1B\xCC\xDA\xFB\xAC\x66\x88\x41\xCE\xE8\xFC\xE4\xDB\x1E\x88\xA6\xED\x27\x50\x1B\x02\x30\x24\x46\x79\xFE\x04\x87\x70\x97\x40\x73\xD1\xC0\xC1\x57\x19\x9A\x69\xA5\x27\x99\xAB\x9D\x62\x84\xF6\x51\xC1\x2C\xC9\x23\x15\xD8\x28\xB7\xAB\x25\x13\xB5\x46\xE1\x86\x02\xFF\x26\x8C\xC4\x88\x92\x1D\x56\xFE\x19\x67\xF2\x55\xE4\x80\xA3\x6B\x9C\xAB\x77\xE1\x51\x71\x0D\x20\xDB\x10\x9A\xDB\xBD\x76\x79\x07\x77\x99\x28\xAD\x9A\x5E\xDA\xB1\x4F\x44\x2C\x35\x8E\xA5\x96\xC7\xFD\x83\xF0\x58\xC6\x79\xD6\x98\x7C\xA8\x8D\xFE\x86\x3E\x07\x16\x92\xE1\x7B\xE7\x1D\xEC\x33\x76\x7E\x42\x2E\x4A\x85\xF9\x91\x89\x68\x84\x03\x81\xA5\x9B\x9A\xBE\xE3\x37\xC5\x54\xAB\x56\x3B\x18\x2D\x41\xA4\x0C\xF8\x42\xDB\x99\xA0\xE0\x72\x6F\xBB\x5D\xE1\x16\x4F\x53\x0A\x64\xF9\x4E\xF4\xBF\x4E\x54\xBD\x78\x6C\x88\xEA\xBF\x9C\x13\x24\xC2\x70\x69\xA2\x7F\x0F\xC8\x3C\xAD\x08\xC9\xB0\x98\x40\xA3\x2A\xE7\x88\x83\xED\x77\x8F\x74", + ["CN=OISTE WISeKey Global Root GA CA,OU=OISTE Foundation Endorsed,OU=Copyright (c) 2005,O=WISeKey,C=CH"] = "\x30\x82\x03\xF1\x30\x82\x02\xD9\xA0\x03\x02\x01\x02\x02\x10\x41\x3D\x72\xC7\xF4\x6B\x1F\x81\x43\x7D\xF1\xD2\x28\x54\xDF\x9A\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x8A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x57\x49\x53\x65\x4B\x65\x79\x31\x1B\x30\x19\x06\x03\x55\x04\x0B\x13\x12\x43\x6F\x70\x79\x72\x69\x67\x68\x74\x20\x28\x63\x29\x20\x32\x30\x30\x35\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x4F\x49\x53\x54\x45\x20\x46\x6F\x75\x6E\x64\x61\x74\x69\x6F\x6E\x20\x45\x6E\x64\x6F\x72\x73\x65\x64\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1F\x4F\x49\x53\x54\x45\x20\x57\x49\x53\x65\x4B\x65\x79\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x20\x47\x41\x20\x43\x41\x30\x1E\x17\x0D\x30\x35\x31\x32\x31\x31\x31\x36\x30\x33\x34\x34\x5A\x17\x0D\x33\x37\x31\x32\x31\x31\x31\x36\x30\x39\x35\x31\x5A\x30\x81\x8A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x48\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x57\x49\x53\x65\x4B\x65\x79\x31\x1B\x30\x19\x06\x03\x55\x04\x0B\x13\x12\x43\x6F\x70\x79\x72\x69\x67\x68\x74\x20\x28\x63\x29\x20\x32\x30\x30\x35\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x4F\x49\x53\x54\x45\x20\x46\x6F\x75\x6E\x64\x61\x74\x69\x6F\x6E\x20\x45\x6E\x64\x6F\x72\x73\x65\x64\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1F\x4F\x49\x53\x54\x45\x20\x57\x49\x53\x65\x4B\x65\x79\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x20\x47\x41\x20\x43\x41\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\xCB\x4F\xB3\x00\x9B\x3D\x36\xDD\xF9\xD1\x49\x6A\x6B\x10\x49\x1F\xEC\xD8\x2B\xB2\xC6\xF8\x32\x81\x29\x43\x95\x4C\x9A\x19\x23\x21\x15\x45\xDE\xE3\xC8\x1C\x51\x55\x5B\xAE\x93\xE8\x37\xFF\x2B\x6B\xE9\xD4\xEA\xBE\x2A\xDD\xA8\x51\x2B\xD7\x66\xC3\x61\x5C\x60\x02\xC8\xF5\xCE\x72\x7B\x3B\xB8\xF2\x4E\x65\x08\x9A\xCD\xA4\x6A\x19\xC1\x01\xBB\x73\xA6\xD7\xF6\xC3\xDD\xCD\xBC\xA4\x8B\xB5\x99\x61\xB8\x01\xA2\xA3\xD4\x4D\xD4\x05\x3D\x91\xAD\xF8\xB4\x08\x71\x64\xAF\x70\xF1\x1C\x6B\x7E\xF6\xC3\x77\x9D\x24\x73\x7B\xE4\x0C\x8C\xE1\xD9\x36\xE1\x99\x8B\x05\x99\x0B\xED\x45\x31\x09\xCA\xC2\x00\xDB\xF7\x72\xA0\x96\xAA\x95\x87\xD0\x8E\xC7\xB6\x61\x73\x0D\x76\x66\x8C\xDC\x1B\xB4\x63\xA2\x9F\x7F\x93\x13\x30\xF1\xA1\x27\xDB\xD9\xFF\x2C\x55\x88\x91\xA0\xE0\x4F\x07\xB0\x28\x56\x8C\x18\x1B\x97\x44\x8E\x89\xDD\xE0\x17\x6E\xE7\x2A\xEF\x8F\x39\x0A\x31\x84\x82\xD8\x40\x14\x49\x2E\x7A\x41\xE4\xA7\xFE\xE3\x64\xCC\xC1\x59\x71\x4B\x2C\x21\xA7\x5B\x7D\xE0\x1D\xD1\x2E\x81\x9B\xC3\xD8\x68\xF7\xBD\x96\x1B\xAC\x70\xB1\x16\x14\x0B\xDB\x60\xB9\x26\x01\x05\x02\x03\x01\x00\x01\xA3\x51\x30\x4F\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\x86\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB3\x03\x7E\xAE\x36\xBC\xB0\x79\xD1\xDC\x94\x26\xB6\x11\xBE\x21\xB2\x69\x86\x94\x30\x10\x06\x09\x2B\x06\x01\x04\x01\x82\x37\x15\x01\x04\x03\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x4B\xA1\xFF\x0B\x87\x6E\xB3\xF9\xC1\x43\xB1\x48\xF3\x28\xC0\x1D\x2E\xC9\x09\x41\xFA\x94\x00\x1C\xA4\xA4\xAB\x49\x4F\x8F\x3D\x1E\xEF\x4D\x6F\xBD\xBC\xA4\xF6\xF2\x26\x30\xC9\x10\xCA\x1D\x88\xFB\x74\x19\x1F\x85\x45\xBD\xB0\x6C\x51\xF9\x36\x7E\xDB\xF5\x4C\x32\x3A\x41\x4F\x5B\x47\xCF\xE8\x0B\x2D\xB6\xC4\x19\x9D\x74\xC5\x47\xC6\x3B\x6A\x0F\xAC\x14\xDB\x3C\xF4\x73\x9C\xA9\x05\xDF\x00\xDC\x74\x78\xFA\xF8\x35\x60\x59\x02\x13\x18\x7C\xBC\xFB\x4D\xB0\x20\x6D\x43\xBB\x60\x30\x7A\x67\x33\x5C\xC5\x99\xD1\xF8\x2D\x39\x52\x73\xFB\x8C\xAA\x97\x25\x5C\x72\xD9\x08\x1E\xAB\x4E\x3C\xE3\x81\x31\x9F\x03\xA6\xFB\xC0\xFE\x29\x88\x55\xDA\x84\xD5\x50\x03\xB6\xE2\x84\xA3\xA6\x36\xAA\x11\x3A\x01\xE1\x18\x4B\xD6\x44\x68\xB3\x3D\xF9\x53\x74\x84\xB3\x46\x91\x46\x96\x00\xB7\x80\x2C\xB6\xE1\xE3\x10\xE2\xDB\xA2\xE7\x28\x8F\x01\x96\x62\x16\x3E\x00\xE3\x1C\xA5\x36\x81\x18\xA2\x4C\x52\x76\xC0\x11\xA3\x6E\xE6\x1D\xBA\xE3\x5A\xBE\x36\x53\xC5\x3E\x75\x8F\x86\x69\x29\x58\x53\xB5\x9C\xBB\x6F\x9F\x5C\xC5\x18\xEC\xDD\x2F\xE1\x98\xC9\xFC\xBE\xDF\x0A\x0D", + ["CN=Microsec e-Szigno Root CA,OU=e-Szigno CA,O=Microsec Ltd.,L=Budapest,C=HU"] = "\x30\x82\x07\xA8\x30\x82\x06\x90\xA0\x03\x02\x01\x02\x02\x11\x00\xCC\xB8\xE7\xBF\x4E\x29\x1A\xFD\xA2\xDC\x66\xA5\x1C\x2C\x0F\x11\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x72\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4C\x74\x64\x2E\x31\x14\x30\x12\x06\x03\x55\x04\x0B\x13\x0B\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x43\x41\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x52\x6F\x6F\x74\x20\x43\x41\x30\x1E\x17\x0D\x30\x35\x30\x34\x30\x36\x31\x32\x32\x38\x34\x34\x5A\x17\x0D\x31\x37\x30\x34\x30\x36\x31\x32\x32\x38\x34\x34\x5A\x30\x72\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4C\x74\x64\x2E\x31\x14\x30\x12\x06\x03\x55\x04\x0B\x13\x0B\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x43\x41\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x52\x6F\x6F\x74\x20\x43\x41\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\xED\xC8\x00\xD5\x81\x7B\xCD\x38\x00\x47\xCC\xDB\x84\xC1\x21\x69\x2C\x74\x90\x0C\x21\xD9\x53\x87\xED\x3E\x43\x44\x53\xAF\xAB\xF8\x80\x9B\x3C\x78\x8D\xD4\x8D\xAE\xB8\xEF\xD3\x11\xDC\x81\xE6\xCF\x3B\x96\x8C\xD6\x6F\x15\xC6\x77\x7E\xA1\x2F\xE0\x5F\x92\xB6\x27\xD7\x76\x9A\x1D\x43\x3C\xEA\xD9\xEC\x2F\xEE\x39\xF3\x6A\x67\x4B\x8B\x82\xCF\x22\xF8\x65\x55\xFE\x2C\xCB\x2F\x7D\x48\x7A\x3D\x75\xF9\xAA\xA0\x27\xBB\x78\xC2\x06\xCA\x51\xC2\x7E\x66\x4B\xAF\xCD\xA2\xA7\x4D\x02\x82\x3F\x82\xAC\x85\xC6\xE1\x0F\x90\x47\x99\x94\x0A\x71\x72\x93\x2A\xC9\xA6\xC0\xBE\x3C\x56\x4C\x73\x92\x27\xF1\x6B\xB5\xF5\xFD\xFC\x30\x05\x60\x92\xC6\xEB\x96\x7E\x01\x91\xC2\x69\xB1\x1E\x1D\x7B\x53\x45\xB8\xDC\x41\x1F\xC9\x8B\x71\xD6\x54\x14\xE3\x8B\x54\x78\x3F\xBE\xF4\x62\x3B\x5B\xF5\xA3\xEC\xD5\x92\x74\xE2\x74\x30\xEF\x01\xDB\xE1\xD4\xAB\x99\x9B\x2A\x6B\xF8\xBD\xA6\x1C\x86\x23\x42\x5F\xEC\x49\xDE\x9A\x8B\x5B\xF4\x72\x3A\x40\xC5\x49\x3E\xA5\xBE\x8E\xAA\x71\xEB\x6C\xFA\xF5\x1A\xE4\x6A\xFD\x7B\x7D\x55\x40\xEF\x58\x6E\xE6\xD9\xD5\xBC\x24\xAB\xC1\xEF\xB7\x02\x03\x01\x00\x01\xA3\x82\x04\x37\x30\x82\x04\x33\x30\x67\x06\x08\x2B\x06\x01\x05\x05\x07\x01\x01\x04\x5B\x30\x59\x30\x28\x06\x08\x2B\x06\x01\x05\x05\x07\x30\x01\x86\x1C\x68\x74\x74\x70\x73\x3A\x2F\x2F\x72\x63\x61\x2E\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x2F\x6F\x63\x73\x70\x30\x2D\x06\x08\x2B\x06\x01\x05\x05\x07\x30\x02\x86\x21\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x2F\x52\x6F\x6F\x74\x43\x41\x2E\x63\x72\x74\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x82\x01\x73\x06\x03\x55\x1D\x20\x04\x82\x01\x6A\x30\x82\x01\x66\x30\x82\x01\x62\x06\x0C\x2B\x06\x01\x04\x01\x81\xA8\x18\x02\x01\x01\x01\x30\x82\x01\x50\x30\x28\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x1C\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x2F\x53\x5A\x53\x5A\x2F\x30\x82\x01\x22\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x82\x01\x14\x1E\x82\x01\x10\x00\x41\x00\x20\x00\x74\x00\x61\x00\x6E\x00\xFA\x00\x73\x00\xED\x00\x74\x00\x76\x00\xE1\x00\x6E\x00\x79\x00\x20\x00\xE9\x00\x72\x00\x74\x00\x65\x00\x6C\x00\x6D\x00\x65\x00\x7A\x00\xE9\x00\x73\x00\xE9\x00\x68\x00\x65\x00\x7A\x00\x20\x00\xE9\x00\x73\x00\x20\x00\x65\x00\x6C\x00\x66\x00\x6F\x00\x67\x00\x61\x00\x64\x00\xE1\x00\x73\x00\xE1\x00\x68\x00\x6F\x00\x7A\x00\x20\x00\x61\x00\x20\x00\x53\x00\x7A\x00\x6F\x00\x6C\x00\x67\x00\xE1\x00\x6C\x00\x74\x00\x61\x00\x74\x00\xF3\x00\x20\x00\x53\x00\x7A\x00\x6F\x00\x6C\x00\x67\x00\xE1\x00\x6C\x00\x74\x00\x61\x00\x74\x00\xE1\x00\x73\x00\x69\x00\x20\x00\x53\x00\x7A\x00\x61\x00\x62\x00\xE1\x00\x6C\x00\x79\x00\x7A\x00\x61\x00\x74\x00\x61\x00\x20\x00\x73\x00\x7A\x00\x65\x00\x72\x00\x69\x00\x6E\x00\x74\x00\x20\x00\x6B\x00\x65\x00\x6C\x00\x6C\x00\x20\x00\x65\x00\x6C\x00\x6A\x00\xE1\x00\x72\x00\x6E\x00\x69\x00\x3A\x00\x20\x00\x68\x00\x74\x00\x74\x00\x70\x00\x3A\x00\x2F\x00\x2F\x00\x77\x00\x77\x00\x77\x00\x2E\x00\x65\x00\x2D\x00\x73\x00\x7A\x00\x69\x00\x67\x00\x6E\x00\x6F\x00\x2E\x00\x68\x00\x75\x00\x2F\x00\x53\x00\x5A\x00\x53\x00\x5A\x00\x2F\x30\x81\xC8\x06\x03\x55\x1D\x1F\x04\x81\xC0\x30\x81\xBD\x30\x81\xBA\xA0\x81\xB7\xA0\x81\xB4\x86\x21\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x2F\x52\x6F\x6F\x74\x43\x41\x2E\x63\x72\x6C\x86\x81\x8E\x6C\x64\x61\x70\x3A\x2F\x2F\x6C\x64\x61\x70\x2E\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x2F\x43\x4E\x3D\x4D\x69\x63\x72\x6F\x73\x65\x63\x25\x32\x30\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x25\x32\x30\x52\x6F\x6F\x74\x25\x32\x30\x43\x41\x2C\x4F\x55\x3D\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x25\x32\x30\x43\x41\x2C\x4F\x3D\x4D\x69\x63\x72\x6F\x73\x65\x63\x25\x32\x30\x4C\x74\x64\x2E\x2C\x4C\x3D\x42\x75\x64\x61\x70\x65\x73\x74\x2C\x43\x3D\x48\x55\x3F\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x52\x65\x76\x6F\x63\x61\x74\x69\x6F\x6E\x4C\x69\x73\x74\x3B\x62\x69\x6E\x61\x72\x79\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x81\x96\x06\x03\x55\x1D\x11\x04\x81\x8E\x30\x81\x8B\x81\x10\x69\x6E\x66\x6F\x40\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\xA4\x77\x30\x75\x31\x23\x30\x21\x06\x03\x55\x04\x03\x0C\x1A\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\xC3\xB3\x20\x52\x6F\x6F\x74\x20\x43\x41\x31\x16\x30\x14\x06\x03\x55\x04\x0B\x0C\x0D\x65\x2D\x53\x7A\x69\x67\x6E\xC3\xB3\x20\x48\x53\x5A\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4B\x66\x74\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x30\x81\xAC\x06\x03\x55\x1D\x23\x04\x81\xA4\x30\x81\xA1\x80\x14\xC7\xA0\x49\x75\x16\x61\x84\xDB\x31\x4B\x84\xD2\xF1\x37\x40\x90\xEF\x4E\xDC\xF7\xA1\x76\xA4\x74\x30\x72\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x13\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4C\x74\x64\x2E\x31\x14\x30\x12\x06\x03\x55\x04\x0B\x13\x0B\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x43\x41\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x52\x6F\x6F\x74\x20\x43\x41\x82\x11\x00\xCC\xB8\xE7\xBF\x4E\x29\x1A\xFD\xA2\xDC\x66\xA5\x1C\x2C\x0F\x11\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC7\xA0\x49\x75\x16\x61\x84\xDB\x31\x4B\x84\xD2\xF1\x37\x40\x90\xEF\x4E\xDC\xF7\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xD3\x13\x9C\x66\x63\x59\x2E\xCA\x5C\x70\x0C\xFC\x83\xBC\x55\xB1\xF4\x8E\x07\x6C\x66\x27\xCE\xC1\x3B\x20\xA9\x1C\xBB\x46\x54\x70\xEE\x5A\xCC\xA0\x77\xEA\x68\x44\x27\xEB\xF2\x29\xDD\x77\xA9\xD5\xFB\xE3\xD4\xA7\x04\xC4\x95\xB8\x0B\xE1\x44\x68\x60\x07\x43\x30\x31\x42\x61\xE5\xEE\xD9\xE5\x24\xD5\x1B\xDF\xE1\x4A\x1B\xAA\x9F\xC7\x5F\xF8\x7A\x11\xEA\x13\x93\x00\xCA\x8A\x58\xB1\xEE\xED\x0E\x4D\xB4\xD7\xA8\x36\x26\x7C\xE0\x3A\xC1\xD5\x57\x82\xF1\x75\xB6\xFD\x89\x5F\xDA\xF3\xA8\x38\x9F\x35\x06\x08\xCE\x22\x95\xBE\xCD\xD5\xFC\xBE\x5B\xDE\x79\x6B\xDC\x7A\xA9\x65\x66\xBE\xB1\x25\x5A\x5F\xED\x7E\xD3\xAC\x46\x6D\x4C\xF4\x32\x87\xB4\x20\x04\xE0\x6C\x78\xB0\x77\xD1\x85\x46\x4B\xA6\x12\xB7\x75\xE8\x4A\xC9\x56\x6C\xD7\x92\xAB\x9D\xF5\x49\x38\xD2\x4F\x53\xE3\x55\x90\x11\xDB\x98\x96\xC6\x49\xF2\x3E\xF4\x9F\x1B\xE0\xF7\x88\xDC\x25\x62\x99\x44\xD8\x73\xBF\x3F\x30\xF3\x0C\x37\x3E\xD4\xC2\x28\x80\x73\xB1\x01\xB7\x9D\x5A\x96\x14\x01\x4B\xA9\x11\x9D\x29\x6A\x2E\xD0\x5D\x81\xC0\xCF\xB2\x20\x43\xC7\x03\xE0\x37\x4E\x5D\x0A\xDC\x59\x20\x25", + ["CN=Certigna,O=Dhimyotis,C=FR"] = "\x30\x82\x03\xA8\x30\x82\x02\x90\xA0\x03\x02\x01\x02\x02\x09\x00\xFE\xDC\xE3\x01\x0F\xC9\x48\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x34\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x0C\x09\x44\x68\x69\x6D\x79\x6F\x74\x69\x73\x31\x11\x30\x0F\x06\x03\x55\x04\x03\x0C\x08\x43\x65\x72\x74\x69\x67\x6E\x61\x30\x1E\x17\x0D\x30\x37\x30\x36\x32\x39\x31\x35\x31\x33\x30\x35\x5A\x17\x0D\x32\x37\x30\x36\x32\x39\x31\x35\x31\x33\x30\x35\x5A\x30\x34\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x0C\x09\x44\x68\x69\x6D\x79\x6F\x74\x69\x73\x31\x11\x30\x0F\x06\x03\x55\x04\x03\x0C\x08\x43\x65\x72\x74\x69\x67\x6E\x61\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\xC8\x68\xF1\xC9\xD6\xD6\xB3\x34\x75\x26\x82\x1E\xEC\xB4\xBE\xEA\x5C\xE1\x26\xED\x11\x47\x61\xE1\xA2\x7C\x16\x78\x40\x21\xE4\x60\x9E\x5A\xC8\x63\xE1\xC4\xB1\x96\x92\xFF\x18\x6D\x69\x23\xE1\x2B\x62\xF7\xDD\xE2\x36\x2F\x91\x07\xB9\x48\xCF\x0E\xEC\x79\xB6\x2C\xE7\x34\x4B\x70\x08\x25\xA3\x3C\x87\x1B\x19\xF2\x81\x07\x0F\x38\x90\x19\xD3\x11\xFE\x86\xB4\xF2\xD1\x5E\x1E\x1E\x96\xCD\x80\x6C\xCE\x3B\x31\x93\xB6\xF2\xA0\xD0\xA9\x95\x12\x7D\xA5\x9A\xCC\x6B\xC8\x84\x56\x8A\x33\xA9\xE7\x22\x15\x53\x16\xF0\xCC\x17\xEC\x57\x5F\xE9\xA2\x0A\x98\x09\xDE\xE3\x5F\x9C\x6F\xDC\x48\xE3\x85\x0B\x15\x5A\xA6\xBA\x9F\xAC\x48\xE3\x09\xB2\xF7\xF4\x32\xDE\x5E\x34\xBE\x1C\x78\x5D\x42\x5B\xCE\x0E\x22\x8F\x4D\x90\xD7\x7D\x32\x18\xB3\x0B\x2C\x6A\xBF\x8E\x3F\x14\x11\x89\x20\x0E\x77\x14\xB5\x3D\x94\x08\x87\xF7\x25\x1E\xD5\xB2\x60\x00\xEC\x6F\x2A\x28\x25\x6E\x2A\x3E\x18\x63\x17\x25\x3F\x3E\x44\x20\x16\xF6\x26\xC8\x25\xAE\x05\x4A\xB4\xE7\x63\x2C\xF3\x8C\x16\x53\x7E\x5C\xFB\x11\x1A\x08\xC1\x46\x62\x9F\x22\xB8\xF1\xC2\x8D\x69\xDC\xFA\x3A\x58\x06\xDF\x02\x03\x01\x00\x01\xA3\x81\xBC\x30\x81\xB9\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x1A\xED\xFE\x41\x39\x90\xB4\x24\x59\xBE\x01\xF2\x52\xD5\x45\xF6\x5A\x39\xDC\x11\x30\x64\x06\x03\x55\x1D\x23\x04\x5D\x30\x5B\x80\x14\x1A\xED\xFE\x41\x39\x90\xB4\x24\x59\xBE\x01\xF2\x52\xD5\x45\xF6\x5A\x39\xDC\x11\xA1\x38\xA4\x36\x30\x34\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x0C\x09\x44\x68\x69\x6D\x79\x6F\x74\x69\x73\x31\x11\x30\x0F\x06\x03\x55\x04\x03\x0C\x08\x43\x65\x72\x74\x69\x67\x6E\x61\x82\x09\x00\xFE\xDC\xE3\x01\x0F\xC9\x48\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x85\x03\x1E\x92\x71\xF6\x42\xAF\xE1\xA3\x61\x9E\xEB\xF3\xC0\x0F\xF2\xA5\xD4\xDA\x95\xE6\xD6\xBE\x68\x36\x3D\x7E\x6E\x1F\x4C\x8A\xEF\xD1\x0F\x21\x6D\x5E\xA5\x52\x63\xCE\x12\xF8\xEF\x2A\xDA\x6F\xEB\x37\xFE\x13\x02\xC7\xCB\x3B\x3E\x22\x6B\xDA\x61\x2E\x7F\xD4\x72\x3D\xDD\x30\xE1\x1E\x4C\x40\x19\x8C\x0F\xD7\x9C\xD1\x83\x30\x7B\x98\x59\xDC\x7D\xC6\xB9\x0C\x29\x4C\xA1\x33\xA2\xEB\x67\x3A\x65\x84\xD3\x96\xE2\xED\x76\x45\x70\x8F\xB5\x2B\xDE\xF9\x23\xD6\x49\x6E\x3C\x14\xB5\xC6\x9F\x35\x1E\x50\xD0\xC1\x8F\x6A\x70\x44\x02\x62\xCB\xAE\x1D\x68\x41\xA7\xAA\x57\xE8\x53\xAA\x07\xD2\x06\xF6\xD5\x14\x06\x0B\x91\x03\x75\x2C\x6C\x72\xB5\x61\x95\x9A\x0D\x8B\xB9\x0D\xE7\xF5\xDF\x54\xCD\xDE\xE6\xD8\xD6\x09\x08\x97\x63\xE5\xC1\x2E\xB0\xB7\x44\x26\xC0\x26\xC0\xAF\x55\x30\x9E\x3B\xD5\x36\x2A\x19\x04\xF4\x5C\x1E\xFF\xCF\x2C\xB7\xFF\xD0\xFD\x87\x40\x11\xD5\x11\x23\xBB\x48\xC0\x21\xA9\xA4\x28\x2D\xFD\x15\xF8\xB0\x4E\x2B\xF4\x30\x5B\x21\xFC\x11\x91\x34\xBE\x41\xEF\x7B\x9D\x97\x75\xFF\x97\x95\xC0\x96\x58\x2F\xEA\xBB\x46\xD7\xBB\xE4\xD9\x2E", + ["CN=AC Ra\C3\ADz Certic\C3\A1mara S.A.,O=Sociedad Cameral de Certificaci\C3\B3n Digital - Certic\C3\A1mara S.A.,C=CO"] = "\x30\x82\x06\x66\x30\x82\x04\x4E\xA0\x03\x02\x01\x02\x02\x0F\x07\x7E\x52\x93\x7B\xE0\x15\xE3\x57\xF0\x69\x8C\xCB\xEC\x0C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4F\x31\x47\x30\x45\x06\x03\x55\x04\x0A\x0C\x3E\x53\x6F\x63\x69\x65\x64\x61\x64\x20\x43\x61\x6D\x65\x72\x61\x6C\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\xC3\xB3\x6E\x20\x44\x69\x67\x69\x74\x61\x6C\x20\x2D\x20\x43\x65\x72\x74\x69\x63\xC3\xA1\x6D\x61\x72\x61\x20\x53\x2E\x41\x2E\x31\x23\x30\x21\x06\x03\x55\x04\x03\x0C\x1A\x41\x43\x20\x52\x61\xC3\xAD\x7A\x20\x43\x65\x72\x74\x69\x63\xC3\xA1\x6D\x61\x72\x61\x20\x53\x2E\x41\x2E\x30\x1E\x17\x0D\x30\x36\x31\x31\x32\x37\x32\x30\x34\x36\x32\x39\x5A\x17\x0D\x33\x30\x30\x34\x30\x32\x32\x31\x34\x32\x30\x32\x5A\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4F\x31\x47\x30\x45\x06\x03\x55\x04\x0A\x0C\x3E\x53\x6F\x63\x69\x65\x64\x61\x64\x20\x43\x61\x6D\x65\x72\x61\x6C\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\xC3\xB3\x6E\x20\x44\x69\x67\x69\x74\x61\x6C\x20\x2D\x20\x43\x65\x72\x74\x69\x63\xC3\xA1\x6D\x61\x72\x61\x20\x53\x2E\x41\x2E\x31\x23\x30\x21\x06\x03\x55\x04\x03\x0C\x1A\x41\x43\x20\x52\x61\xC3\xAD\x7A\x20\x43\x65\x72\x74\x69\x63\xC3\xA1\x6D\x61\x72\x61\x20\x53\x2E\x41\x2E\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xAB\x6B\x89\xA3\x53\xCC\x48\x23\x08\xFB\xC3\xCF\x51\x96\x08\x2E\xB8\x08\x7A\x6D\x3C\x90\x17\x86\xA9\xE9\xED\x2E\x13\x34\x47\xB2\xD0\x70\xDC\xC9\x3C\xD0\x8D\xCA\xEE\x4B\x17\xAB\xD0\x85\xB0\xA7\x23\x04\xCB\xA8\xA2\xFC\xE5\x75\xDB\x40\xCA\x62\x89\x8F\x50\x9E\x01\x3D\x26\x5B\x18\x84\x1C\xCB\x7C\x37\xB7\x7D\xEC\xD3\x7F\x73\x19\xB0\x6A\xB2\xD8\x88\x8A\x2D\x45\x74\xA8\xF7\xB3\xB8\xC0\xD4\xDA\xCD\x22\x89\x74\x4D\x5A\x15\x39\x73\x18\x74\x4F\xB5\xEB\x99\xA7\xC1\x1E\x88\xB4\xC2\x93\x90\x63\x97\xF3\xA7\xA7\x12\xB2\x09\x22\x07\x33\xD9\x91\xCD\x0E\x9C\x1F\x0E\x20\xC7\xEE\xBB\x33\x8D\x8F\xC2\xD2\x58\xA7\x5F\xFD\x65\x37\xE2\x88\xC2\xD8\x8F\x86\x75\x5E\xF9\x2D\xA7\x87\x33\xF2\x78\x37\x2F\x8B\xBC\x1D\x86\x37\x39\xB1\x94\xF2\xD8\xBC\x4A\x9C\x83\x18\x5A\x06\xFC\xF3\xD4\xD4\xBA\x8C\x15\x09\x25\xF0\xF9\xB6\x8D\x04\x7E\x17\x12\x33\x6B\x57\x48\x4C\x4F\xDB\x26\x1E\xEB\xCC\x90\xE7\x8B\xF9\x68\x7C\x70\x0F\xA3\x2A\xD0\x3A\x38\xDF\x37\x97\xE2\x5B\xDE\x80\x61\xD3\x80\xD8\x91\x83\x42\x5A\x4C\x04\x89\x68\x11\x3C\xAC\x5F\x68\x80\x41\xCC\x60\x42\xCE\x0D\x5A\x2A\x0C\x0F\x9B\x30\xC0\xA6\xF0\x86\xDB\xAB\x49\xD7\x97\x6D\x48\x8B\xF9\x03\xC0\x52\x67\x9B\x12\xF7\xC2\xF2\x2E\x98\x65\x42\xD9\xD6\x9A\xE3\xD0\x19\x31\x0C\xAD\x87\xD5\x57\x02\x7A\x30\xE8\x86\x26\xFB\x8F\x23\x8A\x54\x87\xE4\xBF\x3C\xEE\xEB\xC3\x75\x48\x5F\x1E\x39\x6F\x81\x62\x6C\xC5\x2D\xC4\x17\x54\x19\xB7\x37\x8D\x9C\x37\x91\xC8\xF6\x0B\xD5\xEA\x63\x6F\x83\xAC\x38\xC2\xF3\x3F\xDE\x9A\xFB\xE1\x23\x61\xF0\xC8\x26\xCB\x36\xC8\xA1\xF3\x30\x8F\xA4\xA3\xA2\xA1\xDD\x53\xB3\xDE\xF0\x9A\x32\x1F\x83\x91\x79\x30\xC1\xA9\x1F\x53\x9B\x53\xA2\x15\x53\x3F\xDD\x9D\xB3\x10\x3B\x48\x7D\x89\x0F\xFC\xED\x03\xF5\xFB\x25\x64\x75\x0E\x17\x19\x0D\x8F\x00\x16\x67\x79\x7A\x40\xFC\x2D\x59\x07\xD9\x90\xFA\x9A\xAD\x3D\xDC\x80\x8A\xE6\x5C\x35\xA2\x67\x4C\x11\x6B\xB1\xF8\x80\x64\x00\x2D\x6F\x22\x61\xC5\xAC\x4B\x26\xE5\x5A\x10\x82\x9B\xA4\x83\x7B\x34\xF7\x9E\x89\x91\x20\x97\x8E\xB7\x42\xC7\x66\xC3\xD0\xE9\xA4\xD6\xF5\x20\x8D\xC4\xC3\x95\xAC\x44\x0A\x9D\x5B\x73\x3C\x26\x3D\x2F\x4A\xBE\xA7\xC9\xA7\x10\x1E\xFB\x9F\x50\x69\xF3\x02\x03\x01\x00\x01\xA3\x81\xE6\x30\x81\xE3\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xD1\x09\xD0\xE9\xD7\xCE\x79\x74\x54\xF9\x3A\x30\xB3\xF4\x6D\x2C\x03\x03\x1B\x68\x30\x81\xA0\x06\x03\x55\x1D\x20\x04\x81\x98\x30\x81\x95\x30\x81\x92\x06\x04\x55\x1D\x20\x00\x30\x81\x89\x30\x2B\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x1F\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x63\x65\x72\x74\x69\x63\x61\x6D\x61\x72\x61\x2E\x63\x6F\x6D\x2F\x64\x70\x63\x2F\x30\x5A\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x4E\x1A\x4C\x4C\x69\x6D\x69\x74\x61\x63\x69\x6F\x6E\x65\x73\x20\x64\x65\x20\x67\x61\x72\x61\x6E\x74\xED\x61\x73\x20\x64\x65\x20\x65\x73\x74\x65\x20\x63\x65\x72\x74\x69\x66\x69\x63\x61\x64\x6F\x20\x73\x65\x20\x70\x75\x65\x64\x65\x6E\x20\x65\x6E\x63\x6F\x6E\x74\x72\x61\x72\x20\x65\x6E\x20\x6C\x61\x20\x44\x50\x43\x2E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x5C\x94\xB5\xB8\x45\x91\x4D\x8E\x61\x1F\x03\x28\x0F\x53\x7C\xE6\xA4\x59\xA9\xB3\x8A\x7A\xC5\xB0\xFF\x08\x7C\x2C\xA3\x71\x1C\x21\x13\x67\xA1\x95\x12\x40\x35\x83\x83\x8F\x74\xDB\x33\x5C\xF0\x49\x76\x0A\x81\x52\xDD\x49\xD4\x9A\x32\x33\xEF\x9B\xA7\xCB\x75\xE5\x7A\xCB\x97\x12\x90\x5C\xBA\x7B\xC5\x9B\xDF\xBB\x39\x23\xC8\xFF\x98\xCE\x0A\x4D\x22\x01\x48\x07\x7E\x8A\xC0\xD5\x20\x42\x94\x44\xEF\xBF\x77\xA2\x89\x67\x48\x1B\x40\x03\x05\xA1\x89\xEC\xCF\x62\xE3\x3D\x25\x76\x66\xBF\x26\xB7\xBB\x22\xBE\x6F\xFF\x39\x57\x74\xBA\x7A\xC9\x01\x95\xC1\x95\x51\xE8\xAB\x2C\xF8\xB1\x86\x20\xE9\x3F\xCB\x35\x5B\xD2\x17\xE9\x2A\xFE\x83\x13\x17\x40\xEE\x88\x62\x65\x5B\xD5\x3B\x60\xE9\x7B\x3C\xB8\xC9\xD5\x7F\x36\x02\x25\xAA\x68\xC2\x31\x15\xB7\x30\x65\xEB\x7F\x1D\x48\x79\xB1\xCF\x39\xE2\x42\x80\x16\xD3\xF5\x93\x23\xFC\x4C\x97\xC9\x5A\x37\x6C\x7C\x22\xD8\x4A\xCD\xD2\x8E\x36\x83\x39\x91\x90\x10\xC8\xF1\xC9\x35\x7E\x3F\xB8\xD3\x81\xC6\x20\x64\x1A\xB6\x50\xC2\x21\xA4\x78\xDC\xD0\x2F\x3B\x64\x93\x74\xF0\x96\x90\xF1\xEF\xFB\x09\x5A\x34\x40\x96\xF0\x36\x12\xC1\xA3\x74\x8C\x93\x7E\x41\xDE\x77\x8B\xEC\x86\xD9\xD2\x0F\x3F\x2D\xD1\xCC\x40\xA2\x89\x66\x48\x1E\x20\xB3\x9C\x23\x59\x73\xA9\x44\x73\xBC\x24\x79\x90\x56\x37\xB3\xC6\x29\x7E\xA3\x0F\xF1\x29\x39\xEF\x7E\x5C\x28\x32\x70\x35\xAC\xDA\xB8\xC8\x75\x66\xFC\x9B\x4C\x39\x47\x8E\x1B\x6F\x9B\x4D\x02\x54\x22\x33\xEF\x61\xBA\x9E\x29\x84\xEF\x4E\x4B\x33\x47\x76\x97\x6A\xCB\x7E\x5F\xFD\x15\xA6\x9E\x42\x43\x5B\x66\x5A\x8A\x88\x0D\xF7\x16\xB9\x3F\x51\x65\x2B\x66\x6A\x8B\xD1\x38\x52\xA2\xD6\x46\x11\xFA\xFC\x9A\x1C\x74\x9E\x8F\x97\x0B\x02\x4F\x64\xC6\xF5\x68\xD3\x4B\x2D\xFF\xA4\x37\x1E\x8B\x3F\xBF\x44\xBE\x61\x46\xA1\x84\x3D\x08\x27\x4C\x81\x20\x77\x89\x08\xEA\x67\x40\x5E\x6C\x08\x51\x5F\x34\x5A\x8C\x96\x68\xCD\xD7\xF7\x89\xC2\x1C\xD3\x32\x00\xAF\x52\xCB\xD3\x60\x5B\x2A\x3A\x47\x7E\x6B\x30\x33\xA1\x62\x29\x7F\x4A\xB9\xE1\x2D\xE7\x14\x23\x0E\x0E\x18\x47\xE1\x79\xFC\x15\x55\xD0\xB1\xFC\x25\x71\x63\x75\x33\x1C\x23\x2B\xAF\x5C\xD9\xED\x47\x77\x60\x0E\x3B\x0F\x1E\xD2\xC0\xDC\x64\x05\x89\xFC\x78\xD6\x5C\x2C\x26\x43\xA9", + ["CN=TC TrustCenter Class 2 CA II,OU=TC TrustCenter Class 2 CA,O=TC TrustCenter GmbH,C=DE"] = "\x30\x82\x04\xAA\x30\x82\x03\x92\xA0\x03\x02\x01\x02\x02\x0E\x2E\x6A\x00\x01\x00\x02\x1F\xD7\x52\x21\x2C\x11\x5C\x3B\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x76\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1C\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x20\x49\x49\x30\x1E\x17\x0D\x30\x36\x30\x31\x31\x32\x31\x34\x33\x38\x34\x33\x5A\x17\x0D\x32\x35\x31\x32\x33\x31\x32\x32\x35\x39\x35\x39\x5A\x30\x76\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1C\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x20\x49\x49\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\xAB\x80\x87\x9B\x8E\xF0\xC3\x7C\x87\xD7\xE8\x24\x82\x11\xB3\x3C\xDD\x43\x62\xEE\xF8\xC3\x45\xDA\xE8\xE1\xA0\x5F\xD1\x2A\xB2\xEA\x93\x68\xDF\xB4\xC8\xD6\x43\xE9\xC4\x75\x59\x7F\xFC\xE1\x1D\xF8\x31\x70\x23\x1B\x88\x9E\x27\xB9\x7B\xFD\x3A\xD2\xC9\xA9\xE9\x14\x2F\x90\xBE\x03\x52\xC1\x49\xCD\xF6\xFD\xE4\x08\x66\x0B\x57\x8A\xA2\x42\xA0\xB8\xD5\x7F\x69\x5C\x90\x32\xB2\x97\x0D\xCA\x4A\xDC\x46\x3E\x02\x55\x89\x53\xE3\x1A\x5A\xCB\x36\xC6\x07\x56\xF7\x8C\xCF\x11\xF4\x4C\xBB\x30\x70\x04\x95\xA5\xF6\x39\x8C\xFD\x73\x81\x08\x7D\x89\x5E\x32\x1E\x22\xA9\x22\x45\x4B\xB0\x66\x2E\x30\xCC\x9F\x65\xFD\xFC\xCB\x81\xA9\xF1\xE0\x3B\xAF\xA3\x86\xD1\x89\xEA\xC4\x45\x79\x50\x5D\xAE\xE9\x21\x74\x92\x4D\x8B\x59\x82\x8F\x94\xE3\xE9\x4A\xF1\xE7\x49\xB0\x14\xE3\xF5\x62\xCB\xD5\x72\xBD\x1F\xB9\xD2\x9F\xA0\xCD\xA8\xFA\x01\xC8\xD9\x0D\xDF\xDA\xFC\x47\x9D\xB3\xC8\x54\xDF\x49\x4A\xF1\x21\xA9\xFE\x18\x4E\xEE\x48\xD4\x19\xBB\xEF\x7D\xE4\xE2\x9D\xCB\x5B\xB6\x6E\xFF\xE3\xCD\x5A\xE7\x74\x82\x05\xBA\x80\x25\x38\xCB\xE4\x69\x9E\xAF\x41\xAA\x1A\x84\xF5\x02\x03\x01\x00\x01\xA3\x82\x01\x34\x30\x82\x01\x30\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE3\xAB\x54\x4C\x80\xA1\xDB\x56\x43\xB7\x91\x4A\xCB\xF3\x82\x7A\x13\x5C\x08\xAB\x30\x81\xED\x06\x03\x55\x1D\x1F\x04\x81\xE5\x30\x81\xE2\x30\x81\xDF\xA0\x81\xDC\xA0\x81\xD9\x86\x35\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x2F\x63\x72\x6C\x2F\x76\x32\x2F\x74\x63\x5F\x63\x6C\x61\x73\x73\x5F\x32\x5F\x63\x61\x5F\x49\x49\x2E\x63\x72\x6C\x86\x81\x9F\x6C\x64\x61\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x2F\x43\x4E\x3D\x54\x43\x25\x32\x30\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x25\x32\x30\x43\x6C\x61\x73\x73\x25\x32\x30\x32\x25\x32\x30\x43\x41\x25\x32\x30\x49\x49\x2C\x4F\x3D\x54\x43\x25\x32\x30\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x25\x32\x30\x47\x6D\x62\x48\x2C\x4F\x55\x3D\x72\x6F\x6F\x74\x63\x65\x72\x74\x73\x2C\x44\x43\x3D\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2C\x44\x43\x3D\x64\x65\x3F\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x52\x65\x76\x6F\x63\x61\x74\x69\x6F\x6E\x4C\x69\x73\x74\x3F\x62\x61\x73\x65\x3F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x8C\xD7\xDF\x7E\xEE\x1B\x80\x10\xB3\x83\xF5\xDB\x11\xEA\x6B\x4B\xA8\x92\x18\xD9\xF7\x07\x39\xF5\x2C\xBE\x06\x75\x7A\x68\x53\x15\x1C\xEA\x4A\xED\x5E\xFC\x23\xB2\x13\xA0\xD3\x09\xFF\xF6\xF6\x2E\x6B\x41\x71\x79\xCD\xE2\x6D\xFD\xAE\x59\x6B\x85\x1D\xB8\x4E\x22\x9A\xED\x66\x39\x6E\x4B\x94\xE6\x55\xFC\x0B\x1B\x8B\x77\xC1\x53\x13\x66\x89\xD9\x28\xD6\x8B\xF3\x45\x4A\x63\xB7\xFD\x7B\x0B\x61\x5D\xB8\x6D\xBE\xC3\xDC\x5B\x79\xD2\xED\x86\xE5\xA2\x4D\xBE\x5E\x74\x7C\x6A\xED\x16\x38\x1F\x7F\x58\x81\x5A\x1A\xEB\x32\x88\x2D\xB2\xF3\x39\x77\x80\xAF\x5E\xB6\x61\x75\x29\xDB\x23\x4D\x88\xCA\x50\x28\xCB\x85\xD2\xD3\x10\xA2\x59\x6E\xD3\x93\x54\x00\x7A\xA2\x46\x95\x86\x05\x9C\xA9\x19\x98\xE5\x31\x72\x0C\x00\xE2\x67\xD9\x40\xE0\x24\x33\x7B\x6F\x2C\xB9\x5C\xAB\x65\x9D\x2C\xAC\x76\xEA\x35\x99\xF5\x97\xB9\x0F\x24\xEC\xC7\x76\x21\x28\x65\xAE\x57\xE8\x07\x88\x75\x4A\x56\xA0\xD2\x05\x3A\xA4\xE6\x8D\x92\x88\x2C\xF3\xF2\xE1\xC1\xC6\x61\xDB\x41\xC5\xC7\x9B\xF7\x0E\x1A\x51\x45\xC2\x61\x6B\xDC\x64\x27\x17\x8C\x5A\xB7\xDA\x74\x28\xCD\x97\xE4\xBD", + ["CN=TC TrustCenter Class 3 CA II,OU=TC TrustCenter Class 3 CA,O=TC TrustCenter GmbH,C=DE"] = "\x30\x82\x04\xAA\x30\x82\x03\x92\xA0\x03\x02\x01\x02\x02\x0E\x4A\x47\x00\x01\x00\x02\xE5\xA0\x5D\xD6\x3F\x00\x51\xBF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x76\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1C\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x20\x49\x49\x30\x1E\x17\x0D\x30\x36\x30\x31\x31\x32\x31\x34\x34\x31\x35\x37\x5A\x17\x0D\x32\x35\x31\x32\x33\x31\x32\x32\x35\x39\x35\x39\x5A\x30\x76\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x22\x30\x20\x06\x03\x55\x04\x0B\x13\x19\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x31\x25\x30\x23\x06\x03\x55\x04\x03\x13\x1C\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x20\x49\x49\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\xB4\xE0\xBB\x51\xBB\x39\x5C\x8B\x04\xC5\x4C\x79\x1C\x23\x86\x31\x10\x63\x43\x55\x27\x3F\xC6\x45\xC7\xA4\x3D\xEC\x09\x0D\x1A\x1E\x20\xC2\x56\x1E\xDE\x1B\x37\x07\x30\x22\x2F\x6F\xF1\x06\xF1\xAB\xAD\xD6\xC8\xAB\x61\xA3\x2F\x43\xC4\xB0\xB2\x2D\xFC\xC3\x96\x69\x7B\x7E\x8A\xE4\xCC\xC0\x39\x12\x90\x42\x60\xC9\xCC\x35\x68\xEE\xDA\x5F\x90\x56\x5F\xCD\x1C\x4D\x5B\x58\x49\xEB\x0E\x01\x4F\x64\xFA\x2C\x3C\x89\x58\xD8\x2F\x2E\xE2\xB0\x68\xE9\x22\x3B\x75\x89\xD6\x44\x1A\x65\xF2\x1B\x97\x26\x1D\x28\x6D\xAC\xE8\xBD\x59\x1D\x2B\x24\xF6\xD6\x84\x03\x66\x88\x24\x00\x78\x60\xF1\xF8\xAB\xFE\x02\xB2\x6B\xFB\x22\xFB\x35\xE6\x16\xD1\xAD\xF6\x2E\x12\xE4\xFA\x35\x6A\xE5\x19\xB9\x5D\xDB\x3B\x1E\x1A\xFB\xD3\xFF\x15\x14\x08\xD8\x09\x6A\xBA\x45\x9D\x14\x79\x60\x7D\xAF\x40\x8A\x07\x73\xB3\x93\x96\xD3\x74\x34\x8D\x3A\x37\x29\xDE\x5C\xEC\xF5\xEE\x2E\x31\xC2\x20\xDC\xBE\xF1\x4F\x7F\x23\x52\xD9\x5B\xE2\x64\xD9\x9C\xAA\x07\x08\xB5\x45\xBD\xD1\xD0\x31\xC1\xAB\x54\x9F\xA9\xD2\xC3\x62\x60\x03\xF1\xBB\x39\x4A\x92\x4A\x3D\x0A\xB9\x9D\xC5\xA0\xFE\x37\x02\x03\x01\x00\x01\xA3\x82\x01\x34\x30\x82\x01\x30\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xD4\xA2\xFC\x9F\xB3\xC3\xD8\x03\xD3\x57\x5C\x07\xA4\xD0\x24\xA7\xC0\xF2\x00\xD4\x30\x81\xED\x06\x03\x55\x1D\x1F\x04\x81\xE5\x30\x81\xE2\x30\x81\xDF\xA0\x81\xDC\xA0\x81\xD9\x86\x35\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x2F\x63\x72\x6C\x2F\x76\x32\x2F\x74\x63\x5F\x63\x6C\x61\x73\x73\x5F\x33\x5F\x63\x61\x5F\x49\x49\x2E\x63\x72\x6C\x86\x81\x9F\x6C\x64\x61\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2E\x64\x65\x2F\x43\x4E\x3D\x54\x43\x25\x32\x30\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x25\x32\x30\x43\x6C\x61\x73\x73\x25\x32\x30\x33\x25\x32\x30\x43\x41\x25\x32\x30\x49\x49\x2C\x4F\x3D\x54\x43\x25\x32\x30\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x25\x32\x30\x47\x6D\x62\x48\x2C\x4F\x55\x3D\x72\x6F\x6F\x74\x63\x65\x72\x74\x73\x2C\x44\x43\x3D\x74\x72\x75\x73\x74\x63\x65\x6E\x74\x65\x72\x2C\x44\x43\x3D\x64\x65\x3F\x63\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x52\x65\x76\x6F\x63\x61\x74\x69\x6F\x6E\x4C\x69\x73\x74\x3F\x62\x61\x73\x65\x3F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x36\x60\xE4\x70\xF7\x06\x20\x43\xD9\x23\x1A\x42\xF2\xF8\xA3\xB2\xB9\x4D\x8A\xB4\xF3\xC2\x9A\x55\x31\x7C\xC4\x3B\x67\x9A\xB4\xDF\x4D\x0E\x8A\x93\x4A\x17\x8B\x1B\x8D\xCA\x89\xE1\xCF\x3A\x1E\xAC\x1D\xF1\x9C\x32\xB4\x8E\x59\x76\xA2\x41\x85\x25\x37\xA0\x13\xD0\xF5\x7C\x4E\xD5\xEA\x96\xE2\x6E\x72\xC1\xBB\x2A\xFE\x6C\x6E\xF8\x91\x98\x46\xFC\xC9\x1B\x57\x5B\xEA\xC8\x1A\x3B\x3F\xB0\x51\x98\x3C\x07\xDA\x2C\x59\x01\xDA\x8B\x44\xE8\xE1\x74\xFD\xA7\x68\xDD\x54\xBA\x83\x46\xEC\xC8\x46\xB5\xF8\xAF\x97\xC0\x3B\x09\x1C\x8F\xCE\x72\x96\x3D\x33\x56\x70\xBC\x96\xCB\xD8\xD5\x7D\x20\x9A\x83\x9F\x1A\xDC\x39\xF1\xC5\x72\xA3\x11\x03\xFD\x3B\x42\x52\x29\xDB\xE8\x01\xF7\x9B\x5E\x8C\xD6\x8D\x86\x4E\x19\xFA\xBC\x1C\xBE\xC5\x21\xA5\x87\x9E\x78\x2E\x36\xDB\x09\x71\xA3\x72\x34\xF8\x6C\xE3\x06\x09\xF2\x5E\x56\xA5\xD3\xDD\x98\xFA\xD4\xE6\x06\xF4\xF0\xB6\x20\x63\x4B\xEA\x29\xBD\xAA\x82\x66\x1E\xFB\x81\xAA\xA7\x37\xAD\x13\x18\xE6\x92\xC3\x81\xC1\x33\xBB\x88\x1E\xA1\xE7\xE2\xB4\xBD\x31\x6C\x0E\x51\x3D\x6F\xFB\x96\x56\x80\xE2\x36\x17\xD1\xDC\xE4", + ["CN=TC TrustCenter Universal CA I,OU=TC TrustCenter Universal CA,O=TC TrustCenter GmbH,C=DE"] = "\x30\x82\x03\xDD\x30\x82\x02\xC5\xA0\x03\x02\x01\x02\x02\x0E\x1D\xA2\x00\x01\x00\x02\xEC\xB7\x60\x80\x78\x8D\xB6\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x79\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0B\x13\x1B\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x49\x30\x1E\x17\x0D\x30\x36\x30\x33\x32\x32\x31\x35\x35\x34\x32\x38\x5A\x17\x0D\x32\x35\x31\x32\x33\x31\x32\x32\x35\x39\x35\x39\x5A\x30\x79\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0B\x13\x1B\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x31\x26\x30\x24\x06\x03\x55\x04\x03\x13\x1D\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x49\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\xA4\x77\x23\x96\x44\xAF\x90\xF4\x31\xA7\x10\xF4\x26\x87\x9C\xF3\x38\xD9\x0F\x5E\xDE\xCF\x41\xE8\x31\xAD\xC6\x74\x91\x24\x96\x78\x1E\x09\xA0\x9B\x9A\x95\x4A\x4A\xF5\x62\x7C\x02\xA8\xCA\xAC\xFB\x5A\x04\x76\x39\xDE\x5F\xF1\xF9\xB3\xBF\xF3\x03\x58\x55\xD2\xAA\xB7\xE3\x04\x22\xD1\xF8\x94\xDA\x22\x08\x00\x8D\xD3\x7C\x26\x5D\xCC\x77\x79\xE7\x2C\x78\x39\xA8\x26\x73\x0E\xA2\x5D\x25\x69\x85\x4F\x55\x0E\x9A\xEF\xC6\xB9\x44\xE1\x57\x3D\xDF\x1F\x54\x22\xE5\x6F\x65\xAA\x33\x84\x3A\xF3\xCE\x7A\xBE\x55\x97\xAE\x8D\x12\x0F\x14\x33\xE2\x50\x70\xC3\x49\x87\x13\xBC\x51\xDE\xD7\x98\x12\x5A\xEF\x3A\x83\x33\x92\x06\x75\x8B\x92\x7C\x12\x68\x7B\x70\x6A\x0F\xB5\x9B\xB6\x77\x5B\x48\x59\x9D\xE4\xEF\x5A\xAD\xF3\xC1\x9E\xD4\xD7\x45\x4E\xCA\x56\x34\x21\xBC\x3E\x17\x5B\x6F\x77\x0C\x48\x01\x43\x29\xB0\xDD\x3F\x96\x6E\xE6\x95\xAA\x0C\xC0\x20\xB6\xFD\x3E\x36\x27\x9C\xE3\x5C\xCF\x4E\x81\xDC\x19\xBB\x91\x90\x7D\xEC\xE6\x97\x04\x1E\x93\xCC\x22\x49\xD7\x97\x86\xB6\x13\x0A\x3C\x43\x23\x77\x7E\xF0\xDC\xE6\xCD\x24\x1F\x3B\x83\x9B\x34\x3A\x83\x34\xE3\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x92\xA4\x75\x2C\xA4\x9E\xBE\x81\x44\xEB\x79\xFC\x8A\xC5\x95\xA5\xEB\x10\x75\x73\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x92\xA4\x75\x2C\xA4\x9E\xBE\x81\x44\xEB\x79\xFC\x8A\xC5\x95\xA5\xEB\x10\x75\x73\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x28\xD2\xE0\x86\xD5\xE6\xF8\x7B\xF0\x97\xDC\x22\x6B\x3B\x95\x14\x56\x0F\x11\x30\xA5\x9A\x4F\x3A\xB0\x3A\xE0\x06\xCB\x65\xF5\xED\xC6\x97\x27\xFE\x25\xF2\x57\xE6\x5E\x95\x8C\x3E\x64\x60\x15\x5A\x7F\x2F\x0D\x01\xC5\xB1\x60\xFD\x45\x35\xCF\xF0\xB2\xBF\x06\xD9\xEF\x5A\xBE\xB3\x62\x21\xB4\xD7\xAB\x35\x7C\x53\x3E\xA6\x27\xF1\xA1\x2D\xDA\x1A\x23\x9D\xCC\xDD\xEC\x3C\x2D\x9E\x27\x34\x5D\x0F\xC2\x36\x79\xBC\xC9\x4A\x62\x2D\xED\x6B\xD9\x7D\x41\x43\x7C\xB6\xAA\xCA\xED\x61\xB1\x37\x82\x15\x09\x1A\x8A\x16\x30\xD8\xEC\xC9\xD6\x47\x72\x78\x4B\x10\x46\x14\x8E\x5F\x0E\xAF\xEC\xC7\x2F\xAB\x10\xD7\xB6\xF1\x6E\xEC\x86\xB2\xC2\xE8\x0D\x92\x73\xDC\xA2\xF4\x0F\x3A\xBF\x61\x23\x10\x89\x9C\x48\x40\x6E\x70\x00\xB3\xD3\xBA\x37\x44\x58\x11\x7A\x02\x6A\x88\xF0\x37\x34\xF0\x19\xE9\xAC\xD4\x65\x73\xF6\x69\x8C\x64\x94\x3A\x79\x85\x29\xB0\x16\x2B\x0C\x82\x3F\x06\x9C\xC7\xFD\x10\x2B\x9E\x0F\x2C\xB6\x9E\xE3\x15\xBF\xD9\x36\x1C\xBA\x25\x1A\x52\x3D\x1A\xEC\x22\x0C\x1C\xE0\xA4\xA2\x3D\xF0\xE8\x39\xCF\x81\xC0\x7B\xED\x5D\x1F\x6F\xC5\xD0\x0B\xD7\x98", + ["CN=Deutsche Telekom Root CA 2,OU=T-TeleSec Trust Center,O=Deutsche Telekom AG,C=DE"] = "\x30\x82\x03\x9F\x30\x82\x02\x87\xA0\x03\x02\x01\x02\x02\x01\x26\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x71\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x44\x65\x75\x74\x73\x63\x68\x65\x20\x54\x65\x6C\x65\x6B\x6F\x6D\x20\x41\x47\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x54\x2D\x54\x65\x6C\x65\x53\x65\x63\x20\x54\x72\x75\x73\x74\x20\x43\x65\x6E\x74\x65\x72\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x44\x65\x75\x74\x73\x63\x68\x65\x20\x54\x65\x6C\x65\x6B\x6F\x6D\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x1E\x17\x0D\x39\x39\x30\x37\x30\x39\x31\x32\x31\x31\x30\x30\x5A\x17\x0D\x31\x39\x30\x37\x30\x39\x32\x33\x35\x39\x30\x30\x5A\x30\x71\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x44\x65\x75\x74\x73\x63\x68\x65\x20\x54\x65\x6C\x65\x6B\x6F\x6D\x20\x41\x47\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x54\x2D\x54\x65\x6C\x65\x53\x65\x63\x20\x54\x72\x75\x73\x74\x20\x43\x65\x6E\x74\x65\x72\x31\x23\x30\x21\x06\x03\x55\x04\x03\x13\x1A\x44\x65\x75\x74\x73\x63\x68\x65\x20\x54\x65\x6C\x65\x6B\x6F\x6D\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\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\xAB\x0B\xA3\x35\xE0\x8B\x29\x14\xB1\x14\x85\xAF\x3C\x10\xE4\x39\x6F\x35\x5D\x4A\xAE\xDD\xEA\x61\x8D\x95\x49\xF4\x6F\x64\xA3\x1A\x60\x66\xA4\xA9\x40\x22\x84\xD9\xD4\xA5\xE5\x78\x93\x0E\x68\x01\xAD\xB9\x4D\x5C\x3A\xCE\xD3\xB8\xA8\x42\x40\xDF\xCF\xA3\xBA\x82\x59\x6A\x92\x1B\xAC\x1C\x9A\xDA\x08\x2B\x25\x27\xF9\x69\x23\x47\xF1\xE0\xEB\x2C\x7A\x9B\xF5\x13\x02\xD0\x7E\x34\x7C\xC2\x9E\x3C\x00\x59\xAB\xF5\xDA\x0C\xF5\x32\x3C\x2B\xAC\x50\xDA\xD6\xC3\xDE\x83\x94\xCA\xA8\x0C\x99\x32\x0E\x08\x48\x56\x5B\x6A\xFB\xDA\xE1\x58\x58\x01\x49\x5F\x72\x41\x3C\x15\x06\x01\x8E\x5D\xAD\xAA\xB8\x93\xB4\xCD\x9E\xEB\xA7\xE8\x6A\x2D\x52\x34\xDB\x3A\xEF\x5C\x75\x51\xDA\xDB\xF3\x31\xF9\xEE\x71\x98\x32\xC4\x54\x15\x44\x0C\xF9\x9B\x55\xED\xAD\xDF\x18\x08\xA0\xA3\x86\x8A\x49\xEE\x53\x05\x8F\x19\x4C\xD5\xDE\x58\x79\x9B\xD2\x6A\x1C\x42\xAB\xC5\xD5\xA7\xCF\x68\x0F\x96\xE4\xE1\x61\x98\x76\x61\xC8\x91\x7C\xD6\x3E\x00\xE2\x91\x50\x87\xE1\x9D\x0A\xE6\xAD\x97\xD2\x1D\xC6\x3A\x7D\xCB\xBC\xDA\x03\x34\xD5\x8E\x5B\x01\xF5\x6A\x07\xB7\x16\xB6\x6E\x4A\x7F\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x31\xC3\x79\x1B\xBA\xF5\x53\xD7\x17\xE0\x89\x7A\x2D\x17\x6C\x0A\xB3\x2B\x9D\x33\x30\x0F\x06\x03\x55\x1D\x13\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x05\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x94\x64\x59\xAD\x39\x64\xE7\x29\xEB\x13\xFE\x5A\xC3\x8B\x13\x57\xC8\x04\x24\xF0\x74\x77\xC0\x60\xE3\x67\xFB\xE9\x89\xA6\x83\xBF\x96\x82\x7C\x6E\xD4\xC3\x3D\xEF\x9E\x80\x6E\xBB\x29\xB4\x98\x7A\xB1\x3B\x54\xEB\x39\x17\x47\x7E\x1A\x8E\x0B\xFC\x1F\x31\x59\x31\x04\xB2\xCE\x17\xF3\x2C\xC7\x62\x36\x55\xE2\x22\xD8\x89\x55\xB4\x98\x48\xAA\x64\xFA\xD6\x1C\x36\xD8\x44\x78\x5A\x5A\x23\x3A\x57\x97\xF5\x7A\x30\x4F\xAE\x9F\x6A\x4C\x4B\x2B\x8E\xA0\x03\xE3\x3E\xE0\xA9\xD4\xD2\x7B\xD2\xB3\xA8\xE2\x72\x3C\xAD\x9E\xFF\x80\x59\xE4\x9B\x45\xB4\xF6\x3B\xB0\xCD\x39\x19\x98\x32\xE5\xEA\x21\x61\x90\xE4\x31\x21\x8E\x34\xB1\xF7\x2F\x35\x4A\x85\x10\xDA\xE7\x8A\x37\x21\xBE\x59\x63\xE0\xF2\x85\x88\x31\x53\xD4\x54\x14\x85\x70\x79\xF4\x2E\x06\x77\x27\x75\x2F\x1F\xB8\x8A\xF9\xFE\xC5\xBA\xD8\x36\xE4\x83\xEC\xE7\x65\xB7\xBF\x63\x5A\xF3\x46\xAF\x81\x94\x37\xD4\x41\x8C\xD6\x23\xD6\x1E\xCF\xF5\x68\x1B\x44\x63\xA2\x5A\xBA\xA7\x35\x59\xA1\xE5\x70\x05\x9B\x0E\x23\x57\x99\x94\x0A\x6D\xBA\x39\x63\x28\x86\x92\xF3\x18\x84\xD8\xFB\xD1\xCF\x05\x56\x64\x57", + ["C=IL,O=ComSign,CN=ComSign Secured CA"] = "\x30\x82\x03\xAB\x30\x82\x02\x93\xA0\x03\x02\x01\x02\x02\x11\x00\xC7\x28\x47\x09\xB3\xB8\x6C\x45\x8C\x1D\xFA\x24\xF5\x36\x4E\xE9\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3C\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x43\x6F\x6D\x53\x69\x67\x6E\x20\x53\x65\x63\x75\x72\x65\x64\x20\x43\x41\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x43\x6F\x6D\x53\x69\x67\x6E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4C\x30\x1E\x17\x0D\x30\x34\x30\x33\x32\x34\x31\x31\x33\x37\x32\x30\x5A\x17\x0D\x32\x39\x30\x33\x31\x36\x31\x35\x30\x34\x35\x36\x5A\x30\x3C\x31\x1B\x30\x19\x06\x03\x55\x04\x03\x13\x12\x43\x6F\x6D\x53\x69\x67\x6E\x20\x53\x65\x63\x75\x72\x65\x64\x20\x43\x41\x31\x10\x30\x0E\x06\x03\x55\x04\x0A\x13\x07\x43\x6F\x6D\x53\x69\x67\x6E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x49\x4C\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\xC6\xB5\x68\x5F\x1D\x94\x15\xC3\xA4\x08\x55\x2D\xE3\xA0\x57\x7A\xEF\xE9\x74\x2A\xBB\xB9\x7C\x57\x49\x1A\x11\x5E\x4F\x29\x87\x0C\x48\xD6\x6A\xE7\x8F\xD4\x7E\x57\x24\xB9\x06\x89\xE4\x1C\x3C\xEA\xAC\xE3\xDA\x21\x80\x73\x21\x0A\xEF\x79\x98\x6C\x1F\x08\xFF\xA1\x50\x7D\xF2\x98\x1B\xC9\x54\x6F\x3E\xA5\x28\xEC\x21\x04\x0F\x45\xBB\x07\x3D\xA1\xC0\xFA\x2A\x98\x1D\x4E\x06\x93\xFB\xF5\x88\x3B\xAB\x5F\xCB\x16\xBF\xE6\xF3\x9E\x4A\x87\xED\x19\xEA\xC2\x9F\x43\xE4\xF1\x81\xA5\x7F\x10\x4F\x3E\xD1\x4A\x62\xAD\x53\x1B\xCB\x83\xFF\x07\x65\xA5\x92\x2D\x66\xA9\x5B\xB8\x5A\xF4\x1D\xB4\x21\x91\x4A\x17\x7B\x9E\x32\xFE\x56\x24\x39\xB2\x54\x84\x43\xF5\x84\xC2\xD8\xBC\x41\x90\xCC\x9D\xD6\x68\xDA\xE9\x82\x50\xA9\x3B\x68\xCF\xB5\x5D\x02\x94\x60\x16\xB1\x43\xD9\x43\x5D\xDD\x5D\x87\x6E\xEA\xBB\xB3\xC9\x6B\xF6\x03\x94\x09\x70\xDE\x16\x11\x7A\x2B\xE8\x76\x8F\x49\x10\x98\x77\xB9\x63\x5C\x8B\x33\x97\x75\xF6\x0B\x8C\xB2\xAB\x5B\xDE\x74\x20\x25\x3F\xE3\xF3\x11\xF9\x87\x68\x86\x35\x71\xC3\x1D\x8C\x2D\xEB\xE5\x1A\xAC\x0F\x73\xD5\x82\x59\x40\x80\xD3\x02\x03\x01\x00\x01\xA3\x81\xA7\x30\x81\xA4\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x44\x06\x03\x55\x1D\x1F\x04\x3D\x30\x3B\x30\x39\xA0\x37\xA0\x35\x86\x33\x68\x74\x74\x70\x3A\x2F\x2F\x66\x65\x64\x69\x72\x2E\x63\x6F\x6D\x73\x69\x67\x6E\x2E\x63\x6F\x2E\x69\x6C\x2F\x63\x72\x6C\x2F\x43\x6F\x6D\x53\x69\x67\x6E\x53\x65\x63\x75\x72\x65\x64\x43\x41\x2E\x63\x72\x6C\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xC1\x4B\xED\x70\xB6\xF7\x3E\x7C\x00\x3B\x00\x8F\xC7\x3E\x0E\x45\x9F\x1E\x5D\xEC\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC1\x4B\xED\x70\xB6\xF7\x3E\x7C\x00\x3B\x00\x8F\xC7\x3E\x0E\x45\x9F\x1E\x5D\xEC\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x16\xCF\xEE\x92\x13\x50\xAB\x7B\x14\x9E\x33\xB6\x42\x20\x6A\xD4\x15\xBD\x09\xAB\xFC\x72\xE8\xEF\x47\x7A\x90\xAC\x51\xC1\x64\x4E\xE9\x88\xBD\x43\x45\x81\xE3\x66\x23\x3F\x12\x86\x4D\x19\xE4\x05\xB0\xE6\x37\xC2\x8D\xDA\x06\x28\xC9\x0F\x89\xA4\x53\xA9\x75\x3F\xB0\x96\xFB\xAB\x4C\x33\x55\xF9\x78\x26\x46\x6F\x1B\x36\x98\xFB\x42\x76\xC1\x82\xB9\x8E\xDE\xFB\x45\xF9\x63\x1B\x62\x3B\x39\x06\xCA\x77\x7A\xA8\x3C\x09\xCF\x6C\x36\x3D\x0F\x0A\x45\x4B\x69\x16\x1A\x45\x7D\x33\x03\x65\xF9\x52\x71\x90\x26\x95\xAC\x4C\x0C\xF5\x8B\x93\x3F\xCC\x75\x74\x85\x98\xBA\xFF\x62\x7A\x4D\x1F\x89\xFE\xAE\xBD\x94\x00\x99\xBF\x11\xA5\xDC\xE0\x79\xC5\x16\x0B\x7D\x02\x61\x1D\xEA\x85\xF9\x02\x15\x4F\xE7\x5A\x89\x4E\x14\x6F\xE3\x37\x4B\x85\xF5\xC1\x3C\x61\xE0\xFD\x05\x41\xB2\x92\x7F\xC3\x1D\xA0\xD0\xAE\x52\x64\x60\x6B\x18\xC6\x26\x9C\xD8\xF5\x64\xE4\x36\x1A\x62\x9F\x8A\x0F\x3E\xFF\x6D\x4E\x19\x56\x4E\x20\x91\x6C\x9F\x34\x33\x3A\x34\x57\x50\x3A\x6F\x81\x5E\x06\xC6\xF5\x3E\x7C\x4E\x8E\x2B\xCE\x65\x06\x2E\x5D\xD2\x2A\x53\x74\x5E\xD3\x6E\x27\x9E\x8F", + ["CN=Cybertrust Global Root,O=Cybertrust\, Inc"] = "\x30\x82\x03\xA1\x30\x82\x02\x89\xA0\x03\x02\x01\x02\x02\x0B\x04\x00\x00\x00\x00\x01\x0F\x85\xAA\x2D\x48\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3B\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x13\x0F\x43\x79\x62\x65\x72\x74\x72\x75\x73\x74\x2C\x20\x49\x6E\x63\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x43\x79\x62\x65\x72\x74\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\x30\x1E\x17\x0D\x30\x36\x31\x32\x31\x35\x30\x38\x30\x30\x30\x30\x5A\x17\x0D\x32\x31\x31\x32\x31\x35\x30\x38\x30\x30\x30\x30\x5A\x30\x3B\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x13\x0F\x43\x79\x62\x65\x72\x74\x72\x75\x73\x74\x2C\x20\x49\x6E\x63\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x13\x16\x43\x79\x62\x65\x72\x74\x72\x75\x73\x74\x20\x47\x6C\x6F\x62\x61\x6C\x20\x52\x6F\x6F\x74\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\xF8\xC8\xBC\xBD\x14\x50\x66\x13\xFF\xF0\xD3\x79\xEC\x23\xF2\xB7\x1A\xC7\x8E\x85\xF1\x12\x73\xA6\x19\xAA\x10\xDB\x9C\xA2\x65\x74\x5A\x77\x3E\x51\x7D\x56\xF6\xDC\x23\xB6\xD4\xED\x5F\x58\xB1\x37\x4D\xD5\x49\x0E\x6E\xF5\x6A\x87\xD6\xD2\x8C\xD2\x27\xC6\xE2\xFF\x36\x9F\x98\x65\xA0\x13\x4E\xC6\x2A\x64\x9B\xD5\x90\x12\xCF\x14\x06\xF4\x3B\xE3\xD4\x28\xBE\xE8\x0E\xF8\xAB\x4E\x48\x94\x6D\x8E\x95\x31\x10\x5C\xED\xA2\x2D\xBD\xD5\x3A\x6D\xB2\x1C\xBB\x60\xC0\x46\x4B\x01\xF5\x49\xAE\x7E\x46\x8A\xD0\x74\x8D\xA1\x0C\x02\xCE\xEE\xFC\xE7\x8F\xB8\x6B\x66\xF3\x7F\x44\x00\xBF\x66\x25\x14\x2B\xDD\x10\x30\x1D\x07\x96\x3F\x4D\xF6\x6B\xB8\x8F\xB7\x7B\x0C\xA5\x38\xEB\xDE\x47\xDB\xD5\x5D\x39\xFC\x88\xA7\xF3\xD7\x2A\x74\xF1\xE8\x5A\xA2\x3B\x9F\x50\xBA\xA6\x8C\x45\x35\xC2\x50\x65\x95\xDC\x63\x82\xEF\xDD\xBF\x77\x4D\x9C\x62\xC9\x63\x73\x16\xD0\x29\x0F\x49\xA9\x48\xF0\xB3\xAA\xB7\x6C\xC5\xA7\x30\x39\x40\x5D\xAE\xC4\xE2\x5D\x26\x53\xF0\xCE\x1C\x23\x08\x61\xA8\x94\x19\xBA\x04\x62\x40\xEC\x1F\x38\x70\x77\x12\x06\x71\xA7\x30\x18\x5D\x25\x27\xA5\x02\x03\x01\x00\x01\xA3\x81\xA5\x30\x81\xA2\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB6\x08\x7B\x0D\x7A\xCC\xAC\x20\x4C\x86\x56\x32\x5E\xCF\xAB\x6E\x85\x2D\x70\x57\x30\x3F\x06\x03\x55\x1D\x1F\x04\x38\x30\x36\x30\x34\xA0\x32\xA0\x30\x86\x2E\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x32\x2E\x70\x75\x62\x6C\x69\x63\x2D\x74\x72\x75\x73\x74\x2E\x63\x6F\x6D\x2F\x63\x72\x6C\x2F\x63\x74\x2F\x63\x74\x72\x6F\x6F\x74\x2E\x63\x72\x6C\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xB6\x08\x7B\x0D\x7A\xCC\xAC\x20\x4C\x86\x56\x32\x5E\xCF\xAB\x6E\x85\x2D\x70\x57\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x56\xEF\x0A\x23\xA0\x54\x4E\x95\x97\xC9\xF8\x89\xDA\x45\xC1\xD4\xA3\x00\x25\xF4\x1F\x13\xAB\xB7\xA3\x85\x58\x69\xC2\x30\xAD\xD8\x15\x8A\x2D\xE3\xC9\xCD\x81\x5A\xF8\x73\x23\x5A\xA7\x7C\x05\xF3\xFD\x22\x3B\x0E\xD1\x06\xC4\xDB\x36\x4C\x73\x04\x8E\xE5\xB0\x22\xE4\xC5\xF3\x2E\xA5\xD9\x23\xE3\xB8\x4E\x4A\x20\xA7\x6E\x02\x24\x9F\x22\x60\x67\x7B\x8B\x1D\x72\x09\xC5\x31\x5C\xE9\x79\x9F\x80\x47\x3D\xAD\xA1\x0B\x07\x14\x3D\x47\xFF\x03\x69\x1A\x0C\x0B\x44\xE7\x63\x25\xA7\x7F\xB2\xC9\xB8\x76\x84\xED\x23\xF6\x7D\x07\xAB\x45\x7E\xD3\xDF\xB3\xBF\xE9\x8A\xB6\xCD\xA8\xA2\x67\x2B\x52\xD5\xB7\x65\xF0\x39\x4C\x63\xA0\x91\x79\x93\x52\x0F\x54\xDD\x83\xBB\x9F\xD1\x8F\xA7\x53\x73\xC3\xCB\xFF\x30\xEC\x7C\x04\xB8\xD8\x44\x1F\x93\x5F\x71\x09\x22\xB7\x6E\x3E\xEA\x1C\x03\x4E\x9D\x1A\x20\x61\xFB\x81\x37\xEC\x5E\xFC\x0A\x45\xAB\xD7\xE7\x17\x55\xD0\xA0\xEA\x60\x9B\xA6\xF6\xE3\x8C\x5B\x29\xC2\x06\x60\x14\x9D\x2D\x97\x4C\xA9\x93\x15\x9D\x61\xC4\x01\x5F\x48\xD6\x58\xBD\x56\x31\x12\x4E\x11\xC8\x21\xE0\xB3\x11\x91\x65\xDB\xB4\xA6\x88\x38\xCE\x55", + ["OU=ePKI Root Certification Authority,O=Chunghwa Telecom Co.\, Ltd.,C=TW"] = "\x30\x82\x05\xB0\x30\x82\x03\x98\xA0\x03\x02\x01\x02\x02\x10\x15\xC8\xBD\x65\x47\x5C\xAF\xB8\x97\x00\x5E\xE4\x06\xD2\xBC\x9D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x5E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x23\x30\x21\x06\x03\x55\x04\x0A\x0C\x1A\x43\x68\x75\x6E\x67\x68\x77\x61\x20\x54\x65\x6C\x65\x63\x6F\x6D\x20\x43\x6F\x2E\x2C\x20\x4C\x74\x64\x2E\x31\x2A\x30\x28\x06\x03\x55\x04\x0B\x0C\x21\x65\x50\x4B\x49\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x34\x31\x32\x32\x30\x30\x32\x33\x31\x32\x37\x5A\x17\x0D\x33\x34\x31\x32\x32\x30\x30\x32\x33\x31\x32\x37\x5A\x30\x5E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x23\x30\x21\x06\x03\x55\x04\x0A\x0C\x1A\x43\x68\x75\x6E\x67\x68\x77\x61\x20\x54\x65\x6C\x65\x63\x6F\x6D\x20\x43\x6F\x2E\x2C\x20\x4C\x74\x64\x2E\x31\x2A\x30\x28\x06\x03\x55\x04\x0B\x0C\x21\x65\x50\x4B\x49\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xE1\x25\x0F\xEE\x8D\xDB\x88\x33\x75\x67\xCD\xAD\x1F\x7D\x3A\x4E\x6D\x9D\xD3\x2F\x14\xF3\x63\x74\xCB\x01\x21\x6A\x37\xEA\x84\x50\x07\x4B\x26\x5B\x09\x43\x6C\x21\x9E\x6A\xC8\xD5\x03\xF5\x60\x69\x8F\xCC\xF0\x22\xE4\x1F\xE7\xF7\x6A\x22\x31\xB7\x2C\x15\xF2\xE0\xFE\x00\x6A\x43\xFF\x87\x65\xC6\xB5\x1A\xC1\xA7\x4C\x6D\x22\x70\x21\x8A\x31\xF2\x97\x74\x89\x09\x12\x26\x1C\x9E\xCA\xD9\x12\xA2\x95\x3C\xDA\xE9\x67\xBF\x08\xA0\x64\xE3\xD6\x42\xB7\x45\xEF\x97\xF4\xF6\xF5\xD7\xB5\x4A\x15\x02\x58\x7D\x98\x58\x4B\x60\xBC\xCD\xD7\x0D\x9A\x13\x33\x53\xD1\x61\xF9\x7A\xD5\xD7\x78\xB3\x9A\x33\xF7\x00\x86\xCE\x1D\x4D\x94\x38\xAF\xA8\xEC\x78\x51\x70\x8A\x5C\x10\x83\x51\x21\xF7\x11\x3D\x34\x86\x5E\xE5\x48\xCD\x97\x81\x82\x35\x4C\x19\xEC\x65\xF6\x6B\xC5\x05\xA1\xEE\x47\x13\xD6\xB3\x21\x27\x94\x10\x0A\xD9\x24\x3B\xBA\xBE\x44\x13\x46\x30\x3F\x97\x3C\xD8\xD7\xD7\x6A\xEE\x3B\x38\xE3\x2B\xD4\x97\x0E\xB9\x1B\xE7\x07\x49\x7F\x37\x2A\xF9\x77\x78\xCF\x54\xED\x5B\x46\x9D\xA3\x80\x0E\x91\x43\xC1\xD6\x5B\x5F\x14\xBA\x9F\xA6\x8D\x24\x47\x40\x59\xBF\x72\x38\xB2\x36\x6C\x37\xFF\x99\xD1\x5D\x0E\x59\x0A\xAB\x69\xF7\xC0\xB2\x04\x45\x7A\x54\x00\xAE\xBE\x53\xF6\xB5\xE7\xE1\xF8\x3C\xA3\x31\xD2\xA9\xFE\x21\x52\x64\xC5\xA6\x67\xF0\x75\x07\x06\x94\x14\x81\x55\xC6\x27\xE4\x01\x8F\x17\xC1\x6A\x71\xD7\xBE\x4B\xFB\x94\x58\x7D\x7E\x11\x33\xB1\x42\xF7\x62\x6C\x18\xD6\xCF\x09\x68\x3E\x7F\x6C\xF6\x1E\x8F\x62\xAD\xA5\x63\xDB\x09\xA7\x1F\x22\x42\x41\x1E\x6F\x99\x8A\x3E\xD7\xF9\x3F\x40\x7A\x79\xB0\xA5\x01\x92\xD2\x9D\x3D\x08\x15\xA5\x10\x01\x2D\xB3\x32\x76\xA8\x95\x0D\xB3\x7A\x9A\xFB\x07\x10\x78\x11\x6F\xE1\x8F\xC7\xBA\x0F\x25\x1A\x74\x2A\xE5\x1C\x98\x41\x99\xDF\x21\x87\xE8\x95\x06\x6A\x0A\xB3\x6A\x47\x76\x65\xF6\x3A\xCF\x8F\x62\x17\x19\x7B\x0A\x28\xCD\x1A\xD2\x83\x1E\x21\xC7\x2C\xBF\xBE\xFF\x61\x68\xB7\x67\x1B\xBB\x78\x4D\x8D\xCE\x67\xE5\xE4\xC1\x8E\xB7\x23\x66\xE2\x9D\x90\x75\x34\x98\xA9\x36\x2B\x8A\x9A\x94\xB9\x9D\xEC\xCC\x8A\xB1\xF8\x25\x89\x5C\x5A\xB6\x2F\x8C\x1F\x6D\x79\x24\xA7\x52\x68\xC3\x84\x35\xE2\x66\x8D\x63\x0E\x25\x4D\xD5\x19\xB2\xE6\x79\x37\xA7\x22\x9D\x54\x31\x02\x03\x01\x00\x01\xA3\x6A\x30\x68\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x1E\x0C\xF7\xB6\x67\xF2\xE1\x92\x26\x09\x45\xC0\x55\x39\x2E\x77\x3F\x42\x4A\xA2\x30\x0C\x06\x03\x55\x1D\x13\x04\x05\x30\x03\x01\x01\xFF\x30\x39\x06\x04\x67\x2A\x07\x00\x04\x31\x30\x2F\x30\x2D\x02\x01\x00\x30\x09\x06\x05\x2B\x0E\x03\x02\x1A\x05\x00\x30\x07\x06\x05\x67\x2A\x03\x00\x00\x04\x14\x45\xB0\xC2\xC7\x0A\x56\x7C\xEE\x5B\x78\x0C\x95\xF9\x18\x53\xC1\xA6\x1C\xD8\x10\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x09\xB3\x83\x53\x59\x01\x3E\x95\x49\xB9\xF1\x81\xBA\xF9\x76\x20\x23\xB5\x27\x60\x74\xD4\x6A\x99\x34\x5E\x6C\x00\x53\xD9\x9F\xF2\xA6\xB1\x24\x07\x44\x6A\x2A\xC6\xA5\x8E\x78\x12\xE8\x47\xD9\x58\x1B\x13\x2A\x5E\x79\x9B\x9F\x0A\x2A\x67\xA6\x25\x3F\x06\x69\x56\x73\xC3\x8A\x66\x48\xFB\x29\x81\x57\x74\x06\xCA\x9C\xEA\x28\xE8\x38\x67\x26\x2B\xF1\xD5\xB5\x3F\x65\x93\xF8\x36\x5D\x8E\x8D\x8D\x40\x20\x87\x19\xEA\xEF\x27\xC0\x3D\xB4\x39\x0F\x25\x7B\x68\x50\x74\x55\x9C\x0C\x59\x7D\x5A\x3D\x41\x94\x25\x52\x08\xE0\x47\x2C\x15\x31\x19\xD5\xBF\x07\x55\xC6\xBB\x12\xB5\x97\xF4\x5F\x83\x85\xBA\x71\xC1\xD9\x6C\x81\x11\x76\x0A\x0A\xB0\xBF\x82\x97\xF7\xEA\x3D\xFA\xFA\xEC\x2D\xA9\x28\x94\x3B\x56\xDD\xD2\x51\x2E\xAE\xC0\xBD\x08\x15\x8C\x77\x52\x34\x96\xD6\x9B\xAC\xD3\x1D\x8E\x61\x0F\x35\x7B\x9B\xAE\x39\x69\x0B\x62\x60\x40\x20\x36\x8F\xAF\xFB\x36\xEE\x2D\x08\x4A\x1D\xB8\xBF\x9B\x5C\xF8\xEA\xA5\x1B\xA0\x73\xA6\xD8\xF8\x6E\xE0\x33\x04\x5F\x68\xAA\x27\x87\xED\xD9\xC1\x90\x9C\xED\xBD\xE3\x6A\x35\xAF\x63\xDF\xAB\x18\xD9\xBA\xE6\xE9\x4A\xEA\x50\x8A\x0F\x61\x93\x1E\xE2\x2D\x19\xE2\x30\x94\x35\x92\x5D\x0E\xB6\x07\xAF\x19\x80\x8F\x47\x90\x51\x4B\x2E\x4D\xDD\x85\xE2\xD2\x0A\x52\x0A\x17\x9A\xFC\x1A\xB0\x50\x02\xE5\x01\xA3\x63\x37\x21\x4C\x44\xC4\x9B\x51\x99\x11\x0E\x73\x9C\x06\x8F\x54\x2E\xA7\x28\x5E\x44\x39\x87\x56\x2D\x37\xBD\x85\x44\x94\xE1\x0C\x4B\x2C\x9C\xC3\x92\x85\x34\x61\xCB\x0F\xB8\x9B\x4A\x43\x52\xFE\x34\x3A\x7D\xB8\xE9\x29\xDC\x76\xA9\xC8\x30\xF8\x14\x71\x80\xC6\x1E\x36\x48\x74\x22\x41\x5C\x87\x82\xE8\x18\x71\x8B\x41\x89\x44\xE7\x7E\x58\x5B\xA8\xB8\x8D\x13\xE9\xA7\x6C\xC3\x47\xED\xB3\x1A\x9D\x62\xAE\x8D\x82\xEA\x94\x9E\xDD\x59\x10\xC3\xAD\xDD\xE2\x4D\xE3\x31\xD5\xC7\xEC\xE8\xF2\xB0\xFE\x92\x1E\x16\x0A\x1A\xFC\xD9\xF3\xF8\x27\xB6\xC9\xBE\x1D\xB4\x6C\x64\x90\x7F\xF4\xE4\xC4\x5B\xD7\x37\xAE\x42\x0E\xDD\xA4\x1A\x6F\x7C\x88\x54\xC5\x16\x6E\xE1\x7A\x68\x2E\xF8\x3A\xBF\x0D\xA4\x3C\x89\x3B\x78\xA7\x4E\x63\x83\x04\x21\x08\x67\x8D\xF2\x82\x49\xD0\x5B\xFD\xB1\xCD\x0F\x83\x84\xD4\x3E\x20\x85\xF7\x4A\x3D\x2B\x9C\xFD\x2A\x0A\x09\x4D\xEA\x81\xF8\x11\x9C", + ["CN=T\C3\9CB\C4\B0TAK UEKAE K\C3\B6k Sertifika Hizmet Sa\C4\9Flay\C4\B1c\C4\B1s\C4\B1 - S\C3\BCr\C3\BCm 3,OU=Kamu Sertifikasyon Merkezi,OU=Ulusal Elektronik ve Kriptoloji Ara\C5\9Ft\C4\B1rma Enstit\C3\BCs\C3\BC - UEKAE,O=T\C3\BCrkiye Bilimsel ve Teknolojik Ara\C5\9Ft\C4\B1rma Kurumu - T\C3\9CB\C4\B0TAK,L=Gebze - Kocaeli,C=TR"] = "\x30\x82\x05\x17\x30\x82\x03\xFF\xA0\x03\x02\x01\x02\x02\x01\x11\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x82\x01\x2B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x18\x30\x16\x06\x03\x55\x04\x07\x0C\x0F\x47\x65\x62\x7A\x65\x20\x2D\x20\x4B\x6F\x63\x61\x65\x6C\x69\x31\x47\x30\x45\x06\x03\x55\x04\x0A\x0C\x3E\x54\xC3\xBC\x72\x6B\x69\x79\x65\x20\x42\x69\x6C\x69\x6D\x73\x65\x6C\x20\x76\x65\x20\x54\x65\x6B\x6E\x6F\x6C\x6F\x6A\x69\x6B\x20\x41\x72\x61\xC5\x9F\x74\xC4\xB1\x72\x6D\x61\x20\x4B\x75\x72\x75\x6D\x75\x20\x2D\x20\x54\xC3\x9C\x42\xC4\xB0\x54\x41\x4B\x31\x48\x30\x46\x06\x03\x55\x04\x0B\x0C\x3F\x55\x6C\x75\x73\x61\x6C\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x76\x65\x20\x4B\x72\x69\x70\x74\x6F\x6C\x6F\x6A\x69\x20\x41\x72\x61\xC5\x9F\x74\xC4\xB1\x72\x6D\x61\x20\x45\x6E\x73\x74\x69\x74\xC3\xBC\x73\xC3\xBC\x20\x2D\x20\x55\x45\x4B\x41\x45\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x0C\x1A\x4B\x61\x6D\x75\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x73\x79\x6F\x6E\x20\x4D\x65\x72\x6B\x65\x7A\x69\x31\x4A\x30\x48\x06\x03\x55\x04\x03\x0C\x41\x54\xC3\x9C\x42\xC4\xB0\x54\x41\x4B\x20\x55\x45\x4B\x41\x45\x20\x4B\xC3\xB6\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x20\x2D\x20\x53\xC3\xBC\x72\xC3\xBC\x6D\x20\x33\x30\x1E\x17\x0D\x30\x37\x30\x38\x32\x34\x31\x31\x33\x37\x30\x37\x5A\x17\x0D\x31\x37\x30\x38\x32\x31\x31\x31\x33\x37\x30\x37\x5A\x30\x82\x01\x2B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x18\x30\x16\x06\x03\x55\x04\x07\x0C\x0F\x47\x65\x62\x7A\x65\x20\x2D\x20\x4B\x6F\x63\x61\x65\x6C\x69\x31\x47\x30\x45\x06\x03\x55\x04\x0A\x0C\x3E\x54\xC3\xBC\x72\x6B\x69\x79\x65\x20\x42\x69\x6C\x69\x6D\x73\x65\x6C\x20\x76\x65\x20\x54\x65\x6B\x6E\x6F\x6C\x6F\x6A\x69\x6B\x20\x41\x72\x61\xC5\x9F\x74\xC4\xB1\x72\x6D\x61\x20\x4B\x75\x72\x75\x6D\x75\x20\x2D\x20\x54\xC3\x9C\x42\xC4\xB0\x54\x41\x4B\x31\x48\x30\x46\x06\x03\x55\x04\x0B\x0C\x3F\x55\x6C\x75\x73\x61\x6C\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x76\x65\x20\x4B\x72\x69\x70\x74\x6F\x6C\x6F\x6A\x69\x20\x41\x72\x61\xC5\x9F\x74\xC4\xB1\x72\x6D\x61\x20\x45\x6E\x73\x74\x69\x74\xC3\xBC\x73\xC3\xBC\x20\x2D\x20\x55\x45\x4B\x41\x45\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x0C\x1A\x4B\x61\x6D\x75\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x73\x79\x6F\x6E\x20\x4D\x65\x72\x6B\x65\x7A\x69\x31\x4A\x30\x48\x06\x03\x55\x04\x03\x0C\x41\x54\xC3\x9C\x42\xC4\xB0\x54\x41\x4B\x20\x55\x45\x4B\x41\x45\x20\x4B\xC3\xB6\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x20\x2D\x20\x53\xC3\xBC\x72\xC3\xBC\x6D\x20\x33\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\x8A\x6D\x4B\xFF\x10\x88\x3A\xC3\xF6\x7E\x94\xE8\xEA\x20\x64\x70\xAE\x21\x81\xBE\x3A\x7B\x3C\xDB\xF1\x1D\x52\x7F\x59\xFA\xF3\x22\x4C\x95\xA0\x90\xBC\x48\x4E\x11\xAB\xFB\xB7\xB5\x8D\x7A\x83\x28\x8C\x26\x46\xD8\x4E\x95\x40\x87\x61\x9F\xC5\x9E\x6D\x81\x87\x57\x6C\x8A\x3B\xB4\x66\xEA\xCC\x40\xFC\xE3\xAA\x6C\xB2\xCB\x01\xDB\x32\xBF\xD2\xEB\x85\xCF\xA1\x0D\x55\xC3\x5B\x38\x57\x70\xB8\x75\xC6\x79\xD1\x14\x30\xED\x1B\x58\x5B\x6B\xEF\x35\xF2\xA1\x21\x4E\xC5\xCE\x7C\x99\x5F\x6C\xB9\xB8\x22\x93\x50\xA7\xCD\x4C\x70\x6A\xBE\x6A\x05\x7F\x13\x9C\x2B\x1E\xEA\xFE\x47\xCE\x04\xA5\x6F\xAC\x93\x2E\x7C\x2B\x9F\x9E\x79\x13\x91\xE8\xEA\x9E\xCA\x38\x75\x8E\x62\xB0\x95\x93\x2A\xE5\xDF\xE9\x5E\x97\x6E\x20\x5F\x5F\x84\x7A\x44\x39\x19\x40\x1C\xBA\x55\x2B\xFB\x30\xB2\x81\xEF\x84\xE3\xDC\xEC\x98\x38\x39\x03\x85\x08\xA9\x54\x03\x05\x29\xF0\xC9\x8F\x8B\xEA\x0B\x86\x65\x19\x11\xD3\xE9\x09\x23\xDE\x68\x93\x03\xC9\x36\x1C\x21\x6E\xCE\x8C\x66\xF1\x99\x30\xD8\xD7\xB3\xC3\x1D\xF8\x81\x2E\xA8\xBD\x82\x0B\x66\xFE\x82\xCB\xE1\xE0\x1A\x82\xC3\x40\x81\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xBD\x88\x87\xC9\x8F\xF6\xA4\x0A\x0B\xAA\xEB\xC5\xFE\x91\x23\x9D\xAB\x4A\x8A\x32\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x1D\x7C\xFA\x49\x8F\x34\xE9\xB7\x26\x92\x16\x9A\x05\x74\xE7\x4B\xD0\x6D\x39\x6C\xC3\x26\xF6\xCE\xB8\x31\xBC\xC4\xDF\xBC\x2A\xF8\x37\x91\x18\xDC\x04\xC8\x64\x99\x2B\x18\x6D\x80\x03\x59\xC9\xAE\xF8\x58\xD0\x3E\xED\xC3\x23\x9F\x69\x3C\x86\x38\x1C\x9E\xEF\xDA\x27\x78\xD1\x84\x37\x71\x8A\x3C\x4B\x39\xCF\x7E\x45\x06\xD6\x2D\xD8\x8A\x4D\x78\x12\xD6\xAD\xC2\xD3\xCB\xD2\xD0\x41\xF3\x26\x36\x4A\x9B\x95\x6C\x0C\xEE\xE5\xD1\x43\x27\x66\xC1\x88\xF7\x7A\xB3\x20\x6C\xEA\xB0\x69\x2B\xC7\x20\xE8\x0C\x03\xC4\x41\x05\x99\xE2\x3F\xE4\x6B\xF8\xA0\x86\x81\xC7\x84\xC6\x1F\xD5\x4B\x81\x12\xB2\x16\x21\x2C\x13\xA1\x80\xB2\x5E\x0C\x4A\x13\x9E\x20\xD8\x62\x40\xAB\x90\xEA\x64\x4A\x2F\xAC\x0D\x01\x12\x79\x45\xA8\x2F\x87\x19\x68\xC8\xE2\x85\xC7\x30\xB2\x75\xF9\x38\x3F\xB2\xC0\x93\xB4\x6B\xE2\x03\x44\xCE\x67\xA0\xDF\x89\xD6\xAD\x8C\x76\xA3\x13\xC3\x94\x61\x2B\x6B\xD9\x6C\xC1\x07\x0A\x22\x07\x85\x6C\x85\x24\x46\xA9\xBE\x3F\x8B\x78\x84\x82\x7E\x24\x0C\x9D\xFD\x81\x37\xE3\x25\xA8\xED\x36\x4E\x95\x2C\xC9\x9C\x90\xDA\xEC\xA9\x42\x3C\xAD\xB6\x02", + ["CN=Buypass Class 2 CA 1,O=Buypass AS-983163327,C=NO"] = "\x30\x82\x03\x53\x30\x82\x02\x3B\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x1D\x30\x1B\x06\x03\x55\x04\x03\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x20\x31\x30\x1E\x17\x0D\x30\x36\x31\x30\x31\x33\x31\x30\x32\x35\x30\x39\x5A\x17\x0D\x31\x36\x31\x30\x31\x33\x31\x30\x32\x35\x30\x39\x5A\x30\x4B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x1D\x30\x1B\x06\x03\x55\x04\x03\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x32\x20\x43\x41\x20\x31\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\x8B\x3C\x07\x45\xD8\xF6\xDF\xE6\xC7\xCA\xBA\x8D\x43\xC5\x47\x8D\xB0\x5A\xC1\x38\xDB\x92\x84\x1C\xAF\x13\xD4\x0F\x6F\x36\x46\x20\xC4\x2E\xCC\x71\x70\x34\xA2\x34\xD3\x37\x2E\xD8\xDD\x3A\x77\x2F\xC0\xEB\x29\xE8\x5C\xD2\xB5\xA9\x91\x34\x87\x22\x59\xFE\xCC\xDB\xE7\x99\xAF\x96\xC1\xA8\xC7\x40\xDD\xA5\x15\x8C\x6E\xC8\x7C\x97\x03\xCB\xE6\x20\xF2\xD7\x97\x5F\x31\xA1\x2F\x37\xD2\xBE\xEE\xBE\xA9\xAD\xA8\x4C\x9E\x21\x66\x43\x3B\xA8\xBC\xF3\x09\xA3\x38\xD5\x59\x24\xC1\xC2\x47\x76\xB1\x88\x5C\x82\x3B\xBB\x2B\xA6\x04\xD7\x8C\x07\x8F\xCD\xD5\x41\x1D\xF0\xAE\xB8\x29\x2C\x94\x52\x60\x34\x94\x3B\xDA\xE0\x38\xD1\x9D\x33\x3E\x15\xF4\x93\x32\xC5\x00\xDA\xB5\x29\x66\x0E\x3A\x78\x0F\x21\x52\x5F\x02\xE5\x92\x7B\x25\xD3\x92\x1E\x2F\x15\x9D\x81\xE4\x9D\x8E\xE8\xEF\x89\xCE\x14\x4C\x54\x1D\x1C\x81\x12\x4D\x70\xA8\xBE\x10\x05\x17\x7E\x1F\xD1\xB8\x57\x55\xED\xCD\xBB\x52\xC2\xB0\x1E\x78\xC2\x4D\x36\x68\xCB\x56\x26\xC1\x52\xC1\xBD\x76\xF7\x58\xD5\x72\x7E\x1F\x44\x76\xBB\x00\x89\x1D\x16\x9D\x51\x35\xEF\x4D\xC2\x56\xEF\x6B\xE0\x8C\x3B\x0D\xE9\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x3F\x8D\x9A\x59\x8B\xFC\x7B\x7B\x9C\xA3\xAF\x38\xB0\x39\xED\x90\x71\x80\xD6\xC8\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x15\x1A\x7E\x13\x8A\xB9\xE8\x07\xA3\x4B\x27\x32\xB2\x40\x91\xF2\x21\xD1\x64\x85\xBE\x63\x6A\xD2\xCF\x81\xC2\x15\xD5\x7A\x7E\x0C\x29\xAC\x37\x1E\x1C\x7C\x76\x52\x95\xDA\xB5\x7F\x23\xA1\x29\x77\x65\xC9\x32\x9D\xA8\x2E\x56\xAB\x60\x76\xCE\x16\xB4\x8D\x7F\x78\xC0\xD5\x99\x51\x83\x7F\x5E\xD9\xBE\x0C\xA8\x50\xED\x22\xC7\xAD\x05\x4C\x76\xFB\xED\xEE\x1E\x47\x64\xF6\xF7\x27\x7D\x5C\x28\x0F\x45\xC5\x5C\x62\x5E\xA6\x9A\x91\x91\xB7\x53\x17\x2E\xDC\xAD\x60\x9D\x96\x64\x39\xBD\x67\x68\xB2\xAE\x05\xCB\x4D\xE7\x5F\x1F\x57\x86\xD5\x20\x9C\x28\xFB\x6F\x13\x38\xF5\xF6\x11\x92\xF6\x7D\x99\x5E\x1F\x0C\xE8\xAB\x44\x24\x29\x72\x40\x3D\x36\x52\xAF\x8C\x58\x90\x73\xC1\xEC\x61\x2C\x79\xA1\xEC\x87\xB5\x3F\xDA\x4D\xD9\x21\x00\x30\xDE\x90\xDA\x0E\xD3\x1A\x48\xA9\x3E\x85\x0B\x14\x8B\x8C\xBC\x41\x9E\x6A\xF7\x0E\x70\xC0\x35\xF7\x39\xA2\x5D\x66\xD0\x7B\x59\x9F\xA8\x47\x12\x9A\x27\x23\xA4\x2D\x8E\x27\x83\x92\x20\xA1\xD7\x15\x7F\xF1\x2E\x18\xEE\xF4\x48\x7F\x2F\x7F\xF1\xA1\x18\xB5\xA1\x0B\x94\xA0\x62\x20\x32\x9C\x1D\xF6\xD4\xEF\xBF\x4C\x88\x68", + ["CN=Buypass Class 3 CA 1,O=Buypass AS-983163327,C=NO"] = "\x30\x82\x03\x53\x30\x82\x02\x3B\xA0\x03\x02\x01\x02\x02\x01\x02\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x1D\x30\x1B\x06\x03\x55\x04\x03\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x20\x31\x30\x1E\x17\x0D\x30\x35\x30\x35\x30\x39\x31\x34\x31\x33\x30\x33\x5A\x17\x0D\x31\x35\x30\x35\x30\x39\x31\x34\x31\x33\x30\x33\x5A\x30\x4B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4F\x31\x1D\x30\x1B\x06\x03\x55\x04\x0A\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x41\x53\x2D\x39\x38\x33\x31\x36\x33\x33\x32\x37\x31\x1D\x30\x1B\x06\x03\x55\x04\x03\x0C\x14\x42\x75\x79\x70\x61\x73\x73\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x43\x41\x20\x31\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\xA4\x8E\xD7\x74\xD9\x29\x64\xDE\x5F\x1F\x87\x80\x91\xEA\x4E\x39\xE6\x19\xC6\x44\x0B\x80\xD5\x0B\xAF\x53\x07\x8B\x12\xBD\xE6\x67\xF0\x02\xB1\x89\xF6\x60\x8A\xC4\x5B\xB0\x42\xD1\xC0\x21\xA8\xCB\xE1\x9B\xEF\x64\x51\xB6\xA7\xCF\x15\xF5\x74\x80\x68\x04\x90\xA0\x58\xA2\xE6\x74\xA6\x53\x53\x55\x48\x63\x3F\x92\x56\xDD\x24\x4E\x8E\xF8\xBA\x2B\xFF\xF3\x34\x8A\x9E\x28\xD7\x34\x9F\xAC\x2F\xD6\x0F\xF1\xA4\x2F\xBD\x52\xB2\x49\x85\x6D\x39\x35\xF0\x44\x30\x93\x46\x24\xF3\xB6\xE7\x53\xFB\xBC\x61\xAF\xA9\xA3\x14\xFB\xC2\x17\x17\x84\x6C\xE0\x7C\x88\xF8\xC9\x1C\x57\x2C\xF0\x3D\x7E\x94\xBC\x25\x93\x84\xE8\x9A\x00\x9A\x45\x05\x42\x57\x80\xF4\x4E\xCE\xD9\xAE\x39\xF6\xC8\x53\x10\x0C\x65\x3A\x47\x7B\x60\xC2\xD6\xFA\x91\xC9\xC6\x71\x6C\xBD\x91\x87\x3C\x91\x86\x49\xAB\xF3\x0F\xA0\x6C\x26\x76\x5E\x1C\xAC\x9B\x71\xE5\x8D\xBC\x9B\x21\x1E\x9C\xD6\x38\x7E\x24\x80\x15\x31\x82\x96\xB1\x49\xD3\x62\x37\x5B\x88\x0C\x0A\x62\x34\xFE\xA7\x48\x7E\x99\xB1\x30\x8B\x90\x37\x95\x1C\xA8\x1F\xA5\x2C\x8D\xF4\x55\xC8\xDB\xDD\x59\x0A\xC2\xAD\x78\xA0\xF4\x8B\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x38\x14\xE6\xC8\xF0\xA9\xA4\x03\xF4\x4E\x3E\x22\xA3\x5B\xF2\xD6\xE0\xAD\x40\x74\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x01\x67\xA3\x8C\xC9\x25\x3D\x13\x63\x5D\x16\x6F\xEC\xA1\x3E\x09\x5C\x91\x15\x2A\x2A\xD9\x80\x21\x4F\x05\xDC\xBB\xA5\x89\xAB\x13\x33\x2A\x9E\x38\xB7\x8C\x6F\x02\x72\x63\xC7\x73\x77\x1E\x09\x06\xBA\x3B\x28\x7B\xA4\x47\xC9\x61\x6B\x08\x08\x20\xFC\x8A\x05\x8A\x1F\xBC\xBA\xC6\xC2\xFE\xCF\x6E\xEC\x13\x33\x71\x67\x2E\x69\xFA\xA9\x2C\x3F\x66\xC0\x12\x59\x4D\x0B\x54\x02\x92\x84\xBB\xDB\x12\xEF\x83\x70\x70\x78\xC8\x53\xFA\xDF\xC6\xC6\xFF\xDC\x88\x2F\x07\xC0\x49\x9D\x32\x57\x60\xD3\xF2\xF6\x99\x29\x5F\xE7\xAA\x01\xCC\xAC\x33\xA8\x1C\x0A\xBB\x91\xC4\x03\xA0\x6F\xB6\x34\xF9\x86\xD3\xB3\x76\x54\x98\xF4\x4A\x81\xB3\x53\x9D\x4D\x40\xEC\xE5\x77\x13\x45\xAF\x5B\xAA\x1F\xD8\x2F\x4C\x82\x7B\xFE\x2A\xC4\x58\xBB\x4F\xFC\x9E\xFD\x03\x65\x1A\x2A\x0E\xC3\xA5\x20\x16\x94\x6B\x79\xA6\xA2\x12\xB4\xBB\x1A\xA4\x23\x7A\x5F\xF0\xAE\x84\x24\xE4\xF3\x2B\xFB\x8A\x24\xA3\x27\x98\x65\xDA\x30\x75\x76\xFC\x19\x91\xE8\xDB\xEB\x9B\x3F\x32\xBF\x40\x97\x07\x26\xBA\xCC\xF3\x94\x85\x4A\x7A\x27\x93\xCF\x90\x42\xD4\xB8\x5B\x16\xA6\xE7\xCB\x40\x03\xDD\x79", + ["C=TR,O=EBG Bili\C5\9Fim Teknolojileri ve Hizmetleri A.\C5\9E.,CN=EBG Elektronik Sertifika Hizmet Sa\C4\9Flay\C4\B1c\C4\B1s\C4\B1"] = "\x30\x82\x05\xE7\x30\x82\x03\xCF\xA0\x03\x02\x01\x02\x02\x08\x4C\xAF\x73\x42\x1C\x8E\x74\x02\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x80\x31\x38\x30\x36\x06\x03\x55\x04\x03\x0C\x2F\x45\x42\x47\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x37\x30\x35\x06\x03\x55\x04\x0A\x0C\x2E\x45\x42\x47\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x54\x65\x6B\x6E\x6F\x6C\x6F\x6A\x69\x6C\x65\x72\x69\x20\x76\x65\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x30\x1E\x17\x0D\x30\x36\x30\x38\x31\x37\x30\x30\x32\x31\x30\x39\x5A\x17\x0D\x31\x36\x30\x38\x31\x34\x30\x30\x33\x31\x30\x39\x5A\x30\x81\x80\x31\x38\x30\x36\x06\x03\x55\x04\x03\x0C\x2F\x45\x42\x47\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\xC4\x9F\x6C\x61\x79\xC4\xB1\x63\xC4\xB1\x73\xC4\xB1\x31\x37\x30\x35\x06\x03\x55\x04\x0A\x0C\x2E\x45\x42\x47\x20\x42\x69\x6C\x69\xC5\x9F\x69\x6D\x20\x54\x65\x6B\x6E\x6F\x6C\x6F\x6A\x69\x6C\x65\x72\x69\x20\x76\x65\x20\x48\x69\x7A\x6D\x65\x74\x6C\x65\x72\x69\x20\x41\x2E\xC5\x9E\x2E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xEE\xA0\x84\x61\xD0\x3A\x6A\x66\x10\x32\xD8\x31\x38\x7F\xA7\xA7\xE5\xFD\xA1\xE1\xFB\x97\x77\xB8\x71\x96\xE8\x13\x96\x46\x83\x4F\xB6\xF2\x5F\x72\x56\x6E\x13\x60\xA5\x01\x91\xE2\x5B\xC5\xCD\x57\x1F\x77\x63\x51\xFF\x2F\x3D\xDB\xB9\x3F\xAA\xA9\x35\xE7\x79\xD0\xF5\xD0\x24\xB6\x21\xEA\xEB\x23\x94\xFE\x29\xBF\xFB\x89\x91\x0C\x64\x9A\x05\x4A\x2B\xCC\x0C\xEE\xF1\x3D\x9B\x82\x69\xA4\x4C\xF8\x9A\x6F\xE7\x22\xDA\x10\xBA\x5F\x92\xFC\x18\x27\x0A\xA8\xAA\x44\xFA\x2E\x2C\xB4\xFB\x46\x9A\x08\x03\x83\x72\xAB\x88\xE4\x6A\x72\xC9\xE5\x65\x1F\x6E\x2A\x0F\x9D\xB3\xE8\x3B\xE4\x0C\x6E\x7A\xDA\x57\xFD\xD7\xEB\x79\x8B\x5E\x20\x06\xD3\x76\x0B\x6C\x02\x95\xA3\x96\xE4\xCB\x76\x51\xD1\x28\x9D\xA1\x1A\xFC\x44\xA2\x4D\xCC\x7A\x76\xA8\x0D\x3D\xBF\x17\x4F\x22\x88\x50\xFD\xAE\xB6\xEC\x90\x50\x4A\x5B\x9F\x95\x41\xAA\xCA\x0F\xB2\x4A\xFE\x80\x99\x4E\xA3\x46\x15\xAB\xF8\x73\x42\x6A\xC2\x66\x76\xB1\x0A\x26\x15\xDD\x93\x92\xEC\xDB\xA9\x5F\x54\x22\x52\x91\x70\x5D\x13\xEA\x48\xEC\x6E\x03\x6C\xD9\xDD\x6C\xFC\xEB\x0D\x03\xFF\xA6\x83\x12\x9B\xF1\xA9\x93\x0F\xC5\x26\x4C\x31\xB2\x63\x99\x61\x72\xE7\x2A\x64\x99\xD2\xB8\xE9\x75\xE2\x7C\xA9\xA9\x9A\x1A\xAA\xC3\x56\xDB\x10\x9A\x3C\x83\x52\xB6\x7B\x96\xB7\xAC\x87\x77\xA8\xB9\xF2\x67\x0B\x94\x43\xB3\xAF\x3E\x73\xFA\x42\x36\xB1\x25\xC5\x0A\x31\x26\x37\x56\x67\xBA\xA3\x0B\x7D\xD6\xF7\x89\xCD\x67\xA1\xB7\x3A\x1E\x66\x4F\xF6\xA0\x55\x14\x25\x4C\x2C\x33\x0D\xA6\x41\x8C\xBD\x04\x31\x6A\x10\x72\x0A\x9D\x0E\x2E\x76\xBD\x5E\xF3\x51\x89\x8B\xA8\x3F\x55\x73\xBF\xDB\x3A\xC6\x24\x05\x96\x92\x48\xAA\x4B\x8D\x2A\x03\xE5\x57\x91\x10\xF4\x6A\x28\x15\x6E\x47\x77\x84\x5C\x51\x74\x9F\x19\xE9\xE6\x1E\x63\x16\x39\xE3\x11\x15\xE3\x58\x1A\x44\xBD\xCB\xC4\x6C\x66\xD7\x84\x06\xDF\x30\xF4\x37\xA2\x43\x22\x79\xD2\x10\x6C\xDF\xBB\xE6\x13\x11\xFC\x9D\x84\x0A\x13\x7B\xF0\x3B\xD0\xFC\xA3\x0A\xD7\x89\xEA\x96\x7E\x8D\x48\x85\x1E\x64\x5F\xDB\x54\xA2\xAC\xD5\x7A\x02\x79\x6B\xD2\x8A\xF0\x67\xDA\x65\x72\x0D\x14\x70\xE4\xE9\x8E\x78\x8F\x32\x74\x7C\x57\xF2\xD6\xD6\xF4\x36\x89\x1B\xF8\x29\x6C\x8B\xB9\xF6\x97\xD1\xA4\x2E\xAA\xBE\x0B\x19\xC2\x45\xE9\x70\x5D\x02\x03\x00\x9D\xD9\xA3\x63\x30\x61\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE7\xCE\xC6\x4F\xFC\x16\x67\x96\xFA\x4A\xA3\x07\xC1\x04\xA7\xCB\x6A\xDE\xDA\x47\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xE7\xCE\xC6\x4F\xFC\x16\x67\x96\xFA\x4A\xA3\x07\xC1\x04\xA7\xCB\x6A\xDE\xDA\x47\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x9B\x98\x9A\x5D\xBE\xF3\x28\x23\x76\xC6\x6C\xF7\x7F\xE6\x40\x9E\xC0\x36\xDC\x95\x0D\x1D\xAD\x15\xC5\x36\xD8\xD5\x39\xEF\xF2\x1E\x22\x5E\xB3\x82\xB4\x5D\xBB\x4C\x1A\xCA\x92\x0D\xDF\x47\x24\x1E\xB3\x24\xDA\x91\x88\xE9\x83\x70\xDD\x93\xD7\xE9\xBA\xB3\xDF\x16\x5A\x3E\xDE\xE0\xC8\xFB\xD3\xFD\x6C\x29\xF8\x15\x46\xA0\x68\x26\xCC\x93\x52\xAE\x82\x01\x93\x90\xCA\x77\xCA\x4D\x49\xEF\xE2\x5A\xD9\x2A\xBD\x30\xCE\x4C\xB2\x81\xB6\x30\xCE\x59\x4F\xDA\x59\x1D\x6A\x7A\xA4\x45\xB0\x82\x26\x81\x86\x76\xF5\xF5\x10\x00\xB8\xEE\xB3\x09\xE8\x4F\x87\x02\x07\xAE\x24\x5C\xF0\x5F\xAC\x0A\x30\xCC\x8A\x40\xA0\x73\x04\xC1\xFB\x89\x24\xF6\x9A\x1C\x5C\xB7\x3C\x0A\x67\x36\x05\x08\x31\xB3\xAF\xD8\x01\x68\x2A\xE0\x78\x8F\x74\xDE\xB8\x51\xA4\x8C\x6C\x20\x3D\xA2\xFB\xB3\xD4\x09\xFD\x7B\xC2\x80\xAA\x93\x6C\x29\x98\x21\xA8\xBB\x16\xF3\xA9\x12\x5F\x74\xB5\x87\x98\xF2\x95\x26\xDF\x34\xEF\x8A\x53\x91\x88\x5D\x1A\x94\xA3\x3F\x7C\x22\xF8\xD7\x88\xBA\xA6\x8C\x96\xA8\x3D\x52\x34\x62\x9F\x00\x1E\x54\x55\x42\x67\xC6\x4D\x46\x8F\xBB\x14\x45\x3D\x0A\x96\x16\x8E\x10\xA1\x97\x99\xD5\xD3\x30\x85\xCC\xDE\xB4\x72\xB7\xBC\x8A\x3C\x18\x29\x68\xFD\xDC\x71\x07\xEE\x24\x39\x6A\xFA\xED\xA5\xAC\x38\x2F\xF9\x1E\x10\x0E\x06\x71\x1A\x10\x4C\xFE\x75\x7E\xFF\x1E\x57\x39\x42\xCA\xD7\xE1\x15\xA1\x56\x55\x59\x1B\xD1\xA3\xAF\x11\xD8\x4E\xC3\xA5\x2B\xEF\x90\xBF\xC0\xEC\x82\x13\x5B\x8D\xD6\x72\x2C\x93\x4E\x8F\x6A\x29\xDF\x85\x3C\xD3\x0D\xE0\xA2\x18\x12\xCC\x55\x2F\x47\xB7\xA7\x9B\x02\xFE\x41\xF6\x88\x4C\x6D\xDA\xA9\x01\x47\x83\x64\x27\x62\x10\x82\xD6\x12\x7B\x5E\x03\x1F\x34\xA9\xC9\x91\xFE\xAF\x5D\x6D\x86\x27\xB7\x23\xAA\x75\x18\xCA\x20\xE7\xB0\x0F\xD7\x89\x0E\xA6\x67\x22\x63\xF4\x83\x41\x2B\x06\x4B\xBB\x58\xD5\xD1\xD7\xB7\xB9\x10\x63\xD8\x89\x4A\xB4\xAA\xDD\x16\x63\xF5\x6E\xBE\x60\xA1\xF8\xED\xE8\xD6\x90\x4F\x1A\xC6\xC5\xA0\x29\xD3\xA7\x21\xA8\xF5\x5A\x3C\xF7\xC7\x49\xA2\x21\x9A\x4A\x95\x52\x20\x96\x72\x9A\x66\xCB\xF7\xD2\x86\x43\x7C\x22\xBE\x96\xF9\xBD\x01\xA8\x47\xDD\xE5\x3B\x40\xF9\x75\x2B\x9B\x2B\x46\x64\x86\x8D\x1E\xF4\x8F\xFB\x07\x77\xD0\xEA\x49\xA2\x1C\x8D\x52\x14\xA6\x0A\x93", + ["OU=certSIGN ROOT CA,O=certSIGN,C=RO"] = "\x30\x82\x03\x38\x30\x82\x02\x20\xA0\x03\x02\x01\x02\x02\x06\x20\x06\x05\x16\x70\x02\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x3B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x52\x4F\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x63\x65\x72\x74\x53\x49\x47\x4E\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x63\x65\x72\x74\x53\x49\x47\x4E\x20\x52\x4F\x4F\x54\x20\x43\x41\x30\x1E\x17\x0D\x30\x36\x30\x37\x30\x34\x31\x37\x32\x30\x30\x34\x5A\x17\x0D\x33\x31\x30\x37\x30\x34\x31\x37\x32\x30\x30\x34\x5A\x30\x3B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x52\x4F\x31\x11\x30\x0F\x06\x03\x55\x04\x0A\x13\x08\x63\x65\x72\x74\x53\x49\x47\x4E\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x13\x10\x63\x65\x72\x74\x53\x49\x47\x4E\x20\x52\x4F\x4F\x54\x20\x43\x41\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\xB7\x33\xB9\x7E\xC8\x25\x4A\x8E\xB5\xDB\xB4\x28\x1B\xAA\x57\x90\xE8\xD1\x22\xD3\x64\xBA\xD3\x93\xE8\xD4\xAC\x86\x61\x40\x6A\x60\x57\x68\x54\x84\x4D\xBC\x6A\x54\x02\x05\xFF\xDF\x9B\x9A\x2A\xAE\x5D\x07\x8F\x4A\xC3\x28\x7F\xEF\xFB\x2B\xFA\x79\xF1\xC7\xAD\xF0\x10\x53\x24\x90\x8B\x66\xC9\xA8\x88\xAB\xAF\x5A\xA3\x00\xE9\xBE\xBA\x46\xEE\x5B\x73\x7B\x2C\x17\x82\x81\x5E\x62\x2C\xA1\x02\x65\xB3\xBD\xC5\x2B\x00\x7E\xC4\xFC\x03\x33\x57\x0D\xED\xE2\xFA\xCE\x5D\x45\xD6\x38\xCD\x35\xB6\xB2\xC1\xD0\x9C\x81\x4A\xAA\xE4\xB2\x01\x5C\x1D\x8F\x5F\x99\xC4\xB1\xAD\xDB\x88\x21\xEB\x90\x08\x82\x80\xF3\x30\xA3\x43\xE6\x90\x82\xAE\x55\x28\x49\xED\x5B\xD7\xA9\x10\x38\x0E\xFE\x8F\x4C\x5B\x9B\x46\xEA\x41\xF5\xB0\x08\x74\xC3\xD0\x88\x33\xB6\x7C\xD7\x74\xDF\xDC\x84\xD1\x43\x0E\x75\x39\xA1\x25\x40\x28\xEA\x78\xCB\x0E\x2C\x2E\x39\x9D\x8C\x8B\x6E\x16\x1C\x2F\x26\x82\x10\xE2\xE3\x65\x94\x0A\x04\xC0\x5E\xF7\x5D\x5B\xF8\x10\xE2\xD0\xBA\x7A\x4B\xFB\xDE\x37\x00\x00\x1A\x5B\x28\xE3\xD2\x9C\x73\x3E\x32\x87\x98\xA1\xC9\x51\x2F\xD7\xDE\xAC\x33\xB3\x4F\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\xC6\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xE0\x8C\x9B\xDB\x25\x49\xB3\xF1\x7C\x86\xD6\xB2\x42\x87\x0B\xD0\x6B\xA0\xD9\xE4\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3E\xD2\x1C\x89\x2E\x35\xFC\xF8\x75\xDD\xE6\x7F\x65\x88\xF4\x72\x4C\xC9\x2C\xD7\x32\x4E\xF3\xDD\x19\x79\x47\xBD\x8E\x3B\x5B\x93\x0F\x50\x49\x24\x13\x6B\x14\x06\x72\xEF\x09\xD3\xA1\xA1\xE3\x40\x84\xC9\xE7\x18\x32\x74\x3C\x48\x6E\x0F\x9F\x4B\xD4\xF7\x1E\xD3\x93\x86\x64\x54\x97\x63\x72\x50\xD5\x55\xCF\xFA\x20\x93\x02\xA2\x9B\xC3\x23\x93\x4E\x16\x55\x76\xA0\x70\x79\x6D\xCD\x21\x1F\xCF\x2F\x2D\xBC\x19\xE3\x88\x31\xF8\x59\x1A\x81\x09\xC8\x97\xA6\x74\xC7\x60\xC4\x5B\xCC\x57\x8E\xB2\x75\xFD\x1B\x02\x09\xDB\x59\x6F\x72\x93\x69\xF7\x31\x41\xD6\x88\x38\xBF\x87\xB2\xBD\x16\x79\xF9\xAA\xE4\xBE\x88\x25\xDD\x61\x27\x23\x1C\xB5\x31\x07\x04\x36\xB4\x1A\x90\xBD\xA0\x74\x71\x50\x89\x6D\xBC\x14\xE3\x0F\x86\xAE\xF1\xAB\x3E\xC7\xA0\x09\xCC\xA3\x48\xD1\xE0\xDB\x64\xE7\x92\xB5\xCF\xAF\x72\x43\x70\x8B\xF9\xC3\x84\x3C\x13\xAA\x7E\x92\x9B\x57\x53\x93\xFA\x70\xC2\x91\x0E\x31\xF9\x9B\x67\x5D\xE9\x96\x38\x5E\x5F\xB3\x73\x4E\x88\x15\x67\xDE\x9E\x76\x10\x62\x20\xBE\x55\x69\x95\x43\x00\x39\x4D\xF6\xEE\xB0\x5A\x4E\x49\x44\x54\x58\x5F\x42\x83", + ["CN=CNNIC ROOT,O=CNNIC,C=CN"] = "\x30\x82\x03\x55\x30\x82\x02\x3D\xA0\x03\x02\x01\x02\x02\x04\x49\x33\x00\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x32\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0A\x13\x05\x43\x4E\x4E\x49\x43\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x43\x4E\x4E\x49\x43\x20\x52\x4F\x4F\x54\x30\x1E\x17\x0D\x30\x37\x30\x34\x31\x36\x30\x37\x30\x39\x31\x34\x5A\x17\x0D\x32\x37\x30\x34\x31\x36\x30\x37\x30\x39\x31\x34\x5A\x30\x32\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x43\x4E\x31\x0E\x30\x0C\x06\x03\x55\x04\x0A\x13\x05\x43\x4E\x4E\x49\x43\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x43\x4E\x4E\x49\x43\x20\x52\x4F\x4F\x54\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\xD3\x35\xF7\x3F\x73\x77\xAD\xE8\x5B\x73\x17\xC2\xD1\x6F\xED\x55\xBC\x6E\xEA\xE8\xA4\x79\xB2\x6C\xC3\xA3\xEF\xE1\x9F\xB1\x3B\x48\x85\xF5\x9A\x5C\x21\x22\x10\x2C\xC5\x82\xCE\xDA\xE3\x9A\x6E\x37\xE1\x87\x2C\xDC\xB9\x0C\x5A\xBA\x88\x55\xDF\xFD\xAA\xDB\x1F\x31\xEA\x01\xF1\xDF\x39\x01\xC1\x13\xFD\x48\x52\x21\xC4\x55\xDF\xDA\xD8\xB3\x54\x76\xBA\x74\xB1\xB7\x7D\xD7\xC0\xE8\xF6\x59\xC5\x4D\xC8\xBD\xAD\x1F\x14\xDA\xDF\x58\x44\x25\x32\x19\x2A\xC7\x7E\x7E\x8E\xAE\x38\xB0\x30\x7B\x47\x72\x09\x31\xF0\x30\xDB\xC3\x1B\x76\x29\xBB\x69\x76\x4E\x57\xF9\x1B\x64\xA2\x93\x56\xB7\x6F\x99\x6E\xDB\x0A\x04\x9C\x11\xE3\x80\x1F\xCB\x63\x94\x10\x0A\xA9\xE1\x64\x82\x31\xF9\x8C\x27\xED\xA6\x99\x00\xF6\x70\x93\x18\xF8\xA1\x34\x86\xA3\xDD\x7A\xC2\x18\x79\xF6\x7A\x65\x35\xCF\x90\xEB\xBD\x33\x93\x9F\x53\xAB\x73\x3B\xE6\x9B\x34\x20\x2F\x1D\xEF\xA9\x1D\x63\x1A\xA0\x80\xDB\x03\x2F\xF9\x26\x1A\x86\xD2\x8D\xBB\xA9\xBE\x52\x3A\x87\x67\x48\x0D\xBF\xB4\xA0\xD8\x26\xBE\x23\x5F\x73\x37\x7F\x26\xE6\x92\x04\xA3\x7F\xCF\x20\xA7\xB7\xF3\x3A\xCA\xCB\x99\xCB\x02\x03\x01\x00\x01\xA3\x73\x30\x71\x30\x11\x06\x09\x60\x86\x48\x01\x86\xF8\x42\x01\x01\x04\x04\x03\x02\x00\x07\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x65\xF2\x31\xAD\x2A\xF7\xF7\xDD\x52\x96\x0A\xC7\x02\xC1\x0E\xEF\xA6\xD5\x3B\x11\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0B\x06\x03\x55\x1D\x0F\x04\x04\x03\x02\x01\xFE\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x65\xF2\x31\xAD\x2A\xF7\xF7\xDD\x52\x96\x0A\xC7\x02\xC1\x0E\xEF\xA6\xD5\x3B\x11\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x4B\x35\xEE\xCC\xE4\xAE\xBF\xC3\x6E\xAD\x9F\x95\x3B\x4B\x3F\x5B\x1E\xDF\x57\x29\xA2\x59\xCA\x38\xE2\xB9\x1A\xFF\x9E\xE6\x6E\x32\xDD\x1E\xAE\xEA\x35\xB7\xF5\x93\x91\x4E\xDA\x42\xE1\xC3\x17\x60\x50\xF2\xD1\x5C\x26\xB9\x82\xB7\xEA\x6D\xE4\x9C\x84\xE7\x03\x79\x17\xAF\x98\x3D\x94\xDB\xC7\xBA\x00\xE7\xB8\xBF\x01\x57\xC1\x77\x45\x32\x0C\x3B\xF1\xB4\x1C\x08\xB0\xFD\x51\xA0\xA1\xDD\x9A\x1D\x13\x36\x9A\x6D\xB7\xC7\x3C\xB9\xE1\xC5\xD9\x17\xFA\x83\xD5\x3D\x15\xA0\x3C\xBB\x1E\x0B\xE2\xC8\x90\x3F\xA8\x86\x0C\xFC\xF9\x8B\x5E\x85\xCB\x4F\x5B\x4B\x62\x11\x47\xC5\x45\x7C\x05\x2F\x41\xB1\x9E\x10\x69\x1B\x99\x96\xE0\x55\x79\xFB\x4E\x86\x99\xB8\x94\xDA\x86\x38\x6A\x93\xA3\xE7\xCB\x6E\xE5\xDF\xEA\x21\x55\x89\x9C\x7D\x7D\x7F\x98\xF5\x00\x89\xEE\xE3\x84\xC0\x5C\x96\xB5\xC5\x46\xEA\x46\xE0\x85\x55\xB6\x1B\xC9\x12\xD6\xC1\xCD\xCD\x80\xF3\x02\x01\x3C\xC8\x69\xCB\x45\x48\x63\xD8\x94\xD0\xEC\x85\x0E\x3B\x4E\x11\x65\xF4\x82\x8C\xA6\x3D\xAE\x2E\x22\x94\x09\xC8\x5C\xEA\x3C\x81\x5D\x16\x2A\x03\x97\x16\x55\x09\xDB\x8A\x41\x82\x9E\x66\x9B\x11", + ["OU=ApplicationCA,O=Japanese Government,C=JP"] = "\x30\x82\x03\xA0\x30\x82\x02\x88\xA0\x03\x02\x01\x02\x02\x01\x31\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x43\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x4A\x61\x70\x61\x6E\x65\x73\x65\x20\x47\x6F\x76\x65\x72\x6E\x6D\x65\x6E\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0B\x13\x0D\x41\x70\x70\x6C\x69\x63\x61\x74\x69\x6F\x6E\x43\x41\x30\x1E\x17\x0D\x30\x37\x31\x32\x31\x32\x31\x35\x30\x30\x30\x30\x5A\x17\x0D\x31\x37\x31\x32\x31\x32\x31\x35\x30\x30\x30\x30\x5A\x30\x43\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x4A\x61\x70\x61\x6E\x65\x73\x65\x20\x47\x6F\x76\x65\x72\x6E\x6D\x65\x6E\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0B\x13\x0D\x41\x70\x70\x6C\x69\x63\x61\x74\x69\x6F\x6E\x43\x41\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\xA7\x6D\xE0\x74\x4E\x87\x8F\xA5\x06\xDE\x68\xA2\xDB\x86\x99\x4B\x64\x0D\x71\xF0\x0A\x05\x9B\x8E\xAA\xE1\xCC\x2E\xD2\x6A\x3B\xC1\x7A\xB4\x97\x61\x8D\x8A\xBE\xC6\x9A\x9C\x06\xB4\x86\x51\xE4\x37\x0E\x74\x78\x7E\x5F\x8A\x7F\x94\xA4\xD7\x47\x08\xFD\x50\x5A\x56\xE4\x68\xAC\x28\x73\xA0\x7B\xE9\x7F\x18\x92\x40\x4F\x2D\x9D\xF5\xAE\x44\x48\x73\x36\x06\x9E\x64\x2C\x3B\x34\x23\xDB\x5C\x26\xE4\x71\x79\x8F\xD4\x6E\x79\x22\xB9\x93\xC1\xCA\xCD\xC1\x56\xED\x88\x6A\xD7\xA0\x39\x21\x04\x57\x2C\xA2\xF5\xBC\x47\x41\x4F\x5E\x34\x22\x95\xB5\x1F\x29\x6D\x5E\x4A\xF3\x4D\x72\xBE\x41\x56\x20\x87\xFC\xE9\x50\x47\xD7\x30\x14\xEE\x5C\x8C\x55\xBA\x59\x8D\x87\xFC\x23\xDE\x93\xD0\x04\x8C\xFD\xEF\x6D\xBD\xD0\x7A\xC9\xA5\x3A\x6A\x72\x33\xC6\x4A\x0D\x05\x17\x2A\x2D\x7B\xB1\xA7\xD8\xD6\xF0\xBE\xF4\x3F\xEA\x0E\x28\x6D\x41\x61\x23\x76\x78\xC3\xB8\x65\xA4\xF3\x5A\xAE\xCC\xC2\xAA\xD9\xE7\x58\xDE\xB6\x7E\x9D\x85\x6E\x9F\x2A\x0A\x6F\x9F\x03\x29\x30\x97\x28\x1D\xBC\xB7\xCF\x54\x29\x4E\x51\x31\xF9\x27\xB6\x28\x26\xFE\xA2\x63\xE6\x41\x16\xF0\x33\x98\x47\x02\x03\x01\x00\x01\xA3\x81\x9E\x30\x81\x9B\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x54\x5A\xCB\x26\x3F\x71\xCC\x94\x46\x0D\x96\x53\xEA\x6B\x48\xD0\x93\xFE\x42\x75\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x59\x06\x03\x55\x1D\x11\x04\x52\x30\x50\xA4\x4E\x30\x4C\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x18\x30\x16\x06\x03\x55\x04\x0A\x0C\x0F\xE6\x97\xA5\xE6\x9C\xAC\xE5\x9B\xBD\xE6\x94\xBF\xE5\xBA\x9C\x31\x23\x30\x21\x06\x03\x55\x04\x0B\x0C\x1A\xE3\x82\xA2\xE3\x83\x97\xE3\x83\xAA\xE3\x82\xB1\xE3\x83\xBC\xE3\x82\xB7\xE3\x83\xA7\xE3\x83\xB3\x43\x41\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x39\x6A\x44\x76\x77\x38\x3A\xEC\xA3\x67\x46\x0F\xF9\x8B\x06\xA8\xFB\x6A\x90\x31\xCE\x7E\xEC\xDA\xD1\x89\x7C\x7A\xEB\x2E\x0C\xBD\x99\x32\xE7\xB0\x24\xD6\xC3\xFF\xF5\xB2\x88\x09\x87\x2C\xE3\x54\xE1\xA3\xA6\xB2\x08\x0B\xC0\x85\xA8\xC8\xD2\x9C\x71\xF6\x1D\x9F\x60\xFC\x38\x33\x13\xE1\x9E\xDC\x0B\x5F\xDA\x16\x50\x29\x7B\x2F\x70\x91\x0F\x99\xBA\x34\x34\x8D\x95\x74\xC5\x7E\x78\xA9\x66\x5D\xBD\xCA\x21\x77\x42\x10\xAC\x66\x26\x3D\xDE\x91\xAB\xFD\x15\xF0\x6F\xED\x6C\x5F\x10\xF8\xF3\x16\xF6\x03\x8A\x8F\xA7\x12\x11\x0C\xCB\xFD\x3F\x79\xC1\x9C\xFD\x62\xEE\xA3\xCF\x54\x0C\xD1\x2B\x5F\x17\x3E\xE3\x3E\xBF\xC0\x2B\x3E\x09\x9B\xFE\x88\xA6\x7E\xB4\x92\x17\xFC\x23\x94\x81\xBD\x6E\xA7\xC5\x8C\xC2\xEB\x11\x45\xDB\xF8\x41\xC9\x96\x76\xEA\x70\x5F\x79\x12\x6B\xE4\xA3\x07\x5A\x05\xEF\x27\x49\xCF\x21\x9F\x8A\x4C\x09\x70\x66\xA9\x26\xC1\x2B\x11\x4E\x33\xD2\x0E\xFC\xD6\x6C\xD2\x0E\x32\x64\x68\xFF\xAD\x05\x78\x5F\x03\x1D\xA8\xE3\x90\xAC\x24\xE0\x0F\x40\xA7\x4B\xAE\x8B\x28\xB7\x82\xCA\x18\x07\xE6\xB7\x5B\x74\xE9\x20\x19\x7F\xB2\x1B\x89\x54", + ["CN=GeoTrust Primary Certification Authority - G3,OU=(c) 2008 GeoTrust Inc. - For authorized use only,O=GeoTrust Inc.,C=US"] = "\x30\x82\x03\xFE\x30\x82\x02\xE6\xA0\x03\x02\x01\x02\x02\x10\x15\xAC\x6E\x94\x19\xB2\x79\x4B\x41\xF6\x27\xA9\xC3\x18\x0F\x1F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x98\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x39\x30\x37\x06\x03\x55\x04\x0B\x13\x30\x28\x63\x29\x20\x32\x30\x30\x38\x20\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\x30\x1E\x17\x0D\x30\x38\x30\x34\x30\x32\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x32\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x98\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x39\x30\x37\x06\x03\x55\x04\x0B\x13\x30\x28\x63\x29\x20\x32\x30\x30\x38\x20\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x33\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\xDC\xE2\x5E\x62\x58\x1D\x33\x57\x39\x32\x33\xFA\xEB\xCB\x87\x8C\xA7\xD4\x4A\xDD\x06\x88\xEA\x64\x8E\x31\x98\xA5\x38\x90\x1E\x98\xCF\x2E\x63\x2B\xF0\x46\xBC\x44\xB2\x89\xA1\xC0\x28\x0C\x49\x70\x21\x95\x9F\x64\xC0\xA6\x93\x12\x02\x65\x26\x86\xC6\xA5\x89\xF0\xFA\xD7\x84\xA0\x70\xAF\x4F\x1A\x97\x3F\x06\x44\xD5\xC9\xEB\x72\x10\x7D\xE4\x31\x28\xFB\x1C\x61\xE6\x28\x07\x44\x73\x92\x22\x69\xA7\x03\x88\x6C\x9D\x63\xC8\x52\xDA\x98\x27\xE7\x08\x4C\x70\x3E\xB4\xC9\x12\xC1\xC5\x67\x83\x5D\x33\xF3\x03\x11\xEC\x6A\xD0\x53\xE2\xD1\xBA\x36\x60\x94\x80\xBB\x61\x63\x6C\x5B\x17\x7E\xDF\x40\x94\x1E\xAB\x0D\xC2\x21\x28\x70\x88\xFF\xD6\x26\x6C\x6C\x60\x04\x25\x4E\x55\x7E\x7D\xEF\xBF\x94\x48\xDE\xB7\x1D\xDD\x70\x8D\x05\x5F\x88\xA5\x9B\xF2\xC2\xEE\xEA\xD1\x40\x41\x6D\x62\x38\x1D\x56\x06\xC5\x03\x47\x51\x20\x19\xFC\x7B\x10\x0B\x0E\x62\xAE\x76\x55\xBF\x5F\x77\xBE\x3E\x49\x01\x53\x3D\x98\x25\x03\x76\x24\x5A\x1D\xB4\xDB\x89\xEA\x79\xE5\xB6\xB3\x3B\x3F\xBA\x4C\x28\x41\x7F\x06\xAC\x6A\x8E\xC1\xD0\xF6\x05\x1D\x7D\xE6\x42\x86\xE3\xA5\xD5\x47\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xC4\x79\xCA\x8E\xA1\x4E\x03\x1D\x1C\xDC\x6B\xDB\x31\x5B\x94\x3E\x3F\x30\x7F\x2D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x2D\xC5\x13\xCF\x56\x80\x7B\x7A\x78\xBD\x9F\xAE\x2C\x99\xE7\xEF\xDA\xDF\x94\x5E\x09\x69\xA7\xE7\x6E\x68\x8C\xBD\x72\xBE\x47\xA9\x0E\x97\x12\xB8\x4A\xF1\x64\xD3\x39\xDF\x25\x34\xD4\xC1\xCD\x4E\x81\xF0\x0F\x04\xC4\x24\xB3\x34\x96\xC6\xA6\xAA\x30\xDF\x68\x61\x73\xD7\xF9\x8E\x85\x89\xEF\x0E\x5E\x95\x28\x4A\x2A\x27\x8F\x10\x8E\x2E\x7C\x86\xC4\x02\x9E\xDA\x0C\x77\x65\x0E\x44\x0D\x92\xFD\xFD\xB3\x16\x36\xFA\x11\x0D\x1D\x8C\x0E\x07\x89\x6A\x29\x56\xF7\x72\xF4\xDD\x15\x9C\x77\x35\x66\x57\xAB\x13\x53\xD8\x8E\xC1\x40\xC5\xD7\x13\x16\x5A\x72\xC7\xB7\x69\x01\xC4\x7A\xB1\x83\x01\x68\x7D\x8D\x41\xA1\x94\x18\xC1\x25\x5C\xFC\xF0\xFE\x83\x02\x87\x7C\x0D\x0D\xCF\x2E\x08\x5C\x4A\x40\x0D\x3E\xEC\x81\x61\xE6\x24\xDB\xCA\xE0\x0E\x2D\x07\xB2\x3E\x56\xDC\x8D\xF5\x41\x85\x07\x48\x9B\x0C\x0B\xCB\x49\x3F\x7D\xEC\xB7\xFD\xCB\x8D\x67\x89\x1A\xAB\xED\xBB\x1E\xA3\x00\x08\x08\x17\x2A\x82\x5C\x31\x5D\x46\x8A\x2D\x0F\x86\x9B\x74\xD9\x45\xFB\xD4\x40\xB1\x7A\xAA\x68\x2D\x86\xB2\x99\x22\xE1\xC1\x2B\xC7\x9C\xF8\xF3\x5F\xA8\x82\x12\xEB\x19\x11\x2D", + ["CN=thawte Primary Root CA - G2,OU=(c) 2007 thawte\, Inc. - For authorized use only,O=thawte\, Inc.,C=US"] = "\x30\x82\x02\x88\x30\x82\x02\x0D\xA0\x03\x02\x01\x02\x02\x10\x35\xFC\x26\x5C\xD9\x84\x4F\xC9\x3D\x26\x3D\x57\x9B\xAE\xD7\x56\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x30\x81\x84\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x31\x38\x30\x36\x06\x03\x55\x04\x0B\x13\x2F\x28\x63\x29\x20\x32\x30\x30\x37\x20\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1B\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x37\x31\x31\x30\x35\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x38\x30\x31\x31\x38\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x84\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x31\x38\x30\x36\x06\x03\x55\x04\x0B\x13\x2F\x28\x63\x29\x20\x32\x30\x30\x37\x20\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1B\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x76\x30\x10\x06\x07\x2A\x86\x48\xCE\x3D\x02\x01\x06\x05\x2B\x81\x04\x00\x22\x03\x62\x00\x04\xA2\xD5\x9C\x82\x7B\x95\x9D\xF1\x52\x78\x87\xFE\x8A\x16\xBF\x05\xE6\xDF\xA3\x02\x4F\x0D\x07\xC6\x00\x51\xBA\x0C\x02\x52\x2D\x22\xA4\x42\x39\xC4\xFE\x8F\xEA\xC9\xC1\xBE\xD4\x4D\xFF\x9F\x7A\x9E\xE2\xB1\x7C\x9A\xAD\xA7\x86\x09\x73\x87\xD1\xE7\x9A\xE3\x7A\xA5\xAA\x6E\xFB\xBA\xB3\x70\xC0\x67\x88\xA2\x35\xD4\xA3\x9A\xB1\xFD\xAD\xC2\xEF\x31\xFA\xA8\xB9\xF3\xFB\x08\xC6\x91\xD1\xFB\x29\x95\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9A\xD8\x00\x30\x00\xE7\x6B\x7F\x85\x18\xEE\x8B\xB6\xCE\x8A\x0C\xF8\x11\xE1\xBB\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x03\x69\x00\x30\x66\x02\x31\x00\xDD\xF8\xE0\x57\x47\x5B\xA7\xE6\x0A\xC3\xBD\xF5\x80\x8A\x97\x35\x0D\x1B\x89\x3C\x54\x86\x77\x28\xCA\xA1\xF4\x79\xDE\xB5\xE6\x38\xB0\xF0\x65\x70\x8C\x7F\x02\x54\xC2\xBF\xFF\xD8\xA1\x3E\xD9\xCF\x02\x31\x00\xC4\x8D\x94\xFC\xDC\x53\xD2\xDC\x9D\x78\x16\x1F\x15\x33\x23\x53\x52\xE3\x5A\x31\x5D\x9D\xCA\xAE\xBD\x13\x29\x44\x0D\x27\x5B\xA8\xE7\x68\x9C\x12\xF7\x58\x3F\x2E\x72\x02\x57\xA3\x8F\xA1\x14\x2E", + ["CN=thawte Primary Root CA - G3,OU=(c) 2008 thawte\, Inc. - For authorized use only,OU=Certification Services Division,O=thawte\, Inc.,C=US"] = "\x30\x82\x04\x2A\x30\x82\x03\x12\xA0\x03\x02\x01\x02\x02\x10\x60\x01\x97\xB7\x46\xA7\xEA\xB4\xB4\x9A\xD6\x4B\x2F\xF7\x90\xFB\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x38\x30\x36\x06\x03\x55\x04\x0B\x13\x2F\x28\x63\x29\x20\x32\x30\x30\x38\x20\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1B\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x47\x33\x30\x1E\x17\x0D\x30\x38\x30\x34\x30\x32\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x32\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x13\x0C\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x31\x28\x30\x26\x06\x03\x55\x04\x0B\x13\x1F\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x44\x69\x76\x69\x73\x69\x6F\x6E\x31\x38\x30\x36\x06\x03\x55\x04\x0B\x13\x2F\x28\x63\x29\x20\x32\x30\x30\x38\x20\x74\x68\x61\x77\x74\x65\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x24\x30\x22\x06\x03\x55\x04\x03\x13\x1B\x74\x68\x61\x77\x74\x65\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x47\x33\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\xB2\xBF\x27\x2C\xFB\xDB\xD8\x5B\xDD\x78\x7B\x1B\x9E\x77\x66\x81\xCB\x3E\xBC\x7C\xAE\xF3\xA6\x27\x9A\x34\xA3\x68\x31\x71\x38\x33\x62\xE4\xF3\x71\x66\x79\xB1\xA9\x65\xA3\xA5\x8B\xD5\x8F\x60\x2D\x3F\x42\xCC\xAA\x6B\x32\xC0\x23\xCB\x2C\x41\xDD\xE4\xDF\xFC\x61\x9C\xE2\x73\xB2\x22\x95\x11\x43\x18\x5F\xC4\xB6\x1F\x57\x6C\x0A\x05\x58\x22\xC8\x36\x4C\x3A\x7C\xA5\xD1\xCF\x86\xAF\x88\xA7\x44\x02\x13\x74\x71\x73\x0A\x42\x59\x02\xF8\x1B\x14\x6B\x42\xDF\x6F\x5F\xBA\x6B\x82\xA2\x9D\x5B\xE7\x4A\xBD\x1E\x01\x72\xDB\x4B\x74\xE8\x3B\x7F\x7F\x7D\x1F\x04\xB4\x26\x9B\xE0\xB4\x5A\xAC\x47\x3D\x55\xB8\xD7\xB0\x26\x52\x28\x01\x31\x40\x66\xD8\xD9\x24\xBD\xF6\x2A\xD8\xEC\x21\x49\x5C\x9B\xF6\x7A\xE9\x7F\x55\x35\x7E\x96\x6B\x8D\x93\x93\x27\xCB\x92\xBB\xEA\xAC\x40\xC0\x9F\xC2\xF8\x80\xCF\x5D\xF4\x5A\xDC\xCE\x74\x86\xA6\x3E\x6C\x0B\x53\xCA\xBD\x92\xCE\x19\x06\x72\xE6\x0C\x5C\x38\x69\xC7\x04\xD6\xBC\x6C\xCE\x5B\xF6\xF7\x68\x9C\xDC\x25\x15\x48\x88\xA1\xE9\xA9\xF8\x98\x9C\xE0\xF3\xD5\x31\x28\x61\x11\x6C\x67\x96\x8D\x39\x99\xCB\xC2\x45\x24\x39\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xAD\x6C\xAA\x94\x60\x9C\xED\xE4\xFF\xFA\x3E\x0A\x74\x2B\x63\x03\xF7\xB6\x59\xBF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x1A\x40\xD8\x95\x65\xAC\x09\x92\x89\xC6\x39\xF4\x10\xE5\xA9\x0E\x66\x53\x5D\x78\xDE\xFA\x24\x91\xBB\xE7\x44\x51\xDF\xC6\x16\x34\x0A\xEF\x6A\x44\x51\xEA\x2B\x07\x8A\x03\x7A\xC3\xEB\x3F\x0A\x2C\x52\x16\xA0\x2B\x43\xB9\x25\x90\x3F\x70\xA9\x33\x25\x6D\x45\x1A\x28\x3B\x27\xCF\xAA\xC3\x29\x42\x1B\xDF\x3B\x4C\xC0\x33\x34\x5B\x41\x88\xBF\x6B\x2B\x65\xAF\x28\xEF\xB2\xF5\xC3\xAA\x66\xCE\x7B\x56\xEE\xB7\xC8\xCB\x67\xC1\xC9\x9C\x1A\x18\xB8\xC4\xC3\x49\x03\xF1\x60\x0E\x50\xCD\x46\xC5\xF3\x77\x79\xF7\xB6\x15\xE0\x38\xDB\xC7\x2F\x28\xA0\x0C\x3F\x77\x26\x74\xD9\x25\x12\xDA\x31\xDA\x1A\x1E\xDC\x29\x41\x91\x22\x3C\x69\xA7\xBB\x02\xF2\xB6\x5C\x27\x03\x89\xF4\x06\xEA\x9B\xE4\x72\x82\xE3\xA1\x09\xC1\xE9\x00\x19\xD3\x3E\xD4\x70\x6B\xBA\x71\xA6\xAA\x58\xAE\xF4\xBB\xE9\x6C\xB6\xEF\x87\xCC\x9B\xBB\xFF\x39\xE6\x56\x61\xD3\x0A\xA7\xC4\x5C\x4C\x60\x7B\x05\x77\x26\x7A\xBF\xD8\x07\x52\x2C\x62\xF7\x70\x63\xD9\x39\xBC\x6F\x1C\xC2\x79\xDC\x76\x29\xAF\xCE\xC5\x2C\x64\x04\x5E\x88\x36\x6E\x31\xD4\x40\x1A\x62\x34\x36\x3F\x35\x01\xAE\xAC\x63\xA0", + ["CN=GeoTrust Primary Certification Authority - G2,OU=(c) 2007 GeoTrust Inc. - For authorized use only,O=GeoTrust Inc.,C=US"] = "\x30\x82\x02\xAE\x30\x82\x02\x35\xA0\x03\x02\x01\x02\x02\x10\x3C\xB2\xF4\x48\x0A\x00\xE2\xFE\xEB\x24\x3B\x5E\x60\x3E\xC3\x6B\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x30\x81\x98\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x39\x30\x37\x06\x03\x55\x04\x0B\x13\x30\x28\x63\x29\x20\x32\x30\x30\x37\x20\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x37\x31\x31\x30\x35\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x38\x30\x31\x31\x38\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x98\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x31\x39\x30\x37\x06\x03\x55\x04\x0B\x13\x30\x28\x63\x29\x20\x32\x30\x30\x37\x20\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x36\x30\x34\x06\x03\x55\x04\x03\x13\x2D\x47\x65\x6F\x54\x72\x75\x73\x74\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x30\x76\x30\x10\x06\x07\x2A\x86\x48\xCE\x3D\x02\x01\x06\x05\x2B\x81\x04\x00\x22\x03\x62\x00\x04\x15\xB1\xE8\xFD\x03\x15\x43\xE5\xAC\xEB\x87\x37\x11\x62\xEF\xD2\x83\x36\x52\x7D\x45\x57\x0B\x4A\x8D\x7B\x54\x3B\x3A\x6E\x5F\x15\x02\xC0\x50\xA6\xCF\x25\x2F\x7D\xCA\x48\xB8\xC7\x50\x63\x1C\x2A\x21\x08\x7C\x9A\x36\xD8\x0B\xFE\xD1\x26\xC5\x58\x31\x30\x28\x25\xF3\x5D\x5D\xA3\xB8\xB6\xA5\xB4\x92\xED\x6C\x2C\x9F\xEB\xDD\x43\x89\xA2\x3C\x4B\x48\x91\x1D\x50\xEC\x26\xDF\xD6\x60\x2E\xBD\x21\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x15\x5F\x35\x57\x51\x55\xFB\x25\xB2\xAD\x03\x69\xFC\x01\xA3\xFA\xBE\x11\x55\xD5\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x03\x67\x00\x30\x64\x02\x30\x64\x96\x59\xA6\xE8\x09\xDE\x8B\xBA\xFA\x5A\x88\x88\xF0\x1F\x91\xD3\x46\xA8\xF2\x4A\x4C\x02\x63\xFB\x6C\x5F\x38\xDB\x2E\x41\x93\xA9\x0E\xE6\x9D\xDC\x31\x1C\xB2\xA0\xA7\x18\x1C\x79\xE1\xC7\x36\x02\x30\x3A\x56\xAF\x9A\x74\x6C\xF6\xFB\x83\xE0\x33\xD3\x08\x5F\xA1\x9C\xC2\x5B\x9F\x46\xD6\xB6\xCB\x91\x06\x63\xA2\x06\xE7\x33\xAC\x3E\xA8\x81\x12\xD0\xCB\xBA\xD0\x92\x0B\xB6\x9E\x96\xAA\x04\x0F\x8A", + ["CN=VeriSign Universal Root Certification Authority,OU=(c) 2008 VeriSign\, Inc. - For authorized use only,OU=VeriSign Trust Network,O=VeriSign\, Inc.,C=US"] = "\x30\x82\x04\xB9\x30\x82\x03\xA1\xA0\x03\x02\x01\x02\x02\x10\x40\x1A\xC4\x64\x21\xB3\x13\x21\x03\x0E\xBB\xE4\x12\x1A\xC5\x1D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\xBD\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x32\x30\x30\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x38\x30\x36\x06\x03\x55\x04\x03\x13\x2F\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x38\x30\x34\x30\x32\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x32\x30\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xBD\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x32\x30\x30\x38\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x38\x30\x36\x06\x03\x55\x04\x03\x13\x2F\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xC7\x61\x37\x5E\xB1\x01\x34\xDB\x62\xD7\x15\x9B\xFF\x58\x5A\x8C\x23\x23\xD6\x60\x8E\x91\xD7\x90\x98\x83\x7A\xE6\x58\x19\x38\x8C\xC5\xF6\xE5\x64\x85\xB4\xA2\x71\xFB\xED\xBD\xB9\xDA\xCD\x4D\x00\xB4\xC8\x2D\x73\xA5\xC7\x69\x71\x95\x1F\x39\x3C\xB2\x44\x07\x9C\xE8\x0E\xFA\x4D\x4A\xC4\x21\xDF\x29\x61\x8F\x32\x22\x61\x82\xC5\x87\x1F\x6E\x8C\x7C\x5F\x16\x20\x51\x44\xD1\x70\x4F\x57\xEA\xE3\x1C\xE3\xCC\x79\xEE\x58\xD8\x0E\xC2\xB3\x45\x93\xC0\x2C\xE7\x9A\x17\x2B\x7B\x00\x37\x7A\x41\x33\x78\xE1\x33\xE2\xF3\x10\x1A\x7F\x87\x2C\xBE\xF6\xF5\xF7\x42\xE2\xE5\xBF\x87\x62\x89\x5F\x00\x4B\xDF\xC5\xDD\xE4\x75\x44\x32\x41\x3A\x1E\x71\x6E\x69\xCB\x0B\x75\x46\x08\xD1\xCA\xD2\x2B\x95\xD0\xCF\xFB\xB9\x40\x6B\x64\x8C\x57\x4D\xFC\x13\x11\x79\x84\xED\x5E\x54\xF6\x34\x9F\x08\x01\xF3\x10\x25\x06\x17\x4A\xDA\xF1\x1D\x7A\x66\x6B\x98\x60\x66\xA4\xD9\xEF\xD2\x2E\x82\xF1\xF0\xEF\x09\xEA\x44\xC9\x15\x6A\xE2\x03\x6E\x33\xD3\xAC\x9F\x55\x00\xC7\xF6\x08\x6A\x94\xB9\x5F\xDC\xE0\x33\xF1\x84\x60\xF9\x5B\x27\x11\xB4\xFC\x16\xF2\xBB\x56\x6A\x80\x25\x8D\x02\x03\x01\x00\x01\xA3\x81\xB2\x30\x81\xAF\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x6D\x06\x08\x2B\x06\x01\x05\x05\x07\x01\x0C\x04\x61\x30\x5F\xA1\x5D\xA0\x5B\x30\x59\x30\x57\x30\x55\x16\x09\x69\x6D\x61\x67\x65\x2F\x67\x69\x66\x30\x21\x30\x1F\x30\x07\x06\x05\x2B\x0E\x03\x02\x1A\x04\x14\x8F\xE5\xD3\x1A\x86\xAC\x8D\x8E\x6B\xC3\xCF\x80\x6A\xD4\x48\x18\x2C\x7B\x19\x2E\x30\x25\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x6C\x6F\x67\x6F\x2E\x76\x65\x72\x69\x73\x69\x67\x6E\x2E\x63\x6F\x6D\x2F\x76\x73\x6C\x6F\x67\x6F\x2E\x67\x69\x66\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB6\x77\xFA\x69\x48\x47\x9F\x53\x12\xD5\xC2\xEA\x07\x32\x76\x07\xD1\x97\x07\x19\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x4A\xF8\xF8\xB0\x03\xE6\x2C\x67\x7B\xE4\x94\x77\x63\xCC\x6E\x4C\xF9\x7D\x0E\x0D\xDC\xC8\xB9\x35\xB9\x70\x4F\x63\xFA\x24\xFA\x6C\x83\x8C\x47\x9D\x3B\x63\xF3\x9A\xF9\x76\x32\x95\x91\xB1\x77\xBC\xAC\x9A\xBE\xB1\xE4\x31\x21\xC6\x81\x95\x56\x5A\x0E\xB1\xC2\xD4\xB1\xA6\x59\xAC\xF1\x63\xCB\xB8\x4C\x1D\x59\x90\x4A\xEF\x90\x16\x28\x1F\x5A\xAE\x10\xFB\x81\x50\x38\x0C\x6C\xCC\xF1\x3D\xC3\xF5\x63\xE3\xB3\xE3\x21\xC9\x24\x39\xE9\xFD\x15\x66\x46\xF4\x1B\x11\xD0\x4D\x73\xA3\x7D\x46\xF9\x3D\xED\xA8\x5F\x62\xD4\xF1\x3F\xF8\xE0\x74\x57\x2B\x18\x9D\x81\xB4\xC4\x28\xDA\x94\x97\xA5\x70\xEB\xAC\x1D\xBE\x07\x11\xF0\xD5\xDB\xDD\xE5\x8C\xF0\xD5\x32\xB0\x83\xE6\x57\xE2\x8F\xBF\xBE\xA1\xAA\xBF\x3D\x1D\xB5\xD4\x38\xEA\xD7\xB0\x5C\x3A\x4F\x6A\x3F\x8F\xC0\x66\x6C\x63\xAA\xE9\xD9\xA4\x16\xF4\x81\xD1\x95\x14\x0E\x7D\xCD\x95\x34\xD9\xD2\x8F\x70\x73\x81\x7B\x9C\x7E\xBD\x98\x61\xD8\x45\x87\x98\x90\xC5\xEB\x86\x30\xC6\x35\xBF\xF0\xFF\xC3\x55\x88\x83\x4B\xEF\x05\x92\x06\x71\xF2\xB8\x98\x93\xB7\xEC\xCD\x82\x61\xF1\x38\xE6\x4F\x97\x98\x2A\x5A\x8D", + ["CN=VeriSign Class 3 Public Primary Certification Authority - G4,OU=(c) 2007 VeriSign\, Inc. - For authorized use only,OU=VeriSign Trust Network,O=VeriSign\, Inc.,C=US"] = "\x30\x82\x03\x84\x30\x82\x03\x0A\xA0\x03\x02\x01\x02\x02\x10\x2F\x80\xFE\x23\x8C\x0E\x22\x0F\x48\x67\x12\x28\x91\x87\xAC\xB3\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x32\x30\x30\x37\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x34\x30\x1E\x17\x0D\x30\x37\x31\x31\x30\x35\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x38\x30\x31\x31\x38\x32\x33\x35\x39\x35\x39\x5A\x30\x81\xCA\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x17\x30\x15\x06\x03\x55\x04\x0A\x13\x0E\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x31\x1F\x30\x1D\x06\x03\x55\x04\x0B\x13\x16\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x31\x3A\x30\x38\x06\x03\x55\x04\x0B\x13\x31\x28\x63\x29\x20\x32\x30\x30\x37\x20\x56\x65\x72\x69\x53\x69\x67\x6E\x2C\x20\x49\x6E\x63\x2E\x20\x2D\x20\x46\x6F\x72\x20\x61\x75\x74\x68\x6F\x72\x69\x7A\x65\x64\x20\x75\x73\x65\x20\x6F\x6E\x6C\x79\x31\x45\x30\x43\x06\x03\x55\x04\x03\x13\x3C\x56\x65\x72\x69\x53\x69\x67\x6E\x20\x43\x6C\x61\x73\x73\x20\x33\x20\x50\x75\x62\x6C\x69\x63\x20\x50\x72\x69\x6D\x61\x72\x79\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x34\x30\x76\x30\x10\x06\x07\x2A\x86\x48\xCE\x3D\x02\x01\x06\x05\x2B\x81\x04\x00\x22\x03\x62\x00\x04\xA7\x56\x7A\x7C\x52\xDA\x64\x9B\x0E\x2D\x5C\xD8\x5E\xAC\x92\x3D\xFE\x01\xE6\x19\x4A\x3D\x14\x03\x4B\xFA\x60\x27\x20\xD9\x83\x89\x69\xFA\x54\xC6\x9A\x18\x5E\x55\x2A\x64\xDE\x06\xF6\x8D\x4A\x3B\xAD\x10\x3C\x65\x3D\x90\x88\x04\x89\xE0\x30\x61\xB3\xAE\x5D\x01\xA7\x7B\xDE\x7C\xB2\xBE\xCA\x65\x61\x00\x86\xAE\xDA\x8F\x7B\xD0\x89\xAD\x4D\x1D\x59\x9A\x41\xB1\xBC\x47\x80\xDC\x9E\x62\xC3\xF9\xA3\x81\xB2\x30\x81\xAF\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x6D\x06\x08\x2B\x06\x01\x05\x05\x07\x01\x0C\x04\x61\x30\x5F\xA1\x5D\xA0\x5B\x30\x59\x30\x57\x30\x55\x16\x09\x69\x6D\x61\x67\x65\x2F\x67\x69\x66\x30\x21\x30\x1F\x30\x07\x06\x05\x2B\x0E\x03\x02\x1A\x04\x14\x8F\xE5\xD3\x1A\x86\xAC\x8D\x8E\x6B\xC3\xCF\x80\x6A\xD4\x48\x18\x2C\x7B\x19\x2E\x30\x25\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x6C\x6F\x67\x6F\x2E\x76\x65\x72\x69\x73\x69\x67\x6E\x2E\x63\x6F\x6D\x2F\x76\x73\x6C\x6F\x67\x6F\x2E\x67\x69\x66\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB3\x16\x91\xFD\xEE\xA6\x6E\xE4\xB5\x2E\x49\x8F\x87\x78\x81\x80\xEC\xE5\xB1\xB5\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x03\x68\x00\x30\x65\x02\x30\x66\x21\x0C\x18\x26\x60\x5A\x38\x7B\x56\x42\xE0\xA7\xFC\x36\x84\x51\x91\x20\x2C\x76\x4D\x43\x3D\xC4\x1D\x84\x23\xD0\xAC\xD6\x7C\x35\x06\xCE\xCD\x69\xBD\x90\x0D\xDB\x6C\x48\x42\x1D\x0E\xAA\x42\x02\x31\x00\x9C\x3D\x48\x39\x23\x39\x58\x1A\x15\x12\x59\x6A\x9E\xEF\xD5\x59\xB2\x1D\x52\x2C\x99\x71\xCD\xC7\x29\xDF\x1B\x2A\x61\x7B\x71\xD1\xDE\xF3\xC0\xE5\x0D\x3A\x4A\xAA\x2D\xA7\xD8\x86\x2A\xDD\x2E\x10", + ["CN=NetLock Arany (Class Gold) F\C5\91tan\C3\BAs\C3\ADtv\C3\A1ny,OU=Tan\C3\BAs\C3\ADtv\C3\A1nykiad\C3\B3k (Certification Services),O=NetLock Kft.,L=Budapest,C=HU"] = "\x30\x82\x04\x15\x30\x82\x02\xFD\xA0\x03\x02\x01\x02\x02\x06\x49\x41\x2C\xE4\x00\x10\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\xA7\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x0C\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x0C\x0C\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x31\x37\x30\x35\x06\x03\x55\x04\x0B\x0C\x2E\x54\x61\x6E\xC3\xBA\x73\xC3\xAD\x74\x76\xC3\xA1\x6E\x79\x6B\x69\x61\x64\xC3\xB3\x6B\x20\x28\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x29\x31\x35\x30\x33\x06\x03\x55\x04\x03\x0C\x2C\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x41\x72\x61\x6E\x79\x20\x28\x43\x6C\x61\x73\x73\x20\x47\x6F\x6C\x64\x29\x20\x46\xC5\x91\x74\x61\x6E\xC3\xBA\x73\xC3\xAD\x74\x76\xC3\xA1\x6E\x79\x30\x1E\x17\x0D\x30\x38\x31\x32\x31\x31\x31\x35\x30\x38\x32\x31\x5A\x17\x0D\x32\x38\x31\x32\x30\x36\x31\x35\x30\x38\x32\x31\x5A\x30\x81\xA7\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x0C\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x15\x30\x13\x06\x03\x55\x04\x0A\x0C\x0C\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x4B\x66\x74\x2E\x31\x37\x30\x35\x06\x03\x55\x04\x0B\x0C\x2E\x54\x61\x6E\xC3\xBA\x73\xC3\xAD\x74\x76\xC3\xA1\x6E\x79\x6B\x69\x61\x64\xC3\xB3\x6B\x20\x28\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x29\x31\x35\x30\x33\x06\x03\x55\x04\x03\x0C\x2C\x4E\x65\x74\x4C\x6F\x63\x6B\x20\x41\x72\x61\x6E\x79\x20\x28\x43\x6C\x61\x73\x73\x20\x47\x6F\x6C\x64\x29\x20\x46\xC5\x91\x74\x61\x6E\xC3\xBA\x73\xC3\xAD\x74\x76\xC3\xA1\x6E\x79\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\xC4\x24\x5E\x73\xBE\x4B\x6D\x14\xC3\xA1\xF4\xE3\x97\x90\x6E\xD2\x30\x45\x1E\x3C\xEE\x67\xD9\x64\xE0\x1A\x8A\x7F\xCA\x30\xCA\x83\xE3\x20\xC1\xE3\xF4\x3A\xD3\x94\x5F\x1A\x7C\x5B\x6D\xBF\x30\x4F\x84\x27\xF6\x9F\x1F\x49\xBC\xC6\x99\x0A\x90\xF2\x0F\xF5\x7F\x43\x84\x37\x63\x51\x8B\x7A\xA5\x70\xFC\x7A\x58\xCD\x8E\x9B\xED\xC3\x46\x6C\x84\x70\x5D\xDA\xF3\x01\x90\x23\xFC\x4E\x30\xA9\x7E\xE1\x27\x63\xE7\xED\x64\x3C\xA0\xB8\xC9\x33\x63\xFE\x16\x90\xFF\xB0\xB8\xFD\xD7\xA8\xC0\xC0\x94\x43\x0B\xB6\xD5\x59\xA6\x9E\x56\xD0\x24\x1F\x70\x79\xAF\xDB\x39\x54\x0D\x65\x75\xD9\x15\x41\x94\x01\xAF\x5E\xEC\xF6\x8D\xF1\xFF\xAD\x64\xFE\x20\x9A\xD7\x5C\xEB\xFE\xA6\x1F\x08\x64\xA3\x8B\x76\x55\xAD\x1E\x3B\x28\x60\x2E\x87\x25\xE8\xAA\xAF\x1F\xC6\x64\x46\x20\xB7\x70\x7F\x3C\xDE\x48\xDB\x96\x53\xB7\x39\x77\xE4\x1A\xE2\xC7\x16\x84\x76\x97\x5B\x2F\xBB\x19\x15\x85\xF8\x69\x85\xF5\x99\xA7\xA9\xF2\x34\xA7\xA9\xB6\xA6\x03\xFC\x6F\x86\x3D\x54\x7C\x76\x04\x9B\x6B\xF9\x40\x5D\x00\x34\xC7\x2E\x99\x75\x9D\xE5\x88\x03\xAA\x4D\xF8\x03\xD2\x42\x76\xC0\x1B\x02\x03\x00\xA8\x8B\xA3\x45\x30\x43\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x04\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xCC\xFA\x67\x93\xF0\xB6\xB8\xD0\xA5\xC0\x1E\xF3\x53\xFD\x8C\x53\xDF\x83\xD7\x96\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\xAB\x7F\xEE\x1C\x16\xA9\x9C\x3C\x51\x00\xA0\xC0\x11\x08\x05\xA7\x99\xE6\x6F\x01\x88\x54\x61\x6E\xF1\xB9\x18\xAD\x4A\xAD\xFE\x81\x40\x23\x94\x2F\xFB\x75\x7C\x2F\x28\x4B\x62\x24\x81\x82\x0B\xF5\x61\xF1\x1C\x6E\xB8\x61\x38\xEB\x81\xFA\x62\xA1\x3B\x5A\x62\xD3\x94\x65\xC4\xE1\xE6\x6D\x82\xF8\x2F\x25\x70\xB2\x21\x26\xC1\x72\x51\x1F\x8C\x2C\xC3\x84\x90\xC3\x5A\x8F\xBA\xCF\xF4\xA7\x65\xA5\xEB\x98\xD1\xFB\x05\xB2\x46\x75\x15\x23\x6A\x6F\x85\x63\x30\x80\xF0\xD5\x9E\x1F\x29\x1C\xC2\x6C\xB0\x50\x59\x5D\x90\x5B\x3B\xA8\x0D\x30\xCF\xBF\x7D\x7F\xCE\xF1\x9D\x83\xBD\xC9\x46\x6E\x20\xA6\xF9\x61\x51\xBA\x21\x2F\x7B\xBE\xA5\x15\x63\xA1\xD4\x95\x87\xF1\x9E\xB9\xF3\x89\xF3\x3D\x85\xB8\xB8\xDB\xBE\xB5\xB9\x29\xF9\xDA\x37\x05\x00\x49\x94\x03\x84\x44\xE7\xBF\x43\x31\xCF\x75\x8B\x25\xD1\xF4\xA6\x64\xF5\x92\xF6\xAB\x05\xEB\x3D\xE9\xA5\x0B\x36\x62\xDA\xCC\x06\x5F\x36\x8B\xB6\x5E\x31\xB8\x2A\xFB\x5E\xF6\x71\xDF\x44\x26\x9E\xC4\xE6\x0D\x91\xB4\x2E\x75\x95\x80\x51\x6A\x4B\x30\xA6\xB0\x62\xA1\x93\xF1\x9B\xD8\xCE\xC4\x63\x75\x3F\x59\x47\xB1", + ["CN=Staat der Nederlanden Root CA - G2,O=Staat der Nederlanden,C=NL"] = "\x30\x82\x05\xCA\x30\x82\x03\xB2\xA0\x03\x02\x01\x02\x02\x04\x00\x98\x96\x8C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4C\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x0C\x15\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x31\x2B\x30\x29\x06\x03\x55\x04\x03\x0C\x22\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x38\x30\x33\x32\x36\x31\x31\x31\x38\x31\x37\x5A\x17\x0D\x32\x30\x30\x33\x32\x35\x31\x31\x30\x33\x31\x30\x5A\x30\x5A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4E\x4C\x31\x1E\x30\x1C\x06\x03\x55\x04\x0A\x0C\x15\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x31\x2B\x30\x29\x06\x03\x55\x04\x03\x0C\x22\x53\x74\x61\x61\x74\x20\x64\x65\x72\x20\x4E\x65\x64\x65\x72\x6C\x61\x6E\x64\x65\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x47\x32\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC5\x59\xE7\x6F\x75\xAA\x3E\x4B\x9C\xB5\xB8\xAC\x9E\x0B\xE4\xF9\xD9\xCA\xAB\x5D\x8F\xB5\x39\x10\x82\xD7\xAF\x51\xE0\x3B\xE1\x00\x48\x6A\xCF\xDA\xE1\x06\x43\x11\x99\xAA\x14\x25\x12\xAD\x22\xE8\x00\x6D\x43\xC4\xA9\xB8\xE5\x1F\x89\x4B\x67\xBD\x61\x48\xEF\xFD\xD2\xE0\x60\x88\xE5\xB9\x18\x60\x28\xC3\x77\x2B\xAD\xB0\x37\xAA\x37\xDE\x64\x59\x2A\x46\x57\xE4\x4B\xB9\xF8\x37\x7C\xD5\x36\xE7\x80\xC1\xB6\xF3\xD4\x67\x9B\x96\xE8\xCE\xD7\xC6\x0A\x53\xD0\x6B\x49\x96\xF3\xA3\x0B\x05\x77\x48\xF7\x25\xE5\x70\xAC\x30\x14\x20\x25\xE3\x7F\x75\x5A\xE5\x48\xF8\x4E\x7B\x03\x07\x04\xFA\x82\x61\x87\x6E\xF0\x3B\xC4\xA4\xC7\xD0\xF5\x74\x3E\xA5\x5D\x1A\x08\xF2\x9B\x25\xD2\xF6\xAC\x04\x26\x3E\x55\x3A\x62\x28\xA5\x7B\xB2\x30\xAF\xF8\x37\xC2\xD1\xBA\xD6\x38\xFD\xF4\xEF\x49\x30\x37\x99\x26\x21\x48\x85\x01\xA9\xE5\x16\xE7\xDC\x90\x55\xDF\x0F\xE8\x38\xCD\x99\x37\x21\x4F\x5D\xF5\x22\x6F\x6A\xC5\x12\x16\x60\x17\x55\xF2\x65\x66\xA6\xA7\x30\x91\x38\xC1\x38\x1D\x86\x04\x84\xBA\x1A\x25\x78\x5E\x9D\xAF\xCC\x50\x60\xD6\x13\x87\x52\xED\x63\x1F\x6D\x65\x7D\xC2\x15\x18\x74\xCA\xE1\x7E\x64\x29\x8C\x72\xD8\x16\x13\x7D\x0B\x49\x4A\xF1\x28\x1B\x20\x74\x6B\xC5\x3D\xDD\xB0\xAA\x48\x09\x3D\x2E\x82\x94\xCD\x1A\x65\xD9\x2B\x88\x9A\x99\xBC\x18\x7E\x9F\xEE\x7D\x66\x7C\x3E\xBD\x94\xB8\x81\xCE\xCD\x98\x30\x78\xC1\x6F\x67\xD0\xBE\x5F\xE0\x68\xED\xDE\xE2\xB1\xC9\x2C\x59\x78\x92\xAA\xDF\x2B\x60\x63\xF2\xE5\x5E\xB9\xE3\xCA\xFA\x7F\x50\x86\x3E\xA2\x34\x18\x0C\x09\x68\x28\x11\x1C\xE4\xE1\xB9\x5C\x3E\x47\xBA\x32\x3F\x18\xCC\x5B\x84\xF5\xF3\x6B\x74\xC4\x72\x74\xE1\xE3\x8B\xA0\x4A\xBD\x8D\x66\x2F\xEA\xAD\x35\xDA\x20\xD3\x88\x82\x61\xF0\x12\x22\xB6\xBC\xD0\xD5\xA4\xEC\xAF\x54\x88\x25\x24\x3C\xA7\x6D\xB1\x72\x29\x3F\x3E\x57\xA6\x7F\x55\xAF\x6E\x26\xC6\xFE\xE7\xCC\x40\x5C\x51\x44\x81\x0A\x78\xDE\x4A\xCE\x55\xBF\x1D\xD5\xD9\xB7\x56\xEF\xF0\x76\xFF\x0B\x79\xB5\xAF\xBD\xFB\xA9\x69\x91\x46\x97\x68\x80\x14\x36\x1D\xB3\x7F\xBB\x29\x98\x36\xA5\x20\xFA\x82\x60\x62\x33\xA4\xEC\xD6\xBA\x07\xA7\x6E\xC5\xCF\x14\xA6\xE7\xD6\x92\x34\xD8\x81\xF5\xFC\x1D\x5D\xAA\x5C\x1E\xF6\xA3\x4D\x3B\xB8\xF7\x39\x02\x03\x01\x00\x01\xA3\x81\x97\x30\x81\x94\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x52\x06\x03\x55\x1D\x20\x04\x4B\x30\x49\x30\x47\x06\x04\x55\x1D\x20\x00\x30\x3F\x30\x3D\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x31\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x70\x6B\x69\x6F\x76\x65\x72\x68\x65\x69\x64\x2E\x6E\x6C\x2F\x70\x6F\x6C\x69\x63\x69\x65\x73\x2F\x72\x6F\x6F\x74\x2D\x70\x6F\x6C\x69\x63\x79\x2D\x47\x32\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x91\x68\x32\x87\x15\x1D\x89\xE2\xB5\xF1\xAC\x36\x28\x34\x8D\x0B\x7C\x62\x88\xEB\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\xA8\x41\x4A\x67\x2A\x92\x81\x82\x50\x6E\xE1\xD7\xD8\xB3\x39\x3B\xF3\x02\x15\x09\x50\x51\xEF\x2D\xBD\x24\x7B\x88\x86\x3B\xF9\xB4\xBC\x92\x09\x96\xB9\xF6\xC0\xAB\x23\x60\x06\x79\x8C\x11\x4E\x51\xD2\x79\x80\x33\xFB\x9D\x48\xBE\xEC\x41\x43\x81\x1F\x7E\x47\x40\x1C\xE5\x7A\x08\xCA\xAA\x8B\x75\xAD\x14\xC4\xC2\xE8\x66\x3C\x82\x07\xA7\xE6\x27\x82\x5B\x18\xE6\x0F\x6E\xD9\x50\x3E\x8A\x42\x18\x29\xC6\xB4\x56\xFC\x56\x10\xA0\x05\x17\xBD\x0C\x23\x7F\xF4\x93\xED\x9C\x1A\x51\xBE\xDD\x45\x41\xBF\x91\x24\xB4\x1F\x8C\xE9\x5F\xCF\x7B\x21\x99\x9F\x95\x9F\x39\x3A\x46\x1C\x6C\xF9\xCD\x7B\x9C\x90\xCD\x28\xA9\xC7\xA9\x55\xBB\xAC\x62\x34\x62\x35\x13\x4B\x14\x3A\x55\x83\xB9\x86\x8D\x92\xA6\xC6\xF4\x07\x25\x54\xCC\x16\x57\x12\x4A\x82\x78\xC8\x14\xD9\x17\x82\x26\x2D\x5D\x20\x1F\x79\xAE\xFE\xD4\x70\x16\x16\x95\x83\xD8\x35\x39\xFF\x52\x5D\x75\x1C\x16\xC5\x13\x55\xCF\x47\xCC\x75\x65\x52\x4A\xDE\xF0\xB0\xA7\xE4\x0A\x96\x0B\xFB\xAD\xC2\xE2\x25\x84\xB2\xDD\xE4\xBD\x7E\x59\x6C\x9B\xF0\xF0\xD8\xE7\xCA\xF2\xE9\x97\x38\x7E\x89\xBE\xCC\xFB\x39\x17\x61\x3F\x72\xDB\x3A\x91\xD8\x65\x01\x19\x1D\xAD\x50\xA4\x57\x0A\x7C\x4B\xBC\x9C\x71\x73\x2A\x45\x51\x19\x85\xCC\x8E\xFD\x47\xA7\x74\x95\x1D\xA8\xD1\xAF\x4E\x17\xB1\x69\x26\xC2\xAA\x78\x57\x5B\xC5\x4D\xA7\xE5\x9E\x05\x17\x94\xCA\xB2\x5F\xA0\x49\x18\x8D\x34\xE9\x26\x6C\x48\x1E\xAA\x68\x92\x05\xE1\x82\x73\x5A\x9B\xDC\x07\x5B\x08\x6D\x7D\x9D\xD7\x8D\x21\xD9\xFC\x14\x20\xAA\xC2\x45\xDF\x3F\xE7\x00\xB2\x51\xE4\xC2\xF8\x05\xB9\x79\x1A\x8C\x34\xF3\x9E\x5B\xE4\x37\x5B\x6B\x4A\xDF\x2C\x57\x8A\x40\x5A\x36\xBA\xDD\x75\x44\x08\x37\x42\x70\x0C\xFE\xDC\x5E\x21\xA0\xA3\x8A\xC0\x90\x9C\x68\xDA\x50\xE6\x45\x10\x47\x78\xB6\x4E\xD2\x65\xC9\xC3\x37\xDF\xE1\x42\x63\xB0\x57\x37\x45\x2D\x7B\x8A\x9C\xBF\x05\xEA\x65\x55\x33\xF7\x39\x10\xC5\x28\x2A\x21\x7A\x1B\x8A\xC4\x24\xF9\x3F\x15\xC8\x9A\x15\x20\xF5\x55\x62\x96\xED\x6D\x93\x50\xBC\xE4\xAA\x78\xAD\xD9\xCB\x0A\x65\x87\xA6\x66\xC1\xC4\x81\xA3\x77\x3A\x58\x1E\x0B\xEE\x83\x8B\x9D\x1E\xD2\x52\xA4\xCC\x1D\x6F\xB0\x98\x6D\x94\x31\xB5\xF8\x71\x0A\xDC\xB9\xFC\x7D\x32\x60\xE6\xEB\xAF\x8A\x01", + ["CN=CA Disig,O=Disig a.s.,L=Bratislava,C=SK"] = "\x30\x82\x04\x0F\x30\x82\x02\xF7\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x4A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x4B\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x42\x72\x61\x74\x69\x73\x6C\x61\x76\x61\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x44\x69\x73\x69\x67\x20\x61\x2E\x73\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x03\x13\x08\x43\x41\x20\x44\x69\x73\x69\x67\x30\x1E\x17\x0D\x30\x36\x30\x33\x32\x32\x30\x31\x33\x39\x33\x34\x5A\x17\x0D\x31\x36\x30\x33\x32\x32\x30\x31\x33\x39\x33\x34\x5A\x30\x4A\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x53\x4B\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x42\x72\x61\x74\x69\x73\x6C\x61\x76\x61\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x44\x69\x73\x69\x67\x20\x61\x2E\x73\x2E\x31\x11\x30\x0F\x06\x03\x55\x04\x03\x13\x08\x43\x41\x20\x44\x69\x73\x69\x67\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\x92\xF6\x31\xC1\x7D\x88\xFD\x99\x01\xA9\xD8\x7B\xF2\x71\x75\xF1\x31\xC6\xF3\x75\x66\xFA\x51\x28\x46\x84\x97\x78\x34\xBC\x6C\xFC\xBC\x45\x59\x88\x26\x18\x4A\xC4\x37\x1F\xA1\x4A\x44\xBD\xE3\x71\x04\xF5\x44\x17\xE2\x3F\xFC\x48\x58\x6F\x5C\x9E\x7A\x09\xBA\x51\x37\x22\x23\x66\x43\x21\xB0\x3C\x64\xA2\xF8\x6A\x15\x0E\x3F\xEB\x51\xE1\x54\xA9\xDD\x06\x99\xD7\x9A\x3C\x54\x8B\x39\x03\x3F\x0F\xC5\xCE\xC6\xEB\x83\x72\x02\xA8\x1F\x71\xF3\x2D\xF8\x75\x08\xDB\x62\x4C\xE8\xFA\xCE\xF9\xE7\x6A\x1F\xB6\x6B\x35\x82\xBA\xE2\x8F\x16\x92\x7D\x05\x0C\x6C\x46\x03\x5D\xC0\xED\x69\xBF\x3A\xC1\x8A\xA0\xE8\x8E\xD9\xB9\x45\x28\x87\x08\xEC\xB4\xCA\x15\xBE\x82\xDD\xB5\x44\x8B\x2D\xAD\x86\x0C\x68\x62\x6D\x85\x56\xF2\xAC\x14\x63\x3A\xC6\xD1\x99\xAC\x34\x78\x56\x4B\xCF\xB6\xAD\x3F\x8C\x8A\xD7\x04\xE5\xE3\x78\x4C\xF5\x86\xAA\xF5\x8F\xFA\x3D\x6C\x71\xA3\x2D\xCA\x67\xEB\x68\x7B\x6E\x33\xA9\x0C\x82\x28\xA8\x4C\x6A\x21\x40\x15\x20\x0C\x26\x5B\x83\xC2\xA9\x16\x15\xC0\x24\x82\x5D\x2B\x16\xAD\xCA\x63\xF6\x74\x00\xB0\xDF\x43\xC4\x10\x60\x56\x67\x63\x45\x02\x03\x01\x00\x01\xA3\x81\xFF\x30\x81\xFC\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x8D\xB2\x49\x68\x9D\x72\x08\x25\xB9\xC0\x27\xF5\x50\x93\x56\x48\x46\x71\xF9\x8F\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x36\x06\x03\x55\x1D\x11\x04\x2F\x30\x2D\x81\x13\x63\x61\x6F\x70\x65\x72\x61\x74\x6F\x72\x40\x64\x69\x73\x69\x67\x2E\x73\x6B\x86\x16\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x64\x69\x73\x69\x67\x2E\x73\x6B\x2F\x63\x61\x30\x66\x06\x03\x55\x1D\x1F\x04\x5F\x30\x5D\x30\x2D\xA0\x2B\xA0\x29\x86\x27\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x64\x69\x73\x69\x67\x2E\x73\x6B\x2F\x63\x61\x2F\x63\x72\x6C\x2F\x63\x61\x5F\x64\x69\x73\x69\x67\x2E\x63\x72\x6C\x30\x2C\xA0\x2A\xA0\x28\x86\x26\x68\x74\x74\x70\x3A\x2F\x2F\x63\x61\x2E\x64\x69\x73\x69\x67\x2E\x73\x6B\x2F\x63\x61\x2F\x63\x72\x6C\x2F\x63\x61\x5F\x64\x69\x73\x69\x67\x2E\x63\x72\x6C\x30\x1A\x06\x03\x55\x1D\x20\x04\x13\x30\x11\x30\x0F\x06\x0D\x2B\x81\x1E\x91\x93\xE6\x0A\x00\x00\x00\x01\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x5D\x34\x74\x61\x4C\xAF\x3B\xD8\xFF\x9F\x6D\x58\x36\x1C\x3D\x0B\x81\x0D\x12\x2B\x46\x10\x80\xFD\xE7\x3C\x27\xD0\x7A\xC8\xA9\xB6\x7E\x74\x30\x33\xA3\x3A\x8A\x7B\x74\xC0\x79\x79\x42\x93\x6D\xFF\xB1\x29\x14\x82\xAB\x21\x8C\x2F\x17\xF9\x3F\x26\x2F\xF5\x59\xC6\xEF\x80\x06\xB7\x9A\x49\x29\xEC\xCE\x7E\x71\x3C\x6A\x10\x41\xC0\xF6\xD3\x9A\xB2\x7C\x5A\x91\x9C\xC0\xAC\x5B\xC8\x4D\x5E\xF7\xE1\x53\xFF\x43\x77\xFC\x9E\x4B\x67\x6C\xD7\xF3\x83\xD1\xA0\xE0\x7F\x25\xDF\xB8\x98\x0B\x9A\x32\x38\x6C\x30\xA0\xF3\xFF\x08\x15\x33\xF7\x50\x4A\x7B\x3E\xA3\x3E\x20\xA9\xDC\x2F\x56\x80\x0A\xED\x41\x50\xB0\xC9\xF4\xEC\xB2\xE3\x26\x44\x00\x0E\x6F\x9E\x06\xBC\x22\x96\x53\x70\x65\xC4\x50\x0A\x46\x6B\xA4\x2F\x27\x81\x12\x27\x13\x5F\x10\xA1\x76\xCE\x8A\x7B\x37\xEA\xC3\x39\x61\x03\x95\x98\x3A\xE7\x6C\x88\x25\x08\xFC\x79\x68\x0D\x87\x7D\x62\xF8\xB4\x5F\xFB\xC5\xD8\x4C\xBD\x58\xBC\x3F\x43\x5B\xD4\x1E\x01\x4D\x3C\x63\xBE\x23\xEF\x8C\xCD\x5A\x50\xB8\x68\x54\xF9\x0A\x99\x33\x11\x00\xE1\x9E\xC2\x46\x77\x82\xF5\x59\x06\x8C\x21\x4C\x87\x09\xCD\xE5\xA8", + ["CN=Juur-SK,O=AS Sertifitseerimiskeskus,C=EE,emailAddress=pki@sk.ee"] = "\x30\x82\x04\xE6\x30\x82\x03\xCE\xA0\x03\x02\x01\x02\x02\x04\x3B\x8E\x4B\xFC\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x5D\x31\x18\x30\x16\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x09\x70\x6B\x69\x40\x73\x6B\x2E\x65\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x45\x31\x22\x30\x20\x06\x03\x55\x04\x0A\x13\x19\x41\x53\x20\x53\x65\x72\x74\x69\x66\x69\x74\x73\x65\x65\x72\x69\x6D\x69\x73\x6B\x65\x73\x6B\x75\x73\x31\x10\x30\x0E\x06\x03\x55\x04\x03\x13\x07\x4A\x75\x75\x72\x2D\x53\x4B\x30\x1E\x17\x0D\x30\x31\x30\x38\x33\x30\x31\x34\x32\x33\x30\x31\x5A\x17\x0D\x31\x36\x30\x38\x32\x36\x31\x34\x32\x33\x30\x31\x5A\x30\x5D\x31\x18\x30\x16\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x09\x70\x6B\x69\x40\x73\x6B\x2E\x65\x65\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x45\x31\x22\x30\x20\x06\x03\x55\x04\x0A\x13\x19\x41\x53\x20\x53\x65\x72\x74\x69\x66\x69\x74\x73\x65\x65\x72\x69\x6D\x69\x73\x6B\x65\x73\x6B\x75\x73\x31\x10\x30\x0E\x06\x03\x55\x04\x03\x13\x07\x4A\x75\x75\x72\x2D\x53\x4B\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\x81\x71\x36\x3E\x33\x07\xD6\xE3\x30\x8D\x13\x7E\x77\x32\x46\xCB\xCF\x19\xB2\x60\x31\x46\x97\x86\xF4\x98\x46\xA4\xC2\x65\x45\xCF\xD3\x40\x7C\xE3\x5A\x22\xA8\x10\x78\x33\xCC\x88\xB1\xD3\x81\x4A\xF6\x62\x17\x7B\x5F\x4D\x0A\x2E\xD0\xCF\x8B\x23\xEE\x4F\x02\x4E\xBB\xEB\x0E\xCA\xBD\x18\x63\xE8\x80\x1C\x8D\xE1\x1C\x8D\x3D\xE0\xFF\x5B\x5F\xEA\x64\xE5\x97\xE8\x3F\x99\x7F\x0C\x0A\x09\x33\x00\x1A\x53\xA7\x21\xE1\x38\x4B\xD6\x83\x1B\xAD\xAF\x64\xC2\xF9\x1C\x7A\x8C\x66\x48\x4D\x66\x1F\x18\x0A\xE2\x3E\xBB\x1F\x07\x65\x93\x85\xB9\x1A\xB0\xB9\xC4\xFB\x0D\x11\xF6\xF5\xD6\xF9\x1B\xC7\x2C\x2B\xB7\x18\x51\xFE\xE0\x7B\xF6\xA8\x48\xAF\x6C\x3B\x4F\x2F\xEF\xF8\xD1\x47\x1E\x26\x57\xF0\x51\x1D\x33\x96\xFF\xEF\x59\x3D\xDA\x4D\xD1\x15\x34\xC7\xEA\x3F\x16\x48\x7B\x91\x1C\x80\x43\x0F\x3D\xB8\x05\x3E\xD1\xB3\x95\xCD\xD8\xCA\x0F\xC2\x43\x67\xDB\xB7\x93\xE0\x22\x82\x2E\xBE\xF5\x68\x28\x83\xB9\xC1\x3B\x69\x7B\x20\xDA\x4E\x9C\x6D\xE1\xBA\xCD\x8F\x7A\x6C\xB0\x09\x22\xD7\x8B\x0B\xDB\x1C\xD5\x5A\x26\x5B\x0D\xC0\xEA\xE5\x60\xD0\x9F\xFE\x35\xDF\x3F\x02\x03\x01\x00\x01\xA3\x82\x01\xAC\x30\x82\x01\xA8\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x82\x01\x16\x06\x03\x55\x1D\x20\x04\x82\x01\x0D\x30\x82\x01\x09\x30\x82\x01\x05\x06\x0A\x2B\x06\x01\x04\x01\xCE\x1F\x01\x01\x01\x30\x81\xF6\x30\x81\xD0\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x81\xC3\x1E\x81\xC0\x00\x53\x00\x65\x00\x65\x00\x20\x00\x73\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x6B\x00\x61\x00\x61\x00\x74\x00\x20\x00\x6F\x00\x6E\x00\x20\x00\x76\x00\xE4\x00\x6C\x00\x6A\x00\x61\x00\x73\x00\x74\x00\x61\x00\x74\x00\x75\x00\x64\x00\x20\x00\x41\x00\x53\x00\x2D\x00\x69\x00\x73\x00\x20\x00\x53\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x74\x00\x73\x00\x65\x00\x65\x00\x72\x00\x69\x00\x6D\x00\x69\x00\x73\x00\x6B\x00\x65\x00\x73\x00\x6B\x00\x75\x00\x73\x00\x20\x00\x61\x00\x6C\x00\x61\x00\x6D\x00\x2D\x00\x53\x00\x4B\x00\x20\x00\x73\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x6B\x00\x61\x00\x61\x00\x74\x00\x69\x00\x64\x00\x65\x00\x20\x00\x6B\x00\x69\x00\x6E\x00\x6E\x00\x69\x00\x74\x00\x61\x00\x6D\x00\x69\x00\x73\x00\x65\x00\x6B\x00\x73\x30\x21\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x15\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x73\x6B\x2E\x65\x65\x2F\x63\x70\x73\x2F\x30\x2B\x06\x03\x55\x1D\x1F\x04\x24\x30\x22\x30\x20\xA0\x1E\xA0\x1C\x86\x1A\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x73\x6B\x2E\x65\x65\x2F\x6A\x75\x75\x72\x2F\x63\x72\x6C\x2F\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x04\xAA\x7A\x47\xA3\xE4\x89\xAF\x1A\xCF\x0A\x40\xA7\x18\x3F\x6F\xEF\xE9\x7D\xBE\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x04\xAA\x7A\x47\xA3\xE4\x89\xAF\x1A\xCF\x0A\x40\xA7\x18\x3F\x6F\xEF\xE9\x7D\xBE\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\xE6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7B\xC1\x18\x94\x53\xA2\x09\xF3\xFE\x26\x67\x9A\x50\xE4\xC3\x05\x2F\x2B\x35\x78\x91\x4C\x7C\xA8\x11\x11\x79\x4C\x49\x59\xAC\xC8\xF7\x85\x65\x5C\x46\xBB\x3B\x10\xA0\x02\xAF\xCD\x4F\xB5\xCC\x36\x2A\xEC\x5D\xFE\xEF\xA0\x91\xC9\xB6\x93\x6F\x7C\x80\x54\xEC\xC7\x08\x70\x0D\x8E\xFB\x82\xEC\x2A\x60\x78\x69\x36\x36\xD1\xC5\x9C\x8B\x69\xB5\x40\xC8\x94\x65\x77\xF2\x57\x21\x66\x3B\xCE\x85\x40\xB6\x33\x63\x1A\xBF\x79\x1E\xFC\x5C\x1D\xD3\x1D\x93\x1B\x8B\x0C\x5D\x85\xBD\x99\x30\x32\x18\x09\x91\x52\xE9\x7C\xA1\xBA\xFF\x64\x92\x9A\xEC\xFE\x35\xEE\x8C\x2F\xAE\xFC\x20\x86\xEC\x4A\xDE\x1B\x78\x32\x37\xA6\x81\xD2\x9D\xAF\x5A\x12\x16\xCA\x99\x5B\xFC\x6F\x6D\x0E\xC5\xA0\x1E\x86\xC9\x91\xD0\x5C\x98\x82\x5F\x63\x0C\x8A\x5A\xAB\xD8\x95\xA6\xCC\xCB\x8A\xD6\xBF\x64\x4B\x8E\xCA\x8A\xB2\xB0\xE9\x21\x32\x9E\xAA\xA8\x85\x98\x34\x81\x39\x21\x3B\xA8\x3A\x52\x32\x3D\xF6\x6B\x37\x86\x06\x5A\x15\x98\xDC\xF0\x11\x66\xFE\x34\x20\xB7\x03\xF4\x41\x10\x7D\x39\x84\x79\x96\x72\x63\xB6\x96\x02\xE5\x6B\xB9\xAD\x19\x4D\xBB\xC6\x44\xDB\x36\xCB\x2A\x9C\x8E", + ["CN=Hongkong Post Root CA 1,O=Hongkong Post,C=HK"] = "\x30\x82\x03\x30\x30\x82\x02\x18\xA0\x03\x02\x01\x02\x02\x02\x03\xE8\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x47\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x4B\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x48\x6F\x6E\x67\x6B\x6F\x6E\x67\x20\x50\x6F\x73\x74\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x48\x6F\x6E\x67\x6B\x6F\x6E\x67\x20\x50\x6F\x73\x74\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x31\x30\x1E\x17\x0D\x30\x33\x30\x35\x31\x35\x30\x35\x31\x33\x31\x34\x5A\x17\x0D\x32\x33\x30\x35\x31\x35\x30\x34\x35\x32\x32\x39\x5A\x30\x47\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x4B\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x13\x0D\x48\x6F\x6E\x67\x6B\x6F\x6E\x67\x20\x50\x6F\x73\x74\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x13\x17\x48\x6F\x6E\x67\x6B\x6F\x6E\x67\x20\x50\x6F\x73\x74\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x31\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\xFF\x38\xB6\xE9\x66\x02\x49\xE3\xA2\xB4\xE1\x90\xF9\x40\x8F\x79\xF9\xE2\xBD\x79\xFE\x02\xBD\xEE\x24\x92\x1D\x22\xF6\xDA\x85\x72\x69\xFE\xD7\x3F\x09\xD4\xDD\x91\xB5\x02\x9C\xD0\x8D\x5A\xE1\x55\xC3\x50\x86\xB9\x29\x26\xC2\xE3\xD9\xA0\xF1\x69\x03\x28\x20\x80\x45\x22\x2D\x56\xA7\x3B\x54\x95\x56\x22\x59\x1F\x28\xDF\x1F\x20\x3D\x6D\xA2\x36\xBE\x23\xA0\xB1\x6E\xB5\xB1\x27\x3F\x39\x53\x09\xEA\xAB\x6A\xE8\x74\xB2\xC2\x65\x5C\x8E\xBF\x7C\xC3\x78\x84\xCD\x9E\x16\xFC\xF5\x2E\x4F\x20\x2A\x08\x9F\x77\xF3\xC5\x1E\xC4\x9A\x52\x66\x1E\x48\x5E\xE3\x10\x06\x8F\x22\x98\xE1\x65\x8E\x1B\x5D\x23\x66\x3B\xB8\xA5\x32\x51\xC8\x86\xAA\xA1\xA9\x9E\x7F\x76\x94\xC2\xA6\x6C\xB7\x41\xF0\xD5\xC8\x06\x38\xE6\xD4\x0C\xE2\xF3\x3B\x4C\x6D\x50\x8C\xC4\x83\x27\xC1\x13\x84\x59\x3D\x9E\x75\x74\xB6\xD8\x02\x5E\x3A\x90\x7A\xC0\x42\x36\x72\xEC\x6A\x4D\xDC\xEF\xC4\x00\xDF\x13\x18\x57\x5F\x26\x78\xC8\xD6\x0A\x79\x77\xBF\xF7\xAF\xB7\x76\xB9\xA5\x0B\x84\x17\x5D\x10\xEA\x6F\xE1\xAB\x95\x11\x5F\x6D\x3C\xA3\x5C\x4D\x83\x5B\xF2\xB3\x19\x8A\x80\x8B\x0B\x87\x02\x03\x01\x00\x01\xA3\x26\x30\x24\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x03\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\xC6\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x0E\x46\xD5\x3C\xAE\xE2\x87\xD9\x5E\x81\x8B\x02\x98\x41\x08\x8C\x4C\xBC\xDA\xDB\xEE\x27\x1B\x82\xE7\x6A\x45\xEC\x16\x8B\x4F\x85\xA0\xF3\xB2\x70\xBD\x5A\x96\xBA\xCA\x6E\x6D\xEE\x46\x8B\x6E\xE7\x2A\x2E\x96\xB3\x19\x33\xEB\xB4\x9F\xA8\xB2\x37\xEE\x98\xA8\x97\xB6\x2E\xB6\x67\x27\xD4\xA6\x49\xFD\x1C\x93\x65\x76\x9E\x42\x2F\xDC\x22\x6C\x9A\x4F\xF2\x5A\x15\x39\xB1\x71\xD7\x2B\x51\xE8\x6D\x1C\x98\xC0\xD9\x2A\xF4\xA1\x82\x7B\xD5\xC9\x41\xA2\x23\x01\x74\x38\x55\x8B\x0F\xB9\x2E\x67\xA2\x20\x04\x37\xDA\x9C\x0B\xD3\x17\x21\xE0\x8F\x97\x79\x34\x6F\x84\x48\x02\x20\x33\x1B\xE6\x34\x44\x9F\x91\x70\xF4\x80\x5E\x84\x43\xC2\x29\xD2\x6C\x12\x14\xE4\x61\x8D\xAC\x10\x90\x9E\x84\x50\xBB\xF0\x96\x6F\x45\x9F\x8A\xF3\xCA\x6C\x4F\xFA\x11\x3A\x15\x15\x46\xC3\xCD\x1F\x83\x5B\x2D\x41\x12\xED\x50\x67\x41\x13\x3D\x21\xAB\x94\x8A\xAA\x4E\x7C\xC1\xB1\xFB\xA7\xD6\xB5\x27\x2F\x97\xAB\x6E\xE0\x1D\xE2\xD1\x1C\x2C\x1F\x44\xE2\xFC\xBE\x91\xA1\x9C\xFB\xD6\x29\x53\x73\x86\x9F\x53\xD8\x43\x0E\x5D\xD6\x63\x82\x71\x1D\x80\x74\xCA\xF6\xE2\x02\x6B\xD9\x5A", + ["CN=SecureSign RootCA11,O=Japan Certification Services\, Inc.,C=JP"] = "\x30\x82\x03\x6D\x30\x82\x02\x55\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x58\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x2B\x30\x29\x06\x03\x55\x04\x0A\x13\x22\x4A\x61\x70\x61\x6E\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x1C\x30\x1A\x06\x03\x55\x04\x03\x13\x13\x53\x65\x63\x75\x72\x65\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x43\x41\x31\x31\x30\x1E\x17\x0D\x30\x39\x30\x34\x30\x38\x30\x34\x35\x36\x34\x37\x5A\x17\x0D\x32\x39\x30\x34\x30\x38\x30\x34\x35\x36\x34\x37\x5A\x30\x58\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x4A\x50\x31\x2B\x30\x29\x06\x03\x55\x04\x0A\x13\x22\x4A\x61\x70\x61\x6E\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x53\x65\x72\x76\x69\x63\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x1C\x30\x1A\x06\x03\x55\x04\x03\x13\x13\x53\x65\x63\x75\x72\x65\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x43\x41\x31\x31\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\xFD\x77\xAA\xA5\x1C\x90\x05\x3B\xCB\x4C\x9B\x33\x8B\x5A\x14\x45\xA4\xE7\x90\x16\xD1\xDF\x57\xD2\x21\x10\xA4\x17\xFD\xDF\xAC\xD6\x1F\xA7\xE4\xDB\x7C\xF7\xEC\xDF\xB8\x03\xDA\x94\x58\xFD\x5D\x72\x7C\x8C\x3F\x5F\x01\x67\x74\x15\x96\xE3\x02\x3C\x87\xDB\xAE\xCB\x01\x8E\xC2\xF3\x66\xC6\x85\x45\xF4\x02\xC6\x3A\xB5\x62\xB2\xAF\xFA\x9C\xBF\xA4\xE6\xD4\x80\x30\x98\xF3\x0D\xB6\x93\x8F\xA9\xD4\xD8\x36\xF2\xB0\xFC\x8A\xCA\x2C\xA1\x15\x33\x95\x31\xDA\xC0\x1B\xF2\xEE\x62\x99\x86\x63\x3F\xBF\xDD\x93\x2A\x83\xA8\x76\xB9\x13\x1F\xB7\xCE\x4E\x42\x85\x8F\x22\xE7\x2E\x1A\xF2\x95\x09\xB2\x05\xB5\x44\x4E\x77\xA1\x20\xBD\xA9\xF2\x4E\x0A\x7D\x50\xAD\xF5\x05\x0D\x45\x4F\x46\x71\xFD\x28\x3E\x53\xFB\x04\xD8\x2D\xD7\x65\x1D\x4A\x1B\xFA\xCF\x3B\xB0\x31\x9A\x35\x6E\xC8\x8B\x06\xD3\x00\x91\xF2\x94\x08\x65\x4C\xB1\x34\x06\x00\x7A\x89\xE2\xF0\xC7\x03\x59\xCF\xD5\xD6\xE8\xA7\x32\xB3\xE6\x98\x40\x86\xC5\xCD\x27\x12\x8B\xCC\x7B\xCE\xB7\x11\x3C\x62\x60\x07\x23\x3E\x2B\x40\x6E\x94\x80\x09\x6D\xB6\xB3\x6F\x77\x6F\x35\x08\x50\xFB\x02\x87\xC5\x3E\x89\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x5B\xF8\x4D\x4F\xB2\xA5\x86\xD4\x3A\xD2\xF1\x63\x9A\xA0\xBE\x09\xF6\x57\xB7\xDE\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA0\xA1\x38\x16\x66\x2E\xA7\x56\x1F\x21\x9C\x06\xFA\x1D\xED\xB9\x22\xC5\x38\x26\xD8\x4E\x4F\xEC\xA3\x7F\x79\xDE\x46\x21\xA1\x87\x77\x8F\x07\x08\x9A\xB2\xA4\xC5\xAF\x0F\x32\x98\x0B\x7C\x66\x29\xB6\x9B\x7D\x25\x52\x49\x43\xAB\x4C\x2E\x2B\x6E\x7A\x70\xAF\x16\x0E\xE3\x02\x6C\xFB\x42\xE6\x18\x9D\x45\xD8\x55\xC8\xE8\x3B\xDD\xE7\xE1\xF4\x2E\x0B\x1C\x34\x5C\x6C\x58\x4A\xFB\x8C\x88\x50\x5F\x95\x1C\xBF\xED\xAB\x22\xB5\x65\xB3\x85\xBA\x9E\x0F\xB8\xAD\xE5\x7A\x1B\x8A\x50\x3A\x1D\xBD\x0D\xBC\x7B\x54\x50\x0B\xB9\x42\xAF\x55\xA0\x18\x81\xAD\x65\x99\xEF\xBE\xE4\x9C\xBF\xC4\x85\xAB\x41\xB2\x54\x6F\xDC\x25\xCD\xED\x78\xE2\x8E\x0C\x8D\x09\x49\xDD\x63\x7B\x5A\x69\x96\x02\x21\xA8\xBD\x52\x59\xE9\x7D\x35\xCB\xC8\x52\xCA\x7F\x81\xFE\xD9\x6B\xD3\xF7\x11\xED\x25\xDF\xF8\xE7\xF9\xA4\xFA\x72\x97\x84\x53\x0D\xA5\xD0\x32\x18\x51\x76\x59\x14\x6C\x0F\xEB\xEC\x5F\x80\x8C\x75\x43\x83\xC3\x85\x98\xFF\x4C\x9E\x2D\x0D\xE4\x77\x83\x93\x4E\xB5\x96\x07\x8B\x28\x13\x9B\x8C\x19\x8D\x41\x27\x49\x40\xEE\xDE\xE6\x23\x44\x39\xDC\xA1\x22\xD6\xBA\x03\xF2", + ["C=ES,O=EDICOM,OU=PKI,CN=ACEDICOM Root"] = "\x30\x82\x05\xB5\x30\x82\x03\x9D\xA0\x03\x02\x01\x02\x02\x08\x61\x8D\xC7\x86\x3B\x01\x82\x05\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x44\x31\x16\x30\x14\x06\x03\x55\x04\x03\x0C\x0D\x41\x43\x45\x44\x49\x43\x4F\x4D\x20\x52\x6F\x6F\x74\x31\x0C\x30\x0A\x06\x03\x55\x04\x0B\x0C\x03\x50\x4B\x49\x31\x0F\x30\x0D\x06\x03\x55\x04\x0A\x0C\x06\x45\x44\x49\x43\x4F\x4D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x30\x1E\x17\x0D\x30\x38\x30\x34\x31\x38\x31\x36\x32\x34\x32\x32\x5A\x17\x0D\x32\x38\x30\x34\x31\x33\x31\x36\x32\x34\x32\x32\x5A\x30\x44\x31\x16\x30\x14\x06\x03\x55\x04\x03\x0C\x0D\x41\x43\x45\x44\x49\x43\x4F\x4D\x20\x52\x6F\x6F\x74\x31\x0C\x30\x0A\x06\x03\x55\x04\x0B\x0C\x03\x50\x4B\x49\x31\x0F\x30\x0D\x06\x03\x55\x04\x0A\x0C\x06\x45\x44\x49\x43\x4F\x4D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xFF\x92\x95\xE1\x68\x06\x76\xB4\x2C\xC8\x58\x48\xCA\xFD\x80\x54\x29\x55\x63\x24\xFF\x90\x65\x9B\x10\x75\x7B\xC3\x6A\xDB\x62\x02\x01\xF2\x18\x86\xB5\x7C\x5A\x38\xB1\xE4\x58\xB9\xFB\xD3\xD8\x2D\x9F\xBD\x32\x37\xBF\x2C\x15\x6D\xBE\xB5\xF4\x21\xD2\x13\x91\xD9\x07\xAD\x01\x05\xD6\xF3\xBD\x77\xCE\x5F\x42\x81\x0A\xF9\x6A\xE3\x83\x00\xA8\x2B\x2E\x55\x13\x63\x81\xCA\x47\x1C\x7B\x5C\x16\x57\x7A\x1B\x83\x60\x04\x3A\x3E\x65\xC3\xCD\x01\xDE\xDE\xA4\xD6\x0C\xBA\x8E\xDE\xD9\x04\xEE\x17\x56\x22\x9B\x8F\x63\xFD\x4D\x16\x0B\xB7\x7B\x77\x8C\xF9\x25\xB5\xD1\x6D\x99\x12\x2E\x4F\x1A\xB8\xE6\xEA\x04\x92\xAE\x3D\x11\xB9\x51\x42\x3D\x87\xB0\x31\x85\xAF\x79\x5A\x9C\xFE\xE7\x4E\x5E\x92\x4F\x43\xFC\xAB\x3A\xAD\xA5\x12\x26\x66\xB9\xE2\x0C\xD7\x98\xCE\xD4\x58\xA5\x95\x40\x0A\xB7\x44\x9D\x13\x74\x2B\xC2\xA5\xEB\x22\x15\x98\x10\xD8\x8B\xC5\x04\x9F\x1D\x8F\x60\xE5\x06\x1B\x9B\xCF\xB9\x79\xA0\x3D\xA2\x23\x3F\x42\x3F\x6B\xFA\x1C\x03\x7B\x30\x8D\xCE\x6C\xC0\xBF\xE6\x1B\x5F\xBF\x67\xB8\x84\x19\xD5\x15\xEF\x7B\xCB\x90\x36\x31\x62\xC9\xBC\x02\xAB\x46\x5F\x9B\xFE\x1A\x68\x94\x34\x3D\x90\x8E\xAD\xF6\xE4\x1D\x09\x7F\x4A\x88\x38\x3F\xBE\x67\xFD\x34\x96\xF5\x1D\xBC\x30\x74\xCB\x38\xEE\xD5\x6C\xAB\xD4\xFC\xF4\x00\xB7\x00\x5B\x85\x32\x16\x76\x33\xE9\xD8\xA3\x99\x9D\x05\x00\xAA\x16\xE6\xF3\x81\x7D\x6F\x7D\xAA\x86\x6D\xAD\x15\x74\xD3\xC4\xA2\x71\xAA\xF4\x14\x7D\xE7\x32\xB8\x1F\xBC\xD5\xF1\x4E\xBD\x6F\x17\x02\x39\xD7\x0E\x95\x42\x3A\xC7\x00\x3E\xE9\x26\x63\x11\xEA\x0B\xD1\x4A\xFF\x18\x9D\xB2\xD7\x7B\x2F\x3A\xD9\x96\xFB\xE8\x1E\x92\xAE\x13\x55\xC8\xD9\x27\xF6\xDC\x48\x1B\xB0\x24\xC1\x85\xE3\x77\x9D\x9A\xA4\xF3\x0C\x11\x1D\x0D\xC8\xB4\x14\xEE\xB5\x82\x57\x09\xBF\x20\x58\x7F\x2F\x22\x23\xD8\x70\xCB\x79\x6C\xC9\x4B\xF2\xA9\x2A\xC8\xFC\x87\x2B\xD7\x1A\x50\xF8\x27\xE8\x2F\x43\xE3\x3A\xBD\xD8\x57\x71\xFD\xCE\xA6\x52\x5B\xF9\xDD\x4D\xED\xE5\xF6\x6F\x89\xED\xBB\x93\x9C\x76\x21\x75\xF0\x92\x4C\x29\xF7\x2F\x9C\x01\x2E\xFE\x50\x46\x9E\x64\x0C\x14\xB3\x07\x5B\xC5\xC2\x73\x6C\xF1\x07\x5C\x45\x24\x14\x35\xAE\x83\xF1\x6A\x4D\x89\x7A\xFA\xB3\xD8\x2D\x66\xF0\x36\x87\xF5\x2B\x53\x02\x03\x01\x00\x01\xA3\x81\xAA\x30\x81\xA7\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xA6\xB3\xE1\x2B\x2B\x49\xB6\xD7\x73\xA1\xAA\x94\xF5\x01\xE7\x73\x65\x4C\xAC\x50\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x86\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xA6\xB3\xE1\x2B\x2B\x49\xB6\xD7\x73\xA1\xAA\x94\xF5\x01\xE7\x73\x65\x4C\xAC\x50\x30\x44\x06\x03\x55\x1D\x20\x04\x3D\x30\x3B\x30\x39\x06\x04\x55\x1D\x20\x00\x30\x31\x30\x2F\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x61\x63\x65\x64\x69\x63\x6F\x6D\x2E\x65\x64\x69\x63\x6F\x6D\x67\x72\x6F\x75\x70\x2E\x63\x6F\x6D\x2F\x64\x6F\x63\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\xCE\x2C\x0B\x52\x51\x62\x26\x7D\x0C\x27\x83\x8F\xC5\xF6\xDA\xA0\x68\x7B\x4F\x92\x5E\xEA\xA4\x73\x32\x11\x53\x44\xB2\x44\xCB\x9D\xEC\x0F\x79\x42\xB3\x10\xA6\xC7\x0D\x9D\xCB\xB6\xFA\x3F\x3A\x7C\xEA\xBF\x88\x53\x1B\x3C\xF7\x82\xFA\x05\x35\x33\xE1\x35\xA8\x57\xC0\xE7\xFD\x8D\x4F\x3F\x93\x32\x4F\x78\x66\x03\x77\x07\x58\xE9\x95\xC8\x7E\x3E\xD0\x79\x00\x8C\xF2\x1B\x51\x33\x9B\xBC\x94\xE9\x3A\x7B\x6E\x52\x2D\x32\x9E\x23\xA4\x45\xFB\xB6\x2E\x13\xB0\x8B\x18\xB1\xDD\xCE\xD5\x1D\xA7\x42\x7F\x55\xBE\xFB\x5B\xBB\x47\xD4\xFC\x24\xCD\x04\xAE\x96\x05\x15\xD6\xAC\xCE\x30\xF3\xCA\x0B\xC5\xBA\xE2\x22\xE0\xA6\xAD\x22\xE4\x02\xEE\x74\x11\x7F\x4C\xFF\x78\x1D\x35\xDA\xE6\x02\x34\xEB\x18\x12\x61\x77\x06\x09\x16\x63\xEA\x18\xAD\xA2\x87\x1F\xF2\xC7\x80\x09\x09\x75\x4E\x10\xA8\x8F\x3D\x86\xB8\x75\x11\xC0\x24\x62\x8A\x96\x7B\x4A\x45\xE9\xEC\x59\xC5\xBE\x6B\x83\xE6\xE1\xE8\xAC\xB5\x30\x1E\xFE\x05\x07\x80\xF9\xE1\x23\x0D\x50\x8F\x05\x98\xFF\x2C\x5F\xE8\x3B\xB6\xAD\xCF\x81\xB5\x21\x87\xCA\x08\x2A\x23\x27\x30\x20\x2B\xCF\xED\x94\x5B\xAC\xB2\x7A\xD2\xC7\x28\xA1\x8A\x0B\x9B\x4D\x4A\x2C\x6D\x85\x3F\x09\x72\x3C\x67\xE2\xD9\xDC\x07\xBA\xEB\x65\x7B\x5A\x01\x63\xD6\x90\x5B\x4F\x17\x66\x3D\x7F\x0B\x19\xA3\x93\x63\x10\x52\x2A\x9F\x14\x16\x58\xE2\xDC\xA5\xF4\xA1\x16\x8B\x0E\x91\x8B\x81\xCA\x9B\x59\xFA\xD8\x6B\x91\x07\x65\x55\x5F\x52\x1F\xAF\x3A\xFB\x90\xDD\x69\xA5\x5B\x9C\x6D\x0E\x2C\xB6\xFA\xCE\xAC\xA5\x7C\x32\x4A\x67\x40\xDC\x30\x34\x23\xDD\xD7\x04\x23\x66\xF0\xFC\x55\x80\xA7\xFB\x66\x19\x82\x35\x67\x62\x70\x39\x5E\x6F\xC7\xEA\x90\x40\x44\x08\x1E\xB8\xB2\xD6\xDB\xEE\x59\xA7\x0D\x18\x79\x34\xBC\x54\x18\x5E\x53\xCA\x34\x51\xED\x45\x0A\xE6\x8E\xC7\x82\x36\x3E\xA7\x38\x63\xA9\x30\x2C\x17\x10\x60\x92\x9F\x55\x87\x12\x59\x10\xC2\x0F\x67\x69\x11\xCC\x4E\x1E\x7E\x4A\x9A\xAD\xAF\x40\xA8\x75\xAC\x56\x90\x74\xB8\xA0\x9C\xA5\x79\x6F\xDC\xE9\x1A\xC8\x69\x05\xE9\xBA\xFA\x03\xB3\x7C\xE4\xE0\x4E\xC2\xCE\x9D\xE8\xB6\x46\x0D\x6E\x7E\x57\x3A\x67\x94\xC2\xCB\x1F\x9C\x77\x4A\x67\x4E\x69\x86\x43\x93\x38\xFB\xB6\xDB\x4F\x83\x91\xD4\x60\x7E\x4B\x3E\x2B\x38\x07\x55\x98\x5E\xA4", + ["emailAddress=info@e-szigno.hu,CN=Microsec e-Szigno Root CA 2009,O=Microsec Ltd.,L=Budapest,C=HU"] = "\x30\x82\x04\x0A\x30\x82\x02\xF2\xA0\x03\x02\x01\x02\x02\x09\x00\xC2\x7E\x43\x04\x4E\x47\x3F\x19\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x0C\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x0C\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4C\x74\x64\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x03\x0C\x1E\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x30\x39\x31\x1F\x30\x1D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x10\x69\x6E\x66\x6F\x40\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x30\x1E\x17\x0D\x30\x39\x30\x36\x31\x36\x31\x31\x33\x30\x31\x38\x5A\x17\x0D\x32\x39\x31\x32\x33\x30\x31\x31\x33\x30\x31\x38\x5A\x30\x81\x82\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x48\x55\x31\x11\x30\x0F\x06\x03\x55\x04\x07\x0C\x08\x42\x75\x64\x61\x70\x65\x73\x74\x31\x16\x30\x14\x06\x03\x55\x04\x0A\x0C\x0D\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x4C\x74\x64\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x03\x0C\x1E\x4D\x69\x63\x72\x6F\x73\x65\x63\x20\x65\x2D\x53\x7A\x69\x67\x6E\x6F\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x32\x30\x30\x39\x31\x1F\x30\x1D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01\x16\x10\x69\x6E\x66\x6F\x40\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\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\xE9\xF8\x8F\xF3\x63\xAD\xDA\x86\xD8\xA7\xE0\x42\xFB\xCF\x91\xDE\xA6\x26\xF8\x99\xA5\x63\x70\xAD\x9B\xAE\xCA\x33\x40\x7D\x6D\x96\x6E\xA1\x0E\x44\xEE\xE1\x13\x9D\x94\x42\x52\x9A\xBD\x75\x85\x74\x2C\xA8\x0E\x1D\x93\xB6\x18\xB7\x8C\x2C\xA8\xCF\xFB\x5C\x71\xB9\xDA\xEC\xFE\xE8\x7E\x8F\xE4\x2F\x1D\xB2\xA8\x75\x87\xD8\xB7\xA1\xE5\x3B\xCF\x99\x4A\x46\xD0\x83\x19\x7D\xC0\xA1\x12\x1C\x95\x6D\x4A\xF4\xD8\xC7\xA5\x4D\x33\x2E\x85\x39\x40\x75\x7E\x14\x7C\x80\x12\x98\x50\xC7\x41\x67\xB8\xA0\x80\x61\x54\xA6\x6C\x4E\x1F\xE0\x9D\x0E\x07\xE9\xC9\xBA\x33\xE7\xFE\xC0\x55\x28\x2C\x02\x80\xA7\x19\xF5\x9E\xDC\x55\x53\x03\x97\x7B\x07\x48\xFF\x99\xFB\x37\x8A\x24\xC4\x59\xCC\x50\x10\x63\x8E\xAA\xA9\x1A\xB0\x84\x1A\x86\xF9\x5F\xBB\xB1\x50\x6E\xA4\xD1\x0A\xCC\xD5\x71\x7E\x1F\xA7\x1B\x7C\xF5\x53\x6E\x22\x5F\xCB\x2B\xE6\xD4\x7C\x5D\xAE\xD6\xC2\xC6\x4C\xE5\x05\x01\xD9\xED\x57\xFC\xC1\x23\x79\xFC\xFA\xC8\x24\x83\x95\xF3\xB5\x6A\x51\x01\xD0\x77\xD6\xE9\x12\xA1\xF9\x1A\x83\xFB\x82\x1B\xB9\xB0\x97\xF4\x76\x06\x33\x43\x49\xA0\xFF\x0B\xB5\xFA\xB5\x02\x03\x01\x00\x01\xA3\x81\x80\x30\x7E\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xCB\x0F\xC6\xDF\x42\x43\xCC\x3D\xCB\xB5\x48\x23\xA1\x1A\x7A\xA6\x2A\xBB\x34\x68\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\xCB\x0F\xC6\xDF\x42\x43\xCC\x3D\xCB\xB5\x48\x23\xA1\x1A\x7A\xA6\x2A\xBB\x34\x68\x30\x1B\x06\x03\x55\x1D\x11\x04\x14\x30\x12\x81\x10\x69\x6E\x66\x6F\x40\x65\x2D\x73\x7A\x69\x67\x6E\x6F\x2E\x68\x75\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\xC9\xD1\x0E\x5E\x2E\xD5\xCC\xB3\x7C\x3E\xCB\xFC\x3D\xFF\x0D\x28\x95\x93\x04\xC8\xBF\xDA\xCD\x79\xB8\x43\x90\xF0\xA4\xBE\xEF\xF2\xEF\x21\x98\xBC\xD4\xD4\x5D\x06\xF6\xEE\x42\xEC\x30\x6C\xA0\xAA\xA9\xCA\xF1\xAF\x8A\xFA\x3F\x0B\x73\x6A\x3E\xEA\x2E\x40\x7E\x1F\xAE\x54\x61\x79\xEB\x2E\x08\x37\xD7\x23\xF3\x8C\x9F\xBE\x1D\xB1\xE1\xA4\x75\xDB\xA0\xE2\x54\x14\xB1\xBA\x1C\x29\xA4\x18\xF6\x12\xBA\xA2\x14\x14\xE3\x31\x35\xC8\x40\xFF\xB7\xE0\x05\x76\x57\xC1\x1C\x59\xF2\xF8\xBF\xE4\xED\x25\x62\x5C\x84\xF0\x7E\x7E\x1F\xB3\xBE\xF9\xB7\x21\x11\xCC\x03\x01\x56\x70\xA7\x10\x92\x1E\x1B\x34\x81\x1E\xAD\x9C\x1A\xC3\x04\x3C\xED\x02\x61\xD6\x1E\x06\xF3\x5F\x3A\x87\xF2\x2B\xF1\x45\x87\xE5\x3D\xAC\xD1\xC7\x57\x84\xBD\x6B\xAE\xDC\xD8\xF9\xB6\x1B\x62\x70\x0B\x3D\x36\xC9\x42\xF2\x32\xD7\x7A\x61\xE6\xD2\xDB\x3D\xCF\xC8\xA9\xC9\x9B\xDC\xDB\x58\x44\xD7\x6F\x38\xAF\x7F\x78\xD3\xA3\xAD\x1A\x75\xBA\x1C\xC1\x36\x7C\x8F\x1E\x6D\x1C\xC3\x75\x46\xAE\x35\x05\xA6\xF6\x5C\x3D\x21\xEE\x56\xF0\xC9\x82\x22\x2D\x7A\x54\xAB\x70\xC3\x7D\x22\x65\x82\x70\x96", + ["CN=e-Guven Kok Elektronik Sertifika Hizmet Saglayicisi,O=Elektronik Bilgi Guvenligi A.S.,C=TR"] = "\x30\x82\x03\xB6\x30\x82\x02\x9E\xA0\x03\x02\x01\x02\x02\x10\x44\x99\x8D\x3C\xC0\x03\x27\xBD\x9C\x76\x95\xB9\xEA\xDB\xAC\xB5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x28\x30\x26\x06\x03\x55\x04\x0A\x13\x1F\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x42\x69\x6C\x67\x69\x20\x47\x75\x76\x65\x6E\x6C\x69\x67\x69\x20\x41\x2E\x53\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x03\x13\x33\x65\x2D\x47\x75\x76\x65\x6E\x20\x4B\x6F\x6B\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\x67\x6C\x61\x79\x69\x63\x69\x73\x69\x30\x1E\x17\x0D\x30\x37\x30\x31\x30\x34\x31\x31\x33\x32\x34\x38\x5A\x17\x0D\x31\x37\x30\x31\x30\x34\x31\x31\x33\x32\x34\x38\x5A\x30\x75\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x52\x31\x28\x30\x26\x06\x03\x55\x04\x0A\x13\x1F\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x42\x69\x6C\x67\x69\x20\x47\x75\x76\x65\x6E\x6C\x69\x67\x69\x20\x41\x2E\x53\x2E\x31\x3C\x30\x3A\x06\x03\x55\x04\x03\x13\x33\x65\x2D\x47\x75\x76\x65\x6E\x20\x4B\x6F\x6B\x20\x45\x6C\x65\x6B\x74\x72\x6F\x6E\x69\x6B\x20\x53\x65\x72\x74\x69\x66\x69\x6B\x61\x20\x48\x69\x7A\x6D\x65\x74\x20\x53\x61\x67\x6C\x61\x79\x69\x63\x69\x73\x69\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\xC3\x12\x20\x9E\xB0\x5E\x00\x65\x8D\x4E\x46\xBB\x80\x5C\xE9\x2C\x06\x97\xD5\xF3\x72\xC9\x70\xB9\xE7\x4B\x65\x80\xC1\x4B\xBE\x7E\x3C\xD7\x54\x31\x94\xDE\xD5\x12\xBA\x53\x16\x02\xEA\x58\x63\xEF\x5B\xD8\xF3\xED\x2A\x1A\xAA\x71\x48\xA3\xDC\x10\x2D\x5F\x5F\xEB\x5C\x4B\x9C\x96\x08\x42\x25\x28\x11\xCC\x8A\x5A\x62\x01\x50\xD5\xEB\x09\x53\x2F\xF8\xC3\x8F\xFE\xB3\xFC\xFD\x9D\xA2\xE3\x5F\x7D\xBE\xED\x0B\xE0\x60\xEB\x69\xEC\x33\xED\xD8\x8D\xFB\x12\x49\x83\x00\xC9\x8B\x97\x8C\x3B\x73\x2A\x32\xB3\x12\xF7\xB9\x4D\xF2\xF4\x4D\x6D\xC7\xE6\xD6\x26\x37\x08\xF2\xD9\xFD\x6B\x5C\xA3\xE5\x48\x5C\x58\xBC\x42\xBE\x03\x5A\x81\xBA\x1C\x35\x0C\x00\xD3\xF5\x23\x7E\x71\x30\x08\x26\x38\xDC\x25\x11\x47\x2D\xF3\xBA\x23\x10\xA5\xBF\xBC\x02\xF7\x43\x5E\xC7\xFE\xB0\x37\x50\x99\x7B\x0F\x93\xCE\xE6\x43\x2C\xC3\x7E\x0D\xF2\x1C\x43\x66\x60\xCB\x61\x31\x47\x87\xA3\x4F\xAE\xBD\x56\x6C\x4C\xBC\xBC\xF8\x05\xCA\x64\xF4\xE9\x34\xA1\x2C\xB5\x73\xE1\xC2\x3E\xE8\xC8\xC9\x34\x25\x08\x5C\xF3\xED\xA6\xC7\x94\x9F\xAD\x88\x43\x25\xD7\xE1\x39\x60\xFE\xAC\x39\x59\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9F\xEE\x44\xB3\x94\xD5\xFA\x91\x4F\x2E\xD9\x55\x9A\x04\x56\xDB\x2D\xC4\xDB\xA5\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x7F\x5F\xB9\x53\x5B\x63\x3D\x75\x32\xE7\xFA\xC4\x74\x1A\xCB\x46\xDF\x46\x69\x1C\x52\xCF\xAA\x4F\xC2\x68\xEB\xFF\x80\xA9\x51\xE8\x3D\x62\x77\x89\x3D\x0A\x75\x39\xF1\x6E\x5D\x17\x87\x6F\x68\x05\xC1\x94\x6C\xD9\x5D\xDF\xDA\xB2\x59\xCB\xA5\x10\x8A\xCA\xCC\x39\xCD\x9F\xEB\x4E\xDE\x52\xFF\x0C\xF0\xF4\x92\xA9\xF2\x6C\x53\xAB\x9B\xD2\x47\xA0\x1F\x74\xF7\x9B\x9A\xF1\x2F\x15\x9F\x7A\x64\x30\x18\x07\x3C\x2A\x0F\x67\xCA\xFC\x0F\x89\x61\x9D\x65\xA5\x3C\xE5\xBC\x13\x5B\x08\xDB\xE3\xFF\xED\xBB\x06\xBB\x6A\x06\xB1\x7A\x4F\x65\xC6\x82\xFD\x1E\x9C\x8B\xB5\x0D\xEE\x48\xBB\xB8\xBD\xAA\x08\xB4\xFB\xA3\x7C\xCB\x9F\xCD\x90\x76\x5C\x86\x96\x78\x57\x0A\x66\xF9\x58\x1A\x9D\xFD\x97\x29\x60\xDE\x11\xA6\x90\x1C\x19\x1C\xEE\x01\x96\x22\x34\x34\x2E\x91\xF9\xB7\xC4\x27\xD1\x7B\xE6\xBF\xFB\x80\x44\x5A\x16\xE5\xEB\xE0\xD4\x0A\x38\xBC\xE4\x91\xE3\xD5\xEB\x5C\xC1\xAC\xDF\x1B\x6A\x7C\x9E\xE5\x75\xD2\xB6\x97\x87\xDB\xCC\x87\x2B\x43\x3A\x84\x08\xAF\xAB\x3C\xDB\xF7\x3C\x66\x31\x86\xB0\x9D\x53\x79\xED\xF8\x23\xDE\x42\xE3\x2D\x82\xF1\x0F\xE5\xFA\x97", + ["CN=GlobalSign,O=GlobalSign,OU=GlobalSign Root CA - R3"] = "\x30\x82\x03\x5F\x30\x82\x02\x47\xA0\x03\x02\x01\x02\x02\x0B\x04\x00\x00\x00\x00\x01\x21\x58\x53\x08\xA2\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x4C\x31\x20\x30\x1E\x06\x03\x55\x04\x0B\x13\x17\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x52\x33\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x30\x1E\x17\x0D\x30\x39\x30\x33\x31\x38\x31\x30\x30\x30\x30\x30\x5A\x17\x0D\x32\x39\x30\x33\x31\x38\x31\x30\x30\x30\x30\x30\x5A\x30\x4C\x31\x20\x30\x1E\x06\x03\x55\x04\x0B\x13\x17\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x43\x41\x20\x2D\x20\x52\x33\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0A\x47\x6C\x6F\x62\x61\x6C\x53\x69\x67\x6E\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\xCC\x25\x76\x90\x79\x06\x78\x22\x16\xF5\xC0\x83\xB6\x84\xCA\x28\x9E\xFD\x05\x76\x11\xC5\xAD\x88\x72\xFC\x46\x02\x43\xC7\xB2\x8A\x9D\x04\x5F\x24\xCB\x2E\x4B\xE1\x60\x82\x46\xE1\x52\xAB\x0C\x81\x47\x70\x6C\xDD\x64\xD1\xEB\xF5\x2C\xA3\x0F\x82\x3D\x0C\x2B\xAE\x97\xD7\xB6\x14\x86\x10\x79\xBB\x3B\x13\x80\x77\x8C\x08\xE1\x49\xD2\x6A\x62\x2F\x1F\x5E\xFA\x96\x68\xDF\x89\x27\x95\x38\x9F\x06\xD7\x3E\xC9\xCB\x26\x59\x0D\x73\xDE\xB0\xC8\xE9\x26\x0E\x83\x15\xC6\xEF\x5B\x8B\xD2\x04\x60\xCA\x49\xA6\x28\xF6\x69\x3B\xF6\xCB\xC8\x28\x91\xE5\x9D\x8A\x61\x57\x37\xAC\x74\x14\xDC\x74\xE0\x3A\xEE\x72\x2F\x2E\x9C\xFB\xD0\xBB\xBF\xF5\x3D\x00\xE1\x06\x33\xE8\x82\x2B\xAE\x53\xA6\x3A\x16\x73\x8C\xDD\x41\x0E\x20\x3A\xC0\xB4\xA7\xA1\xE9\xB2\x4F\x90\x2E\x32\x60\xE9\x57\xCB\xB9\x04\x92\x68\x68\xE5\x38\x26\x60\x75\xB2\x9F\x77\xFF\x91\x14\xEF\xAE\x20\x49\xFC\xAD\x40\x15\x48\xD1\x02\x31\x61\x19\x5E\xB8\x97\xEF\xAD\x77\xB7\x64\x9A\x7A\xBF\x5F\xC1\x13\xEF\x9B\x62\xFB\x0D\x6C\xE0\x54\x69\x16\xA9\x03\xDA\x6E\xE9\x83\x93\x71\x76\xC6\x69\x85\x82\x17\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x8F\xF0\x4B\x7F\xA8\x2E\x45\x24\xAE\x4D\x50\xFA\x63\x9A\x8B\xDE\xE2\xDD\x1B\xBC\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x4B\x40\xDB\xC0\x50\xAA\xFE\xC8\x0C\xEF\xF7\x96\x54\x45\x49\xBB\x96\x00\x09\x41\xAC\xB3\x13\x86\x86\x28\x07\x33\xCA\x6B\xE6\x74\xB9\xBA\x00\x2D\xAE\xA4\x0A\xD3\xF5\xF1\xF1\x0F\x8A\xBF\x73\x67\x4A\x83\xC7\x44\x7B\x78\xE0\xAF\x6E\x6C\x6F\x03\x29\x8E\x33\x39\x45\xC3\x8E\xE4\xB9\x57\x6C\xAA\xFC\x12\x96\xEC\x53\xC6\x2D\xE4\x24\x6C\xB9\x94\x63\xFB\xDC\x53\x68\x67\x56\x3E\x83\xB8\xCF\x35\x21\xC3\xC9\x68\xFE\xCE\xDA\xC2\x53\xAA\xCC\x90\x8A\xE9\xF0\x5D\x46\x8C\x95\xDD\x7A\x58\x28\x1A\x2F\x1D\xDE\xCD\x00\x37\x41\x8F\xED\x44\x6D\xD7\x53\x28\x97\x7E\xF3\x67\x04\x1E\x15\xD7\x8A\x96\xB4\xD3\xDE\x4C\x27\xA4\x4C\x1B\x73\x73\x76\xF4\x17\x99\xC2\x1F\x7A\x0E\xE3\x2D\x08\xAD\x0A\x1C\x2C\xFF\x3C\xAB\x55\x0E\x0F\x91\x7E\x36\xEB\xC3\x57\x49\xBE\xE1\x2E\x2D\x7C\x60\x8B\xC3\x41\x51\x13\x23\x9D\xCE\xF7\x32\x6B\x94\x01\xA8\x99\xE7\x2C\x33\x1F\x3A\x3B\x25\xD2\x86\x40\xCE\x3B\x2C\x86\x78\xC9\x61\x2F\x14\xBA\xEE\xDB\x55\x6F\xDF\x84\xEE\x05\x09\x4D\xBD\x28\xD8\x72\xCE\xD3\x62\x50\x65\x1E\xEB\x92\x97\x83\x31\xD9\xB3\xB5\xCA\x47\x58\x3F\x5F", + ["CN=TC TrustCenter Universal CA III,OU=TC TrustCenter Universal CA,O=TC TrustCenter GmbH,C=DE"] = "\x30\x82\x03\xE1\x30\x82\x02\xC9\xA0\x03\x02\x01\x02\x02\x0E\x63\x25\x00\x01\x00\x02\x14\x8D\x33\x15\x02\xE4\x6C\xF4\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0B\x13\x1B\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1F\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x49\x49\x49\x30\x1E\x17\x0D\x30\x39\x30\x39\x30\x39\x30\x38\x31\x35\x32\x37\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x7B\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x44\x45\x31\x1C\x30\x1A\x06\x03\x55\x04\x0A\x13\x13\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x47\x6D\x62\x48\x31\x24\x30\x22\x06\x03\x55\x04\x0B\x13\x1B\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x31\x28\x30\x26\x06\x03\x55\x04\x03\x13\x1F\x54\x43\x20\x54\x72\x75\x73\x74\x43\x65\x6E\x74\x65\x72\x20\x55\x6E\x69\x76\x65\x72\x73\x61\x6C\x20\x43\x41\x20\x49\x49\x49\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\xC2\xDA\x9C\x62\xB0\xB9\x71\x12\xB0\x0B\xC8\x1A\x57\xB2\xAE\x83\x14\x99\xB3\x34\x4B\x9B\x90\xA2\xC5\xE7\xE7\x2F\x02\xA0\x4D\x2D\xA4\xFA\x85\xDA\x9B\x25\x85\x2D\x40\x28\x20\x6D\xEA\xE0\xBD\xB1\x48\x83\x22\x29\x44\x9F\x4E\x83\xEE\x35\x51\x13\x73\x74\xD5\xBC\xF2\x30\x66\x94\x53\xC0\x40\x36\x2F\x0C\x84\x65\xCE\x0F\x6E\xC2\x58\x93\xE8\x2C\x0B\x3A\xE9\xC1\x8E\xFB\xF2\x6B\xCA\x3C\xE2\x9C\x4E\x8E\xE4\xF9\x7D\xD3\x27\x9F\x1B\xD5\x67\x78\x87\x2D\x7F\x0B\x47\xB3\xC7\xE8\xC9\x48\x7C\xAF\x2F\xCC\x0A\xD9\x41\xEF\x9F\xFE\x9A\xE1\xB2\xAE\xF9\x53\xB5\xE5\xE9\x46\x9F\x60\xE3\xDF\x8D\xD3\x7F\xFB\x96\x7E\xB3\xB5\x72\xF8\x4B\xAD\x08\x79\xCD\x69\x89\x40\x27\xF5\x2A\xC1\xAD\x43\xEC\xA4\x53\xC8\x61\xB6\xF7\xD2\x79\x2A\x67\x18\x76\x48\x6D\x5B\x25\x01\xD1\x26\xC5\xB7\x57\x69\x23\x15\x5B\x61\x8A\xAD\xF0\x1B\x2D\xD9\xAF\x5C\xF1\x26\x90\x69\xA9\xD5\x0C\x40\xF5\x33\x80\x43\x8F\x9C\xA3\x76\x2A\x45\xB4\xAF\xBF\x7F\x3E\x87\x3F\x76\xC5\xCD\x2A\xDE\x20\xC5\x16\x58\xCB\xF9\x1B\xF5\x0F\xCB\x0D\x11\x52\x64\xB8\xD2\x76\x62\x77\x83\xF1\x58\x9F\xFF\x02\x03\x01\x00\x01\xA3\x63\x30\x61\x30\x1F\x06\x03\x55\x1D\x23\x04\x18\x30\x16\x80\x14\x56\xE7\xE1\x5B\x25\x43\x80\xE0\xF6\x8C\xE1\x71\xBC\x8E\xE5\x80\x2F\xC4\x48\xE2\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x56\xE7\xE1\x5B\x25\x43\x80\xE0\xF6\x8C\xE1\x71\xBC\x8E\xE5\x80\x2F\xC4\x48\xE2\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x83\xC7\xAF\xEA\x7F\x4D\x0A\x3C\x39\xB1\x68\xBE\x7B\x6D\x89\x2E\xE9\xB3\x09\xE7\x18\x57\x8D\x85\x9A\x17\xF3\x76\x42\x50\x13\x0F\xC7\x90\x6F\x33\xAD\xC5\x49\x60\x2B\x6C\x49\x58\x19\xD4\xE2\xBE\xB7\xBF\xAB\x49\xBC\x94\xC8\xAB\xBE\x28\x6C\x16\x68\xE0\xC8\x97\x46\x20\xA0\x68\x67\x60\x88\x39\x20\x51\xD8\x68\x01\x11\xCE\xA7\xF6\x11\x07\xF6\xEC\xEC\xAC\x1A\x1F\xB2\x66\x6E\x56\x67\x60\x7A\x74\x5E\xC0\x6D\x97\x36\xAE\xB5\x0D\x5D\x66\x73\xC0\x25\x32\x45\xD8\x4A\x06\x07\x8F\xC4\xB7\x07\xB1\x4D\x06\x0D\xE1\xA5\xEB\xF4\x75\xCA\xBA\x9C\xD0\xBD\xB3\xD3\x32\x24\x4C\xEE\x7E\xE2\x76\x04\x4B\x49\x53\xD8\xF2\xE9\x54\x33\xFC\xE5\x71\x1F\x3D\x14\x5C\x96\x4B\xF1\x3A\xF2\x00\xBB\x6C\xB4\xFA\x96\x55\x08\x88\x09\xC1\xCC\x91\x19\x29\xB0\x20\x2D\xFF\xCB\x38\xA4\x40\xE1\x17\xBE\x79\x61\x80\xFF\x07\x03\x86\x4C\x4E\x7B\x06\x9F\x11\x86\x8D\x89\xEE\x27\xC4\xDB\xE2\xBC\x19\x8E\x0B\xC3\xC3\x13\xC7\x2D\x03\x63\x3B\xD3\xE8\xE4\xA2\x2A\xC2\x82\x08\x94\x16\x54\xF0\xEF\x1F\x27\x90\x25\xB8\x0D\x0E\x28\x1B\x47\x77\x47\xBD\x1C\xA8\x25\xF1\x94\xB4\x66", + ["CN=Autoridad de Certificacion Firmaprofesional CIF A62634068,C=ES"] = "\x30\x82\x06\x14\x30\x82\x03\xFC\xA0\x03\x02\x01\x02\x02\x08\x53\xEC\x3B\xEE\xFB\xB2\x48\x5F\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x51\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x42\x30\x40\x06\x03\x55\x04\x03\x0C\x39\x41\x75\x74\x6F\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x46\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x20\x43\x49\x46\x20\x41\x36\x32\x36\x33\x34\x30\x36\x38\x30\x1E\x17\x0D\x30\x39\x30\x35\x32\x30\x30\x38\x33\x38\x31\x35\x5A\x17\x0D\x33\x30\x31\x32\x33\x31\x30\x38\x33\x38\x31\x35\x5A\x30\x51\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x42\x30\x40\x06\x03\x55\x04\x03\x0C\x39\x41\x75\x74\x6F\x72\x69\x64\x61\x64\x20\x64\x65\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x63\x69\x6F\x6E\x20\x46\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x20\x43\x49\x46\x20\x41\x36\x32\x36\x33\x34\x30\x36\x38\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xCA\x96\x6B\x8E\xEA\xF8\xFB\xF1\xA2\x35\xE0\x7F\x4C\xDA\xE0\xC3\x52\xD7\x7D\xB6\x10\xC8\x02\x5E\xB3\x43\x2A\xC4\x4F\x6A\xB2\xCA\x1C\x5D\x28\x9A\x78\x11\x1A\x69\x59\x57\xAF\xB5\x20\x42\xE4\x8B\x0F\xE6\xDF\x5B\xA6\x03\x92\x2F\xF5\x11\xE4\x62\xD7\x32\x71\x38\xD9\x04\x0C\x71\xAB\x3D\x51\x7E\x0F\x07\xDF\x63\x05\x5C\xE9\xBF\x94\x6F\xC1\x29\x82\xC0\xB4\xDA\x51\xB0\xC1\x3C\xBB\xAD\x37\x4A\x5C\xCA\xF1\x4B\x36\x0E\x24\xAB\xBF\xC3\x84\x77\xFD\xA8\x50\xF4\xB1\xE7\xC6\x2F\xD2\x2D\x59\x8D\x7A\x0A\x4E\x96\x69\x52\x02\xAA\x36\x98\xEC\xFC\xFA\x14\x83\x0C\x37\x1F\xC9\x92\x37\x7F\xD7\x81\x2D\xE5\xC4\xB9\xE0\x3E\x34\xFE\x67\xF4\x3E\x66\xD1\xD3\xF4\x40\xCF\x5E\x62\x34\x0F\x70\x06\x3E\x20\x18\x5A\xCE\xF7\x72\x1B\x25\x6C\x93\x74\x14\x93\xA3\x73\xB1\x0E\xAA\x87\x10\x23\x59\x5F\x20\x05\x19\x47\xED\x68\x8E\x92\x12\xCA\x5D\xFC\xD6\x2B\xB2\x92\x3C\x20\xCF\xE1\x5F\xAF\x20\xBE\xA0\x76\x7F\x76\xE5\xEC\x1A\x86\x61\x33\x3E\xE7\x7B\xB4\x3F\xA0\x0F\x8E\xA2\xB9\x6A\x6F\xB9\x87\x26\x6F\x41\x6C\x88\xA6\x50\xFD\x6A\x63\x0B\xF5\x93\x16\x1B\x19\x8F\xB2\xED\x9B\x9B\xC9\x90\xF5\x01\x0C\xDF\x19\x3D\x0F\x3E\x38\x23\xC9\x2F\x8F\x0C\xD1\x02\xFE\x1B\x55\xD6\x4E\xD0\x8D\x3C\xAF\x4F\xA4\xF3\xFE\xAF\x2A\xD3\x05\x9D\x79\x08\xA1\xCB\x57\x31\xB4\x9C\xC8\x90\xB2\x67\xF4\x18\x16\x93\x3A\xFC\x47\xD8\xD1\x78\x96\x31\x1F\xBA\x2B\x0C\x5F\x5D\x99\xAD\x63\x89\x5A\x24\x20\x76\xD8\xDF\xFD\xAB\x4E\xA6\x22\xAA\x9D\x5E\xE6\x27\x8A\x7D\x68\x29\xA3\xE7\x8A\xB8\xDA\x11\xBB\x17\x2D\x99\x9D\x13\x24\x46\xF7\xC5\xE2\xD8\x9F\x8E\x7F\xC7\x8F\x74\x6D\x5A\xB2\xE8\x72\xF5\xAC\xEE\x24\x10\xAD\x2F\x14\xDA\xFF\x2D\x9A\x46\x71\x47\xBE\x42\xDF\xBB\x01\xDB\xF4\x7F\xD3\x28\x8F\x31\x59\x5B\xD3\xC9\x02\xA6\xB4\x52\xCA\x6E\x97\xFB\x43\xC5\x08\x26\x6F\x8A\xF4\xBB\xFD\x9F\x28\xAA\x0D\xD5\x45\xF3\x13\x3A\x1D\xD8\xC0\x78\x8F\x41\x67\x3C\x1E\x94\x64\xAE\x7B\x0B\xC5\xE8\xD9\x01\x88\x39\x1A\x97\x86\x64\x41\xD5\x3B\x87\x0C\x6E\xFA\x0F\xC6\xBD\x48\x14\xBF\x39\x4D\xD4\x9E\x41\xB6\x8F\x96\x1D\x63\x96\x93\xD9\x95\x06\x78\x31\x68\x9E\x37\x06\x3B\x80\x89\x45\x61\x39\x23\xC7\x1B\x44\xA3\x15\xE5\x1C\xF8\x92\x30\xBB\x02\x03\x01\x00\x01\xA3\x81\xEF\x30\x81\xEC\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x01\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x65\xCD\xEB\xAB\x35\x1E\x00\x3E\x7E\xD5\x74\xC0\x1C\xB4\x73\x47\x0E\x1A\x64\x2F\x30\x81\xA6\x06\x03\x55\x1D\x20\x04\x81\x9E\x30\x81\x9B\x30\x81\x98\x06\x04\x55\x1D\x20\x00\x30\x81\x8F\x30\x2F\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x23\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x66\x69\x72\x6D\x61\x70\x72\x6F\x66\x65\x73\x69\x6F\x6E\x61\x6C\x2E\x63\x6F\x6D\x2F\x63\x70\x73\x30\x5C\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x50\x1E\x4E\x00\x50\x00\x61\x00\x73\x00\x65\x00\x6F\x00\x20\x00\x64\x00\x65\x00\x20\x00\x6C\x00\x61\x00\x20\x00\x42\x00\x6F\x00\x6E\x00\x61\x00\x6E\x00\x6F\x00\x76\x00\x61\x00\x20\x00\x34\x00\x37\x00\x20\x00\x42\x00\x61\x00\x72\x00\x63\x00\x65\x00\x6C\x00\x6F\x00\x6E\x00\x61\x00\x20\x00\x30\x00\x38\x00\x30\x00\x31\x00\x37\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x17\x7D\xA0\xF9\xB4\xDD\xC5\xC5\xEB\xAD\x4B\x24\xB5\xA1\x02\xAB\xDD\xA5\x88\x4A\xB2\x0F\x55\x4B\x2B\x57\x8C\x3B\xE5\x31\xDD\xFE\xC4\x32\xF1\xE7\x5B\x64\x96\x36\x32\x18\xEC\xA5\x32\x77\xD7\xE3\x44\xB6\xC0\x11\x2A\x80\xB9\x3D\x6A\x6E\x7C\x9B\xD3\xAD\xFC\xC3\xD6\xA3\xE6\x64\x29\x7C\xD1\xE1\x38\x1E\x82\x2B\xFF\x27\x65\xAF\xFB\x16\x15\xC4\x2E\x71\x84\xE5\xB5\xFF\xFA\xA4\x47\xBD\x64\x32\xBB\xF6\x25\x84\xA2\x27\x42\xF5\x20\xB0\xC2\x13\x10\x11\xCD\x10\x15\xBA\x42\x90\x2A\xD2\x44\xE1\x96\x26\xEB\x31\x48\x12\xFD\x2A\xDA\xC9\x06\xCF\x74\x1E\xA9\x4B\xD5\x87\x28\xF9\x79\x34\x92\x3E\x2E\x44\xE8\xF6\x8F\x4F\x8F\x35\x3F\x25\xB3\x39\xDC\x63\x2A\x90\x6B\x20\x5F\xC4\x52\x12\x4E\x97\x2C\x2A\xAC\x9D\x97\xDE\x48\xF2\xA3\x66\xDB\xC2\xD2\x83\x95\xA6\x66\xA7\x9E\x25\x0F\xE9\x0B\x33\x91\x65\x0A\x5A\xC3\xD9\x54\x12\xDD\xAF\xC3\x4E\x0E\x1F\x26\x5E\x0D\xDC\xB3\x8D\xEC\xD5\x81\x70\xDE\xD2\x4F\x24\x05\xF3\x6C\x4E\xF5\x4C\x49\x66\x8D\xD1\xFF\xD2\x0B\x25\x41\x48\xFE\x51\x84\xC6\x42\xAF\x80\x04\xCF\xD0\x7E\x64\x49\xE4\xF2\xDF\xA2\xEC\xB1\x4C\xC0\x2A\x1D\xE7\xB4\xB1\x65\xA2\xC4\xBC\xF1\x98\xF4\xAA\x70\x07\x63\xB4\xB8\xDA\x3B\x4C\xFA\x40\x22\x30\x5B\x11\xA6\xF0\x05\x0E\xC6\x02\x03\x48\xAB\x86\x9B\x85\xDD\xDB\xDD\xEA\xA2\x76\x80\x73\x7D\xF5\x9C\x04\xC4\x45\x8D\xE7\xB9\x1C\x8B\x9E\xEA\xD7\x75\xD1\x72\xB1\xDE\x75\x44\xE7\x42\x7D\xE2\x57\x6B\x7D\xDC\x99\xBC\x3D\x83\x28\xEA\x80\x93\x8D\xC5\x4C\x65\xC1\x70\x81\xB8\x38\xFC\x43\x31\xB2\xF6\x03\x34\x47\xB2\xAC\xFB\x22\x06\xCB\x1E\xDD\x17\x47\x1C\x5F\x66\xB9\xD3\x1A\xA2\xDA\x11\xB1\xA4\xBC\x23\xC9\xE4\xBE\x87\xFF\xB9\x94\xB6\xF8\x5D\x20\x4A\xD4\x5F\xE7\xBD\x68\x7B\x65\xF2\x15\x1E\xD2\x3A\xA9\x2D\xE9\xD8\x6B\x24\xAC\x97\x58\x44\x47\xAD\x59\x18\xF1\x21\x65\x70\xDE\xCE\x34\x60\xA8\x40\xF1\xF3\x3C\xA4\xC3\x28\x23\x8C\xFE\x27\x33\x43\x40\xA0\x17\x3C\xEB\xEA\x3B\xB0\x72\xA6\xA3\xB9\x4A\x4B\x5E\x16\x48\xF4\xB2\xBC\xC8\x8C\x92\xC5\x9D\x9F\xAC\x72\x36\xBC\x34\x80\x34\x6B\xA9\x8B\x92\xC0\xB8\x17\xED\xEC\x76\x53\xF5\x24\x01\x8C\xB3\x22\xE8\x4B\x7C\x55\xC6\x9D\xFA\xA3\x14\xBB\x65\x85\x6E\x6E\x4F\x12\x7E\x0A\x3C\x9D\x95", + ["CN=Izenpe.com,O=IZENPE S.A.,C=ES"] = "\x30\x82\x05\xF1\x30\x82\x03\xD9\xA0\x03\x02\x01\x02\x02\x10\x00\xB0\xB7\x5A\x16\x48\x5F\xBF\xE1\xCB\xF5\x8B\xD7\x19\xE6\x7D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x38\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x49\x5A\x45\x4E\x50\x45\x20\x53\x2E\x41\x2E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x0C\x0A\x49\x7A\x65\x6E\x70\x65\x2E\x63\x6F\x6D\x30\x1E\x17\x0D\x30\x37\x31\x32\x31\x33\x31\x33\x30\x38\x32\x38\x5A\x17\x0D\x33\x37\x31\x32\x31\x33\x30\x38\x32\x37\x32\x35\x5A\x30\x38\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x49\x5A\x45\x4E\x50\x45\x20\x53\x2E\x41\x2E\x31\x13\x30\x11\x06\x03\x55\x04\x03\x0C\x0A\x49\x7A\x65\x6E\x70\x65\x2E\x63\x6F\x6D\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC9\xD3\x7A\xCA\x0F\x1E\xAC\xA7\x86\xE8\x16\x65\x6A\xB1\xC2\x1B\x45\x32\x71\x95\xD9\xFE\x10\x5B\xCC\xAF\xE7\xA5\x79\x01\x8F\x89\xC3\xCA\xF2\x55\x71\xF7\x77\xBE\x77\x94\xF3\x72\xA4\x2C\x44\xD8\x9E\x92\x9B\x14\x3A\xA1\xE7\x24\x90\x0A\x0A\x56\x8E\xC5\xD8\x26\x94\xE1\xD9\x48\xE1\x2D\x3E\xDA\x0A\x72\xDD\xA3\x99\x15\xDA\x81\xA2\x87\xF4\x7B\x6E\x26\x77\x89\x58\xAD\xD6\xEB\x0C\xB2\x41\x7A\x73\x6E\x6D\xDB\x7A\x78\x41\xE9\x08\x88\x12\x7E\x87\x2E\x66\x11\x63\x6C\x54\xFB\x3C\x9D\x72\xC0\xBC\x2E\xFF\xC2\xB7\xDD\x0D\x76\xE3\x3A\xD7\xF7\xB4\x68\xBE\xA2\xF5\xE3\x81\x6E\xC1\x46\x6F\x5D\x8D\xE0\x4D\xC6\x54\x55\x89\x1A\x33\x31\x0A\xB1\x57\xB9\xA3\x8A\x98\xC3\xEC\x3B\x34\xC5\x95\x41\x69\x7E\x75\xC2\x3C\x20\xC5\x61\xBA\x51\x47\xA0\x20\x90\x93\xA1\x90\x4B\xF3\x4E\x7C\x85\x45\x54\x9A\xD1\x05\x26\x41\xB0\xB5\x4D\x1D\x33\xBE\xC4\x03\xC8\x25\x7C\xC1\x70\xDB\x3B\xF4\x09\x2D\x54\x27\x48\xAC\x2F\xE1\xC4\xAC\x3E\xC8\xCB\x92\x4C\x53\x39\x37\x23\xEC\xD3\x01\xF9\xE0\x09\x44\x4D\x4D\x64\xC0\xE1\x0D\x5A\x87\x22\xBC\xAD\x1B\xA3\xFE\x26\xB5\x15\xF3\xA7\xFC\x84\x19\xE9\xEC\xA1\x88\xB4\x44\x69\x84\x83\xF3\x89\xD1\x74\x06\xA9\xCC\x0B\xD6\xC2\xDE\x27\x85\x50\x26\xCA\x17\xB8\xC9\x7A\x87\x56\x2C\x1A\x01\x1E\x6C\xBE\x13\xAD\x10\xAC\xB5\x24\xF5\x38\x91\xA1\xD6\x4B\xDA\xF1\xBB\xD2\xDE\x47\xB5\xF1\xBC\x81\xF6\x59\x6B\xCF\x19\x53\xE9\x8D\x15\xCB\x4A\xCB\xA9\x6F\x44\xE5\x1B\x41\xCF\xE1\x86\xA7\xCA\xD0\x6A\x9F\xBC\x4C\x8D\x06\x33\x5A\xA2\x85\xE5\x90\x35\xA0\x62\x5C\x16\x4E\xF0\xE3\xA2\xFA\x03\x1A\xB4\x2C\x71\xB3\x58\x2C\xDE\x7B\x0B\xDB\x1A\x0F\xEB\xDE\x21\x1F\x06\x77\x06\x03\xB0\xC9\xEF\x99\xFC\xC0\xB9\x4F\x0B\x86\x28\xFE\xD2\xB9\xEA\xE3\xDA\xA5\xC3\x47\x69\x12\xE0\xDB\xF0\xF6\x19\x8B\xED\x7B\x70\xD7\x02\xD6\xED\x87\x18\x28\x2C\x04\x24\x4C\x77\xE4\x48\x8A\x1A\xC6\x3B\x9A\xD4\x0F\xCA\xFA\x75\xD2\x01\x40\x5A\x8D\x79\xBF\x8B\xCF\x4B\xCF\xAA\x16\xC1\x95\xE4\xAD\x4C\x8A\x3E\x17\x91\xD4\xB1\x62\xE5\x82\xE5\x80\x04\xA4\x03\x7E\x8D\xBF\xDA\x7F\xA2\x0F\x97\x4F\x0C\xD3\x0D\xFB\xD7\xD1\xE5\x72\x7E\x1C\xC8\x77\xFF\x5B\x9A\x0F\xB7\xAE\x05\x46\xE5\xF1\xA8\x16\xEC\x47\xA4\x17\x02\x03\x01\x00\x01\xA3\x81\xF6\x30\x81\xF3\x30\x81\xB0\x06\x03\x55\x1D\x11\x04\x81\xA8\x30\x81\xA5\x81\x0F\x69\x6E\x66\x6F\x40\x69\x7A\x65\x6E\x70\x65\x2E\x63\x6F\x6D\xA4\x81\x91\x30\x81\x8E\x31\x47\x30\x45\x06\x03\x55\x04\x0A\x0C\x3E\x49\x5A\x45\x4E\x50\x45\x20\x53\x2E\x41\x2E\x20\x2D\x20\x43\x49\x46\x20\x41\x30\x31\x33\x33\x37\x32\x36\x30\x2D\x52\x4D\x65\x72\x63\x2E\x56\x69\x74\x6F\x72\x69\x61\x2D\x47\x61\x73\x74\x65\x69\x7A\x20\x54\x31\x30\x35\x35\x20\x46\x36\x32\x20\x53\x38\x31\x43\x30\x41\x06\x03\x55\x04\x09\x0C\x3A\x41\x76\x64\x61\x20\x64\x65\x6C\x20\x4D\x65\x64\x69\x74\x65\x72\x72\x61\x6E\x65\x6F\x20\x45\x74\x6F\x72\x62\x69\x64\x65\x61\x20\x31\x34\x20\x2D\x20\x30\x31\x30\x31\x30\x20\x56\x69\x74\x6F\x72\x69\x61\x2D\x47\x61\x73\x74\x65\x69\x7A\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x1D\x1C\x65\x0E\xA8\xF2\x25\x7B\xB4\x91\xCF\xE4\xB1\xB1\xE6\xBD\x55\x74\x6C\x05\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x02\x01\x00\x78\xA6\x0C\x16\x4A\x9F\x4C\x88\x3A\xC0\xCB\x0E\xA5\x16\x7D\x9F\xB9\x48\x5F\x18\x8F\x0D\x62\x36\xF6\xCD\x19\x6B\xAC\xAB\xD5\xF6\x91\x7D\xAE\x71\xF3\x3F\xB3\x0E\x78\x85\x9B\x95\xA4\x27\x21\x47\x42\x4A\x7C\x48\x3A\xF5\x45\x7C\xB3\x0C\x8E\x51\x78\xAC\x95\x13\xDE\xC6\xFD\x7D\xB8\x1A\x90\x4C\xAB\x92\x03\xC7\xED\x42\x01\xCE\x0F\xD8\xB1\xFA\xA2\x92\xE1\x60\x6D\xAE\x7A\x6B\x09\xAA\xC6\x29\xEE\x68\x49\x67\x30\x80\x24\x7A\x31\x16\x39\x5B\x7E\xF1\x1C\x2E\xDD\x6C\x09\xAD\xF2\x31\xC1\x82\x4E\xB9\xBB\xF9\xBE\xBF\x2A\x85\x3F\xC0\x40\xA3\x3A\x59\xFC\x59\x4B\x3C\x28\x24\xDB\xB4\x15\x75\xAE\x0D\x88\xBA\x2E\x73\xC0\xBD\x58\x87\xE5\x42\xF2\xEB\x5E\xEE\x1E\x30\x22\x99\xCB\x37\xD1\xC4\x21\x6C\x81\xEC\xBE\x6D\x26\xE6\x1C\xE4\x42\x20\x9E\x47\xB0\xAC\x83\x59\x70\x2C\x35\xD6\xAF\x36\x34\xB4\xCD\x3B\xF8\x32\xA8\xEF\xE3\x78\x89\xFB\x8D\x45\x2C\xDA\x9C\xB8\x7E\x40\x1C\x61\xE7\x3E\xA2\x92\x2C\x4B\xF2\xCD\xFA\x98\xB6\x29\xFF\xF3\xF2\x7B\xA9\x1F\x2E\xA0\x93\x57\x2B\xDE\x85\x03\xF9\x69\x37\xCB\x9E\x78\x6A\x05\xB4\xC5\x31\x78\x89\xEC\x7A\xA7\x85\xE1\xB9\x7B\x3C\xDE\xBE\x1E\x79\x84\xCE\x9F\x70\x0E\x59\xC2\x35\x2E\x90\x2A\x31\xD9\xE4\x45\x7A\x41\xA4\x2E\x13\x9B\x34\x0E\x66\x7B\x49\xAB\x64\x97\xD0\x46\xC3\x79\x9D\x72\x50\x63\xA6\x98\x5B\x06\xBD\x48\x6D\xD8\x39\x83\x70\xE8\x35\xF0\x05\xD1\xAA\xBC\xE3\xDB\xC8\x02\xEA\x7C\xFD\x82\xDA\xC2\x5B\x52\x35\xAE\x98\x3A\xAD\xBA\x35\x93\x23\xA7\x1F\x48\xDD\x35\x46\x98\xB2\x10\x68\xE4\xA5\x31\xC2\x0A\x58\x2E\x19\x81\x10\xC9\x50\x75\xFC\xEA\x5A\x16\xCE\x11\xD7\xEE\xEF\x50\x88\x2D\x61\xFF\x3F\x42\x73\x05\x94\x43\xD5\x8E\x3C\x4E\x01\x3A\x19\xA5\x1F\x46\x4E\x77\xD0\x5D\xE5\x81\x22\x21\x87\xFE\x94\x7D\x84\xD8\x93\xAD\xD6\x68\x43\x48\xB2\xDB\xEB\x73\x24\xE7\x91\x7F\x54\xA4\xB6\x80\x3E\x9D\xA3\x3C\x4C\x72\xC2\x57\xC4\xA0\xD4\xCC\x38\x27\xCE\xD5\x06\x9E\xA2\x48\xD9\xE9\x9F\xCE\x82\x70\x36\x93\x9A\x3B\xDF\x96\x21\xE3\x59\xB7\x0C\xDA\x91\x37\xF0\xFD\x59\x5A\xB3\x99\xC8\x69\x6C\x43\x26\x01\x35\x63\x60\x55\x89\x03\x3A\x75\xD8\xBA\x4A\xD9\x54\xFF\xEE\xDE\x80\xD8\x2D\xD1\x38\xD5\x5E\x2D\x0B\x98\x7D\x3E\x6C\xDB\xFC\x26\x88\xC7", + ["CN=Chambers of Commerce Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU"] = "\x30\x82\x07\x4F\x30\x82\x05\x37\xA0\x03\x02\x01\x02\x02\x09\x00\xA3\xDA\x42\x7E\xA4\xB1\xAE\xDA\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x30\x1E\x17\x0D\x30\x38\x30\x38\x30\x31\x31\x32\x32\x39\x35\x30\x5A\x17\x0D\x33\x38\x30\x37\x33\x31\x31\x32\x32\x39\x35\x30\x5A\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xAF\x00\xCB\x70\x37\x2B\x80\x5A\x4A\x3A\x6C\x78\x94\x7D\xA3\x7F\x1A\x1F\xF6\x35\xD5\xBD\xDB\xCB\x0D\x44\x72\x3E\x26\xB2\x90\x52\xBA\x63\x3B\x28\x58\x6F\xA5\xB3\x6D\x94\xA6\xF3\xDD\x64\x0C\x55\xF6\xF6\xE7\xF2\x22\x22\x80\x5E\xE1\x62\xC6\xB6\x29\xE1\x81\x6C\xF2\xBF\xE5\x7D\x32\x6A\x54\xA0\x32\x19\x59\xFE\x1F\x8B\xD7\x3D\x60\x86\x85\x24\x6F\xE3\x11\xB3\x77\x3E\x20\x96\x35\x21\x6B\xB3\x08\xD9\x70\x2E\x64\xF7\x84\x92\x53\xD6\x0E\xB0\x90\x8A\x8A\xE3\x87\x8D\x06\xD3\xBD\x90\x0E\xE2\x99\xA1\x1B\x86\x0E\xDA\x9A\x0A\xBB\x0B\x61\x50\x06\x52\xF1\x9E\x7F\x76\xEC\xCB\x0F\xD0\x1E\x0D\xCF\x99\x30\x3D\x1C\xC4\x45\x10\x58\xAC\xD6\xD3\xE8\xD7\xE5\xEA\xC5\x01\x07\x77\xD6\x51\xE6\x03\x7F\x8A\x48\xA5\x4D\x68\x75\xB9\xE9\xBC\x9E\x4E\x19\x71\xF5\x32\x4B\x9C\x6D\x60\x19\x0B\xFB\xCC\x9D\x75\xDC\xBF\x26\xCD\x8F\x93\x78\x39\x79\x73\x5E\x25\x0E\xCA\x5C\xEB\x77\x12\x07\xCB\x64\x41\x47\x72\x93\xAB\x50\xC3\xEB\x09\x76\x64\x34\xD2\x39\xB7\x76\x11\x09\x0D\x76\x45\xC4\xA9\xAE\x3D\x6A\xAF\xB5\x7D\x65\x2F\x94\x58\x10\xEC\x5C\x7C\xAF\x7E\xE2\xB6\x18\xD9\xD0\x9B\x4E\x5A\x49\xDF\xA9\x66\x0B\xCC\x3C\xC6\x78\x7C\xA7\x9C\x1D\xE3\xCE\x8E\x53\xBE\x05\xDE\x60\x0F\x6B\xE5\x1A\xDB\x3F\xE3\xE1\x21\xC9\x29\xC1\xF1\xEB\x07\x9C\x52\x1B\x01\x44\x51\x3C\x7B\x25\xD7\xC4\xE5\x52\x54\x5D\x25\x07\xCA\x16\x20\xB8\xAD\xE4\x41\xEE\x7A\x08\xFE\x99\x6F\x83\xA6\x91\x02\xB0\x6C\x36\x55\x6A\xE7\x7D\xF5\x96\xE6\xCA\x81\xD6\x97\xF1\x94\x83\xE9\xED\xB0\xB1\x6B\x12\x69\x1E\xAC\xFB\x5D\xA9\xC5\x98\xE9\xB4\x5B\x58\x7A\xBE\x3D\xA2\x44\x3A\x63\x59\xD4\x0B\x25\xDE\x1B\x4F\xBD\xE5\x01\x9E\xCD\xD2\x29\xD5\x9F\x17\x19\x0A\x6F\xBF\x0C\x90\xD3\x09\x5F\xD9\xE3\x8A\x35\xCC\x79\x5A\x4D\x19\x37\x92\xB7\xC4\xC1\xAD\xAF\xF4\x79\x24\x9A\xB2\x01\x0B\xB1\xAF\x5C\x96\xF3\x80\x32\xFB\x5C\x3D\x98\xF1\xA0\x3F\x4A\xDE\xBE\xAF\x94\x2E\xD9\x55\x9A\x17\x6E\x60\x9D\x63\x6C\xB8\x63\xC9\xAE\x81\x5C\x18\x35\xE0\x90\xBB\xBE\x3C\x4F\x37\x22\xB9\x7E\xEB\xCF\x9E\x77\x21\xA6\x3D\x38\x81\xFB\x48\xDA\x31\x3D\x2B\xE3\x89\xF5\xD0\xB5\xBD\x7E\xE0\x50\xC4\x12\x89\xB3\x23\x9A\x10\x31\x85\xDB\xAE\x6F\xEF\x38\x33\x18\x76\x11\x02\x03\x01\x00\x01\xA3\x82\x01\x6C\x30\x82\x01\x68\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x0C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xF9\x24\xAC\x0F\xB2\xB5\xF8\x79\xC0\xFA\x60\x88\x1B\xC4\xD9\x4D\x02\x9E\x17\x19\x30\x81\xE3\x06\x03\x55\x1D\x23\x04\x81\xDB\x30\x81\xD8\x80\x14\xF9\x24\xAC\x0F\xB2\xB5\xF8\x79\xC0\xFA\x60\x88\x1B\xC4\xD9\x4D\x02\x9E\x17\x19\xA1\x81\xB4\xA4\x81\xB1\x30\x81\xAE\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x29\x30\x27\x06\x03\x55\x04\x03\x13\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x20\x6F\x66\x20\x43\x6F\x6D\x6D\x65\x72\x63\x65\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x82\x09\x00\xA3\xDA\x42\x7E\xA4\xB1\xAE\xDA\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x3D\x06\x03\x55\x1D\x20\x04\x36\x30\x34\x30\x32\x06\x04\x55\x1D\x20\x00\x30\x2A\x30\x28\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x1C\x68\x74\x74\x70\x3A\x2F\x2F\x70\x6F\x6C\x69\x63\x79\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x90\x12\xAF\x22\x35\xC2\xA3\x39\xF0\x2E\xDE\xE9\xB5\xE9\x78\x7C\x48\xBE\x3F\x7D\x45\x92\x5E\xE9\xDA\xB1\x19\xFC\x16\x3C\x9F\xB4\x5B\x66\x9E\x6A\xE7\xC3\xB9\x5D\x88\xE8\x0F\xAD\xCF\x23\x0F\xDE\x25\x3A\x5E\xCC\x4F\xA5\xC1\xB5\x2D\xAC\x24\xD2\x58\x07\xDE\xA2\xCF\x69\x84\x60\x33\xE8\x10\x0D\x13\xA9\x23\xD0\x85\xE5\x8E\x7B\xA6\x9E\x3D\x72\x13\x72\x33\xF5\xAA\x7D\xC6\x63\x1F\x08\xF4\xFE\x01\x7F\x24\xCF\x2B\x2C\x54\x09\xDE\xE2\x2B\x6D\x92\xC6\x39\x4F\x16\xEA\x3C\x7E\x7A\x46\xD4\x45\x6A\x46\xA8\xEB\x75\x82\x56\xA7\xAB\xA0\x7C\x68\x13\x33\xF6\x9D\x30\xF0\x6F\x27\x39\x24\x23\x2A\x90\xFD\x90\x29\x35\xF2\x93\xDF\x34\xA5\xC6\xF7\xF8\xEF\x8C\x0F\x62\x4A\x7C\xAE\xD3\xF5\x54\xF8\x8D\xB6\x9A\x56\x87\x16\x82\x3A\x33\xAB\x5A\x22\x08\xF7\x82\xBA\xEA\x2E\xE0\x47\x9A\xB4\xB5\x45\xA3\x05\x3B\xD9\xDC\x2E\x45\x40\x3B\xEA\xDC\x7F\xE8\x3B\xEB\xD1\xEC\x26\xD8\x35\xA4\x30\xC5\x3A\xAC\x57\x9E\xB3\x76\xA5\x20\x7B\xF9\x1E\x4A\x05\x62\x01\xA6\x28\x75\x60\x97\x92\x0D\x6E\x3E\x4D\x37\x43\x0D\x92\x15\x9C\x18\x22\xCD\x51\x99\xA0\x29\x1A\x3C\x5F\x8A\x32\x33\x5B\x30\xC7\x89\x2F\x47\x98\x0F\xA3\x03\xC6\xF6\xF1\xAC\xDF\x32\xF0\xD9\x81\x1A\xE4\x9C\xBD\xF6\x80\x14\xF0\xD1\x2C\xB9\x85\xF5\xD8\xA3\xB1\xC8\xA5\x21\xE5\x1C\x13\x97\xEE\x0E\xBD\xDF\x29\xA9\xEF\x34\x53\x5B\xD3\xE4\x6A\x13\x84\x06\xB6\x32\x02\xC4\x52\xAE\x22\xD2\xDC\xB2\x21\x42\x1A\xDA\x40\xF0\x29\xC9\xEC\x0A\x0C\x5C\xE2\xD0\xBA\xCC\x48\xD3\x37\x0A\xCC\x12\x0A\x8A\x79\xB0\x3D\x03\x7F\x69\x4B\xF4\x34\x20\x7D\xB3\x34\xEA\x8E\x4B\x64\xF5\x3E\xFD\xB3\x23\x67\x15\x0D\x04\xB8\xF0\x2D\xC1\x09\x51\x3C\xB2\x6C\x15\xF0\xA5\x23\xD7\x83\x74\xE4\xE5\x2E\xC9\xFE\x98\x27\x42\xC6\xAB\xC6\x9E\xB0\xD0\x5B\x38\xA5\x9B\x50\xDE\x7E\x18\x98\xB5\x45\x3B\xF6\x79\xB4\xE8\xF7\x1A\x7B\x06\x83\xFB\xD0\x8B\xDA\xBB\xC7\xBD\x18\xAB\x08\x6F\x3C\x80\x6B\x40\x3F\x19\x19\xBA\x65\x8A\xE6\xBE\xD5\x5C\xD3\x36\xD7\xEF\x40\x52\x24\x60\x38\x67\x04\x31\xEC\x8F\xF3\x82\xC6\xDE\xB9\x55\xF3\x3B\x31\x91\x5A\xDC\xB5\x08\x15\xAD\x76\x25\x0A\x0D\x7B\x2E\x87\xE2\x0C\xA6\x06\xBC\x26\x10\x6D\x37\x9D\xEC\xDD\x78\x8C\x7C\x80\xC5\xF0\xD9\x77\x48\xD0", + ["CN=Global Chambersign Root - 2008,O=AC Camerfirma S.A.,serialNumber=A82743287,L=Madrid (see current address at www.camerfirma.com/address),C=EU"] = "\x30\x82\x07\x49\x30\x82\x05\x31\xA0\x03\x02\x01\x02\x02\x09\x00\xC9\xCD\xD3\xE9\xD5\x7D\x23\xCE\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\xAC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x47\x6C\x6F\x62\x61\x6C\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x30\x1E\x17\x0D\x30\x38\x30\x38\x30\x31\x31\x32\x33\x31\x34\x30\x5A\x17\x0D\x33\x38\x30\x37\x33\x31\x31\x32\x33\x31\x34\x30\x5A\x30\x81\xAC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x47\x6C\x6F\x62\x61\x6C\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC0\xDF\x56\xD3\xE4\x3A\x9B\x76\x45\xB4\x13\xDB\xFF\xC1\xB6\x19\x8B\x37\x41\x18\x95\x52\x47\xEB\x17\x9D\x29\x88\x8E\x35\x6C\x06\x32\x2E\x47\x62\xF3\x49\x04\xBF\x7D\x44\x36\xB1\x71\xCC\xBD\x5A\x09\x73\xD5\xD9\x85\x44\xFF\x91\x57\x25\xDF\x5E\x36\x8E\x70\xD1\x5C\x71\x43\x1D\xD9\xDA\xEF\x5C\xD2\xFB\x1B\xBD\x3A\xB5\xCB\xAD\xA3\xCC\x44\xA7\x0D\xAE\x21\x15\x3F\xB9\x7A\x5B\x92\x75\xD8\xA4\x12\x38\x89\x19\x8A\xB7\x80\xD2\xE2\x32\x6F\x56\x9C\x91\xD6\x88\x10\x0B\xB3\x74\x64\x92\x74\x60\xF3\xF6\xCF\x18\x4F\x60\xB2\x23\xD0\xC7\x3B\xCE\x61\x4B\x99\x8F\xC2\x0C\xD0\x40\xB2\x98\xDC\x0D\xA8\x4E\xA3\xB9\x0A\xAE\x60\xA0\xAD\x45\x52\x63\xBA\x66\xBD\x68\xE0\xF9\xBE\x1A\xA8\x81\xBB\x1E\x41\x78\x75\xD3\xC1\xFE\x00\x55\xB0\x87\x54\xE8\x27\x90\x35\x1D\x4C\x33\xAD\x97\xFC\x97\x2E\x98\x84\xBF\x2C\xC9\xA3\xBF\xD1\x98\x11\x14\xED\x63\xF8\xCA\x98\x88\x58\x17\x99\xED\x45\x03\x97\x7E\x3C\x86\x1E\x88\x8C\xBE\xF2\x91\x84\x8F\x65\x34\xD8\x00\x4C\x7D\xB7\x31\x17\x5A\x29\x7A\x0A\x18\x24\x30\xA3\x37\xB5\x7A\xA9\x01\x7D\x26\xD6\xF9\x0E\x8E\x59\xF1\xFD\x1B\x33\xB5\x29\x3B\x17\x3B\x41\xB6\x21\xDD\xD4\xC0\x3D\xA5\x9F\x9F\x1F\x43\x50\xC9\xBB\xBC\x6C\x7A\x97\x98\xEE\xCD\x8C\x1F\xFB\x9C\x51\xAE\x8B\x70\xBD\x27\x9F\x71\xC0\x6B\xAC\x7D\x90\x66\xE8\xD7\x5D\x3A\x0D\xB0\xD5\xC2\x8D\xD5\xC8\x9D\x9D\xC1\x6D\xD0\xD0\xBF\x51\xE4\xE3\xF8\xC3\x38\x36\xAE\xD6\xA7\x75\xE6\xAF\x84\x43\x5D\x93\x92\x0C\x6A\x07\xDE\x3B\x1D\x98\x22\xD6\xAC\xC1\x35\xDB\xA3\xA0\x25\xFF\x72\xB5\x76\x1D\xDE\x6D\xE9\x2C\x66\x2C\x52\x84\xD0\x45\x92\xCE\x1C\xE5\xE5\x33\x1D\xDC\x07\x53\x54\xA3\xAA\x82\x3B\x9A\x37\x2F\xDC\xDD\xA0\x64\xE9\xE6\xDD\xBD\xAE\xFC\x64\x85\x1D\x3C\xA7\xC9\x06\xDE\x84\xFF\x6B\xE8\x6B\x1A\x3C\xC5\xA2\xB3\x42\xFB\x8B\x09\x3E\x5F\x08\x52\xC7\x62\xC4\xD4\x05\x71\xBF\xC4\x64\xE4\xF8\xA1\x83\xE8\x3E\x12\x9B\xA8\x1E\xD4\x36\x4D\x2F\x71\xF6\x8D\x28\xF6\x83\xA9\x13\xD2\x61\xC1\x91\xBB\x48\xC0\x34\x8F\x41\x8C\x4B\x4C\xDB\x69\x12\xFF\x50\x94\x9C\x20\x83\x59\x73\xED\x7C\xA1\xF2\xF1\xFD\xDD\xF7\x49\xD3\x43\x58\xA0\x56\x63\xCA\x3D\x3D\xE5\x35\x56\x59\xE9\x0E\xCA\x20\xCC\x2B\x4B\x93\x29\x0F\x02\x03\x01\x00\x01\xA3\x82\x01\x6A\x30\x82\x01\x66\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x0C\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\xB9\x09\xCA\x9C\x1E\xDB\xD3\x6C\x3A\x6B\xAE\xED\x54\xF1\x5B\x93\x06\x35\x2E\x5E\x30\x81\xE1\x06\x03\x55\x1D\x23\x04\x81\xD9\x30\x81\xD6\x80\x14\xB9\x09\xCA\x9C\x1E\xDB\xD3\x6C\x3A\x6B\xAE\xED\x54\xF1\x5B\x93\x06\x35\x2E\x5E\xA1\x81\xB2\xA4\x81\xAF\x30\x81\xAC\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x55\x31\x43\x30\x41\x06\x03\x55\x04\x07\x13\x3A\x4D\x61\x64\x72\x69\x64\x20\x28\x73\x65\x65\x20\x63\x75\x72\x72\x65\x6E\x74\x20\x61\x64\x64\x72\x65\x73\x73\x20\x61\x74\x20\x77\x77\x77\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x2F\x61\x64\x64\x72\x65\x73\x73\x29\x31\x12\x30\x10\x06\x03\x55\x04\x05\x13\x09\x41\x38\x32\x37\x34\x33\x32\x38\x37\x31\x1B\x30\x19\x06\x03\x55\x04\x0A\x13\x12\x41\x43\x20\x43\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x20\x53\x2E\x41\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x47\x6C\x6F\x62\x61\x6C\x20\x43\x68\x61\x6D\x62\x65\x72\x73\x69\x67\x6E\x20\x52\x6F\x6F\x74\x20\x2D\x20\x32\x30\x30\x38\x82\x09\x00\xC9\xCD\xD3\xE9\xD5\x7D\x23\xCE\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x3D\x06\x03\x55\x1D\x20\x04\x36\x30\x34\x30\x32\x06\x04\x55\x1D\x20\x00\x30\x2A\x30\x28\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x1C\x68\x74\x74\x70\x3A\x2F\x2F\x70\x6F\x6C\x69\x63\x79\x2E\x63\x61\x6D\x65\x72\x66\x69\x72\x6D\x61\x2E\x63\x6F\x6D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x80\x88\x7F\x70\xDE\x92\x28\xD9\x05\x94\x46\xFF\x90\x57\xA9\xF1\x2F\xDF\x1A\x0D\x6B\xFA\x7C\x0E\x1C\x49\x24\x79\x27\xD8\x46\xAA\x6F\x29\x59\x52\x88\x70\x12\xEA\xDD\x3D\xF5\x9B\x53\x54\x6F\xE1\x60\xA2\xA8\x09\xB9\xEC\xEB\x59\x7C\xC6\x35\xF1\xDC\x18\xE9\xF1\x67\xE5\xAF\xBA\x45\xE0\x09\xDE\xCA\x44\x0F\xC2\x17\x0E\x77\x91\x45\x7A\x33\x5F\x5F\x96\x2C\x68\x8B\xC1\x47\x8F\x98\x9B\x3D\xC0\xEC\xCB\xF5\xD5\x82\x92\x84\x35\xD1\xBE\x36\x38\x56\x72\x31\x5B\x47\x2D\xAA\x17\xA4\x63\x51\xEB\x0A\x01\xAD\x7F\xEC\x75\x9E\xCB\xA1\x1F\xF1\x7F\x12\xB1\xB9\xE4\x64\x7F\x67\xD6\x23\x2A\xF4\xB8\x39\x5D\x98\xE8\x21\xA7\xE1\xBD\x3D\x42\x1A\x74\x9A\x70\xAF\x68\x6C\x50\x5D\x49\xCF\xFF\xFB\x0E\x5D\xE6\x2C\x47\xD7\x81\x3A\x59\x00\xB5\x73\x6B\x63\x20\xF6\x31\x45\x08\x39\x0E\xF4\x70\x7E\x40\x70\x5A\x3F\xD0\x6B\x42\xA9\x74\x3D\x28\x2F\x02\x6D\x75\x72\x95\x09\x8D\x48\x63\xC6\xC6\x23\x57\x92\x93\x5E\x35\xC1\x8D\xF9\x0A\xF7\x2C\x9D\x62\x1C\xF6\xAD\x7C\xDD\xA6\x31\x1E\xB6\xB1\xC7\x7E\x85\x26\xFA\xA4\x6A\xB5\xDA\x63\x30\xD1\xEF\x93\x37\xB2\x66\x2F\x7D\x05\xF7\xE7\xB7\x4B\x98\x94\x35\xC0\xD9\x3A\x29\xC1\x9D\xB2\x50\x33\x1D\x4A\xA9\x5A\xA6\xC9\x03\xEF\xED\xF4\xE7\xA8\x6E\x8A\xB4\x57\x84\xEB\xA4\x3F\xD0\xEE\xAA\xAA\x87\x5B\x63\xE8\x93\xE2\x6B\xA8\xD4\xB8\x72\x78\x6B\x1B\xED\x39\xE4\x5D\xCB\x9B\xAA\x87\xD5\x4F\x4E\x00\xFE\xD9\x6A\x9F\x3C\x31\x0F\x28\x02\x01\x7D\x98\xE8\xA7\xB0\xA2\x64\x9E\x79\xF8\x48\xF2\x15\xA9\xCC\xE6\xC8\x44\xEB\x3F\x78\x99\xF2\x7B\x71\x3E\x3C\xF1\x98\xA7\xC5\x18\x12\x3F\xE6\xBB\x28\x33\x42\xE9\x45\x0A\x7C\x6D\xF2\x86\x79\x2F\xC5\x82\x19\x7D\x09\x89\x7C\xB2\x54\x76\x88\xAE\xDE\xC1\xF3\xCC\xE1\x6E\xDB\x31\xD6\x93\xAE\x99\xA0\xEF\x25\x6A\x73\x98\x89\x5B\x3A\x2E\x13\x88\x1E\xBF\xC0\x92\x94\x34\x1B\xE3\x27\xB7\x8B\x1E\x6F\x42\xFF\xE7\xE9\x37\x9B\x50\x1D\x2D\xA2\xF9\x02\xEE\xCB\x58\x58\x3A\x71\xBC\x68\xE3\xAA\xC1\xAF\x1C\x28\x1F\xA2\xDC\x23\x65\x3F\x81\xEA\xAE\x99\xD3\xD8\x30\xCF\x13\x0D\x4F\x15\xC9\x84\xBC\xA7\x48\x2D\xF8\x30\x23\x77\xD8\x46\x4B\x79\x6D\xF6\x8C\xED\x3A\x7F\x60\x11\x78\xF4\xE9\x9B\xAE\xD5\x54\xC0\x74\x80\xD1\x0B\x42\x9F\xC1", + ["CN=Go Daddy Root Certificate Authority - G2,O=GoDaddy.com\, Inc.,L=Scottsdale,ST=Arizona,C=US"] = "\x30\x82\x03\xC5\x30\x82\x02\xAD\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x83\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7A\x6F\x6E\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x53\x63\x6F\x74\x74\x73\x64\x61\x6C\x65\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x13\x11\x47\x6F\x44\x61\x64\x64\x79\x2E\x63\x6F\x6D\x2C\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x03\x13\x28\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x39\x30\x39\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x83\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7A\x6F\x6E\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x53\x63\x6F\x74\x74\x73\x64\x61\x6C\x65\x31\x1A\x30\x18\x06\x03\x55\x04\x0A\x13\x11\x47\x6F\x44\x61\x64\x64\x79\x2E\x63\x6F\x6D\x2C\x20\x49\x6E\x63\x2E\x31\x31\x30\x2F\x06\x03\x55\x04\x03\x13\x28\x47\x6F\x20\x44\x61\x64\x64\x79\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\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\x71\x62\x08\xF1\xFA\x59\x34\xF7\x1B\xC9\x18\xA3\xF7\x80\x49\x58\xE9\x22\x83\x13\xA6\xC5\x20\x43\x01\x3B\x84\xF1\xE6\x85\x49\x9F\x27\xEA\xF6\x84\x1B\x4E\xA0\xB4\xDB\x70\x98\xC7\x32\x01\xB1\x05\x3E\x07\x4E\xEE\xF4\xFA\x4F\x2F\x59\x30\x22\xE7\xAB\x19\x56\x6B\xE2\x80\x07\xFC\xF3\x16\x75\x80\x39\x51\x7B\xE5\xF9\x35\xB6\x74\x4E\xA9\x8D\x82\x13\xE4\xB6\x3F\xA9\x03\x83\xFA\xA2\xBE\x8A\x15\x6A\x7F\xDE\x0B\xC3\xB6\x19\x14\x05\xCA\xEA\xC3\xA8\x04\x94\x3B\x46\x7C\x32\x0D\xF3\x00\x66\x22\xC8\x8D\x69\x6D\x36\x8C\x11\x18\xB7\xD3\xB2\x1C\x60\xB4\x38\xFA\x02\x8C\xCE\xD3\xDD\x46\x07\xDE\x0A\x3E\xEB\x5D\x7C\xC8\x7C\xFB\xB0\x2B\x53\xA4\x92\x62\x69\x51\x25\x05\x61\x1A\x44\x81\x8C\x2C\xA9\x43\x96\x23\xDF\xAC\x3A\x81\x9A\x0E\x29\xC5\x1C\xA9\xE9\x5D\x1E\xB6\x9E\x9E\x30\x0A\x39\xCE\xF1\x88\x80\xFB\x4B\x5D\xCC\x32\xEC\x85\x62\x43\x25\x34\x02\x56\x27\x01\x91\xB4\x3B\x70\x2A\x3F\x6E\xB1\xE8\x9C\x88\x01\x7D\x9F\xD4\xF9\xDB\x53\x6D\x60\x9D\xBF\x2C\xE7\x58\xAB\xB8\x5F\x46\xFC\xCE\xC4\x1B\x03\x3C\x09\xEB\x49\x31\x5C\x69\x46\xB3\xE0\x47\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x3A\x9A\x85\x07\x10\x67\x28\xB6\xEF\xF6\xBD\x05\x41\x6E\x20\xC1\x94\xDA\x0F\xDE\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x99\xDB\x5D\x79\xD5\xF9\x97\x59\x67\x03\x61\xF1\x7E\x3B\x06\x31\x75\x2D\xA1\x20\x8E\x4F\x65\x87\xB4\xF7\xA6\x9C\xBC\xD8\xE9\x2F\xD0\xDB\x5A\xEE\xCF\x74\x8C\x73\xB4\x38\x42\xDA\x05\x7B\xF8\x02\x75\xB8\xFD\xA5\xB1\xD7\xAE\xF6\xD7\xDE\x13\xCB\x53\x10\x7E\x8A\x46\xD1\x97\xFA\xB7\x2E\x2B\x11\xAB\x90\xB0\x27\x80\xF9\xE8\x9F\x5A\xE9\x37\x9F\xAB\xE4\xDF\x6C\xB3\x85\x17\x9D\x3D\xD9\x24\x4F\x79\x91\x35\xD6\x5F\x04\xEB\x80\x83\xAB\x9A\x02\x2D\xB5\x10\xF4\xD8\x90\xC7\x04\x73\x40\xED\x72\x25\xA0\xA9\x9F\xEC\x9E\xAB\x68\x12\x99\x57\xC6\x8F\x12\x3A\x09\xA4\xBD\x44\xFD\x06\x15\x37\xC1\x9B\xE4\x32\xA3\xED\x38\xE8\xD8\x64\xF3\x2C\x7E\x14\xFC\x02\xEA\x9F\xCD\xFF\x07\x68\x17\xDB\x22\x90\x38\x2D\x7A\x8D\xD1\x54\xF1\x69\xE3\x5F\x33\xCA\x7A\x3D\x7B\x0A\xE3\xCA\x7F\x5F\x39\xE5\xE2\x75\xBA\xC5\x76\x18\x33\xCE\x2C\xF0\x2F\x4C\xAD\xF7\xB1\xE7\xCE\x4F\xA8\xC4\x9B\x4A\x54\x06\xC5\x7F\x7D\xD5\x08\x0F\xE2\x1C\xFE\x7E\x17\xB8\xAC\x5E\xF6\xD4\x16\xB2\x43\x09\x0C\x4D\xF6\xA7\x6B\xB4\x99\x84\x65\xCA\x7A\x88\xE2\xE2\x44\xBE\x5C\xF7\xEA\x1C\xF5", + ["CN=Starfield Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US"] = "\x30\x82\x03\xDD\x30\x82\x02\xC5\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x8F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7A\x6F\x6E\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x53\x63\x6F\x74\x74\x73\x64\x61\x6C\x65\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x39\x30\x39\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x8F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7A\x6F\x6E\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x53\x63\x6F\x74\x74\x73\x64\x61\x6C\x65\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x32\x30\x30\x06\x03\x55\x04\x03\x13\x29\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\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\xBD\xED\xC1\x03\xFC\xF6\x8F\xFC\x02\xB1\x6F\x5B\x9F\x48\xD9\x9D\x79\xE2\xA2\xB7\x03\x61\x56\x18\xC3\x47\xB6\xD7\xCA\x3D\x35\x2E\x89\x43\xF7\xA1\x69\x9B\xDE\x8A\x1A\xFD\x13\x20\x9C\xB4\x49\x77\x32\x29\x56\xFD\xB9\xEC\x8C\xDD\x22\xFA\x72\xDC\x27\x61\x97\xEE\xF6\x5A\x84\xEC\x6E\x19\xB9\x89\x2C\xDC\x84\x5B\xD5\x74\xFB\x6B\x5F\xC5\x89\xA5\x10\x52\x89\x46\x55\xF4\xB8\x75\x1C\xE6\x7F\xE4\x54\xAE\x4B\xF8\x55\x72\x57\x02\x19\xF8\x17\x71\x59\xEB\x1E\x28\x07\x74\xC5\x9D\x48\xBE\x6C\xB4\xF4\xA4\xB0\xF3\x64\x37\x79\x92\xC0\xEC\x46\x5E\x7F\xE1\x6D\x53\x4C\x62\xAF\xCD\x1F\x0B\x63\xBB\x3A\x9D\xFB\xFC\x79\x00\x98\x61\x74\xCF\x26\x82\x40\x63\xF3\xB2\x72\x6A\x19\x0D\x99\xCA\xD4\x0E\x75\xCC\x37\xFB\x8B\x89\xC1\x59\xF1\x62\x7F\x5F\xB3\x5F\x65\x30\xF8\xA7\xB7\x4D\x76\x5A\x1E\x76\x5E\x34\xC0\xE8\x96\x56\x99\x8A\xB3\xF0\x7F\xA4\xCD\xBD\xDC\x32\x31\x7C\x91\xCF\xE0\x5F\x11\xF8\x6B\xAA\x49\x5C\xD1\x99\x94\xD1\xA2\xE3\x63\x5B\x09\x76\xB5\x56\x62\xE1\x4B\x74\x1D\x96\xD4\x26\xD4\x08\x04\x59\xD0\x98\x0E\x0E\xE6\xDE\xFC\xC3\xEC\x1F\x90\xF1\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x7C\x0C\x32\x1F\xA7\xD9\x30\x7F\xC4\x7D\x68\xA3\x62\xA8\xA1\xCE\xAB\x07\x5B\x27\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x11\x59\xFA\x25\x4F\x03\x6F\x94\x99\x3B\x9A\x1F\x82\x85\x39\xD4\x76\x05\x94\x5E\xE1\x28\x93\x6D\x62\x5D\x09\xC2\xA0\xA8\xD4\xB0\x75\x38\xF1\x34\x6A\x9D\xE4\x9F\x8A\x86\x26\x51\xE6\x2C\xD1\xC6\x2D\x6E\x95\x20\x4A\x92\x01\xEC\xB8\x8A\x67\x7B\x31\xE2\x67\x2E\x8C\x95\x03\x26\x2E\x43\x9D\x4A\x31\xF6\x0E\xB5\x0C\xBB\xB7\xE2\x37\x7F\x22\xBA\x00\xA3\x0E\x7B\x52\xFB\x6B\xBB\x3B\xC4\xD3\x79\x51\x4E\xCD\x90\xF4\x67\x07\x19\xC8\x3C\x46\x7A\x0D\x01\x7D\xC5\x58\xE7\x6D\xE6\x85\x30\x17\x9A\x24\xC4\x10\xE0\x04\xF7\xE0\xF2\x7F\xD4\xAA\x0A\xFF\x42\x1D\x37\xED\x94\xE5\x64\x59\x12\x20\x77\x38\xD3\x32\x3E\x38\x81\x75\x96\x73\xFA\x68\x8F\xB1\xCB\xCE\x1F\xC5\xEC\xFA\x9C\x7E\xCF\x7E\xB1\xF1\x07\x2D\xB6\xFC\xBF\xCA\xA4\xBF\xD0\x97\x05\x4A\xBC\xEA\x18\x28\x02\x90\xBD\x54\x78\x09\x21\x71\xD3\xD1\x7D\x1D\xD9\x16\xB0\xA9\x61\x3D\xD0\x0A\x00\x22\xFC\xC7\x7B\xCB\x09\x64\x45\x0B\x3B\x40\x81\xF7\x7D\x7C\x32\xF5\x98\xCA\x58\x8E\x7D\x2A\xEE\x90\x59\x73\x64\xF9\x36\x74\x5E\x25\xA1\xF5\x66\x05\x2E\x7F\x39\x15\xA9\x2A\xFB\x50\x8B\x8E\x85\x69\xF4", + ["CN=Starfield Services Root Certificate Authority - G2,O=Starfield Technologies\, Inc.,L=Scottsdale,ST=Arizona,C=US"] = "\x30\x82\x03\xEF\x30\x82\x02\xD7\xA0\x03\x02\x01\x02\x02\x01\x00\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x81\x98\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7A\x6F\x6E\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x53\x63\x6F\x74\x74\x73\x64\x61\x6C\x65\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x3B\x30\x39\x06\x03\x55\x04\x03\x13\x32\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\x30\x1E\x17\x0D\x30\x39\x30\x39\x30\x31\x30\x30\x30\x30\x30\x30\x5A\x17\x0D\x33\x37\x31\x32\x33\x31\x32\x33\x35\x39\x35\x39\x5A\x30\x81\x98\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x10\x30\x0E\x06\x03\x55\x04\x08\x13\x07\x41\x72\x69\x7A\x6F\x6E\x61\x31\x13\x30\x11\x06\x03\x55\x04\x07\x13\x0A\x53\x63\x6F\x74\x74\x73\x64\x61\x6C\x65\x31\x25\x30\x23\x06\x03\x55\x04\x0A\x13\x1C\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x2C\x20\x49\x6E\x63\x2E\x31\x3B\x30\x39\x06\x03\x55\x04\x03\x13\x32\x53\x74\x61\x72\x66\x69\x65\x6C\x64\x20\x53\x65\x72\x76\x69\x63\x65\x73\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x65\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x20\x2D\x20\x47\x32\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\xD5\x0C\x3A\xC4\x2A\xF9\x4E\xE2\xF5\xBE\x19\x97\x5F\x8E\x88\x53\xB1\x1F\x3F\xCB\xCF\x9F\x20\x13\x6D\x29\x3A\xC8\x0F\x7D\x3C\xF7\x6B\x76\x38\x63\xD9\x36\x60\xA8\x9B\x5E\x5C\x00\x80\xB2\x2F\x59\x7F\xF6\x87\xF9\x25\x43\x86\xE7\x69\x1B\x52\x9A\x90\xE1\x71\xE3\xD8\x2D\x0D\x4E\x6F\xF6\xC8\x49\xD9\xB6\xF3\x1A\x56\xAE\x2B\xB6\x74\x14\xEB\xCF\xFB\x26\xE3\x1A\xBA\x1D\x96\x2E\x6A\x3B\x58\x94\x89\x47\x56\xFF\x25\xA0\x93\x70\x53\x83\xDA\x84\x74\x14\xC3\x67\x9E\x04\x68\x3A\xDF\x8E\x40\x5A\x1D\x4A\x4E\xCF\x43\x91\x3B\xE7\x56\xD6\x00\x70\xCB\x52\xEE\x7B\x7D\xAE\x3A\xE7\xBC\x31\xF9\x45\xF6\xC2\x60\xCF\x13\x59\x02\x2B\x80\xCC\x34\x47\xDF\xB9\xDE\x90\x65\x6D\x02\xCF\x2C\x91\xA6\xA6\xE7\xDE\x85\x18\x49\x7C\x66\x4E\xA3\x3A\x6D\xA9\xB5\xEE\x34\x2E\xBA\x0D\x03\xB8\x33\xDF\x47\xEB\xB1\x6B\x8D\x25\xD9\x9B\xCE\x81\xD1\x45\x46\x32\x96\x70\x87\xDE\x02\x0E\x49\x43\x85\xB6\x6C\x73\xBB\x64\xEA\x61\x41\xAC\xC9\xD4\x54\xDF\x87\x2F\xC7\x22\xB2\x26\xCC\x9F\x59\x54\x68\x9F\xFC\xBE\x2A\x2F\xC4\x55\x1C\x75\x40\x60\x17\x85\x02\x55\x39\x8B\x7F\x05\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9C\x5F\x00\xDF\xAA\x01\xD7\x30\x2B\x38\x88\xA2\xB8\x6D\x4A\x9C\xF2\x11\x91\x83\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x4B\x36\xA6\x84\x77\x69\xDD\x3B\x19\x9F\x67\x23\x08\x6F\x0E\x61\xC9\xFD\x84\xDC\x5F\xD8\x36\x81\xCD\xD8\x1B\x41\x2D\x9F\x60\xDD\xC7\x1A\x68\xD9\xD1\x6E\x86\xE1\x88\x23\xCF\x13\xDE\x43\xCF\xE2\x34\xB3\x04\x9D\x1F\x29\xD5\xBF\xF8\x5E\xC8\xD5\xC1\xBD\xEE\x92\x6F\x32\x74\xF2\x91\x82\x2F\xBD\x82\x42\x7A\xAD\x2A\xB7\x20\x7D\x4D\xBC\x7A\x55\x12\xC2\x15\xEA\xBD\xF7\x6A\x95\x2E\x6C\x74\x9F\xCF\x1C\xB4\xF2\xC5\x01\xA3\x85\xD0\x72\x3E\xAD\x73\xAB\x0B\x9B\x75\x0C\x6D\x45\xB7\x8E\x94\xAC\x96\x37\xB5\xA0\xD0\x8F\x15\x47\x0E\xE3\xE8\x83\xDD\x8F\xFD\xEF\x41\x01\x77\xCC\x27\xA9\x62\x85\x33\xF2\x37\x08\xEF\x71\xCF\x77\x06\xDE\xC8\x19\x1D\x88\x40\xCF\x7D\x46\x1D\xFF\x1E\xC7\xE1\xCE\xFF\x23\xDB\xC6\xFA\x8D\x55\x4E\xA9\x02\xE7\x47\x11\x46\x3E\xF4\xFD\xBD\x7B\x29\x26\xBB\xA9\x61\x62\x37\x28\xB6\x2D\x2A\xF6\x10\x86\x64\xC9\x70\xA7\xD2\xAD\xB7\x29\x70\x79\xEA\x3C\xDA\x63\x25\x9F\xFD\x68\xB7\x30\xEC\x70\xFB\x75\x8A\xB7\x6D\x60\x67\xB2\x1E\xC8\xB9\xE9\xD8\xA8\x6F\x02\x8B\x67\x0D\x4D\x26\x57\x71\xDA\x20\xFC\xC1\x4A\x50\x8D\xB1\x28\xBA", + ["CN=AffirmTrust Commercial,O=AffirmTrust,C=US"] = "\x30\x82\x03\x4C\x30\x82\x02\x34\xA0\x03\x02\x01\x02\x02\x08\x77\x77\x06\x27\x26\xA9\xB1\x7C\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x30\x44\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x0C\x16\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x43\x6F\x6D\x6D\x65\x72\x63\x69\x61\x6C\x30\x1E\x17\x0D\x31\x30\x30\x31\x32\x39\x31\x34\x30\x36\x30\x36\x5A\x17\x0D\x33\x30\x31\x32\x33\x31\x31\x34\x30\x36\x30\x36\x5A\x30\x44\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x0C\x16\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x43\x6F\x6D\x6D\x65\x72\x63\x69\x61\x6C\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\xF6\x1B\x4F\x67\x07\x2B\xA1\x15\xF5\x06\x22\xCB\x1F\x01\xB2\xE3\x73\x45\x06\x44\x49\x2C\xBB\x49\x25\x14\xD6\xCE\xC3\xB7\xAB\x2C\x4F\xC6\x41\x32\x94\x57\xFA\x12\xA7\x5B\x0E\xE2\x8F\x1F\x1E\x86\x19\xA7\xAA\xB5\x2D\xB9\x5F\x0D\x8A\xC2\xAF\x85\x35\x79\x32\x2D\xBB\x1C\x62\x37\xF2\xB1\x5B\x4A\x3D\xCA\xCD\x71\x5F\xE9\x42\xBE\x94\xE8\xC8\xDE\xF9\x22\x48\x64\xC6\xE5\xAB\xC6\x2B\x6D\xAD\x05\xF0\xFA\xD5\x0B\xCF\x9A\xE5\xF0\x50\xA4\x8B\x3B\x47\xA5\x23\x5B\x7A\x7A\xF8\x33\x3F\xB8\xEF\x99\x97\xE3\x20\xC1\xD6\x28\x89\xCF\x94\xFB\xB9\x45\xED\xE3\x40\x17\x11\xD4\x74\xF0\x0B\x31\xE2\x2B\x26\x6A\x9B\x4C\x57\xAE\xAC\x20\x3E\xBA\x45\x7A\x05\xF3\xBD\x9B\x69\x15\xAE\x7D\x4E\x20\x63\xC4\x35\x76\x3A\x07\x02\xC9\x37\xFD\xC7\x47\xEE\xE8\xF1\x76\x1D\x73\x15\xF2\x97\xA4\xB5\xC8\x7A\x79\xD9\x42\xAA\x2B\x7F\x5C\xFE\xCE\x26\x4F\xA3\x66\x81\x35\xAF\x44\xBA\x54\x1E\x1C\x30\x32\x65\x9D\xE6\x3C\x93\x5E\x50\x4E\x7A\xE3\x3A\xD4\x6E\xCC\x1A\xFB\xF9\xD2\x37\xAE\x24\x2A\xAB\x57\x03\x22\x28\x0D\x49\x75\x7F\xB7\x28\xDA\x75\xBF\x8E\xE3\xDC\x0E\x79\x31\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9D\x93\xC6\x53\x8B\x5E\xCA\xAF\x3F\x9F\x1E\x0F\xE5\x99\x95\xBC\x24\xF6\x94\x8F\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0B\x05\x00\x03\x82\x01\x01\x00\x58\xAC\xF4\x04\x0E\xCD\xC0\x0D\xFF\x0A\xFD\xD4\xBA\x16\x5F\x29\xBD\x7B\x68\x99\x58\x49\xD2\xB4\x1D\x37\x4D\x7F\x27\x7D\x46\x06\x5D\x43\xC6\x86\x2E\x3E\x73\xB2\x26\x7D\x4F\x93\xA9\xB6\xC4\x2A\x9A\xAB\x21\x97\x14\xB1\xDE\x8C\xD3\xAB\x89\x15\xD8\x6B\x24\xD4\xF1\x16\xAE\xD8\xA4\x5C\xD4\x7F\x51\x8E\xED\x18\x01\xB1\x93\x63\xBD\xBC\xF8\x61\x80\x9A\x9E\xB1\xCE\x42\x70\xE2\xA9\x7D\x06\x25\x7D\x27\xA1\xFE\x6F\xEC\xB3\x1E\x24\xDA\xE3\x4B\x55\x1A\x00\x3B\x35\xB4\x3B\xD9\xD7\x5D\x30\xFD\x81\x13\x89\xF2\xC2\x06\x2B\xED\x67\xC4\x8E\xC9\x43\xB2\x5C\x6B\x15\x89\x02\xBC\x62\xFC\x4E\xF2\xB5\x33\xAA\xB2\x6F\xD3\x0A\xA2\x50\xE3\xF6\x3B\xE8\x2E\x44\xC2\xDB\x66\x38\xA9\x33\x56\x48\xF1\x6D\x1B\x33\x8D\x0D\x8C\x3F\x60\x37\x9D\xD3\xCA\x6D\x7E\x34\x7E\x0D\x9F\x72\x76\x8B\x1B\x9F\x72\xFD\x52\x35\x41\x45\x02\x96\x2F\x1C\xB2\x9A\x73\x49\x21\xB1\x49\x47\x45\x47\xB4\xEF\x6A\x34\x11\xC9\x4D\x9A\xCC\x59\xB7\xD6\x02\x9E\x5A\x4E\x65\xB5\x94\xAE\x1B\xDF\x29\xB0\x16\xF1\xBF\x00\x9E\x07\x3A\x17\x64\xB5\x04\xB5\x23\x21\x99\x0A\x95\x3B\x97\x7C\xEF", + ["CN=AffirmTrust Networking,O=AffirmTrust,C=US"] = "\x30\x82\x03\x4C\x30\x82\x02\x34\xA0\x03\x02\x01\x02\x02\x08\x7C\x4F\x04\x39\x1C\xD4\x99\x2D\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x44\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x0C\x16\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x69\x6E\x67\x30\x1E\x17\x0D\x31\x30\x30\x31\x32\x39\x31\x34\x30\x38\x32\x34\x5A\x17\x0D\x33\x30\x31\x32\x33\x31\x31\x34\x30\x38\x32\x34\x5A\x30\x44\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x1F\x30\x1D\x06\x03\x55\x04\x03\x0C\x16\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x4E\x65\x74\x77\x6F\x72\x6B\x69\x6E\x67\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\xB4\x84\xCC\x33\x17\x2E\x6B\x94\x6C\x6B\x61\x52\xA0\xEB\xA3\xCF\x79\x94\x4C\xE5\x94\x80\x99\xCB\x55\x64\x44\x65\x8F\x67\x64\xE2\x06\xE3\x5C\x37\x49\xF6\x2F\x9B\x84\x84\x1E\x2D\xF2\x60\x9D\x30\x4E\xCC\x84\x85\xE2\x2C\xCF\x1E\x9E\xFE\x36\xAB\x33\x77\x35\x44\xD8\x35\x96\x1A\x3D\x36\xE8\x7A\x0E\xD8\xD5\x47\xA1\x6A\x69\x8B\xD9\xFC\xBB\x3A\xAE\x79\x5A\xD5\xF4\xD6\x71\xBB\x9A\x90\x23\x6B\x9A\xB7\x88\x74\x87\x0C\x1E\x5F\xB9\x9E\x2D\xFA\xAB\x53\x2B\xDC\xBB\x76\x3E\x93\x4C\x08\x08\x8C\x1E\xA2\x23\x1C\xD4\x6A\xAD\x22\xBA\x99\x01\x2E\x6D\x65\xCB\xBE\x24\x66\x55\x24\x4B\x40\x44\xB1\x1B\xD7\xE1\xC2\x85\xC0\xDE\x10\x3F\x3D\xED\xB8\xFC\xF1\xF1\x23\x53\xDC\xBF\x65\x97\x6F\xD9\xF9\x40\x71\x8D\x7D\xBD\x95\xD4\xCE\xBE\xA0\x5E\x27\x23\xDE\xFD\xA6\xD0\x26\x0E\x00\x29\xEB\x3C\x46\xF0\x3D\x60\xBF\x3F\x50\xD2\xDC\x26\x41\x51\x9E\x14\x37\x42\x04\xA3\x70\x57\xA8\x1B\x87\xED\x2D\xFA\x7B\xEE\x8C\x0A\xE3\xA9\x66\x89\x19\xCB\x41\xF9\xDD\x44\x36\x61\xCF\xE2\x77\x46\xC8\x7D\xF6\xF4\x92\x81\x36\xFD\xDB\x34\xF1\x72\x7E\xF3\x0C\x16\xBD\xB4\x15\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x07\x1F\xD2\xE7\x9C\xDA\xC2\x6E\xA2\x40\xB4\xB0\x7A\x50\x10\x50\x74\xC4\xC8\xBD\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x89\x57\xB2\x16\x7A\xA8\xC2\xFD\xD6\xD9\x9B\x9B\x34\xC2\x9C\xB4\x32\x14\x4D\xA7\xA4\xDF\xEC\xBE\xA7\xBE\xF8\x43\xDB\x91\x37\xCE\xB4\x32\x2E\x50\x55\x1A\x35\x4E\x76\x43\x71\x20\xEF\x93\x77\x4E\x15\x70\x2E\x87\xC3\xC1\x1D\x6D\xDC\xCB\xB5\x27\xD4\x2C\x56\xD1\x52\x53\x3A\x44\xD2\x73\xC8\xC4\x1B\x05\x65\x5A\x62\x92\x9C\xEE\x41\x8D\x31\xDB\xE7\x34\xEA\x59\x21\xD5\x01\x7A\xD7\x64\xB8\x64\x39\xCD\xC9\xED\xAF\xED\x4B\x03\x48\xA7\xA0\x99\x01\x80\xDC\x65\xA3\x36\xAE\x65\x59\x48\x4F\x82\x4B\xC8\x65\xF1\x57\x1D\xE5\x59\x2E\x0A\x3F\x6C\xD8\xD1\xF5\xE5\x09\xB4\x6C\x54\x00\x0A\xE0\x15\x4D\x87\x75\x6D\xB7\x58\x96\x5A\xDD\x6D\xD2\x00\xA0\xF4\x9B\x48\xBE\xC3\x37\xA4\xBA\x36\xE0\x7C\x87\x85\x97\x1A\x15\xA2\xDE\x2E\xA2\x5B\xBD\xAF\x18\xF9\x90\x50\xCD\x70\x59\xF8\x27\x67\x47\xCB\xC7\xA0\x07\x3A\x7D\xD1\x2C\x5D\x6C\x19\x3A\x66\xB5\x7D\xFD\x91\x6F\x82\xB1\xBE\x08\x93\xDB\x14\x47\xF1\xA2\x37\xC7\x45\x9E\x3C\xC7\x77\xAF\x64\xA8\x93\xDF\xF6\x69\x83\x82\x60\xF2\x49\x42\x34\xED\x5A\x00\x54\x85\x1C\x16\x36\x92\x0C\x5C\xFA\xA6\xAD\xBF\xDB", + ["CN=AffirmTrust Premium,O=AffirmTrust,C=US"] = "\x30\x82\x05\x46\x30\x82\x03\x2E\xA0\x03\x02\x01\x02\x02\x08\x6D\x8C\x14\x46\xB1\xA6\x0A\xEE\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0C\x05\x00\x30\x41\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x1C\x30\x1A\x06\x03\x55\x04\x03\x0C\x13\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x50\x72\x65\x6D\x69\x75\x6D\x30\x1E\x17\x0D\x31\x30\x30\x31\x32\x39\x31\x34\x31\x30\x33\x36\x5A\x17\x0D\x34\x30\x31\x32\x33\x31\x31\x34\x31\x30\x33\x36\x5A\x30\x41\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x1C\x30\x1A\x06\x03\x55\x04\x03\x0C\x13\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x50\x72\x65\x6D\x69\x75\x6D\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\xC4\x12\xDF\xA9\x5F\xFE\x41\xDD\xDD\xF5\x9F\x8A\xE3\xF6\xAC\xE1\x3C\x78\x9A\xBC\xD8\xF0\x7F\x7A\xA0\x33\x2A\xDC\x8D\x20\x5B\xAE\x2D\x6F\xE7\x93\xD9\x36\x70\x6A\x68\xCF\x8E\x51\xA3\x85\x5B\x67\x04\xA0\x10\x24\x6F\x5D\x28\x82\xC1\x97\x57\xD8\x48\x29\x13\xB6\xE1\xBE\x91\x4D\xDF\x85\x0C\x53\x18\x9A\x1E\x24\xA2\x4F\x8F\xF0\xA2\x85\x0B\xCB\xF4\x29\x7F\xD2\xA4\x58\xEE\x26\x4D\xC9\xAA\xA8\x7B\x9A\xD9\xFA\x38\xDE\x44\x57\x15\xE5\xF8\x8C\xC8\xD9\x48\xE2\x0D\x16\x27\x1D\x1E\xC8\x83\x85\x25\xB7\xBA\xAA\x55\x41\xCC\x03\x22\x4B\x2D\x91\x8D\x8B\xE6\x89\xAF\x66\xC7\xE9\xFF\x2B\xE9\x3C\xAC\xDA\xD2\xB3\xC3\xE1\x68\x9C\x89\xF8\x7A\x00\x56\xDE\xF4\x55\x95\x6C\xFB\xBA\x64\xDD\x62\x8B\xDF\x0B\x77\x32\xEB\x62\xCC\x26\x9A\x9B\xBB\xAA\x62\x83\x4C\xB4\x06\x7A\x30\xC8\x29\xBF\xED\x06\x4D\x97\xB9\x1C\xC4\x31\x2B\xD5\x5F\xBC\x53\x12\x17\x9C\x99\x57\x29\x66\x77\x61\x21\x31\x07\x2E\x25\x49\x9D\x18\xF2\xEE\xF3\x2B\x71\x8C\xB5\xBA\x39\x07\x49\x77\xFC\xEF\x2E\x92\x90\x05\x8D\x2D\x2F\x77\x7B\xEF\x43\xBF\x35\xBB\x9A\xD8\xF9\x73\xA7\x2C\xF2\xD0\x57\xEE\x28\x4E\x26\x5F\x8F\x90\x68\x09\x2F\xB8\xF8\xDC\x06\xE9\x2E\x9A\x3E\x51\xA7\xD1\x22\xC4\x0A\xA7\x38\x48\x6C\xB3\xF9\xFF\x7D\xAB\x86\x57\xE3\xBA\xD6\x85\x78\x77\xBA\x43\xEA\x48\x7F\xF6\xD8\xBE\x23\x6D\x1E\xBF\xD1\x36\x6C\x58\x5C\xF1\xEE\xA4\x19\x54\x1A\xF5\x03\xD2\x76\xE6\xE1\x8C\xBD\x3C\xB3\xD3\x48\x4B\xE2\xC8\xF8\x7F\x92\xA8\x76\x46\x9C\x42\x65\x3E\xA4\x1E\xC1\x07\x03\x5A\x46\x2D\xB8\x97\xF3\xB7\xD5\xB2\x55\x21\xEF\xBA\xDC\x4C\x00\x97\xFB\x14\x95\x27\x33\xBF\xE8\x43\x47\x46\xD2\x08\x99\x16\x60\x3B\x9A\x7E\xD2\xE6\xED\x38\xEA\xEC\x01\x1E\x3C\x48\x56\x49\x09\xC7\x4C\x37\x00\x9E\x88\x0E\xC0\x73\xE1\x6F\x66\xE9\x72\x47\x30\x3E\x10\xE5\x0B\x03\xC9\x9A\x42\x00\x6C\xC5\x94\x7E\x61\xC4\x8A\xDF\x7F\x82\x1A\x0B\x59\xC4\x59\x32\x77\xB3\xBC\x60\x69\x56\x39\xFD\xB4\x06\x7B\x2C\xD6\x64\x36\xD9\xBD\x48\xED\x84\x1F\x7E\xA5\x22\x8F\x2A\xB8\x42\xF4\x82\xB7\xD4\x53\x90\x78\x4E\x2D\x1A\xFD\x81\x6F\x44\xD7\x3B\x01\x74\x96\x42\xE0\x00\xE2\x2E\x6B\xEA\xC5\xEE\x72\xAC\xBB\xBF\xFE\xEA\xAA\xA8\xF8\xDC\xF6\xB2\x79\x8A\xB6\x67\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9D\xC0\x67\xA6\x0C\x22\xD9\x26\xF5\x45\xAB\xA6\x65\x52\x11\x27\xD8\x45\xAC\x63\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x0C\x05\x00\x03\x82\x02\x01\x00\xB3\x57\x4D\x10\x62\x4E\x3A\xE4\xAC\xEA\xB8\x1C\xAF\x32\x23\xC8\xB3\x49\x5A\x51\x9C\x76\x28\x8D\x79\xAA\x57\x46\x17\xD5\xF5\x52\xF6\xB7\x44\xE8\x08\x44\xBF\x18\x84\xD2\x0B\x80\xCD\xC5\x12\xFD\x00\x55\x05\x61\x87\x41\xDC\xB5\x24\x9E\x3C\xC4\xD8\xC8\xFB\x70\x9E\x2F\x78\x96\x83\x20\x36\xDE\x7C\x0F\x69\x13\x88\xA5\x75\x36\x98\x08\xA6\xC6\xDF\xAC\xCE\xE3\x58\xD6\xB7\x3E\xDE\xBA\xF3\xEB\x34\x40\xD8\xA2\x81\xF5\x78\x3F\x2F\xD5\xA5\xFC\xD9\xA2\xD4\x5E\x04\x0E\x17\xAD\xFE\x41\xF0\xE5\xB2\x72\xFA\x44\x82\x33\x42\xE8\x2D\x58\xF7\x56\x8C\x62\x3F\xBA\x42\xB0\x9C\x0C\x5C\x7E\x2E\x65\x26\x5C\x53\x4F\x00\xB2\x78\x7E\xA1\x0D\x99\x2D\x8D\xB8\x1D\x8E\xA2\xC4\xB0\xFD\x60\xD0\x30\xA4\x8E\xC8\x04\x62\xA9\xC4\xED\x35\xDE\x7A\x97\xED\x0E\x38\x5E\x92\x2F\x93\x70\xA5\xA9\x9C\x6F\xA7\x7D\x13\x1D\x7E\xC6\x08\x48\xB1\x5E\x67\xEB\x51\x08\x25\xE9\xE6\x25\x6B\x52\x29\x91\x9C\xD2\x39\x73\x08\x57\xDE\x99\x06\xB4\x5B\x9D\x10\x06\xE1\xC2\x00\xA8\xB8\x1C\x4A\x02\x0A\x14\xD0\xC1\x41\xCA\xFB\x8C\x35\x21\x7D\x82\x38\xF2\xA9\x54\x91\x19\x35\x93\x94\x6D\x6A\x3A\xC5\xB2\xD0\xBB\x89\x86\x93\xE8\x9B\xC9\x0F\x3A\xA7\x7A\xB8\xA1\xF0\x78\x46\xFA\xFC\x37\x2F\xE5\x8A\x84\xF3\xDF\xFE\x04\xD9\xA1\x68\xA0\x2F\x24\xE2\x09\x95\x06\xD5\x95\xCA\xE1\x24\x96\xEB\x7C\xF6\x93\x05\xBB\xED\x73\xE9\x2D\xD1\x75\x39\xD7\xE7\x24\xDB\xD8\x4E\x5F\x43\x8F\x9E\xD0\x14\x39\xBF\x55\x70\x48\x99\x57\x31\xB4\x9C\xEE\x4A\x98\x03\x96\x30\x1F\x60\x06\xEE\x1B\x23\xFE\x81\x60\x23\x1A\x47\x62\x85\xA5\xCC\x19\x34\x80\x6F\xB3\xAC\x1A\xE3\x9F\xF0\x7B\x48\xAD\xD5\x01\xD9\x67\xB6\xA9\x72\x93\xEA\x2D\x66\xB5\xB2\xB8\xE4\x3D\x3C\xB2\xEF\x4C\x8C\xEA\xEB\x07\xBF\xAB\x35\x9A\x55\x86\xBC\x18\xA6\xB5\xA8\x5E\xB4\x83\x6C\x6B\x69\x40\xD3\x9F\xDC\xF1\xC3\x69\x6B\xB9\xE1\x6D\x09\xF4\xF1\xAA\x50\x76\x0A\x7A\x7D\x7A\x17\xA1\x55\x96\x42\x99\x31\x09\xDD\x60\x11\x8D\x05\x30\x7E\xE6\x8E\x46\xD1\x9D\x14\xDA\xC7\x17\xE4\x05\x96\x8C\xC4\x24\xB5\x1B\xCF\x14\x07\xB2\x40\xF8\xA3\x9E\x41\x86\xBC\x04\xD0\x6B\x96\xC8\x2A\x80\x34\xFD\xBF\xEF\x06\xA3\xDD\x58\xC5\x85\x3D\x3E\x8F\xFE\x9E\x29\xE0\xB6\xB8\x09\x68\x19\x1C\x18\x43", + ["CN=AffirmTrust Premium ECC,O=AffirmTrust,C=US"] = "\x30\x82\x01\xFE\x30\x82\x01\x85\xA0\x03\x02\x01\x02\x02\x08\x74\x97\x25\x8A\xC7\x3F\x7A\x54\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x0C\x17\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x50\x72\x65\x6D\x69\x75\x6D\x20\x45\x43\x43\x30\x1E\x17\x0D\x31\x30\x30\x31\x32\x39\x31\x34\x32\x30\x32\x34\x5A\x17\x0D\x34\x30\x31\x32\x33\x31\x31\x34\x32\x30\x32\x34\x5A\x30\x45\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x55\x53\x31\x14\x30\x12\x06\x03\x55\x04\x0A\x0C\x0B\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x31\x20\x30\x1E\x06\x03\x55\x04\x03\x0C\x17\x41\x66\x66\x69\x72\x6D\x54\x72\x75\x73\x74\x20\x50\x72\x65\x6D\x69\x75\x6D\x20\x45\x43\x43\x30\x76\x30\x10\x06\x07\x2A\x86\x48\xCE\x3D\x02\x01\x06\x05\x2B\x81\x04\x00\x22\x03\x62\x00\x04\x0D\x30\x5E\x1B\x15\x9D\x03\xD0\xA1\x79\x35\xB7\x3A\x3C\x92\x7A\xCA\x15\x1C\xCD\x62\xF3\x9C\x26\x5C\x07\x3D\xE5\x54\xFA\xA3\xD6\xCC\x12\xEA\xF4\x14\x5F\xE8\x8E\x19\xAB\x2F\x2E\x48\xE6\xAC\x18\x43\x78\xAC\xD0\x37\xC3\xBD\xB2\xCD\x2C\xE6\x47\xE2\x1A\xE6\x63\xB8\x3D\x2E\x2F\x78\xC4\x4F\xDB\xF4\x0F\xA4\x68\x4C\x55\x72\x6B\x95\x1D\x4E\x18\x42\x95\x78\xCC\x37\x3C\x91\xE2\x9B\x65\x2B\x29\xA3\x42\x30\x40\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x9A\xAF\x29\x7A\xC0\x11\x35\x35\x26\x51\x30\x00\xC3\x6A\xFE\x40\xD5\xAE\xD6\x3C\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0A\x06\x08\x2A\x86\x48\xCE\x3D\x04\x03\x03\x03\x67\x00\x30\x64\x02\x30\x17\x09\xF3\x87\x88\x50\x5A\xAF\xC8\xC0\x42\xBF\x47\x5F\xF5\x6C\x6A\x86\xE0\xC4\x27\x74\xE4\x38\x53\xD7\x05\x7F\x1B\x34\xE3\xC6\x2F\xB3\xCA\x09\x3C\x37\x9D\xD7\xE7\xB8\x46\xF1\xFD\xA1\xE2\x71\x02\x30\x42\x59\x87\x43\xD4\x51\xDF\xBA\xD3\x09\x32\x5A\xCE\x88\x7E\x57\x3D\x9C\x5F\x42\x6B\xF5\x07\x2D\xB5\xF0\x82\x93\xF9\x59\x6F\xAE\x64\xFA\x58\xE5\x8B\x1E\xE3\x63\xBE\xB5\x81\xCD\x6F\x02\x8C\x79", + ["CN=Certum Trusted Network CA,OU=Certum Certification Authority,O=Unizeto Technologies S.A.,C=PL"] = "\x30\x82\x03\xBB\x30\x82\x02\xA3\xA0\x03\x02\x01\x02\x02\x03\x04\x44\xC0\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x7E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x50\x4C\x31\x22\x30\x20\x06\x03\x55\x04\x0A\x13\x19\x55\x6E\x69\x7A\x65\x74\x6F\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x20\x53\x2E\x41\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x0B\x13\x1E\x43\x65\x72\x74\x75\x6D\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x43\x65\x72\x74\x75\x6D\x20\x54\x72\x75\x73\x74\x65\x64\x20\x4E\x65\x74\x77\x6F\x72\x6B\x20\x43\x41\x30\x1E\x17\x0D\x30\x38\x31\x30\x32\x32\x31\x32\x30\x37\x33\x37\x5A\x17\x0D\x32\x39\x31\x32\x33\x31\x31\x32\x30\x37\x33\x37\x5A\x30\x7E\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x50\x4C\x31\x22\x30\x20\x06\x03\x55\x04\x0A\x13\x19\x55\x6E\x69\x7A\x65\x74\x6F\x20\x54\x65\x63\x68\x6E\x6F\x6C\x6F\x67\x69\x65\x73\x20\x53\x2E\x41\x2E\x31\x27\x30\x25\x06\x03\x55\x04\x0B\x13\x1E\x43\x65\x72\x74\x75\x6D\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x31\x22\x30\x20\x06\x03\x55\x04\x03\x13\x19\x43\x65\x72\x74\x75\x6D\x20\x54\x72\x75\x73\x74\x65\x64\x20\x4E\x65\x74\x77\x6F\x72\x6B\x20\x43\x41\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\xE3\xFB\x7D\xA3\x72\xBA\xC2\xF0\xC9\x14\x87\xF5\x6B\x01\x4E\xE1\x6E\x40\x07\xBA\x6D\x27\x5D\x7F\xF7\x5B\x2D\xB3\x5A\xC7\x51\x5F\xAB\xA4\x32\xA6\x61\x87\xB6\x6E\x0F\x86\xD2\x30\x02\x97\xF8\xD7\x69\x57\xA1\x18\x39\x5D\x6A\x64\x79\xC6\x01\x59\xAC\x3C\x31\x4A\x38\x7C\xD2\x04\xD2\x4B\x28\xE8\x20\x5F\x3B\x07\xA2\xCC\x4D\x73\xDB\xF3\xAE\x4F\xC7\x56\xD5\x5A\xA7\x96\x89\xFA\xF3\xAB\x68\xD4\x23\x86\x59\x27\xCF\x09\x27\xBC\xAC\x6E\x72\x83\x1C\x30\x72\xDF\xE0\xA2\xE9\xD2\xE1\x74\x75\x19\xBD\x2A\x9E\x7B\x15\x54\x04\x1B\xD7\x43\x39\xAD\x55\x28\xC5\xE2\x1A\xBB\xF4\xC0\xE4\xAE\x38\x49\x33\xCC\x76\x85\x9F\x39\x45\xD2\xA4\x9E\xF2\x12\x8C\x51\xF8\x7C\xE4\x2D\x7F\xF5\xAC\x5F\xEB\x16\x9F\xB1\x2D\xD1\xBA\xCC\x91\x42\x77\x4C\x25\xC9\x90\x38\x6F\xDB\xF0\xCC\xFB\x8E\x1E\x97\x59\x3E\xD5\x60\x4E\xE6\x05\x28\xED\x49\x79\x13\x4B\xBA\x48\xDB\x2F\xF9\x72\xD3\x39\xCA\xFE\x1F\xD8\x34\x72\xF5\xB4\x40\xCF\x31\x01\xC3\xEC\xDE\x11\x2D\x17\x5D\x1F\xB8\x50\xD1\x5E\x19\xA7\x69\xDE\x07\x33\x28\xCA\x50\x95\xF9\xA7\x54\xCB\x54\x86\x50\x45\xA9\xF9\x49\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x08\x76\xCD\xCB\x07\xFF\x24\xF6\xC5\xCD\xED\xBB\x90\xBC\xE2\x84\x37\x46\x75\xF7\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\xA6\xA8\xAD\x22\xCE\x01\x3D\xA6\xA3\xFF\x62\xD0\x48\x9D\x8B\x5E\x72\xB0\x78\x44\xE3\xDC\x1C\xAF\x09\xFD\x23\x48\xFA\xBD\x2A\xC4\xB9\x55\x04\xB5\x10\xA3\x8D\x27\xDE\x0B\x82\x63\xD0\xEE\xDE\x0C\x37\x79\x41\x5B\x22\xB2\xB0\x9A\x41\x5C\xA6\x70\xE0\xD4\xD0\x77\xCB\x23\xD3\x00\xE0\x6C\x56\x2F\xE1\x69\x0D\x0D\xD9\xAA\xBF\x21\x81\x50\xD9\x06\xA5\xA8\xFF\x95\x37\xD0\xAA\xFE\xE2\xB3\xF5\x99\x2D\x45\x84\x8A\xE5\x42\x09\xD7\x74\x02\x2F\xF7\x89\xD8\x99\xE9\xBC\x27\xD4\x47\x8D\xBA\x0D\x46\x1C\x77\xCF\x14\xA4\x1C\xB9\xA4\x31\xC4\x9C\x28\x74\x03\x34\xFF\x33\x19\x26\xA5\xE9\x0D\x74\xB7\x3E\x97\xC6\x76\xE8\x27\x96\xA3\x66\xDD\xE1\xAE\xF2\x41\x5B\xCA\x98\x56\x83\x73\x70\xE4\x86\x1A\xD2\x31\x41\xBA\x2F\xBE\x2D\x13\x5A\x76\x6F\x4E\xE8\x4E\x81\x0E\x3F\x5B\x03\x22\xA0\x12\xBE\x66\x58\x11\x4A\xCB\x03\xC4\xB4\x2A\x2A\x2D\x96\x17\xE0\x39\x54\xBC\x48\xD3\x76\x27\x9D\x9A\x2D\x06\xA6\xC9\xEC\x39\xD2\xAB\xDB\x9F\x9A\x0B\x27\x02\x35\x29\xB1\x40\x95\xE7\xF9\xE8\x9C\x55\x88\x19\x46\xD6\xB7\x34\xF5\x7E\xCE\x39\x9A\xD9\x38\xF1\x51\xF7\x4F\x2C", + ["CN=Certinomis - Autorit\C3\A9 Racine,OU=0002 433998903,O=Certinomis,C=FR"] = "\x30\x82\x05\x9C\x30\x82\x03\x84\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x43\x65\x72\x74\x69\x6E\x6F\x6D\x69\x73\x31\x17\x30\x15\x06\x03\x55\x04\x0B\x13\x0E\x30\x30\x30\x32\x20\x34\x33\x33\x39\x39\x38\x39\x30\x33\x31\x26\x30\x24\x06\x03\x55\x04\x03\x0C\x1D\x43\x65\x72\x74\x69\x6E\x6F\x6D\x69\x73\x20\x2D\x20\x41\x75\x74\x6F\x72\x69\x74\xC3\xA9\x20\x52\x61\x63\x69\x6E\x65\x30\x1E\x17\x0D\x30\x38\x30\x39\x31\x37\x30\x38\x32\x38\x35\x39\x5A\x17\x0D\x32\x38\x30\x39\x31\x37\x30\x38\x32\x38\x35\x39\x5A\x30\x63\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x46\x52\x31\x13\x30\x11\x06\x03\x55\x04\x0A\x13\x0A\x43\x65\x72\x74\x69\x6E\x6F\x6D\x69\x73\x31\x17\x30\x15\x06\x03\x55\x04\x0B\x13\x0E\x30\x30\x30\x32\x20\x34\x33\x33\x39\x39\x38\x39\x30\x33\x31\x26\x30\x24\x06\x03\x55\x04\x03\x0C\x1D\x43\x65\x72\x74\x69\x6E\x6F\x6D\x69\x73\x20\x2D\x20\x41\x75\x74\x6F\x72\x69\x74\xC3\xA9\x20\x52\x61\x63\x69\x6E\x65\x30\x82\x02\x22\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01\x05\x00\x03\x82\x02\x0F\x00\x30\x82\x02\x0A\x02\x82\x02\x01\x00\x9D\x85\x9F\x86\xD3\xE3\xAF\xC7\xB2\x6B\x6E\x33\xE0\x9E\xB7\x42\x34\x55\x9D\xF9\x81\xBE\x63\xD8\x23\x76\x0E\x97\x54\xCD\x99\x4C\x1A\xF1\x39\xC7\x88\xD8\x17\x50\x0C\x9E\x61\xDA\xC0\x4E\x55\xDE\xE7\x5A\xB8\x7A\x4E\x77\x87\x0D\xE5\xB8\xEB\xFA\x9E\x5E\x7B\x1E\xC4\xCF\x28\x74\xC7\x93\xF5\x14\xC6\x22\x28\x04\xF9\x91\xC3\xAB\x27\x73\x6A\x0E\x2E\x4D\xF3\x2E\x28\x1F\x70\xDF\x55\x2F\x4E\xED\xC7\x71\x6F\x09\x72\x2E\xED\xD5\x32\x97\xD0\xF1\x58\x77\xD1\x60\xBC\x4E\x5E\xDB\x9A\x84\xF6\x47\x61\x45\x2B\xF6\x50\xA6\x7F\x6A\x71\x27\x48\x84\x35\x9E\xAC\xFE\x69\xA9\x9E\x7A\x5E\x35\x25\xFA\xB4\xA7\x49\x35\x77\x96\xA7\x36\x5B\xE1\xCD\xDF\x23\x70\xD8\x5D\x4C\xA5\x08\x83\xF1\xA6\x24\x38\x13\xA8\xEC\x2F\xA8\xA1\x67\xC7\xA6\x2D\x86\x47\xEE\x8A\xFC\xEC\x9B\x0E\x74\xF4\x2B\x49\x02\x7B\x90\x75\x8C\xFC\x99\x39\x01\x39\xD6\x4A\x89\xE5\x9E\x76\xAB\x3E\x96\x28\x38\x26\x8B\xDD\x8D\x8C\xC0\xF6\x01\x1E\x6F\xA5\x31\x12\x38\x7D\x95\xC2\x71\xEE\xED\x74\xAE\xE4\x36\xA2\x43\x75\xD5\xF1\x00\x9B\xE2\xE4\xD7\xCC\x42\x03\x4B\x78\x7A\xE5\x7D\xBB\xB8\xAE\x2E\x20\x93\xD3\xE4\x61\xDF\x71\xE1\x76\x67\x97\x3F\xB6\xDF\x6A\x73\x5A\x64\x22\xE5\x42\xDB\xCF\x81\x03\x93\xD8\xF4\xE3\x10\xE0\x72\xF6\x00\x70\xAC\xF0\xC1\x7A\x0F\x05\x7F\xCF\x34\x69\x45\xB5\x93\xE4\x19\xDB\x52\x16\x23\x05\x89\x0E\x8D\x48\xE4\x25\x6F\xB3\x78\xBF\x62\xF5\x07\xFA\x95\x24\xC2\x96\xB2\xE8\xA3\x23\xC2\x5D\x03\xFC\xC3\xD3\xE5\x7C\xC9\x75\x23\xD7\xF4\xF5\xBC\xDE\xE4\xDF\xCD\x80\xBF\x91\x88\x7D\xA7\x13\xB4\x39\xBA\x2C\xBA\xBD\xD1\x6B\xCC\xF3\xA5\x28\xED\x44\x9E\x7D\x52\xA3\x6F\x96\x2E\x19\x7E\x1C\xF3\x5B\xC7\x16\x8E\xBB\x60\x7D\x77\x66\x47\x54\x82\x00\x11\x60\x6C\x32\xC1\xA8\x38\x1B\xEB\x6E\x98\x13\xD6\xEE\x38\xF5\xF0\x9F\x0E\xEF\xFE\x31\x81\xC1\xD2\x24\x95\x2F\x53\x7A\x69\xA2\xF0\x0F\x86\x45\x8E\x58\x82\x2B\x4C\x22\xD4\x5E\xA0\xE7\x7D\x26\x27\x48\xDF\x25\x46\x8D\x4A\x28\x7C\x86\x9E\xF9\x9B\x1A\x59\xB9\x65\xBF\x05\xDD\xB6\x42\x5D\x3D\xE6\x00\x48\x82\x5E\x20\xF7\x11\x82\xDE\xCA\xD8\x9F\xE6\x37\x47\x26\x1E\xEB\x78\xF7\x61\xC3\x41\x64\x58\x02\x41\xF9\xDA\xE0\xD1\xF8\xF9\xE8\xFD\x52\x38\xB6\xF5\x89\xDF\x02\x03\x01\x00\x01\xA3\x5B\x30\x59\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x0D\x8C\xB6\x61\xDA\x44\xB8\xD1\x14\x7D\xC3\xBE\x7D\x5E\x48\xF0\xCE\xCA\x6A\xB0\x30\x17\x06\x03\x55\x1D\x20\x04\x10\x30\x0E\x30\x0C\x06\x0A\x2A\x81\x7A\x01\x56\x02\x02\x00\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x02\x01\x00\x24\x3E\x60\x06\x7E\x1D\xEF\x3A\x3E\xDB\xEA\xAF\x1C\x9A\x2C\x01\x0B\xF4\xC5\xB5\xD9\x49\x31\xF4\x5D\x41\x8D\x89\x0C\x4E\xFF\x6C\xA2\xFD\xFF\xE2\x06\xC8\x39\x9F\xF1\x5A\xA9\xDD\x22\x58\x15\xA8\x8A\xD3\xB1\xE6\x32\x09\x82\x03\x6C\xD7\x3F\x08\xC7\xF8\xB9\xBA\x00\x6D\xB9\xD6\xFC\x52\x32\x5D\xA4\x7F\xA4\x31\x94\xBB\xB6\x4C\x38\x7F\x28\x30\x35\xFF\x9F\x23\x53\xB7\xB6\xEE\x14\x70\x00\x40\x2B\xDA\x47\xAB\x34\x7E\x5E\xA7\x56\x30\x61\x2B\x8B\x43\xAC\xFD\xB6\x88\x28\xF5\x6B\xB6\x3E\x60\x4A\xBA\x42\x90\x34\x67\x8D\xEA\xEB\x5F\x45\x54\x3B\x17\xAC\x8B\xE4\xC6\x65\x0F\xEE\xD0\x8C\x5D\x66\x39\xCE\x32\xA7\xD8\x10\x97\xC0\x7E\x34\x9C\x9F\x94\xF3\xF6\x86\x1F\xCF\x1B\x73\xAD\x94\x79\x87\x68\x70\xC3\x33\xA5\x70\xE7\xD8\xD5\x38\x94\x6F\x63\x79\xEB\xBF\x0A\x0E\x08\xE7\xC5\x2F\x0F\x42\xA0\x2B\x14\x40\xFF\x21\xE0\x05\xC5\x27\xE1\x84\x11\x13\xBA\xD6\x86\x1D\x41\x0B\x13\x23\x89\xD3\xC9\x0B\xE8\x8A\xBA\x7A\xA3\xA3\x73\x37\x35\x80\x7D\x12\xB8\x33\x77\x40\x38\xC0\xFA\x5E\x30\xD2\xF2\xB6\xA3\xB1\xD6\xA2\x95\x97\x81\x9B\x52\xED\x69\x4C\xFF\x80\xE4\x53\xDB\x54\x5B\x03\x6D\x54\x5F\xB1\xB8\xEF\x24\xBD\x6F\x9F\x11\xC3\xC7\x64\xC2\x0F\x28\x62\x85\x66\x5E\x1A\x7B\xB2\xB7\xEF\xAE\x35\xC9\x19\x33\xA8\xB8\x27\xDB\x33\x55\xBF\x68\xE1\x75\x48\x44\x56\xFB\xCD\xD3\x48\xBB\x47\x89\x3A\xAC\x69\xF5\x80\xC6\xE4\x44\x50\x2F\x54\xC4\xAA\x43\xC5\x31\x31\x58\xBD\x96\xC5\xEA\x75\x6C\x9A\x75\xB1\x4D\xF8\xF7\x97\xFF\x96\x16\xF2\x97\x4D\xE8\xF6\xF3\x11\xF9\x3A\x7D\x8A\x38\x6E\x04\xCB\xE1\xD3\x45\x15\xAA\xA5\xD1\x1D\x9D\x5D\x63\xE8\x24\xE6\x36\x14\xE2\x87\xAD\x1B\x59\xF5\x44\x9B\xFB\xD7\x77\x7C\x1F\x01\x70\x62\xA1\x20\x1A\xA2\xC5\x1A\x28\xF4\x21\x03\xEE\x2E\xD9\xC1\x80\xEA\xB9\xD9\x82\xD6\x5B\x76\xC2\xCB\x3B\xB5\xD2\x00\xF0\xA3\x0E\xE1\xAD\x6E\x40\xF7\xDB\xA0\xB4\xD0\x46\xAE\x15\xD7\x44\xC2\x4D\x35\xF9\xD2\x0B\xF2\x17\xF6\xAC\x66\xD5\x24\xB2\x4F\xD1\x1C\x99\xC0\x6E\xF5\x7D\xEB\x74\x04\xB8\xF9\x4D\x77\x09\xD7\xB4\xCF\x07\x30\x09\xF1\xB8\x00\x56\xD9\x17\x16\x16\x0A\x2B\x86\xDF\x8F\x01\x19\x1A\xE5\xBB\x82\x63\xFF\xBE\x0B\x76\x16\x5E\x37\x37\xE6\xD8\x74\x97\xA2\x99\x45\x79", + ["CN=Root CA Generalitat Valenciana,OU=PKIGVA,O=Generalitat Valenciana,C=ES"] = "\x30\x82\x06\x8B\x30\x82\x05\x73\xA0\x03\x02\x01\x02\x02\x04\x3B\x45\xE5\x68\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x68\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x1F\x30\x1D\x06\x03\x55\x04\x0A\x13\x16\x47\x65\x6E\x65\x72\x61\x6C\x69\x74\x61\x74\x20\x56\x61\x6C\x65\x6E\x63\x69\x61\x6E\x61\x31\x0F\x30\x0D\x06\x03\x55\x04\x0B\x13\x06\x50\x4B\x49\x47\x56\x41\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x52\x6F\x6F\x74\x20\x43\x41\x20\x47\x65\x6E\x65\x72\x61\x6C\x69\x74\x61\x74\x20\x56\x61\x6C\x65\x6E\x63\x69\x61\x6E\x61\x30\x1E\x17\x0D\x30\x31\x30\x37\x30\x36\x31\x36\x32\x32\x34\x37\x5A\x17\x0D\x32\x31\x30\x37\x30\x31\x31\x35\x32\x32\x34\x37\x5A\x30\x68\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x1F\x30\x1D\x06\x03\x55\x04\x0A\x13\x16\x47\x65\x6E\x65\x72\x61\x6C\x69\x74\x61\x74\x20\x56\x61\x6C\x65\x6E\x63\x69\x61\x6E\x61\x31\x0F\x30\x0D\x06\x03\x55\x04\x0B\x13\x06\x50\x4B\x49\x47\x56\x41\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x52\x6F\x6F\x74\x20\x43\x41\x20\x47\x65\x6E\x65\x72\x61\x6C\x69\x74\x61\x74\x20\x56\x61\x6C\x65\x6E\x63\x69\x61\x6E\x61\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\xC6\x2A\xAB\x57\x11\x37\x2F\x22\x8A\xCA\x03\x74\x1D\xCA\xED\x2D\xA2\x0B\xBC\x33\x52\x40\x26\x47\xBE\x5A\x69\xA6\x3B\x72\x36\x17\x4C\xE8\xDF\xB8\xBB\x2F\x76\xE1\x40\x46\x74\x65\x02\x90\x52\x08\xB4\xFF\xA8\x8C\xC1\xE0\xC7\x89\x56\x10\x39\x33\xEF\x68\xB4\x5F\x5F\xDA\x6D\x23\xA1\x89\x5E\x22\xA3\x4A\x06\xF0\x27\xF0\x57\xB9\xF8\xE9\x4E\x32\x77\x0A\x3F\x41\x64\xF3\xEB\x65\xEE\x76\xFE\x54\xAA\x7D\x1D\x20\xAE\xF3\xD7\x74\xC2\x0A\x5F\xF5\x08\x28\x52\x08\xCC\x55\x5D\xD2\x0F\xDB\x9A\x81\xA5\xBB\xA1\xB3\xC1\x94\xCD\x54\xE0\x32\x75\x31\x91\x1A\x62\xB2\xDE\x75\xE2\xCF\x4F\x89\xD9\x91\x90\x0F\x41\x1B\xB4\x5A\x4A\x77\xBD\x67\x83\xE0\x93\xE7\x5E\xA7\x0C\xE7\x81\xD3\xF4\x52\xAC\x53\xB2\x03\xC7\x44\x26\xFB\x79\xE5\xCB\x34\x60\x50\x10\x7B\x1B\xDB\x6B\xD7\x47\xAB\x5F\x7C\x68\xCA\x6E\x9D\x41\x03\x10\xEE\x6B\x99\x7B\x5E\x25\xA8\xC2\xAB\xE4\xC0\xF3\x5C\x9C\xE3\xBE\xCE\x31\x4C\x64\x1E\x5E\x80\xA2\xF5\x83\x7E\x0C\xD6\xCA\x8C\x55\x8E\xBE\xE0\xBE\x49\x07\x0F\xA3\x24\x41\x7A\x58\x1D\x84\xEA\x58\x12\xC8\xE1\xB7\xED\xEF\x93\xDE\x94\x08\x31\x02\x03\x01\x00\x01\xA3\x82\x03\x3B\x30\x82\x03\x37\x30\x32\x06\x08\x2B\x06\x01\x05\x05\x07\x01\x01\x04\x26\x30\x24\x30\x22\x06\x08\x2B\x06\x01\x05\x05\x07\x30\x01\x86\x16\x68\x74\x74\x70\x3A\x2F\x2F\x6F\x63\x73\x70\x2E\x70\x6B\x69\x2E\x67\x76\x61\x2E\x65\x73\x30\x12\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x08\x30\x06\x01\x01\xFF\x02\x01\x02\x30\x82\x02\x34\x06\x03\x55\x1D\x20\x04\x82\x02\x2B\x30\x82\x02\x27\x30\x82\x02\x23\x06\x0A\x2B\x06\x01\x04\x01\xBF\x55\x02\x01\x00\x30\x82\x02\x13\x30\x82\x01\xE8\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x02\x30\x82\x01\xDA\x1E\x82\x01\xD6\x00\x41\x00\x75\x00\x74\x00\x6F\x00\x72\x00\x69\x00\x64\x00\x61\x00\x64\x00\x20\x00\x64\x00\x65\x00\x20\x00\x43\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x63\x00\x61\x00\x63\x00\x69\x00\xF3\x00\x6E\x00\x20\x00\x52\x00\x61\x00\xED\x00\x7A\x00\x20\x00\x64\x00\x65\x00\x20\x00\x6C\x00\x61\x00\x20\x00\x47\x00\x65\x00\x6E\x00\x65\x00\x72\x00\x61\x00\x6C\x00\x69\x00\x74\x00\x61\x00\x74\x00\x20\x00\x56\x00\x61\x00\x6C\x00\x65\x00\x6E\x00\x63\x00\x69\x00\x61\x00\x6E\x00\x61\x00\x2E\x00\x0D\x00\x0A\x00\x4C\x00\x61\x00\x20\x00\x44\x00\x65\x00\x63\x00\x6C\x00\x61\x00\x72\x00\x61\x00\x63\x00\x69\x00\xF3\x00\x6E\x00\x20\x00\x64\x00\x65\x00\x20\x00\x50\x00\x72\x00\xE1\x00\x63\x00\x74\x00\x69\x00\x63\x00\x61\x00\x73\x00\x20\x00\x64\x00\x65\x00\x20\x00\x43\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x63\x00\x61\x00\x63\x00\x69\x00\xF3\x00\x6E\x00\x20\x00\x71\x00\x75\x00\x65\x00\x20\x00\x72\x00\x69\x00\x67\x00\x65\x00\x20\x00\x65\x00\x6C\x00\x20\x00\x66\x00\x75\x00\x6E\x00\x63\x00\x69\x00\x6F\x00\x6E\x00\x61\x00\x6D\x00\x69\x00\x65\x00\x6E\x00\x74\x00\x6F\x00\x20\x00\x64\x00\x65\x00\x20\x00\x6C\x00\x61\x00\x20\x00\x70\x00\x72\x00\x65\x00\x73\x00\x65\x00\x6E\x00\x74\x00\x65\x00\x20\x00\x41\x00\x75\x00\x74\x00\x6F\x00\x72\x00\x69\x00\x64\x00\x61\x00\x64\x00\x20\x00\x64\x00\x65\x00\x20\x00\x43\x00\x65\x00\x72\x00\x74\x00\x69\x00\x66\x00\x69\x00\x63\x00\x61\x00\x63\x00\x69\x00\xF3\x00\x6E\x00\x20\x00\x73\x00\x65\x00\x20\x00\x65\x00\x6E\x00\x63\x00\x75\x00\x65\x00\x6E\x00\x74\x00\x72\x00\x61\x00\x20\x00\x65\x00\x6E\x00\x20\x00\x6C\x00\x61\x00\x20\x00\x64\x00\x69\x00\x72\x00\x65\x00\x63\x00\x63\x00\x69\x00\xF3\x00\x6E\x00\x20\x00\x77\x00\x65\x00\x62\x00\x20\x00\x68\x00\x74\x00\x74\x00\x70\x00\x3A\x00\x2F\x00\x2F\x00\x77\x00\x77\x00\x77\x00\x2E\x00\x70\x00\x6B\x00\x69\x00\x2E\x00\x67\x00\x76\x00\x61\x00\x2E\x00\x65\x00\x73\x00\x2F\x00\x63\x00\x70\x00\x73\x30\x25\x06\x08\x2B\x06\x01\x05\x05\x07\x02\x01\x16\x19\x68\x74\x74\x70\x3A\x2F\x2F\x77\x77\x77\x2E\x70\x6B\x69\x2E\x67\x76\x61\x2E\x65\x73\x2F\x63\x70\x73\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x7B\x35\xD3\x40\xD2\x1C\x78\x19\x66\xEF\x74\x10\x28\xDC\x3E\x4F\xB2\x78\x04\xFC\x30\x81\x95\x06\x03\x55\x1D\x23\x04\x81\x8D\x30\x81\x8A\x80\x14\x7B\x35\xD3\x40\xD2\x1C\x78\x19\x66\xEF\x74\x10\x28\xDC\x3E\x4F\xB2\x78\x04\xFC\xA1\x6C\xA4\x6A\x30\x68\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x45\x53\x31\x1F\x30\x1D\x06\x03\x55\x04\x0A\x13\x16\x47\x65\x6E\x65\x72\x61\x6C\x69\x74\x61\x74\x20\x56\x61\x6C\x65\x6E\x63\x69\x61\x6E\x61\x31\x0F\x30\x0D\x06\x03\x55\x04\x0B\x13\x06\x50\x4B\x49\x47\x56\x41\x31\x27\x30\x25\x06\x03\x55\x04\x03\x13\x1E\x52\x6F\x6F\x74\x20\x43\x41\x20\x47\x65\x6E\x65\x72\x61\x6C\x69\x74\x61\x74\x20\x56\x61\x6C\x65\x6E\x63\x69\x61\x6E\x61\x82\x04\x3B\x45\xE5\x68\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x24\x61\x4E\xF5\xB5\xC8\x42\x02\x2A\xB3\x5C\x75\xAD\xC5\x6D\xCA\xE7\x94\x3F\xA5\x68\x95\x88\xC1\x54\xC0\x10\x69\xA2\x12\x2F\x18\x3F\x25\x50\xA8\x7C\x4A\xEA\xC6\x09\xD9\xF4\x75\xC6\x40\xDA\xAF\x50\x9D\x3D\xA5\x16\xBB\x6D\x31\xC6\xC7\x73\x0A\x48\xFE\x20\x72\xED\x6F\xCC\xE8\x83\x61\x16\x46\x90\x01\x95\x4B\x7D\x8E\x9A\x52\x09\x2F\xF6\x6F\x1C\xE4\xA1\x71\xCF\x8C\x2A\x5A\x17\x73\x83\x47\x4D\x0F\x36\xFB\x04\x4D\x49\x51\xE2\x14\xC9\x64\x61\xFB\xD4\x14\xE0\xF4\x9E\xB7\x34\x8F\x0A\x26\xBD\x97\x5C\xF4\x79\x3A\x4A\x30\x19\xCC\xAD\x4F\xA0\x98\x8A\xB4\x31\x97\x2A\xE2\x73\x6D\x7E\x78\xB8\xF8\x88\x89\x4F\xB1\x22\x91\x64\x4B\xF5\x50\xDE\x03\xDB\xE5\xC5\x76\xE7\x13\x66\x75\x7E\x65\xFB\x01\x9F\x93\x87\x88\x9D\xF9\x46\x57\x7C\x4D\x60\xAF\x98\x73\x13\x23\xA4\x20\x91\x81\xFA\xD0\x61\x66\xB8\x7D\xD1\xAF\xD6\x6F\x1E\x6C\x3D\xE9\x11\xFD\xA9\xF9\x82\x22\x86\x99\x33\x71\x5A\xEA\x19\x57\x3D\x91\xCD\xA9\xC0\xA3\x6E\x07\x13\xA6\xC9\xED\xF8\x68\xA3\x9E\xC3\x5A\x72\x09\x87\x28\xD1\xC4\x73\xC4\x73\x18\x5F\x50\x75\x16\x31\x9F\xB7\xE8\x7C\xC3", + ["CN=A-Trust-nQual-03,OU=A-Trust-nQual-03,O=A-Trust Ges. f. Sicherheitssysteme im elektr. Datenverkehr GmbH,C=AT"] = "\x30\x82\x03\xCF\x30\x82\x02\xB7\xA0\x03\x02\x01\x02\x02\x03\x01\x6C\x1E\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x81\x8D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x48\x30\x46\x06\x03\x55\x04\x0A\x0C\x3F\x41\x2D\x54\x72\x75\x73\x74\x20\x47\x65\x73\x2E\x20\x66\x2E\x20\x53\x69\x63\x68\x65\x72\x68\x65\x69\x74\x73\x73\x79\x73\x74\x65\x6D\x65\x20\x69\x6D\x20\x65\x6C\x65\x6B\x74\x72\x2E\x20\x44\x61\x74\x65\x6E\x76\x65\x72\x6B\x65\x68\x72\x20\x47\x6D\x62\x48\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x0C\x10\x41\x2D\x54\x72\x75\x73\x74\x2D\x6E\x51\x75\x61\x6C\x2D\x30\x33\x31\x19\x30\x17\x06\x03\x55\x04\x03\x0C\x10\x41\x2D\x54\x72\x75\x73\x74\x2D\x6E\x51\x75\x61\x6C\x2D\x30\x33\x30\x1E\x17\x0D\x30\x35\x30\x38\x31\x37\x32\x32\x30\x30\x30\x30\x5A\x17\x0D\x31\x35\x30\x38\x31\x37\x32\x32\x30\x30\x30\x30\x5A\x30\x81\x8D\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x41\x54\x31\x48\x30\x46\x06\x03\x55\x04\x0A\x0C\x3F\x41\x2D\x54\x72\x75\x73\x74\x20\x47\x65\x73\x2E\x20\x66\x2E\x20\x53\x69\x63\x68\x65\x72\x68\x65\x69\x74\x73\x73\x79\x73\x74\x65\x6D\x65\x20\x69\x6D\x20\x65\x6C\x65\x6B\x74\x72\x2E\x20\x44\x61\x74\x65\x6E\x76\x65\x72\x6B\x65\x68\x72\x20\x47\x6D\x62\x48\x31\x19\x30\x17\x06\x03\x55\x04\x0B\x0C\x10\x41\x2D\x54\x72\x75\x73\x74\x2D\x6E\x51\x75\x61\x6C\x2D\x30\x33\x31\x19\x30\x17\x06\x03\x55\x04\x03\x0C\x10\x41\x2D\x54\x72\x75\x73\x74\x2D\x6E\x51\x75\x61\x6C\x2D\x30\x33\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\xAD\x3D\x61\x6E\x03\xF3\x90\x3B\xC0\x41\x0B\x84\x80\xCD\xEC\x2A\xA3\x9D\x6B\xBB\x6E\xC2\x42\x84\xF7\x51\x14\xE1\xA0\xA8\x2D\x51\xA3\x51\xF2\xDE\x23\xF0\x34\x44\xFF\x94\xEB\xCC\x05\x23\x95\x40\xB9\x07\x78\xA5\x25\xF6\x0A\xBD\x45\x86\xE8\xD9\xBD\xC0\x04\x8E\x85\x44\x61\xEF\x7F\xA7\xC9\xFA\xC1\x25\xCC\x85\x2C\x63\x3F\x05\x60\x73\x49\x05\xE0\x60\x78\x95\x10\x4B\xDC\xF9\x11\x59\xCE\x71\x7F\x40\x9B\x8A\xAA\x24\xDF\x0B\x42\xE2\xDB\x56\xBC\x4A\xD2\xA5\x0C\x9B\xB7\x43\x3E\xDD\x83\xD3\x26\x10\x02\xCF\xEA\x23\xC4\x49\x4E\xE5\xD3\xE9\xB4\x88\xAB\x0C\xAE\x62\x92\xD4\x65\x87\xD9\x6A\xD7\xF4\x85\x9F\xE4\x33\x22\x25\xA5\xE5\xC8\x33\xBA\xC3\xC7\x41\xDC\x5F\xC6\x6A\xCC\x00\x0E\x6D\x32\xA8\xB6\x87\x36\x00\x62\x77\x9B\x1E\x1F\x34\xCB\x90\x3C\x78\x88\x74\x05\xEB\x79\xF5\x93\x71\x65\xCA\x9D\xC7\x6B\x18\x2D\x3D\x5C\x4E\xE7\xD5\xF8\x3F\x31\x7D\x8F\x87\xEC\x0A\x22\x2F\x23\xE9\xFE\xBB\x7D\xC9\xE0\xF4\xEC\xEB\x7C\xC4\xB0\xC3\x2D\x62\xB5\x9A\x71\xD6\xB1\x6A\xE8\xEC\xD9\xED\xD5\x72\xEC\xBE\x57\x01\xCE\x05\x55\x9F\xDE\xD1\x60\x88\x10\xB3\x02\x03\x01\x00\x01\xA3\x36\x30\x34\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x11\x06\x03\x55\x1D\x0E\x04\x0A\x04\x08\x44\x6A\x95\x67\x55\x79\x11\x4F\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x55\xD4\x54\xD1\x59\x48\x5C\xB3\x93\x85\xAA\xBF\x63\x2F\xE4\x80\xCE\x34\xA3\x34\x62\x3E\xF6\xD8\xEE\x67\x88\x31\x04\x03\x6F\x0B\xD4\x07\xFB\x4E\x75\x0F\xD3\x2E\xD3\xC0\x17\xC7\xC6\x28\xEC\x06\x0D\x11\x24\x0E\x0E\xA5\x5D\xBF\x8C\xB2\x13\x96\x71\xDC\xD4\xCE\x0E\x0D\x0A\x68\x32\x6C\xB9\x41\x31\x19\xAB\xB1\x07\x7B\x4D\x98\xD3\x5C\xB0\xD1\xF0\xA7\x42\xA0\xB5\xC4\x8E\xAF\xFE\xF1\x3F\xF4\xEF\x4F\x46\x00\x76\xEB\x02\xFB\xF9\x9D\xD2\x40\x96\xC7\x88\x3A\xB8\x9F\x11\x79\xF3\x80\x65\xA8\xBD\x1F\xD3\x78\x81\xA0\x51\x4C\x37\xB4\xA6\x5D\x25\x70\xD1\x66\xC9\x68\xF9\x2E\x11\x14\x68\xF1\x54\x98\x08\xAC\x26\x92\x0F\xDE\x89\x9E\xD4\xFA\xB3\x79\x2B\xD2\xA3\x79\xD4\xEC\x8B\xAC\x87\x53\x68\x42\x4C\x51\x51\x74\x1E\x1B\x27\x2E\xE3\xF5\x1F\x29\x74\x4D\xED\xAF\xF7\xE1\x92\x99\x81\xE8\xBE\x3A\xC7\x17\x50\xF6\xB7\xC6\xFC\x9B\xB0\x8A\x6B\xD6\x88\x03\x91\x8F\x06\x77\x3A\x85\x02\xDD\x98\xD5\x43\x78\x3F\xC6\x30\x15\xAC\x9B\x6B\xCB\x57\xB7\x89\x51\x8B\x3A\xE8\xC9\x84\x0C\xDB\xB1\x50\x20\x0A\x1A\x4A\xBA\x6A\x1A\xBD\xEC\x1B\xC8\xC5\x84\x9A\xCD", + ["CN=TWCA Root Certification Authority,OU=Root CA,O=TAIWAN-CA,C=TW"] = "\x30\x82\x03\x7B\x30\x82\x02\x63\xA0\x03\x02\x01\x02\x02\x01\x01\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x30\x5F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x0C\x09\x54\x41\x49\x57\x41\x4E\x2D\x43\x41\x31\x10\x30\x0E\x06\x03\x55\x04\x0B\x0C\x07\x52\x6F\x6F\x74\x20\x43\x41\x31\x2A\x30\x28\x06\x03\x55\x04\x03\x0C\x21\x54\x57\x43\x41\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\x30\x1E\x17\x0D\x30\x38\x30\x38\x32\x38\x30\x37\x32\x34\x33\x33\x5A\x17\x0D\x33\x30\x31\x32\x33\x31\x31\x35\x35\x39\x35\x39\x5A\x30\x5F\x31\x0B\x30\x09\x06\x03\x55\x04\x06\x13\x02\x54\x57\x31\x12\x30\x10\x06\x03\x55\x04\x0A\x0C\x09\x54\x41\x49\x57\x41\x4E\x2D\x43\x41\x31\x10\x30\x0E\x06\x03\x55\x04\x0B\x0C\x07\x52\x6F\x6F\x74\x20\x43\x41\x31\x2A\x30\x28\x06\x03\x55\x04\x03\x0C\x21\x54\x57\x43\x41\x20\x52\x6F\x6F\x74\x20\x43\x65\x72\x74\x69\x66\x69\x63\x61\x74\x69\x6F\x6E\x20\x41\x75\x74\x68\x6F\x72\x69\x74\x79\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\xB0\x7E\x72\xB8\xA4\x03\x94\xE6\xA7\xDE\x09\x38\x91\x4A\x11\x40\x87\xA7\x7C\x59\x64\x14\x7B\xB5\x11\x10\xDD\xFE\xBF\xD5\xC0\xBB\x56\xE2\x85\x25\xF4\x35\x72\x0F\xF8\x53\xD0\x41\xE1\x44\x01\xC2\xB4\x1C\xC3\x31\x42\x16\x47\x85\x33\x22\x76\xB2\x0A\x6F\x0F\xE5\x25\x50\x4F\x85\x86\xBE\xBF\x98\x2E\x10\x67\x1E\xBE\x11\x05\x86\x05\x90\xC4\x59\xD0\x7C\x78\x10\xB0\x80\x5C\xB7\xE1\xC7\x2B\x75\xCB\x7C\x9F\xAE\xB5\xD1\x9D\x23\x37\x63\xA7\xDC\x42\xA2\x2D\x92\x04\x1B\x50\xC1\x7B\xB8\x3E\x1B\xC9\x56\x04\x8B\x2F\x52\x9B\xAD\xA9\x56\xE9\xC1\xFF\xAD\xA9\x58\x87\x30\xB6\x81\xF7\x97\x45\xFC\x19\x57\x3B\x2B\x6F\xE4\x47\xF4\x99\x45\xFE\x1D\xF1\xF8\x97\xA3\x88\x1D\x37\x1C\x5C\x8F\xE0\x76\x25\x9A\x50\xF8\xA0\x54\xFF\x44\x90\x76\x23\xD2\x32\xC6\xC3\xAB\x06\xBF\xFC\xFB\xBF\xF3\xAD\x7D\x92\x62\x02\x5B\x29\xD3\x35\xA3\x93\x9A\x43\x64\x60\x5D\xB2\xFA\x32\xFF\x3B\x04\xAF\x4D\x40\x6A\xF9\xC7\xE3\xEF\x23\xFD\x6B\xCB\xE5\x0F\x8B\x38\x0D\xEE\x0A\xFC\xFE\x0F\x98\x9F\x30\x31\xDD\x6C\x52\x65\xF9\x8B\x81\xBE\x22\xE1\x1C\x58\x03\xBA\x91\x1B\x89\x07\x02\x03\x01\x00\x01\xA3\x42\x30\x40\x30\x0E\x06\x03\x55\x1D\x0F\x01\x01\xFF\x04\x04\x03\x02\x01\x06\x30\x0F\x06\x03\x55\x1D\x13\x01\x01\xFF\x04\x05\x30\x03\x01\x01\xFF\x30\x1D\x06\x03\x55\x1D\x0E\x04\x16\x04\x14\x6A\x38\x5B\x26\x8D\xDE\x8B\x5A\xF2\x4F\x7A\x54\x83\x19\x18\xE3\x08\x35\xA6\xBA\x30\x0D\x06\x09\x2A\x86\x48\x86\xF7\x0D\x01\x01\x05\x05\x00\x03\x82\x01\x01\x00\x3C\xD5\x77\x3D\xDA\xDF\x89\xBA\x87\x0C\x08\x54\x6A\x20\x50\x92\xBE\xB0\x41\x3D\xB9\x26\x64\x83\x0A\x2F\xE8\x40\xC0\x97\x28\x27\x82\x30\x4A\xC9\x93\xFF\x6A\xE7\xA6\x00\x7F\x89\x42\x9A\xD6\x11\xE5\x53\xCE\x2F\xCC\xF2\xDA\x05\xC4\xFE\xE2\x50\xC4\x3A\x86\x7D\xCC\xDA\x7E\x10\x09\x3B\x92\x35\x2A\x53\xB2\xFE\xEB\x2B\x05\xD9\x6C\x5D\xE6\xD0\xEF\xD3\x6A\x66\x9E\x15\x28\x85\x7A\xE8\x82\x00\xAC\x1E\xA7\x09\x69\x56\x42\xD3\x68\x51\x18\xBE\x54\x9A\xBF\x44\x41\xBA\x49\xBE\x20\xBA\x69\x5C\xEE\xB8\x77\xCD\xCE\x6C\x1F\xAD\x83\x96\x18\x7D\x0E\xB5\x14\x39\x84\xF1\x28\xE9\x2D\xA3\x9E\x7B\x1E\x7A\x72\x5A\x83\xB3\x79\x6F\xEF\xB4\xFC\xD0\x0A\xA5\x58\x4F\x46\xDF\xFB\x6D\x79\x59\xF2\x84\x22\x52\xAE\x0F\xCC\xFB\x7C\x3B\xE7\x6A\xCA\x47\x61\xC3\x7A\xF8\xD3\x92\x04\x1F\xB8\x20\x84\xE1\x36\x54\x16\xC7\x40\xDE\x3B\x8A\x73\xDC\xDF\xC6\x09\x4C\xDF\xEC\xDA\xFF\xD4\x53\x42\xA1\xC9\xF2\x62\x1D\x22\x83\x3C\x97\xC5\xF9\x19\x62\x27\xAC\x65\x22\xD7\xD3\x3C\xC6\xE5\x8E\xB2\x53\xCC\x49\xCE\xBC\x30\xFE\x7B\x0E\x33\x90\xFB\xED\xD2\x14\x91\x1F\x07\xAF", }; diff --git a/scripts/base/protocols/syslog/consts.bro b/scripts/base/protocols/syslog/consts.bro index f08e7f71d7..dce1877ecf 100644 --- a/scripts/base/protocols/syslog/consts.bro +++ b/scripts/base/protocols/syslog/consts.bro @@ -1,6 +1,9 @@ +##! Constants definitions for syslog. + module Syslog; export { + ## Mapping between the constants and string values for syslog facilities. const facility_codes: table[count] of string = { [0] = "KERN", [1] = "USER", @@ -27,7 +30,8 @@ export { [22] = "LOCAL6", [23] = "LOCAL7", } &default=function(c: count): string { return fmt("?-%d", c); }; - + + ## Mapping between the constants and string values for syslog severities. const severity_codes: table[count] of string = { [0] = "EMERG", [1] = "ALERT", diff --git a/scripts/base/protocols/syslog/main.bro b/scripts/base/protocols/syslog/main.bro index c514556975..79f89d5e71 100644 --- a/scripts/base/protocols/syslog/main.bro +++ b/scripts/base/protocols/syslog/main.bro @@ -1,35 +1,42 @@ -##! Core script support for logging syslog messages. +##! Core script support for logging syslog messages. This script represents +##! one syslog message as one logged record. @load ./consts module Syslog; export { - redef enum Log::ID += { SYSLOG }; + redef enum Log::ID += { LOG }; type Info: record { + ## Timestamp of when the syslog message was seen. ts: time &log; uid: string &log; id: conn_id &log; + ## Protocol over which the message was seen. proto: transport_proto &log; + ## Syslog facility for the message. facility: string &log; + ## Syslog severity for the message. severity: string &log; + ## The plain text message. message: string &log; }; - - const ports = { 514/udp } &redef; } redef capture_filters += { ["syslog"] = "port 514" }; +const ports = { 514/udp } &redef; redef dpd_config += { [ANALYZER_SYSLOG_BINPAC] = [$ports = ports] }; +redef likely_server_ports += { 514/udp }; + redef record connection += { syslog: Info &optional; }; event bro_init() &priority=5 { - Log::create_stream(SYSLOG, [$columns=Info]); + Log::create_stream(Syslog::LOG, [$columns=Info]); } event syslog_message(c: connection, facility: count, severity: count, msg: string) &priority=5 @@ -48,5 +55,5 @@ event syslog_message(c: connection, facility: count, severity: count, msg: strin event syslog_message(c: connection, facility: count, severity: count, msg: string) &priority=-5 { - Log::write(SYSLOG, c$syslog); + Log::write(Syslog::LOG, c$syslog); } diff --git a/scripts/base/utils/directions-and-hosts.bro b/scripts/base/utils/directions-and-hosts.bro index 6b387ef980..a88c4827a6 100644 --- a/scripts/base/utils/directions-and-hosts.bro +++ b/scripts/base/utils/directions-and-hosts.bro @@ -1,3 +1,4 @@ +@load ./site type Direction: enum { ## The connection originator is not within the locally-monitored network, diff --git a/scripts/base/utils/site.bro b/scripts/base/utils/site.bro index 536c891572..4aeb70fe3f 100644 --- a/scripts/base/utils/site.bro +++ b/scripts/base/utils/site.bro @@ -18,7 +18,7 @@ export { const local_nets: set[subnet] &redef; ## This is used for retrieving the subnet when you multiple - ## :bro:id:`local_nets`. A membership query can be done with an + ## :bro:id:`Site::local_nets`. A membership query can be done with an ## :bro:type:`addr` and the table will yield the subnet it was found ## within. global local_nets_table: table[subnet] of subnet = {}; diff --git a/scripts/policy/frameworks/communication/listen-clear.bro b/scripts/policy/frameworks/communication/listen-clear.bro deleted file mode 100644 index ea94fe262a..0000000000 --- a/scripts/policy/frameworks/communication/listen-clear.bro +++ /dev/null @@ -1,20 +0,0 @@ -##! Listen for other Bro instances to make unencrypted connections. - -@load base/frameworks/communication - -module Communication; - -export { - ## Which port to listen on for clear connections. - const listen_port_clear = Communication::default_port_clear &redef; - - ## Which IP address to bind to (0.0.0.0 for any interface). - const listen_if_clear = 0.0.0.0 &redef; - -} - -event bro_init() &priority=-10 - { - enable_communication(); - listen(listen_if_clear, listen_port_clear, F); - } diff --git a/scripts/policy/frameworks/communication/listen-ssl.bro b/scripts/policy/frameworks/communication/listen-ssl.bro deleted file mode 100644 index b228289be2..0000000000 --- a/scripts/policy/frameworks/communication/listen-ssl.bro +++ /dev/null @@ -1,21 +0,0 @@ -##! Listen for other Bro instances and encrypt the connection with SSL. - -@load base/frameworks/communication - -module Communication; - -export { - ## Which port to listen on for SSL encrypted connections. - const listen_port_ssl = Communication::default_port_ssl &redef; - - ## Which IP address to bind to for SSL encrypted connections - ## (0.0.0.0 for any interface). - const listen_if_ssl = 0.0.0.0 &redef; - -} - -event bro_init() &priority=-10 - { - enable_communication(); - listen(listen_if_ssl, listen_port_ssl, T); - } diff --git a/scripts/policy/frameworks/communication/listen.bro b/scripts/policy/frameworks/communication/listen.bro new file mode 100644 index 0000000000..e366e5b4ff --- /dev/null +++ b/scripts/policy/frameworks/communication/listen.bro @@ -0,0 +1,12 @@ +##! Loading this script will make the Bro instance listen for remote +##! Bro instances to connect. + +@load base/frameworks/communication + +module Communication; + +event bro_init() &priority=-10 + { + enable_communication(); + listen(listen_interface, listen_port, listen_ssl); + } diff --git a/scripts/policy/frameworks/control/controllee.bro b/scripts/policy/frameworks/control/controllee.bro index 518336abd8..b4769764f4 100644 --- a/scripts/policy/frameworks/control/controllee.bro +++ b/scripts/policy/frameworks/control/controllee.bro @@ -1,7 +1,16 @@ +##! The controllee portion of the control framework. Load this script if remote +##! runtime control of the Bro process is desired. +##! +##! A controllee only needs to load the controllee script in addition +##! to the specific analysis scripts desired. It may also need a node +##! configured as a controller node in the communications nodes configuration:: +##! +##! bro frameworks/control/controllee +@load base/frameworks/control # If an instance is a controllee, it implicitly needs to listen for remote # connections. -@load frameworks/communication/listen-clear +@load frameworks/communication/listen module Control; diff --git a/scripts/policy/frameworks/control/controller.bro b/scripts/policy/frameworks/control/controller.bro index 83fd5e5451..39647095db 100644 --- a/scripts/policy/frameworks/control/controller.bro +++ b/scripts/policy/frameworks/control/controller.bro @@ -1,3 +1,11 @@ +##! This is a utility script that implements the controller interface for the +##! control framework. It's intended to be run to control a remote Bro +##! and then shutdown. +##! +##! It's intended to be used from the command line like this:: +##! bro frameworks/control/controller Control::host= Control::port= Control::cmd= [Control::arg=] + +@load base/frameworks/control @load base/frameworks/communication module Control; @@ -64,7 +72,10 @@ function configuration_update_func(p: event_peer) # We don't want to update non-const globals because that's usually # where state is stored and those values will frequently be declared # with &redef so that attributes can be redefined. - if ( t$constant && t$redefinable ) + # + # NOTE: functions are currently not fully supported for serialization and hence + # aren't sent. + if ( t$constant && t$redefinable && t$type_name != "func" ) { send_id(p, id); ++cnt; diff --git a/scripts/policy/frameworks/dpd/detect-protocols.bro b/scripts/policy/frameworks/dpd/detect-protocols.bro index cbe81df889..8f4e892ce4 100644 --- a/scripts/policy/frameworks/dpd/detect-protocols.bro +++ b/scripts/policy/frameworks/dpd/detect-protocols.bro @@ -1,10 +1,13 @@ ##! Finds connections with protocols on non-standard ports with DPD. +@load base/frameworks/notice +@load base/utils/site +@load base/utils/conn-ids + module ProtocolDetector; export { redef enum Notice::Type += { - Off_Port_Protocol_Found, # raised for each connection found Protocol_Found, Server_Found, }; @@ -151,13 +154,10 @@ function report_protocols(c: connection) { if ( [a, c$id$resp_h, c$id$resp_p] in valids ) do_notice(c, a, valids[a, c$id$resp_h, c$id$resp_p]); - else if ( [a, 0.0.0.0, c$id$resp_p] in valids ) do_notice(c, a, valids[a, 0.0.0.0, c$id$resp_p]); else do_notice(c, a, NONE); - - append_addl(c, analyzer_name(a)); } delete conns[c$id]; @@ -214,20 +214,6 @@ event protocol_confirmation(c: connection, atype: count, aid: count) } } -# event connection_analyzer_disabled(c: connection, analyzer: count) -# { -# if ( c$id !in conns ) -# return; -# -# delete conns[c$id][analyzer]; -# } - -function append_proto_addl(c: connection) - { - for ( a in conns[c$id] ) - append_addl(c, fmt_protocol(get_protocol(c, a))); - } - function found_protocol(c: connection, analyzer: count, protocol: string) { # Don't report anything running on a well-known port. diff --git a/scripts/policy/frameworks/dpd/packet-segment-logging.bro b/scripts/policy/frameworks/dpd/packet-segment-logging.bro index 2276b49e64..3883cd1207 100644 --- a/scripts/policy/frameworks/dpd/packet-segment-logging.bro +++ b/scripts/policy/frameworks/dpd/packet-segment-logging.bro @@ -4,6 +4,8 @@ ##! A caveat to logging packet data is that in some cases, the packet may ##! not be the packet that actually caused the protocol violation. +@load base/frameworks/dpd + module DPD; export { diff --git a/scripts/policy/frameworks/metrics/conn-example.bro b/scripts/policy/frameworks/metrics/conn-example.bro index 61360496cf..974012963b 100644 --- a/scripts/policy/frameworks/metrics/conn-example.bro +++ b/scripts/policy/frameworks/metrics/conn-example.bro @@ -1,3 +1,8 @@ +##! An example of using the metrics framework to collect connection metrics +##! aggregated into /24 CIDR ranges. + +@load base/frameworks/metrics +@load base/utils/site redef enum Metrics::ID += { CONNS_ORIGINATED, @@ -17,4 +22,4 @@ event connection_established(c: connection) Metrics::add_data(CONNS_ORIGINATED, [$host=c$id$orig_h], 1); Metrics::add_data(CONNS_RESPONDED, [$host=c$id$resp_h], 1); } - \ No newline at end of file + diff --git a/scripts/policy/frameworks/metrics/http-example.bro b/scripts/policy/frameworks/metrics/http-example.bro index 94592a852f..58ca4e6614 100644 --- a/scripts/policy/frameworks/metrics/http-example.bro +++ b/scripts/policy/frameworks/metrics/http-example.bro @@ -1,6 +1,17 @@ +##! Provides an example of aggregating and limiting collection down to +##! only local networks. Additionally, the status code for the response from +##! the request is added into the metric. + +@load base/frameworks/metrics +@load base/protocols/http +@load base/utils/site redef enum Metrics::ID += { + ## Measures HTTP requests indexed on both the request host and the response + ## code from the server. HTTP_REQUESTS_BY_STATUS_CODE, + + ## Currently unfinished and not working. HTTP_REQUESTS_BY_HOST_HEADER, }; @@ -8,19 +19,19 @@ event bro_init() { # TODO: these are waiting on a fix with table vals + records before they will work. #Metrics::add_filter(HTTP_REQUESTS_BY_HOST_HEADER, - # [$pred(index: Index) = { return Site:is_local_addr(index$host) }, + # [$pred(index: Metrics::Index) = { return Site::is_local_addr(index$host); }, # $aggregation_mask=24, - # $break_interval=5mins]); - # - ## Site::local_nets must be defined in order for this to actually do anything. - #Metrics::add_filter(HTTP_REQUESTS_BY_STATUS_CODE, [$aggregation_table=Site::local_nets_table, - # $break_interval=5mins]); + # $break_interval=1min]); + + # Site::local_nets must be defined in order for this to actually do anything. + Metrics::add_filter(HTTP_REQUESTS_BY_STATUS_CODE, [$aggregation_table=Site::local_nets_table, + $break_interval=1min]); } event HTTP::log_http(rec: HTTP::Info) { if ( rec?$host ) - Metrics::add_data(HTTP_REQUESTS_BY_HOST_HEADER, [$str=rec$host]); + Metrics::add_data(HTTP_REQUESTS_BY_HOST_HEADER, [$str=rec$host], 1); if ( rec?$status_code ) - Metrics::add_data(HTTP_REQUESTS_BY_STATUS_CODE, [$host=rec$id$orig_h, $str=fmt("%d", rec$status_code)]); - } \ No newline at end of file + Metrics::add_data(HTTP_REQUESTS_BY_STATUS_CODE, [$host=rec$id$orig_h, $str=fmt("%d", rec$status_code)], 1); + } diff --git a/scripts/policy/frameworks/metrics/ssl-example.bro b/scripts/policy/frameworks/metrics/ssl-example.bro index f3c5b8b902..5ec675779a 100644 --- a/scripts/policy/frameworks/metrics/ssl-example.bro +++ b/scripts/policy/frameworks/metrics/ssl-example.bro @@ -1,4 +1,10 @@ +##! Provides an example of using the metrics framework to collect the number +##! of times a specific server name indicator value is seen in SSL session +##! establishments. Names ending in google.com are being filtered out as an +##! example of the predicate based filtering in metrics filters. +@load base/frameworks/metrics +@load base/protocols/ssl redef enum Metrics::ID += { SSL_SERVERNAME, @@ -19,4 +25,4 @@ event SSL::log_ssl(rec: SSL::Info) { if ( rec?$server_name ) Metrics::add_data(SSL_SERVERNAME, [$str=rec$server_name], 1); - } \ No newline at end of file + } diff --git a/scripts/policy/frameworks/software/version-changes.bro b/scripts/policy/frameworks/software/version-changes.bro index 3b562b5334..974a23dc76 100644 --- a/scripts/policy/frameworks/software/version-changes.bro +++ b/scripts/policy/frameworks/software/version-changes.bro @@ -1,26 +1,25 @@ +##! Provides the possibly to define software names that are interesting to +##! watch for changes. A notice is generated if software versions change on a +##! host. + +@load base/frameworks/notice +@load base/frameworks/software module Software; export { redef enum Notice::Type += { - ## For certain softwares, a version changing may matter. In that case, + ## For certain software, a version changing may matter. In that case, ## this notice will be generated. Software that matters if the version ## changes can be configured with the ## :bro:id:`Software::interesting_version_changes` variable. Software_Version_Change, }; - ## Some software is more interesting when the version changes and this + ## Some software is more interesting when the version changes and this is ## a set of all software that should raise a notice when a different ## version is seen on a host. - const interesting_version_changes: set[string] = { - "SSH" - } &redef; - - ## Some software is more interesting when the version changes and this - ## a set of all software that should raise a notice when a different - ## version is seen on a host. - const interesting_type_changes: set[string] = {}; + const interesting_version_changes: set[string] = { } &redef; } event log_software(rec: Info) diff --git a/scripts/policy/frameworks/software/vulnerable.bro b/scripts/policy/frameworks/software/vulnerable.bro index ec0348d563..c2c2ba5b32 100644 --- a/scripts/policy/frameworks/software/vulnerable.bro +++ b/scripts/policy/frameworks/software/vulnerable.bro @@ -1,8 +1,15 @@ +##! Provides a variable to define vulnerable versions of software and if a +##! a version of that software as old or older than the defined version a +##! notice will be generated. + +@load base/frameworks/notice +@load base/frameworks/software module Software; export { redef enum Notice::Type += { + ## Indicates that a vulnerable version of software was detected. Vulnerable_Version, }; @@ -16,6 +23,7 @@ event log_software(rec: Info) if ( rec$name in vulnerable_versions && cmp_versions(rec$version, vulnerable_versions[rec$name]) <= 0 ) { - NOTICE([$note=Vulnerable_Version, $src=rec$host, $msg=software_fmt(rec)]); + NOTICE([$note=Vulnerable_Version, $src=rec$host, + $msg=fmt("A vulnerable version of software was detected: %s", software_fmt(rec))]); } - } \ No newline at end of file + } diff --git a/scripts/policy/frameworks/tunnel.bro b/scripts/policy/frameworks/tunnel.bro index a24bd6e1f6..98a860653c 100644 --- a/scripts/policy/frameworks/tunnel.bro +++ b/scripts/policy/frameworks/tunnel.bro @@ -27,23 +27,20 @@ ##! *Limitation:* The decapsulated packets are not fed through the ##! defragmenter again and decapsulation happens only on the primary ##! path, i.e., it's not available for the secondary path. -##! -##! @load base/protocols/conn module Tunnel; -#redef use_connection_compressor = F; -## enab redef Tunnel::decapsulate_ip = T; redef Tunnel::decapsulate_udp = T; redef Tunnel::udp_tunnel_allports = T; export { - redef enum Log::ID += { TUNNEL }; + ## The Tunnel logging stream identifier. + redef enum Log::ID += { LOG }; - ## This record will be logged + ## This record describing a tunneled connection will be logged. type Info : record { ## This is the time of the first record ts: time &log; @@ -56,17 +53,20 @@ export { ## The parent connection of IP-pair parent: Parent &log; }; + + ## Event that can be handled to access the :bro:type:`Tunnel::Info` + ## record as it is sent on to the logging framework. global log_tunnel: event(rec: Info); redef record Conn::Info += { - ## If the connection is tunneled the type of tunnel + ## If the connection is tunneled, the type of tunnel. tunnel_type: Tunneltype &log &optional; }; } event bro_init() { - Log::create_stream(TUNNEL, [$columns=Info, $ev=log_tunnel]); + Log::create_stream(Tunnel::LOG, [$columns=Info, $ev=log_tunnel]); } event new_connection(c: connection) @@ -79,6 +79,6 @@ event new_connection(c: connection) info$id = c$id; info$proto = get_port_transport_proto(c$id$resp_p); info$parent = c$tunnel_parent; - Log::write(TUNNEL, info); + Log::write(Tunnel::LOG, info); } } diff --git a/scripts/policy/hot.conn.bro b/scripts/policy/hot.conn.bro deleted file mode 100644 index 3b29504f73..0000000000 --- a/scripts/policy/hot.conn.bro +++ /dev/null @@ -1,200 +0,0 @@ -@load hot - -redef enum Notice += { - Sensitive_Connection, # connection marked "hot" -}; - -# Whether to translate the local address in Sensitive_Connection notices -# to a hostname. Meant as a demonstration of the "when" construct. -const xlate_hot_local_addr = F &redef; - -# The sets are indexed by the complete hot messages. -global hot_conns_reported: table[conn_id] of set[string]; - -const conn_closed = { TCP_CLOSED, TCP_RESET }; - -const state_graphic = { - ["OTH"] = "?>?", ["REJ"] = "[", - ["RSTO"] = ">]", ["RSTOS0"] = "}]", ["RSTR"] = ">[", ["RSTRH"] = "<[", - ["S0"] = "}", ["S1"] = ">", ["S2"] = "}2", ["S3"] = "}3", - ["SF"] = ">", ["SH"] = ">h", ["SHR"] = " 0 ) - log_hot_conn(c); - } - -event connection_state_remove(c: connection) &priority = -10 - { - local os = c$orig$state; - local rs = c$resp$state; - - if ( os == TCP_ESTABLISHED && rs == TCP_ESTABLISHED ) - # It was still active, no summary generated. - connection_gone(c, "remove"); - - else if ( (os == TCP_CLOSED || rs == TCP_CLOSED) && - (os == TCP_ESTABLISHED || rs == TCP_ESTABLISHED) ) - # One side has closed, the other hasn't - it's in state S2 - # or S3, hasn't been reported yet. - connection_gone(c, "remove"); - - delete hot_conns_reported[c$id]; - } - - -event partial_connection(c: connection) - { - if ( c$orig$state == TCP_PARTIAL && c$resp$state == TCP_INACTIVE ) - # This appears to be a stealth scan. Don't do hot-checking - # as there wasn't an established connection. - ; - else - { - Hot::check_hot(c, Hot::CONN_ESTABLISHED); - Hot::check_hot(c, Hot::APPL_ESTABLISHED); # assume it's been established - } - - if ( c$hot > 0 ) - log_hot_conn(c); - } - -event connection_attempt(c: connection) - { - Hot::check_spoof(c); - Hot::check_hot(c, Hot::CONN_ATTEMPTED); - } - -event connection_finished(c: connection) - { - if ( c$orig$size == 0 || c$resp$size == 0 ) - # Hard to get excited about this - not worth logging again. - c$hot = 0; - else - Hot::check_hot(c, Hot::CONN_FINISHED); - } - -event connection_partial_close(c: connection) - { - if ( c$orig$size == 0 || c$resp$size == 0 ) - # Hard to get excited about this - not worth logging again. - c$hot = 0; - else - Hot::check_hot(c, Hot::CONN_FINISHED); - } - -event connection_half_finished(c: connection) - { - Hot::check_hot(c, Hot::CONN_ATTEMPTED); - } - -event connection_rejected(c: connection) - { - Hot::check_hot(c, Hot::CONN_REJECTED); - } - -event connection_reset(c: connection) - { - Hot::check_hot(c, Hot::CONN_FINISHED); - } - -event connection_pending(c: connection) - { - if ( c$orig$state in conn_closed && - (c$resp$state == TCP_INACTIVE || c$resp$state == TCP_PARTIAL) ) - # This is a stray FIN or RST - don't bother reporting. - return; - - if ( c$orig$state == TCP_RESET || c$resp$state == TCP_RESET ) - # We already reported this connection when the RST - # occurred. - return; - - Hot::check_hot(c, Hot::CONN_FINISHED); - } - -function connection_gone(c: connection, gone_type: string) - { - if ( c$orig$size == 0 || c$resp$size == 0 ) - { - if ( c$orig$state == TCP_RESET && c$resp$state == TCP_INACTIVE) - # A bare RST, no other context. Ignore it. - return; - - # Hard to get excited about this - not worth logging again, - # per connection_finished(). - c$hot = 0; - } - else - Hot::check_hot(c, Hot::CONN_TIMEOUT); - } diff --git a/scripts/policy/integration/barnyard2/__load__.bro b/scripts/policy/integration/barnyard2/__load__.bro index 9e870eb7aa..c4790c6b32 100644 --- a/scripts/policy/integration/barnyard2/__load__.bro +++ b/scripts/policy/integration/barnyard2/__load__.bro @@ -1,3 +1,2 @@ -@load integration/barnyard2/types -@load integration/barnyard2/event -@load integration/barnyard2/base +@load ./types +@load ./main diff --git a/scripts/policy/integration/barnyard2/event.bro b/scripts/policy/integration/barnyard2/event.bro deleted file mode 100644 index 5fa2747a28..0000000000 --- a/scripts/policy/integration/barnyard2/event.bro +++ /dev/null @@ -1,3 +0,0 @@ -## This is the event that Barnyard2 instances will send if they're -## configured with the bro_alert output plugin. -global barnyard_alert: event(id: Barnyard2::PacketID, alert: Barnyard2::AlertData, msg: string, data: string); diff --git a/scripts/policy/integration/barnyard2/base.bro b/scripts/policy/integration/barnyard2/main.bro similarity index 85% rename from scripts/policy/integration/barnyard2/base.bro rename to scripts/policy/integration/barnyard2/main.bro index f05ad0e9bf..1d38d80809 100644 --- a/scripts/policy/integration/barnyard2/base.bro +++ b/scripts/policy/integration/barnyard2/main.bro @@ -2,12 +2,12 @@ ##! Barnyard2 and logs them. In the future it will do more correlation ##! and derive new notices from the alerts. -@load integration/barnyard2/types +@load ./types module Barnyard2; export { - redef enum Log::ID += { BARNYARD2 }; + redef enum Log::ID += { LOG }; type Info: record { ts: time &log; @@ -15,15 +15,15 @@ export { alert: AlertData &log; }; - ## This can convert a Barnyard :bro:type:`PacketID` value to a + ## This can convert a Barnyard :bro:type:`Barnyard2::PacketID` value to a ## :bro:type:`conn_id` value in the case that you might need to index ## into an existing data structure elsewhere within Bro. global pid2cid: function(p: PacketID): conn_id; } -event bro_init() +event bro_init() &priority=5 { - Log::create_stream(BARNYARD2, [$columns=Info]); + Log::create_stream(Barnyard2::LOG, [$columns=Info]); } @@ -34,7 +34,7 @@ function pid2cid(p: PacketID): conn_id event barnyard_alert(id: PacketID, alert: AlertData, msg: string, data: string) { - Log::write(BARNYARD2, [$ts=network_time(), $pid=id, $alert=alert]); + Log::write(Barnyard2::LOG, [$ts=network_time(), $pid=id, $alert=alert]); #local proto_connection_string: string; #if ( id$src_p == 0/tcp ) diff --git a/scripts/policy/integration/barnyard2/types.bro b/scripts/policy/integration/barnyard2/types.bro index 9bc56773ef..6cfcbb9535 100644 --- a/scripts/policy/integration/barnyard2/types.bro +++ b/scripts/policy/integration/barnyard2/types.bro @@ -22,4 +22,11 @@ export { dst_ip: addr; dst_p: port; } &log; -} \ No newline at end of file + + ## This is the event that Barnyard2 instances will send if they're + ## configured with the bro_alert output plugin. + global barnyard_alert: event(id: Barnyard2::PacketID, + alert: Barnyard2::AlertData, + msg: string, + data: string); +} diff --git a/scripts/policy/misc/capture-loss.bro b/scripts/policy/misc/capture-loss.bro new file mode 100644 index 0000000000..b2d23020f8 --- /dev/null +++ b/scripts/policy/misc/capture-loss.bro @@ -0,0 +1,85 @@ +##! This script logs evidence regarding the degree to which the packet +##! capture process suffers from measurement loss. +##! The loss could be due to overload on the host or NIC performing +##! the packet capture or it could even be beyond the host. If you are +##! capturing from a switch with a SPAN port, it's very possible that +##! the switch itself could be overloaded and dropping packets. +##! Reported loss is computed in terms of number of "gap events" (ACKs +##! for a sequence number that's above a gap). + +@load base/frameworks/notice +@load base/frameworks/metrics + +module CaptureLoss; + +export { + redef enum Log::ID += { LOG }; + + redef enum Notice::Type += { + ## Report if the detected capture loss exceeds the percentage + ## threshold. + Too_Much_Loss + }; + + type Info: record { + ## Timestamp for when the measurement occurred. + ts: time &log; + ## The time delay between this measurement and the last. + ts_delta: interval &log; + ## In the event that there are multiple Bro instances logging + ## to the same host, this distinguishes each peer with it's + ## individual name. + peer: string &log; + ## Number of missed ACKs from the previous measurement interval. + gaps: count &log; + ## Total number of ACKs seen in the previous measurement interval. + acks: count &log; + ## Percentage of ACKs seen where the data being ACKed wasn't seen. + percent_lost: string &log; + }; + + ## The interval at which capture loss reports are created. + const watch_interval = 15mins &redef; + + ## The percentage of missed data that is considered "too much" + ## when the :bro:enum:`CaptureLoss::Too_Much_Loss` notice should be + ## generated. The value is expressed as a double between 0 and 1 with 1 + ## being 100% + const too_much_loss: double = 0.1 &redef; +} + +event CaptureLoss::take_measurement(last_ts: time, last_acks: count, last_gaps: count) + { + if ( last_ts == 0 ) + { + schedule watch_interval { CaptureLoss::take_measurement(network_time(), 0, 0) }; + return; + } + + local now = network_time(); + local g = get_gap_summary(); + local acks = g$ack_events - last_acks; + local gaps = g$gap_events - last_gaps; + local pct_lost = (acks == 0) ? 0.0 : (100 * (1.0 * gaps) / (1.0 * acks)); + local info: Info = [$ts=now, + $ts_delta=now-last_ts, + $peer=peer_description, + $acks=acks, $gaps=gaps, + $percent_lost=fmt("%.3f%%", pct_lost)]; + + if ( pct_lost >= too_much_loss*100 ) + NOTICE([$note=Too_Much_Loss, + $msg=fmt("The capture loss script detected an estimated loss rate above %.3f%%", pct_lost)]); + + Log::write(LOG, info); + schedule watch_interval { CaptureLoss::take_measurement(now, g$ack_events, g$gap_events) }; + } + +event bro_init() &priority=5 + { + Log::create_stream(LOG, [$columns=Info]); + + # We only schedule the event if we are capturing packets. + if ( reading_live_traffic() || reading_traces() ) + schedule watch_interval { CaptureLoss::take_measurement(network_time(), 0, 0) }; + } diff --git a/scripts/policy/misc/loaded-scripts.bro b/scripts/policy/misc/loaded-scripts.bro index 2077e6c99a..468478e682 100644 --- a/scripts/policy/misc/loaded-scripts.bro +++ b/scripts/policy/misc/loaded-scripts.bro @@ -1,20 +1,38 @@ +##! Log the loaded scripts. + module LoadedScripts; export { - redef enum Log::ID += { LOADED_SCRIPTS }; + redef enum Log::ID += { LOG }; type Info: record { - depth: count &log; - name: string &log; + ## Name of the script loaded potentially with spaces included before + ## the file name to indicate load depth. The convention is two spaces + ## per level of depth. + name: string &log; }; } -event bro_init() +const depth: table[count] of string = { + [0] = "", + [1] = " ", + [2] = " ", + [3] = " ", + [4] = " ", + [5] = " ", + [6] = " ", + [7] = " ", + [8] = " ", + [9] = " ", + [10] = " ", +}; + +event bro_init() &priority=5 { - Log::create_stream(LOADED_SCRIPTS, [$columns=Info]); + Log::create_stream(LoadedScripts::LOG, [$columns=Info]); } event bro_script_loaded(path: string, level: count) { - Log::write(LOADED_SCRIPTS, [$depth=level, $name=path]); + Log::write(LoadedScripts::LOG, [$name=cat(depth[level], path)]); } \ No newline at end of file diff --git a/scripts/policy/misc/profiling.bro b/scripts/policy/misc/profiling.bro index 457675b1d6..31451f1a55 100644 --- a/scripts/policy/misc/profiling.bro +++ b/scripts/policy/misc/profiling.bro @@ -2,14 +2,13 @@ module Profiling; +## Set the profiling output file. redef profiling_file = open_log_file("prof"); -export { - ## Cheap profiling every 15 seconds. - redef profiling_interval = 15 secs &redef; -} +## Set the cheap profiling interval. +redef profiling_interval = 15 secs; -# Expensive profiling every 5 minutes. +## Set the expensive profiling interval. redef expensive_profiling_multiple = 20; event bro_init() diff --git a/scripts/policy/misc/stats.bro b/scripts/policy/misc/stats.bro new file mode 100644 index 0000000000..d7866fd136 --- /dev/null +++ b/scripts/policy/misc/stats.bro @@ -0,0 +1,83 @@ +##! Log memory/packet/lag statistics. Differs from profiling.bro in that this +##! is lighter-weight (much less info, and less load to generate). + +@load base/frameworks/notice + +module Stats; + +export { + redef enum Log::ID += { LOG }; + + ## How often stats are reported. + const stats_report_interval = 1min &redef; + + type Info: record { + ## Timestamp for the measurement. + ts: time &log; + ## Peer that generated this log. Mostly for clusters. + peer: string &log; + ## Amount of memory currently in use in MB. + mem: count &log; + ## Number of packets processed since the last stats interval. + pkts_proc: count &log; + ## Number of events that been processed since the last stats interval. + events_proc: count &log; + ## Number of events that have been queued since the last stats interval. + events_queued: count &log; + + ## Lag between the wall clock and packet timestamps if reading live traffic. + lag: interval &log &optional; + ## Number of packets received since the last stats interval if reading + ## live traffic. + pkts_recv: count &log &optional; + ## Number of packets dropped since the last stats interval if reading + ## live traffic. + pkts_dropped: count &log &optional; + ## Number of packets seen on the link since the last stats interval + ## if reading live traffic. + pkts_link: count &log &optional; + }; + + ## Event to catch stats as they are written to the logging stream. + global log_stats: event(rec: Info); +} + +event bro_init() &priority=5 + { + Log::create_stream(Stats::LOG, [$columns=Info, $ev=log_stats]); + } + +event check_stats(last_ts: time, last_ns: NetStats, last_res: bro_resources) + { + local now = current_time(); + local ns = net_stats(); + local res = resource_usage(); + + if ( bro_is_terminating() ) + # No more stats will be written or scheduled when Bro is + # shutting down. + return; + + local info: Info = [$ts=now, $peer=peer_description, $mem=res$mem/1000000, + $pkts_proc=res$num_packets - last_res$num_packets, + $events_proc=res$num_events_dispatched - last_res$num_events_dispatched, + $events_queued=res$num_events_queued - last_res$num_events_queued]; + + if ( reading_live_traffic() ) + { + info$lag = now - network_time(); + # Someone's going to have to explain what this is and add a field to the Info record. + # info$util = 100.0*((res$user_time + res$system_time) - (last_res$user_time + last_res$system_time))/(now-last_ts); + info$pkts_recv = ns$pkts_recvd - last_ns$pkts_recvd; + info$pkts_dropped = ns$pkts_dropped - last_ns$pkts_dropped; + info$pkts_link = ns$pkts_link - last_ns$pkts_link; + } + + Log::write(Stats::LOG, info); + schedule stats_report_interval { check_stats(now, ns, res) }; + } + +event bro_init() + { + schedule stats_report_interval { check_stats(current_time(), net_stats(), resource_usage()) }; + } diff --git a/scripts/policy/misc/trim-trace-file.bro b/scripts/policy/misc/trim-trace-file.bro index 3caa41c06b..8a7781b628 100644 --- a/scripts/policy/misc/trim-trace-file.bro +++ b/scripts/policy/misc/trim-trace-file.bro @@ -10,7 +10,8 @@ export { ## This event can be generated externally to this script if on-demand ## tracefile rotation is required with the caveat that the script doesn't ## currently attempt to get back on schedule automatically and the next - ## trim will likely won't happen on the :bro:id:`trim_interval`. + ## trim will likely won't happen on the + ## :bro:id:`TrimTraceFile::trim_interval`. global go: event(first_trim: bool); } diff --git a/scripts/policy/protocols/conn/known-hosts.bro b/scripts/policy/protocols/conn/known-hosts.bro index 72bdaf01a4..8914a5a22a 100644 --- a/scripts/policy/protocols/conn/known-hosts.bro +++ b/scripts/policy/protocols/conn/known-hosts.bro @@ -1,14 +1,18 @@ ##! This script logs hosts that Bro determines have performed complete TCP ##! handshakes and logs the address once per day (by default). The log that -##! output provides an easy way to determine a count of the IP addresses in +##! is output provides an easy way to determine a count of the IP addresses in ##! use on a network per day. -module KnownHosts; +@load base/utils/directions-and-hosts + +module Known; export { - redef enum Log::ID += { KNOWN_HOSTS }; - - type Info: record { + ## The known-hosts logging stream identifier. + redef enum Log::ID += { HOSTS_LOG }; + + ## The record type which contains the column fields of the known-hosts log. + type HostsInfo: record { ## The timestamp at which the host was detected. ts: time &log; ## The address that was detected originating or responding to a TCP @@ -17,8 +21,8 @@ export { }; ## The hosts whose existence should be logged and tracked. - ## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS - const asset_tracking = LOCAL_HOSTS &redef; + ## See :bro:type:`Host` for possible choices. + const host_tracking = LOCAL_HOSTS &redef; ## The set of all known addresses to store for preventing duplicate ## logging of addresses. It can also be used from other scripts to @@ -26,13 +30,15 @@ export { ## Maintain the list of known hosts for 24 hours so that the existence ## of each individual address is logged each day. global known_hosts: set[addr] &create_expire=1day &synchronized &redef; - - global log_known_hosts: event(rec: Info); + + ## An event that can be handled to access the :bro:type:`Known::HostsInfo` + ## record as it is sent on to the logging framework. + global log_known_hosts: event(rec: HostsInfo); } event bro_init() { - Log::create_stream(KNOWN_HOSTS, [$columns=Info, $ev=log_known_hosts]); + Log::create_stream(Known::HOSTS_LOG, [$columns=HostsInfo, $ev=log_known_hosts]); } event connection_established(c: connection) &priority=5 @@ -41,10 +47,13 @@ event connection_established(c: connection) &priority=5 for ( host in set(id$orig_h, id$resp_h) ) { - if ( host !in known_hosts && addr_matches_host(host, asset_tracking) ) + if ( host !in known_hosts && + c$orig$state == TCP_ESTABLISHED && + c$resp$state == TCP_ESTABLISHED && + addr_matches_host(host, host_tracking) ) { add known_hosts[host]; - Log::write(KNOWN_HOSTS, [$ts=network_time(), $host=host]); + Log::write(Known::HOSTS_LOG, [$ts=network_time(), $host=host]); } } } diff --git a/scripts/policy/protocols/conn/known-services.bro b/scripts/policy/protocols/conn/known-services.bro index 35a19a14f0..f494a30f82 100644 --- a/scripts/policy/protocols/conn/known-services.bro +++ b/scripts/policy/protocols/conn/known-services.bro @@ -3,75 +3,98 @@ ##! completed a TCP handshake with another host. If a protocol is detected ##! during the session, the protocol will also be logged. -module KnownServices; +@load base/utils/directions-and-hosts -redef enum Log::ID += { KNOWN_SERVICES }; +module Known; export { - type Info: record { + ## The known-services logging stream identifier. + redef enum Log::ID += { SERVICES_LOG }; + + ## The record type which contains the column fields of the known-services + ## log. + type ServicesInfo: record { + ## The time at which the service was detected. ts: time &log; + ## The host address on which the service is running. host: addr &log; + ## The port number on which the service is running. port_num: port &log; + ## The transport-layer protocol which the service uses. port_proto: transport_proto &log; + ## A set of protocols that match the service's connection payloads. service: set[string] &log; - - done: bool &default=F; }; ## The hosts whose services should be tracked and logged. - const asset_tracking = LOCAL_HOSTS &redef; - + ## See :bro:type:`Host` for possible choices. + const service_tracking = LOCAL_HOSTS &redef; + + ## Tracks the set of daily-detected services for preventing the logging + ## of duplicates, but can also be inspected by other scripts for + ## different purposes. global known_services: set[addr, port] &create_expire=1day &synchronized; - - global log_known_services: event(rec: Info); + + ## Event that can be handled to access the :bro:type:`Known::ServicesInfo` + ## record as it is sent on to the logging framework. + global log_known_services: event(rec: ServicesInfo); } redef record connection += { + # This field is to indicate whether or not the processing for detecting + # and logging the service for this connection is complete. known_services_done: bool &default=F; - known_services_watch: bool &default=F; }; -event bro_init() +event bro_init() &priority=5 { - Log::create_stream(KNOWN_SERVICES, [$columns=Info, - $ev=log_known_services]); + Log::create_stream(Known::SERVICES_LOG, [$columns=ServicesInfo, + $ev=log_known_services]); + } + +event log_it(ts: time, a: addr, p: port, services: set[string]) + { + if ( [a, p] !in known_services ) + { + add known_services[a, p]; + + local i: ServicesInfo; + i$ts=ts; + i$host=a; + i$port_num=p; + i$port_proto=get_port_transport_proto(p); + i$service=services; + Log::write(Known::SERVICES_LOG, i); + } } function known_services_done(c: connection) { local id = c$id; - if ( ! c$known_services_done && - get_port_transport_proto(id$resp_p) == tcp && - addr_matches_host(id$resp_h, asset_tracking) && - [id$resp_h, id$resp_p] !in known_services && - "ftp-data" !in c$service ) # don't include ftp data sessions - { - local i: Info; - i$ts=c$start_time; - i$host=id$resp_h; - i$port_num=id$resp_p; - i$port_proto=get_port_transport_proto(id$resp_p); - i$service=c$service; - - add known_services[id$resp_h, id$resp_p]; - Log::write(KNOWN_SERVICES, i); - c$known_services_done = T; - } + c$known_services_done = T; + + if ( ! addr_matches_host(id$resp_h, service_tracking) || + "ftp-data" in c$service || # don't include ftp data sessions + ("DNS" in c$service && c$resp$size == 0) ) # for dns, require that the server talks. + return; + + # If no protocol was detected, wait a short + # time before attempting to log in case a protocol is detected + # on another connection. + if ( |c$service| == 0 ) + schedule 5min { log_it(network_time(), id$resp_h, id$resp_p, c$service) }; + else + event log_it(network_time(), id$resp_h, id$resp_p, c$service); } event protocol_confirmation(c: connection, atype: count, aid: count) &priority=-5 { known_services_done(c); } - -event connection_established(c: connection) - { - c$known_services_watch=T; - } # Handle the connection ending in case no protocol was ever detected. event connection_state_remove(c: connection) &priority=-5 { - if ( c$known_services_watch ) + if ( ! c$known_services_done && c$resp$state == TCP_ESTABLISHED ) known_services_done(c); } diff --git a/scripts/policy/protocols/conn/scan.bro b/scripts/policy/protocols/conn/scan.bro deleted file mode 100644 index ab715cccb3..0000000000 --- a/scripts/policy/protocols/conn/scan.bro +++ /dev/null @@ -1,604 +0,0 @@ -@load base/frameworks/notice -@load port-name - -module Scan; - -export { - redef enum Notice::Type += { - ## The source has scanned a number of ports. - PortScan, - ## The source has scanned a number of addresses. - AddressScan, - ## Apparent flooding backscatter seen from source. - BackscatterSeen, - - ## Summary of scanning activity. - ScanSummary, - ## Summary of distinct ports per scanner. - PortScanSummary, - ## Summary of distinct low ports per scanner. - LowPortScanSummary, - - ## Source touched a landmine destination. - Landmine, - ## Source reached :bro:id:`Scan::shut_down_threshold` - ShutdownThreshold, - ## Source touched privileged ports. - LowPortTrolling, - }; - - # Whether to consider UDP "connections" for scan detection. - # Can lead to false positives due to UDP fanout from some P2P apps. - const suppress_UDP_scan_checks = F &redef; - - const activate_priv_port_check = T &redef; - const activate_landmine_check = F &redef; - const landmine_thresh_trigger = 5 &redef; - - const landmine_address: set[addr] &redef; - - const scan_summary_trigger = 25 &redef; - const port_summary_trigger = 20 &redef; - const lowport_summary_trigger = 10 &redef; - - # Raise ShutdownThresh after this many failed attempts - const shut_down_threshold = 100 &redef; - - # Which services should be analyzed when detecting scanning - # (not consulted if analyze_all_services is set). - const analyze_services: set[port] &redef; - const analyze_all_services = T &redef; - - # Track address scaners only if at least these many hosts contacted. - const addr_scan_trigger = 0 &redef; - - # Ignore address scanners for further scan detection after - # scanning this many hosts. - # 0 disables. - const ignore_scanners_threshold = 0 &redef; - - # Report a scan of peers at each of these points. - const report_peer_scan: vector of count = { - 20, 100, 1000, 10000, 50000, 100000, 250000, 500000, 1000000, - } &redef; - - const report_outbound_peer_scan: vector of count = { - 100, 1000, 10000, - } &redef; - - # Report a scan of ports at each of these points. - const report_port_scan: vector of count = { - 50, 250, 1000, 5000, 10000, 25000, 65000, - } &redef; - - # Once a source has scanned this many different ports (to however many - # different remote hosts), start tracking its per-destination access. - const possible_port_scan_thresh = 20 &redef; - - # Threshold for scanning privileged ports. - const priv_scan_trigger = 5 &redef; - const troll_skip_service = { - smtp, ftp, ssh, 20/tcp, http, - } &redef; - - const report_accounts_tried: vector of count = { - 20, 100, 1000, 10000, 100000, 1000000, - } &redef; - - const report_remote_accounts_tried: vector of count = { - 100, 500, - } &redef; - - # Report a successful password guessing if the source attempted - # at least this many. - const password_guessing_success_threshhold = 20 &redef; - - const skip_accounts_tried: set[addr] &redef; - - const addl_web = { - 81/tcp, 443/tcp, 8000/tcp, 8001/tcp, 8080/tcp, } - &redef; - - const skip_services = { ident, } &redef; - const skip_outbound_services = { Hot::allow_services, ftp, addl_web, } - &redef; - - const skip_scan_sources = { - 255.255.255.255, # who knows why we see these, but we do - - # AltaVista. Here just as an example of what sort of things - # you might list. - test-scooter.av.pa-x.dec.com, - } &redef; - - const skip_scan_nets: set[subnet] = {} &redef; - - # List of well known local server/ports to exclude for scanning - # purposes. - const skip_dest_server_ports: set[addr, port] = {} &redef; - - # Reverse (SYN-ack) scans seen from these ports are considered - # to reflect possible SYN-flooding backscatter, and not true - # (stealth) scans. - const backscatter_ports = { - http, 53/tcp, 53/udp, bgp, 6666/tcp, 6667/tcp, - } &redef; - - const report_backscatter: vector of count = { - 20, - } &redef; - - global check_scan: - function(c: connection, established: bool, reverse: bool): bool; - - # The following tables are defined here so that we can redef - # the expire timeouts. - # FIXME: should we allow redef of attributes on IDs which - # are not exported? - - # How many different hosts connected to with a possible - # backscatter signature. - global distinct_backscatter_peers: table[addr] of table[addr] of count - &read_expire = 15 min; - - # Expire functions that trigger summaries. - global scan_summary: - function(t: table[addr] of set[addr], orig: addr): interval; - global port_summary: - function(t: table[addr] of set[port], orig: addr): interval; - global lowport_summary: - function(t: table[addr] of set[port], orig: addr): interval; - - # Indexed by scanner address, yields # distinct peers scanned. - # pre_distinct_peers tracks until addr_scan_trigger hosts first. - global pre_distinct_peers: table[addr] of set[addr] - &read_expire = 15 mins &redef; - - global distinct_peers: table[addr] of set[addr] - &read_expire = 15 mins &expire_func=scan_summary &redef; - global distinct_ports: table[addr] of set[port] - &read_expire = 15 mins &expire_func=port_summary &redef; - global distinct_low_ports: table[addr] of set[port] - &read_expire = 15 mins &expire_func=lowport_summary &redef; - - # Indexed by scanner address, yields a table with scanned hosts - # (and ports). - global scan_triples: table[addr] of table[addr] of set[port]; - - global remove_possible_source: - function(s: set[addr], idx: addr): interval; - global possible_scan_sources: set[addr] - &expire_func=remove_possible_source &read_expire = 15 mins; - - # Indexed by source address, yields user name & password tried. - global accounts_tried: table[addr] of set[string, string] - &read_expire = 1 days; - - global ignored_scanners: set[addr] &create_expire = 1 day &redef; - - # These tables track whether a threshold has been reached. - # More precisely, the counter is the next index of threshold vector. - global shut_down_threshold_reached: table[addr] of bool &default=F; - global rb_idx: table[addr] of count - &default=0 &read_expire = 1 days &redef; - global rps_idx: table[addr] of count - &default=0 &read_expire = 1 days &redef; - global rops_idx: table[addr] of count - &default=0 &read_expire = 1 days &redef; - global rpts_idx: table[addr,addr] of count - &default=0 &read_expire = 1 days &redef; - global rat_idx: table[addr] of count - &default=0 &read_expire = 1 days &redef; - global rrat_idx: table[addr] of count - &default=0 &read_expire = 1 days &redef; -} - -global thresh_check: function(v: vector of count, idx: table[addr] of count, - orig: addr, n: count): bool; -global thresh_check_2: function(v: vector of count, - idx: table[addr,addr] of count, orig: addr, - resp: addr, n: count): bool; - -function scan_summary(t: table[addr] of set[addr], orig: addr): interval - { - local num_distinct_peers = orig in t ? |t[orig]| : 0; - - if ( num_distinct_peers >= scan_summary_trigger ) - NOTICE([$note=ScanSummary, $src=orig, $n=num_distinct_peers, - $msg=fmt("%s scanned a total of %d hosts", - orig, num_distinct_peers)]); - - return 0 secs; - } - -function port_summary(t: table[addr] of set[port], orig: addr): interval - { - local num_distinct_ports = orig in t ? |t[orig]| : 0; - - if ( num_distinct_ports >= port_summary_trigger ) - NOTICE([$note=PortScanSummary, $src=orig, $n=num_distinct_ports, - $msg=fmt("%s scanned a total of %d ports", - orig, num_distinct_ports)]); - - return 0 secs; - } - -function lowport_summary(t: table[addr] of set[port], orig: addr): interval - { - local num_distinct_lowports = orig in t ? |t[orig]| : 0; - - if ( num_distinct_lowports >= lowport_summary_trigger ) - NOTICE([$note=LowPortScanSummary, $src=orig, - $n=num_distinct_lowports, - $msg=fmt("%s scanned a total of %d low ports", - orig, num_distinct_lowports)]); - - return 0 secs; - } - -function clear_addr(a: addr) - { - delete distinct_peers[a]; - delete distinct_ports[a]; - delete distinct_low_ports[a]; - delete scan_triples[a]; - delete possible_scan_sources[a]; - delete distinct_backscatter_peers[a]; - delete pre_distinct_peers[a]; - delete rb_idx[a]; - delete rps_idx[a]; - delete rops_idx[a]; - delete rat_idx[a]; - delete rrat_idx[a]; - delete shut_down_threshold_reached[a]; - delete ignored_scanners[a]; - } - -function ignore_addr(a: addr) - { - clear_addr(a); - add ignored_scanners[a]; - } - -function check_scan(c: connection, established: bool, reverse: bool): bool - { - local id = c$id; - - local service = "ftp-data" in c$service ? 20/tcp - : (reverse ? id$orig_p : id$resp_p); - local rev_service = reverse ? id$resp_p : id$orig_p; - local orig = reverse ? id$resp_h : id$orig_h; - local resp = reverse ? id$orig_h : id$resp_h; - local outbound = is_local_addr(orig); - - # The following works better than using get_conn_transport_proto() - # because c might not correspond to an active connection (which - # causes the function to fail). - if ( suppress_UDP_scan_checks && - service >= 0/udp && service <= 65535/udp ) - return F; - - if ( service in skip_services && ! outbound ) - return F; - - if ( outbound && service in skip_outbound_services ) - return F; - - if ( orig in skip_scan_sources ) - return F; - - if ( orig in skip_scan_nets ) - return F; - - # Don't include well known server/ports for scanning purposes. - if ( ! outbound && [resp, service] in skip_dest_server_ports ) - return F; - - if ( orig in ignored_scanners) - return F; - - if ( (! established || service !in Hot::allow_services) && - # not established, service not expressly allowed - - # not known peer set - (orig !in distinct_peers || resp !in distinct_peers[orig]) && - - # want to consider service for scan detection - (analyze_all_services || service in analyze_services) ) - { - if ( reverse && rev_service in backscatter_ports && - # reverse, non-priv backscatter port - service >= 1024/tcp ) - { - if ( orig !in distinct_backscatter_peers ) - { - local empty_bs_table: - table[addr] of count &default=0; - distinct_backscatter_peers[orig] = - empty_bs_table; - } - - if ( ++distinct_backscatter_peers[orig][resp] <= 2 && - # The test is <= 2 because we get two check_scan() - # calls, once on connection attempt and once on - # tear-down. - - distinct_backscatter_peers[orig][resp] == 1 && - - # Looks like backscatter, and it's not scanning - # a privileged port. - - thresh_check(report_backscatter, rb_idx, orig, - |distinct_backscatter_peers[orig]|) - ) - { - local rev_svc = rev_service in port_names ? - port_names[rev_service] : - fmt("%s", rev_service); - - NOTICE([$note=BackscatterSeen, $src=orig, - $p=rev_service, - $msg=fmt("backscatter seen from %s (%d hosts; %s)", - orig, |distinct_backscatter_peers[orig]|, rev_svc)]); - } - - if ( ignore_scanners_threshold > 0 && - |distinct_backscatter_peers[orig]| > - ignore_scanners_threshold ) - ignore_addr(orig); - } - - else - { # done with backscatter check - local ignore = F; - - local svc = service in port_names ? - port_names[service] : fmt("%s", service); - - if ( orig !in distinct_peers && addr_scan_trigger > 0 ) - { - if ( orig !in pre_distinct_peers ) - pre_distinct_peers[orig] = set(); - - add pre_distinct_peers[orig][resp]; - if ( |pre_distinct_peers[orig]| < addr_scan_trigger ) - ignore = T; - } - - if ( ! ignore ) - { # XXXXX - - if ( orig !in distinct_peers ) - distinct_peers[orig] = set() &mergeable; - - if ( resp !in distinct_peers[orig] ) - add distinct_peers[orig][resp]; - - local n = |distinct_peers[orig]|; - - if ( activate_landmine_check && - n >= landmine_thresh_trigger && - mask_addr(resp, 24) in landmine_address ) - { - local msg2 = fmt("landmine address trigger %s%s ", orig, svc); - NOTICE([$note=Landmine, $src=orig, - $p=service, $msg=msg2]); - } - - # Check for threshold if not outbound. - if ( ! shut_down_threshold_reached[orig] && - n >= shut_down_threshold && - ! outbound && orig !in neighbor_nets ) - { - shut_down_threshold_reached[orig] = T; - local msg = fmt("shutdown threshold reached for %s", orig); - NOTICE([$note=ShutdownThreshold, $src=orig, - $p=service, $msg=msg]); - } - - else - { - local address_scan = F; - if ( outbound && - # inside host scanning out? - thresh_check(report_outbound_peer_scan, rops_idx, orig, n) ) - address_scan = T; - - if ( ! outbound && - thresh_check(report_peer_scan, rps_idx, orig, n) ) - address_scan = T; - - if ( address_scan ) - NOTICE([$note=AddressScan, - $src=orig, $p=service, - $n=n, - $msg=fmt("%s has scanned %d hosts (%s)", - orig, n, svc)]); - - if ( address_scan && - ignore_scanners_threshold > 0 && - n > ignore_scanners_threshold ) - ignore_addr(orig); - } - } - } # XXXX - } - - if ( established ) - # Don't consider established connections for port scanning, - # it's too easy to be mislead by FTP-like applications that - # legitimately gobble their way through the port space. - return F; - - # Coarse search for port-scanning candidates: those that have made - # connections (attempts) to possible_port_scan_thresh or more - # distinct ports. - if ( orig !in distinct_ports || service !in distinct_ports[orig] ) - { - if ( orig !in distinct_ports ) - distinct_ports[orig] = set() &mergeable; - - if ( service !in distinct_ports[orig] ) - add distinct_ports[orig][service]; - - if ( |distinct_ports[orig]| >= possible_port_scan_thresh && - orig !in scan_triples ) - { - scan_triples[orig] = table() &mergeable; - add possible_scan_sources[orig]; - } - } - - # For sources that have been identified as possible scan sources, - # keep track of per-host scanning. - if ( orig in possible_scan_sources ) - { - if ( orig !in scan_triples ) - scan_triples[orig] = table() &mergeable; - - if ( resp !in scan_triples[orig] ) - scan_triples[orig][resp] = set() &mergeable; - - if ( service !in scan_triples[orig][resp] ) - { - add scan_triples[orig][resp][service]; - - if ( thresh_check_2(report_port_scan, rpts_idx, - orig, resp, - |scan_triples[orig][resp]|) ) - { - local m = |scan_triples[orig][resp]|; - NOTICE([$note=PortScan, $n=m, $src=orig, - $p=service, - $msg=fmt("%s has scanned %d ports of %s", orig, m, resp)]); - } - } - } - - return T; - } - - -# Hook into the catch&release dropping. When an address gets restored, we reset -# the source to allow dropping it again. -event Drop::address_restored(a: addr) - { - #Drop::debug_log(fmt("received restored for %s (scan.bro)", a)); - clear_addr(a); - } - -event Drop::address_cleared(a: addr) - { - #Drop::debug_log(fmt("received cleared for %s (scan.bro)", a)); - clear_addr(a); - } - -# When removing a possible scan source, we automatically delete its scanned -# hosts and ports. But we do not want the deletion propagated, because every -# peer calls the expire_function on its own (and thus applies the delete -# operation on its own table). -function remove_possible_source(s: set[addr], idx: addr): interval - { - suspend_state_updates(); - delete scan_triples[idx]; - resume_state_updates(); - - return 0 secs; - } - -# To recognize whether a certain threshhold vector (e.g. report_peer_scans) -# has been transgressed, a global variable containing the next vector index -# (idx) must be incremented. This cumbersome mechanism is necessary because -# values naturally don't increment by one (e.g. replayed table merges). -function thresh_check(v: vector of count, idx: table[addr] of count, - orig: addr, n: count): bool - { - if ( ignore_scanners_threshold > 0 && n > ignore_scanners_threshold ) - { - ignore_addr(orig); - return F; - } - - if ( idx[orig] < |v| && n >= v[idx[orig]] ) - { - ++idx[orig]; - return T; - } - else - return F; - } - -# Same as above, except the index has a different type signature. -function thresh_check_2(v: vector of count, idx: table[addr, addr] of count, - orig: addr, resp: addr, n: count): bool - { - if ( ignore_scanners_threshold > 0 && n > ignore_scanners_threshold ) - { - ignore_addr(orig); - return F; - } - - if ( idx[orig,resp] < |v| && n >= v[idx[orig, resp]] ) - { - ++idx[orig,resp]; - return T; - } - else - return F; - } - -event connection_established(c: connection) - { - local is_reverse_scan = (c$orig$state == TCP_INACTIVE); - Scan::check_scan(c, T, is_reverse_scan); - } - -event partial_connection(c: connection) - { - Scan::check_scan(c, T, F); - } - -event connection_attempt(c: connection) - { - Scan::check_scan(c, F, c$orig$state == TCP_INACTIVE); - } - -event connection_half_finished(c: connection) - { - # Half connections never were "established", so do scan-checking here. - Scan::check_scan(c, F, F); - } - -event connection_rejected(c: connection) - { - local is_reverse_scan = c$orig$state == TCP_RESET; - - Scan::check_scan(c, F, is_reverse_scan); - } - -event connection_reset(c: connection) - { - if ( c$orig$state == TCP_INACTIVE || c$resp$state == TCP_INACTIVE ) - # We never heard from one side - that looks like a scan. - Scan::check_scan(c, c$orig$size + c$resp$size > 0, - c$orig$state == TCP_INACTIVE); - } - -event connection_pending(c: connection) - { - if ( c$orig$state == TCP_PARTIAL && c$resp$state == TCP_INACTIVE ) - Scan::check_scan(c, F, F); - } - -# Report the remaining entries in the tables. -event bro_done() - { - for ( orig in distinct_peers ) - scan_summary(distinct_peers, orig); - - for ( orig in distinct_ports ) - port_summary(distinct_ports, orig); - - for ( orig in distinct_low_ports ) - lowport_summary(distinct_low_ports, orig); - } diff --git a/scripts/policy/protocols/conn/weirds.bro b/scripts/policy/protocols/conn/weirds.bro new file mode 100644 index 0000000000..9d6730819c --- /dev/null +++ b/scripts/policy/protocols/conn/weirds.bro @@ -0,0 +1,44 @@ +##! This script handles core generated connection related "weird" events to +##! push weird information about connections into the weird framework. +##! For live operational deployments, this can frequently cause load issues +##! due to large numbers of these events and quite possibly shouldn't be +##! loaded. + +@load base/frameworks/notice + +module Conn; + +export { + redef enum Notice::Type += { + ## Possible evasion; usually just chud. + Retransmission_Inconsistency, + ## Could mean packet drop; could also be chud. + Ack_Above_Hole, + ## Data has sequence hole; perhaps due to filtering. + Content_Gap, + }; +} + +event rexmit_inconsistency(c: connection, t1: string, t2: string) + { + NOTICE([$note=Retransmission_Inconsistency, + $conn=c, + $msg=fmt("%s rexmit inconsistency (%s) (%s)", + id_string(c$id), t1, t2), + $identifier=fmt("%s", c$id)]); + } + +event ack_above_hole(c: connection) + { + NOTICE([$note=Ack_Above_Hole, $conn=c, + $msg=fmt("%s ack above a hole", id_string(c$id))]); + } + +event content_gap(c: connection, is_orig: bool, seq: count, length: count) + { + NOTICE([$note=Content_Gap, $conn=c, + $msg=fmt("%s content gap (%s %d/%d)%s", + id_string(c$id), is_orig ? ">" : "<", seq, length, + is_external_connection(c) ? " [external]" : "")]); + } + diff --git a/scripts/policy/protocols/dns/auth-addl.bro b/scripts/policy/protocols/dns/auth-addl.bro index ba21131f7c..8c04379c1c 100644 --- a/scripts/policy/protocols/dns/auth-addl.bro +++ b/scripts/policy/protocols/dns/auth-addl.bro @@ -1,3 +1,9 @@ +##! This script adds authoritative and additional responses for the current +##! query to the DNS log. It can cause severe overhead due to the need +##! for all authoritative and additional responses to have events generated. +##! This script is not recommended for use on heavily loaded links. + +@load base/protocols/dns/main redef dns_skip_all_auth = F; redef dns_skip_all_addl = F; @@ -6,12 +12,14 @@ module DNS; export { redef record Info += { + ## Authoritative responses for the query. auth: set[string] &log &optional; + ## Additional responses for the query. addl: set[string] &log &optional; }; } -event do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=4 +event DNS::do_reply(c: connection, msg: dns_msg, ans: dns_answer, reply: string) &priority=4 { # The "ready" flag will be set here. This causes the setting from the # base script to be overridden since the base script will log immediately diff --git a/scripts/policy/protocols/dns/detect-external-names.bro b/scripts/policy/protocols/dns/detect-external-names.bro index fd49fee183..a1897d06e7 100644 --- a/scripts/policy/protocols/dns/detect-external-names.bro +++ b/scripts/policy/protocols/dns/detect-external-names.bro @@ -1,20 +1,18 @@ -##! Script for detecting strange activity within DNS. -##! -##! Notices raised: -##! -##! * :bro:enum:`DNS::External_Name` -##! -##! A remote host resolves to a local host, but the name is not considered -##! to be within a local zone. :bro:id:`local_zones` variable **must** -##! be set appropriately for this detection. +##! This script detects names which are not within zones considered to be +##! local but resolving to addresses considered local. +##! The :bro:id:`Site::local_zones` variable **must** be set appropriately for +##! this detection. + +@load base/frameworks/notice +@load base/utils/site module DNS; export { redef enum Notice::Type += { ## Raised when a non-local name is found to be pointing at a local host. - ## This only works appropriately when all of your authoritative DNS - ## servers are located in your :bro:id:`Site::local_nets`. + ## :bro:id:`Site::local_zones` variable **must** be set appropriately + ## for this detection. External_Name, }; } @@ -27,11 +25,11 @@ event dns_A_reply(c: connection, msg: dns_msg, ans: dns_answer, a: addr) &priori # Check for responses from remote hosts that point at local hosts # but the name is not considered to be within a "local" zone. if ( Site::is_local_addr(a) && # referring to a local host - !Site::is_local_addr(c$id$resp_h) && # response from an external nameserver - !Site::is_local_name(ans$query) ) # name isn't in a local zone. + ! Site::is_local_name(ans$query) ) # name isn't in a local zone. { NOTICE([$note=External_Name, $msg=fmt("%s is pointing to a local host - %s.", ans$query, a), - $conn=c]); + $conn=c, + $identifier=cat(a,ans$query)]); } } diff --git a/scripts/policy/protocols/ftp/detect.bro b/scripts/policy/protocols/ftp/detect.bro index 4e69dec655..e1bd627921 100644 --- a/scripts/policy/protocols/ftp/detect.bro +++ b/scripts/policy/protocols/ftp/detect.bro @@ -1,9 +1,13 @@ +##! Detect various potentially bad FTP activities. + +@load base/frameworks/notice +@load base/protocols/ftp module FTP; export { redef enum Notice::Type += { - ## This indicates that a successful response to a "SITE EXEC" + ## Indicates that a successful response to a "SITE EXEC" ## command/arg pair was seen. Site_Exec_Success, }; @@ -19,6 +23,7 @@ event ftp_reply(c: connection, code: count, msg: string, cont_resp: bool) &prior /[Ee][Xx][Ee][Cc]/ in c$ftp$cmdarg$arg ) { NOTICE([$note=Site_Exec_Success, $conn=c, - $msg=fmt("%s %s", c$ftp$cmdarg$cmd, c$ftp$cmdarg$arg)]); + $msg=fmt("FTP command: %s %s", c$ftp$cmdarg$cmd, c$ftp$cmdarg$arg), + $identifier=cat(c$id$orig_h, c$id$resp_h, "SITE EXEC")]); } - } \ No newline at end of file + } diff --git a/scripts/policy/protocols/ftp/software.bro b/scripts/policy/protocols/ftp/software.bro index 918123bb4c..0ae963d552 100644 --- a/scripts/policy/protocols/ftp/software.bro +++ b/scripts/policy/protocols/ftp/software.bro @@ -1,17 +1,21 @@ ##! Software detection with the FTP protocol. -##! -##! TODO: -##! -##! * Detect server software with initial 220 message -##! * Detect client software with password given for anonymous users -##! (e.g. cyberduck@example.net) + +# TODO: +# +# * Detect server software with initial 220 message +# * Detect client software with password given for anonymous users +# (e.g. cyberduck@example.net) + +@load base/frameworks/software module FTP; export { redef enum Software::Type += { - FTP_CLIENT, - FTP_SERVER, + ## Identifier for FTP clients in the software framework. + CLIENT, + ## Not currently implemented. + SERVER, }; } @@ -19,7 +23,6 @@ event ftp_request(c: connection, command: string, arg: string) &priority=4 { if ( command == "CLNT" ) { - local si = Software::parse(arg, c$id$orig_h, FTP_CLIENT); - Software::found(c$id, si); + Software::found(c$id, [$unparsed_version=arg, $host=c$id$orig_h, $software_type=CLIENT]); } } diff --git a/scripts/policy/protocols/http/detect-MHR.bro b/scripts/policy/protocols/http/detect-MHR.bro index fd54a62aeb..a0e3cb50fb 100644 --- a/scripts/policy/protocols/http/detect-MHR.bro +++ b/scripts/policy/protocols/http/detect-MHR.bro @@ -1,12 +1,18 @@ -##! This script takes MD5 sums of files transferred over HTTP and checks them with -##! Team Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/). +##! Detect file downloads over HTTP that have MD5 sums matching files in Team +##! Cymru's Malware Hash Registry (http://www.team-cymru.org/Services/MHR/). ##! By default, not all file transfers will have MD5 sums calculated. Read the -##! documentation for the base/protocols/http/file-hash.bro script to see how to -##! configure which transfers will have hashes calculated. +##! documentation for the :doc:base/protocols/http/file-hash.bro script to see +##! how to configure which transfers will have hashes calculated. + +@load base/frameworks/notice +@load base/protocols/http + +module HTTP; export { redef enum Notice::Type += { - ## If the MD5 sum of a file transferred over HTTP + ## The MD5 sum of a file transferred over HTTP matched in the + ## malware hash registry. Malware_Hash_Registry_Match }; } diff --git a/scripts/policy/protocols/http/detect-intel.bro b/scripts/policy/protocols/http/detect-intel.bro index ebe6713c03..281d705c13 100644 --- a/scripts/policy/protocols/http/detect-intel.bro +++ b/scripts/policy/protocols/http/detect-intel.bro @@ -1,4 +1,8 @@ -##! Intelligence based HTTP detections. +##! Intelligence based HTTP detections. Not yet working! + +@load base/protocols/http/main +@load base/protocols/http/utils +@load base/frameworks/intel/main module HTTP; @@ -14,4 +18,4 @@ event log_http(rec: Info) $sub=HTTP::build_url_http(rec), $id=rec$id]); } - } \ No newline at end of file + } diff --git a/scripts/policy/protocols/http/detect-sqli.bro b/scripts/policy/protocols/http/detect-sqli.bro index e2933626f7..a92565c63a 100644 --- a/scripts/policy/protocols/http/detect-sqli.bro +++ b/scripts/policy/protocols/http/detect-sqli.bro @@ -1,16 +1,25 @@ -##! SQL injection detection in HTTP. +##! SQL injection attack detection in HTTP. + +@load base/frameworks/notice +@load base/frameworks/metrics +@load base/protocols/http module HTTP; export { redef enum Notice::Type += { + ## Indicates that a host performing SQL injection attacks was detected. SQL_Injection_Attacker, - SQL_Injection_Attack, + ## Indicates that a host was seen to have SQL injection attacks against + ## it. This is tracked by IP address as opposed to hostname. + SQL_Injection_Victim, }; redef enum Metrics::ID += { - SQL_ATTACKS, - SQL_ATTACKS_AGAINST, + ## Metric to track SQL injection attackers. + SQLI_ATTACKER, + ## Metrics to track SQL injection victims. + SQLI_VICTIM, }; redef enum Tags += { @@ -22,8 +31,18 @@ export { ## Indicator of a cookie based SQL injection attack. Not implemented yet. COOKIE_SQLI, }; + + ## Defines the threshold that determines if an SQL injection attack + ## is ongoing based on the number of requests that appear to be SQL + ## injection attacks. + const sqli_requests_threshold = 50 &redef; + + ## Interval at which to watch for the + ## :bro:id:`HTTP::sqli_requests_threshold` variable to be crossed. + ## At the end of each interval the counter is reset. + const sqli_requests_interval = 5min &redef; - ## This regular expression is used to match URI based SQL injections + ## Regular expression is used to match URI based SQL injections. const match_sql_injection_uri = /[\?&][^[:blank:]\x00-\x37\|]+?=[\-[:alnum:]%]+([[:blank:]\x00-\x37]|\/\*.*?\*\/)*['"]?([[:blank:]\x00-\x37]|\/\*.*?\*\/|\)?;)+.*?([hH][aA][vV][iI][nN][gG]|[uU][nN][iI][oO][nN]|[eE][xX][eE][cC]|[sS][eE][lL][eE][cC][tT]|[dD][eE][lL][eE][tT][eE]|[dD][rR][oO][pP]|[dD][eE][cC][lL][aA][rR][eE]|[cC][rR][eE][aA][tT][eE]|[iI][nN][sS][eE][rR][tT])([[:blank:]\x00-\x37]|\/\*.*?\*\/)+/ | /[\?&][^[:blank:]\x00-\x37\|]+?=[\-0-9%]+([[:blank:]\x00-\x37]|\/\*.*?\*\/)*['"]?([[:blank:]\x00-\x37]|\/\*.*?\*\/|\)?;)+([xX]?[oO][rR]|[nN]?[aA][nN][dD])([[:blank:]\x00-\x37]|\/\*.*?\*\/)+['"]?(([^a-zA-Z&]+)?=|[eE][xX][iI][sS][tT][sS])/ @@ -33,15 +52,20 @@ export { | /\/\*![[:digit:]]{5}.*?\*\// &redef; } -event bro_init() +event bro_init() &priority=3 { - Metrics::add_filter(SQL_ATTACKS, [$log=F, - $break_interval=5mins, - $note=SQL_Injection_Attacker]); - Metrics::add_filter(SQL_ATTACKS_AGAINST, [$log=F, - $break_interval=5mins, - $note=SQL_Injection_Attack, - $notice_threshold=50]); + # Add filters to the metrics so that the metrics framework knows how to + # determine when it looks like an actual attack and how to respond when + # thresholds are crossed. + + Metrics::add_filter(SQLI_ATTACKER, [$log=F, + $notice_threshold=sqli_requests_threshold, + $break_interval=sqli_requests_interval, + $note=SQL_Injection_Attacker]); + Metrics::add_filter(SQLI_VICTIM, [$log=F, + $notice_threshold=sqli_requests_threshold, + $break_interval=sqli_requests_interval, + $note=SQL_Injection_Victim]); } event http_request(c: connection, method: string, original_URI: string, @@ -51,7 +75,7 @@ event http_request(c: connection, method: string, original_URI: string, { add c$http$tags[URI_SQLI]; - Metrics::add_data(SQL_ATTACKS, [$host=c$id$orig_h], 1); - Metrics::add_data(SQL_ATTACKS_AGAINST, [$host=c$id$resp_h], 1); + Metrics::add_data(SQLI_ATTACKER, [$host=c$id$orig_h], 1); + Metrics::add_data(SQLI_VICTIM, [$host=c$id$resp_h], 1); } - } \ No newline at end of file + } diff --git a/scripts/policy/protocols/http/detect-webapps.bro b/scripts/policy/protocols/http/detect-webapps.bro index 350f0def98..796da5c29a 100644 --- a/scripts/policy/protocols/http/detect-webapps.bro +++ b/scripts/policy/protocols/http/detect-webapps.bro @@ -1,3 +1,8 @@ +##! Detect and log web applications through the software framework. + +@load base/frameworks/signatures +@load base/frameworks/software +@load base/protocols/http module HTTP; @@ -7,10 +12,12 @@ redef Signatures::ignored_ids += /^webapp-/; export { redef enum Software::Type += { + ## Identifier for web applications in the software framework. WEB_APPLICATION, }; redef record Software::Info += { + ## Most root URL where the software was discovered. url: string &optional &log; }; } @@ -20,7 +27,8 @@ event signature_match(state: signature_state, msg: string, data: string) &priori if ( /^webapp-/ !in state$sig_id ) return; local c = state$conn; - local si = Software::parse(msg, c$id$resp_h, WEB_APPLICATION); + local si = Software::Info; + si = [$name=msg, $unparsed_version=msg, $host=c$id$resp_h, $host_p=c$id$resp_p, $software_type=WEB_APPLICATION]; si$url = build_url_http(c$http); if ( c$id$resp_h in Software::tracked && si$name in Software::tracked[c$id$resp_h] ) @@ -29,7 +37,8 @@ event signature_match(state: signature_state, msg: string, data: string) &priori # use that as the new url for the software. # PROBLEM: different version of the same software on the same server with a shared root path local is_substring = 0; - if ( Software::tracked[c$id$resp_h][si$name]?$url ) + if ( Software::tracked[c$id$resp_h][si$name]?$url && + |si$url| <= |Software::tracked[c$id$resp_h][si$name]$url| ) is_substring = strstr(Software::tracked[c$id$resp_h][si$name]$url, si$url); if ( is_substring == 1 ) diff --git a/scripts/policy/protocols/http/header-names.bro b/scripts/policy/protocols/http/header-names.bro new file mode 100644 index 0000000000..bd0e55f02f --- /dev/null +++ b/scripts/policy/protocols/http/header-names.bro @@ -0,0 +1,45 @@ +##! Extract and include the header names used for each request in the HTTP +##! logging stream. The headers in the logging stream will be stored in the +##! same order which they were seen on the wire. + +@load base/protocols/http/main + +module HTTP; + +export { + redef record Info += { + ## The vector of HTTP header names sent by the client. No header + ## values are included here, just the header names. + client_header_names: vector of string &log &optional; + + ## The vector of HTTP header names sent by the server. No header + ## values are included here, just the header names. + server_header_names: vector of string &log &optional; + }; + + ## A boolean value to determine if client header names are to be logged. + const log_client_header_names = T &redef; + + ## A boolean value to determine if server header names are to be logged. + const log_server_header_names = F &redef; +} + +event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=3 + { + if ( ! is_orig || ! c?$http ) + return; + + if ( log_client_header_names ) + { + if ( ! c$http?$client_header_names ) + c$http$client_header_names = vector(); + c$http$client_header_names[|c$http$client_header_names|] = name; + } + + if ( log_server_header_names ) + { + if ( ! c$http?$server_header_names ) + c$http$server_header_names = vector(); + c$http$server_header_names[|c$http$server_header_names|] = name; + } + } diff --git a/scripts/policy/protocols/http/headers.bro b/scripts/policy/protocols/http/headers.bro deleted file mode 100644 index 4451e876ec..0000000000 --- a/scripts/policy/protocols/http/headers.bro +++ /dev/null @@ -1,23 +0,0 @@ -##! Extract and include the header keys used for each request in the log. - -module HTTP; - -export { - redef record Info += { - ## The vector of HTTP headers. No header values are included here, just - ## the header names. - ## TODO: with an empty vector as &default, the vector isn't coerced to the - ## correct type. - headers: vector of string &log &optional; - }; -} - -event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=4 - { - if ( ! is_orig ) - return; - - if ( ! c$http?$headers ) - c$http$headers = vector(); - c$http$headers[|c$http$headers|] = name; - } diff --git a/scripts/policy/protocols/http/software-browser-plugins.bro b/scripts/policy/protocols/http/software-browser-plugins.bro new file mode 100644 index 0000000000..b466a9da40 --- /dev/null +++ b/scripts/policy/protocols/http/software-browser-plugins.bro @@ -0,0 +1,60 @@ +##! Detect browser plugins as they leak through requests to Omniture +##! advertising servers. + +@load base/protocols/http +@load base/frameworks/software + +module HTTP; + +export { + redef record Info += { + ## Indicates if the server is an omniture advertising server. + omniture: bool &default=F; + }; + + redef enum Software::Type += { + ## Identifier for browser plugins in the software framework. + BROWSER_PLUGIN + }; +} + +event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=3 + { + if ( is_orig ) + { + if ( name == "X-FLASH-VERSION" ) + { + # Flash doesn't include it's name so we'll add it here since it + # simplifies the version parsing. + value = cat("Flash/", value); + Software::found(c$id, [$unparsed_version=value, $host=c$id$orig_h, $software_type=BROWSER_PLUGIN]); + } + } + else + { + # Find if the server is Omniture + if ( name == "SERVER" && /^Omniture/ in value ) + c$http$omniture = T; + } + } + +event log_http(rec: Info) + { + # We only want to inspect requests that were sent to omniture advertising + # servers. + if ( rec$omniture && rec?$uri ) + { + # We do {5,} because sometimes we see p=6 in the urls. + local parts = split_n(rec$uri, /&p=([^&]{5,});&/, T, 1); + if ( 2 in parts ) + { + # We do sub_bytes here just to remove the extra extracted + # characters from the regex split above. + local sw = sub_bytes(parts[2], 4, |parts[2]|-5); + local plugins = split(sw, /[[:blank:]]*;[[:blank:]]*/); + + for ( i in plugins ) + Software::found(rec$id, [$unparsed_version=plugins[i], $host=rec$id$orig_h, $software_type=BROWSER_PLUGIN]); + } + } + } diff --git a/scripts/policy/protocols/http/software.bro b/scripts/policy/protocols/http/software.bro index 5a16b862a6..2ad4246a56 100644 --- a/scripts/policy/protocols/http/software.bro +++ b/scripts/policy/protocols/http/software.bro @@ -1,22 +1,21 @@ ##! Software identification and extraction for HTTP traffic. +@load base/frameworks/software + module HTTP; export { redef enum Software::Type += { - WEB_SERVER, - WEB_APPSERVER, - WEB_BROWSER, - WEB_BROWSER_PLUGIN + ## Identifier for web servers in the software framework. + SERVER, + ## Identifier for app servers in the software framework. + APPSERVER, + ## Identifier for web browsers in the software framework. + BROWSER, }; ## The pattern of HTTP User-Agents which you would like to ignore. const ignored_user_agents = /NO_DEFAULT/ &redef; - - ## These are patterns to identify browser plugins (including toolbars) - ## based on the User-Agent header. - const plugin_user_agents = /BingBar [0-9\.]*/ ##< Bing toolbar - | /GoogleToolbar [0-9\.]*;/ &redef; ##< Google toolbar } event http_header(c: connection, is_orig: bool, name: string, value: string) &priority=2 @@ -24,32 +23,18 @@ event http_header(c: connection, is_orig: bool, name: string, value: string) &pr if ( is_orig ) { if ( name == "USER-AGENT" && ignored_user_agents !in value ) - { - local ua_type = WEB_BROWSER; - if ( plugin_user_agents in value ) - ua_type = WEB_BROWSER_PLUGIN; - - Software::found(c$id, Software::parse(value, c$id$orig_h, ua_type)); - } - else if ( name == "X-FLASH-VERSION" ) - { - # Flash doesn't include it's name so we'll add it here since it - # simplifies the version parsing. - value = cat("Flash/", value); - local flash_version = Software::parse(value, c$id$orig_h, WEB_BROWSER_PLUGIN); - Software::found(c$id, flash_version); - } + Software::found(c$id, [$unparsed_version=value, $host=c$id$orig_h, $software_type=BROWSER]); } else { if ( name == "SERVER" ) - Software::found(c$id, Software::parse(value, c$id$resp_h, WEB_SERVER)); + Software::found(c$id, [$unparsed_version=value, $host=c$id$resp_h, $host_p=c$id$resp_p, $software_type=SERVER]); else if ( name == "X-POWERED-BY" ) - Software::found(c$id, Software::parse(value, c$id$resp_h, WEB_APPSERVER)); + Software::found(c$id, [$unparsed_version=value, $host=c$id$resp_h, $host_p=c$id$resp_p, $software_type=APPSERVER]); else if ( name == "MICROSOFTSHAREPOINTTEAMSERVICES" ) { value = cat("SharePoint/", value); - Software::found(c$id, Software::parse(value, c$id$resp_h, WEB_APPSERVER)); + Software::found(c$id, [$unparsed_version=value, $host=c$id$resp_h, $host_p=c$id$resp_p, $software_type=APPSERVER]); } } - } \ No newline at end of file + } diff --git a/scripts/policy/protocols/http/var-extraction-cookies.bro b/scripts/policy/protocols/http/var-extraction-cookies.bro index b30be9d2c1..610c6e1381 100644 --- a/scripts/policy/protocols/http/var-extraction-cookies.bro +++ b/scripts/policy/protocols/http/var-extraction-cookies.bro @@ -1,8 +1,12 @@ -##! This script extracts and logs variables from cookies sent by clients +##! Extracts and logs variables names from cookies sent by clients. + +@load base/protocols/http/main +@load base/protocols/http/utils module HTTP; redef record Info += { + ## Variable names extracted from all cookies. cookie_vars: vector of string &optional &log; }; diff --git a/scripts/policy/protocols/http/var-extraction-uri.bro b/scripts/policy/protocols/http/var-extraction-uri.bro index a6e6b1d971..27ee89d6f2 100644 --- a/scripts/policy/protocols/http/var-extraction-uri.bro +++ b/scripts/policy/protocols/http/var-extraction-uri.bro @@ -1,8 +1,12 @@ -##! This script extracts and logs variables from the requested URI +##! Extracts and log variables from the requested URI in the default HTTP +##! logging stream. + +@load base/protocols/http module HTTP; redef record Info += { + ## Variable names from the URI. uri_vars: vector of string &optional &log; }; diff --git a/scripts/policy/protocols/smtp/detect-suspicious-orig.bro b/scripts/policy/protocols/smtp/detect-suspicious-orig.bro index 26f667cfd6..4635b17a83 100644 --- a/scripts/policy/protocols/smtp/detect-suspicious-orig.bro +++ b/scripts/policy/protocols/smtp/detect-suspicious-orig.bro @@ -1,3 +1,5 @@ +@load base/frameworks/notice/main +@load base/protocols/smtp/main module SMTP; @@ -23,11 +25,13 @@ event log_smtp(rec: Info) ip = rec$x_originating_ip; loc = lookup_location(ip); - if ( loc$country_code in suspicious_origination_countries || + if ( (loc?$country_code && + loc$country_code in suspicious_origination_countries) || ip in suspicious_origination_networks ) { NOTICE([$note=Suspicious_Origination, - $msg=fmt("An email originated from %s (%s).", loc$country_code, ip), + $msg=fmt("An email originated from %s (%s).", + loc?$country_code ? loc$country_code : "", ip), $id=rec$id]); } } @@ -36,11 +40,12 @@ event log_smtp(rec: Info) ip = rec$path[|rec$path|-1]; loc = lookup_location(ip); - if ( loc$country_code in suspicious_origination_countries || + if ( (loc?$country_code && + loc$country_code in suspicious_origination_countries) || ip in suspicious_origination_networks ) { NOTICE([$note=Suspicious_Origination, - $msg=fmt("Based up Received headers, email originated from %s (%s).", loc$country_code, ip), + $msg=fmt("Based up Received headers, email originated from %s (%s).", loc?$country_code ? loc$country_code : "", ip), $id=rec$id]); } } diff --git a/scripts/policy/protocols/smtp/software.bro b/scripts/policy/protocols/smtp/software.bro index ccb7366a2a..f520485338 100644 --- a/scripts/policy/protocols/smtp/software.bro +++ b/scripts/policy/protocols/smtp/software.bro @@ -7,6 +7,9 @@ ##! * Find some heuristic to determine if email was sent through ##! a MS Exhange webmail interface as opposed to a desktop client. +@load base/frameworks/software/main +@load base/protocols/smtp/main + module SMTP; export { @@ -72,8 +75,7 @@ event log_smtp(rec: Info) if ( addr_matches_host(rec$id$orig_h, detect_clients_in_messages_from) ) { - local s = Software::parse(rec$user_agent, client_ip, s_type); - Software::found(rec$id, s); + Software::found(rec$id, [$unparsed_version=rec$user_agent, $host=client_ip, $software_type=s_type]); } } } diff --git a/scripts/policy/protocols/ssh/detect-bruteforcing.bro b/scripts/policy/protocols/ssh/detect-bruteforcing.bro index fb1c075d86..aa6e920c12 100644 --- a/scripts/policy/protocols/ssh/detect-bruteforcing.bro +++ b/scripts/policy/protocols/ssh/detect-bruteforcing.bro @@ -1,20 +1,27 @@ +##! Detect hosts which are doing password guessing attacks and/or password +##! bruteforcing over SSH. + +@load base/protocols/ssh +@load base/frameworks/metrics +@load base/frameworks/notice +@load base/frameworks/intel module SSH; export { redef enum Notice::Type += { ## Indicates that a host has been identified as crossing the - ## :bro:id:`password_guesses_limit` threshold with heuristically + ## :bro:id:`SSH::password_guesses_limit` threshold with heuristically ## determined failed logins. Password_Guessing, ## Indicates that a host previously identified as a "password guesser" - ## has now had a heuristically successful login attempt. + ## has now had a heuristically successful login attempt. This is not + ## currently implemented. Login_By_Password_Guesser, }; redef enum Metrics::ID += { - ## This metric is to measure failed logins with the hope of detecting - ## bruteforcing hosts. + ## Metric is to measure failed logins. FAILED_LOGIN, }; @@ -32,8 +39,9 @@ export { ## client subnets and the yield value represents server subnets. const ignore_guessers: table[subnet] of subnet &redef; - ## Keeps track of hosts identified as guessing passwords. - global password_guessers: set[addr] &read_expire=guessing_timeout+1hr &synchronized; + ## Tracks hosts identified as guessing passwords. + global password_guessers: set[addr] + &read_expire=guessing_timeout+1hr &synchronized &redef; } event bro_init() @@ -68,4 +76,4 @@ event SSH::heuristic_failed_login(c: connection) if ( ! (id$orig_h in ignore_guessers && id$resp_h in ignore_guessers[id$orig_h]) ) Metrics::add_data(FAILED_LOGIN, [$host=id$orig_h], 1); - } \ No newline at end of file + } diff --git a/scripts/policy/protocols/ssh/geo-data.bro b/scripts/policy/protocols/ssh/geo-data.bro index 97bd0a5803..0f8bb932fe 100644 --- a/scripts/policy/protocols/ssh/geo-data.bro +++ b/scripts/policy/protocols/ssh/geo-data.bro @@ -1,5 +1,7 @@ -##! This implements all of the additional information and geodata detections -##! for SSH analysis. +##! Geodata based detections for SSH analysis. + +@load base/frameworks/notice +@load base/protocols/ssh module SSH; @@ -8,17 +10,17 @@ export { ## If an SSH login is seen to or from a "watched" country based on the ## :bro:id:`SSH::watched_countries` variable then this notice will ## be generated. - Login_From_Watched_Country, + Watched_Country_Login, }; - ## The set of countries for which you'd like to throw notices upon - ## successful login - const watched_countries: set[string] = {"RO"} &redef; - redef record Info += { ## Add geographic data related to the "remote" host of the connection. remote_location: geo_location &log &optional; }; + + ## The set of countries for which you'd like to generate notices upon + ## successful login. + const watched_countries: set[string] = {"RO"} &redef; } event SSH::heuristic_successful_login(c: connection) &priority=5 @@ -30,10 +32,12 @@ event SSH::heuristic_successful_login(c: connection) &priority=5 # Add the location data to the SSH record. c$ssh$remote_location = location; - if ( location$country_code in watched_countries ) + if ( location?$country_code && location$country_code in watched_countries ) { - NOTICE([$note=Login_From_Watched_Country, + NOTICE([$note=Watched_Country_Login, $conn=c, - $msg=fmt("SSH login from watched country: %s", location$country_code)]); + $msg=fmt("SSH login %s watched country: %s", + (c$ssh$direction == OUTBOUND) ? "to" : "from", + location$country_code)]); } } diff --git a/scripts/policy/protocols/ssh/interesting-hostnames.bro b/scripts/policy/protocols/ssh/interesting-hostnames.bro index 93767e5f54..f79c67ede9 100644 --- a/scripts/policy/protocols/ssh/interesting-hostnames.bro +++ b/scripts/policy/protocols/ssh/interesting-hostnames.bro @@ -1,14 +1,19 @@ +##! This script will generate a notice if an apparent SSH login originates +##! or heads to a host with a reverse hostname that looks suspicious. By +##! default, the regular expression to match "interesting" hostnames includes +##! names that are typically used for infrastructure hosts like nameservers, +##! mail servers, web servers and ftp servers. + +@load base/frameworks/notice module SSH; export { redef enum Notice::Type += { - ## Generated if a login originates from a host matched by the - ## :bro:id:`interesting_hostnames` regular expression. - Login_From_Interesting_Hostname, - ## Generated if a login goes to a host matched by the - ## :bro:id:`interesting_hostnames` regular expression. - Login_To_Interesting_Hostname, + ## Generated if a login originates or responds with a host where the + ## reverse hostname lookup resolves to a name matched by the + ## :bro:id:`SSH::interesting_hostnames` regular expression. + Interesting_Hostname_Login, }; ## Strange/bad host names to see successful SSH logins from or to. @@ -24,26 +29,18 @@ export { event SSH::heuristic_successful_login(c: connection) { - # Check to see if this login came from an interesting hostname. - when ( local orig_hostname = lookup_addr(c$id$orig_h) ) + for ( host in set(c$id$orig_h, c$id$resp_h) ) { - if ( interesting_hostnames in orig_hostname ) + when ( local hostname = lookup_addr(host) ) { - NOTICE([$note=Login_From_Interesting_Hostname, - $conn=c, - $msg=fmt("Interesting login from hostname: %s", orig_hostname), - $sub=orig_hostname]); - } - } - # Check to see if this login went to an interesting hostname. - when ( local resp_hostname = lookup_addr(c$id$resp_h) ) - { - if ( interesting_hostnames in resp_hostname ) - { - NOTICE([$note=Login_To_Interesting_Hostname, - $conn=c, - $msg=fmt("Interesting login to hostname: %s", resp_hostname), - $sub=resp_hostname]); + if ( interesting_hostnames in hostname ) + { + NOTICE([$note=Interesting_Hostname_Login, + $msg=fmt("Possible SSH login involving a %s %s with an interesting hostname.", + Site::is_local_addr(host) ? "local" : "remote", + host == c$id$orig_h ? "client" : "server"), + $sub=hostname, $conn=c]); + } } } } diff --git a/scripts/policy/protocols/ssh/software.bro b/scripts/policy/protocols/ssh/software.bro index 1aa3bce1a2..ba03bed284 100644 --- a/scripts/policy/protocols/ssh/software.bro +++ b/scripts/policy/protocols/ssh/software.bro @@ -1,9 +1,15 @@ +##! Extracts SSH client and server information from SSH +##! connections and forwards it to the software framework. + +@load base/frameworks/software module SSH; export { redef enum Software::Type += { + ## Identifier for SSH clients in the software framework. SERVER, + ## Identifier for SSH servers in the software framework. CLIENT, }; } @@ -12,14 +18,12 @@ event ssh_client_version(c: connection, version: string) &priority=4 { # Get rid of the protocol information when passing to the software framework. local cleaned_version = sub(version, /^SSH[0-9\.\-]+/, ""); - local si = Software::parse(cleaned_version, c$id$orig_h, CLIENT); - Software::found(c$id, si); + Software::found(c$id, [$unparsed_version=cleaned_version, $host=c$id$orig_h, $software_type=CLIENT]); } event ssh_server_version(c: connection, version: string) &priority=4 { # Get rid of the protocol information when passing to the software framework. local cleaned_version = sub(version, /SSH[0-9\.\-]{2,}/, ""); - local si = Software::parse(cleaned_version, c$id$resp_h, SERVER); - Software::found(c$id, si); + Software::found(c$id, [$unparsed_version=cleaned_version, $host=c$id$resp_h, $host_p=c$id$resp_p, $software_type=SERVER]); } diff --git a/scripts/policy/protocols/ssl/cert-hash.bro b/scripts/policy/protocols/ssl/cert-hash.bro new file mode 100644 index 0000000000..32a165a946 --- /dev/null +++ b/scripts/policy/protocols/ssl/cert-hash.bro @@ -0,0 +1,22 @@ +##! Calculate MD5 sums for server DER formatted certificates. + +@load base/protocols/ssl + +module SSL; + +export { + redef record Info += { + ## MD5 sum of the raw server certificate. + cert_hash: string &log &optional; + }; +} + +event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string) &priority=4 + { + # We aren't tracking client certificates yet and we are also only tracking + # the primary cert. Watch that this came from an SSL analyzed session too. + if ( is_orig || chain_idx != 0 || ! c?$ssl ) + return; + + c$ssl$cert_hash = md5_hash(der_cert); + } \ No newline at end of file diff --git a/scripts/policy/protocols/ssl/expiring-certs.bro b/scripts/policy/protocols/ssl/expiring-certs.bro new file mode 100644 index 0000000000..80616e6a99 --- /dev/null +++ b/scripts/policy/protocols/ssl/expiring-certs.bro @@ -0,0 +1,63 @@ +##! Generate notices when X.509 certificates over SSL/TLS are expired or +##! going to expire soon based on the date and time values stored within the +##! certificate. + +@load base/protocols/ssl +@load base/frameworks/notice +@load base/utils/directions-and-hosts + +@load protocols/ssl/cert-hash + +module SSL; + +export { + redef enum Notice::Type += { + ## Indicates that a certificate's NotValidAfter date has lapsed and + ## the certificate is now invalid. + Certificate_Expired, + ## Indicates that a certificate is going to expire within + ## :bro:id:`SSL::notify_when_cert_expiring_in`. + Certificate_Expires_Soon, + ## Indicates that a certificate's NotValidBefore date is future dated. + Certificate_Not_Valid_Yet, + }; + + ## The category of hosts you would like to be notified about which have + ## certificates that are going to be expiring soon. By default, these + ## notices will be suppressed by the notice framework for 1 day after + ## a particular certificate has had a notice generated. + ## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS + const notify_certs_expiration = LOCAL_HOSTS &redef; + + ## The time before a certificate is going to expire that you would like to + ## start receiving :bro:enum:`SSL::Certificate_Expires_Soon` notices. + const notify_when_cert_expiring_in = 30days &redef; +} + +event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string) &priority=3 + { + # If this isn't the host cert or we aren't interested in the server, just return. + if ( is_orig || + chain_idx != 0 || + ! c$ssl?$cert_hash || + ! addr_matches_host(c$id$resp_h, notify_certs_expiration) ) + return; + + if ( cert$not_valid_before > network_time() ) + NOTICE([$note=Certificate_Not_Valid_Yet, + $conn=c, $suppress_for=1day, + $msg=fmt("Certificate %s isn't valid until %T", cert$subject, cert$not_valid_before), + $identifier=cat(c$id$resp_h, c$id$resp_p, c$ssl$cert_hash)]); + + else if ( cert$not_valid_after < network_time() ) + NOTICE([$note=Certificate_Expired, + $conn=c, $suppress_for=1day, + $msg=fmt("Certificate %s expired at %T", cert$subject, cert$not_valid_after), + $identifier=cat(c$id$resp_h, c$id$resp_p, c$ssl$cert_hash)]); + + else if ( cert$not_valid_after - notify_when_cert_expiring_in < network_time() ) + NOTICE([$note=Certificate_Expires_Soon, + $msg=fmt("Certificate %s is going to expire at %T", cert$subject, cert$not_valid_after), + $conn=c, $suppress_for=1day, + $identifier=cat(c$id$resp_h, c$id$resp_p, c$ssl$cert_hash)]); + } diff --git a/scripts/policy/protocols/ssl/extract-certs-pem.bro b/scripts/policy/protocols/ssl/extract-certs-pem.bro new file mode 100644 index 0000000000..420c60a4fd --- /dev/null +++ b/scripts/policy/protocols/ssl/extract-certs-pem.bro @@ -0,0 +1,49 @@ +##! This script is used to extract host certificates seen on the wire to disk +##! after being converted to PEM files. The certificates will be stored in +##! a single file, one for local certificates and one for remote certificates. +##! +##! ..note:: +##! +##! - It doesn't work well on a cluster because each worker will write its +##! own certificate files and no duplicate checking is done across +##! clusters so each node would log each certificate. +##! +##! - If there is a certificate input based vulnerability found in the +##! openssl command line utility, you could be in trouble because this +##! script uses that utility to convert from DER to PEM certificates. +##! + +@load base/protocols/ssl +@load base/utils/directions-and-hosts +@load protocols/ssl/cert-hash + +module SSL; + +export { + ## Control if host certificates offered by the defined hosts + ## will be written to the PEM certificates file. + ## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS + const extract_certs_pem = LOCAL_HOSTS &redef; +} + +# This is an internally maintained variable to prevent relogging of +# certificates that have already been seen. It is indexed on an md5 sum of +# the certificate. +global extracted_certs: set[string] = set() &read_expire=1hr &redef; + +event ssl_established(c: connection) &priority=5 + { + if ( ! c$ssl?$cert ) + return; + if ( ! addr_matches_host(c$id$resp_h, extract_certs_pem) ) + return; + + if ( c$ssl$cert_hash in extracted_certs ) + # If we already extracted this cert, don't do it again. + return; + + add extracted_certs[c$ssl$cert_hash]; + local side = Site::is_local_addr(c$id$resp_h) ? "local" : "remote"; + local cmd = fmt("%s x509 -inform DER -outform PEM >> certs-%s.pem", openssl_util, side); + piped_exec(cmd, c$ssl$cert); + } diff --git a/scripts/policy/protocols/ssl/known-certs.bro b/scripts/policy/protocols/ssl/known-certs.bro index a8815dca07..3986a9aa1e 100644 --- a/scripts/policy/protocols/ssl/known-certs.bro +++ b/scripts/policy/protocols/ssl/known-certs.bro @@ -1,10 +1,15 @@ +##! Log information about certificates while attempting to avoid duplicate logging. -module KnownCerts; +@load base/utils/directions-and-hosts +@load base/protocols/ssl +@load protocols/ssl/cert-hash + +module Known; export { - redef enum Log::ID += { KNOWN_CERTS }; + redef enum Log::ID += { CERTS_LOG }; - type Info: record { + type CertsInfo: record { ## The timestamp when the certificate was detected. ts: time &log; ## The address that offered the certificate. @@ -22,36 +27,37 @@ export { ## The certificates whose existence should be logged and tracked. ## Choices are: LOCAL_HOSTS, REMOTE_HOSTS, ALL_HOSTS, NO_HOSTS - const asset_tracking = LOCAL_HOSTS &redef; + const cert_tracking = LOCAL_HOSTS &redef; ## The set of all known certificates to store for preventing duplicate ## logging. It can also be used from other scripts to ## inspect if a certificate has been seen in use. The string value - ## in the set is for storing the certificate's serial number. - global known_certs: set[addr, string] &create_expire=1day &synchronized &redef; + ## in the set is for storing the DER formatted certificate's MD5 hash. + global certs: set[addr, string] &create_expire=1day &synchronized &redef; - global log_known_certs: event(rec: Info); + ## Event that can be handled to access the loggable record as it is sent + ## on to the logging framework. + global log_known_certs: event(rec: CertsInfo); } -event bro_init() +event bro_init() &priority=5 { - Log::create_stream(KNOWN_CERTS, [$columns=Info, $ev=log_known_certs]); + Log::create_stream(Known::CERTS_LOG, [$columns=CertsInfo, $ev=log_known_certs]); } -event x509_certificate(c: connection, cert: X509, is_server: bool, chain_idx: count, chain_len: count, der_cert: string) +event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string) &priority=3 { - # We aren't tracking client certificates yet. - if ( ! is_server ) return; - # We are also only tracking the primary cert. - if ( chain_idx != 0 ) return; - + # Make sure this is the server cert and we have a hash for it. + if ( is_orig || chain_idx != 0 || ! c$ssl?$cert_hash ) + return; + local host = c$id$resp_h; - if ( [host, cert$serial] !in known_certs && addr_matches_host(host, asset_tracking) ) + if ( [host, c$ssl$cert_hash] !in certs && addr_matches_host(host, cert_tracking) ) { - add known_certs[host, cert$serial]; - Log::write(KNOWN_CERTS, [$ts=network_time(), $host=host, - $port_num=c$id$resp_p, $subject=cert$subject, - $issuer_subject=cert$issuer, - $serial=cert$serial]); + add certs[host, c$ssl$cert_hash]; + Log::write(Known::CERTS_LOG, [$ts=network_time(), $host=host, + $port_num=c$id$resp_p, $subject=cert$subject, + $issuer_subject=cert$issuer, + $serial=cert$serial]); } } diff --git a/scripts/policy/protocols/ssl/validate-certs.bro b/scripts/policy/protocols/ssl/validate-certs.bro index 43920557f4..03624eac84 100644 --- a/scripts/policy/protocols/ssl/validate-certs.bro +++ b/scripts/policy/protocols/ssl/validate-certs.bro @@ -1,30 +1,52 @@ +##! Perform full certificate chain validation for SSL certificates. + +@load base/frameworks/notice +@load base/protocols/ssl +@load protocols/ssl/cert-hash module SSL; export { redef enum Notice::Type += { + ## This notice indicates that the result of validating the certificate + ## along with it's full certificate chain was invalid. Invalid_Server_Cert }; redef record Info += { + ## Result of certificate validation for this connection. validation_status: string &log &optional; }; - + + ## MD5 hash values for recently validated certs along with the validation + ## status message are kept in this table to avoid constant validation + ## everytime the same certificate is seen. + global recently_validated_certs: table[string] of string = table() + &read_expire=5mins &synchronized &redef; } -event ssl_established(c: connection) &priority=5 +event ssl_established(c: connection) &priority=3 { # If there aren't any certs we can't very well do certificate validation. - if ( !c$ssl?$cert || !c$ssl?$cert_chain ) + if ( ! c$ssl?$cert || ! c$ssl?$cert_chain ) return; + + if ( c$ssl?$cert_hash && c$ssl$cert_hash in recently_validated_certs ) + { + c$ssl$validation_status = recently_validated_certs[c$ssl$cert_hash]; + } + else + { + local result = x509_verify(c$ssl$cert, c$ssl$cert_chain, root_certs); + c$ssl$validation_status = x509_err2str(result); + } - local result = x509_verify(c$ssl$cert, c$ssl$cert_chain, root_certs); - c$ssl$validation_status = x509_err2str(result); - if ( result != 0 ) + if ( c$ssl$validation_status != "ok" ) { local message = fmt("SSL certificate validation failed with (%s)", c$ssl$validation_status); NOTICE([$note=Invalid_Server_Cert, $msg=message, - $sub=c$ssl$subject, $conn=c]); + $sub=c$ssl$subject, $conn=c, + $identifier=cat(c$id$resp_h,c$id$resp_p,c$ssl$validation_status,c$ssl$cert_hash)]); } } diff --git a/scripts/policy/tuning/defaults/__load__.bro b/scripts/policy/tuning/defaults/__load__.bro index 790a706b7d..ffc760e5f7 100644 --- a/scripts/policy/tuning/defaults/__load__.bro +++ b/scripts/policy/tuning/defaults/__load__.bro @@ -1,3 +1,2 @@ -@load ./remove-high-volume-notices @load ./packet-fragments @load ./warnings \ No newline at end of file diff --git a/scripts/policy/tuning/defaults/remove-high-volume-notices.bro b/scripts/policy/tuning/defaults/remove-high-volume-notices.bro deleted file mode 100644 index 1133bf952b..0000000000 --- a/scripts/policy/tuning/defaults/remove-high-volume-notices.bro +++ /dev/null @@ -1,11 +0,0 @@ -##! This strives to tune out high volume and less useful data -##! from the notice log. - -# Remove these notices from logging since they can be too noisy. -redef Notice::ignored_types += { - Weird::Content_Gap, - Weird::Ack_Above_Hole, - Weird::Retransmission_Inconsistency, - ## Only allow these to go in the weird log. - Weird::Weird_Activity, -}; diff --git a/scripts/policy/tuning/defaults/warnings.bro b/scripts/policy/tuning/defaults/warnings.bro index ea8f18c3bc..cedc3d62ad 100644 --- a/scripts/policy/tuning/defaults/warnings.bro +++ b/scripts/policy/tuning/defaults/warnings.bro @@ -2,8 +2,10 @@ ##! good to set in most cases or other things that could be done to achieve ##! better detection. +@load base/utils/site + event bro_init() &priority=-10 { if ( |Site::local_nets| == 0 ) print "WARNING: No Site::local_nets have been defined. It's usually a good idea to define your local networks."; - } \ No newline at end of file + } diff --git a/scripts/policy/tuning/track-all-assets.bro b/scripts/policy/tuning/track-all-assets.bro index fe61ff93b6..b00dc8ad40 100644 --- a/scripts/policy/tuning/track-all-assets.bro +++ b/scripts/policy/tuning/track-all-assets.bro @@ -1,9 +1,9 @@ - +@load base/frameworks/software @load protocols/conn/known-hosts @load protocols/conn/known-services @load protocols/ssl/known-certs -redef Software::asset_tracking = ALL_HOSTS; -redef KnownHosts::asset_tracking = ALL_HOSTS; -redef KnownServices::asset_tracking = ALL_HOSTS; -redef KnownCerts::asset_tracking = ALL_HOSTS; +redef Software::asset_tracking = ALL_HOSTS; +redef Known::host_tracking = ALL_HOSTS; +redef Known::service_tracking = ALL_HOSTS; +redef Known::cert_tracking = ALL_HOSTS; diff --git a/scripts/site/local-manager.bro b/scripts/site/local-manager.bro index aa28bd79da..5e6005f21e 100644 --- a/scripts/site/local-manager.bro +++ b/scripts/site/local-manager.bro @@ -1,7 +1 @@ -##! Local site policy loaded only by the manager in a cluster. - -# If you are running a cluster you should define your Notice::policy here -# so that notice processing occurs on the manager. -redef Notice::policy += { - -}; +##! Local site policy loaded only by the manager if Bro is running as a cluster. diff --git a/scripts/site/local-proxy.bro b/scripts/site/local-proxy.bro index 1b71cc1870..478ba6d048 100644 --- a/scripts/site/local-proxy.bro +++ b/scripts/site/local-proxy.bro @@ -1,2 +1 @@ ##! Local site policy loaded only by the proxies if Bro is running as a cluster. - diff --git a/scripts/site/local.bro b/scripts/site/local.bro index f894a30432..9681f7a75c 100644 --- a/scripts/site/local.bro +++ b/scripts/site/local.bro @@ -1,33 +1,46 @@ -##! Local site policy. Customize as appropriate. This file will not be -##! overwritten when upgrading or reinstalling. +##! Local site policy. Customize as appropriate. +##! +##! This file will not be overwritten when upgrading or reinstalling! -# Load the script to log which script were loaded during each run +# This script logs which scripts were loaded during each run. @load misc/loaded-scripts # Apply the default tuning scripts for common tuning settings. @load tuning/defaults -# Vulnerable versions of software to generate notices for when discovered. +# Generate notices when vulnerable versions of software are discovered. # The default is to only monitor software found in the address space defined # as "local". Refer to the software framework's documentation for more # information. @load frameworks/software/vulnerable + +# Example vulnerable software. This needs to be updated and maintained over +# time as new vulnerabilities are discovered. redef Software::vulnerable_versions += { ["Flash"] = [$major=10,$minor=2,$minor2=153,$addl="1"], ["Java"] = [$major=1,$minor=6,$minor2=0,$addl="22"], }; +# Detect software changing (e.g. attacker installing hacked SSHD). +@load frameworks/software/version-changes + # This adds signatures to detect cleartext forward and reverse windows shells. redef signature_files += "frameworks/signatures/detect-windows-shells.sig"; +# Uncomment the following line to begin receiving (by default hourly) emails +# containing all of your notices. +# redef Notice::policy += { [$action = Notice::ACTION_ALARM, $priority = 0] }; + # Load all of the scripts that detect software in various protocols. -@load protocols/http/software -#@load protocols/http/detect-webapps @load protocols/ftp/software @load protocols/smtp/software @load protocols/ssh/software +@load protocols/http/software +# The detect-webapps script could possibly cause performance trouble when +# running on live traffic. Enable it cautiously. +#@load protocols/http/detect-webapps -# Load the script to detect DNS results pointing toward your Site::local_nets +# This script detects DNS results pointing toward your Site::local_nets # where the name is not part of your local DNS zone and is being hosted # externally. Requires that the Site::local_zones variable is defined. @load protocols/dns/detect-external-names @@ -35,15 +48,12 @@ redef signature_files += "frameworks/signatures/detect-windows-shells.sig"; # Script to detect various activity in FTP sessions. @load protocols/ftp/detect -# Detect software changing (e.g. attacker installing hacked SSHD). -@load frameworks/software/version-changes - # Scripts that do asset tracking. @load protocols/conn/known-hosts @load protocols/conn/known-services @load protocols/ssl/known-certs -# Load the script to enable SSL/TLS certificate validation. +# This script enables SSL/TLS certificate validation. @load protocols/ssl/validate-certs # If you have libGeoIP support built in, do some geographic detections and @@ -56,13 +66,5 @@ redef signature_files += "frameworks/signatures/detect-windows-shells.sig"; # Detect MD5 sums in Team Cymru's Malware Hash Registry. @load protocols/http/detect-MHR -# Detect SQL injection attacks +# Detect SQL injection attacks. @load protocols/http/detect-sqli - -# Uncomment this redef if you want to extract SMTP MIME entities for -# some file types. The numbers given indicate how many bytes to extract for -# the various mime types. -redef SMTP::entity_excerpt_len += { -# ["text/plain"] = 1024, -# ["text/html"] = 1024, -}; diff --git a/scripts/test-all-policy.bro b/scripts/test-all-policy.bro index a42ef893fc..415468a801 100644 --- a/scripts/test-all-policy.bro +++ b/scripts/test-all-policy.bro @@ -9,24 +9,28 @@ # The base/ scripts are all loaded by default and not included here. -# @load frameworks/communication/listen-clear.bro -# @load frameworks/communication/listen-ssl.bro +# @load frameworks/communication/listen.bro # @load frameworks/control/controllee.bro # @load frameworks/control/controller.bro @load frameworks/dpd/detect-protocols.bro @load frameworks/dpd/packet-segment-logging.bro +@load frameworks/metrics/conn-example.bro +@load frameworks/metrics/http-example.bro +@load frameworks/metrics/ssl-example.bro @load frameworks/software/version-changes.bro @load frameworks/software/vulnerable.bro @load integration/barnyard2/__load__.bro -@load integration/barnyard2/base.bro -@load integration/barnyard2/event.bro +@load integration/barnyard2/main.bro @load integration/barnyard2/types.bro @load misc/analysis-groups.bro +@load misc/capture-loss.bro @load misc/loaded-scripts.bro +@load misc/profiling.bro +@load misc/stats.bro @load misc/trim-trace-file.bro @load protocols/conn/known-hosts.bro @load protocols/conn/known-services.bro -# @load protocols/conn/scan.bro +@load protocols/conn/weirds.bro @load protocols/dns/auth-addl.bro @load protocols/dns/detect-external-names.bro @load protocols/ftp/detect.bro @@ -35,19 +39,25 @@ @load protocols/http/detect-MHR.bro @load protocols/http/detect-sqli.bro @load protocols/http/detect-webapps.bro -@load protocols/http/headers.bro +@load protocols/http/header-names.bro +@load protocols/http/software-browser-plugins.bro @load protocols/http/software.bro @load protocols/http/var-extraction-cookies.bro @load protocols/http/var-extraction-uri.bro +@load protocols/smtp/blocklists.bro @load protocols/smtp/detect-suspicious-orig.bro @load protocols/smtp/software.bro +@load protocols/ssh/detect-bruteforcing.bro +@load protocols/ssh/geo-data.bro +@load protocols/ssh/interesting-hostnames.bro @load protocols/ssh/software.bro +@load protocols/ssl/cert-hash.bro +@load protocols/ssl/expiring-certs.bro +@load protocols/ssl/extract-certs-pem.bro @load protocols/ssl/known-certs.bro @load protocols/ssl/validate-certs.bro @load tuning/__load__.bro @load tuning/defaults/__load__.bro @load tuning/defaults/packet-fragments.bro -@load tuning/defaults/remove-high-volume-notices.bro @load tuning/defaults/warnings.bro @load tuning/track-all-assets.bro -# @load hot.conn.bro diff --git a/src/ARP.cc b/src/ARP.cc index cdf0baa170..7ffd82764c 100644 --- a/src/ARP.cc +++ b/src/ARP.cc @@ -1,5 +1,3 @@ -// $Id: ARP.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. @@ -19,7 +17,7 @@ ARP_Analyzer::~ARP_Analyzer() { } -bool ARP_Analyzer::IsARP(const u_char* pkt, int hdr_size) const +bool ARP_Analyzer::IsARP(const u_char* pkt, int hdr_size) { unsigned short network_protocol = *(unsigned short*) (pkt + hdr_size - 2); diff --git a/src/ARP.h b/src/ARP.h index c7765eb9a9..f4b623c513 100644 --- a/src/ARP.h +++ b/src/ARP.h @@ -1,5 +1,3 @@ -// $Id: ARP.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef arp_h @@ -17,6 +15,8 @@ #include #elif defined(HAVE_NETINET_IF_ETHER_H) #include +#elif defined(HAVE_NET_ETHERTYPES_H) +#include #endif #ifndef arp_pkthdr @@ -31,9 +31,6 @@ public: ARP_Analyzer(); virtual ~ARP_Analyzer(); - // Whether a packet is of interest for ARP analysis. - bool IsARP(const u_char* pkt, int hdr_size) const; - void NextPacket(double t, const struct pcap_pkthdr* hdr, const u_char* const pkt, int hdr_size); @@ -41,6 +38,10 @@ public: void RREvent(EventHandlerPtr e, const u_char* src, const u_char* dst, const char* spa, const char* sha, const char* tpa, const char* tha); + + // Whether a packet is of interest for ARP analysis. + static bool IsARP(const u_char* pkt, int hdr_size); + protected: AddrVal* ConstructAddrVal(const void* addr); StringVal* EthAddrToStr(const u_char* addr); diff --git a/src/Analyzer.cc b/src/Analyzer.cc index b995c2f74b..92ca3ecc50 100644 --- a/src/Analyzer.cc +++ b/src/Analyzer.cc @@ -1,5 +1,3 @@ -// $Id: Analyzer.cc,v 1.1.4.28 2006/06/01 17:18:10 sommer Exp $ - #include #include "Analyzer.h" @@ -51,18 +49,6 @@ const Analyzer::Config Analyzer::analyzer_configs[] = { { AnalyzerTag::ICMP, "ICMP", ICMP_Analyzer::InstantiateAnalyzer, ICMP_Analyzer::Available, 0, false }, - { AnalyzerTag::ICMP_TimeExceeded, "ICMP_TIMEEXCEEDED", - ICMP_TimeExceeded_Analyzer::InstantiateAnalyzer, - ICMP_TimeExceeded_Analyzer::Available, 0, false }, - { AnalyzerTag::ICMP_Unreachable, "ICMP_UNREACHABLE", - ICMP_Unreachable_Analyzer::InstantiateAnalyzer, - ICMP_Unreachable_Analyzer::Available, 0, false }, - { AnalyzerTag::ICMP_Echo, "ICMP_ECHO", - ICMP_Echo_Analyzer::InstantiateAnalyzer, - ICMP_Echo_Analyzer::Available, 0, false }, - { AnalyzerTag::ICMP_Redir, "ICMP_REDIR", - ICMP_Redir_Analyzer::InstantiateAnalyzer, - ICMP_Redir_Analyzer::Available, 0, false }, { AnalyzerTag::TCP, "TCP", TCP_Analyzer::InstantiateAnalyzer, TCP_Analyzer::Available, 0, false }, @@ -155,7 +141,7 @@ const Analyzer::Config Analyzer::analyzer_configs[] = { { AnalyzerTag::TCPStats, "TCPSTATS", TCPStats_Analyzer::InstantiateAnalyzer, TCPStats_Analyzer::Available, 0, false }, - { AnalyzerTag::ConnSize, "CONNSIZE", + { AnalyzerTag::ConnSize, "CONNSIZE", ConnSize_Analyzer::InstantiateAnalyzer, ConnSize_Analyzer::Available, 0, false }, @@ -428,19 +414,7 @@ void Analyzer::ForwardPacket(int len, const u_char* data, bool is_orig, if ( ! (current->finished || current->removing ) ) current->NextPacket(len, data, is_orig, seq, ip, caplen); else - { - if ( removing ) - { - current->Done(); - removing = false; - } - - // Analyzer has already been disabled so delete it. - DBG_LOG(DBG_DPD, "%s deleted child %s", - fmt_analyzer(this).c_str(), fmt_analyzer(current).c_str()); - children.erase(--i); - delete current; - } + DeleteChild(--i); } AppendNewChildren(); @@ -463,19 +437,7 @@ void Analyzer::ForwardStream(int len, const u_char* data, bool is_orig) if ( ! (current->finished || current->removing ) ) current->NextStream(len, data, is_orig); else - { - // Analyzer has already been disabled so delete it. - if ( current->removing ) - { - current->Done(); - removing = false; - } - - DBG_LOG(DBG_DPD, "%s deleted child %s", - fmt_analyzer(this).c_str(), fmt_analyzer(current).c_str()); - children.erase(--i); - delete current; - } + DeleteChild(--i); } AppendNewChildren(); @@ -498,19 +460,7 @@ void Analyzer::ForwardUndelivered(int seq, int len, bool is_orig) if ( ! (current->finished || current->removing ) ) current->NextUndelivered(seq, len, is_orig); else - { - if ( current->removing ) - { - current->Done(); - removing = false; - } - - // Analyzer has already been disabled so delete it. - DBG_LOG(DBG_DPD, "%s deleted child %s", - fmt_analyzer(this).c_str(), fmt_analyzer(current).c_str()); - children.erase(--i); - delete current; - } + DeleteChild(--i); } AppendNewChildren(); @@ -530,19 +480,7 @@ void Analyzer::ForwardEndOfData(bool orig) if ( ! (current->finished || current->removing ) ) current->NextEndOfData(orig); else - { - if ( current->removing ) - { - current->Done(); - removing = false; - } - - // Analyzer has already been disabled so delete it. - DBG_LOG(DBG_DPD, "%s deleted child %s", - fmt_analyzer(this).c_str(), fmt_analyzer(current).c_str()); - children.erase(--i); - delete current; - } + DeleteChild(--i); } AppendNewChildren(); @@ -608,7 +546,7 @@ void Analyzer::RemoveChildAnalyzer(AnalyzerID id) LOOP_OVER_CHILDREN(i) if ( (*i)->id == id && ! ((*i)->finished || (*i)->removing) ) { - DBG_LOG(DBG_DPD, "%s disabled child %s", GetTagName(), id, + DBG_LOG(DBG_DPD, "%s disabling child %s", GetTagName(), id, fmt_analyzer(this).c_str(), fmt_analyzer(*i).c_str()); // See comment above. (*i)->removing = true; @@ -659,6 +597,26 @@ Analyzer* Analyzer::FindChild(AnalyzerTag::Tag arg_tag) return 0; } +void Analyzer::DeleteChild(analyzer_list::iterator i) + { + Analyzer* child = *i; + + // Analyzer must have already been finished or marked for removal. + assert(child->finished || child->removing); + + if ( child->removing ) + { + child->Done(); + child->removing = false; + } + + DBG_LOG(DBG_DPD, "%s deleted child %s 3", + fmt_analyzer(this).c_str(), fmt_analyzer(child).c_str()); + + children.erase(i); + delete child; + } + void Analyzer::AddSupportAnalyzer(SupportAnalyzer* analyzer) { if ( HasSupportAnalyzer(analyzer->GetTag(), analyzer->IsOrig()) ) diff --git a/src/Analyzer.h b/src/Analyzer.h index 4a3ead5844..7797e215fe 100644 --- a/src/Analyzer.h +++ b/src/Analyzer.h @@ -1,5 +1,3 @@ -// $Id:$ -// // Main analyzer interface. #ifndef ANALYZER_H @@ -279,6 +277,10 @@ protected: void AppendNewChildren(); private: + // Internal method to eventually delete a child analyzer that's + // already Done(). + void DeleteChild(analyzer_list::iterator i); + AnalyzerTag::Tag tag; AnalyzerID id; diff --git a/src/AnalyzerTags.h b/src/AnalyzerTags.h index e64a4ec76e..dc10a55f22 100644 --- a/src/AnalyzerTags.h +++ b/src/AnalyzerTags.h @@ -1,5 +1,3 @@ -// $Id: AnalyzerTags.h,v 1.1.2.5 2006/06/01 01:55:42 sommer Exp $ - #ifndef ANALYZERTAGS_H #define ANALYZERTAGS_H @@ -22,9 +20,7 @@ namespace AnalyzerTag { PIA_TCP, PIA_UDP, // Transport-layer analyzers. - ICMP, - ICMP_TimeExceeded, ICMP_Unreachable, ICMP_Echo, ICMP_Redir, - TCP, UDP, + ICMP, TCP, UDP, // Application-layer analyzers (hand-written). BitTorrent, BitTorrentTracker, diff --git a/src/Anon.cc b/src/Anon.cc index bd29b3cfe9..d2a28a0e08 100644 --- a/src/Anon.cc +++ b/src/Anon.cc @@ -1,5 +1,3 @@ -// $Id: Anon.cc 7075 2010-09-13 02:39:38Z vern $ - #include #include #include @@ -155,7 +153,9 @@ void AnonymizeIPAddr_A50::init() int AnonymizeIPAddr_A50::PreservePrefix(ipaddr32_t input, int num_bits) { - DEBUG_MSG("%s/%d\n", dotted_addr(input), num_bits); + DEBUG_MSG("%s/%d\n", + IPAddr(IPv4, &input, IPAddr::Network).AsString().c_str(), + num_bits); if ( ! before_anonymization ) { diff --git a/src/Anon.h b/src/Anon.h index 2f138c36d7..ce234f4680 100644 --- a/src/Anon.h +++ b/src/Anon.h @@ -1,5 +1,3 @@ -// $Id: Anon.h 416 2004-09-17 03:52:28Z vern $ - // The prefix-preserving IP address anonymization code is largely // based on (and sometimes directly copied from) Eddie Kohler's // ipsumdump-1.20 code, per: diff --git a/src/Attr.cc b/src/Attr.cc index 22b4337405..82d9c9ddc7 100644 --- a/src/Attr.cc +++ b/src/Attr.cc @@ -1,5 +1,3 @@ -// $Id: Attr.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -7,7 +5,7 @@ #include "Attr.h" #include "Expr.h" #include "Serializer.h" -#include "LogMgr.h" +#include "threading/SerialTypes.h" const char* attr_name(attr_tag t) { @@ -62,16 +60,19 @@ void Attr::DescribeReST(ODesc* d) const d->Add("="); d->SP(); - if ( expr->Type()->Tag() == TYPE_FUNC ) - d->Add(":bro:type:`func`"); - else if ( expr->Type()->Tag() == TYPE_ENUM ) + if ( expr->Tag() == EXPR_NAME ) { - d->Add(":bro:enum:`"); + d->Add(":bro:see:`"); expr->Describe(d); d->Add("`"); } + else if ( expr->Type()->Tag() == TYPE_FUNC ) + { + d->Add(":bro:type:`func`"); + } + else { d->Add("``"); @@ -415,7 +416,7 @@ void Attributes::CheckAttr(Attr* a) break; case ATTR_LOG: - if ( ! LogVal::IsCompatibleType(type) ) + if ( ! threading::Value::IsCompatibleType(type) ) Error("&log applied to a type that cannot be logged"); break; @@ -483,7 +484,11 @@ bool Attributes::DoSerialize(SerialInfo* info) const loop_over_list((*attrs), i) { Attr* a = (*attrs)[i]; - SERIALIZE_OPTIONAL(a->AttrExpr()) + + // Broccoli doesn't support expressions. + Expr* e = (! info->broccoli_peer) ? a->AttrExpr() : 0; + SERIALIZE_OPTIONAL(e); + if ( ! SERIALIZE(char(a->Tag())) ) return false; } diff --git a/src/Attr.h b/src/Attr.h index 89a81428e5..6c835dc61c 100644 --- a/src/Attr.h +++ b/src/Attr.h @@ -1,5 +1,3 @@ -// $Id: Attr.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef attr_h diff --git a/src/BPF_Program.cc b/src/BPF_Program.cc index 7796ccce81..a6d3d80c05 100644 --- a/src/BPF_Program.cc +++ b/src/BPF_Program.cc @@ -1,5 +1,3 @@ -// $Id: BPF_Program.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/BPF_Program.h b/src/BPF_Program.h index 4c6e090cda..88ed669da2 100644 --- a/src/BPF_Program.h +++ b/src/BPF_Program.h @@ -1,5 +1,3 @@ -// $Id: BPF_Program.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef bpf_program_h diff --git a/src/BackDoor.cc b/src/BackDoor.cc index 493fd9ae00..c218a98ce2 100644 --- a/src/BackDoor.cc +++ b/src/BackDoor.cc @@ -1,5 +1,3 @@ -// $Id: BackDoor.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/BackDoor.h b/src/BackDoor.h index 50d97514ef..40ea3bbaa3 100644 --- a/src/BackDoor.h +++ b/src/BackDoor.h @@ -1,5 +1,3 @@ -// $Id: BackDoor.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef backdoor_h diff --git a/src/Base64.cc b/src/Base64.cc index 2585debf5e..b0da8ea74c 100644 --- a/src/Base64.cc +++ b/src/Base64.cc @@ -1,16 +1,27 @@ -// $Id: Base64.cc 6024 2008-07-26 19:20:47Z vern $ - #include "config.h" #include "Base64.h" -static int base64_table[256]; +int Base64Decoder::default_base64_table[256]; +const string Base64Decoder::default_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -static void init_base64_table() +int* Base64Decoder::InitBase64Table(const string& alphabet) { - static int table_initialized = 0; + assert(alphabet.size() == 64); - if ( ++table_initialized > 1 ) - return; + static bool default_table_initialized = false; + + if ( alphabet == default_alphabet && default_table_initialized ) + return default_base64_table; + + int* base64_table = 0; + + if ( alphabet == default_alphabet ) + { + base64_table = default_base64_table; + default_table_initialized = true; + } + else + base64_table = new int[256]; int i; for ( i = 0; i < 256; ++i ) @@ -18,28 +29,36 @@ static void init_base64_table() for ( i = 0; i < 26; ++i ) { - base64_table['A' + i] = i; - base64_table['a' + i] = i + 26; + base64_table[int(alphabet[0 + i])] = i; + base64_table[int(alphabet[26 + i])] = i + 26; } for ( i = 0; i < 10; ++i ) - base64_table['0' + i] = i + 52; + base64_table[int(alphabet[52 + i])] = i + 52; // Casts to avoid compiler warnings. - base64_table[int('+')] = 62; - base64_table[int('/')] = 63; + base64_table[int(alphabet[62])] = 62; + base64_table[int(alphabet[63])] = 63; base64_table[int('=')] = 0; + + return base64_table; } -Base64Decoder::Base64Decoder(Analyzer* arg_analyzer) +Base64Decoder::Base64Decoder(Analyzer* arg_analyzer, const string& alphabet) { - init_base64_table(); + base64_table = InitBase64Table(alphabet.size() ? alphabet : default_alphabet); base64_group_next = 0; base64_padding = base64_after_padding = 0; errored = 0; analyzer = arg_analyzer; } +Base64Decoder::~Base64Decoder() + { + if ( base64_table != default_base64_table ) + delete base64_table; + } + int Base64Decoder::Decode(int len, const char* data, int* pblen, char** pbuf) { int blen; @@ -144,13 +163,21 @@ int Base64Decoder::Done(int* pblen, char** pbuf) return 0; } -BroString* decode_base64(const BroString* s) + +BroString* decode_base64(const BroString* s, const BroString* a) { + if ( a && a->Len() != 64 ) + { + reporter->Error("base64 decoding alphabet is not 64 characters: %s", + a->CheckString()); + return 0; + } + int buf_len = int((s->Len() + 3) / 4) * 3 + 1; int rlen2, rlen = buf_len; char* rbuf2, *rbuf = new char[rlen]; - Base64Decoder dec(0); + Base64Decoder dec(0, a ? a->CheckString() : ""); if ( dec.Decode(s->Len(), (const char*) s->Bytes(), &rlen, &rbuf) == -1 ) goto err; diff --git a/src/Base64.h b/src/Base64.h index 5bf5d4e2bc..0e02c94cf0 100644 --- a/src/Base64.h +++ b/src/Base64.h @@ -1,5 +1,3 @@ -// $Id: Base64.h 3526 2006-09-12 07:32:21Z vern $ - #ifndef base64_h #define base64_h @@ -15,11 +13,11 @@ class Base64Decoder { public: - // is used for error reporting, and it should be zero - // when the decoder is called by the built-in function - // decode_base64(). - Base64Decoder(Analyzer* analyzer); - ~Base64Decoder() { } + // is used for error reporting, and it should be zero when + // the decoder is called by the built-in function decode_base64(). + // Empty alphabet indicates the default base64 alphabet. + Base64Decoder(Analyzer* analyzer, const string& alphabet = ""); + ~Base64Decoder(); // A note on Decode(): // @@ -46,7 +44,7 @@ public: if ( analyzer ) analyzer->Weird("base64_illegal_encoding", msg); else - reporter->Error(msg); + reporter->Error("%s", msg); } protected: @@ -59,8 +57,13 @@ protected: int base64_after_padding; int errored; // if true, we encountered an error - skip further processing Analyzer* analyzer; + int* base64_table; + + static int* InitBase64Table(const string& alphabet); + static int default_base64_table[256]; + static const string default_alphabet; }; -BroString* decode_base64(const BroString* s); +BroString* decode_base64(const BroString* s, const BroString* a = 0); #endif /* base64_h */ diff --git a/src/BitTorrent.cc b/src/BitTorrent.cc index e99047beb1..824e4ec98d 100644 --- a/src/BitTorrent.cc +++ b/src/BitTorrent.cc @@ -1,5 +1,3 @@ -// $Id:$ -// // This code contributed by Nadi Sarrar. #include "BitTorrent.h" @@ -68,39 +66,44 @@ void BitTorrent_Analyzer::DeliverStream(int len, const u_char* data, bool orig) void BitTorrent_Analyzer::Undelivered(int seq, int len, bool orig) { - uint64 entry_offset = orig ? - *interp->upflow()->next_message_offset() : - *interp->downflow()->next_message_offset(); - uint64& this_stream_len = orig ? stream_len_orig : stream_len_resp; - bool& this_stop = orig ? stop_orig : stop_resp; - TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); - this_stream_len += len; + // TODO: Code commented out for now. I think that shoving data that + // is definitely wrong into the parser seems like a really bad idea. + // The way it's currently tracking the next message offset isn't + // compatible with new 64bit int support in binpac either. - if ( entry_offset < this_stream_len ) - { // entry point is somewhere in the gap - DeliverWeird("Stopping BitTorrent analysis: cannot recover from content gap", orig); - this_stop = true; - if ( stop_orig && stop_resp ) - ProtocolViolation("BitTorrent: content gap and/or protocol violation"); - } - else - { // fill the gap - try - { - u_char gap[len]; - memset(gap, 0, len); - interp->NewData(orig, gap, gap + len); - } - catch ( binpac::Exception const &e ) - { - DeliverWeird("Stopping BitTorrent analysis: filling content gap failed", orig); - this_stop = true; - if ( stop_orig && stop_resp ) - ProtocolViolation("BitTorrent: content gap and/or protocol violation"); - } - } + //uint64 entry_offset = orig ? + // *interp->upflow()->next_message_offset() : + // *interp->downflow()->next_message_offset(); + //uint64& this_stream_len = orig ? stream_len_orig : stream_len_resp; + //bool& this_stop = orig ? stop_orig : stop_resp; + // + //this_stream_len += len; + // + //if ( entry_offset < this_stream_len ) + // { // entry point is somewhere in the gap + // DeliverWeird("Stopping BitTorrent analysis: cannot recover from content gap", orig); + // this_stop = true; + // if ( stop_orig && stop_resp ) + // ProtocolViolation("BitTorrent: content gap and/or protocol violation"); + // } + //else + // { // fill the gap + // try + // { + // u_char gap[len]; + // memset(gap, 0, len); + // interp->NewData(orig, gap, gap + len); + // } + // catch ( binpac::Exception const &e ) + // { + // DeliverWeird("Stopping BitTorrent analysis: filling content gap failed", orig); + // this_stop = true; + // if ( stop_orig && stop_resp ) + // ProtocolViolation("BitTorrent: content gap and/or protocol violation"); + // } + // } } void BitTorrent_Analyzer::EndpointEOF(TCP_Reassembler* endp) diff --git a/src/BitTorrent.h b/src/BitTorrent.h index 7f745d48c8..191b4c50d7 100644 --- a/src/BitTorrent.h +++ b/src/BitTorrent.h @@ -1,5 +1,3 @@ -// $Id:$ -// // This code contributed by Nadi Sarrar. #ifndef bittorrent_h diff --git a/src/BitTorrentTracker.cc b/src/BitTorrentTracker.cc index f0b290751d..995a01dd63 100644 --- a/src/BitTorrentTracker.cc +++ b/src/BitTorrentTracker.cc @@ -1,5 +1,3 @@ -// $Id:$ -// // This code contributed by Nadi Sarrar. #include "BitTorrentTracker.h" diff --git a/src/BitTorrentTracker.h b/src/BitTorrentTracker.h index 167c9d0d10..d57665d104 100644 --- a/src/BitTorrentTracker.h +++ b/src/BitTorrentTracker.h @@ -1,5 +1,3 @@ -// $Id:$ -// // This code contributed by Nadi Sarrar. #ifndef bittorrenttracker_h diff --git a/src/BroDoc.cc b/src/BroDoc.cc index 302bd04c88..1e2d7d52ea 100644 --- a/src/BroDoc.cc +++ b/src/BroDoc.cc @@ -60,7 +60,7 @@ BroDoc::BroDoc(const std::string& rel, const std::string& abs) if ( ! reST_file ) fprintf(stderr, "Failed to open %s\n", reST_filename.c_str()); -#ifdef DEBUG +#ifdef DOCDEBUG fprintf(stdout, "Documenting absolute source: %s\n", abs.c_str()); fprintf(stdout, "\trelative dir: %s\n", rel.c_str()); fprintf(stdout, "\tdoc title: %s\n", doc_title.c_str()); @@ -85,12 +85,13 @@ void BroDoc::AddImport(const std::string& s) if ( ext_pos != std::string::npos ) lname = lname.substr(0, ext_pos); - const char* full_filename = ""; - const char* subpath = ""; + const char* full_filename = NULL; + const char* subpath = NULL; + FILE* f = search_for_file(lname.c_str(), "bro", &full_filename, true, &subpath); - if ( f ) + if ( f && full_filename && subpath ) { fclose(f); @@ -126,12 +127,14 @@ void BroDoc::AddImport(const std::string& s) } delete [] tmp; - delete [] full_filename; - delete [] subpath; } + else fprintf(stderr, "Failed to document '@load %s' in file: %s\n", s.c_str(), reST_filename.c_str()); + + delete [] full_filename; + delete [] subpath; } void BroDoc::SetPacketFilter(const std::string& s) @@ -170,13 +173,26 @@ void BroDoc::WriteDocFile() const { WriteToDoc(".. Automatically generated. Do not edit.\n\n"); + WriteToDoc(":tocdepth: 3\n\n"); + WriteSectionHeading(doc_title.c_str(), '='); - WriteToDoc("\n:download:`Original Source File <%s>`\n\n", - downloadable_filename.c_str()); + WriteStringList(".. bro:namespace:: %s\n", modules); - WriteSectionHeading("Overview", '-'); - WriteStringList("%s\n", "%s\n\n", summary); + WriteToDoc("\n"); + + // WriteSectionHeading("Overview", '-'); + WriteStringList("%s\n", summary); + + WriteToDoc("\n"); + + if ( ! modules.empty() ) + { + WriteToDoc(":Namespace%s: ", (modules.size() > 1 ? "s" : "")); + // WriteStringList(":bro:namespace:`%s`", modules); + WriteStringList("``%s``, ", "``%s``", modules); + WriteToDoc("\n"); + } if ( ! imports.empty() ) { @@ -196,37 +212,39 @@ void BroDoc::WriteDocFile() const WriteToDoc("\n"); } + WriteToDoc(":Source File: :download:`%s`\n", + downloadable_filename.c_str()); + WriteToDoc("\n"); WriteInterface("Summary", '~', '#', true, true); - if ( ! modules.empty() ) - { - WriteSectionHeading("Namespaces", '~'); - WriteStringList(".. bro:namespace:: %s\n", modules); - WriteToDoc("\n"); - } - if ( ! notices.empty() ) - WriteBroDocObjList(notices, "Notices", '~'); + WriteBroDocObjList(notices, "Notices", '#'); - WriteInterface("Public Interface", '-', '~', true, false); + if ( port_analysis.size() || packet_filter.size() ) + WriteSectionHeading("Configuration Changes", '#'); if ( ! port_analysis.empty() ) { - WriteSectionHeading("Port Analysis", '-'); - WriteToDoc(":ref:`More Information `\n\n"); - WriteStringList("%s", port_analysis); + WriteSectionHeading("Port Analysis", '^'); + WriteToDoc("Loading this script makes the following changes to " + ":bro:see:`dpd_config`.\n\n"); + WriteStringList("%s, ", "%s", port_analysis); } if ( ! packet_filter.empty() ) { - WriteSectionHeading("Packet Filter", '-'); - WriteToDoc(":ref:`More Information `\n\n"); + WriteSectionHeading("Packet Filter", '^'); + WriteToDoc("Loading this script makes the following changes to " + ":bro:see:`capture_filters`.\n\n"); WriteToDoc("Filters added::\n\n"); WriteToDoc("%s\n", packet_filter.c_str()); } + WriteInterface("Detailed Interface", '~', '#', true, false); + +#if 0 // Disabled for now. BroDocObjList::const_iterator it; bool hasPrivateIdentifiers = false; @@ -240,7 +258,8 @@ void BroDoc::WriteDocFile() const } if ( hasPrivateIdentifiers ) - WriteInterface("Private Interface", '-', '~', false, false); + WriteInterface("Private Interface", '~', '#', false, false); +#endif } void BroDoc::WriteInterface(const char* heading, char underline, diff --git a/src/BroDoc.h b/src/BroDoc.h index 112401253c..ac6ff0a59b 100644 --- a/src/BroDoc.h +++ b/src/BroDoc.h @@ -167,6 +167,18 @@ public: all.push_back(o); } + /** + * Schedules documentation of an event handler declared by the script. + * @param o A pointer to a BroDocObj which contains the internal + * Bro language representation of the script event handler and + * also any associated comments about it. + */ + void AddEventHandler(const BroDocObj* o) + { + event_handlers.push_back(o); + all.push_back(o); + } + /** * Schedules documentation of a function declared by the script. * @param o A pointer to a BroDocObj which contains the internal @@ -228,6 +240,7 @@ protected: BroDocObjList types; BroDocObjList notices; BroDocObjList events; + BroDocObjList event_handlers; BroDocObjMap functions; BroDocObjList redefs; diff --git a/src/BroDocObj.cc b/src/BroDocObj.cc index d9fe16632b..12753ea15d 100644 --- a/src/BroDocObj.cc +++ b/src/BroDocObj.cc @@ -4,9 +4,12 @@ #include "ID.h" #include "BroDocObj.h" +BroDocObj* BroDocObj::last = 0; + BroDocObj::BroDocObj(const ID* id, std::list*& reST, bool is_fake) { + last = this; broID = id; reST_doc_strings = reST; reST = 0; diff --git a/src/BroDocObj.h b/src/BroDocObj.h index 0ad96afa86..cb512f8cda 100644 --- a/src/BroDocObj.h +++ b/src/BroDocObj.h @@ -103,6 +103,20 @@ public: */ int LongestShortDescLen() const; + /** + * Adds a reST documentation string to this BroDocObj's list. + * @param s the documentation string to append. + */ + void AddDocString(const std::string& s) + { + if ( ! reST_doc_strings ) + reST_doc_strings = new std::list(); + reST_doc_strings->push_back(s); + FormulateShortDesc(); + } + + static BroDocObj* last; + protected: std::list* reST_doc_strings; std::list short_desc; diff --git a/src/BroList.h b/src/BroList.h index b71615a18a..6168bf7bda 100644 --- a/src/BroList.h +++ b/src/BroList.h @@ -1,5 +1,3 @@ -// $Id: BroList.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef brolist_h diff --git a/src/BroString.cc b/src/BroString.cc index 8677cd9533..e05995b156 100644 --- a/src/BroString.cc +++ b/src/BroString.cc @@ -1,5 +1,3 @@ -// $Id: BroString.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/BroString.h b/src/BroString.h index 48471cb99e..58991d78af 100644 --- a/src/BroString.h +++ b/src/BroString.h @@ -1,5 +1,3 @@ -// $Id: BroString.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef brostring_h diff --git a/src/Brofiler.cc b/src/Brofiler.cc new file mode 100644 index 0000000000..c9a3505069 --- /dev/null +++ b/src/Brofiler.cc @@ -0,0 +1,102 @@ +#include +#include +#include +#include +#include "Brofiler.h" +#include "util.h" + +Brofiler::Brofiler() + : ignoring(0), delim('\t') + { + } + +Brofiler::~Brofiler() + { + } + +bool Brofiler::ReadStats() + { + char* bf = getenv("BRO_PROFILER_FILE"); + if ( ! bf ) + return false; + + FILE* f = fopen(bf, "r"); + if ( ! f ) + return false; + + char line[16384]; + string delimiter; + delimiter = delim; + + while( fgets(line, sizeof(line), f) ) + { + line[strlen(line) - 1] = 0; //remove newline + string cnt(strtok(line, delimiter.c_str())); + string location(strtok(0, delimiter.c_str())); + string desc(strtok(0, delimiter.c_str())); + pair location_desc(location, desc); + uint64 count; + atoi_n(cnt.size(), cnt.c_str(), 0, 10, count); + usage_map[location_desc] = count; + } + + fclose(f); + return true; + } + +bool Brofiler::WriteStats() + { + char* bf = getenv("BRO_PROFILER_FILE"); + if ( ! bf ) return false; + + FILE* f; + const char* p = strstr(bf, ".XXXXXX"); + + if ( p && ! p[7] ) + { + int fd = mkstemp(bf); + if ( fd == -1 ) + { + reporter->Error("Failed to generate unique file name from BRO_PROFILER_FILE: %s", bf); + return false; + } + f = fdopen(fd, "w"); + } + else + { + f = fopen(bf, "w"); + } + + if ( ! f ) + { + reporter->Error("Failed to open BRO_PROFILER_FILE destination '%s' for writing", bf); + return false; + } + + for ( list::const_iterator it = stmts.begin(); + it != stmts.end(); ++it ) + { + ODesc location_info; + (*it)->GetLocationInfo()->Describe(&location_info); + ODesc desc_info; + (*it)->Describe(&desc_info); + string desc(desc_info.Description()); + for_each(desc.begin(), desc.end(), canonicalize_desc()); + pair location_desc(location_info.Description(), desc); + if ( usage_map.find(location_desc) != usage_map.end() ) + usage_map[location_desc] += (*it)->GetAccessCount(); + else + usage_map[location_desc] = (*it)->GetAccessCount(); + } + + map, uint64 >::const_iterator it; + for ( it = usage_map.begin(); it != usage_map.end(); ++it ) + { + fprintf(f, "%"PRIu64"%c%s%c%s\n", it->second, delim, + it->first.first.c_str(), delim, it->first.second.c_str()); + } + + fclose(f); + return true; + } + diff --git a/src/Brofiler.h b/src/Brofiler.h new file mode 100644 index 0000000000..22e5808bf6 --- /dev/null +++ b/src/Brofiler.h @@ -0,0 +1,81 @@ +#ifndef BROFILER_H_ +#define BROFILER_H_ + +#include +#include +#include +#include + + +/** + * A simple class for managing stats of Bro script coverage across Bro runs. + */ +class Brofiler { +public: + Brofiler(); + virtual ~Brofiler(); + + /** + * Imports Bro script Stmt usage information from file pointed to by + * environment variable BRO_PROFILER_FILE. + * + * @return: true if usage info was read, otherwise false. + */ + bool ReadStats(); + + /** + * Combines usage stats from current run with any read from ReadStats(), + * then writes information to file pointed to by environment variable + * BRO_PROFILER_FILE. If the value of that env. variable ends with + * ".XXXXXX" (exactly 6 X's), then it is first passed through mkstemp + * to get a unique file. + * + * @return: true when usage info is written, otherwise false. + */ + bool WriteStats(); + + void SetDelim(char d) { delim = d; } + + void IncIgnoreDepth() { ignoring++; } + void DecIgnoreDepth() { ignoring--; } + + void AddStmt(const Stmt* s) { if ( ignoring == 0 ) stmts.push_back(s); } + +private: + /** + * The current, global Brofiler instance creates this list at parse-time. + */ + list stmts; + + /** + * Indicates whether new statments will not be considered as part of + * coverage statistics because it was marked with the @no-test tag. + */ + unsigned int ignoring; + + /** + * This maps Stmt location-desc pairs to the total number of times that + * Stmt has been executed. The map can be initialized from a file at + * startup time and modified at shutdown time before writing back + * to a file. + */ + map, uint64> usage_map; + + /** + * The character to use to delimit Brofiler output files. Default is '\t'. + */ + char delim; + + /** + * A canonicalization routine for Stmt descriptions containing characters + * that don't agree with the output format of Brofiler. + */ + struct canonicalize_desc { + void operator() (char& c) + { + if ( c == '\n' ) c = ' '; + } + }; +}; + +#endif /* BROFILER_H_ */ diff --git a/src/CCL.cc b/src/CCL.cc index 326dcc7320..6c4ec5ea2e 100644 --- a/src/CCL.cc +++ b/src/CCL.cc @@ -1,5 +1,3 @@ -// $Id: CCL.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/CCL.h b/src/CCL.h index 760e64b6f9..2870acf53a 100644 --- a/src/CCL.h +++ b/src/CCL.h @@ -1,5 +1,3 @@ -// $Id: CCL.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef ccl_h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 1638c4deb3..a755fde64e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,4 +1,5 @@ -include_directories(${CMAKE_CURRENT_SOURCE_DIR} +include_directories(BEFORE + ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) @@ -107,20 +108,28 @@ macro(BIF_TARGET bifInput) add_custom_command(OUTPUT ${bifOutputs} COMMAND bifcl ARGS ${CMAKE_CURRENT_SOURCE_DIR}/${bifInput} || (rm -f ${bifOutputs} && exit 1) + # In order be able to run bro from the build directory, + # the generated bro script needs to be inside a + # a directory tree named the same way it will be + # referenced from an @load. + COMMAND "${CMAKE_COMMAND}" + ARGS -E copy ${bifInput}.bro base/${bifInput}.bro + COMMAND "${CMAKE_COMMAND}" + ARGS -E remove -f ${bifInput}.bro DEPENDS ${bifInput} DEPENDS bifcl COMMENT "[BIFCL] Processing ${bifInput}" ) list(APPEND ALL_BIF_OUTPUTS ${bifOutputs}) list(APPEND INSTALL_BIF_OUTPUTS - ${CMAKE_CURRENT_BINARY_DIR}/${bifInput}.bro) + ${CMAKE_CURRENT_BINARY_DIR}/base/${bifInput}.bro) endmacro(BIF_TARGET) # returns a list of output files that bifcl will produce # for given input file in ${outputFileVar} macro(GET_BIF_OUTPUT_FILES inputFile outputFileVar) set(${outputFileVar} - ${inputFile}.bro + base/${inputFile}.bro ${inputFile}.func_def ${inputFile}.func_h ${inputFile}.func_init @@ -204,6 +213,8 @@ binpac_target(syslog.pac ######################################################################## ## bro target +find_package (Threads) + # This macro stores associated headers for any C/C++ source files given # as arguments (past _var) as a list in the CMake variable named "_var". macro(COLLECT_HEADERS _var) @@ -240,10 +251,6 @@ set(dns_SRCS nb_dns.c) set_source_files_properties(nb_dns.c PROPERTIES COMPILE_FLAGS -fno-strict-aliasing) -if (USE_NMALLOC) - set(malloc_SRCS malloc.c) -endif () - set(bro_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.c ${BIF_SRCS} @@ -277,12 +284,12 @@ set(bro_SRCS BPF_Program.cc BroDoc.cc BroDocObj.cc + Brofiler.cc BroString.cc CCL.cc ChunkedIO.cc CompHash.cc Conn.cc - ConnCompressor.cc ConnSizeAnalyzer.cc ContentLine.cc DCE_RPC.cc @@ -325,12 +332,11 @@ set(bro_SRCS IntSet.cc InterConn.cc IOSource.cc + IP.cc + IPAddr.cc IRC.cc List.cc Reporter.cc - LogMgr.cc - LogWriter.cc - LogWriterAscii.cc Login.cc MIME.cc NCP.cc @@ -396,14 +402,27 @@ set(bro_SRCS XDR.cc ZIP.cc bsd-getopt-long.c + bro_inet_ntop.c cq.c md5.c patricia.c setsignal.c PacketDumper.cc strsep.c + modp_numtoa.c + + threading/BasicThread.cc + threading/Manager.cc + threading/MsgThread.cc + threading/SerialTypes.cc + + logging/Manager.cc + logging/WriterBackend.cc + logging/WriterFrontend.cc + logging/writers/Ascii.cc + logging/writers/None.cc + ${dns_SRCS} - ${malloc_SRCS} ${openssl_SRCS} ) @@ -411,21 +430,14 @@ collect_headers(bro_HEADERS ${bro_SRCS}) add_definitions(-DBRO_SCRIPT_INSTALL_PATH="${BRO_SCRIPT_INSTALL_PATH}") add_definitions(-DBRO_SCRIPT_SOURCE_PATH="${BRO_SCRIPT_SOURCE_PATH}") +add_definitions(-DBRO_BUILD_PATH="${CMAKE_CURRENT_BINARY_DIR}") add_executable(bro ${bro_SRCS} ${bro_HEADERS}) -set(brolibs - ${BinPAC_LIBRARY} - ${PCAP_LIBRARY} - ${OpenSSL_LIBRARIES} - ${BIND_LIBRARY} - ${OPTLIBS} -) - -target_link_libraries(bro ${brolibs}) +target_link_libraries(bro ${brodeps} ${CMAKE_THREAD_LIBS_INIT}) install(TARGETS bro DESTINATION bin) -install(FILES ${INSTALL_BIF_OUTPUTS} DESTINATION ${BRO_SCRIPT_INSTALL_PATH}) +install(FILES ${INSTALL_BIF_OUTPUTS} DESTINATION ${BRO_SCRIPT_INSTALL_PATH}/base) set(BRO_EXE bro CACHE STRING "Bro executable binary" FORCE) diff --git a/src/ChunkedIO.cc b/src/ChunkedIO.cc index d54b4eb70b..f5bcb4b7c1 100644 --- a/src/ChunkedIO.cc +++ b/src/ChunkedIO.cc @@ -1,5 +1,3 @@ -// $Id: ChunkedIO.cc 6888 2009-08-20 18:23:11Z vern $ - #include #include #include @@ -1172,8 +1170,6 @@ void ChunkedIOSSL::Stats(char* buffer, int length) ChunkedIO::Stats(buffer + i, length - i); } -#ifdef HAVE_LIBZ - bool CompressedChunkedIO::Init() { zin.zalloc = 0; @@ -1350,5 +1346,3 @@ void CompressedChunkedIO::Stats(char* buffer, int length) io->Stats(buffer + i, length - i); buffer[length-1] = '\0'; } - -#endif /* HAVE_LIBZ */ diff --git a/src/ChunkedIO.h b/src/ChunkedIO.h index 1f946c18ba..56b5656945 100644 --- a/src/ChunkedIO.h +++ b/src/ChunkedIO.h @@ -1,5 +1,3 @@ -// $Id: ChunkedIO.h 6888 2009-08-20 18:23:11Z vern $ -// // Implements non-blocking chunk-wise I/O. #ifndef CHUNKEDIO_H @@ -289,8 +287,6 @@ private: static SSL_CTX* ctx; }; -#ifdef HAVE_LIBZ - #include // Wrapper class around a another ChunkedIO which the (un-)compresses data. @@ -337,6 +333,4 @@ protected: unsigned long uncompressed_bytes_written; }; -#endif /* HAVE_LIBZ */ - #endif diff --git a/src/CompHash.cc b/src/CompHash.cc index 763e5da463..86677f9719 100644 --- a/src/CompHash.cc +++ b/src/CompHash.cc @@ -1,5 +1,3 @@ -// $Id: CompHash.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -7,6 +5,7 @@ #include "CompHash.h" #include "Val.h" #include "Reporter.h" +#include "Func.h" CompositeHash::CompositeHash(TypeList* composite_type) { @@ -108,40 +107,18 @@ char* CompositeHash::SingleValHash(int type_check, char* kp0, case TYPE_INTERNAL_ADDR: { - // Use uint32 instead of int, because 'int' is not - // guaranteed to be 32-bit. uint32* kp = AlignAndPadType(kp0); -#ifdef BROv6 - const addr_type av = v->AsAddr(); - kp[0] = av[0]; - kp[1] = av[1]; - kp[2] = av[2]; - kp[3] = av[3]; + v->AsAddr().CopyIPv6(kp); kp1 = reinterpret_cast(kp+4); -#else - *kp = v->AsAddr(); - kp1 = reinterpret_cast(kp+1); -#endif } break; case TYPE_INTERNAL_SUBNET: { uint32* kp = AlignAndPadType(kp0); -#ifdef BROv6 - const subnet_type* sv = v->AsSubNet(); - kp[0] = sv->net[0]; - kp[1] = sv->net[1]; - kp[2] = sv->net[2]; - kp[3] = sv->net[3]; - kp[4] = sv->width; + v->AsSubNet().Prefix().CopyIPv6(kp); + kp[4] = v->AsSubNet().Length(); kp1 = reinterpret_cast(kp+5); -#else - const subnet_type* sv = v->AsSubNet(); - kp[0] = sv->net; - kp[1] = sv->width; - kp1 = reinterpret_cast(kp+2); -#endif } break; @@ -156,20 +133,20 @@ char* CompositeHash::SingleValHash(int type_check, char* kp0, case TYPE_INTERNAL_VOID: case TYPE_INTERNAL_OTHER: { - if ( v->Type()->Tag() == TYPE_FUNC ) + switch ( v->Type()->Tag() ) { + case TYPE_FUNC: { - Val** kp = AlignAndPadType(kp0); - v->Ref(); - // Ref((BroObj*) v->AsFunc()); - *kp = v; + uint32* kp = AlignAndPadType(kp0); + *kp = v->AsFunc()->GetUniqueFuncID(); kp1 = reinterpret_cast(kp+1); + break; } - else if ( v->Type()->Tag() == TYPE_RECORD ) + case TYPE_RECORD: { char* kp = kp0; RecordVal* rv = v->AsRecordVal(); - RecordType* rt = v->Type()->AsRecordType(); + RecordType* rt = bt->AsRecordType(); int num_fields = rt->NumFields(); for ( int i = 0; i < num_fields; ++i ) @@ -189,14 +166,87 @@ char* CompositeHash::SingleValHash(int type_check, char* kp0, } kp1 = kp; + break; } - else + + case TYPE_TABLE: + { + int* kp = AlignAndPadType(kp0); + TableVal* tv = v->AsTableVal(); + ListVal* lv = tv->ConvertToList(); + *kp = tv->Size(); + kp1 = reinterpret_cast(kp+1); + for ( int i = 0; i < tv->Size(); ++i ) + { + Val* key = lv->Index(i); + if ( ! (kp1 = SingleValHash(type_check, kp1, key->Type(), key, + false)) ) + return 0; + + if ( ! v->Type()->IsSet() ) + { + Val* val = tv->Lookup(key); + if ( ! (kp1 = SingleValHash(type_check, kp1, val->Type(), + val, false)) ) + return 0; + } + } + } + break; + + case TYPE_VECTOR: + { + unsigned int* kp = AlignAndPadType(kp0); + VectorVal* vv = v->AsVectorVal(); + VectorType* vt = v->Type()->AsVectorType(); + vector* indices = v->AsVector(); + *kp = vv->Size(); + kp1 = reinterpret_cast(kp+1); + for ( unsigned int i = 0; i < vv->Size(); ++i ) + { + Val* val = vv->Lookup(i); + unsigned int* kp = AlignAndPadType(kp1); + *kp = i; + kp1 = reinterpret_cast(kp+1); + kp = AlignAndPadType(kp1); + *kp = val ? 1 : 0; + kp1 = reinterpret_cast(kp+1); + + if ( val ) + { + if ( ! (kp1 = SingleValHash(type_check, kp1, + vt->YieldType(), val, false)) ) + return 0; + } + } + } + break; + + case TYPE_LIST: + { + int* kp = AlignAndPadType(kp0); + ListVal* lv = v->AsListVal(); + *kp = lv->Length(); + kp1 = reinterpret_cast(kp+1); + for ( int i = 0; i < lv->Length(); ++i ) + { + Val* v = lv->Index(i); + if ( ! (kp1 = SingleValHash(type_check, kp1, v->Type(), v, + false)) ) + return 0; + } + } + break; + + default: { reporter->InternalError("bad index type in CompositeHash::SingleValHash"); return 0; } } - break; + + break; // case TYPE_INTERNAL_VOID/OTHER + } case TYPE_INTERNAL_STRING: { @@ -286,26 +336,16 @@ HashKey* CompositeHash::ComputeSingletonHash(const Val* v, int type_check) const if ( type_check && v->Type()->InternalType() != singleton_tag ) return 0; - uint32 tmp_addr; switch ( singleton_tag ) { case TYPE_INTERNAL_INT: case TYPE_INTERNAL_UNSIGNED: return new HashKey(v->ForceAsInt()); case TYPE_INTERNAL_ADDR: -#ifdef BROv6 - return new HashKey(v->AsAddr(), 4); -#else - return new HashKey(v->AsAddr()); -#endif + return v->AsAddr().GetHashKey(); case TYPE_INTERNAL_SUBNET: -#ifdef BROv6 - return new HashKey((const uint32*) v->AsSubNet(), 5); -#else - return new HashKey((const uint32*) v->AsSubNet(), 2); - -#endif + return v->AsSubNet().GetHashKey(); case TYPE_INTERNAL_DOUBLE: return new HashKey(v->InternalDouble()); @@ -313,7 +353,7 @@ HashKey* CompositeHash::ComputeSingletonHash(const Val* v, int type_check) const case TYPE_INTERNAL_VOID: case TYPE_INTERNAL_OTHER: if ( v->Type()->Tag() == TYPE_FUNC ) - return new HashKey(v); + return new HashKey(v->AsFunc()->GetUniqueFuncID()); reporter->InternalError("bad index type in CompositeHash::ComputeSingletonHash"); return 0; @@ -353,22 +393,13 @@ int CompositeHash::SingleTypeKeySize(BroType* bt, const Val* v, break; case TYPE_INTERNAL_ADDR: -#ifdef BROv6 sz = SizeAlign(sz, sizeof(uint32)); sz += sizeof(uint32) * 3; // to make a total of 4 words -#else - sz = SizeAlign(sz, sizeof(uint32)); -#endif break; case TYPE_INTERNAL_SUBNET: -#ifdef BROv6 sz = SizeAlign(sz, sizeof(uint32)); sz += sizeof(uint32) * 4; // to make a total of 5 words -#else - sz = SizeAlign(sz, sizeof(uint32)); - sz += sizeof(uint32); // make room for width -#endif break; case TYPE_INTERNAL_DOUBLE: @@ -378,10 +409,14 @@ int CompositeHash::SingleTypeKeySize(BroType* bt, const Val* v, case TYPE_INTERNAL_VOID: case TYPE_INTERNAL_OTHER: { - if ( bt->Tag() == TYPE_FUNC ) - sz = SizeAlign(sz, sizeof(Val*)); + switch ( bt->Tag() ) { + case TYPE_FUNC: + { + sz = SizeAlign(sz, sizeof(uint32)); + break; + } - else if ( bt->Tag() == TYPE_RECORD ) + case TYPE_RECORD: { const RecordVal* rv = v ? v->AsRecordVal() : 0; RecordType* rt = bt->AsRecordType(); @@ -399,14 +434,81 @@ int CompositeHash::SingleTypeKeySize(BroType* bt, const Val* v, if ( ! sz ) return 0; } + + break; } - else + + case TYPE_TABLE: + { + if ( ! v ) + return (optional && ! calc_static_size) ? sz : 0; + + sz = SizeAlign(sz, sizeof(int)); + TableVal* tv = const_cast(v->AsTableVal()); + ListVal* lv = tv->ConvertToList(); + for ( int i = 0; i < tv->Size(); ++i ) + { + Val* key = lv->Index(i); + sz = SingleTypeKeySize(key->Type(), key, type_check, sz, false, + calc_static_size); + if ( ! sz ) return 0; + if ( ! bt->IsSet() ) + { + Val* val = tv->Lookup(key); + sz = SingleTypeKeySize(val->Type(), val, type_check, sz, + false, calc_static_size); + if ( ! sz ) return 0; + } + } + + break; + } + + case TYPE_VECTOR: + { + if ( ! v ) + return (optional && ! calc_static_size) ? sz : 0; + + sz = SizeAlign(sz, sizeof(unsigned int)); + VectorVal* vv = const_cast(v->AsVectorVal()); + for ( unsigned int i = 0; i < vv->Size(); ++i ) + { + Val* val = vv->Lookup(i); + sz = SizeAlign(sz, sizeof(unsigned int)); + sz = SizeAlign(sz, sizeof(unsigned int)); + if ( val ) + sz = SingleTypeKeySize(bt->AsVectorType()->YieldType(), + val, type_check, sz, false, + calc_static_size); + if ( ! sz ) return 0; + } + + break; + } + + case TYPE_LIST: + { + sz = SizeAlign(sz, sizeof(int)); + ListVal* lv = const_cast(v->AsListVal()); + for ( int i = 0; i < lv->Length(); ++i ) + { + sz = SingleTypeKeySize(lv->Index(i)->Type(), lv->Index(i), + type_check, sz, false, calc_static_size); + if ( ! sz) return 0; + } + + break; + } + + default: { reporter->InternalError("bad index type in CompositeHash::CompositeHash"); return 0; } } - break; + + break; // case TYPE_INTERNAL_VOID/OTHER + } case TYPE_INTERNAL_STRING: if ( ! v ) @@ -525,7 +627,7 @@ ListVal* CompositeHash::RecoverVals(const HashKey* k) const } if ( kp != k_end ) - reporter->InternalError("under-ran key in CompositeHash::DescribeKey %ld", k_end - kp); + reporter->InternalError("under-ran key in CompositeHash::DescribeKey %zd", k_end - kp); return l; } @@ -605,16 +707,13 @@ const char* CompositeHash::RecoverOneVal(const HashKey* k, const char* kp0, case TYPE_INTERNAL_ADDR: { const uint32* const kp = AlignType(kp0); -#ifdef BROv6 - const_addr_type addr_val = kp; kp1 = reinterpret_cast(kp+4); -#else - const_addr_type addr_val = *kp; - kp1 = reinterpret_cast(kp+1); -#endif + + IPAddr addr(IPv6, kp, IPAddr::Network); + switch ( tag ) { case TYPE_ADDR: - pval = new AddrVal(addr_val); + pval = new AddrVal(addr); break; default: @@ -627,47 +726,45 @@ const char* CompositeHash::RecoverOneVal(const HashKey* k, const char* kp0, case TYPE_INTERNAL_SUBNET: { - const subnet_type* const kp = - reinterpret_cast( - AlignType(kp0)); - kp1 = reinterpret_cast(kp+1); - - pval = new SubNetVal(kp->net, kp->width); + const uint32* const kp = AlignType(kp0); + kp1 = reinterpret_cast(kp+5); + pval = new SubNetVal(kp, kp[4]); } break; case TYPE_INTERNAL_VOID: case TYPE_INTERNAL_OTHER: { - if ( t->Tag() == TYPE_FUNC ) + switch ( t->Tag() ) { + case TYPE_FUNC: { - Val* const * const kp = AlignType(kp0); + const uint32* const kp = AlignType(kp0); kp1 = reinterpret_cast(kp+1); - Val* v = *kp; + Func* f = Func::GetFuncPtrByID(*kp); - if ( ! v || ! v->Type() ) + if ( ! f ) + reporter->InternalError("failed to look up unique function id %" PRIu32 " in CompositeHash::RecoverOneVal()", *kp); + + pval = new Val(f); + + if ( ! pval->Type() ) reporter->InternalError("bad aggregate Val in CompositeHash::RecoverOneVal()"); - if ( t->Tag() != TYPE_FUNC && - // ### Maybe fix later, but may be fundamentally - // un-checkable --US - ! same_type(v->Type(), t) ) - { + else if ( t->Tag() != TYPE_FUNC && + ! same_type(pval->Type(), t) ) + // ### Maybe fix later, but may be fundamentally + // un-checkable --US reporter->InternalError("inconsistent aggregate Val in CompositeHash::RecoverOneVal()"); - } // ### A crude approximation for now. - if ( t->Tag() == TYPE_FUNC && - v->Type()->Tag() != TYPE_FUNC ) - { + else if ( t->Tag() == TYPE_FUNC && + pval->Type()->Tag() != TYPE_FUNC ) reporter->InternalError("inconsistent aggregate Val in CompositeHash::RecoverOneVal()"); - } - - pval = v->Ref(); } + break; - else if ( t->Tag() == TYPE_RECORD ) + case TYPE_RECORD: { const char* kp = kp0; RecordType* rt = t->AsRecordType(); @@ -704,11 +801,91 @@ const char* CompositeHash::RecoverOneVal(const HashKey* k, const char* kp0, pval = rv; kp1 = kp; } - else + break; + + case TYPE_TABLE: + { + int n; + const int* const kp = AlignType(kp0); + n = *kp; + kp1 = reinterpret_cast(kp+1); + TableType* tt = t->AsTableType(); + TableVal* tv = new TableVal(tt); + vector keys, values; + for ( int i = 0; i < n; ++i ) + { + Val* key; + kp1 = RecoverOneVal(k, kp1, k_end, tt->Indices(), key, false); + keys.push_back(key); + if ( ! t->IsSet() ) + { + Val* value; + kp1 = RecoverOneVal(k, kp1, k_end, tt->YieldType(), value, + false); + values.push_back(value); + } + } + + for ( int i = 0; i < n; ++i ) + tv->Assign(keys[i], t->IsSet() ? 0 : values[i]); + + pval = tv; + } + break; + + case TYPE_VECTOR: + { + unsigned int n; + const unsigned int* kp = AlignType(kp0); + n = *kp; + kp1 = reinterpret_cast(kp+1); + VectorType* vt = t->AsVectorType(); + VectorVal* vv = new VectorVal(vt); + for ( unsigned int i = 0; i < n; ++i ) + { + kp = AlignType(kp1); + unsigned int index = *kp; + kp1 = reinterpret_cast(kp+1); + kp = AlignType(kp1); + unsigned int have_val = *kp; + kp1 = reinterpret_cast(kp+1); + Val* value = 0; + if ( have_val ) + kp1 = RecoverOneVal(k, kp1, k_end, vt->YieldType(), value, + false); + vv->Assign(index, value, 0); + } + + pval = vv; + } + break; + + case TYPE_LIST: + { + int n; + const int* const kp = AlignType(kp0); + n = *kp; + kp1 = reinterpret_cast(kp+1); + TypeList* tl = t->AsTypeList(); + ListVal* lv = new ListVal(TYPE_ANY); + for ( int i = 0; i < n; ++i ) + { + Val* v; + BroType* it = (*tl->Types())[i]; + kp1 = RecoverOneVal(k, kp1, k_end, it, v, false); + lv->Append(v); + } + + pval = lv; + } + break; + + default: { reporter->InternalError("bad index type in CompositeHash::DescribeKey"); } } + } break; case TYPE_INTERNAL_STRING: diff --git a/src/CompHash.h b/src/CompHash.h index 0e12cbf9a8..1a02114358 100644 --- a/src/CompHash.h +++ b/src/CompHash.h @@ -1,5 +1,3 @@ -// $Id: CompHash.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef comphash_h diff --git a/src/Conn.cc b/src/Conn.cc index e3e56c5eef..c2008b1faa 100644 --- a/src/Conn.cc +++ b/src/Conn.cc @@ -1,5 +1,3 @@ -// $Id: Conn.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -17,32 +15,6 @@ #include "binpac.h" #include "TunnelHandler.h" -HashKey* ConnID::BuildConnKey() const - { - Key key; - - // Lookup up connection based on canonical ordering, which is - // the smaller of and - // followed by the other. - if ( is_one_way || - addr_port_canon_lt(src_addr, src_port, dst_addr, dst_port) ) - { - copy_addr(src_addr, key.ip1); - copy_addr(dst_addr, key.ip2); - key.port1 = src_port; - key.port2 = dst_port; - } - else - { - copy_addr(dst_addr, key.ip1); - copy_addr(src_addr, key.ip2); - key.port1 = dst_port; - key.port2 = src_port; - } - - return new HashKey(&key, sizeof(key)); - } - void ConnectionTimer::Init(Connection* arg_conn, timer_func arg_timer, int arg_do_expire) { @@ -146,8 +118,8 @@ Connection::Connection(NetSessions* s, HashKey* k, double t, const ConnID* id, T key = k; start_time = last_time = t; - copy_addr(id->src_addr, orig_addr); - copy_addr(id->dst_addr, resp_addr); + orig_addr = id->src_addr; + resp_addr = id->dst_addr; orig_port = id->src_port; resp_port = id->dst_port; proto = TRANSPORT_UNKNOWN; @@ -210,9 +182,7 @@ Connection::~Connection() Unref(conn_val); } - if ( tunnel_parent ) - delete tunnel_parent; - + delete tunnel_parent; delete key; delete root_analyzer; delete conn_timer_mgr; @@ -531,7 +501,7 @@ Val* Connection::BuildVersionVal(const char* s, int len) return sw; } -int Connection::VersionFoundEvent(const uint32* addr, const char* s, int len, +int Connection::VersionFoundEvent(const IPAddr& addr, const char* s, int len, Analyzer* analyzer) { if ( ! software_version_found && ! software_parse_error ) @@ -569,7 +539,7 @@ int Connection::VersionFoundEvent(const uint32* addr, const char* s, int len, return 1; } -int Connection::UnparsedVersionFoundEvent(const uint32* addr, +int Connection::UnparsedVersionFoundEvent(const IPAddr& addr, const char* full, int len, Analyzer* analyzer) { // Skip leading white space. @@ -703,10 +673,9 @@ TimerMgr* Connection::GetTimerMgr() const void Connection::FlipRoles() { - uint32 tmp_addr[NUM_ADDR_WORDS]; - copy_addr(resp_addr, tmp_addr); - copy_addr(orig_addr, resp_addr); - copy_addr(tmp_addr, orig_addr); + IPAddr tmp_addr = resp_addr; + orig_addr = resp_addr; + resp_addr = tmp_addr; uint32 tmp_port = resp_port; resp_port = orig_port; @@ -762,14 +731,14 @@ void Connection::Describe(ODesc* d) const } d->SP(); - d->Add(dotted_addr(orig_addr)); + d->Add(orig_addr); d->Add(":"); d->Add(ntohs(orig_port)); d->SP(); d->AddSP("->"); - d->Add(dotted_addr(resp_addr)); + d->Add(resp_addr); d->Add(":"); d->Add(ntohs(resp_port)); @@ -792,9 +761,8 @@ bool Connection::DoSerialize(SerialInfo* info) const // First we write the members which are needed to // create the HashKey. - for ( int j = 0; j < NUM_ADDR_WORDS; ++j ) - if ( ! SERIALIZE(orig_addr[j]) || ! SERIALIZE(resp_addr[j]) ) - return false; + if ( ! SERIALIZE(orig_addr) || ! SERIALIZE(resp_addr) ) + return false; if ( ! SERIALIZE(orig_port) || ! SERIALIZE(resp_port) ) return false; @@ -840,21 +808,21 @@ bool Connection::DoUnserialize(UnserialInfo* info) // Build the hash key first. Some of the recursive *::Unserialize() // functions may need it. - for ( int i = 0; i < NUM_ADDR_WORDS; ++i ) - if ( ! UNSERIALIZE(&orig_addr[i]) || ! UNSERIALIZE(&resp_addr[i]) ) - goto error; + ConnID id; + + if ( ! UNSERIALIZE(&orig_addr) || ! UNSERIALIZE(&resp_addr) ) + goto error; if ( ! UNSERIALIZE(&orig_port) || ! UNSERIALIZE(&resp_port) ) goto error; - ConnID id; id.src_addr = orig_addr; id.dst_addr = resp_addr; // This doesn't work for ICMP. But I guess this is not really important. id.src_port = orig_port; id.dst_port = resp_port; id.is_one_way = 0; // ### incorrect for ICMP - key = id.BuildConnKey(); + key = BuildConnIDHashKey(id); int len; if ( ! UNSERIALIZE(&len) ) diff --git a/src/Conn.h b/src/Conn.h index 828ad66e7c..99af34a07a 100644 --- a/src/Conn.h +++ b/src/Conn.h @@ -1,5 +1,3 @@ -// $Id: Conn.h 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef conn_h @@ -14,6 +12,7 @@ #include "PersistenceSerializer.h" #include "RuleMatcher.h" #include "AnalyzerTags.h" +#include "IPAddr.h" class Connection; class ConnectionTimer; @@ -35,52 +34,17 @@ typedef enum { typedef void (Connection::*timer_func)(double t); struct ConnID { - const uint32* src_addr; - const uint32* dst_addr; + IPAddr src_addr; + IPAddr dst_addr; uint32 src_port; uint32 dst_port; - bool is_one_way; // if true, don't canonicalize - - // Returns a ListVal suitable for looking up a connection in - // a hash table. addr/ports are expected to be in network order. - // Unless is_one_way is true, the lookup sorts src and dst, - // so src_addr/src_port and dst_addr/dst_port just have to - // reflect the two different sides of the connection, - // neither has to be the particular source/destination - // or originator/responder. - HashKey* BuildConnKey() const; - - // The structure used internally for hashing. - struct Key { - uint32 ip1[NUM_ADDR_WORDS]; - uint32 ip2[NUM_ADDR_WORDS]; - uint16 port1; - uint16 port2; - }; + bool is_one_way; // if true, don't canonicalize order }; -static inline int addr_port_canon_lt(const uint32* a1, uint32 p1, - const uint32* a2, uint32 p2) +static inline int addr_port_canon_lt(const IPAddr& addr1, uint32 p1, + const IPAddr& addr2, uint32 p2) { -#ifdef BROv6 - // Because it's a canonical ordering, not a strict ordering, - // we can choose to give more weight to the least significant - // word than to the most significant word. This matters - // because for the common case of IPv4 addresses embedded in - // a IPv6 address, the top three words are identical, so we can - // save a few cycles by first testing the bottom word. - return a1[3] < a2[3] || - (a1[3] == a2[3] && - (a1[2] < a2[2] || - (a1[2] == a2[2] && - (a1[1] < a2[1] || - (a1[1] == a2[1] && - (a1[0] < a2[0] || - (a1[0] == a2[0] && - p1 < p2))))))); -#else - return *a1 < *a2 || (*a1 == *a2 && p1 < p2); -#endif + return addr1 < addr2 || (addr1 == addr2 && p1 < p2); } class Analyzer; @@ -122,8 +86,8 @@ public: double LastTime() const { return last_time; } void SetLastTime(double t) { last_time = t; } - const uint32* OrigAddr() const { return orig_addr; } - const uint32* RespAddr() const { return resp_addr; } + const IPAddr& OrigAddr() const { return orig_addr; } + const IPAddr& RespAddr() const { return resp_addr; } uint32 OrigPort() const { return orig_port; } uint32 RespPort() const { return resp_port; } @@ -188,11 +152,11 @@ public: // Raises a software_version_found event based on the // given string (returns false if it's not parseable). - int VersionFoundEvent(const uint32* addr, const char* s, int len, + int VersionFoundEvent(const IPAddr& addr, const char* s, int len, Analyzer* analyzer = 0); // Raises a software_unparsed_version_found event. - int UnparsedVersionFoundEvent(const uint32* addr, + int UnparsedVersionFoundEvent(const IPAddr& addr, const char* full_descr, int len, Analyzer* analyzer); void Event(EventHandlerPtr f, Analyzer* analyzer, const char* name = 0); @@ -276,30 +240,6 @@ public: // Sets the transport protocol in use. void SetTransport(TransportProto arg_proto) { proto = arg_proto; } - // If the connection compressor is activated, we need a special memory - // layout for connections. (See ConnCompressor.h) - void* operator new(size_t size) - { - if ( ! use_connection_compressor ) - return ::operator new(size); - - void* c = ::operator new(size + 4); - - // We have to turn off the is_pending bit. By setting the - // first four bytes to zero, we'll achieve this. - *((uint32*) c) = 0; - - return ((char *) c) + 4; - } - - void operator delete(void* ptr) - { - if ( ! use_connection_compressor ) - ::operator delete(ptr); - else - ::operator delete(((char*) ptr) - 4); - } - void SetUID(uint64 arg_uid) { uid = arg_uid; } protected: @@ -328,8 +268,8 @@ protected: TimerMgr::Tag* conn_timer_mgr; timer_list timers; - uint32 orig_addr[NUM_ADDR_WORDS]; // in network order - uint32 resp_addr[NUM_ADDR_WORDS]; // in network order + IPAddr orig_addr; + IPAddr resp_addr; uint32 orig_port, resp_port; // in network order TransportProto proto; double start_time, last_time; diff --git a/src/ConnCompressor.cc b/src/ConnCompressor.cc deleted file mode 100644 index 112abe089e..0000000000 --- a/src/ConnCompressor.cc +++ /dev/null @@ -1,1043 +0,0 @@ -// $Id: ConnCompressor.cc 7008 2010-03-25 02:42:20Z vern $ - -#include - -#include "ConnCompressor.h" -#include "Event.h" -#include "ConnSizeAnalyzer.h" -#include "net_util.h" - -// The basic model of the compressor is to wait for an answer before -// instantiating full connection state. Until we see a reply, only a minimal -// amount of state is stored. This has some consequences: -// -// - We try to mimic TCP.cc as close as possible, but this works only to a -// certain degree; e.g., we don't consider any of the wait-a-bit-after- -// the-connection-has-been-closed timers. That means we will get differences -// in connection semantics if the compressor is turned on. On the other -// hand, these differences will occur only for not well-established -// sessions, and experience shows that for these kinds of connections -// semantics are ill-defined in any case. -// -// - If an originator sends multiple different packets before we see a reply, -// we lose the information about additional packets (more precisely, we -// merge the packet headers into one). In particular, we lose any payload. -// This is a major problem if we see only one direction of a connection. -// When analyzing only SYN/FIN/RSTs this leads to differences if we miss -// the SYN/ACK. -// -// To avoid losing payload, there is the option cc_instantiate_on_data: -// if enabled and the originator sends a non-control packet after the -// initial packet, we instantiate full connection state. -// -// - We lose some of the information contained in initial packets (e.g., most -// IP/TCP options and any payload). If you depend on them, you don't -// want to use the compressor. -// -// Optionally, the compressor can take care only of initial SYNs and -// instantiate full connection state for all other connection setups. -// To enable, set cc_handle_only_syns to true. -// -// - The compressor may handle refused connections (i.e., initial packets -// followed by RST from responder) itself. Again, this leads to differences -// from default TCP processing and is therefore turned off by default. -// To enable, set cc_handle_resets to true. -// -// - We don't match signatures on connections which are completely handled -// by the compressor. Matching would require significant additional state -// w/o being very helpful. -// -// - If use_conn_size_analyzer is True, the reported counts for bytes and -// packets may not account for some packets/data that is part of those -// packets which the connection compressor handles. The error, if any, will -// however be small. - - -#ifdef DEBUG -static inline const char* fmt_conn_id(const ConnCompressor::PendingConn* c) - { - if ( c->ip1_is_src ) - return fmt_conn_id(c->key.ip1, c->key.port1, - c->key.ip2, c->key.port2); - else - return fmt_conn_id(c->key.ip2, c->key.port2, - c->key.ip1, c->key.port1); - } - -static inline const char* fmt_conn_id(const Connection* c) - { - return fmt_conn_id(c->OrigAddr(), c->OrigPort(), - c->RespAddr(), c->RespPort()); - } - -static inline const char* fmt_conn_id(const IP_Hdr* ip) - { - const struct tcphdr* tp = (const struct tcphdr*) ip->Payload(); - return fmt_conn_id(ip->SrcAddr(), tp->th_sport, - ip->DstAddr(), tp->th_dport); - } -#endif - -ConnCompressor::ConnCompressor() - { - first_block = last_block = 0; - first_non_expired = 0; - conn_val = 0; - - sizes.connections = sizes.connections_total = 0; - sizes.pending_valid = sizes.pending_total = sizes.pending_in_mem = 0; - sizes.hash_table_size = 0; - sizes.memory = 0; - } - -ConnCompressor::~ConnCompressor() - { - Block* next; - for ( Block* b = first_block; b; b = next ) - { - next = b->next; - delete b; - } - } - -Connection* ConnCompressor::NextPacket(double t, HashKey* key, const IP_Hdr* ip, - const struct pcap_pkthdr* hdr, const u_char* const pkt) - { - // Expire old stuff. - DoExpire(t); - - // Most sanity checks on header sizes are already done ... - const struct tcphdr* tp = (const struct tcphdr*) ip->Payload(); - - // ... except this one. - uint32 tcp_hdr_len = tp->th_off * 4; - if ( tcp_hdr_len > uint32(ip->TotalLen() - ip->HdrLen()) ) - { - sessions->Weird("truncated_header", hdr, pkt); - delete key; - return 0; - } - - bool external = current_iosrc->GetCurrentTag(); - ConnData* c = conns.Lookup(key); - - Unref(conn_val); - conn_val = 0; - - // Do we already have a Connection object? - if ( c && IsConnPtr(c) ) - { - Connection* conn = MakeConnPtr(c); - int consistent = 1; - - if ( external ) - { - // External, and we already have a full connection. - // That means we use the same logic as in NetSessions - // to compare the tags. - consistent = sessions->CheckConnectionTag(conn); - if ( consistent < 0 ) - { - delete key; - return 0; - } - } - - if ( ! consistent || conn->IsReuse(t, ip->Payload()) ) - { - if ( consistent ) - { - DBG_LOG(DBG_COMPRESSOR, "%s reuse", fmt_conn_id(conn)); - conn->Event(connection_reused, 0); - } - - sessions->Remove(conn); - --sizes.connections; - - return Instantiate(t, key, ip); - } - - DBG_LOG(DBG_COMPRESSOR, "%s pass through", fmt_conn_id(conn)); - delete key; - return conn; - } - - PendingConn* pending = c ? MakePendingConnPtr(c) : 0; - - if ( c && external ) - { - // External, but previous packets were not, i.e., they used - // the global timer queue. We finish the old connection - // and instantiate a full one now. - DBG_LOG(DBG_TM, "got packet with tag %s for already" - "known cc connection, instantiating full conn", - current_iosrc->GetCurrentTag()->c_str()); - - Event(pending, 0, connection_attempt, - TCP_ENDPOINT_INACTIVE, 0, TCP_ENDPOINT_INACTIVE); - Event(pending, 0, connection_state_remove, - TCP_ENDPOINT_INACTIVE, 0, TCP_ENDPOINT_INACTIVE); - Remove(key); - - return Instantiate(t, key, ip); - } - - if ( c && pending->invalid && - network_time < pending->time + tcp_session_timer ) - { - // The old connection has terminated sooner than - // tcp_session_timer. We assume this packet to be - // a latecomer, and ignore it. - DBG_LOG(DBG_COMPRESSOR, "%s ignored", fmt_conn_id(pending)); - sessions->DumpPacket(hdr, pkt); - delete key; - return 0; - } - - // Simulate tcp_{reset,close}_delay for initial FINs/RSTs - if ( c && ! pending->invalid && - ((pending->FIN && pending->time + tcp_close_delay < t ) || - (pending->RST && pending->time + tcp_reset_delay < t )) ) - { - DBG_LOG(DBG_COMPRESSOR, "%s closed", fmt_conn_id(pending)); - int orig_state = - pending->FIN ? TCP_ENDPOINT_CLOSED : TCP_ENDPOINT_RESET; - - Event(pending, 0, connection_partial_close, orig_state, - ip->PayloadLen() - (tp->th_off * 4), - TCP_ENDPOINT_INACTIVE); - Event(pending, 0, connection_state_remove, orig_state, - ip->PayloadLen() - (tp->th_off * 4), - TCP_ENDPOINT_INACTIVE); - - Remove(key); - - Connection* tc = FirstFromOrig(t, key, ip, tp); - if ( ! tc ) - { - delete key; - sessions->DumpPacket(hdr, pkt); - } - - return tc; - } - - Connection* tc; - - if ( ! c || pending->invalid ) - { - // First packet of a connection. - if ( c ) - Remove(key); - - if ( external ) - // External, we directly instantiate a full connection. - tc = Instantiate(t, key, ip); - else - tc = FirstFromOrig(t, key, ip, tp); - } - - else if ( addr_eq(ip->SrcAddr(), SrcAddr(pending)) && - tp->th_sport == SrcPort(pending) ) - // Another packet from originator. - tc = NextFromOrig(pending, t, key, ip, tp); - - else - // A reply. - tc = Response(pending, t, key, ip, tp); - - if ( ! tc ) - { - delete key; - sessions->DumpPacket(hdr, pkt); - } - - return tc; - } - -static int parse_tcp_options(unsigned int opt, unsigned int optlen, - const u_char* option, TCP_Analyzer* analyzer, - bool is_orig, void* cookie) - { - ConnCompressor::PendingConn* c = (ConnCompressor::PendingConn*) cookie; - - // We're only interested in window_scale. - if ( opt == 3 ) - c->window_scale = option[2]; - - return 0; - } - -Connection* ConnCompressor::FirstFromOrig(double t, HashKey* key, - const IP_Hdr* ip, const tcphdr* tp) - { - if ( cc_handle_only_syns && ! (tp->th_flags & TH_SYN) ) - return Instantiate(t, key, ip); - - // The first packet of a connection. - PendingConn* pending = MakeNewState(t); - PktHdrToPendingConn(t, key, ip, tp, pending); - - DBG_LOG(DBG_COMPRESSOR, "%s our", fmt_conn_id(pending)); - - // The created DictEntry will point directly into our PendingConn. - // So, we have to be careful when we delete it. - conns.Dictionary::Insert(&pending->key, sizeof(pending->key), - pending->hash, MakeMapPtr(pending), 0); - - // Mimic some of TCP_Analyzer's weirds for SYNs. - // To be completely precise, we'd need to check this at a few - // more locations in NextFromOrig() and Reply(). However, that - // does not really seem worth it, as this is the standard case. - if ( tp->th_flags & TH_SYN ) - { - if ( tp->th_flags & TH_RST ) - Weird(pending, t, "TCP_christmas"); - - if ( tp->th_flags & TH_URG ) - Weird(pending, t, "baroque_SYN"); - - int len = ip->TotalLen() - ip->HdrLen() - tp->th_off * 4; - - if ( len > 0 ) - // T/TCP definitely complicates this. - Weird(pending, t, "SYN_with_data"); - } - - if ( tp->th_flags & TH_FIN ) - { - if ( ! (tp->th_flags & TH_SYN) ) - Weird(pending, t, "spontaneous_FIN"); - } - - if ( tp->th_flags & TH_RST ) - { - if ( ! (tp->th_flags & TH_SYN) ) - Weird(pending, t, "spontaneous_RST"); - } - - ++sizes.pending_valid; - ++sizes.pending_total; - ++sizes.pending_in_mem; - - Event(pending, 0, new_connection, - TCP_ENDPOINT_INACTIVE, 0, TCP_ENDPOINT_INACTIVE); - - if ( current_iosrc->GetCurrentTag() ) - { - Val* tag = - new StringVal(current_iosrc->GetCurrentTag()->c_str()); - Event(pending, 0, connection_external, - TCP_ENDPOINT_INACTIVE, 0, TCP_ENDPOINT_INACTIVE, tag); - } - - return 0; - } - -Connection* ConnCompressor::NextFromOrig(PendingConn* pending, double t, - HashKey* key, const IP_Hdr* ip, - const tcphdr* tp) - { - // Another packet from the same host without seeing an answer so far. - DBG_LOG(DBG_COMPRESSOR, "%s same again", fmt_conn_id(pending)); - - ++pending->num_pkts; - ++pending->num_bytes_ip += ip->PayloadLen(); - - // New window scale overrides old - not great, this is a (subtle) - // evasion opportunity. - if ( TCP_Analyzer::ParseTCPOptions(tp, parse_tcp_options, 0, 0, - pending) < 0 ) - Weird(pending, t, "corrupt_tcp_options"); - - if ( tp->th_flags & TH_SYN ) - // New seq overrides old. - pending->seq = tp->th_seq; - - // Mimic TCP_Endpoint::Size() - int size = ntohl(tp->th_seq) - ntohl(pending->seq); - if ( size != 0 ) - --size; - - if ( size != 0 && (pending->FIN || (tp->th_flags & TH_FIN)) ) - --size; - - if ( size < 0 ) - // We only care about the size for broken connections. - // Surely for those it's more likely that the sequence - // numbers are confused than that they really transferred - // > 2 GB of data. Plus, for 64-bit ints these sign-extend - // up to truly huge, non-sensical unsigned values. - size = 0; - - if ( pending->SYN ) - { - // We're in state SYN_SENT or SYN_ACK_SENT. - if ( tp->th_flags & TH_RST) - { - Event(pending, t, connection_reset, - TCP_ENDPOINT_RESET, size, TCP_ENDPOINT_INACTIVE); - Event(pending, t, connection_state_remove, - TCP_ENDPOINT_RESET, size, TCP_ENDPOINT_INACTIVE); - - Invalidate(key); - return 0; - } - - else if ( tp->th_flags & TH_FIN) - { - Event(pending, t, connection_partial_close, - TCP_ENDPOINT_CLOSED, size, TCP_ENDPOINT_INACTIVE); - Event(pending, t, connection_state_remove, - TCP_ENDPOINT_CLOSED, size, TCP_ENDPOINT_INACTIVE); - Invalidate(key); - return 0; - } - - else if ( tp->th_flags & TH_SYN ) - { - if ( (tp->th_flags & TH_ACK) && ! pending->ACK ) - Weird(pending, t, "repeated_SYN_with_ack"); - } - - else - { - // A data packet without seeing a SYN/ACK first. As - // long as we stick with the principle of instantiating - // state only when we see a reply, we have to throw - // this data away. Optionally we may instantiate a - // real connection now. - - if ( cc_instantiate_on_data ) - return Instantiate(key, pending); - // else - // Weird(pending, t, "data_without_SYN_ACK"); - } - } - - else - { // We're in state INACTIVE. - if ( tp->th_flags & TH_RST) - { - Event(pending, t, connection_reset, - TCP_ENDPOINT_RESET, size, TCP_ENDPOINT_INACTIVE); - Event(pending, t, connection_state_remove, - TCP_ENDPOINT_RESET, size, TCP_ENDPOINT_INACTIVE); - - Invalidate(key); - return 0; - } - - else if ( tp->th_flags & TH_FIN) - { - Event(pending, t, connection_half_finished, - TCP_ENDPOINT_CLOSED, size, TCP_ENDPOINT_INACTIVE); - Event(pending, t, connection_state_remove, - TCP_ENDPOINT_CLOSED, size, TCP_ENDPOINT_INACTIVE); - - Invalidate(key); - return 0; - } - - else if ( tp->th_flags & TH_SYN ) - { - if ( ! tp->th_flags & TH_ACK ) - { - Weird(pending, t, "SYN_after_partial"); - pending->SYN = 1; - } - } - - else - // Another data packet. See discussion above. - if ( cc_instantiate_on_data ) - return Instantiate(key, pending); - - // else - // Weird(pending, t, "data_without_SYN_ACK"); - } - - return 0; - } - -Connection* ConnCompressor::Response(PendingConn* pending, double t, - HashKey* key, const IP_Hdr* ip, - const tcphdr* tp) - { - // The packet comes from the former responder. That means we are - // seeing a reply, so we are going to create a "real" connection now. - DBG_LOG(DBG_COMPRESSOR, "%s response", fmt_conn_id(pending)); - - // Optional: if it's a RST after SYN, we directly generate a - // connection_rejected and throw the state away. - if ( cc_handle_resets && (tp->th_flags & TH_RST) && pending->SYN ) - { - // See discussion of size in DoExpire(). - DBG_LOG(DBG_COMPRESSOR, "%s reset", fmt_conn_id(pending)); - - Event(pending, t, connection_reset, - TCP_ENDPOINT_SYN_SENT, 0, TCP_ENDPOINT_RESET); - Event(pending, t, connection_state_remove, - TCP_ENDPOINT_SYN_SENT, 0, TCP_ENDPOINT_RESET); - - Invalidate(key); - return 0; - } - - // If a connection's initial packet is a RST, Bro's standard TCP - // processing considers the connection done right away. We simulate - // this by instantiating a second connection in this case. The - // first one will time out eventually. - if ( pending->RST && ! pending->SYN ) - { - int orig_state = - pending->RST ? TCP_ENDPOINT_RESET : TCP_ENDPOINT_CLOSED; - Event(pending, 0, connection_attempt, - orig_state, 0, TCP_ENDPOINT_INACTIVE); - Event(pending, 0, connection_state_remove, - orig_state, 0, TCP_ENDPOINT_INACTIVE); - - // Override with current packet. - PktHdrToPendingConn(t, key, ip, tp, pending); - return 0; - } - - return Instantiate(key, pending); - } - -Connection* ConnCompressor::Instantiate(HashKey* key, PendingConn* pending) - { - // Instantantiate a Connection. - ConnID conn_id; - conn_id.src_addr = SrcAddr(pending); - conn_id.dst_addr = DstAddr(pending); - conn_id.src_port = SrcPort(pending); - conn_id.dst_port = DstPort(pending); - - pending->invalid = 1; - --sizes.pending_valid; - --sizes.pending_total; - - // Fake the first packet. - const IP_Hdr* faked_pkt = PendingConnToPacket(pending); - Connection* new_conn = sessions->NewConn(key, pending->time, &conn_id, - faked_pkt->Payload(), IPPROTO_TCP, 0); - - if ( ! new_conn ) - { - // This connection is not to be analyzed (e.g., it may be - // a partial one). - DBG_LOG(DBG_COMPRESSOR, "%s nop", fmt_conn_id(pending)); - return 0; - } - - new_conn->SetUID(pending->uid); - - DBG_LOG(DBG_COMPRESSOR, "%s instantiated", fmt_conn_id(pending)); - - ++sizes.connections; - ++sizes.connections_total; - - if ( new_packet ) - new_conn->Event(new_packet, 0, - sessions->BuildHeader(faked_pkt->IP4_Hdr())); - - // NewConn() may have swapped originator and responder. - int is_orig = addr_eq(conn_id.src_addr, new_conn->OrigAddr()) && - conn_id.src_port == new_conn->OrigPort(); - - // Pass the faked packet to the connection. - const u_char* payload = faked_pkt->Payload(); - - int dummy_record_packet, dummy_record_content; - new_conn->NextPacket(pending->time, is_orig, - faked_pkt, faked_pkt->PayloadLen(), - faked_pkt->PayloadLen(), payload, - dummy_record_packet, dummy_record_content, 0, 0, 0); - - // Removing necessary because the key will be destroyed at some point. - conns.Remove(&pending->key, sizeof(pending->key), pending->hash, true); - conns.Insert(key, MakeMapPtr(new_conn)); - - return new_conn; - } - -Connection* ConnCompressor::Instantiate(double t, HashKey* key, - const IP_Hdr* ip) - { - const struct tcphdr* tp = (const struct tcphdr*) ip->Payload(); - - ConnID conn_id; - conn_id.src_addr = ip->SrcAddr(); - conn_id.dst_addr = ip->DstAddr(); - conn_id.src_port = tp->th_sport; - conn_id.dst_port = tp->th_dport; - - Connection* new_conn = - sessions->NewConn(key, t, &conn_id, ip->Payload(), IPPROTO_TCP, 0); - - if ( ! new_conn ) - { - // This connection is not to be analyzed (e.g., it may be - // a partial one). - DBG_LOG(DBG_COMPRESSOR, "%s nop", fmt_conn_id(ip)); - return 0; - } - - DBG_LOG(DBG_COMPRESSOR, "%s instantiated", fmt_conn_id(ip)); - - conns.Insert(key, MakeMapPtr(new_conn)); - ++sizes.connections; - ++sizes.connections_total; - - if ( new_connection ) - new_conn->Event(new_connection, 0); - - if ( current_iosrc->GetCurrentTag() ) - { - Val* tag = - new StringVal(current_iosrc->GetCurrentTag()->c_str()); - new_conn->Event(connection_external, 0, tag); - } - - return new_conn; - } - -void ConnCompressor::PktHdrToPendingConn(double time, const HashKey* key, - const IP_Hdr* ip, const struct tcphdr* tp, PendingConn* c) - { - memcpy(&c->key, key->Key(), key->Size()); - - c->hash = key->Hash(); - c->ip1_is_src = addr_eq(c->key.ip1, ip->SrcAddr()) && - c->key.port1 == tp->th_sport; - c->time = time; - c->window = tp->th_win; - c->seq = tp->th_seq; - c->ack = tp->th_ack; - c->window_scale = 0; - c->SYN = (tp->th_flags & TH_SYN) != 0; - c->FIN = (tp->th_flags & TH_FIN) != 0; - c->RST = (tp->th_flags & TH_RST) != 0; - c->ACK = (tp->th_flags & TH_ACK) != 0; - c->uid = calculate_unique_id(); - c->num_bytes_ip = ip->TotalLen(); - c->num_pkts = 1; - c->invalid = 0; - - if ( TCP_Analyzer::ParseTCPOptions(tp, parse_tcp_options, 0, 0, c) < 0 ) - sessions->Weird("corrupt_tcp_options", ip); - } - -// Fakes an empty TCP packet based on the information in PendingConn. -const IP_Hdr* ConnCompressor::PendingConnToPacket(const PendingConn* c) - { - static ip* ip = 0; - static tcphdr* tp = 0; - static IP_Hdr* ip_hdr = 0; - - if ( ! ip ) - { // Initialize. ### Note, only handles IPv4 for now. - int packet_length = sizeof(*ip) + sizeof(*tp); - ip = (struct ip*) new char[packet_length]; - tp = (struct tcphdr*) (((char*) ip) + sizeof(*ip)); - ip_hdr = new IP_Hdr(ip); - - // Constant fields. - ip->ip_v = 4; - ip->ip_hl = sizeof(*ip) / 4; // no options - ip->ip_tos = 0; - ip->ip_len = htons(packet_length); - ip->ip_id = 0; - ip->ip_off = 0; - ip->ip_ttl = 255; - ip->ip_p = IPPROTO_TCP; - ip->ip_sum = 0; // is not going to be checked - - tp->th_off = sizeof(*tp) / 4; // no options for now - tp->th_urp = 0; - } - - // Note, do *not* use copy_addr() here. This is because we're - // copying to an IPv4 header, which has room for exactly and - // only an IPv4 address. -#ifdef BROv6 - if ( ! is_v4_addr(c->key.ip1) || ! is_v4_addr(c->key.ip2) ) - reporter->InternalError("IPv6 snuck into connection compressor"); -#endif - *(uint32*) &ip->ip_src = - to_v4_addr(c->ip1_is_src ? c->key.ip1 : c->key.ip2); - *(uint32*) &ip->ip_dst = - to_v4_addr(c->ip1_is_src ? c->key.ip2 : c->key.ip1); - - if ( c->ip1_is_src ) - { - tp->th_sport = c->key.port1; - tp->th_dport = c->key.port2; - } - else - { - tp->th_sport = c->key.port2; - tp->th_dport = c->key.port1; - } - - tp->th_win = c->window; - tp->th_seq = c->seq; - tp->th_ack = c->ack; - tp->th_flags = MakeFlags(c); - tp->th_sum = 0; - tp->th_sum = 0xffff - tcp_checksum(ip, tp, 0); - - // FIXME: Add TCP options. - return ip_hdr; - } - -uint8 ConnCompressor::MakeFlags(const PendingConn* c) const - { - uint8 tcp_flags = 0; - if ( c->SYN ) - tcp_flags |= TH_SYN; - if ( c->FIN ) - tcp_flags |= TH_FIN; - if ( c->RST ) - tcp_flags |= TH_RST; - if ( c->ACK ) - tcp_flags |= TH_ACK; - - return tcp_flags; - } - -ConnCompressor::PendingConn* ConnCompressor::MakeNewState(double t) - { - // See if there is enough space in the current block. - if ( last_block && - int(sizeof(PendingConn)) <= BLOCK_SIZE - last_block->bytes_used ) - { - PendingConn* c = (PendingConn*) &last_block->data[last_block->bytes_used]; - last_block->bytes_used += sizeof(PendingConn); - c->is_pending = true; - return c; - } - - // Get new block. - Block* b = new Block; - b->time = t; - b->bytes_used = sizeof(PendingConn); - b->next = 0; - b->prev = last_block; - - if ( last_block ) - last_block->next = b; - else - first_block = b; - - last_block = b; - - sizes.memory += padded_sizeof(*b); - PendingConn* c = (PendingConn*) &b->data; - c->is_pending = true; - return c; - } - -void ConnCompressor::DoExpire(double t) - { - while ( first_block ) - { - Block* b = first_block; - - unsigned char* p = - first_non_expired ? first_non_expired : b->data; - - while ( p < b->data + b->bytes_used ) - { - Unref(conn_val); - conn_val = 0; - - PendingConn* c = (PendingConn*) p; - if ( t && (c->time + tcp_SYN_timeout > t) ) - { - // All following entries are still - // recent enough. - first_non_expired = p; - return; - } - - if ( ! c->invalid ) - { - // Expired. - DBG_LOG(DBG_COMPRESSOR, "%s expire", fmt_conn_id(c)); - - HashKey key(&c->key, sizeof(c->key), c->hash, true); - - ConnData* cd = conns.Lookup(&key); - if ( cd && ! IsConnPtr(cd) ) - conns.Remove(&c->key, sizeof(c->key), - c->hash, true); - - int orig_state = TCP_ENDPOINT_INACTIVE; - - if ( c->FIN ) - orig_state = TCP_ENDPOINT_CLOSED; - if ( c->RST ) - orig_state = TCP_ENDPOINT_RESET; - if ( c->SYN ) - orig_state = TCP_ENDPOINT_SYN_SENT; - - // We're not able to get the correct size - // here (with "correct" meaning value that - // standard connection processing reports). - // We could if would also store last_seq, but - // doesn't seem worth it. - - Event(c, 0, connection_attempt, - orig_state, 0, TCP_ENDPOINT_INACTIVE); - Event(c, 0, connection_state_remove, - orig_state, 0, TCP_ENDPOINT_INACTIVE); - - c->invalid = 1; - --sizes.pending_valid; - } - - p += sizeof(PendingConn); - --sizes.pending_in_mem; - } - - // Full block expired, so delete it. - first_block = b->next; - - if ( b->next ) - b->next->prev = 0; - else - last_block = 0; - - delete b; - - first_non_expired = 0; - sizes.memory -= padded_sizeof(*b); - } - } - -void ConnCompressor::Event(const PendingConn* pending, double t, - const EventHandlerPtr& event, int orig_state, - int orig_size, int resp_state, Val* arg) - { - if ( ! conn_val ) - { - if ( ! event ) - return; - - // We only raise events if NewConn() would have actually - // instantiated the Connection. - bool flip_roles; - if ( ! sessions->WantConnection(ntohs(SrcPort(pending)), - ntohs(DstPort(pending)), - TRANSPORT_TCP, - MakeFlags(pending), - flip_roles) ) - return; - - conn_val = new RecordVal(connection_type); - RecordVal* id_val = new RecordVal(conn_id); - RecordVal* orig_endp = new RecordVal(endpoint); - RecordVal* resp_endp = new RecordVal(endpoint); - - if ( orig_state == TCP_ENDPOINT_INACTIVE ) - { - if ( pending->SYN ) - orig_state = pending->ACK ? - TCP_ENDPOINT_SYN_ACK_SENT : - TCP_ENDPOINT_SYN_SENT; - else - orig_state = TCP_ENDPOINT_PARTIAL; - } - - int tcp_state = TCP_ENDPOINT_INACTIVE; - - if ( ! flip_roles ) - { - id_val->Assign(0, new AddrVal(SrcAddr(pending))); - id_val->Assign(1, new PortVal(ntohs(SrcPort(pending)), - TRANSPORT_TCP)); - id_val->Assign(2, new AddrVal(DstAddr(pending))); - id_val->Assign(3, new PortVal(ntohs(DstPort(pending)), - TRANSPORT_TCP)); - orig_endp->Assign(0, new Val(orig_size, TYPE_COUNT)); - orig_endp->Assign(1, new Val(orig_state, TYPE_COUNT)); - - if ( ConnSize_Analyzer::Available() ) - { - // Fill in optional fields if ConnSize_Analyzer is on. - orig_endp->Assign(2, new Val(pending->num_pkts, TYPE_COUNT)); - orig_endp->Assign(3, new Val(pending->num_bytes_ip, TYPE_COUNT)); - } - - resp_endp->Assign(0, new Val(0, TYPE_COUNT)); - resp_endp->Assign(1, new Val(resp_state, TYPE_COUNT)); - resp_endp->Assign(2, new Val(0, TYPE_COUNT)); - resp_endp->Assign(3, new Val(0, TYPE_COUNT)); - } - else - { - id_val->Assign(0, new AddrVal(DstAddr(pending))); - id_val->Assign(1, new PortVal(ntohs(DstPort(pending)), - TRANSPORT_TCP)); - id_val->Assign(2, new AddrVal(SrcAddr(pending))); - id_val->Assign(3, new PortVal(ntohs(SrcPort(pending)), - TRANSPORT_TCP)); - - orig_endp->Assign(0, new Val(0, TYPE_COUNT)); - orig_endp->Assign(1, new Val(resp_state, TYPE_COUNT)); - orig_endp->Assign(2, new Val(0, TYPE_COUNT)); - orig_endp->Assign(3, new Val(0, TYPE_COUNT)); - - resp_endp->Assign(0, new Val(orig_size, TYPE_COUNT)); - resp_endp->Assign(1, new Val(orig_state, TYPE_COUNT)); - - if ( ConnSize_Analyzer::Available() ) - { - // Fill in optional fields if ConnSize_Analyzer is on - resp_endp->Assign(2, new Val(pending->num_pkts, TYPE_COUNT)); - resp_endp->Assign(3, new Val(pending->num_bytes_ip, TYPE_COUNT)); - } - - DBG_LOG(DBG_COMPRESSOR, "%s swapped direction", fmt_conn_id(pending)); - } - - conn_val->Assign(0, id_val); - conn_val->Assign(1, orig_endp); - conn_val->Assign(2, resp_endp); - conn_val->Assign(3, new Val(pending->time, TYPE_TIME)); - conn_val->Assign(4, new Val(t > 0 ? t - pending->time : 0, - TYPE_INTERVAL)); // duration - conn_val->Assign(5, new TableVal(string_set)); // service - conn_val->Assign(6, new StringVal("cc=1")); // addl - conn_val->Assign(7, new Val(0, TYPE_COUNT)); // hot - conn_val->Assign(8, new StringVal("")); // history - - char tmp[20]; // uid. - conn_val->Assign(9, new StringVal(uitoa_n(pending->uid, tmp, sizeof(tmp), 62))); - - conn_val->SetOrigin(0); - } - - if ( event == conn_weird ) - { - // Special case to go through the logger. - const char* msg = arg->AsString()->CheckString(); - reporter->Weird(conn_val->Ref(), msg); - return; - } - - val_list* vl = new val_list; - if ( arg ) - vl->append(arg); - vl->append(conn_val->Ref()); - - mgr.QueueEvent(event, vl, SOURCE_LOCAL); - } - -void ConnCompressor::Drain() - { - IterCookie* cookie = conns.InitForIteration(); - ConnData* c; - - DoExpire(0); - - while ( (c = conns.NextEntry(cookie)) ) - { - Unref(conn_val); - conn_val = 0; - - if ( IsConnPtr(c) ) - { - Connection* tc = MakeConnPtr(c); - tc->Done(); - tc->Event(connection_state_remove, 0); - Unref(tc); - --sizes.connections; - } - - else - { - PendingConn* pc = MakePendingConnPtr(c); - if ( ! pc->invalid ) - { - // Same discussion for size here than - // in DoExpire(). - Event(pc, 0, connection_attempt, - TCP_ENDPOINT_INACTIVE, 0, - TCP_ENDPOINT_INACTIVE); - Event(pc, 0, connection_state_remove, - TCP_ENDPOINT_INACTIVE, 0, - TCP_ENDPOINT_INACTIVE); - - --sizes.pending_valid; - pc->invalid = 1; - } - } - } - } - -void ConnCompressor::Invalidate(HashKey* k) - { - ConnData* c = (ConnData*) conns.Lookup(k); - - assert(c && ! IsConnPtr(c)); - PendingConn* pc = MakePendingConnPtr(c); - - DBG_LOG(DBG_COMPRESSOR, "%s invalidate", fmt_conn_id(pc)); - - if ( ! pc->invalid ) - { - conns.Remove(&pc->key, sizeof(pc->key), pc->hash, true); - pc->invalid = 1; - --sizes.pending_valid; - } - } - -Connection* ConnCompressor::Insert(Connection* newconn) - { - HashKey* key = newconn->Key(); - ConnData* c = conns.Lookup(key); - Connection* old = 0; - - // Do we already have a Connection object? - if ( c ) - { - if ( IsConnPtr(c) ) - old = MakeConnPtr(c); - Remove(key); - } - - conns.Insert(key, MakeMapPtr(newconn)); - return old; - } - -bool ConnCompressor::Remove(HashKey* k) - { - ConnData* c = (ConnData*) conns.Lookup(k); - if ( ! c ) - return false; - - if ( IsConnPtr(c) ) - { - DBG_LOG(DBG_COMPRESSOR, "%s remove", fmt_conn_id(MakeConnPtr(c))); - conns.Remove(k); - --sizes.connections; - } - else - { - PendingConn* pc = MakePendingConnPtr(c); - DBG_LOG(DBG_COMPRESSOR, "%s remove", fmt_conn_id(pc)); - - conns.Remove(&pc->key, sizeof(pc->key), pc->hash, true); - - if ( ! pc->invalid ) - { - pc->invalid = 1; - --sizes.pending_valid; - } - } - - return true; - } diff --git a/src/ConnCompressor.h b/src/ConnCompressor.h deleted file mode 100644 index e2140526d0..0000000000 --- a/src/ConnCompressor.h +++ /dev/null @@ -1,237 +0,0 @@ -// $Id: ConnCompressor.h 6008 2008-07-23 00:24:22Z vern $ -// -// The ConnCompressor keeps track of the first packet seen for a conn_id using -// only a minimal amount of memory. This helps us to avoid instantiating -// full Connection objects for never-established sessions. -// -// TCP only. - -#ifndef CONNCOMPRESSOR_H -#define CONNCOMPRESSOR_H - -#include "Conn.h" -#include "Dict.h" -#include "NetVar.h" -#include "TCP.h" - -class ConnCompressor { -public: - ConnCompressor(); - ~ConnCompressor(); - - // Handle next packet. Returns 0 if packet in handled internally. - // Takes ownership of key. - Connection* NextPacket(double t, HashKey* k, const IP_Hdr* ip_hdr, - const struct pcap_pkthdr* hdr, const u_char* const pkt); - - // Look up a connection. Returns non-nil for connections for - // which a Connection object has already been instantiated. - Connection* Lookup(HashKey* k) - { - ConnData* c = conns.Lookup(k); - return c && IsConnPtr(c) ? MakeConnPtr(c) : 0; - } - - // Inserts connection into compressor. If another entry with this key - // already exists, it's replaced. If that was a full connection, it is - // also returned. - Connection* Insert(Connection* c); - - // Remove all state belonging to the given connection. Returns - // true if the connection was found in the compressor's table, - // false if not. - bool Remove(HashKey* k); - - // Flush state. - void Drain(); - - struct Sizes { - // Current number of already fully instantiated connections. - unsigned int connections; - - // Total number of fully instantiated connections. - unsigned int connections_total; - - // Current number of seen but non-yet instantiated connections. - unsigned int pending_valid; - - // Total number of seen but non-yet instantiated connections. - unsigned int pending_total; - - // Total number of all entries in pending list (some a which - // may already been invalid, but not yet removed from memory). - unsigned int pending_in_mem; - - // Total number of hash table entires - // (should equal connections + pending_valid) - unsigned int hash_table_size; - - // Total memory usage; - unsigned int memory; - }; - - const Sizes& Size() - { sizes.hash_table_size = conns.Length(); return sizes; } - - unsigned int MemoryAllocation() const { return sizes.memory; } - - // As long as we have only seen packets from one side, we just - // store a PendingConn. - struct PendingConn { - // True if the block is indeed a PendingConn (see below). - unsigned int is_pending:1; - - // Whether roles in key are flipped. - unsigned int ip1_is_src:1; - - unsigned int invalid:1; // deleted - int window_scale:4; - unsigned int SYN:1; - unsigned int FIN:1; - unsigned int RST:1; - unsigned int ACK:1; - - double time; - ConnID::Key key; - uint32 seq; - uint32 ack; - hash_t hash; - uint16 window; - uint64 uid; - - // The following are set if use_conn_size_analyzer is T. - uint16 num_pkts; - uint16 num_bytes_ip; - }; - -private: - // Helpers to extract addrs/ports from PendingConn. - - const uint32* SrcAddr(const PendingConn* c) - { return c->ip1_is_src ? c->key.ip1 : c->key.ip2; } - const uint32* DstAddr(const PendingConn* c) - { return c->ip1_is_src ? c->key.ip2 : c->key.ip1; } - - uint16 SrcPort(const PendingConn* c) - { return c->ip1_is_src ? c->key.port1 : c->key.port2; } - uint16 DstPort(const PendingConn* c) - { return c->ip1_is_src ? c->key.port2 : c->key.port1; } - - - // Called for the first packet in a connection. - Connection* FirstFromOrig(double t, HashKey* key, - const IP_Hdr* ip, const tcphdr* tp); - - // Called for more packets from the orginator w/o seeing a response. - Connection* NextFromOrig(PendingConn* pending, double t, HashKey* key, - const IP_Hdr* ip, const tcphdr* tp); - - // Called for the first response packet. Instantiates a Connection. - Connection* Response(PendingConn* pending, double t, HashKey* key, - const IP_Hdr* ip, const tcphdr* tp); - - // Instantiates a full TCP connection (invalidates pending connection). - Connection* Instantiate(HashKey* key, PendingConn* pending); - - // Same but based on packet. - Connection* Instantiate(double t, HashKey* key, const IP_Hdr* ip); - - // Fills the attributes of a PendingConn based on the given arguments. - void PktHdrToPendingConn(double time, const HashKey* key, - const IP_Hdr* ip, const struct tcphdr* tp, PendingConn* c); - - // Fakes a TCP packet based on the available information. - const IP_Hdr* PendingConnToPacket(const PendingConn* c); - - // Construct a TCP-flags byte. - uint8 MakeFlags(const PendingConn* c) const; - - // Allocate room for a new (Ext)PendingConn. - PendingConn* MakeNewState(double t); - - // Expire PendingConns. - void DoExpire(double t); - - // Remove all state belonging to the given connection. - void Invalidate(HashKey* k); - - // Sends the given connection_* event. If orig_state is - // TCP_ENDPOINT__INACTIVE, tries to guess a better one based - // on pending. If arg in non-nil, it will be used as the - // *first* argument of the event call (this is for conn_weird()). - void Event(const PendingConn* pending, double t, - const EventHandlerPtr& event, int orig_state, - int orig_size, int resp_state, Val* arg = 0); - - void Weird(const PendingConn* pending, double t, const char* msg) - { - // This will actually go through the Reporter; Event() takes - // care of that. - Event(pending, t, conn_weird, TCP_ENDPOINT_INACTIVE, 0, - TCP_ENDPOINT_INACTIVE, new StringVal(msg)); - } - - static const int BLOCK_SIZE = 16 * 1024; - - // The memory managment for PendConns. - struct Block { - double time; - Block* prev; - Block* next; - int bytes_used; - unsigned char data[BLOCK_SIZE]; - }; - - // In the connection hash table, we store pointers to both PendingConns - // and Connections. Thus, we need a way to differentiate between - // these two types. To avoid an additional indirection, we use a little - // hack: a pointer retrieved from the table is interpreted as a - // PendingConn first. However, if is_pending is false, it's in fact a - // Connection which starts at offset 4. The methods below help to - // implement this scheme transparently. An "operator new" in - // Connection takes care of building Connection's accordingly. - typedef PendingConn ConnData; - declare(PDict, ConnData); - typedef PDict(ConnData) ConnMap; - ConnMap conns; - - static ConnData* MakeMapPtr(PendingConn* c) - { assert(c->is_pending); return c; } - - static ConnData* MakeMapPtr(Connection* c) - { - ConnData* p = (ConnData*) (((char*) c) - 4); - assert(!p->is_pending); - return p; - } - - static PendingConn* MakePendingConnPtr(ConnData* c) - { assert(c->is_pending); return c; } - - static Connection* MakeConnPtr(ConnData* c) - { - assert(!c->is_pending); - return (Connection*) (((char*) c) + 4); - } - - static bool IsConnPtr(ConnData* c) - { return ! c->is_pending; } - - // New blocks are inserted at the end. - Block* first_block; - Block* last_block; - - // If we have already expired some entries in a block, - // this points to the first non-expired. - unsigned char* first_non_expired; - - // Last "connection" that we have build. - RecordVal* conn_val; - - // Statistics. - Sizes sizes; - }; - -extern ConnCompressor* conn_compressor; - -#endif diff --git a/src/ConnSizeAnalyzer.cc b/src/ConnSizeAnalyzer.cc index c98a9f6827..a1b892f4db 100644 --- a/src/ConnSizeAnalyzer.cc +++ b/src/ConnSizeAnalyzer.cc @@ -1,5 +1,3 @@ -// $Id$ -// // See the file "COPYING" in the main distribution directory for copyright. // // See ConnSize.h for more extensive comments. diff --git a/src/ConnSizeAnalyzer.h b/src/ConnSizeAnalyzer.h index 38446b0763..1fdd57bb15 100644 --- a/src/ConnSizeAnalyzer.h +++ b/src/ConnSizeAnalyzer.h @@ -1,5 +1,3 @@ -// $Id$ -// // See the file "COPYING" in the main distribution directory for copyright. // diff --git a/src/ContentLine.cc b/src/ContentLine.cc index e9f0856462..5601694e1d 100644 --- a/src/ContentLine.cc +++ b/src/ContentLine.cc @@ -1,5 +1,3 @@ -// $Id: ContentLine.cc,v 1.1.2.8 2006/06/01 01:55:42 sommer Exp $ - #include #include "ContentLine.h" diff --git a/src/ContentLine.h b/src/ContentLine.h index 25482ecc2f..5e9f01945f 100644 --- a/src/ContentLine.h +++ b/src/ContentLine.h @@ -1,5 +1,3 @@ -// $Id: ContentLine.h,v 1.1.2.9 2006/06/01 01:55:42 sommer Exp $ -// // Support-analyzer to split a reassembled stream into lines. #ifndef CONTENTLINE_H diff --git a/src/Continuation.h b/src/Continuation.h index bde07203a9..009d2a87f3 100644 --- a/src/Continuation.h +++ b/src/Continuation.h @@ -1,5 +1,3 @@ -// $Id: Continuation.h 2698 2006-04-03 05:50:52Z vern $ -// // Helper class to implement continuation-like mechanisms for // suspending/resuming tasks for incremental operation. // diff --git a/src/DCE_RPC.cc b/src/DCE_RPC.cc index 4e21ecd545..21cb3be9a0 100644 --- a/src/DCE_RPC.cc +++ b/src/DCE_RPC.cc @@ -1,5 +1,3 @@ -// $Id: DCE_RPC.cc 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -139,12 +137,12 @@ static bool is_mapped_dce_rpc_endpoint(const dce_rpc_endpoint_addr& addr) bool is_mapped_dce_rpc_endpoint(const ConnID* id, TransportProto proto) { -#ifdef BROv6 - if ( ! is_v4_addr(id->dst_addr) ) + if ( id->dst_addr.GetFamily() == IPv6 ) + // TODO: Does the protocol support v6 addresses? #773 return false; -#endif + dce_rpc_endpoint_addr addr; - addr.addr = ntohl(to_v4_addr(id->dst_addr)); + addr.addr = id->dst_addr; addr.port = ntohs(id->dst_port); addr.proto = proto; @@ -162,12 +160,7 @@ static void add_dce_rpc_endpoint(const dce_rpc_endpoint_addr& addr, // of the dce_rpc_endpoints table. // FIXME: Don't hard-code the timeout. - // Convert the address to a v4/v6 address (depending on how - // Bro was configured). This is all based on the address currently - // being a 32-bit host-order v4 address. - AddrVal a(htonl(addr.addr)); - const addr_type at = a.AsAddr(); - dpm->ExpectConnection(0, at, addr.port, addr.proto, + dpm->ExpectConnection(IPAddr(), addr.addr, addr.port, addr.proto, AnalyzerTag::DCE_RPC, 5 * 60, 0); } @@ -420,8 +413,8 @@ void DCE_RPC_Session::DeliverEpmapperMapResponse( break; case binpac::DCE_RPC_Simple::EPM_PROTOCOL_IP: - mapped.addr.addr = - floor->rhs()->data()->ip(); + uint32 hostip = floor->rhs()->data()->ip(); + mapped.addr.addr = IPAddr(IPv4, &hostip, IPAddr::Host); break; } } @@ -435,7 +428,7 @@ void DCE_RPC_Session::DeliverEpmapperMapResponse( vl->append(analyzer->BuildConnVal()); vl->append(new StringVal(mapped.uuid.to_string())); vl->append(new PortVal(mapped.addr.port, mapped.addr.proto)); - vl->append(new AddrVal(htonl(mapped.addr.addr))); + vl->append(new AddrVal(mapped.addr.addr)); analyzer->ConnectionEvent(epm_map_response, vl); } diff --git a/src/DCE_RPC.h b/src/DCE_RPC.h index a856599b19..acdbf1637d 100644 --- a/src/DCE_RPC.h +++ b/src/DCE_RPC.h @@ -1,5 +1,3 @@ -// $Id: DCE_RPC.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef dce_rpc_h @@ -10,6 +8,7 @@ #include "NetVar.h" #include "TCP.h" +#include "IPAddr.h" #include "dce_rpc_simple_pac.h" @@ -36,19 +35,19 @@ const char* uuid_to_string(const u_char* uuid_data); struct dce_rpc_endpoint_addr { // All fields are in host byteorder. - uint32 addr; + IPAddr addr; u_short port; TransportProto proto; dce_rpc_endpoint_addr() { - addr = 0; + addr = IPAddr(); port = 0; proto = TRANSPORT_UNKNOWN; } bool is_valid_addr() const - { return addr != 0 && port != 0 && proto != TRANSPORT_UNKNOWN; } + { return addr != IPAddr() && port != 0 && proto != TRANSPORT_UNKNOWN; } bool operator<(dce_rpc_endpoint_addr const &e) const { @@ -66,7 +65,7 @@ struct dce_rpc_endpoint_addr { { static char buf[128]; snprintf(buf, sizeof(buf), "%s/%d/%s", - dotted_addr(htonl(addr)), port, + addr.AsString().c_str(), port, proto == TRANSPORT_TCP ? "tcp" : (proto == TRANSPORT_UDP ? "udp" : "?")); diff --git a/src/DFA.cc b/src/DFA.cc index 43e719f24a..e58ea260e5 100644 --- a/src/DFA.cc +++ b/src/DFA.cc @@ -1,5 +1,3 @@ -// $Id: DFA.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/DFA.h b/src/DFA.h index 6fa4d85f0d..0f6c7d2f25 100644 --- a/src/DFA.h +++ b/src/DFA.h @@ -1,5 +1,3 @@ -// $Id: DFA.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. diff --git a/src/DHCP-binpac.cc b/src/DHCP-binpac.cc index 23149b7837..2aec6e6e9f 100644 --- a/src/DHCP-binpac.cc +++ b/src/DHCP-binpac.cc @@ -1,5 +1,3 @@ -// $Id:$ - #include "DHCP-binpac.h" DHCP_Analyzer_binpac::DHCP_Analyzer_binpac(Connection* conn) diff --git a/src/DHCP-binpac.h b/src/DHCP-binpac.h index d0e93dcfc2..06ddff3bb6 100644 --- a/src/DHCP-binpac.h +++ b/src/DHCP-binpac.h @@ -1,5 +1,3 @@ -// $Id:$ - #ifndef dhcp_binpac_h #define dhcp_binpac_h diff --git a/src/DNS-binpac.cc b/src/DNS-binpac.cc index e06ef1ab19..eb95ac2e1c 100644 --- a/src/DNS-binpac.cc +++ b/src/DNS-binpac.cc @@ -1,5 +1,3 @@ -// $Id:$ - #include "DNS-binpac.h" #include "TCP_Reassembler.h" diff --git a/src/DNS-binpac.h b/src/DNS-binpac.h index b43e3b6aae..9e8cb16f69 100644 --- a/src/DNS-binpac.h +++ b/src/DNS-binpac.h @@ -1,5 +1,3 @@ -// $Id:$ - #ifndef dns_binpac_h #define dns_binpac_h diff --git a/src/DNS.cc b/src/DNS.cc index d13f184ca5..a3b0b62ef3 100644 --- a/src/DNS.cc +++ b/src/DNS.cc @@ -1,5 +1,3 @@ -// $Id: DNS.cc 6885 2009-08-20 04:37:55Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -46,6 +44,7 @@ int DNS_Interpreter::ParseMessage(const u_char* data, int len, int is_query) // This should weed out most of it. if ( dns_max_queries > 0 && msg.qdcount > dns_max_queries ) { + analyzer->ProtocolViolation("DNS_Conn_count_too_large"); analyzer->Weird("DNS_Conn_count_too_large"); EndMessage(&msg); return 0; @@ -69,6 +68,8 @@ int DNS_Interpreter::ParseMessage(const u_char* data, int len, int is_query) return 0; } + analyzer->ProtocolConfirmation(); + AddrVal server(analyzer->Conn()->RespAddr()); int skip_auth = dns_skip_all_auth; @@ -757,62 +758,37 @@ int DNS_Interpreter::ParseRR_A(DNS_MsgInfo* msg, int DNS_Interpreter::ParseRR_AAAA(DNS_MsgInfo* msg, const u_char*& data, int& len, int rdlength) { - // We need to parse an IPv6 address, high-order byte first. - // ### Currently, we fake an A reply rather than an AAAA reply, - // since for the latter we won't be able to express the full - // address (unless Bro was compiled for IPv6 addresses). We do - // this fake by using just the bottom 4 bytes of the IPv6 address. uint32 addr[4]; - int i; - for ( i = 0; i < 4; ++i ) + for ( int i = 0; i < 4; ++i ) { - addr[i] = ntohl(ExtractLong(data, len)); + addr[i] = htonl(ExtractLong(data, len)); if ( len < 0 ) { - analyzer->Weird("DNS_AAAA_neg_length"); + if ( msg->atype == TYPE_AAAA ) + analyzer->Weird("DNS_AAAA_neg_length"); + else + analyzer->Weird("DNS_A6_neg_length"); return 0; } } - // Currently, dns_AAAA_reply is treated like dns_A_reply, since - // IPv6 addresses are not generally processed. This needs to be - // fixed. ### - if ( dns_A_reply && ! msg->skip_event ) + EventHandlerPtr event; + if ( msg->atype == TYPE_AAAA ) + event = dns_AAAA_reply; + else + event = dns_A6_reply; + if ( event && ! msg->skip_event ) { val_list* vl = new val_list; vl->append(analyzer->BuildConnVal()); vl->append(msg->BuildHdrVal()); vl->append(msg->BuildAnswerVal()); - vl->append(new AddrVal(htonl(addr[3]))); - - analyzer->ConnectionEvent(dns_A_reply, vl); - } - -#if 0 -alternative AAAA code from Chris - if ( dns_AAAA_reply && ! msg->skip_event ) - { - val_list* vl = new val_list; - - vl->append(analyzer->BuildConnVal()); - vl->append(msg->BuildHdrVal()); - vl->append(msg->BuildAnswerVal()); -#ifdef BROv6 - // FIXME: might need to htonl the addr first vl->append(new AddrVal(addr)); -#else - vl->append(new AddrVal((uint32)0x0000)); -#endif - char addrstr[INET6_ADDRSTRLEN]; - inet_ntop(AF_INET6, addr, addrstr, INET6_ADDRSTRLEN); - vl->append(new StringVal(addrstr)); - - analyzer->ConnectionEvent(dns_AAAA_reply, vl); + analyzer->ConnectionEvent(event, vl); } -#endif return 1; } diff --git a/src/DNS.h b/src/DNS.h index ca9261c008..83ca80911e 100644 --- a/src/DNS.h +++ b/src/DNS.h @@ -1,5 +1,3 @@ -// $Id: DNS.h 6885 2009-08-20 04:37:55Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef dns_h diff --git a/src/DNS_Mgr.cc b/src/DNS_Mgr.cc index 87d0db4dac..9e65d3c9a9 100644 --- a/src/DNS_Mgr.cc +++ b/src/DNS_Mgr.cc @@ -1,5 +1,3 @@ -// $Id: DNS_Mgr.cc 7073 2010-09-13 00:45:02Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -48,13 +46,13 @@ extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); class DNS_Mgr_Request { public: - DNS_Mgr_Request(const char* h) { host = copy_string(h); addr = 0; } - DNS_Mgr_Request(uint32 a) { addr = a; host = 0; } + DNS_Mgr_Request(const char* h, int af) { host = copy_string(h); fam = af; } + DNS_Mgr_Request(const IPAddr& a) { addr = a; host = 0; fam = 0; } ~DNS_Mgr_Request() { delete [] host; } // Returns nil if this was an address request. const char* ReqHost() const { return host; } - uint32 ReqAddr() const { return addr; } + const IPAddr& ReqAddr() const { return addr; } int MakeRequest(nb_dns_info* nb_dns); int RequestPending() const { return request_pending; } @@ -63,8 +61,8 @@ public: protected: char* host; // if non-nil, this is a host request - uint32 addr; - uint32 ttl; + int fam; // address family query type for host requests + IPAddr addr; int request_pending; }; @@ -77,15 +75,20 @@ int DNS_Mgr_Request::MakeRequest(nb_dns_info* nb_dns) char err[NB_DNS_ERRSIZE]; if ( host ) - return nb_dns_host_request(nb_dns, host, (void*) this, err) >= 0; + return nb_dns_host_request2(nb_dns, host, fam, (void*) this, err) >= 0; else - return nb_dns_addr_request(nb_dns, addr, (void*) this, err) >= 0; + { + const uint32* bytes; + int len = addr.GetBytes(&bytes); + return nb_dns_addr_request2(nb_dns, (char*) bytes, + len == 1 ? AF_INET : AF_INET6, (void*) this, err) >= 0; + } } class DNS_Mapping { public: DNS_Mapping(const char* host, struct hostent* h, uint32 ttl); - DNS_Mapping(uint32 addr, struct hostent* h, uint32 ttl); + DNS_Mapping(const IPAddr& addr, struct hostent* h, uint32 ttl); DNS_Mapping(FILE* f); int NoMapping() const { return no_mapping; } @@ -95,9 +98,11 @@ public: // Returns nil if this was an address request. const char* ReqHost() const { return req_host; } - uint32 ReqAddr() const { return req_addr; } - const char* ReqStr() const - { return req_host ? req_host : dotted_addr(ReqAddr()); } + IPAddr ReqAddr() const { return req_addr; } + string ReqStr() const + { + return req_host ? req_host : req_addr; + } ListVal* Addrs(); TableVal* AddrsSet(); // addresses returned as a set @@ -111,7 +116,14 @@ public: int Valid() const { return ! failed; } bool Expired() const - { return current_time() > (creation_time + req_ttl); } + { + if ( req_host && num_addrs == 0) + return false; // nothing to expire + + return current_time() > (creation_time + req_ttl); + } + + int Type() const { return map_type; } protected: friend class DNS_Mgr; @@ -123,7 +135,7 @@ protected: int init_failed; char* req_host; - uint32 req_addr; + IPAddr req_addr; uint32 req_ttl; int num_names; @@ -131,11 +143,12 @@ protected: StringVal* host_val; int num_addrs; - uint32* addrs; + IPAddr* addrs; ListVal* addrs_val; int failed; double creation_time; + int map_type; }; void DNS_Mgr_mapping_delete_func(void* v) @@ -156,14 +169,13 @@ DNS_Mapping::DNS_Mapping(const char* host, struct hostent* h, uint32 ttl) { Init(h); req_host = copy_string(host); - req_addr = 0; req_ttl = ttl; if ( names && ! names[0] ) names[0] = copy_string(host); } -DNS_Mapping::DNS_Mapping(uint32 addr, struct hostent* h, uint32 ttl) +DNS_Mapping::DNS_Mapping(const IPAddr& addr, struct hostent* h, uint32 ttl) { Init(h); req_addr = addr; @@ -177,7 +189,6 @@ DNS_Mapping::DNS_Mapping(FILE* f) init_failed = 1; req_host = 0; - req_addr = 0; char buf[512]; @@ -190,14 +201,15 @@ DNS_Mapping::DNS_Mapping(FILE* f) char req_buf[512+1], name_buf[512+1]; int is_req_host; - if ( sscanf(buf, "%lf %d %512s %d %512s %d", &creation_time, &is_req_host, - req_buf, &failed, name_buf, &num_addrs) != 6 ) + if ( sscanf(buf, "%lf %d %512s %d %512s %d %d %"PRIu32, &creation_time, + &is_req_host, req_buf, &failed, name_buf, &map_type, &num_addrs, + &req_ttl) != 8 ) return; if ( is_req_host ) req_host = copy_string(req_buf); else - req_addr = dotted_to_addr(req_buf); + req_addr = IPAddr(req_buf); num_names = 1; names = new char*[num_names]; @@ -205,7 +217,7 @@ DNS_Mapping::DNS_Mapping(FILE* f) if ( num_addrs > 0 ) { - addrs = new uint32[num_addrs]; + addrs = new IPAddr[num_addrs]; for ( int i = 0; i < num_addrs; ++i ) { @@ -219,7 +231,7 @@ DNS_Mapping::DNS_Mapping(FILE* f) if ( newline ) *newline = '\0'; - addrs[i] = dotted_to_addr(buf); + addrs[i] = IPAddr(buf); } } else @@ -282,14 +294,6 @@ StringVal* DNS_Mapping::Host() return host_val; } -// Converts an array of 4 bytes in network order to the corresponding -// 32-bit network long. -static uint32 raw_bytes_to_addr(const unsigned char b[4]) - { - uint32 l = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3]; - return uint32(htonl(l)); - } - void DNS_Mapping::Init(struct hostent* h) { no_mapping = 0; @@ -298,12 +302,13 @@ void DNS_Mapping::Init(struct hostent* h) host_val = 0; addrs_val = 0; - if ( ! h || h->h_addrtype != AF_INET || h->h_length != 4 ) + if ( ! h ) { Clear(); return; } + map_type = h->h_addrtype; num_names = 1; // for now, just use official name names = new char*[num_names]; names[0] = h->h_name ? copy_string(h->h_name) : 0; @@ -313,10 +318,14 @@ void DNS_Mapping::Init(struct hostent* h) if ( num_addrs > 0 ) { - addrs = new uint32[num_addrs]; + addrs = new IPAddr[num_addrs]; for ( int i = 0; i < num_addrs; ++i ) - addrs[i] = raw_bytes_to_addr( - (unsigned char*)h->h_addr_list[i]); + if ( h->h_addrtype == AF_INET ) + addrs[i] = IPAddr(IPv4, (uint32*)h->h_addr_list[i], + IPAddr::Network); + else if ( h->h_addrtype == AF_INET6 ) + addrs[i] = IPAddr(IPv6, (uint32*)h->h_addr_list[i], + IPAddr::Network); } else addrs = 0; @@ -332,18 +341,19 @@ void DNS_Mapping::Clear() host_val = 0; addrs_val = 0; no_mapping = 0; + map_type = 0; failed = 1; } void DNS_Mapping::Save(FILE* f) const { - fprintf(f, "%.0f %d %s %d %s %d\n", creation_time, req_host != 0, - req_host ? req_host : dotted_addr(req_addr), + fprintf(f, "%.0f %d %s %d %s %d %d %"PRIu32"\n", creation_time, req_host != 0, + req_host ? req_host : req_addr.AsString().c_str(), failed, (names && names[0]) ? names[0] : "*", - num_addrs); + map_type, num_addrs, req_ttl); for ( int i = 0; i < num_addrs; ++i ) - fprintf(f, "%s\n", dotted_addr(addrs[i])); + fprintf(f, "%s\n", addrs[i].AsString().c_str()); } @@ -353,9 +363,6 @@ DNS_Mgr::DNS_Mgr(DNS_MgrMode arg_mode) mode = arg_mode; - host_mappings.SetDeleteFunc(DNS_Mgr_mapping_delete_func); - addr_mappings.SetDeleteFunc(DNS_Mgr_mapping_delete_func); - char err[NB_DNS_ERRSIZE]; nb_dns = nb_dns_init(err); @@ -372,6 +379,9 @@ DNS_Mgr::DNS_Mgr(DNS_MgrMode arg_mode) cache_name = dir = 0; asyncs_pending = 0; + num_requests = 0; + successful = 0; + failed = 0; } DNS_Mgr::~DNS_Mgr() @@ -439,24 +449,34 @@ TableVal* DNS_Mgr::LookupHost(const char* name) if ( mode != DNS_PRIME ) { - DNS_Mapping* d = host_mappings.Lookup(name); + HostMap::iterator it = host_mappings.find(name); - if ( d ) + if ( it != host_mappings.end() ) { - if ( d->Valid() ) - return d->Addrs()->ConvertToSet(); - else + DNS_Mapping* d4 = it->second.first; + DNS_Mapping* d6 = it->second.second; + + if ( (d4 && d4->Failed()) || (d6 && d6->Failed()) ) { reporter->Warning("no such host: %s", name); return empty_addr_set(); } + else if ( d4 && d6 ) + { + TableVal* tv4 = d4->AddrsSet(); + TableVal* tv6 = d6->AddrsSet(); + tv4->AddTo(tv6, false); + Unref(tv4); + return tv6; + } } } // Not found, or priming. switch ( mode ) { case DNS_PRIME: - requests.append(new DNS_Mgr_Request(name)); + requests.append(new DNS_Mgr_Request(name, AF_INET)); + requests.append(new DNS_Mgr_Request(name, AF_INET6)); return empty_addr_set(); case DNS_FORCE: @@ -464,7 +484,8 @@ TableVal* DNS_Mgr::LookupHost(const char* name) return 0; case DNS_DEFAULT: - requests.append(new DNS_Mgr_Request(name)); + requests.append(new DNS_Mgr_Request(name, AF_INET)); + requests.append(new DNS_Mgr_Request(name, AF_INET6)); Resolve(); return LookupHost(name); @@ -474,24 +495,25 @@ TableVal* DNS_Mgr::LookupHost(const char* name) } } -Val* DNS_Mgr::LookupAddr(uint32 addr) +Val* DNS_Mgr::LookupAddr(const IPAddr& addr) { if ( ! did_init ) Init(); if ( mode != DNS_PRIME ) { - HashKey h(&addr, 1); - DNS_Mapping* d = addr_mappings.Lookup(&h); + AddrMap::iterator it = addr_mappings.find(addr); - if ( d ) + if ( it != addr_mappings.end() ) { + DNS_Mapping* d = it->second; if ( d->Valid() ) return d->Host(); else { - reporter->Warning("can't resolve IP address: %s", dotted_addr(addr)); - return new StringVal(dotted_addr(addr)); + string s(addr); + reporter->Warning("can't resolve IP address: %s", s.c_str()); + return new StringVal(s.c_str()); } } } @@ -504,7 +526,7 @@ Val* DNS_Mgr::LookupAddr(uint32 addr) case DNS_FORCE: reporter->FatalError("can't find DNS entry for %s in cache", - dotted_addr(addr)); + addr.AsString().c_str()); return 0; case DNS_DEFAULT: @@ -680,28 +702,53 @@ void DNS_Mgr::AddResult(DNS_Mgr_Request* dr, struct nb_dns_result* r) if ( dr->ReqHost() ) { new_dm = new DNS_Mapping(dr->ReqHost(), h, ttl); - prev_dm = host_mappings.Insert(dr->ReqHost(), new_dm); + prev_dm = 0; + + HostMap::iterator it = host_mappings.find(dr->ReqHost()); + if ( it == host_mappings.end() ) + { + host_mappings[dr->ReqHost()].first = + new_dm->Type() == AF_INET ? new_dm : 0; + host_mappings[dr->ReqHost()].second = + new_dm->Type() == AF_INET ? 0 : new_dm; + } + + else + { + if ( new_dm->Type() == AF_INET ) + { + prev_dm = it->second.first; + it->second.first = new_dm; + } + else + { + prev_dm = it->second.second; + it->second.second = new_dm; + } + } if ( new_dm->Failed() && prev_dm && prev_dm->Valid() ) { // Put previous, valid entry back - CompareMappings // will generate a corresponding warning. - (void) host_mappings.Insert(dr->ReqHost(), prev_dm); + if ( prev_dm->Type() == AF_INET ) + host_mappings[dr->ReqHost()].first = prev_dm; + else + host_mappings[dr->ReqHost()].second = prev_dm; + ++keep_prev; } } else { new_dm = new DNS_Mapping(dr->ReqAddr(), h, ttl); - uint32 tmp_addr = dr->ReqAddr(); - HashKey k(&tmp_addr, 1); - prev_dm = addr_mappings.Insert(&k, new_dm); + AddrMap::iterator it = addr_mappings.find(dr->ReqAddr()); + prev_dm = (it == addr_mappings.end()) ? 0 : it->second; + addr_mappings[dr->ReqAddr()] = new_dm; if ( new_dm->Failed() && prev_dm && prev_dm->Valid() ) { - uint32 tmp_addr = dr->ReqAddr(); - HashKey k2(&tmp_addr, 1); - (void) addr_mappings.Insert(&k2, prev_dm); + addr_mappings[dr->ReqAddr()] = prev_dm; ++keep_prev; } } @@ -773,17 +820,13 @@ ListVal* DNS_Mgr::AddrListDelta(ListVal* al1, ListVal* al2) for ( int i = 0; i < al1->Length(); ++i ) { - addr_type al1_i = al1->Index(i)->AsAddr(); + const IPAddr& al1_i = al1->Index(i)->AsAddr(); int j; for ( j = 0; j < al2->Length(); ++j ) { - addr_type al2_j = al2->Index(j)->AsAddr(); -#ifdef BROv6 - if ( addr_eq(al1_i, al2_j) ) -#else + const IPAddr& al2_j = al2->Index(j)->AsAddr(); if ( al1_i == al2_j ) -#endif break; } @@ -799,8 +842,8 @@ void DNS_Mgr::DumpAddrList(FILE* f, ListVal* al) { for ( int i = 0; i < al->Length(); ++i ) { - addr_type al_i = al->Index(i)->AsAddr(); - fprintf(f, "%s%s", i > 0 ? "," : "", dotted_addr(al_i)); + const IPAddr& al_i = al->Index(i)->AsAddr(); + fprintf(f, "%s%s", i > 0 ? "," : "", al_i.AsString().c_str()); } } @@ -813,12 +856,20 @@ void DNS_Mgr::LoadCache(FILE* f) for ( ; ! m->NoMapping() && ! m->InitFailed(); m = new DNS_Mapping(f) ) { if ( m->ReqHost() ) - host_mappings.Insert(m->ReqHost(), m); + { + if ( host_mappings.find(m->ReqHost()) == host_mappings.end() ) + { + host_mappings[m->ReqHost()].first = 0; + host_mappings[m->ReqHost()].second = 0; + } + if ( m->Type() == AF_INET ) + host_mappings[m->ReqHost()].first = m; + else + host_mappings[m->ReqHost()].second = m; + } else { - uint32 tmp_addr = m->ReqAddr(); - HashKey h(&tmp_addr, 1); - addr_mappings.Insert(&h, m); + addr_mappings[m->ReqAddr()] = m; } } @@ -829,26 +880,42 @@ void DNS_Mgr::LoadCache(FILE* f) fclose(f); } -void DNS_Mgr::Save(FILE* f, PDict(DNS_Mapping)& m) +void DNS_Mgr::Save(FILE* f, const AddrMap& m) { - IterCookie* cookie = m.InitForIteration(); - DNS_Mapping* dm; - - while ( (dm = m.NextEntry(cookie)) ) - dm->Save(f); + for ( AddrMap::const_iterator it = m.begin(); it != m.end(); ++it ) + { + if ( it->second ) + it->second->Save(f); + } } -const char* DNS_Mgr::LookupAddrInCache(dns_mgr_addr_type addr) +void DNS_Mgr::Save(FILE* f, const HostMap& m) { - HashKey h(&addr, 1); - DNS_Mapping* d = dns_mgr->addr_mappings.Lookup(&h); + HostMap::const_iterator it; - if ( ! d ) + for ( it = m.begin(); it != m.end(); ++it ) + { + if ( it->second.first ) + it->second.first->Save(f); + + if ( it->second.second ) + it->second.second->Save(f); + } + } + +const char* DNS_Mgr::LookupAddrInCache(const IPAddr& addr) + { + AddrMap::iterator it = dns_mgr->addr_mappings.find(addr); + + if ( it == addr_mappings.end() ) return 0; + DNS_Mapping* d = it->second; + if ( d->Expired() ) { - dns_mgr->addr_mappings.Remove(&h); + dns_mgr->addr_mappings.erase(it); + delete d; return 0; } @@ -859,22 +926,32 @@ const char* DNS_Mgr::LookupAddrInCache(dns_mgr_addr_type addr) TableVal* DNS_Mgr::LookupNameInCache(string name) { - DNS_Mapping* d = dns_mgr->host_mappings.Lookup(name.c_str()); - - if ( ! d || ! d->names ) + HostMap::iterator it = dns_mgr->host_mappings.find(name); + if ( it == dns_mgr->host_mappings.end() ) return 0; - if ( d->Expired() ) + DNS_Mapping* d4 = it->second.first; + DNS_Mapping* d6 = it->second.second; + + if ( ! d4 || ! d4->names || ! d6 || ! d6->names ) + return 0; + + if ( d4->Expired() || d6->Expired() ) { - HashKey h(name.c_str()); - dns_mgr->host_mappings.Remove(&h); + dns_mgr->host_mappings.erase(it); + delete d4; + delete d6; return 0; } - return d->AddrsSet(); + TableVal* tv4 = d4->AddrsSet(); + TableVal* tv6 = d6->AddrsSet(); + tv4->AddTo(tv6, false); + Unref(tv4); + return tv6; } -void DNS_Mgr::AsyncLookupAddr(dns_mgr_addr_type host, LookupCallback* callback) +void DNS_Mgr::AsyncLookupAddr(const IPAddr& host, LookupCallback* callback) { if ( ! did_init ) Init(); @@ -950,15 +1027,31 @@ void DNS_Mgr::IssueAsyncRequests() AsyncRequest* req = asyncs_queued.front(); asyncs_queued.pop_front(); + ++num_requests; + DNS_Mgr_Request* dr; + DNS_Mgr_Request* dr6 = 0; + if ( req->IsAddrReq() ) dr = new DNS_Mgr_Request(req->host); else - dr = new DNS_Mgr_Request(req->name.c_str()); + { + dr = new DNS_Mgr_Request(req->name.c_str(), AF_INET); + dr6 = new DNS_Mgr_Request(req->name.c_str(), AF_INET6); + } if ( ! dr->MakeRequest(nb_dns) ) { reporter->Warning("can't issue DNS request"); + ++failed; + req->Timeout(); + continue; + } + + if ( dr6 && ! dr6->MakeRequest(nb_dns) ) + { + reporter->Warning("can't issue DNS request"); + ++failed; req->Timeout(); continue; } @@ -981,7 +1074,7 @@ double DNS_Mgr::NextTimestamp(double* network_time) return asyncs_timeouts.size() ? timer_mgr->Time() : -1.0; } -void DNS_Mgr::CheckAsyncAddrRequest(dns_mgr_addr_type addr, bool timeout) +void DNS_Mgr::CheckAsyncAddrRequest(const IPAddr& addr, bool timeout) { // Note that this code is a mirror of that for CheckAsyncHostRequest. @@ -993,10 +1086,16 @@ void DNS_Mgr::CheckAsyncAddrRequest(dns_mgr_addr_type addr, bool timeout) { const char* name = LookupAddrInCache(addr); if ( name ) + { + ++successful; i->second->Resolved(name); + } else if ( timeout ) + { + ++failed; i->second->Timeout(); + } else return; @@ -1022,12 +1121,16 @@ void DNS_Mgr::CheckAsyncHostRequest(const char* host, bool timeout) if ( addrs ) { + ++successful; i->second->Resolved(addrs); Unref(addrs); } else if ( timeout ) + { + ++failed; i->second->Timeout(); + } else return; @@ -1040,14 +1143,36 @@ void DNS_Mgr::CheckAsyncHostRequest(const char* host, bool timeout) } } -void DNS_Mgr::Process() +void DNS_Mgr::Flush() { + DoProcess(false); + HostMap::iterator it; + for ( it = host_mappings.begin(); it != host_mappings.end(); ++it ) + { + delete it->second.first; + delete it->second.second; + } + + for ( AddrMap::iterator it2 = addr_mappings.begin(); it2 != addr_mappings.end(); ++it2 ) + delete it2->second; + + host_mappings.clear(); + addr_mappings.clear(); + } + +void DNS_Mgr::Process() + { + DoProcess(false); + } + +void DNS_Mgr::DoProcess(bool flush) + { while ( asyncs_timeouts.size() > 0 ) { AsyncRequest* req = asyncs_timeouts.top(); - if ( req->time + DNS_TIMEOUT > current_time() ) + if ( req->time + DNS_TIMEOUT > current_time() || flush ) break; if ( req->IsAddrReq() ) @@ -1076,6 +1201,14 @@ void DNS_Mgr::Process() else if ( status > 0 ) { DNS_Mgr_Request* dr = (DNS_Mgr_Request*) r.cookie; + + bool do_host_timeout = true; + if ( dr->ReqHost() && + host_mappings.find(dr->ReqHost()) == host_mappings.end() ) + // Don't timeout when this is the first result in an expected pair + // (one result each for A and AAAA queries). + do_host_timeout = false; + if ( dr->RequestPending() ) { AddResult(dr, &r); @@ -1085,9 +1218,11 @@ void DNS_Mgr::Process() if ( ! dr->ReqHost() ) CheckAsyncAddrRequest(dr->ReqAddr(), true); else - CheckAsyncHostRequest(dr->ReqHost(), true); + CheckAsyncHostRequest(dr->ReqHost(), do_host_timeout); IssueAsyncRequests(); + + delete dr; } } @@ -1127,3 +1262,14 @@ int DNS_Mgr::AnswerAvailable(int timeout) return status; } + +void DNS_Mgr::GetStats(Stats* stats) + { + stats->requests = num_requests; + stats->successful = successful; + stats->failed = failed; + stats->pending = asyncs_pending; + stats->cached_hosts = host_mappings.size(); + stats->cached_addresses = addr_mappings.size(); + } + diff --git a/src/DNS_Mgr.h b/src/DNS_Mgr.h index 151c05289f..7983a91573 100644 --- a/src/DNS_Mgr.h +++ b/src/DNS_Mgr.h @@ -1,6 +1,4 @@ -// $Id: DNS_Mgr.h 6915 2009-09-22 05:04:17Z vern $ -// -// See the file "COPYING" in the main distribution directory for copyright. + // See the file "COPYING" in the main distribution directory for copyright. #ifndef dnsmgr_h #define dnsmgr_h @@ -8,12 +6,14 @@ #include #include #include +#include #include "util.h" #include "BroList.h" #include "Dict.h" #include "EventHandler.h" #include "IOSource.h" +#include "IPAddr.h" class Val; class ListVal; @@ -29,7 +29,6 @@ struct nb_dns_result; declare(PDict,ListVal); class DNS_Mapping; -declare(PDict,DNS_Mapping); enum DNS_MgrMode { DNS_PRIME, // used to prime the cache @@ -41,22 +40,19 @@ enum DNS_MgrMode { // Number of seconds we'll wait for a reply. #define DNS_TIMEOUT 5 -// ### For now, we don't support IPv6 lookups. When we do, this -// should become addr_type. -typedef uint32 dns_mgr_addr_type; - class DNS_Mgr : public IOSource { public: DNS_Mgr(DNS_MgrMode mode); virtual ~DNS_Mgr(); bool Init(); + void Flush(); // Looks up the address or addresses of the given host, and returns // a set of addr. TableVal* LookupHost(const char* host); - Val* LookupAddr(uint32 addr); + Val* LookupAddr(const IPAddr& addr); // Define the directory where to store the data. void SetDir(const char* arg_dir) { dir = copy_string(arg_dir); } @@ -65,7 +61,7 @@ public: void Resolve(); int Save(); - const char* LookupAddrInCache(dns_mgr_addr_type addr); + const char* LookupAddrInCache(const IPAddr& addr); TableVal* LookupNameInCache(string name); // Support for async lookups. @@ -79,9 +75,20 @@ public: virtual void Timeout() = 0; }; - void AsyncLookupAddr(dns_mgr_addr_type host, LookupCallback* callback); + void AsyncLookupAddr(const IPAddr& host, LookupCallback* callback); void AsyncLookupName(string name, LookupCallback* callback); + struct Stats { + unsigned long requests; // These count only async requests. + unsigned long successful; + unsigned long failed; + unsigned long pending; + unsigned long cached_hosts; + unsigned long cached_addresses; + }; + + void GetStats(Stats* stats); + protected: friend class LookupCallback; friend class DNS_Mgr_Request; @@ -97,8 +104,11 @@ protected: ListVal* AddrListDelta(ListVal* al1, ListVal* al2); void DumpAddrList(FILE* f, ListVal* al); + typedef map > HostMap; + typedef map AddrMap; void LoadCache(FILE* f); - void Save(FILE* f, PDict(DNS_Mapping)& m); + void Save(FILE* f, const AddrMap& m); + void Save(FILE* f, const HostMap& m); // Selects on the fd to see if there is an answer available (timeout // is secs). Returns 0 on timeout, -1 on EINTR or other error, and 1 @@ -110,9 +120,12 @@ protected: // Finish the request if we have a result. If not, time it out if // requested. - void CheckAsyncAddrRequest(dns_mgr_addr_type addr, bool timeout); + void CheckAsyncAddrRequest(const IPAddr& addr, bool timeout); void CheckAsyncHostRequest(const char* host, bool timeout); + // Process outstanding requests. + void DoProcess(bool flush); + // IOSource interface. virtual void GetFds(int* read, int* write, int* except); virtual double NextTimestamp(double* network_time); @@ -123,8 +136,8 @@ protected: PDict(ListVal) services; - PDict(DNS_Mapping) host_mappings; - PDict(DNS_Mapping) addr_mappings; + HostMap host_mappings; + AddrMap addr_mappings; DNS_mgr_request_list requests; @@ -150,7 +163,7 @@ protected: struct AsyncRequest { double time; - dns_mgr_addr_type host; + IPAddr host; string name; CallbackList callbacks; @@ -191,7 +204,7 @@ protected: }; - typedef map AsyncRequestAddrMap; + typedef map AsyncRequestAddrMap; AsyncRequestAddrMap asyncs_addrs; typedef map AsyncRequestNameMap; @@ -204,6 +217,10 @@ protected: TimeoutQueue asyncs_timeouts; int asyncs_pending; + + unsigned long num_requests; + unsigned long successful; + unsigned long failed; }; extern DNS_Mgr* dns_mgr; diff --git a/src/DPM.cc b/src/DPM.cc index 69b859a9e1..d7e5cd25ef 100644 --- a/src/DPM.cc +++ b/src/DPM.cc @@ -1,5 +1,3 @@ -// $Id: DPM.cc,v 1.1.4.14 2006/06/01 17:18:10 sommer Exp $ - #include "DPM.h" #include "PIA.h" #include "Hash.h" @@ -13,53 +11,28 @@ #include "ConnSizeAnalyzer.h" -ExpectedConn::ExpectedConn(const uint32* _orig, const uint32* _resp, +ExpectedConn::ExpectedConn(const IPAddr& _orig, const IPAddr& _resp, uint16 _resp_p, uint16 _proto) { - if ( orig ) - copy_addr(_orig, orig); + if ( _orig == IPAddr(string("0.0.0.0")) ) + // don't use the IPv4 mapping, use the literal unspecified address + // to indicate a wildcard + orig = IPAddr(string("::")); else - { - for ( int i = 0; i < NUM_ADDR_WORDS; ++i ) - orig[i] = 0; - } - - copy_addr(_resp, resp); - - resp_p = _resp_p; - proto = _proto; - } - -ExpectedConn::ExpectedConn(uint32 _orig, uint32 _resp, - uint16 _resp_p, uint16 _proto) - { -#ifdef BROv6 - // Use the IPv4-within-IPv6 convention, as this is what's - // needed when we mix uint32's (like in this construction) - // with addr_type's (for example, when looking up expected - // connections). - - orig[0] = orig[1] = orig[2] = 0; - resp[0] = resp[1] = resp[2] = 0; - orig[3] = _orig; - resp[3] = _resp; -#else - orig[0] = _orig; - resp[0] = _resp; -#endif + orig = _orig; + resp = _resp; resp_p = _resp_p; proto = _proto; } ExpectedConn::ExpectedConn(const ExpectedConn& c) { - copy_addr(c.orig, orig); - copy_addr(c.resp, resp); + orig = c.orig; + resp = c.resp; resp_p = c.resp_p; proto = c.proto; } - DPM::DPM() : expected_conns_queue(AssignedAnalyzer::compare) { @@ -101,7 +74,7 @@ void DPM::PostScriptInit() void DPM::AddConfig(const Analyzer::Config& cfg) { -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG HeapLeakChecker::Disabler disabler; #endif @@ -160,23 +133,18 @@ AnalyzerTag::Tag DPM::GetExpected(int proto, const Connection* conn) ExpectedConn c(conn->OrigAddr(), conn->RespAddr(), ntohs(conn->RespPort()), proto); - // Can't use sizeof(c) due to potential alignment issues. - // FIXME: I guess this is still not portable ... - HashKey key(&c, sizeof(c.orig) + sizeof(c.resp) + - sizeof(c.resp_p) + sizeof(c.proto)); - - AssignedAnalyzer* a = expected_conns.Lookup(&key); + HashKey* key = BuildExpectedConnHashKey(c); + AssignedAnalyzer* a = expected_conns.Lookup(key); + delete key; if ( ! a ) { // Wildcard for originator. - for ( int i = 0; i < NUM_ADDR_WORDS; ++i ) - c.orig[i] = 0; + c.orig = IPAddr(string("::")); - HashKey key(&c, sizeof(c.orig) + sizeof(c.resp) + - sizeof(c.resp_p) + sizeof(c.proto)); - - a = expected_conns.Lookup(&key); + HashKey* key = BuildExpectedConnHashKey(c); + a = expected_conns.Lookup(key); + delete key; } if ( ! a ) @@ -217,46 +185,8 @@ bool DPM::BuildInitialAnalyzerTree(TransportProto proto, Connection* conn, break; case TRANSPORT_ICMP: { - const struct icmp* icmpp = (const struct icmp *) data; - switch ( icmpp->icmp_type ) { - - case ICMP_ECHO: - case ICMP_ECHOREPLY: - if ( ICMP_Echo_Analyzer::Available() ) - { - root = icmp = new ICMP_Echo_Analyzer(conn); - DBG_DPD(conn, "activated ICMP Echo analyzer"); - } - break; - - case ICMP_REDIRECT: - if ( ICMP_Redir_Analyzer::Available() ) - { - root = new ICMP_Redir_Analyzer(conn); - DBG_DPD(conn, "activated ICMP Redir analyzer"); - } - break; - - case ICMP_UNREACH: - if ( ICMP_Unreachable_Analyzer::Available() ) - { - root = icmp = new ICMP_Unreachable_Analyzer(conn); - DBG_DPD(conn, "activated ICMP Unreachable analyzer"); - } - break; - - case ICMP_TIMXCEED: - if ( ICMP_TimeExceeded_Analyzer::Available() ) - { - root = icmp = new ICMP_TimeExceeded_Analyzer(conn); - DBG_DPD(conn, "activated ICMP Time Exceeded analyzer"); - } - break; - } - - if ( ! root ) - root = icmp = new ICMP_Analyzer(conn); - + root = icmp = new ICMP_Analyzer(conn); + DBG_DPD(conn, "activated ICMP analyzer"); analyzed = true; break; } @@ -406,7 +336,8 @@ bool DPM::BuildInitialAnalyzerTree(TransportProto proto, Connection* conn, return true; } -void DPM::ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p, +void DPM::ExpectConnection(const IPAddr& orig, const IPAddr& resp, + uint16 resp_p, TransportProto proto, AnalyzerTag::Tag analyzer, double timeout, void* cookie) { @@ -418,11 +349,7 @@ void DPM::ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p, { if ( ! a->deleted ) { - HashKey* key = new HashKey(&a->conn, - sizeof(a->conn.orig) + - sizeof(a->conn.resp) + - sizeof(a->conn.resp_p) + - sizeof(a->conn.proto)); + HashKey* key = BuildExpectedConnHashKey(a->conn); expected_conns.Remove(key); delete key; } @@ -441,10 +368,9 @@ void DPM::ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p, ExpectedConn c(orig, resp, resp_p, proto); - HashKey key(&c, sizeof(c.orig) + sizeof(c.resp) + - sizeof(c.resp_p) + sizeof(c.proto)); + HashKey* key = BuildExpectedConnHashKey(c); - AssignedAnalyzer* a = expected_conns.Lookup(&key); + AssignedAnalyzer* a = expected_conns.Lookup(key); if ( a ) a->deleted = true; @@ -456,8 +382,9 @@ void DPM::ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p, a->timeout = network_time + timeout; a->deleted = false; - expected_conns.Insert(&key, a); + expected_conns.Insert(key, a); expected_conns_queue.push(a); + delete key; } void DPM::Done() @@ -468,11 +395,7 @@ void DPM::Done() AssignedAnalyzer* a = expected_conns_queue.top(); if ( ! a->deleted ) { - HashKey* key = new HashKey(&a->conn, - sizeof(a->conn.orig) + - sizeof(a->conn.resp) + - sizeof(a->conn.resp_p) + - sizeof(a->conn.proto)); + HashKey* key = BuildExpectedConnHashKey(a->conn); expected_conns.Remove(key); delete key; } diff --git a/src/DPM.h b/src/DPM.h index 056f6b25cc..f59d21dbfc 100644 --- a/src/DPM.h +++ b/src/DPM.h @@ -1,5 +1,3 @@ -// $Id:$ -// // The central management unit for dynamic analyzer selection. #ifndef DPM_H @@ -29,19 +27,13 @@ // Map to assign expected connections to analyzers. class ExpectedConn { public: - // This form can be used for IPv6 as well as IPv4. - ExpectedConn(const uint32* _orig, const uint32* _resp, + ExpectedConn(const IPAddr& _orig, const IPAddr& _resp, uint16 _resp_p, uint16 _proto); - // This form only works for expecting an IPv4 connection. Note - // that we do the right thing whether we're built IPv4-only or - // BROv6. - ExpectedConn(uint32 _orig, uint32 _resp, uint16 _resp_p, uint16 _proto); - ExpectedConn(const ExpectedConn& c); - uint32 orig[NUM_ADDR_WORDS]; - uint32 resp[NUM_ADDR_WORDS]; + IPAddr orig; + IPAddr resp; uint16 resp_p; uint16 proto; }; @@ -92,7 +84,7 @@ public: // Schedules a particular analyzer for an upcoming connection. // 0 acts as a wildcard for orig. (Cookie is currently unused. // Eventually, we may pass it on to the analyzer). - void ExpectConnection(addr_type orig, addr_type resp, uint16 resp_p, + void ExpectConnection(const IPAddr& orig, const IPAddr& resp, uint16 resp_p, TransportProto proto, AnalyzerTag::Tag analyzer, double timeout, void* cookie); diff --git a/src/DbgBreakpoint.cc b/src/DbgBreakpoint.cc index 7205a78521..11847fc4dc 100644 --- a/src/DbgBreakpoint.cc +++ b/src/DbgBreakpoint.cc @@ -1,5 +1,3 @@ -// $Id: DbgBreakpoint.cc 1345 2005-09-08 07:42:11Z vern $ - // Implementation of breakpoints. #include "config.h" diff --git a/src/DbgBreakpoint.h b/src/DbgBreakpoint.h index 505d1389a4..5fadfe0474 100644 --- a/src/DbgBreakpoint.h +++ b/src/DbgBreakpoint.h @@ -1,5 +1,3 @@ -// $Id: DbgBreakpoint.h 80 2004-07-14 20:15:50Z jason $ - // Structures and methods for implementing breakpoints in the Bro debugger. #ifndef DbgBreakpoint_h diff --git a/src/DbgDisplay.h b/src/DbgDisplay.h index 033dac79e9..1c83d84ec4 100644 --- a/src/DbgDisplay.h +++ b/src/DbgDisplay.h @@ -1,5 +1,3 @@ -// $Id: DbgDisplay.h 80 2004-07-14 20:15:50Z jason $ - // Structures and methods for implementing watches in the Bro debugger. #ifndef dbg_display_h diff --git a/src/DbgWatch.h b/src/DbgWatch.h index ed85e88748..e3359f53ad 100644 --- a/src/DbgWatch.h +++ b/src/DbgWatch.h @@ -1,5 +1,3 @@ -// $Id: DbgWatch.h 80 2004-07-14 20:15:50Z jason $ - // Structures and methods for implementing watches in the Bro debugger. #ifndef dbgwatch_h diff --git a/src/Debug.cc b/src/Debug.cc index 7b6dcfdb68..ea9c52f77e 100644 --- a/src/Debug.cc +++ b/src/Debug.cc @@ -54,7 +54,7 @@ DebuggerState::~DebuggerState() bool StmtLocMapping::StartsAfter(const StmtLocMapping* m2) { if ( ! m2 ) - reporter->InternalError("Assertion failed: %s", "m2 != 0"); + reporter->InternalError("Assertion failed: m2 != 0"); return loc.first_line > m2->loc.first_line || (loc.first_line == m2->loc.first_line && @@ -142,7 +142,7 @@ int TraceState::LogTrace(const char* fmt, ...) if ( ! loc.filename ) { - loc.filename = ""; + loc.filename = copy_string(""); loc.last_line = 0; } @@ -603,7 +603,7 @@ int dbg_execute_command(const char* cmd) #endif if ( int(cmd_code) >= num_debug_cmds() ) - reporter->InternalError("Assertion failed: %s", "int(cmd_code) < num_debug_cmds()"); + reporter->InternalError("Assertion failed: int(cmd_code) < num_debug_cmds()"); // Dispatch to the op-specific handler (with args). int retcode = dbg_dispatch_cmd(cmd_code, arguments); @@ -612,7 +612,7 @@ int dbg_execute_command(const char* cmd) const DebugCmdInfo* info = get_debug_cmd_info(cmd_code); if ( ! info ) - reporter->InternalError("Assertion failed: %s", "info"); + reporter->InternalError("Assertion failed: info"); if ( ! info ) return -2; // ### yuck, why -2? @@ -735,7 +735,7 @@ string get_context_description(const Stmt* stmt, const Frame* frame) loc = *stmt->GetLocationInfo(); else { - loc.filename = ""; + loc.filename = copy_string(""); loc.last_line = 0; } @@ -766,7 +766,7 @@ int dbg_handle_debug_input() const Stmt* stmt = curr_frame->GetNextStmt(); if ( ! stmt ) - reporter->InternalError("Assertion failed: %s", "stmt != 0"); + reporter->InternalError("Assertion failed: stmt != 0"); const Location loc = *stmt->GetLocationInfo(); @@ -797,7 +797,7 @@ int dbg_handle_debug_input() input_line = (char*) safe_malloc(1024); input_line[1023] = 0; // ### Maybe it's not always stdin. - fgets(input_line, 1023, stdin); + input_line = fgets(input_line, 1023, stdin); #endif // ### Maybe not stdin; maybe do better cleanup. @@ -943,11 +943,11 @@ Val* dbg_eval_expr(const char* expr) (g_frame_stack.size() - 1) - g_debugger_state.curr_frame_idx; if ( ! (frame_idx >= 0 && (unsigned) frame_idx < g_frame_stack.size()) ) - reporter->InternalError("Assertion failed: %s", "frame_idx >= 0 && (unsigned) frame_idx < g_frame_stack.size()"); + reporter->InternalError("Assertion failed: frame_idx >= 0 && (unsigned) frame_idx < g_frame_stack.size()"); Frame* frame = g_frame_stack[frame_idx]; if ( ! (frame) ) - reporter->InternalError("Assertion failed: %s", "frame"); + reporter->InternalError("Assertion failed: frame"); const BroFunc* func = frame->GetFunction(); if ( func ) diff --git a/src/Debug.h b/src/Debug.h index ad82337b12..a83e05c224 100644 --- a/src/Debug.h +++ b/src/Debug.h @@ -1,5 +1,3 @@ -// $Id: Debug.h 80 2004-07-14 20:15:50Z jason $ - // Debugging support for Bro policy files. #ifndef debug_h diff --git a/src/DebugCmds.h b/src/DebugCmds.h index a14990b918..e7b9c6a4c1 100644 --- a/src/DebugCmds.h +++ b/src/DebugCmds.h @@ -1,5 +1,3 @@ -// $Id: DebugCmds.h 80 2004-07-14 20:15:50Z jason $ -// // Support routines to help deal with Bro debugging commands and // implementation of most commands. diff --git a/src/DebugLogger.cc b/src/DebugLogger.cc index adf06b7d67..c41a0552c6 100644 --- a/src/DebugLogger.cc +++ b/src/DebugLogger.cc @@ -1,5 +1,3 @@ -// $Id: DebugLogger.cc 4771 2007-08-11 05:50:24Z vern $ - #ifdef DEBUG #include @@ -17,7 +15,7 @@ DebugLogger::Stream DebugLogger::streams[NUM_DBGS] = { { "compressor", 0, false }, {"string", 0, false }, { "notifiers", 0, false }, { "main-loop", 0, false }, { "dpd", 0, false }, { "tm", 0, false }, - { "logging", 0, false } + { "logging", 0, false }, { "threading", 0, false } }; DebugLogger::DebugLogger(const char* filename) @@ -74,7 +72,7 @@ void DebugLogger::EnableStreams(const char* s) if ( strcasecmp("verbose", tok) == 0 ) verbose = true; else - reporter->InternalError("unknown debug stream %s\n", tok); + reporter->FatalError("unknown debug stream %s\n", tok); } tok = strtok(0, ","); diff --git a/src/DebugLogger.h b/src/DebugLogger.h index 49c875a5c4..71e21bfa26 100644 --- a/src/DebugLogger.h +++ b/src/DebugLogger.h @@ -1,5 +1,3 @@ -// $Id: DebugLogger.h 4771 2007-08-11 05:50:24Z vern $ -// // A logger for (selective) debugging output. Only compiled in if DEBUG is // defined. @@ -26,6 +24,7 @@ enum DebugStream { DBG_DPD, // Dynamic application detection framework DBG_TM, // Time-machine packet input via Brocolli DBG_LOGGING, // Logging streams + DBG_THREADING, // Threading system NUM_DBGS // Has to be last }; diff --git a/src/Desc.cc b/src/Desc.cc index 454de549ef..9d94321427 100644 --- a/src/Desc.cc +++ b/src/Desc.cc @@ -1,5 +1,3 @@ -// $Id: Desc.cc 6245 2008-10-07 00:56:59Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -43,8 +41,7 @@ ODesc::ODesc(desc_type t, BroFile* arg_f) do_flush = 1; include_stats = 0; indent_with_spaces = 0; - escape = 0; - escape_len = 0; + escape = false; } ODesc::~ODesc() @@ -58,10 +55,9 @@ ODesc::~ODesc() free(base); } -void ODesc::SetEscape(const char* arg_escape, int len) +void ODesc::EnableEscaping() { - escape = arg_escape; - escape_len = len; + escape = true; } void ODesc::PushIndent() @@ -104,7 +100,7 @@ void ODesc::Add(int i) else { char tmp[256]; - sprintf(tmp, "%d", i); + modp_litoa10(i, tmp); Add(tmp); } } @@ -116,7 +112,7 @@ void ODesc::Add(uint32 u) else { char tmp[256]; - sprintf(tmp, "%u", u); + modp_ulitoa10(u, tmp); Add(tmp); } } @@ -128,7 +124,7 @@ void ODesc::Add(int64 i) else { char tmp[256]; - sprintf(tmp, "%" PRId64, i); + modp_litoa10(i, tmp); Add(tmp); } } @@ -140,7 +136,7 @@ void ODesc::Add(uint64 u) else { char tmp[256]; - sprintf(tmp, "%" PRIu64, u); + modp_ulitoa10(u, tmp); Add(tmp); } } @@ -152,7 +148,7 @@ void ODesc::Add(double d) else { char tmp[256]; - sprintf(tmp, IsReadable() ? "%.15g" : "%.17g", d); + modp_dtoa2(d, tmp, IsReadable() ? 6 : 8); Add(tmp); if ( d == double(int(d)) ) @@ -161,6 +157,16 @@ void ODesc::Add(double d) } } +void ODesc::Add(const IPAddr& addr) + { + Add(addr.AsString()); + } + +void ODesc::Add(const IPPrefix& prefix) + { + Add(prefix.AsString()); + } + void ODesc::AddCS(const char* s) { int n = strlen(s); @@ -230,54 +236,62 @@ static const char* find_first_unprintable(ODesc* d, const char* bytes, unsigned return 0; } +pair ODesc::FirstEscapeLoc(const char* bytes, size_t n) + { + pair p(find_first_unprintable(this, bytes, n), 1); + + string str(bytes, n); + list::const_iterator it; + for ( it = escape_sequences.begin(); it != escape_sequences.end(); ++it ) + { + size_t pos = str.find(*it); + if ( pos != string::npos && (p.first == 0 || bytes + pos < p.first) ) + { + p.first = bytes + pos; + p.second = it->size(); + } + } + + return p; + } + void ODesc::AddBytes(const void* bytes, unsigned int n) { + if ( ! escape ) + { + AddBytesRaw(bytes, n); + return; + } + const char* s = (const char*) bytes; const char* e = (const char*) bytes + n; while ( s < e ) { - const char* t1 = escape ? (const char*) memchr(s, escape[0], e - s) : e; - const char* t2 = find_first_unprintable(this, s, t1 ? e - t1 : e - s); - - if ( t2 && (t2 < t1 || ! t1) ) + pair p = FirstEscapeLoc(s, e - s); + if ( p.first ) { - AddBytesRaw(s, t2 - s); - - char hex[6] = "\\x00"; - hex[2] = hex_chars[((*t2) & 0xf0) >> 4]; - hex[3] = hex_chars[(*t2) & 0x0f]; - AddBytesRaw(hex, sizeof(hex)); - - s = t2 + 1; - continue; + AddBytesRaw(s, p.first - s); + if ( p.second == 1 ) + { + char hex[6] = "\\x00"; + hex[2] = hex_chars[((*p.first) & 0xf0) >> 4]; + hex[3] = hex_chars[(*p.first) & 0x0f]; + AddBytesRaw(hex, 4); + } + else + { + string esc_str = get_escaped_string(string(p.first, p.second), true); + AddBytesRaw(esc_str.c_str(), esc_str.size()); + } + s = p.first + p.second; } - - if ( ! escape ) - break; - - if ( ! t1 ) - break; - - if ( memcmp(t1, escape, escape_len) != 0 ) - break; - - AddBytesRaw(s, t1 - s); - - for ( int i = 0; i < escape_len; ++i ) + else { - char hex[5] = "\\x00"; - hex[2] = hex_chars[((*t1) & 0xf0) >> 4]; - hex[3] = hex_chars[(*t1) & 0x0f]; - AddBytesRaw(hex, sizeof(hex)); - ++t1; + AddBytesRaw(s, e - s); + break; } - - s = t1; } - - if ( s < e ) - AddBytesRaw(s, e - s); } void ODesc::AddBytesRaw(const void* bytes, unsigned int n) @@ -294,7 +308,7 @@ void ODesc::AddBytesRaw(const void* bytes, unsigned int n) if ( ! write_failed ) // Most likely it's a "disk full" so report // subsequent failures only once. - reporter->Error(fmt("error writing to %s: %s", f->Name(), strerror(errno))); + reporter->Error("error writing to %s: %s", f->Name(), strerror(errno)); write_failed = true; return; @@ -332,3 +346,18 @@ void ODesc::OutOfMemory() { reporter->InternalError("out of memory"); } + +void ODesc::Clear() + { + offset = 0; + + // If we've allocated an exceedingly large amount of space, free it. + if ( size > 10 * 1024 * 1024 ) + { + free(base); + size = DEFAULT_SIZE; + base = safe_malloc(size); + ((char*) base)[0] = '\0'; + } + } + diff --git a/src/Desc.h b/src/Desc.h index a9758d764b..9c60c68106 100644 --- a/src/Desc.h +++ b/src/Desc.h @@ -1,11 +1,12 @@ -// $Id: Desc.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef descriptor_h #define descriptor_h #include +#include +#include + #include "BroString.h" typedef enum { @@ -21,6 +22,8 @@ typedef enum { } desc_style; class BroFile; +class IPAddr; +class IPPrefix; class ODesc { public: @@ -50,8 +53,13 @@ public: void SetFlush(int arg_do_flush) { do_flush = arg_do_flush; } - // The string passed in must remain valid as long as this object lives. - void SetEscape(const char* escape, int len); + void EnableEscaping(); + void AddEscapeSequence(const char* s) { escape_sequences.push_back(s); } + void AddEscapeSequence(const char* s, size_t n) + { escape_sequences.push_back(string(s, n)); } + void RemoveEscapeSequence(const char* s) { escape_sequences.remove(s); } + void RemoveEscapeSequence(const char* s, size_t n) + { escape_sequences.remove(string(s, n)); } void PushIndent(); void PopIndent(); @@ -63,11 +71,14 @@ public: void Add(const char* s, int do_indent=1); void AddN(const char* s, int len) { AddBytes(s, len); } + void Add(const string& s) { AddBytes(s.data(), s.size()); } void Add(int i); void Add(uint32 u); void Add(int64 i); void Add(uint64 u); void Add(double d); + void Add(const IPAddr& addr); + void Add(const IPPrefix& prefix); // Add s as a counted string. void AddCS(const char* s); @@ -122,6 +133,8 @@ public: int Len() const { return offset; } + void Clear(); + protected: void Indent(); @@ -133,6 +146,19 @@ protected: void OutOfMemory(); + /** + * Returns the location of the first place in the bytes to be hex-escaped. + * + * @param bytes the starting memory address to start searching for + * escapable character. + * @param n the maximum number of bytes to search. + * @return a pair whose first element represents a starting memory address + * to be escaped up to the number of characters indicated by the + * second element. The first element may be 0 if nothing is + * to be escaped. + */ + pair FirstEscapeLoc(const char* bytes, size_t n); + desc_type type; desc_style style; @@ -140,8 +166,8 @@ protected: unsigned int offset; // where we are in the buffer unsigned int size; // size of buffer in bytes - int escape_len; // number of bytes in to escape sequence - const char* escape; // bytes to escape on output + bool escape; // escape unprintable characters in output? + list escape_sequences; // additional sequences of chars to escape BroFile* f; // or the file we're using. diff --git a/src/Dict.cc b/src/Dict.cc index 6bef17ad3e..c71cf4c417 100644 --- a/src/Dict.cc +++ b/src/Dict.cc @@ -1,5 +1,3 @@ -// $Id: Dict.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -69,6 +67,19 @@ Dictionary::Dictionary(dict_order ordering, int initial_size) } Dictionary::~Dictionary() + { + DeInit(); + delete order; + } + +void Dictionary::Clear() + { + DeInit(); + Init(2); + tbl2 = 0; + } + +void Dictionary::DeInit() { for ( int i = 0; i < num_buckets; ++i ) if ( tbl[i] ) @@ -86,7 +97,6 @@ Dictionary::~Dictionary() } delete [] tbl; - delete order; if ( tbl2 == 0 ) return; @@ -105,7 +115,9 @@ Dictionary::~Dictionary() delete chain; } + delete [] tbl2; + tbl2 = 0; } void* Dictionary::Lookup(const void* key, int key_size, hash_t hash) const diff --git a/src/Dict.h b/src/Dict.h index 75ac82c827..3a2239ef54 100644 --- a/src/Dict.h +++ b/src/Dict.h @@ -1,5 +1,3 @@ -// $Id: Dict.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef dict_h @@ -120,11 +118,15 @@ public: void MakeRobustCookie(IterCookie* cookie) { cookies.append(cookie); } + // Remove all entries. + void Clear(); + unsigned int MemoryAllocation() const; private: void Init(int size); void Init2(int size); // initialize second table for resizing + void DeInit(); // Internal version of Insert(). void* Insert(DictEntry* entry, int copy_key); diff --git a/src/Discard.cc b/src/Discard.cc index fcee23e5e0..edfeea1408 100644 --- a/src/Discard.cc +++ b/src/Discard.cc @@ -1,5 +1,3 @@ -// $Id: Discard.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include @@ -12,11 +10,6 @@ Discarder::Discarder() { - ip_hdr = internal_type("ip_hdr")->AsRecordType(); - tcp_hdr = internal_type("tcp_hdr")->AsRecordType(); - udp_hdr = internal_type("udp_hdr")->AsRecordType(); - icmp_hdr = internal_type("icmp_hdr")->AsRecordType(); - check_ip = internal_func("discarder_check_ip"); check_tcp = internal_func("discarder_check_tcp"); check_udp = internal_func("discarder_check_udp"); @@ -38,32 +31,39 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) { int discard_packet = 0; - const struct ip* ip4 = ip->IP4_Hdr(); - if ( check_ip ) { val_list* args = new val_list; - args->append(BuildHeader(ip4)); - discard_packet = check_ip->Call(args)->AsBool(); + args->append(ip->BuildPktHdrVal()); + + try + { + discard_packet = check_ip->Call(args)->AsBool(); + } + + catch ( InterpreterException& e ) + { + discard_packet = false; + } + delete args; if ( discard_packet ) return discard_packet; } - int proto = ip4->ip_p; + int proto = ip->NextProto(); if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP && proto != IPPROTO_ICMP ) // This is not a protocol we understand. return 0; // XXX shall we only check the first packet??? - uint32 frag_field = ntohs(ip4->ip_off); - if ( (frag_field & 0x3fff) != 0 ) + if ( ip->IsFragment() ) // Never check any fragment. return 0; - int ip_hdr_len = ip4->ip_hl * 4; + int ip_hdr_len = ip->HdrLen(); len -= ip_hdr_len; // remove IP header caplen -= ip_hdr_len; @@ -79,7 +79,7 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) // Where the data starts - if this is a protocol we know about, // this gets advanced past the transport header. - const u_char* data = ((u_char*) ip4 + ip_hdr_len); + const u_char* data = ip->Payload(); if ( is_tcp ) { @@ -89,10 +89,19 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) int th_len = tp->th_off * 4; val_list* args = new val_list; - args->append(BuildHeader(ip4)); - args->append(BuildHeader(tp, len)); + args->append(ip->BuildPktHdrVal()); args->append(BuildData(data, th_len, len, caplen)); - discard_packet = check_tcp->Call(args)->AsBool(); + + try + { + discard_packet = check_tcp->Call(args)->AsBool(); + } + + catch ( InterpreterException& e ) + { + discard_packet = false; + } + delete args; } } @@ -105,10 +114,19 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) int uh_len = sizeof (struct udphdr); val_list* args = new val_list; - args->append(BuildHeader(ip4)); - args->append(BuildHeader(up)); + args->append(ip->BuildPktHdrVal()); args->append(BuildData(data, uh_len, len, caplen)); - discard_packet = check_udp->Call(args)->AsBool(); + + try + { + discard_packet = check_udp->Call(args)->AsBool(); + } + + catch ( InterpreterException& e ) + { + discard_packet = false; + } + delete args; } } @@ -120,9 +138,18 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) const struct icmp* ih = (const struct icmp*) data; val_list* args = new val_list; - args->append(BuildHeader(ip4)); - args->append(BuildHeader(ih)); - discard_packet = check_icmp->Call(args)->AsBool(); + args->append(ip->BuildPktHdrVal()); + + try + { + discard_packet = check_icmp->Call(args)->AsBool(); + } + + catch ( InterpreterException& e ) + { + discard_packet = false; + } + delete args; } } @@ -130,62 +157,6 @@ int Discarder::NextPacket(const IP_Hdr* ip, int len, int caplen) return discard_packet; } -Val* Discarder::BuildHeader(const struct ip* ip) - { - RecordVal* hdr = new RecordVal(ip_hdr); - - hdr->Assign(0, new Val(ip->ip_hl * 4, TYPE_COUNT)); - hdr->Assign(1, new Val(ip->ip_tos, TYPE_COUNT)); - hdr->Assign(2, new Val(ntohs(ip->ip_len), TYPE_COUNT)); - hdr->Assign(3, new Val(ntohs(ip->ip_id), TYPE_COUNT)); - hdr->Assign(4, new Val(ip->ip_ttl, TYPE_COUNT)); - hdr->Assign(5, new Val(ip->ip_p, TYPE_COUNT)); - hdr->Assign(6, new AddrVal(ip->ip_src.s_addr)); - hdr->Assign(7, new AddrVal(ip->ip_dst.s_addr)); - - return hdr; - } - -Val* Discarder::BuildHeader(const struct tcphdr* tp, int tcp_len) - { - RecordVal* hdr = new RecordVal(tcp_hdr); - - hdr->Assign(0, new PortVal(ntohs(tp->th_sport), TRANSPORT_TCP)); - hdr->Assign(1, new PortVal(ntohs(tp->th_dport), TRANSPORT_TCP)); - hdr->Assign(2, new Val(uint32(ntohl(tp->th_seq)), TYPE_COUNT)); - hdr->Assign(3, new Val(uint32(ntohl(tp->th_ack)), TYPE_COUNT)); - - int tcp_hdr_len = tp->th_off * 4; - - hdr->Assign(4, new Val(tcp_hdr_len, TYPE_COUNT)); - hdr->Assign(5, new Val(tcp_len - tcp_hdr_len, TYPE_COUNT)); - - hdr->Assign(6, new Val(tp->th_flags, TYPE_COUNT)); - hdr->Assign(7, new Val(ntohs(tp->th_win), TYPE_COUNT)); - - return hdr; - } - -Val* Discarder::BuildHeader(const struct udphdr* up) - { - RecordVal* hdr = new RecordVal(udp_hdr); - - hdr->Assign(0, new PortVal(ntohs(up->uh_sport), TRANSPORT_UDP)); - hdr->Assign(1, new PortVal(ntohs(up->uh_dport), TRANSPORT_UDP)); - hdr->Assign(2, new Val(ntohs(up->uh_ulen), TYPE_COUNT)); - - return hdr; - } - -Val* Discarder::BuildHeader(const struct icmp* icmp) - { - RecordVal* hdr = new RecordVal(icmp_hdr); - - hdr->Assign(0, new Val(icmp->icmp_type, TYPE_COUNT)); - - return hdr; - } - Val* Discarder::BuildData(const u_char* data, int hdrlen, int len, int caplen) { len -= hdrlen; diff --git a/src/Discard.h b/src/Discard.h index 4ffcab39d1..f4daabefa7 100644 --- a/src/Discard.h +++ b/src/Discard.h @@ -1,5 +1,3 @@ -// $Id: Discard.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef discard_h @@ -27,17 +25,8 @@ public: int NextPacket(const IP_Hdr* ip, int len, int caplen); protected: - Val* BuildHeader(const struct ip* ip); - Val* BuildHeader(const struct tcphdr* tp, int tcp_len); - Val* BuildHeader(const struct udphdr* up); - Val* BuildHeader(const struct icmp* icmp); Val* BuildData(const u_char* data, int hdrlen, int len, int caplen); - RecordType* ip_hdr; - RecordType* tcp_hdr; - RecordType* udp_hdr; - RecordType* icmp_hdr; - Func* check_ip; Func* check_tcp; Func* check_udp; diff --git a/src/EquivClass.cc b/src/EquivClass.cc index ff5dc88603..6ab667b146 100644 --- a/src/EquivClass.cc +++ b/src/EquivClass.cc @@ -1,5 +1,3 @@ -// $Id: EquivClass.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/EquivClass.h b/src/EquivClass.h index 9b35a9bb64..e5193cde47 100644 --- a/src/EquivClass.h +++ b/src/EquivClass.h @@ -1,5 +1,3 @@ -// $Id: EquivClass.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef equiv_class_h diff --git a/src/Event.cc b/src/Event.cc index 0ba5b68a21..97f29000d6 100644 --- a/src/Event.cc +++ b/src/Event.cc @@ -1,5 +1,3 @@ -// $Id: Event.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/Event.h b/src/Event.h index ce498ae9cc..e0ce7bf555 100644 --- a/src/Event.h +++ b/src/Event.h @@ -1,5 +1,3 @@ -// $Id: Event.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef event_h @@ -43,7 +41,16 @@ protected: if ( handler->ErrorHandler() ) reporter->BeginErrorHandler(); - handler->Call(args, no_remote); + try + { + handler->Call(args, no_remote); + } + + catch ( InterpreterException& e ) + { + // Already reported. + } + if ( obj ) // obj->EventDone(); Unref(obj); diff --git a/src/EventHandler.cc b/src/EventHandler.cc index 9a06763bc0..2867b63437 100644 --- a/src/EventHandler.cc +++ b/src/EventHandler.cc @@ -1,5 +1,3 @@ -// $Id: EventHandler.cc 5911 2008-07-03 22:59:01Z vern $ - #include "Event.h" #include "EventHandler.h" #include "Func.h" @@ -70,6 +68,7 @@ void EventHandler::Call(val_list* vl, bool no_remote) } if ( local ) + // No try/catch here; we pass exceptions upstream. Unref(local->Call(vl)); else { diff --git a/src/EventHandler.h b/src/EventHandler.h index 6a9438fd4c..a86b8a285c 100644 --- a/src/EventHandler.h +++ b/src/EventHandler.h @@ -1,5 +1,3 @@ -// $Id: EventHandler.h 5911 2008-07-03 22:59:01Z vern $ -// // Capsulates local and remote event handlers. #ifndef EVENTHANDLER @@ -9,7 +7,6 @@ #include "List.h" #include "BroList.h" -#include "net_util.h" class Func; class FuncType; diff --git a/src/EventLauncher.cc b/src/EventLauncher.cc index 1982d78c11..246c9dc8aa 100644 --- a/src/EventLauncher.cc +++ b/src/EventLauncher.cc @@ -1,5 +1,3 @@ -// $Id:$ - #include "Val.h" #include "Analyzer.h" #include "EventLauncher.h" diff --git a/src/EventLauncher.h b/src/EventLauncher.h index 276f28ef75..6a57c59391 100644 --- a/src/EventLauncher.h +++ b/src/EventLauncher.h @@ -1,5 +1,3 @@ -// $Id:$ - #ifndef event_launcher_h #define event_launcher_h diff --git a/src/EventRegistry.cc b/src/EventRegistry.cc index f5691ab448..4d29c5d95f 100644 --- a/src/EventRegistry.cc +++ b/src/EventRegistry.cc @@ -1,5 +1,3 @@ -// $Id: EventRegistry.cc 6829 2009-07-09 09:12:59Z vern $ - #include "EventRegistry.h" #include "RE.h" #include "RemoteSerializer.h" diff --git a/src/EventRegistry.h b/src/EventRegistry.h index bd9e0cd185..6ee5e3bcbd 100644 --- a/src/EventRegistry.h +++ b/src/EventRegistry.h @@ -1,5 +1,3 @@ -// $Id: EventRegistry.h 6829 2009-07-09 09:12:59Z vern $ -// // Each event raised/handled by Bro is registered in the EventRegistry. #ifndef EVENT_REGISTRY diff --git a/src/Expr.cc b/src/Expr.cc index dc47340ccd..58f5db3fd1 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -1,5 +1,3 @@ -// $Id: Expr.cc 6864 2009-08-16 23:30:39Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -16,6 +14,7 @@ #include "Net.h" #include "Traverse.h" #include "Trigger.h" +#include "IPAddr.h" const char* expr_name(BroExprTag t) { @@ -223,7 +222,9 @@ bool Expr::DoUnserialize(UnserialInfo* info) tag = BroExprTag(c); - UNSERIALIZE_OPTIONAL(type, BroType::Unserialize(info)); + BroType* t = 0; + UNSERIALIZE_OPTIONAL(t, BroType::Unserialize(info)); + SetType(t); return true; } @@ -359,7 +360,7 @@ bool NameExpr::DoUnserialize(UnserialInfo* info) if ( id ) ::Ref(id); else - reporter->Warning("unserialized unknown global name"); + reporter->Warning("configuration changed: unserialized unknown global name from persistent state"); delete [] name; } @@ -834,30 +835,30 @@ Val* BinaryExpr::StringFold(Val* v1, Val* v2) const Val* BinaryExpr::AddrFold(Val* v1, Val* v2) const { - addr_type a1 = v1->AsAddr(); - addr_type a2 = v2->AsAddr(); + IPAddr a1 = v1->AsAddr(); + IPAddr a2 = v2->AsAddr(); int result = 0; switch ( tag ) { -#undef DO_FOLD -#ifdef BROv6 -#define DO_FOLD(sense) { result = memcmp(a1, a2, 16) sense 0; break; } -#else -#define DO_FOLD(sense) \ - { \ - a1 = ntohl(a1); \ - a2 = ntohl(a2); \ - result = (a1 < a2 ? -1 : (a1 == a2 ? 0 : 1)) sense 0; \ - break; \ - } -#endif - case EXPR_LT: DO_FOLD(<) - case EXPR_LE: DO_FOLD(<=) - case EXPR_EQ: DO_FOLD(==) - case EXPR_NE: DO_FOLD(!=) - case EXPR_GE: DO_FOLD(>=) - case EXPR_GT: DO_FOLD(>) + case EXPR_LT: + result = a1 < a2; + break; + case EXPR_LE: + result = a1 < a2 || a1 == a2; + break; + case EXPR_EQ: + result = a1 == a2; + break; + case EXPR_NE: + result = a1 != a2; + break; + case EXPR_GE: + result = ! ( a1 < a2 ); + break; + case EXPR_GT: + result = ( ! ( a1 < a2 ) ) && ( a1 != a2 ); + break; default: BadTag("BinaryExpr::AddrFold", expr_name(tag)); @@ -868,20 +869,13 @@ Val* BinaryExpr::AddrFold(Val* v1, Val* v2) const Val* BinaryExpr::SubNetFold(Val* v1, Val* v2) const { - subnet_type* n1 = v1->AsSubNet(); - subnet_type* n2 = v2->AsSubNet(); + const IPPrefix& n1 = v1->AsSubNet(); + const IPPrefix& n2 = v2->AsSubNet(); - if ( n1->width != n2->width ) + if ( n1 == n2 ) + return new Val(1, TYPE_BOOL); + else return new Val(0, TYPE_BOOL); - -#ifdef BROv6 - if ( memcmp(n1->net, n2->net, 16) ) -#else - if ( n1->net != n2->net ) -#endif - return new Val(0, TYPE_BOOL); - - return new Val(1, TYPE_BOOL); } void BinaryExpr::SwapOps() @@ -1681,15 +1675,13 @@ DivideExpr::DivideExpr(Expr* arg_op1, Expr* arg_op2) Val* DivideExpr::AddrFold(Val* v1, Val* v2) const { - addr_type a1 = v1->AsAddr(); - uint32 mask; if ( v2->Type()->Tag() == TYPE_COUNT ) mask = static_cast(v2->InternalUnsigned()); else mask = static_cast(v2->InternalInt()); - return new SubNetVal(a1, mask); + return new SubNetVal(v1->AsAddr(), mask); } Expr* DivideExpr::DoSimplify() @@ -2435,7 +2427,7 @@ bool RefExpr::DoUnserialize(UnserialInfo* info) } AssignExpr::AssignExpr(Expr* arg_op1, Expr* arg_op2, int arg_is_init, - Val* arg_val) + Val* arg_val, attr_list* arg_attrs) : BinaryExpr(EXPR_ASSIGN, arg_is_init ? arg_op1 : arg_op1->MakeLvalue(), arg_op2) { @@ -2455,14 +2447,14 @@ AssignExpr::AssignExpr(Expr* arg_op1, Expr* arg_op2, int arg_is_init, // We discard the status from TypeCheck since it has already // generated error messages. - (void) TypeCheck(); + (void) TypeCheck(arg_attrs); val = arg_val ? arg_val->Ref() : 0; SetLocationInfo(arg_op1->GetLocationInfo(), arg_op2->GetLocationInfo()); } -bool AssignExpr::TypeCheck() +bool AssignExpr::TypeCheck(attr_list* attrs) { TypeTag bt1 = op1->Type()->Tag(); TypeTag bt2 = op2->Type()->Tag(); @@ -2494,6 +2486,21 @@ bool AssignExpr::TypeCheck() return true; } + if ( bt1 == TYPE_TABLE && op2->Tag() == EXPR_LIST ) + { + attr_list* attr_copy = 0; + + if ( attrs ) + { + attr_copy = new attr_list; + loop_over_list(*attrs, i) + attr_copy->append((*attrs)[i]); + } + + op2 = new TableConstructorExpr(op2->AsListExpr(), attr_copy); + return true; + } + if ( bt1 == TYPE_VECTOR && bt2 == bt1 && op2->Type()->AsVectorType()->IsUnspecifiedVector() ) { @@ -2657,8 +2664,6 @@ void AssignExpr::EvalIntoAggregate(const BroType* t, Val* aggr, Frame* f) const Error("bad table insertion"); TableVal* tv = aggr->AsTableVal(); - const TableType* tt = tv->Type()->AsTableType(); - const BroType* yt = tv->Type()->YieldType(); Val* index = op1->Eval(f); Val* v = op2->Eval(f); @@ -3118,8 +3123,9 @@ Val* FieldExpr::Fold(Val* v) const return def_attr->AttrExpr()->Eval(0); else { - Internal("field value missing"); - return 0; + reporter->ExprRuntimeError(this, "field value missing"); + assert(false); + return 0; // Will never get here, but compiler can't tell. } } @@ -3627,150 +3633,6 @@ bool FieldAssignExpr::DoUnserialize(UnserialInfo* info) return true; } -RecordMatchExpr::RecordMatchExpr(Expr* op1 /* record to match */, - Expr* op2 /* cases to match against */) -: BinaryExpr(EXPR_MATCH, op1, op2) - { - BroType* result_type = 0; - - // Make sure the second argument is of a suitable type. - if ( ! op2->Type()->IsSet() ) - { - ExprError("matching must be done against a set of match records"); - return; - } - - type_list* elt_types = op2->Type()->AsSetType()->Indices()->Types(); - - if ( ! elt_types->length() || - (*elt_types)[0]->Tag() != TYPE_RECORD ) - { - ExprError("matching must be done against a set of match records"); - return; - } - - RecordType* case_rec_type = (*elt_types)[0]->AsRecordType(); - - // NOTE: The "result" and "pred" field names are hardcoded here. - result_field_index = case_rec_type->FieldOffset("result"); - - if ( result_field_index < 0 ) - { - ExprError("match records must have a $result field"); - return; - } - - result_type = case_rec_type->FieldType("result")->Ref(); - - // Check that pred exists, and that the first argument matches it. - if ( (pred_field_index = case_rec_type->FieldOffset("pred")) < 0 || - case_rec_type->FieldType("pred")->Tag() != TYPE_FUNC ) - { - ExprError("match records must have a $pred' field of function type"); - return; - } - - FuncType* pred_type = case_rec_type->FieldType("pred")->AsFuncType(); - type_list* pred_arg_types = pred_type->ArgTypes()->Types(); - if ( pred_arg_types->length() != 1 || - ! check_and_promote_expr(op1, (*pred_arg_types)[0]) ) - ExprError("record to match does not have the same type as predicate argument"); - - // NOTE: The "priority" field name is hardcoded here. - if ( (priority_field_index = case_rec_type->FieldOffset("priority")) >= 0 && - ! IsArithmetic(case_rec_type->FieldType("priority")->Tag()) ) - ExprError("$priority field must have a numeric type"); - - SetType(result_type); - } - -void RecordMatchExpr::ExprDescribe(ODesc* d) const - { - if ( d->IsReadable() ) - { - d->Add("match "); - op1->Describe(d); - d->Add(" using "); - op2->Describe(d); - } - } - -Val* RecordMatchExpr::Fold(Val* v1, Val* v2) const - { - TableVal* match_set = v2->AsTableVal(); - if ( ! match_set ) - Internal("non-table in RecordMatchExpr"); - - Val* return_val = 0; - double highest_priority = -1e100; - - ListVal* match_recs = match_set->ConvertToList(TYPE_ANY); - for ( int i = 0; i < match_recs->Length(); ++i ) - { - val_list args(1); - args.append(v1->Ref()); - - double this_priority = 0; - - // ### Get rid of the double Index if TYPE_ANY->TYPE_RECORD. - Val* v = match_recs->Index(i)->AsListVal()->Index(0); - - const RecordVal* match_rec = v->AsRecordVal(); - if ( ! match_rec ) - Internal("Element of match set is not a record"); - - if ( priority_field_index >= 0 ) - { - this_priority = - match_rec->Lookup(priority_field_index)->CoerceToDouble(); - if ( this_priority <= highest_priority ) - { - Unref(v1); - continue; - } - } - - Val* pred_val = - match_rec->Lookup(pred_field_index)->AsFunc()->Call(&args); - bool is_zero = pred_val->IsZero(); - Unref(pred_val); - - if ( ! is_zero ) - { - Val* new_return_val = - match_rec->Lookup(result_field_index); - - Unref(return_val); - return_val = new_return_val->Ref(); - - if ( priority_field_index >= 0 ) - highest_priority = this_priority; - else - break; - } - } - - Unref(match_recs); - - return return_val; - } - -IMPLEMENT_SERIAL(RecordMatchExpr, SER_RECORD_MATCH_EXPR); - -bool RecordMatchExpr::DoSerialize(SerialInfo* info) const - { - DO_SERIALIZE(SER_RECORD_MATCH_EXPR, BinaryExpr); - return SERIALIZE(pred_field_index) && SERIALIZE(result_field_index) && - SERIALIZE(priority_field_index); - } - -bool RecordMatchExpr::DoUnserialize(UnserialInfo* info) - { - DO_UNSERIALIZE(BinaryExpr); - return UNSERIALIZE(&pred_field_index) && UNSERIALIZE(&result_field_index) && - UNSERIALIZE(&priority_field_index); - } - ArithCoerceExpr::ArithCoerceExpr(Expr* arg_op, TypeTag t) : UnaryExpr(EXPR_ARITH_COERCE, arg_op) { @@ -3971,12 +3833,18 @@ RecordCoerceExpr::RecordCoerceExpr(Expr* op, RecordType* r) if ( ! same_type(sup_t_i, sub_t_i) ) { - char buf[512]; - safe_snprintf(buf, sizeof(buf), - "type clash for field \"%s\"", sub_r->FieldName(i)); - Error(buf, sub_t_i); - SetError(); - break; + if ( sup_t_i->Tag() != TYPE_RECORD || + sub_t_i->Tag() != TYPE_RECORD || + ! record_promotion_compatible(sup_t_i->AsRecordType(), + sub_t_i->AsRecordType()) ) + { + char buf[512]; + safe_snprintf(buf, sizeof(buf), + "type clash for field \"%s\"", sub_r->FieldName(i)); + Error(buf, sub_t_i); + SetError(); + break; + } } map[t_i] = i; @@ -4024,10 +3892,36 @@ Val* RecordCoerceExpr::Fold(Val* v) const rhs = rhs->Ref(); assert(rhs || Type()->AsRecordType()->FieldDecl(i)->FindAttr(ATTR_OPTIONAL)); + + BroType* rhs_type = rhs->Type(); + RecordType* val_type = val->Type()->AsRecordType(); + BroType* field_type = val_type->FieldType(i); + + if ( rhs_type->Tag() == TYPE_RECORD && + field_type->Tag() == TYPE_RECORD && + ! same_type(rhs_type, field_type) ) + { + Val* new_val = rhs->AsRecordVal()->CoerceTo( + field_type->AsRecordType()); + if ( new_val ) + { + Unref(rhs); + rhs = new_val; + } + } + val->Assign(i, rhs); } else - val->Assign(i, 0); + { + const Attr* def = + Type()->AsRecordType()->FieldDecl(i)->FindAttr(ATTR_DEFAULT); + + if ( def ) + val->Assign(i, def->AttrExpr()->Eval(0)); + else + val->Assign(i, 0); + } } return val; @@ -4196,7 +4090,7 @@ Val* FlattenExpr::Fold(Val* v) const l->Append(fa->AttrExpr()->Eval(0)); else - Internal("missing field value"); + reporter->ExprRuntimeError(this, "missing field value"); } return l; @@ -4622,7 +4516,7 @@ Val* CallExpr::Eval(Frame* f) const if ( f ) f->SetCall(this); - ret = func->Call(v, f); + ret = func->Call(v, f); // No try/catch here; we pass exceptions upstream. if ( f ) f->ClearCall(); // Don't Unref() the arguments, as Func::Call already did that. @@ -4869,6 +4763,7 @@ Val* ListExpr::Eval(Frame* f) const if ( ! ev ) { Error("uninitialized list value"); + Unref(v); return 0; } diff --git a/src/Expr.h b/src/Expr.h index 2e5d5b637a..f0798359c2 100644 --- a/src/Expr.h +++ b/src/Expr.h @@ -1,5 +1,3 @@ -// $Id: Expr.h 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef expr_h @@ -625,7 +623,7 @@ class AssignExpr : public BinaryExpr { public: // If val is given, evaluating this expression will always yield the val // yet still perform the assignment. Used for triggers. - AssignExpr(Expr* op1, Expr* op2, int is_init, Val* val = 0); + AssignExpr(Expr* op1, Expr* op2, int is_init, Val* val = 0, attr_list* attrs = 0); virtual ~AssignExpr() { Unref(val); } Expr* Simplify(SimplifyType simp_type); @@ -640,7 +638,7 @@ protected: friend class Expr; AssignExpr() { } - bool TypeCheck(); + bool TypeCheck(attr_list* attrs = 0); bool TypeCheckArithmetics(TypeTag bt1, TypeTag bt2); DECLARE_SERIAL(AssignExpr); @@ -825,32 +823,6 @@ protected: string field_name; }; -class RecordMatchExpr : public BinaryExpr { -public: - RecordMatchExpr(Expr* op1 /* record to match */, - Expr* op2 /* cases to match against */); - -protected: - friend class Expr; - RecordMatchExpr() - { - pred_field_index = result_field_index = - priority_field_index = 0; - } - - virtual Val* Fold(Val* v1, Val* v2) const; - void ExprDescribe(ODesc*) const; - - DECLARE_SERIAL(RecordMatchExpr); - - // The following are used to hold the field offset of - // $pred, $result, $priority, so the names only need to - // be looked up at compile-time. - int pred_field_index; - int result_field_index; - int priority_field_index; -}; - class ArithCoerceExpr : public UnaryExpr { public: ArithCoerceExpr(Expr* op, TypeTag t); diff --git a/src/FTP.cc b/src/FTP.cc index 3dcf5722d8..588348ea8d 100644 --- a/src/FTP.cc +++ b/src/FTP.cc @@ -1,5 +1,3 @@ -// $Id: FTP.cc 6782 2009-06-28 02:19:03Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/FTP.h b/src/FTP.h index c50d463b65..4ef6c44d83 100644 --- a/src/FTP.h +++ b/src/FTP.h @@ -1,5 +1,3 @@ -// $Id: FTP.h 6782 2009-06-28 02:19:03Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef ftp_h diff --git a/src/File.cc b/src/File.cc index c8390c9bb5..d4e31bcc16 100644 --- a/src/File.cc +++ b/src/File.cc @@ -1,5 +1,3 @@ -// $Id: File.cc 6942 2009-11-16 03:54:08Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -151,7 +149,7 @@ BroFile::BroFile(const char* arg_name, const char* arg_access, BroType* arg_t) t = arg_t ? arg_t : base_type(TYPE_STRING); if ( ! Open() ) { - reporter->Error(fmt("cannot open %s: %s", name, strerror(errno))); + reporter->Error("cannot open %s: %s", name, strerror(errno)); is_open = 0; okay_to_manage = 0; } @@ -234,7 +232,7 @@ BroFile::~BroFile() delete [] access; delete [] cipher_buffer; -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG heap_checker->UnIgnoreObject(this); #endif } @@ -257,7 +255,7 @@ void BroFile::Init() cipher_ctx = 0; cipher_buffer = 0; -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG heap_checker->IgnoreObject(this); #endif } @@ -287,7 +285,7 @@ FILE* BroFile::BringIntoCache() if ( ! f ) { - reporter->Error("can't open %s", this); + reporter->Error("can't open %s", name); f = fopen("/dev/null", "w"); @@ -302,7 +300,7 @@ FILE* BroFile::BringIntoCache() UpdateFileSize(); if ( fseek(f, position, SEEK_SET) < 0 ) - reporter->Error("reopen seek failed", this); + reporter->Error("reopen seek failed"); InsertAtBeginning(); @@ -315,7 +313,7 @@ FILE* BroFile::Seek(long new_position) return 0; if ( fseek(f, new_position, SEEK_SET) < 0 ) - reporter->Error("seek failed", this); + reporter->Error("seek failed"); return f; } @@ -326,7 +324,7 @@ void BroFile::SetBuf(bool arg_buffered) return; if ( setvbuf(f, NULL, arg_buffered ? _IOFBF : _IOLBF, 0) != 0 ) - reporter->Error("setvbuf failed", this); + reporter->Error("setvbuf failed"); buffered = arg_buffered; } @@ -388,7 +386,7 @@ void BroFile::Suspend() if ( (position = ftell(f)) < 0 ) { - reporter->Error("ftell failed", this); + reporter->Error("ftell failed"); position = 0; } @@ -643,7 +641,7 @@ void BroFile::InitEncrypt(const char* keyfile) if ( ! key ) { - reporter->Error(fmt("can't open key file %s: %s", keyfile, strerror(errno))); + reporter->Error("can't open key file %s: %s", keyfile, strerror(errno)); Close(); return; } @@ -651,8 +649,8 @@ void BroFile::InitEncrypt(const char* keyfile) pub_key = PEM_read_PUBKEY(key, 0, 0, 0); if ( ! pub_key ) { - reporter->Error(fmt("can't read key from %s: %s", keyfile, - ERR_error_string(ERR_get_error(), 0))); + reporter->Error("can't read key from %s: %s", keyfile, + ERR_error_string(ERR_get_error(), 0)); Close(); return; } @@ -665,7 +663,7 @@ void BroFile::InitEncrypt(const char* keyfile) unsigned char secret[EVP_PKEY_size(pub_key)]; unsigned char* psecret = secret; - unsigned long secret_len; + unsigned int secret_len; int iv_len = EVP_CIPHER_iv_length(cipher_type); unsigned char iv[iv_len]; @@ -673,8 +671,8 @@ void BroFile::InitEncrypt(const char* keyfile) if ( ! EVP_SealInit(cipher_ctx, cipher_type, &psecret, (int*) &secret_len, iv, &pub_key, 1) ) { - reporter->Error(fmt("can't init cipher context for %s: %s", keyfile, - ERR_error_string(ERR_get_error(), 0))); + reporter->Error("can't init cipher context for %s: %s", keyfile, + ERR_error_string(ERR_get_error(), 0)); Close(); return; } @@ -686,8 +684,8 @@ void BroFile::InitEncrypt(const char* keyfile) fwrite(secret, ntohl(secret_len), 1, f) && fwrite(iv, iv_len, 1, f)) ) { - reporter->Error(fmt("can't write header to log file %s: %s", - name, strerror(errno))); + reporter->Error("can't write header to log file %s: %s", + name, strerror(errno)); Close(); return; } @@ -711,8 +709,8 @@ void BroFile::FinishEncrypt() if ( outl && ! fwrite(cipher_buffer, outl, 1, f) ) { - reporter->Error(fmt("write error for %s: %s", - name, strerror(errno))); + reporter->Error("write error for %s: %s", + name, strerror(errno)); return; } @@ -743,17 +741,17 @@ int BroFile::Write(const char* data, int len) if ( ! EVP_SealUpdate(cipher_ctx, cipher_buffer, &outl, (unsigned char*)data, inl) ) { - reporter->Error(fmt("encryption error for %s: %s", + reporter->Error("encryption error for %s: %s", name, - ERR_error_string(ERR_get_error(), 0))); + ERR_error_string(ERR_get_error(), 0)); Close(); return 0; } if ( outl && ! fwrite(cipher_buffer, outl, 1, f) ) { - reporter->Error(fmt("write error for %s: %s", - name, strerror(errno))); + reporter->Error("write error for %s: %s", + name, strerror(errno)); Close(); return 0; } @@ -800,7 +798,7 @@ void BroFile::UpdateFileSize() struct stat s; if ( fstat(fileno(f), &s) < 0 ) { - reporter->Error(fmt("can't stat fd for %s: %s", name, strerror(errno))); + reporter->Error("can't stat fd for %s: %s", name, strerror(errno)); current_size = 0; return; } diff --git a/src/File.h b/src/File.h index dad0d6da8b..444d6209e2 100644 --- a/src/File.h +++ b/src/File.h @@ -1,5 +1,3 @@ -// $Id: File.h 6888 2009-08-20 18:23:11Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef file_h diff --git a/src/FileAnalyzer.cc b/src/FileAnalyzer.cc index 16bf003775..d4064e8144 100644 --- a/src/FileAnalyzer.cc +++ b/src/FileAnalyzer.cc @@ -1,27 +1,21 @@ -// $Id: FileAnalyzer.cc,v 1.1.4.2 2006/06/01 17:18:10 sommer Exp $ - #include #include "FileAnalyzer.h" #include "Reporter.h" -#ifdef HAVE_LIBMAGIC magic_t File_Analyzer::magic = 0; magic_t File_Analyzer::magic_mime = 0; -#endif File_Analyzer::File_Analyzer(Connection* conn) : TCP_ApplicationAnalyzer(AnalyzerTag::File, conn) { buffer_len = 0; -#ifdef HAVE_LIBMAGIC if ( ! magic ) { InitMagic(&magic, MAGIC_NONE); InitMagic(&magic_mime, MAGIC_MIME); } -#endif } void File_Analyzer::DeliverStream(int len, const u_char* data, bool orig) @@ -54,13 +48,11 @@ void File_Analyzer::Identify() const char* descr = 0; const char* mime = 0; -#ifdef HAVE_LIBMAGIC if ( magic ) descr = magic_buffer(magic, buffer, buffer_len); if ( magic_mime ) mime = magic_buffer(magic_mime, buffer, buffer_len); -#endif val_list* vl = new val_list; vl->append(BuildConnVal()); @@ -70,19 +62,17 @@ void File_Analyzer::Identify() ConnectionEvent(file_transferred, vl); } -#ifdef HAVE_LIBMAGIC void File_Analyzer::InitMagic(magic_t* magic, int flags) { *magic = magic_open(flags); if ( ! *magic ) - reporter->Error(fmt("can't init libmagic: %s", magic_error(*magic))); + reporter->Error("can't init libmagic: %s", magic_error(*magic)); else if ( magic_load(*magic, 0) < 0 ) { - reporter->Error(fmt("can't load magic file: %s", magic_error(*magic))); + reporter->Error("can't load magic file: %s", magic_error(*magic)); magic_close(*magic); *magic = 0; } } -#endif diff --git a/src/FileAnalyzer.h b/src/FileAnalyzer.h index f343547210..dcf9d22e8e 100644 --- a/src/FileAnalyzer.h +++ b/src/FileAnalyzer.h @@ -1,5 +1,3 @@ -// $Id:$ -// // Analyzer for connections that transfer binary data. #ifndef FILEANALYZER_H @@ -7,9 +5,7 @@ #include "TCP.h" -#ifdef HAVE_LIBMAGIC #include -#endif class File_Analyzer : public TCP_ApplicationAnalyzer { public: @@ -33,12 +29,10 @@ protected: char buffer[BUFFER_SIZE]; int buffer_len; -#ifdef HAVE_LIBMAGIC static void InitMagic(magic_t* magic, int flags); static magic_t magic; static magic_t magic_mime; -#endif }; #endif diff --git a/src/Finger.cc b/src/Finger.cc index 9a0fda8985..be0f3754b5 100644 --- a/src/Finger.cc +++ b/src/Finger.cc @@ -1,5 +1,3 @@ -// $Id: Finger.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/Finger.h b/src/Finger.h index 98738765a3..3c61c4ad2a 100644 --- a/src/Finger.h +++ b/src/Finger.h @@ -1,5 +1,3 @@ -// $Id: Finger.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef finger_h diff --git a/src/FlowSrc.cc b/src/FlowSrc.cc index 6f31cf2c3e..fe6998ea79 100644 --- a/src/FlowSrc.cc +++ b/src/FlowSrc.cc @@ -1,5 +1,3 @@ -/// $Id: FlowSrc.cc 4621 2007-07-10 13:37:13Z bager $ -// // See the file "COPYING" in the main distribution directory for copyright. // // Written by Bernhard Ager, TU Berlin (2006/2007). diff --git a/src/FlowSrc.h b/src/FlowSrc.h index 3173badf66..7b0b14ad15 100644 --- a/src/FlowSrc.h +++ b/src/FlowSrc.h @@ -1,5 +1,3 @@ -// $Id: FlowSrc.h 4618 2007-07-09 18:12:32Z bager $ -// // See the file "COPYING" in the main distribution directory for copyright. // // Written by Bernhard Ager, TU Berlin (2006/2007). diff --git a/src/Frag.cc b/src/Frag.cc index abf68baa14..d873f5bc0c 100644 --- a/src/Frag.cc +++ b/src/Frag.cc @@ -1,5 +1,3 @@ -// $Id: Frag.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -29,21 +27,30 @@ void FragTimer::Dispatch(double t, int /* is_expire */) FragReassembler::FragReassembler(NetSessions* arg_s, const IP_Hdr* ip, const u_char* pkt, - uint32 frag_field, HashKey* k, double t) -: Reassembler(0, ip->DstAddr(), REASSEM_IP) + HashKey* k, double t) + : Reassembler(0, REASSEM_IP) { s = arg_s; key = k; + const struct ip* ip4 = ip->IP4_Hdr(); - proto_hdr_len = ip4->ip_hl * 4; - proto_hdr = (struct ip*) new u_char[64]; // max IP header + slop - // Don't do a structure copy - need to pick up options, too. - memcpy((void*) proto_hdr, (const void*) ip4, proto_hdr_len); + if ( ip4 ) + { + proto_hdr_len = ip->HdrLen(); + proto_hdr = new u_char[64]; // max IP header + slop + // Don't do a structure copy - need to pick up options, too. + memcpy((void*) proto_hdr, (const void*) ip4, proto_hdr_len); + } + else + { + proto_hdr_len = ip->HdrLen() - 8; // minus length of fragment header + proto_hdr = new u_char[proto_hdr_len]; + memcpy(proto_hdr, ip->IP6_Hdr(), proto_hdr_len); + } reassembled_pkt = 0; frag_size = 0; // flag meaning "not known" - - AddFragment(t, ip, pkt, frag_field); + next_proto = ip->NextProto(); if ( frag_timeout != 0.0 ) { @@ -52,6 +59,8 @@ FragReassembler::FragReassembler(NetSessions* arg_s, } else expire_timer = 0; + + AddFragment(t, ip, pkt); } FragReassembler::~FragReassembler() @@ -62,28 +71,42 @@ FragReassembler::~FragReassembler() delete key; } -void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt, - uint32 frag_field) +void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt) { const struct ip* ip4 = ip->IP4_Hdr(); - if ( ip4->ip_p != proto_hdr->ip_p || ip4->ip_hl != proto_hdr->ip_hl ) + if ( ip4 ) + { + if ( ip4->ip_p != ((const struct ip*)proto_hdr)->ip_p || + ip4->ip_hl != ((const struct ip*)proto_hdr)->ip_hl ) // || ip4->ip_tos != proto_hdr->ip_tos // don't check TOS, there's at least one stack that actually // uses different values, and it's hard to see an associated // attack. s->Weird("fragment_protocol_inconsistency", ip); + } + else + { + if ( ip->NextProto() != next_proto || + ip->HdrLen() - 8 != proto_hdr_len ) + s->Weird("fragment_protocol_inconsistency", ip); + // TODO: more detailed unfrag header consistency checks? + } - if ( frag_field & 0x4000 ) + if ( ip->DF() ) // Linux MTU discovery for UDP can do this, for example. s->Weird("fragment_with_DF", ip); - int offset = (ntohs(ip4->ip_off) & 0x1fff) * 8; - int len = ntohs(ip4->ip_len); - int hdr_len = proto_hdr->ip_hl * 4; + int offset = ip->FragOffset(); + int len = ip->TotalLen(); + int hdr_len = ip->HdrLen(); int upper_seq = offset + len - hdr_len; - if ( (frag_field & 0x2000) == 0 ) + if ( ! offset ) + // Make sure to use the first fragment header's next field. + next_proto = ip->NextProto(); + + if ( ! ip->MF() ) { // Last fragment. if ( frag_size == 0 ) @@ -127,7 +150,7 @@ void FragReassembler::AddFragment(double t, const IP_Hdr* ip, const u_char* pkt, void FragReassembler::Overlap(const u_char* b1, const u_char* b2, int n) { - IP_Hdr proto_h((const struct ip*) proto_hdr); + IP_Hdr proto_h(proto_hdr, false, proto_hdr_len); if ( memcmp((const void*) b1, (const void*) b2, n) ) s->Weird("fragment_inconsistency", &proto_h); @@ -159,7 +182,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) // can happen for benign reasons when we're // intermingling parts of two fragmented packets. - IP_Hdr proto_h((const struct ip*) proto_hdr); + IP_Hdr proto_h(proto_hdr, false, proto_hdr_len); s->Weird("fragment_size_inconsistency", &proto_h); // We decide to analyze the contiguous portion now. @@ -173,7 +196,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) else if ( last_block->upper > frag_size ) { - IP_Hdr proto_h((const struct ip*) proto_hdr); + IP_Hdr proto_h(proto_hdr, false, proto_hdr_len); s->Weird("fragment_size_inconsistency", &proto_h); frag_size = last_block->upper; } @@ -195,8 +218,7 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) u_char* pkt = new u_char[n]; memcpy((void*) pkt, (const void*) proto_hdr, proto_hdr_len); - struct ip* reassem4 = (struct ip*) pkt; - reassem4->ip_len = htons(frag_size + proto_hdr_len); + u_char* pkt_start = pkt; pkt += proto_hdr_len; @@ -216,7 +238,27 @@ void FragReassembler::BlockInserted(DataBlock* /* start_block */) } delete reassembled_pkt; - reassembled_pkt = new IP_Hdr(reassem4); + + if ( ((const struct ip*)pkt_start)->ip_v == 4 ) + { + struct ip* reassem4 = (struct ip*) pkt_start; + reassem4->ip_len = htons(frag_size + proto_hdr_len); + reassembled_pkt = new IP_Hdr(reassem4, true); + } + + else if ( ((const struct ip*)pkt_start)->ip_v == 6 ) + { + struct ip6_hdr* reassem6 = (struct ip6_hdr*) pkt_start; + reassem6->ip6_plen = htons(frag_size + proto_hdr_len - 40); + const IPv6_Hdr_Chain* chain = new IPv6_Hdr_Chain(reassem6, next_proto, n); + reassembled_pkt = new IP_Hdr(reassem6, true, n, chain); + } + + else + { + reporter->InternalError("bad IP version in fragment reassembly"); + } + DeleteTimer(); } diff --git a/src/Frag.h b/src/Frag.h index ddd5f73144..86cf3a9dd4 100644 --- a/src/Frag.h +++ b/src/Frag.h @@ -1,5 +1,3 @@ -// $Id: Frag.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef frag_h @@ -22,11 +20,10 @@ typedef void (FragReassembler::*frag_timer_func)(double t); class FragReassembler : public Reassembler { public: FragReassembler(NetSessions* s, const IP_Hdr* ip, const u_char* pkt, - uint32 frag_field, HashKey* k, double t); + HashKey* k, double t); ~FragReassembler(); - void AddFragment(double t, const IP_Hdr* ip, const u_char* pkt, - uint32 frag_field); + void AddFragment(double t, const IP_Hdr* ip, const u_char* pkt); void Expire(double t); void DeleteTimer(); @@ -39,11 +36,12 @@ protected: void BlockInserted(DataBlock* start_block); void Overlap(const u_char* b1, const u_char* b2, int n); - struct ip* proto_hdr; + u_char* proto_hdr; IP_Hdr* reassembled_pkt; int proto_hdr_len; NetSessions* s; int frag_size; // size of fully reassembled fragment + uint16 next_proto; // first IPv6 fragment header's next proto field HashKey* key; FragTimer* expire_timer; diff --git a/src/Frame.cc b/src/Frame.cc index 4eeb7e1fcc..f86fa32805 100644 --- a/src/Frame.cc +++ b/src/Frame.cc @@ -1,5 +1,3 @@ -// $Id: Frame.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/Frame.h b/src/Frame.h index 34a4f63f89..85e1dbec2e 100644 --- a/src/Frame.h +++ b/src/Frame.h @@ -1,5 +1,3 @@ -// $Id: Frame.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef frame_h diff --git a/src/Func.cc b/src/Func.cc index 4a495904bd..65cb22b09d 100644 --- a/src/Func.cc +++ b/src/Func.cc @@ -1,5 +1,3 @@ -// $Id: Func.cc 6703 2009-05-13 22:27:44Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -55,6 +53,19 @@ extern RETSIGTYPE sig_handler(int signo); const Expr* calling_expr = 0; bool did_builtin_init = false; +vector Func::unique_ids; + +Func::Func() : scope(0), id(0), return_value(0) + { + unique_id = unique_ids.size(); + unique_ids.push_back(this); + } + +Func::Func(Kind arg_kind) : scope(0), kind(arg_kind), id(0), return_value(0) + { + unique_id = unique_ids.size(); + unique_ids.push_back(this); + } Func::~Func() { @@ -276,6 +287,8 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const { // Can only happen for events. assert(IsEvent()); + loop_over_list(*args, i) + Unref((*args)[i]); return 0 ; } @@ -334,7 +347,7 @@ Val* BroFunc::Call(val_list* args, Frame* parent) const (flow != FLOW_RETURN /* we fell off the end */ || ! result /* explicit return with no result */) && ! f->HasDelayed() ) - reporter->Warning("non-void function returns without a value:", id->Name()); + reporter->Warning("non-void function returns without a value: %s", id->Name()); if ( result && g_trace_state.DoTrace() ) { diff --git a/src/Func.h b/src/Func.h index 6e1ea8597c..909b2a9802 100644 --- a/src/Func.h +++ b/src/Func.h @@ -1,5 +1,3 @@ -// $Id: Func.h 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef func_h @@ -22,8 +20,7 @@ public: enum Kind { BRO_FUNC, BUILTIN_FUNC }; - Func(Kind arg_kind) - { scope = 0; kind = arg_kind; id = 0; return_value = 0; } + Func(Kind arg_kind); virtual ~Func(); @@ -70,8 +67,12 @@ public: ID* GetReturnValueID() const; virtual TraversalCode Traverse(TraversalCallback* cb) const; + uint32 GetUniqueFuncID() const { return unique_id; } + static Func* GetFuncPtrByID(uint32 id) + { return id >= unique_ids.size() ? 0 : unique_ids[id]; } + protected: - Func() { scope = 0; id = 0; return_value = 0; } + Func(); DECLARE_ABSTRACT_SERIAL(Func); @@ -80,6 +81,8 @@ protected: Kind kind; ID* id; ID* return_value; + uint32 unique_id; + static vector unique_ids; }; diff --git a/src/Gnutella.cc b/src/Gnutella.cc index 9787147400..6b5e901bc5 100644 --- a/src/Gnutella.cc +++ b/src/Gnutella.cc @@ -1,5 +1,3 @@ -// $Id: Gnutella.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -44,6 +42,12 @@ Gnutella_Analyzer::Gnutella_Analyzer(Connection* conn) resp_msg_state = new GnutellaMsgState(); } +Gnutella_Analyzer::~Gnutella_Analyzer() + { + delete orig_msg_state; + delete resp_msg_state; + } + void Gnutella_Analyzer::Done() { TCP_ApplicationAnalyzer::Done(); diff --git a/src/Gnutella.h b/src/Gnutella.h index c390f418f4..455876462d 100644 --- a/src/Gnutella.h +++ b/src/Gnutella.h @@ -1,5 +1,3 @@ -// $Id: Gnutella.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef gnutella_h @@ -37,6 +35,7 @@ public: class Gnutella_Analyzer : public TCP_ApplicationAnalyzer { public: Gnutella_Analyzer(Connection* conn); + ~Gnutella_Analyzer(); virtual void Done (); virtual void DeliverStream(int len, const u_char* data, bool orig); diff --git a/src/H3.h b/src/H3.h index b4eab3a727..9e6f1c5c35 100644 --- a/src/H3.h +++ b/src/H3.h @@ -1,5 +1,3 @@ -// $Id: H3.h 3230 2006-06-08 02:19:25Z vern $ - // Copyright 2004, 2005 // The Regents of the University of California // All Rights Reserved diff --git a/src/HTTP-binpac.cc b/src/HTTP-binpac.cc index 003d74d8e2..70cf37457b 100644 --- a/src/HTTP-binpac.cc +++ b/src/HTTP-binpac.cc @@ -1,5 +1,3 @@ -// $Id:$ - #include "HTTP-binpac.h" #include "TCP_Reassembler.h" diff --git a/src/HTTP-binpac.h b/src/HTTP-binpac.h index 9352515dc8..62b6fd0db3 100644 --- a/src/HTTP-binpac.h +++ b/src/HTTP-binpac.h @@ -1,5 +1,3 @@ -// $Id:$ - #ifndef http_binpac_h #define http_binpac_h diff --git a/src/HTTP.cc b/src/HTTP.cc index 54613bb9e1..9d9f01be64 100644 --- a/src/HTTP.cc +++ b/src/HTTP.cc @@ -1,5 +1,3 @@ -// $Id: HTTP.cc 7073 2010-09-13 00:45:02Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -7,6 +5,8 @@ #include #include #include +#include +#include #include "NetVar.h" #include "HTTP.h" @@ -43,9 +43,7 @@ HTTP_Entity::HTTP_Entity(HTTP_Message *arg_message, MIME_Entity* parent_entity, header_length = 0; deliver_body = (http_entity_data != 0); encoding = IDENTITY; -#ifdef HAVE_LIBZ zip = 0; -#endif } void HTTP_Entity::EndOfData() @@ -53,7 +51,6 @@ void HTTP_Entity::EndOfData() if ( DEBUG_http ) DEBUG_MSG("%.6f: end of data\n", network_time); -#ifdef HAVE_LIBZ if ( zip ) { zip->Done(); @@ -61,7 +58,6 @@ void HTTP_Entity::EndOfData() zip = 0; encoding = IDENTITY; } -#endif if ( body_length ) http_message->MyHTTP_Analyzer()-> @@ -179,7 +175,6 @@ private: void HTTP_Entity::DeliverBody(int len, const char* data, int trailing_CRLF) { -#ifdef HAVE_LIBZ if ( encoding == GZIP || encoding == DEFLATE ) { ZIP_Analyzer::Method method = @@ -198,7 +193,6 @@ void HTTP_Entity::DeliverBody(int len, const char* data, int trailing_CRLF) zip->NextStream(len, (const u_char*) data, false); } else -#endif DeliverBodyClear(len, data, trailing_CRLF); } @@ -312,6 +306,67 @@ void HTTP_Entity::SubmitHeader(MIME_Header* h) } } + // Figure out content-length for HTTP 206 Partial Content response + // that uses multipart/byteranges content-type. + else if ( strcasecmp_n(h->get_name(), "content-range") == 0 && Parent() && + Parent()->MIMEContentType() == CONTENT_TYPE_MULTIPART && + http_message->MyHTTP_Analyzer()->HTTP_ReplyCode() == 206 ) + { + data_chunk_t vt = h->get_value_token(); + string byte_unit(vt.data, vt.length); + vt = h->get_value_after_token(); + string byte_range(vt.data, vt.length); + byte_range.erase(remove(byte_range.begin(), byte_range.end(), ' '), + byte_range.end()); + + if ( byte_unit != "bytes" ) + { + http_message->Weird("HTTP_content_range_unknown_byte_unit"); + return; + } + + size_t p = byte_range.find("/"); + if ( p == string::npos ) + { + http_message->Weird("HTTP_content_range_cannot_parse"); + return; + } + + string byte_range_resp_spec = byte_range.substr(0, p); + string instance_length = byte_range.substr(p + 1); + + p = byte_range_resp_spec.find("-"); + if ( p == string::npos ) + { + http_message->Weird("HTTP_content_range_cannot_parse"); + return; + } + + string first_byte_pos = byte_range_resp_spec.substr(0, p); + string last_byte_pos = byte_range_resp_spec.substr(p + 1); + + if ( DEBUG_http ) + DEBUG_MSG("Parsed Content-Range: %s %s-%s/%s\n", byte_unit.c_str(), + first_byte_pos.c_str(), last_byte_pos.c_str(), + instance_length.c_str()); + + int64_t f, l; + atoi_n(first_byte_pos.size(), first_byte_pos.c_str(), 0, 10, f); + atoi_n(last_byte_pos.size(), last_byte_pos.c_str(), 0, 10, l); + int64_t len = l - f + 1; + + if ( DEBUG_http ) + DEBUG_MSG("Content-Range length = %"PRId64"\n", len); + + if ( len > 0 ) + content_length = len; + else + { + http_message->Weird("HTTP_non_positive_content_range"); + return; + } + } + else if ( strcasecmp_n(h->get_name(), "transfer-encoding") == 0 ) { data_chunk_t vt = h->get_value_token(); @@ -389,9 +444,7 @@ void HTTP_Entity::SubmitAllHeaders() // content-length headers or if connection is to be closed afterwards // anyway. else if ( http_message->MyHTTP_Analyzer()->IsConnectionClose () -#ifdef HAVE_LIBZ || encoding == GZIP || encoding == DEFLATE -#endif ) { // FIXME: Using INT_MAX is kind of a hack here. Better @@ -1307,7 +1360,9 @@ void HTTP_Analyzer::ReplyMade(const int interrupted, const char* msg) if ( reply_message ) reply_message->Done(interrupted, msg); - if ( ! unanswered_requests.empty() ) + // 1xx replies do not indicate the final response to a request, + // so don't pop an unanswered request in that case. + if ( (reply_code < 100 || reply_code >= 200) && ! unanswered_requests.empty() ) { Unref(unanswered_requests.front()); unanswered_requests.pop(); @@ -1488,7 +1543,7 @@ void HTTP_Analyzer::HTTP_Header(int is_orig, MIME_Header* h) } } -void HTTP_Analyzer::ParseVersion(data_chunk_t ver, const uint32* host, +void HTTP_Analyzer::ParseVersion(data_chunk_t ver, const IPAddr& host, bool user_agent) { int len = ver.length; diff --git a/src/HTTP.h b/src/HTTP.h index 4d621fa526..c9d8ae55d1 100644 --- a/src/HTTP.h +++ b/src/HTTP.h @@ -1,5 +1,3 @@ -// $Id: HTTP.h 6942 2009-11-16 03:54:08Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef http_h @@ -10,6 +8,7 @@ #include "MIME.h" #include "binpac_bro.h" #include "ZIP.h" +#include "IPAddr.h" enum CHUNKED_TRANSFER_STATE { NON_CHUNKED_TRANSFER, @@ -31,10 +30,8 @@ public: int expect_body); ~HTTP_Entity() { -#ifdef HAVE_LIBZ if ( zip ) { zip->Done(); delete zip; } -#endif } void EndOfData(); @@ -57,9 +54,7 @@ protected: int64_t header_length; int deliver_body; enum { IDENTITY, GZIP, COMPRESS, DEFLATE } encoding; -#ifdef HAVE_LIBZ ZIP_Analyzer* zip; -#endif MIME_Entity* NewChildEntity() { return new HTTP_Entity(http_message, this, 1); } @@ -165,6 +160,9 @@ public: void SkipEntityData(int is_orig); + int IsConnectionClose() { return connection_close; } + int HTTP_ReplyCode() const { return reply_code; }; + // Overriden from Analyzer. virtual void Done(); virtual void DeliverStream(int len, const u_char* data, bool orig); @@ -180,9 +178,10 @@ public: { return new HTTP_Analyzer(conn); } static bool Available() - { return (http_request || http_reply) && !FLAGS_use_binpac; } - - int IsConnectionClose() { return connection_close; } + { return (http_request || http_reply || http_header || + http_all_headers || http_begin_entity || http_end_entity || + http_content_type || http_entity_data || http_message_done || + http_event || http_stats) && !FLAGS_use_binpac; } protected: void GenStats(); @@ -214,7 +213,7 @@ protected: const BroString* UnansweredRequestMethod(); - void ParseVersion(data_chunk_t ver, const uint32* host, bool user_agent); + void ParseVersion(data_chunk_t ver, const IPAddr& host, bool user_agent); int HTTP_ReplyCode(const char* code_str); int ExpectReplyMessageBody(); diff --git a/src/Hash.cc b/src/Hash.cc index 1902af4f37..7873e398c3 100644 --- a/src/Hash.cc +++ b/src/Hash.cc @@ -1,5 +1,3 @@ -// $Id: Hash.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. // The hash function works as follows: diff --git a/src/Hash.h b/src/Hash.h index d9659b442a..00db53d075 100644 --- a/src/Hash.h +++ b/src/Hash.h @@ -1,5 +1,3 @@ -// $Id: Hash.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef hash_h @@ -9,7 +7,7 @@ #include "BroString.h" -#define UHASH_KEY_SIZE 32 +#define UHASH_KEY_SIZE 36 typedef uint64 hash_t; diff --git a/src/ICMP.cc b/src/ICMP.cc index 4e11583651..5e1eeb66e4 100644 --- a/src/ICMP.cc +++ b/src/ICMP.cc @@ -1,5 +1,3 @@ -// $Id: ICMP.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include @@ -11,6 +9,8 @@ #include "Event.h" #include "ICMP.h" +#include + ICMP_Analyzer::ICMP_Analyzer(Connection* c) : TransportLayerAnalyzer(AnalyzerTag::ICMP, c) { @@ -34,7 +34,7 @@ void ICMP_Analyzer::Done() matcher_state.FinishEndpointMatcher(); } -void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data, +void ICMP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, int seq, const IP_Hdr* ip, int caplen) { assert(ip); @@ -48,13 +48,33 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data, PacketContents(data + 8, min(len, caplen) - 8); const struct icmp* icmpp = (const struct icmp*) data; - len = arg_len; - if ( ! ignore_checksums && caplen >= len && - icmp_checksum(icmpp, len) != 0xffff ) + assert(caplen >= len); // Should have been caught earlier already. + + if ( ! ignore_checksums ) { - Weird("bad_ICMP_checksum"); - return; + int chksum = 0; + + switch ( ip->NextProto() ) + { + case IPPROTO_ICMP: + chksum = icmp_checksum(icmpp, len); + break; + + case IPPROTO_ICMPV6: + chksum = icmp6_checksum(icmpp, ip, len); + break; + + default: + reporter->InternalError("unexpected IP proto in ICMP analyzer"); + break; + } + + if ( chksum != 0xffff ) + { + Weird("bad_ICMP_checksum"); + return; + } } Conn()->SetLastTime(current_timestamp); @@ -79,7 +99,13 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data, else len_stat += len; - NextICMP(current_timestamp, icmpp, len, caplen, data); + if ( ip->NextProto() == IPPROTO_ICMP ) + NextICMP4(current_timestamp, icmpp, len, caplen, data, ip); + else if ( ip->NextProto() == IPPROTO_ICMPV6 ) + NextICMP6(current_timestamp, icmpp, len, caplen, data, ip); + else + reporter->InternalError("unexpected next protocol in ICMP::DeliverPacket()"); + if ( caplen >= len ) ForwardPacket(len, data, is_orig, seq, ip, caplen); @@ -89,26 +115,89 @@ void ICMP_Analyzer::DeliverPacket(int arg_len, const u_char* data, false, false, true); } -void ICMP_Analyzer::NextICMP(double /* t */, const struct icmp* /* icmpp */, - int /* len */, int /* caplen */, - const u_char*& /* data */) +void ICMP_Analyzer::NextICMP4(double t, const struct icmp* icmpp, int len, int caplen, + const u_char*& data, const IP_Hdr* ip_hdr ) { - ICMPEvent(icmp_sent); + switch ( icmpp->icmp_type ) + { + case ICMP_ECHO: + case ICMP_ECHOREPLY: + Echo(t, icmpp, len, caplen, data, ip_hdr); + break; + + case ICMP_UNREACH: + case ICMP_TIMXCEED: + Context4(t, icmpp, len, caplen, data, ip_hdr); + break; + + default: + ICMPEvent(icmp_sent, icmpp, len, 0); + break; + } } -void ICMP_Analyzer::ICMPEvent(EventHandlerPtr f) +void ICMP_Analyzer::NextICMP6(double t, const struct icmp* icmpp, int len, int caplen, + const u_char*& data, const IP_Hdr* ip_hdr ) { + switch ( icmpp->icmp_type ) + { + // Echo types. + case ICMP6_ECHO_REQUEST: + case ICMP6_ECHO_REPLY: + Echo(t, icmpp, len, caplen, data, ip_hdr); + break; + + // Error messages all have the same structure for their context, + // and are handled by the same function. + case ICMP6_PARAM_PROB: + case ICMP6_TIME_EXCEEDED: + case ICMP6_PACKET_TOO_BIG: + case ICMP6_DST_UNREACH: + Context6(t, icmpp, len, caplen, data, ip_hdr); + break; + + // Router related messages. + case ND_REDIRECT: + Redirect(t, icmpp, len, caplen, data, ip_hdr); + break; + case ND_ROUTER_ADVERT: + RouterAdvert(t, icmpp, len, caplen, data, ip_hdr); + break; + case ND_NEIGHBOR_ADVERT: + NeighborAdvert(t, icmpp, len, caplen, data, ip_hdr); + break; + case ND_NEIGHBOR_SOLICIT: + NeighborSolicit(t, icmpp, len, caplen, data, ip_hdr); + break; + case ND_ROUTER_SOLICIT: + case ICMP6_ROUTER_RENUMBERING: + Router(t, icmpp, len, caplen, data, ip_hdr); + break; + +#if 0 + // Currently not specifically implemented. + case MLD_LISTENER_QUERY: + case MLD_LISTENER_REPORT: + case MLD_LISTENER_REDUCTION: +#endif + default: + ICMPEvent(icmp_sent, icmpp, len, 1); + break; + } + } + +void ICMP_Analyzer::ICMPEvent(EventHandlerPtr f, const struct icmp* icmpp, int len, int icmpv6) + { if ( ! f ) return; val_list* vl = new val_list; vl->append(BuildConnVal()); - vl->append(BuildICMPVal()); - + vl->append(BuildICMPVal(icmpp, len, icmpv6)); ConnectionEvent(f, vl); } -RecordVal* ICMP_Analyzer::BuildICMPVal() +RecordVal* ICMP_Analyzer::BuildICMPVal(const struct icmp* icmpp, int len, int icmpv6) { if ( ! icmp_conn_val ) { @@ -116,9 +205,10 @@ RecordVal* ICMP_Analyzer::BuildICMPVal() icmp_conn_val->Assign(0, new AddrVal(Conn()->OrigAddr())); icmp_conn_val->Assign(1, new AddrVal(Conn()->RespAddr())); - icmp_conn_val->Assign(2, new Val(type, TYPE_COUNT)); - icmp_conn_val->Assign(3, new Val(code, TYPE_COUNT)); + icmp_conn_val->Assign(2, new Val(icmpp->icmp_type, TYPE_COUNT)); + icmp_conn_val->Assign(3, new Val(icmpp->icmp_code, TYPE_COUNT)); icmp_conn_val->Assign(4, new Val(len, TYPE_COUNT)); + icmp_conn_val->Assign(5, new Val(icmpv6, TYPE_BOOL)); } Ref(icmp_conn_val); @@ -126,91 +216,115 @@ RecordVal* ICMP_Analyzer::BuildICMPVal() return icmp_conn_val; } -RecordVal* ICMP_Analyzer::ExtractICMPContext(int len, const u_char*& data) +TransportProto ICMP_Analyzer::GetContextProtocol(const IP_Hdr* ip_hdr, uint32* src_port, uint32* dst_port) { - const struct ip* ip = (const struct ip *) data; - uint32 ip_hdr_len = ip->ip_hl * 4; + const u_char* transport_hdr; + uint32 ip_hdr_len = ip_hdr->HdrLen(); + bool ip4 = ip_hdr->IP4_Hdr(); + + if ( ip4 ) + transport_hdr = ((u_char *) ip_hdr->IP4_Hdr() + ip_hdr_len); + else + transport_hdr = ((u_char *) ip_hdr->IP6_Hdr() + ip_hdr_len); + + TransportProto proto; + + switch ( ip_hdr->NextProto() ) { + case 1: proto = TRANSPORT_ICMP; break; + case 6: proto = TRANSPORT_TCP; break; + case 17: proto = TRANSPORT_UDP; break; + case 58: proto = TRANSPORT_ICMP; break; + default: proto = TRANSPORT_UNKNOWN; break; + } + + switch ( proto ) { + case TRANSPORT_ICMP: + { + const struct icmp* icmpp = + (const struct icmp *) transport_hdr; + bool is_one_way; // dummy + *src_port = ntohs(icmpp->icmp_type); + + if ( ip4 ) + *dst_port = ntohs(ICMP4_counterpart(icmpp->icmp_type, + icmpp->icmp_code, is_one_way)); + else + *dst_port = ntohs(ICMP6_counterpart(icmpp->icmp_type, + icmpp->icmp_code, is_one_way)); + + break; + } + + case TRANSPORT_TCP: + { + const struct tcphdr* tp = + (const struct tcphdr *) transport_hdr; + *src_port = ntohs(tp->th_sport); + *dst_port = ntohs(tp->th_dport); + break; + } + + case TRANSPORT_UDP: + { + const struct udphdr* up = + (const struct udphdr *) transport_hdr; + *src_port = ntohs(up->uh_sport); + *dst_port = ntohs(up->uh_dport); + break; + } + + default: + *src_port = *dst_port = ntohs(0); + break; + } + + return proto; + } + +RecordVal* ICMP_Analyzer::ExtractICMP4Context(int len, const u_char*& data) + { + const IP_Hdr ip_hdr_data((const struct ip*) data, false); + const IP_Hdr* ip_hdr = &ip_hdr_data; + + uint32 ip_hdr_len = ip_hdr->HdrLen(); uint32 ip_len, frag_offset; TransportProto proto = TRANSPORT_UNKNOWN; int DF, MF, bad_hdr_len, bad_checksum; - uint32 src_addr, dst_addr; + IPAddr src_addr, dst_addr; uint32 src_port, dst_port; - if ( ip_hdr_len < sizeof(struct ip) || ip_hdr_len > uint32(len) ) - { // We don't have an entire IP header. + if ( len < (int)sizeof(struct ip) || ip_hdr_len > uint32(len) ) + { + // We don't have an entire IP header. bad_hdr_len = 1; ip_len = frag_offset = 0; DF = MF = bad_checksum = 0; - src_addr = dst_addr = 0; src_port = dst_port = 0; } else { bad_hdr_len = 0; - ip_len = ntohs(ip->ip_len); - bad_checksum = ones_complement_checksum((void*) ip, ip_hdr_len, 0) != 0xffff; + ip_len = ip_hdr->TotalLen(); + bad_checksum = (ones_complement_checksum((void*) ip_hdr->IP4_Hdr(), ip_hdr_len, 0) != 0xffff); - src_addr = uint32(ip->ip_src.s_addr); - dst_addr = uint32(ip->ip_dst.s_addr); + src_addr = ip_hdr->SrcAddr(); + dst_addr = ip_hdr->DstAddr(); - switch ( ip->ip_p ) { - case 1: proto = TRANSPORT_ICMP; break; - case 6: proto = TRANSPORT_TCP; break; - case 17: proto = TRANSPORT_UDP; break; + DF = ip_hdr->DF(); + MF = ip_hdr->MF(); + frag_offset = ip_hdr->FragOffset(); - // Default uses TRANSPORT_UNKNOWN, per initialization above. - } - - uint32 frag_field = ntohs(ip->ip_off); - DF = frag_field & 0x4000; - MF = frag_field & 0x2000; - frag_offset = frag_field & /* IP_OFFMASK not portable */ 0x1fff; - const u_char* transport_hdr = ((u_char *) ip + ip_hdr_len); - - if ( uint32(len) < ip_hdr_len + 4 ) + if ( uint32(len) >= ip_hdr_len + 4 ) + proto = GetContextProtocol(ip_hdr, &src_port, &dst_port); + else { // 4 above is the magic number meaning that both // port numbers are included in the ICMP. - bad_hdr_len = 1; src_port = dst_port = 0; + bad_hdr_len = 1; } - - switch ( proto ) { - case TRANSPORT_ICMP: - { - const struct icmp* icmpp = - (const struct icmp *) transport_hdr; - bool is_one_way; // dummy - src_port = ntohs(icmpp->icmp_type); - dst_port = ntohs(ICMP_counterpart(icmpp->icmp_type, - icmpp->icmp_code, - is_one_way)); - } - break; - - case TRANSPORT_TCP: - { - const struct tcphdr* tp = - (const struct tcphdr *) transport_hdr; - src_port = ntohs(tp->th_sport); - dst_port = ntohs(tp->th_dport); - } - break; - - case TRANSPORT_UDP: - { - const struct udphdr* up = - (const struct udphdr *) transport_hdr; - src_port = ntohs(up->uh_sport); - dst_port = ntohs(up->uh_dport); - } - break; - - default: - src_port = dst_port = ntohs(0); - } } RecordVal* iprec = new RecordVal(icmp_context); @@ -220,8 +334,8 @@ RecordVal* ICMP_Analyzer::ExtractICMPContext(int len, const u_char*& data) id_val->Assign(1, new PortVal(src_port, proto)); id_val->Assign(2, new AddrVal(dst_addr)); id_val->Assign(3, new PortVal(dst_port, proto)); - iprec->Assign(0, id_val); + iprec->Assign(0, id_val); iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); iprec->Assign(2, new Val(proto, TYPE_COUNT)); iprec->Assign(3, new Val(frag_offset, TYPE_COUNT)); @@ -233,6 +347,66 @@ RecordVal* ICMP_Analyzer::ExtractICMPContext(int len, const u_char*& data) return iprec; } +RecordVal* ICMP_Analyzer::ExtractICMP6Context(int len, const u_char*& data) + { + int DF = 0, MF = 0, bad_hdr_len = 0; + TransportProto proto = TRANSPORT_UNKNOWN; + + IPAddr src_addr; + IPAddr dst_addr; + uint32 ip_len, frag_offset = 0; + uint32 src_port, dst_port; + + if ( len < (int)sizeof(struct ip6_hdr) ) + { + bad_hdr_len = 1; + ip_len = 0; + src_port = dst_port = 0; + } + else + { + const IP_Hdr ip_hdr_data((const struct ip6_hdr*) data, false, len); + const IP_Hdr* ip_hdr = &ip_hdr_data; + + ip_len = ip_hdr->TotalLen(); + src_addr = ip_hdr->SrcAddr(); + dst_addr = ip_hdr->DstAddr(); + frag_offset = ip_hdr->FragOffset(); + MF = ip_hdr->MF(); + DF = ip_hdr->DF(); + + if ( uint32(len) >= uint32(ip_hdr->HdrLen() + 4) ) + proto = GetContextProtocol(ip_hdr, &src_port, &dst_port); + else + { + // 4 above is the magic number meaning that both + // port numbers are included in the ICMP. + src_port = dst_port = 0; + bad_hdr_len = 1; + } + } + + RecordVal* iprec = new RecordVal(icmp_context); + RecordVal* id_val = new RecordVal(conn_id); + + id_val->Assign(0, new AddrVal(src_addr)); + id_val->Assign(1, new PortVal(src_port, proto)); + id_val->Assign(2, new AddrVal(dst_addr)); + id_val->Assign(3, new PortVal(dst_port, proto)); + + iprec->Assign(0, id_val); + iprec->Assign(1, new Val(ip_len, TYPE_COUNT)); + iprec->Assign(2, new Val(proto, TYPE_COUNT)); + iprec->Assign(3, new Val(frag_offset, TYPE_COUNT)); + iprec->Assign(4, new Val(bad_hdr_len, TYPE_BOOL)); + // bad_checksum is always false since IPv6 layer doesn't have a checksum. + iprec->Assign(5, new Val(0, TYPE_BOOL)); + iprec->Assign(6, new Val(MF, TYPE_BOOL)); + iprec->Assign(7, new Val(DF, TYPE_BOOL)); + + return iprec; + } + bool ICMP_Analyzer::IsReuse(double /* t */, const u_char* /* pkt */) { return 0; @@ -245,7 +419,7 @@ void ICMP_Analyzer::Describe(ODesc* d) const d->Add(Conn()->LastTime()); d->AddSP(")"); - d->Add(dotted_addr(Conn()->OrigAddr())); + d->Add(Conn()->OrigAddr()); d->Add("."); d->Add(type); d->Add("."); @@ -254,7 +428,7 @@ void ICMP_Analyzer::Describe(ODesc* d) const d->SP(); d->AddSP("->"); - d->Add(dotted_addr(Conn()->RespAddr())); + d->Add(Conn()->RespAddr()); } void ICMP_Analyzer::UpdateConnVal(RecordVal *conn_val) @@ -296,15 +470,20 @@ unsigned int ICMP_Analyzer::MemoryAllocation() const + (icmp_conn_val ? icmp_conn_val->MemoryAllocation() : 0); } -ICMP_Echo_Analyzer::ICMP_Echo_Analyzer(Connection* c) -: ICMP_Analyzer(AnalyzerTag::ICMP_Echo, c) - { - } -void ICMP_Echo_Analyzer::NextICMP(double t, const struct icmp* icmpp, int len, - int caplen, const u_char*& data) +void ICMP_Analyzer::Echo(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr) { - EventHandlerPtr f = type == ICMP_ECHO ? icmp_echo_request : icmp_echo_reply; + // For handling all Echo related ICMP messages + EventHandlerPtr f = 0; + + if ( ip_hdr->NextProto() == IPPROTO_ICMPV6 ) + f = (icmpp->icmp_type == ICMP6_ECHO_REQUEST) + ? icmp_echo_request : icmp_echo_reply; + else + f = (icmpp->icmp_type == ICMP_ECHO) + ? icmp_echo_request : icmp_echo_reply; + if ( ! f ) return; @@ -315,7 +494,7 @@ void ICMP_Echo_Analyzer::NextICMP(double t, const struct icmp* icmpp, int len, val_list* vl = new val_list; vl->append(BuildConnVal()); - vl->append(BuildICMPVal()); + vl->append(BuildICMPVal(icmpp, len, ip_hdr->NextProto() != IPPROTO_ICMP)); vl->append(new Val(iid, TYPE_COUNT)); vl->append(new Val(iseq, TYPE_COUNT)); vl->append(new StringVal(payload)); @@ -323,66 +502,224 @@ void ICMP_Echo_Analyzer::NextICMP(double t, const struct icmp* icmpp, int len, ConnectionEvent(f, vl); } -ICMP_Redir_Analyzer::ICMP_Redir_Analyzer(Connection* c) -: ICMP_Analyzer(AnalyzerTag::ICMP_Redir, c) - { - } -void ICMP_Redir_Analyzer::NextICMP(double t, const struct icmp* icmpp, int len, - int caplen, const u_char*& data) +void ICMP_Analyzer::RouterAdvert(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/) { - uint32 addr = ntohl(icmpp->icmp_hun.ih_void); + EventHandlerPtr f = icmp_router_advertisement; + uint32 reachable, retrans; + + memcpy(&reachable, data, sizeof(reachable)); + memcpy(&retrans, data + sizeof(reachable), sizeof(retrans)); val_list* vl = new val_list; vl->append(BuildConnVal()); - vl->append(BuildICMPVal()); - vl->append(new AddrVal(htonl(addr))); + vl->append(BuildICMPVal(icmpp, len, 1)); + vl->append(new Val(icmpp->icmp_num_addrs, TYPE_COUNT)); + vl->append(new Val(icmpp->icmp_wpa & 0x80, TYPE_BOOL)); + vl->append(new Val(htons(icmpp->icmp_lifetime), TYPE_COUNT)); + vl->append(new Val(reachable, TYPE_INTERVAL)); + vl->append(new Val(retrans, TYPE_INTERVAL)); - ConnectionEvent(icmp_redirect, vl); + ConnectionEvent(f, vl); } -void ICMP_Context_Analyzer::NextICMP(double t, const struct icmp* icmpp, - int len, int caplen, const u_char*& data) +void ICMP_Analyzer::NeighborAdvert(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/) + { + EventHandlerPtr f = icmp_neighbor_advertisement; + in6_addr tgtaddr; + + memcpy(&tgtaddr.s6_addr, data, sizeof(tgtaddr.s6_addr)); + + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(icmpp, len, 1)); + vl->append(new AddrVal(IPAddr(tgtaddr))); + + ConnectionEvent(f, vl); + } + + +void ICMP_Analyzer::NeighborSolicit(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/) + { + EventHandlerPtr f = icmp_neighbor_solicitation; + in6_addr tgtaddr; + + memcpy(&tgtaddr.s6_addr, data, sizeof(tgtaddr.s6_addr)); + + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(icmpp, len, 1)); + vl->append(new AddrVal(IPAddr(tgtaddr))); + + ConnectionEvent(f, vl); + } + + +void ICMP_Analyzer::Redirect(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/) + { + EventHandlerPtr f = icmp_redirect; + in6_addr tgtaddr, dstaddr; + + memcpy(&tgtaddr.s6_addr, data, sizeof(tgtaddr.s6_addr)); + memcpy(&dstaddr.s6_addr, data + sizeof(tgtaddr.s6_addr), sizeof(dstaddr.s6_addr)); + + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(icmpp, len, 1)); + vl->append(new AddrVal(IPAddr(tgtaddr))); + vl->append(new AddrVal(IPAddr(dstaddr))); + + ConnectionEvent(f, vl); + } + + +void ICMP_Analyzer::Router(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* /*ip_hdr*/) { EventHandlerPtr f = 0; - switch ( type ) { - case ICMP_UNREACH: f = icmp_unreachable; break; - case ICMP_TIMXCEED: f = icmp_time_exceeded; break; + + switch ( icmpp->icmp_type ) + { + case ND_ROUTER_SOLICIT: + f = icmp_router_solicitation; + break; + case ICMP6_ROUTER_RENUMBERING: + default: + ICMPEvent(icmp_sent, icmpp, len, 1); + return; + } + + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(icmpp, len, 1)); + + ConnectionEvent(f, vl); } + +void ICMP_Analyzer::Context4(double t, const struct icmp* icmpp, + int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr) + { + EventHandlerPtr f = 0; + + switch ( icmpp->icmp_type ) + { + case ICMP_UNREACH: + f = icmp_unreachable; + break; + + case ICMP_TIMXCEED: + f = icmp_time_exceeded; + break; + } + if ( f ) { val_list* vl = new val_list; vl->append(BuildConnVal()); - vl->append(BuildICMPVal()); - vl->append(new Val(code, TYPE_COUNT)); - vl->append(ExtractICMPContext(caplen, data)); - + vl->append(BuildICMPVal(icmpp, len, 0)); + vl->append(new Val(icmpp->icmp_code, TYPE_COUNT)); + vl->append(ExtractICMP4Context(caplen, data)); ConnectionEvent(f, vl); } } -int ICMP_counterpart(int icmp_type, int icmp_code, bool& is_one_way) +void ICMP_Analyzer::Context6(double t, const struct icmp* icmpp, + int len, int caplen, const u_char*& data, const IP_Hdr* ip_hdr) + { + EventHandlerPtr f = 0; + + switch ( icmpp->icmp_type ) + { + case ICMP6_DST_UNREACH: + f = icmp_unreachable; + break; + + case ICMP6_PARAM_PROB: + f = icmp_parameter_problem; + break; + + case ICMP6_TIME_EXCEEDED: + f = icmp_time_exceeded; + break; + + case ICMP6_PACKET_TOO_BIG: + f = icmp_packet_too_big; + break; + } + + if ( f ) + { + val_list* vl = new val_list; + vl->append(BuildConnVal()); + vl->append(BuildICMPVal(icmpp, len, 1)); + vl->append(new Val(icmpp->icmp_code, TYPE_COUNT)); + vl->append(ExtractICMP6Context(caplen, data)); + ConnectionEvent(f, vl); + } + } + +int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way) { is_one_way = false; - // return the counterpart type if one exists. This allows us + // Return the counterpart type if one exists. This allows us // to track corresponding ICMP requests/replies. // Note that for the two-way ICMP messages, icmp_code is // always 0 (RFC 792). switch ( icmp_type ) { case ICMP_ECHO: return ICMP_ECHOREPLY; case ICMP_ECHOREPLY: return ICMP_ECHO; + case ICMP_TSTAMP: return ICMP_TSTAMPREPLY; case ICMP_TSTAMPREPLY: return ICMP_TSTAMP; + case ICMP_IREQ: return ICMP_IREQREPLY; case ICMP_IREQREPLY: return ICMP_IREQ; + case ICMP_ROUTERSOLICIT: return ICMP_ROUTERADVERT; + case ICMP_MASKREQ: return ICMP_MASKREPLY; case ICMP_MASKREPLY: return ICMP_MASKREQ; default: is_one_way = true; return icmp_code; } } + +int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way) + { + is_one_way = false; + + switch ( icmp_type ) { + case ICMP6_ECHO_REQUEST: return ICMP6_ECHO_REPLY; + case ICMP6_ECHO_REPLY: return ICMP6_ECHO_REQUEST; + + case ND_ROUTER_SOLICIT: return ND_ROUTER_ADVERT; + case ND_ROUTER_ADVERT: return ND_ROUTER_SOLICIT; + + case ND_NEIGHBOR_SOLICIT: return ND_NEIGHBOR_ADVERT; + case ND_NEIGHBOR_ADVERT: return ND_NEIGHBOR_SOLICIT; + + case MLD_LISTENER_QUERY: return MLD_LISTENER_REPORT; + case MLD_LISTENER_REPORT: return MLD_LISTENER_QUERY; + + // ICMP node information query and response respectively (not defined in + // icmp6.h) + case 139: return 140; + case 140: return 139; + + // Home Agent Address Discovery Request Message and reply + case 144: return 145; + case 145: return 144; + + // TODO: Add further counterparts. + + default: is_one_way = true; return icmp_code; + } + } diff --git a/src/ICMP.h b/src/ICMP.h index 62b859beba..59a399f74f 100644 --- a/src/ICMP.h +++ b/src/ICMP.h @@ -1,5 +1,3 @@ -// $Id: ICMP.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef icmp_h @@ -35,21 +33,49 @@ protected: virtual bool IsReuse(double t, const u_char* pkt); virtual unsigned int MemoryAllocation() const; - void ICMPEvent(EventHandlerPtr f); + void ICMPEvent(EventHandlerPtr f, const struct icmp* icmpp, int len, int icmpv6); + + void Echo(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void Context(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void Redirect(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void RouterAdvert(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void NeighborAdvert(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void NeighborSolicit(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void Router(double t, const struct icmp* icmpp, int len, + int caplen, const u_char*& data, const IP_Hdr* ip_hdr); + void Describe(ODesc* d) const; - RecordVal* BuildICMPVal(); + RecordVal* BuildICMPVal(const struct icmp* icmpp, int len, int icmpv6); - virtual void NextICMP(double t, const struct icmp* icmpp, - int len, int caplen, const u_char*& data); + void NextICMP4(double t, const struct icmp* icmpp, int len, int caplen, + const u_char*& data, const IP_Hdr* ip_hdr ); - RecordVal* ExtractICMPContext(int len, const u_char*& data); + RecordVal* ExtractICMP4Context(int len, const u_char*& data); + + void Context4(double t, const struct icmp* icmpp, int len, int caplen, + const u_char*& data, const IP_Hdr* ip_hdr); + + TransportProto GetContextProtocol(const IP_Hdr* ip_hdr, uint32* src_port, + uint32* dst_port); + + void NextICMP6(double t, const struct icmp* icmpp, int len, int caplen, + const u_char*& data, const IP_Hdr* ip_hdr ); + + RecordVal* ExtractICMP6Context(int len, const u_char*& data); + + void Context6(double t, const struct icmp* icmpp, int len, int caplen, + const u_char*& data, const IP_Hdr* ip_hdr); RecordVal* icmp_conn_val; int type; int code; - int len; - int request_len, reply_len; RuleMatcherState matcher_state; @@ -58,81 +84,9 @@ private: void UpdateEndpointVal(RecordVal* endp, int is_orig); }; -class ICMP_Echo_Analyzer : public ICMP_Analyzer { -public: - ICMP_Echo_Analyzer(Connection* conn); - - static Analyzer* InstantiateAnalyzer(Connection* conn) - { return new ICMP_Echo_Analyzer(conn); } - - static bool Available() { return icmp_echo_request || icmp_echo_reply; } - -protected: - ICMP_Echo_Analyzer() { } - - virtual void NextICMP(double t, const struct icmp* icmpp, - int len, int caplen, const u_char*& data); -}; - -class ICMP_Redir_Analyzer : public ICMP_Analyzer { -public: - ICMP_Redir_Analyzer(Connection* conn); - - static Analyzer* InstantiateAnalyzer(Connection* conn) - { return new ICMP_Redir_Analyzer(conn); } - - static bool Available() { return icmp_redirect; } - -protected: - ICMP_Redir_Analyzer() { } - - virtual void NextICMP(double t, const struct icmp* icmpp, - int len, int caplen, const u_char*& data); -}; - -class ICMP_Context_Analyzer : public ICMP_Analyzer { -public: - ICMP_Context_Analyzer(AnalyzerTag::Tag tag, Connection* conn) - : ICMP_Analyzer(tag, conn) { } - -protected: - ICMP_Context_Analyzer() { } - - virtual void NextICMP(double t, const struct icmp* icmpp, - int len, int caplen, const u_char*& data); -}; - -class ICMP_TimeExceeded_Analyzer : public ICMP_Context_Analyzer { -public: - ICMP_TimeExceeded_Analyzer(Connection* conn) - : ICMP_Context_Analyzer(AnalyzerTag::ICMP_TimeExceeded, conn) { } - - static Analyzer* InstantiateAnalyzer(Connection* conn) - { return new ICMP_TimeExceeded_Analyzer(conn); } - - static bool Available() { return icmp_time_exceeded; } - -protected: - ICMP_TimeExceeded_Analyzer() { } -}; - -class ICMP_Unreachable_Analyzer : public ICMP_Context_Analyzer { -public: - ICMP_Unreachable_Analyzer(Connection* conn) - : ICMP_Context_Analyzer(AnalyzerTag::ICMP_Unreachable, conn) { } - - static Analyzer* InstantiateAnalyzer(Connection* conn) - { return new ICMP_Unreachable_Analyzer(conn); } - - static bool Available() { return icmp_unreachable; } - -protected: - ICMP_Unreachable_Analyzer() { } -}; - - // Returns the counterpart type to the given type (e.g., the counterpart // to ICMP_ECHOREPLY is ICMP_ECHO). -extern int ICMP_counterpart(int icmp_type, int icmp_code, bool& is_one_way); +extern int ICMP4_counterpart(int icmp_type, int icmp_code, bool& is_one_way); +extern int ICMP6_counterpart(int icmp_type, int icmp_code, bool& is_one_way); #endif diff --git a/src/ID.cc b/src/ID.cc index 2decef725f..a70aa3fd0e 100644 --- a/src/ID.cc +++ b/src/ID.cc @@ -1,5 +1,3 @@ -// $Id: ID.cc 6724 2009-06-07 09:23:03Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -374,7 +372,7 @@ ID* ID::Unserialize(UnserialInfo* info) Ref(id); global_scope()->Insert(id->Name(), id); -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG heap_checker->IgnoreObject(id); #endif } diff --git a/src/ID.h b/src/ID.h index 49d844ebc3..9c1f56e80f 100644 --- a/src/ID.h +++ b/src/ID.h @@ -1,5 +1,3 @@ -// $Id: ID.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef id_h diff --git a/src/IOSource.cc b/src/IOSource.cc index 83f4ef15f2..d47007caad 100644 --- a/src/IOSource.cc +++ b/src/IOSource.cc @@ -1,5 +1,3 @@ -// $Id: IOSource.cc 4771 2007-08-11 05:50:24Z vern $ - #include #include #include diff --git a/src/IOSource.h b/src/IOSource.h index 53057f3583..db50bbd2a9 100644 --- a/src/IOSource.h +++ b/src/IOSource.h @@ -1,5 +1,3 @@ -// $Id: IOSource.h 6888 2009-08-20 18:23:11Z vern $ -// // Interface for classes providing/consuming data during Bro's main loop. #ifndef iosource_h diff --git a/src/IP.cc b/src/IP.cc new file mode 100644 index 0000000000..f5598600d5 --- /dev/null +++ b/src/IP.cc @@ -0,0 +1,627 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "IP.h" +#include "Type.h" +#include "Val.h" +#include "Var.h" + +static RecordType* ip4_hdr_type = 0; +static RecordType* ip6_hdr_type = 0; +static RecordType* ip6_ext_hdr_type = 0; +static RecordType* ip6_option_type = 0; +static RecordType* ip6_hopopts_type = 0; +static RecordType* ip6_dstopts_type = 0; +static RecordType* ip6_routing_type = 0; +static RecordType* ip6_fragment_type = 0; +static RecordType* ip6_ah_type = 0; +static RecordType* ip6_esp_type = 0; +static RecordType* ip6_mob_type = 0; +static RecordType* ip6_mob_msg_type = 0; +static RecordType* ip6_mob_brr_type = 0; +static RecordType* ip6_mob_hoti_type = 0; +static RecordType* ip6_mob_coti_type = 0; +static RecordType* ip6_mob_hot_type = 0; +static RecordType* ip6_mob_cot_type = 0; +static RecordType* ip6_mob_bu_type = 0; +static RecordType* ip6_mob_back_type = 0; +static RecordType* ip6_mob_be_type = 0; + +static inline RecordType* hdrType(RecordType*& type, const char* name) + { + if ( ! type ) + type = internal_type(name)->AsRecordType(); + + return type; + } + +static VectorVal* BuildOptionsVal(const u_char* data, int len) + { + VectorVal* vv = new VectorVal(new VectorType( + hdrType(ip6_option_type, "ip6_option")->Ref())); + + while ( len > 0 ) + { + const struct ip6_opt* opt = (const struct ip6_opt*) data; + RecordVal* rv = new RecordVal(ip6_option_type); + rv->Assign(0, new Val(opt->ip6o_type, TYPE_COUNT)); + + if ( opt->ip6o_type == 0 ) + { + // Pad1 option + rv->Assign(1, new Val(0, TYPE_COUNT)); + rv->Assign(2, new StringVal("")); + data += sizeof(uint8); + len -= sizeof(uint8); + } + else + { + // PadN or other option + uint16 off = 2 * sizeof(uint8); + rv->Assign(1, new Val(opt->ip6o_len, TYPE_COUNT)); + rv->Assign(2, new StringVal( + new BroString(data + off, opt->ip6o_len, 1))); + data += opt->ip6o_len + off; + len -= opt->ip6o_len + off; + } + + vv->Assign(vv->Size(), rv, 0); + } + + return vv; + } + +RecordVal* IPv6_Hdr::BuildRecordVal(VectorVal* chain) const + { + RecordVal* rv = 0; + + switch ( type ) { + case IPPROTO_IPV6: + { + rv = new RecordVal(hdrType(ip6_hdr_type, "ip6_hdr")); + const struct ip6_hdr* ip6 = (const struct ip6_hdr*)data; + rv->Assign(0, new Val((ntohl(ip6->ip6_flow) & 0x0ff00000)>>20, TYPE_COUNT)); + rv->Assign(1, new Val(ntohl(ip6->ip6_flow) & 0x000fffff, TYPE_COUNT)); + rv->Assign(2, new Val(ntohs(ip6->ip6_plen), TYPE_COUNT)); + rv->Assign(3, new Val(ip6->ip6_nxt, TYPE_COUNT)); + rv->Assign(4, new Val(ip6->ip6_hlim, TYPE_COUNT)); + rv->Assign(5, new AddrVal(IPAddr(ip6->ip6_src))); + rv->Assign(6, new AddrVal(IPAddr(ip6->ip6_dst))); + if ( ! chain ) + chain = new VectorVal(new VectorType( + hdrType(ip6_ext_hdr_type, "ip6_ext_hdr")->Ref())); + rv->Assign(7, chain); + } + break; + + case IPPROTO_HOPOPTS: + { + rv = new RecordVal(hdrType(ip6_hopopts_type, "ip6_hopopts")); + const struct ip6_hbh* hbh = (const struct ip6_hbh*)data; + rv->Assign(0, new Val(hbh->ip6h_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(hbh->ip6h_len, TYPE_COUNT)); + uint16 off = 2 * sizeof(uint8); + rv->Assign(2, BuildOptionsVal(data + off, Length() - off)); + + } + break; + + case IPPROTO_DSTOPTS: + { + rv = new RecordVal(hdrType(ip6_dstopts_type, "ip6_dstopts")); + const struct ip6_dest* dst = (const struct ip6_dest*)data; + rv->Assign(0, new Val(dst->ip6d_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(dst->ip6d_len, TYPE_COUNT)); + uint16 off = 2 * sizeof(uint8); + rv->Assign(2, BuildOptionsVal(data + off, Length() - off)); + } + break; + + case IPPROTO_ROUTING: + { + rv = new RecordVal(hdrType(ip6_routing_type, "ip6_routing")); + const struct ip6_rthdr* rt = (const struct ip6_rthdr*)data; + rv->Assign(0, new Val(rt->ip6r_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(rt->ip6r_len, TYPE_COUNT)); + rv->Assign(2, new Val(rt->ip6r_type, TYPE_COUNT)); + rv->Assign(3, new Val(rt->ip6r_segleft, TYPE_COUNT)); + uint16 off = 4 * sizeof(uint8); + rv->Assign(4, new StringVal(new BroString(data + off, Length() - off, 1))); + } + break; + + case IPPROTO_FRAGMENT: + { + rv = new RecordVal(hdrType(ip6_fragment_type, "ip6_fragment")); + const struct ip6_frag* frag = (const struct ip6_frag*)data; + rv->Assign(0, new Val(frag->ip6f_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(frag->ip6f_reserved, TYPE_COUNT)); + rv->Assign(2, new Val((ntohs(frag->ip6f_offlg) & 0xfff8)>>3, TYPE_COUNT)); + rv->Assign(3, new Val((ntohs(frag->ip6f_offlg) & 0x0006)>>1, TYPE_COUNT)); + rv->Assign(4, new Val(ntohs(frag->ip6f_offlg) & 0x0001, TYPE_BOOL)); + rv->Assign(5, new Val(ntohl(frag->ip6f_ident), TYPE_COUNT)); + } + break; + + case IPPROTO_AH: + { + rv = new RecordVal(hdrType(ip6_ah_type, "ip6_ah")); + rv->Assign(0, new Val(((ip6_ext*)data)->ip6e_nxt, TYPE_COUNT)); + rv->Assign(1, new Val(((ip6_ext*)data)->ip6e_len, TYPE_COUNT)); + rv->Assign(2, new Val(ntohs(((uint16*)data)[1]), TYPE_COUNT)); + rv->Assign(3, new Val(ntohl(((uint32*)data)[1]), TYPE_COUNT)); + rv->Assign(4, new Val(ntohl(((uint32*)data)[2]), TYPE_COUNT)); + uint16 off = 3 * sizeof(uint32); + rv->Assign(5, new StringVal(new BroString(data + off, Length() - off, 1))); + } + break; + + case IPPROTO_ESP: + { + rv = new RecordVal(hdrType(ip6_esp_type, "ip6_esp")); + const uint32* esp = (const uint32*)data; + rv->Assign(0, new Val(ntohl(esp[0]), TYPE_COUNT)); + rv->Assign(1, new Val(ntohl(esp[1]), TYPE_COUNT)); + } + break; + +#ifdef ENABLE_MOBILE_IPV6 + case IPPROTO_MOBILITY: + { + rv = new RecordVal(hdrType(ip6_mob_type, "ip6_mobility_hdr")); + const struct ip6_mobility* mob = (const struct ip6_mobility*) data; + rv->Assign(0, new Val(mob->ip6mob_payload, TYPE_COUNT)); + rv->Assign(1, new Val(mob->ip6mob_len, TYPE_COUNT)); + rv->Assign(2, new Val(mob->ip6mob_type, TYPE_COUNT)); + rv->Assign(3, new Val(mob->ip6mob_rsv, TYPE_COUNT)); + rv->Assign(4, new Val(ntohs(mob->ip6mob_chksum), TYPE_COUNT)); + + RecordVal* msg = new RecordVal(hdrType(ip6_mob_msg_type, "ip6_mobility_msg")); + msg->Assign(0, new Val(mob->ip6mob_type, TYPE_COUNT)); + + uint16 off = sizeof(ip6_mobility); + const u_char* msg_data = data + off; + + switch ( mob->ip6mob_type ) { + case 0: + { + RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_brr")); + m->Assign(0, new Val(ntohs(*((uint16*)msg_data)), TYPE_COUNT)); + off += sizeof(uint16); + m->Assign(1, BuildOptionsVal(data + off, Length() - off)); + msg->Assign(1, m); + } + break; + + case 1: + { + RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_hoti")); + m->Assign(0, new Val(ntohs(*((uint16*)msg_data)), TYPE_COUNT)); + m->Assign(1, new Val(ntohll(*((uint64*)(msg_data + sizeof(uint16)))), TYPE_COUNT)); + off += sizeof(uint16) + sizeof(uint64); + m->Assign(2, BuildOptionsVal(data + off, Length() - off)); + msg->Assign(2, m); + break; + } + + case 2: + { + RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_coti")); + m->Assign(0, new Val(ntohs(*((uint16*)msg_data)), TYPE_COUNT)); + m->Assign(1, new Val(ntohll(*((uint64*)(msg_data + sizeof(uint16)))), TYPE_COUNT)); + off += sizeof(uint16) + sizeof(uint64); + m->Assign(2, BuildOptionsVal(data + off, Length() - off)); + msg->Assign(3, m); + break; + } + + case 3: + { + RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_hot")); + m->Assign(0, new Val(ntohs(*((uint16*)msg_data)), TYPE_COUNT)); + m->Assign(1, new Val(ntohll(*((uint64*)(msg_data + sizeof(uint16)))), TYPE_COUNT)); + m->Assign(2, new Val(ntohll(*((uint64*)(msg_data + sizeof(uint16) + sizeof(uint64)))), TYPE_COUNT)); + off += sizeof(uint16) + 2 * sizeof(uint64); + m->Assign(3, BuildOptionsVal(data + off, Length() - off)); + msg->Assign(4, m); + break; + } + + case 4: + { + RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_cot")); + m->Assign(0, new Val(ntohs(*((uint16*)msg_data)), TYPE_COUNT)); + m->Assign(1, new Val(ntohll(*((uint64*)(msg_data + sizeof(uint16)))), TYPE_COUNT)); + m->Assign(2, new Val(ntohll(*((uint64*)(msg_data + sizeof(uint16) + sizeof(uint64)))), TYPE_COUNT)); + off += sizeof(uint16) + 2 * sizeof(uint64); + m->Assign(3, BuildOptionsVal(data + off, Length() - off)); + msg->Assign(5, m); + break; + } + + case 5: + { + RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_bu")); + m->Assign(0, new Val(ntohs(*((uint16*)msg_data)), TYPE_COUNT)); + m->Assign(1, new Val(ntohs(*((uint16*)(msg_data + sizeof(uint16)))) & 0x8000, TYPE_BOOL)); + m->Assign(2, new Val(ntohs(*((uint16*)(msg_data + sizeof(uint16)))) & 0x4000, TYPE_BOOL)); + m->Assign(3, new Val(ntohs(*((uint16*)(msg_data + sizeof(uint16)))) & 0x2000, TYPE_BOOL)); + m->Assign(4, new Val(ntohs(*((uint16*)(msg_data + sizeof(uint16)))) & 0x1000, TYPE_BOOL)); + m->Assign(5, new Val(ntohs(*((uint16*)(msg_data + 2*sizeof(uint16)))), TYPE_COUNT)); + off += 3 * sizeof(uint16); + m->Assign(6, BuildOptionsVal(data + off, Length() - off)); + msg->Assign(6, m); + break; + } + + case 6: + { + RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_back")); + m->Assign(0, new Val(*((uint8*)msg_data), TYPE_COUNT)); + m->Assign(1, new Val(*((uint8*)(msg_data + sizeof(uint8))) & 0x80, TYPE_BOOL)); + m->Assign(2, new Val(ntohs(*((uint16*)(msg_data + sizeof(uint16)))), TYPE_COUNT)); + m->Assign(3, new Val(ntohs(*((uint16*)(msg_data + 2*sizeof(uint16)))), TYPE_COUNT)); + off += 3 * sizeof(uint16); + m->Assign(4, BuildOptionsVal(data + off, Length() - off)); + msg->Assign(7, m); + break; + } + + case 7: + { + RecordVal* m = new RecordVal(hdrType(ip6_mob_brr_type, "ip6_mobility_be")); + m->Assign(0, new Val(*((uint8*)msg_data), TYPE_COUNT)); + const in6_addr* hoa = (const in6_addr*)(msg_data + sizeof(uint16)); + m->Assign(1, new AddrVal(IPAddr(*hoa))); + off += sizeof(uint16) + sizeof(in6_addr); + m->Assign(2, BuildOptionsVal(data + off, Length() - off)); + msg->Assign(8, m); + break; + } + + default: + reporter->Weird(fmt("unknown_mobility_type_%d", mob->ip6mob_type)); + break; + } + + rv->Assign(5, msg); + } + break; +#endif //ENABLE_MOBILE_IPV6 + + default: + break; + } + + return rv; + } + +RecordVal* IP_Hdr::BuildIPHdrVal() const + { + RecordVal* rval = 0; + + if ( ip4 ) + { + rval = new RecordVal(hdrType(ip4_hdr_type, "ip4_hdr")); + rval->Assign(0, new Val(ip4->ip_hl * 4, TYPE_COUNT)); + rval->Assign(1, new Val(ip4->ip_tos, TYPE_COUNT)); + rval->Assign(2, new Val(ntohs(ip4->ip_len), TYPE_COUNT)); + rval->Assign(3, new Val(ntohs(ip4->ip_id), TYPE_COUNT)); + rval->Assign(4, new Val(ip4->ip_ttl, TYPE_COUNT)); + rval->Assign(5, new Val(ip4->ip_p, TYPE_COUNT)); + rval->Assign(6, new AddrVal(ip4->ip_src.s_addr)); + rval->Assign(7, new AddrVal(ip4->ip_dst.s_addr)); + } + else + { + rval = ((*ip6_hdrs)[0])->BuildRecordVal(ip6_hdrs->BuildVal()); + } + + return rval; + } + +RecordVal* IP_Hdr::BuildPktHdrVal() const + { + static RecordType* pkt_hdr_type = 0; + static RecordType* tcp_hdr_type = 0; + static RecordType* udp_hdr_type = 0; + static RecordType* icmp_hdr_type = 0; + + if ( ! pkt_hdr_type ) + { + pkt_hdr_type = internal_type("pkt_hdr")->AsRecordType(); + tcp_hdr_type = internal_type("tcp_hdr")->AsRecordType(); + udp_hdr_type = internal_type("udp_hdr")->AsRecordType(); + icmp_hdr_type = internal_type("icmp_hdr")->AsRecordType(); + } + + RecordVal* pkt_hdr = new RecordVal(pkt_hdr_type); + + if ( ip4 ) + pkt_hdr->Assign(0, BuildIPHdrVal()); + else + pkt_hdr->Assign(1, BuildIPHdrVal()); + + // L4 header. + const u_char* data = Payload(); + + int proto = NextProto(); + switch ( proto ) { + case IPPROTO_TCP: + { + const struct tcphdr* tp = (const struct tcphdr*) data; + RecordVal* tcp_hdr = new RecordVal(tcp_hdr_type); + + int tcp_hdr_len = tp->th_off * 4; + int data_len = PayloadLen() - tcp_hdr_len; + + tcp_hdr->Assign(0, new PortVal(ntohs(tp->th_sport), TRANSPORT_TCP)); + tcp_hdr->Assign(1, new PortVal(ntohs(tp->th_dport), TRANSPORT_TCP)); + tcp_hdr->Assign(2, new Val(uint32(ntohl(tp->th_seq)), TYPE_COUNT)); + tcp_hdr->Assign(3, new Val(uint32(ntohl(tp->th_ack)), TYPE_COUNT)); + tcp_hdr->Assign(4, new Val(tcp_hdr_len, TYPE_COUNT)); + tcp_hdr->Assign(5, new Val(data_len, TYPE_COUNT)); + tcp_hdr->Assign(6, new Val(tp->th_flags, TYPE_COUNT)); + tcp_hdr->Assign(7, new Val(ntohs(tp->th_win), TYPE_COUNT)); + + pkt_hdr->Assign(2, tcp_hdr); + break; + } + + case IPPROTO_UDP: + { + const struct udphdr* up = (const struct udphdr*) data; + RecordVal* udp_hdr = new RecordVal(udp_hdr_type); + + udp_hdr->Assign(0, new PortVal(ntohs(up->uh_sport), TRANSPORT_UDP)); + udp_hdr->Assign(1, new PortVal(ntohs(up->uh_dport), TRANSPORT_UDP)); + udp_hdr->Assign(2, new Val(ntohs(up->uh_ulen), TYPE_COUNT)); + + pkt_hdr->Assign(3, udp_hdr); + break; + } + + case IPPROTO_ICMP: + { + const struct icmp* icmpp = (const struct icmp *) data; + RecordVal* icmp_hdr = new RecordVal(icmp_hdr_type); + + icmp_hdr->Assign(0, new Val(icmpp->icmp_type, TYPE_COUNT)); + + pkt_hdr->Assign(4, icmp_hdr); + break; + } + + default: + { + // This is not a protocol we understand. + break; + } + } + + return pkt_hdr; + } + +static inline bool isIPv6ExtHeader(uint8 type) + { + switch (type) { + case IPPROTO_HOPOPTS: + case IPPROTO_ROUTING: + case IPPROTO_DSTOPTS: + case IPPROTO_FRAGMENT: + case IPPROTO_AH: + case IPPROTO_ESP: +#ifdef ENABLE_MOBILE_IPV6 + case IPPROTO_MOBILITY: +#endif + return true; + default: + return false; + } + } + +void IPv6_Hdr_Chain::Init(const struct ip6_hdr* ip6, int total_len, + bool set_next, uint16 next) + { + length = 0; + uint8 current_type, next_type; + next_type = IPPROTO_IPV6; + const u_char* hdrs = (const u_char*) ip6; + + if ( total_len < (int)sizeof(struct ip6_hdr) ) + reporter->InternalError("IPv6_HdrChain::Init with truncated IP header"); + + do + { + // We can't determine a given header's length if there's less than + // two bytes of data available (2nd byte of extension headers is length) + if ( total_len < 2 ) + return; + + current_type = next_type; + IPv6_Hdr* p = new IPv6_Hdr(current_type, hdrs); + + next_type = p->NextHdr(); + uint16 cur_len = p->Length(); + + // If this header is truncated, don't add it to chain, don't go further. + if ( cur_len > total_len ) + { + delete p; + return; + } + + if ( set_next && next_type == IPPROTO_FRAGMENT ) + { + p->ChangeNext(next); + next_type = next; + } + + chain.push_back(p); + + // Check for routing headers and remember final destination address. + if ( current_type == IPPROTO_ROUTING ) + ProcessRoutingHeader((const struct ip6_rthdr*) hdrs, cur_len); + +#ifdef ENABLE_MOBILE_IPV6 + // Only Mobile IPv6 has a destination option we care about right now. + if ( current_type == IPPROTO_DSTOPTS ) + ProcessDstOpts((const struct ip6_dest*) hdrs, cur_len); +#endif + + hdrs += cur_len; + length += cur_len; + total_len -= cur_len; + + } while ( current_type != IPPROTO_FRAGMENT && + current_type != IPPROTO_ESP && +#ifdef ENABLE_MOBILE_IPV6 + current_type != IPPROTO_MOBILITY && +#endif + isIPv6ExtHeader(next_type) ); + } + +void IPv6_Hdr_Chain::ProcessRoutingHeader(const struct ip6_rthdr* r, uint16 len) + { + if ( finalDst ) + { + // RFC 2460 section 4.1 says Routing should occur at most once. + reporter->Weird(SrcAddr(), DstAddr(), "multiple_routing_headers"); + return; + } + + // Last 16 bytes of header (for all known types) is the address we want. + const in6_addr* addr = (const in6_addr*)(((const u_char*)r) + len - 16); + + switch ( r->ip6r_type ) { + case 0: // Defined by RFC 2460, deprecated by RFC 5095 + { + if ( r->ip6r_segleft > 0 && r->ip6r_len >= 2 ) + { + if ( r->ip6r_len % 2 == 0 ) + finalDst = new IPAddr(*addr); + else + reporter->Weird(SrcAddr(), DstAddr(), "odd_routing0_len"); + } + + // Always raise a weird since this type is deprecated. + reporter->Weird(SrcAddr(), DstAddr(), "routing0_hdr"); + } + break; + +#ifdef ENABLE_MOBILE_IPV6 + case 2: // Defined by Mobile IPv6 RFC 6275. + { + if ( r->ip6r_segleft > 0 ) + { + if ( r->ip6r_len == 2 ) + finalDst = new IPAddr(*addr); + else + reporter->Weird(SrcAddr(), DstAddr(), "bad_routing2_len"); + } + } + break; +#endif + + default: + reporter->Weird(fmt("unknown_routing_type_%d", r->ip6r_type)); + break; + } + } + +#ifdef ENABLE_MOBILE_IPV6 +void IPv6_Hdr_Chain::ProcessDstOpts(const struct ip6_dest* d, uint16 len) + { + const u_char* data = (const u_char*) d; + len -= 2 * sizeof(uint8); + data += 2* sizeof(uint8); + + while ( len > 0 ) + { + const struct ip6_opt* opt = (const struct ip6_opt*) data; + switch ( opt->ip6o_type ) { + case 201: // Home Address Option, Mobile IPv6 RFC 6275 section 6.3 + { + if ( opt->ip6o_len == 16 ) + if ( homeAddr ) + reporter->Weird(SrcAddr(), DstAddr(), "multiple_home_addr_opts"); + else + homeAddr = new IPAddr(*((const in6_addr*)(data + 2))); + else + reporter->Weird(SrcAddr(), DstAddr(), "bad_home_addr_len"); + } + break; + + default: + break; + } + + if ( opt->ip6o_type == 0 ) + { + data += sizeof(uint8); + len -= sizeof(uint8); + } + else + { + data += 2 * sizeof(uint8) + opt->ip6o_len; + len -= 2 * sizeof(uint8) + opt->ip6o_len; + } + } + } +#endif + +VectorVal* IPv6_Hdr_Chain::BuildVal() const + { + if ( ! ip6_ext_hdr_type ) + { + ip6_ext_hdr_type = internal_type("ip6_ext_hdr")->AsRecordType(); + ip6_hopopts_type = internal_type("ip6_hopopts")->AsRecordType(); + ip6_dstopts_type = internal_type("ip6_dstopts")->AsRecordType(); + ip6_routing_type = internal_type("ip6_routing")->AsRecordType(); + ip6_fragment_type = internal_type("ip6_fragment")->AsRecordType(); + ip6_ah_type = internal_type("ip6_ah")->AsRecordType(); + ip6_esp_type = internal_type("ip6_esp")->AsRecordType(); + ip6_mob_type = internal_type("ip6_mobility_hdr")->AsRecordType(); + } + + VectorVal* rval = new VectorVal(new VectorType(ip6_ext_hdr_type->Ref())); + + for ( size_t i = 1; i < chain.size(); ++i ) + { + RecordVal* v = chain[i]->BuildRecordVal(); + RecordVal* ext_hdr = new RecordVal(ip6_ext_hdr_type); + uint8 type = chain[i]->Type(); + ext_hdr->Assign(0, new Val(type, TYPE_COUNT)); + + switch (type) { + case IPPROTO_HOPOPTS: + ext_hdr->Assign(1, v); + break; + case IPPROTO_DSTOPTS: + ext_hdr->Assign(2, v); + break; + case IPPROTO_ROUTING: + ext_hdr->Assign(3, v); + break; + case IPPROTO_FRAGMENT: + ext_hdr->Assign(4, v); + break; + case IPPROTO_AH: + ext_hdr->Assign(5, v); + break; + case IPPROTO_ESP: + ext_hdr->Assign(6, v); + break; +#ifdef ENABLE_MOBILE_IPV6 + case IPPROTO_MOBILITY: + ext_hdr->Assign(7, v); + break; +#endif + default: + reporter->InternalError("IPv6_Hdr_Chain bad header %d", type); + break; + } + rval->Assign(rval->Size(), ext_hdr, 0); + } + + return rval; + } diff --git a/src/IP.h b/src/IP.h index 4f76ef50ed..502ae857c0 100644 --- a/src/IP.h +++ b/src/IP.h @@ -1,72 +1,373 @@ -// $Id: IP.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef ip_h #define ip_h #include "config.h" +#include "net_util.h" +#include "IPAddr.h" +#include "Reporter.h" +#include "Val.h" +#include "Type.h" +#include +#include +#include -#include +#ifdef ENABLE_MOBILE_IPV6 +#ifndef IPPROTO_MOBILITY +#define IPPROTO_MOBILITY 135 +#endif + +struct ip6_mobility { + uint8 ip6mob_payload; + uint8 ip6mob_len; + uint8 ip6mob_type; + uint8 ip6mob_rsv; + uint16 ip6mob_chksum; +}; + +#endif //ENABLE_MOBILE_IPV6 + +/** + * Base class for IPv6 header/extensions. + */ +class IPv6_Hdr { +public: + /** + * Construct an IPv6 header or extension header from assigned type number. + */ + IPv6_Hdr(uint8 t, const u_char* d) : type(t), data(d) {} + + /** + * Replace the value of the next protocol field. + */ + void ChangeNext(uint8 next_type) + { + switch ( type ) { + case IPPROTO_IPV6: + ((ip6_hdr*)data)->ip6_nxt = next_type; + break; + case IPPROTO_HOPOPTS: + case IPPROTO_DSTOPTS: + case IPPROTO_ROUTING: + case IPPROTO_FRAGMENT: + case IPPROTO_AH: +#ifdef ENABLE_MOBILE_IPV6 + case IPPROTO_MOBILITY: +#endif + ((ip6_ext*)data)->ip6e_nxt = next_type; + break; + case IPPROTO_ESP: + default: + break; + } + } + + ~IPv6_Hdr() {} + + /** + * Returns the assigned IPv6 extension header type number of the header + * that immediately follows this one. + */ + uint8 NextHdr() const + { + switch ( type ) { + case IPPROTO_IPV6: + return ((ip6_hdr*)data)->ip6_nxt; + case IPPROTO_HOPOPTS: + case IPPROTO_DSTOPTS: + case IPPROTO_ROUTING: + case IPPROTO_FRAGMENT: + case IPPROTO_AH: +#ifdef ENABLE_MOBILE_IPV6 + case IPPROTO_MOBILITY: +#endif + return ((ip6_ext*)data)->ip6e_nxt; + case IPPROTO_ESP: + default: + return IPPROTO_NONE; + } + } + + /** + * Returns the length of the header in bytes. + */ + uint16 Length() const + { + switch ( type ) { + case IPPROTO_IPV6: + return 40; + case IPPROTO_HOPOPTS: + case IPPROTO_DSTOPTS: + case IPPROTO_ROUTING: +#ifdef ENABLE_MOBILE_IPV6 + case IPPROTO_MOBILITY: +#endif + return 8 + 8 * ((ip6_ext*)data)->ip6e_len; + case IPPROTO_FRAGMENT: + return 8; + case IPPROTO_AH: + return 8 + 4 * ((ip6_ext*)data)->ip6e_len; + case IPPROTO_ESP: + return 8; //encrypted payload begins after 8 bytes + default: + return 0; + } + } + + /** + * Returns the RFC 1700 et seq. IANA assigned number for the header. + */ + uint8 Type() const { return type; } + + /** + * Returns pointer to the start of where header structure resides in memory. + */ + const u_char* Data() const { return data; } + + /** + * Returns the script-layer record representation of the header. + */ + RecordVal* BuildRecordVal(VectorVal* chain = 0) const; + +protected: + uint8 type; + const u_char* data; +}; + +class IPv6_Hdr_Chain { +public: + /** + * Initializes the header chain from an IPv6 header structure. + */ + IPv6_Hdr_Chain(const struct ip6_hdr* ip6, int len) : +#ifdef ENABLE_MOBILE_IPV6 + homeAddr(0), +#endif + finalDst(0) + { Init(ip6, len, false); } + + ~IPv6_Hdr_Chain() + { + for ( size_t i = 0; i < chain.size(); ++i ) delete chain[i]; +#ifdef ENABLE_MOBILE_IPV6 + delete homeAddr; +#endif + delete finalDst; + } + + /** + * Returns the number of headers in the chain. + */ + size_t Size() const { return chain.size(); } + + /** + * Returns the sum of the length of all headers in the chain in bytes. + */ + uint16 TotalLength() const { return length; } + + /** + * Accesses the header at the given location in the chain. + */ + const IPv6_Hdr* operator[](const size_t i) const { return chain[i]; } + + /** + * Returns whether the header chain indicates a fragmented packet. + */ + bool IsFragment() const + { return chain[chain.size()-1]->Type() == IPPROTO_FRAGMENT; } + + /** + * Returns pointer to fragment header structure if the chain contains one. + */ + const struct ip6_frag* GetFragHdr() const + { return IsFragment() ? + (const struct ip6_frag*)chain[chain.size()-1]->Data(): 0; } + + /** + * If the header chain is a fragment, returns the offset in number of bytes + * relative to the start of the Fragmentable Part of the original packet. + */ + uint16 FragOffset() const + { return IsFragment() ? + (ntohs(GetFragHdr()->ip6f_offlg) & 0xfff8) : 0; } + + /** + * If the header chain is a fragment, returns the identification field. + */ + uint32 ID() const + { return IsFragment() ? ntohl(GetFragHdr()->ip6f_ident) : 0; } + + /** + * If the header chain is a fragment, returns the M (more fragments) flag. + */ + int MF() const + { return IsFragment() ? + (ntohs(GetFragHdr()->ip6f_offlg) & 0x0001) != 0 : 0; } + + /** + * If the chain contains a Destination Options header with a Home Address + * option as defined by Mobile IPv6 (RFC 6275), then return it, else + * return the source address in the main IPv6 header. + */ + IPAddr SrcAddr() const + { +#ifdef ENABLE_MOBILE_IPV6 + if ( homeAddr ) + return IPAddr(*homeAddr); + else +#endif + return IPAddr(((const struct ip6_hdr*)(chain[0]->Data()))->ip6_src); + } + + /** + * If the chain contains a Routing header with non-zero segments left, + * then return the last address of the first such header, else return + * the destination address of the main IPv6 header. + */ + IPAddr DstAddr() const + { + if ( finalDst ) + return IPAddr(*finalDst); + else + return IPAddr(((const struct ip6_hdr*)(chain[0]->Data()))->ip6_dst); + } + + /** + * Returns a vector of ip6_ext_hdr RecordVals that includes script-layer + * representation of all extension headers in the chain. + */ + VectorVal* BuildVal() const; + +protected: + // for access to protected ctor that changes next header values that + // point to a fragment + friend class FragReassembler; + + /** + * Initializes the header chain from an IPv6 header structure, and replaces + * the first next protocol pointer field that points to a fragment header. + */ + IPv6_Hdr_Chain(const struct ip6_hdr* ip6, uint16 next, int len) : +#ifdef ENABLE_MOBILE_IPV6 + homeAddr(0), +#endif + finalDst(0) + { Init(ip6, len, true, next); } + + /** + * Initializes the header chain from an IPv6 header structure of a given + * length, possibly setting the first next protocol pointer field that + * points to a fragment header. + */ + void Init(const struct ip6_hdr* ip6, int total_len, bool set_next, + uint16 next = 0); + + /** + * Process a routing header and allocate/remember the final destination + * address if it has segments left and is a valid routing header. + */ + void ProcessRoutingHeader(const struct ip6_rthdr* r, uint16 len); + +#ifdef ENABLE_MOBILE_IPV6 + /** + * Inspect a Destination Option header's options for things we need to + * remember, such as the Home Address option from Mobile IPv6. + */ + void ProcessDstOpts(const struct ip6_dest* d, uint16 len); +#endif + + vector chain; + + /** + * The summation of all header lengths in the chain in bytes. + */ + uint16 length; + +#ifdef ENABLE_MOBILE_IPV6 + /** + * Home Address of the packet's source as defined by Mobile IPv6 (RFC 6275). + */ + IPAddr* homeAddr; +#endif + + /** + * The final destination address in chain's first Routing header that has + * non-zero segments left. + */ + IPAddr* finalDst; +}; + +/** + * A class that wraps either an IPv4 or IPv6 packet and abstracts methods + * for inquiring about common features between the two. + */ class IP_Hdr { public: - IP_Hdr(struct ip* arg_ip4) + /** + * Attempts to construct the header from some blob of data based on IP + * version number. Caller must have already checked that the header + * is not truncated. + * @param p pointer to memory containing an IPv4 or IPv6 packet. + * @param arg_del whether to take ownership of \a p pointer's memory. + * @param len the length of data, in bytes, pointed to by \a p. + */ + IP_Hdr(const u_char* p, bool arg_del, int len) + : ip4(0), ip6(0), del(arg_del), ip6_hdrs(0) { - ip4 = arg_ip4; - ip6 = 0; - del = 1; - -#ifdef BROv6 - src_addr[0] = src_addr[1] = src_addr[2] = 0; - dst_addr[0] = dst_addr[1] = dst_addr[2] = 0; - - src_addr[3] = ip4->ip_src.s_addr; - dst_addr[3] = ip4->ip_dst.s_addr; -#endif + if ( ((const struct ip*)p)->ip_v == 4 ) + ip4 = (const struct ip*)p; + else if ( ((const struct ip*)p)->ip_v == 6 ) + { + ip6 = (const struct ip6_hdr*)p; + ip6_hdrs = new IPv6_Hdr_Chain(ip6, len); + } + else + { + if ( arg_del ) + delete [] p; + reporter->InternalError("bad IP version in IP_Hdr ctor"); + } } - IP_Hdr(const struct ip* arg_ip4) + /** + * Construct the header wrapper from an IPv4 packet. Caller must have + * already checked that the header is not truncated. + * @param arg_ip4 pointer to memory containing an IPv4 packet. + * @param arg_del whether to take ownership of \a arg_ip4 pointer's memory. + */ + IP_Hdr(const struct ip* arg_ip4, bool arg_del) + : ip4(arg_ip4), ip6(0), del(arg_del), ip6_hdrs(0) { - ip4 = arg_ip4; - ip6 = 0; - del = 0; - -#ifdef BROv6 - src_addr[0] = src_addr[1] = src_addr[2] = 0; - dst_addr[0] = dst_addr[1] = dst_addr[2] = 0; - - src_addr[3] = ip4->ip_src.s_addr; - dst_addr[3] = ip4->ip_dst.s_addr; -#endif } - IP_Hdr(struct ip6_hdr* arg_ip6) + /** + * Construct the header wrapper from an IPv6 packet. Caller must have + * already checked that the static IPv6 header is not truncated. If + * the packet contains extension headers and they are truncated, that can + * be checked afterwards by comparing \a len with \a TotalLen. E.g. + * NetSessions::DoNextPacket does this to skip truncated packets. + * @param arg_ip6 pointer to memory containing an IPv6 packet. + * @param arg_del whether to take ownership of \a arg_ip6 pointer's memory. + * @param len the packet's length in bytes. + * @param c an already-constructed header chain to take ownership of. + */ + IP_Hdr(const struct ip6_hdr* arg_ip6, bool arg_del, int len, + const IPv6_Hdr_Chain* c = 0) + : ip4(0), ip6(arg_ip6), del(arg_del), + ip6_hdrs(c ? c : new IPv6_Hdr_Chain(ip6, len)) { - ip4 = 0; - ip6 = arg_ip6; - del = 1; - -#ifdef BROv6 - memcpy(src_addr, ip6->ip6_src.s6_addr, 16); - memcpy(dst_addr, ip6->ip6_dst.s6_addr, 16); -#endif - } - - IP_Hdr(const struct ip6_hdr* arg_ip6) - { - ip4 = 0; - ip6 = arg_ip6; - del = 0; - -#ifdef BROv6 - memcpy(src_addr, ip6->ip6_src.s6_addr, 16); - memcpy(dst_addr, ip6->ip6_dst.s6_addr, 16); -#endif } + /** + * Destructor. + */ ~IP_Hdr() { + if ( ip6 ) + delete ip6_hdrs; + if ( del ) { if ( ip4 ) @@ -76,68 +377,175 @@ public: } } + /** + * If an IPv4 packet is wrapped, return a pointer to it, else null. + */ const struct ip* IP4_Hdr() const { return ip4; } + + /** + * If an IPv6 packet is wrapped, return a pointer to it, else null. + */ const struct ip6_hdr* IP6_Hdr() const { return ip6; } -#ifdef BROv6 - const uint32* SrcAddr() const { return src_addr; } - const uint32* DstAddr() const { return dst_addr; } -#else - const uint32* SrcAddr() const - { return ip4 ? &(ip4->ip_src.s_addr) : 0; } - const uint32* DstAddr() const - { return ip4 ? &(ip4->ip_dst.s_addr) : 0; } -#endif + /** + * Returns the source address held in the IP header. + */ + IPAddr IPHeaderSrcAddr() const + { return ip4 ? IPAddr(ip4->ip_src) : IPAddr(ip6->ip6_src); } - uint32 SrcAddr4() const { return ip4->ip_src.s_addr; } - uint32 DstAddr4() const { return ip4->ip_dst.s_addr; } + /** + * Returns the destination address held in the IP header. + */ + IPAddr IPHeaderDstAddr() const + { return ip4 ? IPAddr(ip4->ip_dst) : IPAddr(ip6->ip6_dst); } - uint16 ID4() const { return ip4 ? ip4->ip_id : 0; } + /** + * For IPv4 or IPv6 headers that don't contain a Home Address option + * (Mobile IPv6, RFC 6275), return source address held in the IP header. + * For IPv6 headers that contain a Home Address option, return that address. + */ + IPAddr SrcAddr() const + { return ip4 ? IPAddr(ip4->ip_src) : ip6_hdrs->SrcAddr(); } + /** + * For IPv4 or IPv6 headers that don't contain a Routing header with + * non-zero segments left, return destination address held in the IP header. + * For IPv6 headers with a Routing header that has non-zero segments left, + * return the last address in the first such Routing header. + */ + IPAddr DstAddr() const + { return ip4 ? IPAddr(ip4->ip_dst) : ip6_hdrs->DstAddr(); } + + /** + * Returns a pointer to the payload of the IP packet, usually an + * upper-layer protocol. + */ const u_char* Payload() const { if ( ip4 ) return ((const u_char*) ip4) + ip4->ip_hl * 4; else - return ((const u_char*) ip6) + 40; + return ((const u_char*) ip6) + ip6_hdrs->TotalLength(); } +#ifdef ENABLE_MOBILE_IPV6 + /** + * Returns a pointer to the mobility header of the IP packet, if present, + * else a null pointer. + */ + const ip6_mobility* MobilityHeader() const + { + if ( ip4 ) + return 0; + else if ( (*ip6_hdrs)[ip6_hdrs->Size()-1]->Type() != IPPROTO_MOBILITY ) + return 0; + else + return (const ip6_mobility*)(*ip6_hdrs)[ip6_hdrs->Size()-1]->Data(); + } +#endif + + /** + * Returns the length of the IP packet's payload (length of packet minus + * header length or, for IPv6, also minus length of all extension headers). + */ uint16 PayloadLen() const { if ( ip4 ) return ntohs(ip4->ip_len) - ip4->ip_hl * 4; else - return ntohs(ip6->ip6_plen); + return ntohs(ip6->ip6_plen) + 40 - ip6_hdrs->TotalLength(); } - uint16 TotalLen() const - { - if ( ip4 ) - return ntohs(ip4->ip_len); - else - return ntohs(ip6->ip6_plen) + 40; - } + /** + * Returns the length of the IP packet (length of headers and payload). + */ + uint32 TotalLen() const + { return ip4 ? ntohs(ip4->ip_len) : ntohs(ip6->ip6_plen) + 40; } - uint16 HdrLen() const { return ip4 ? ip4->ip_hl * 4 : 40; } + /** + * Returns length of IP packet header (includes extension headers for IPv6). + */ + uint16 HdrLen() const + { return ip4 ? ip4->ip_hl * 4 : ip6_hdrs->TotalLength(); } + + /** + * For IPv6 header chains, returns the type of the last header in the chain. + */ + uint8 LastHeader() const + { return ip4 ? IPPROTO_RAW : + ((*ip6_hdrs)[ip6_hdrs->Size()-1])->Type(); } + + /** + * Returns the protocol type of the IP packet's payload, usually an + * upper-layer protocol. For IPv6, this returns the last (extension) + * header's Next Header value. + */ unsigned char NextProto() const - { return ip4 ? ip4->ip_p : ip6->ip6_nxt; } + { return ip4 ? ip4->ip_p : + ((*ip6_hdrs)[ip6_hdrs->Size()-1])->NextHdr(); } + + /** + * Returns the IPv4 Time to Live or IPv6 Hop Limit field. + */ unsigned char TTL() const { return ip4 ? ip4->ip_ttl : ip6->ip6_hlim; } - uint16 FragField() const - { return ntohs(ip4 ? ip4->ip_off : 0); } + + /** + * Returns whether the IP header indicates this packet is a fragment. + */ + bool IsFragment() const + { return ip4 ? (ntohs(ip4->ip_off) & 0x3fff) != 0 : + ip6_hdrs->IsFragment(); } + + /** + * Returns the fragment packet's offset in relation to the original + * packet in bytes. + */ + uint16 FragOffset() const + { return ip4 ? (ntohs(ip4->ip_off) & 0x1fff) * 8 : + ip6_hdrs->FragOffset(); } + + /** + * Returns the fragment packet's identification field. + */ + uint32 ID() const + { return ip4 ? ntohs(ip4->ip_id) : ip6_hdrs->ID(); } + + /** + * Returns whether a fragment packet's "More Fragments" field is set. + */ + int MF() const + { return ip4 ? (ntohs(ip4->ip_off) & 0x2000) != 0 : ip6_hdrs->MF(); } + + /** + * Returns whether a fragment packet's "Don't Fragment" field is set. + * Note that IPv6 has no such field. + */ int DF() const - { return ip4 ? ((ntohs(ip4->ip_off) & IP_DF) != 0) : 0; } - uint16 IP_ID() const - { return ip4 ? (ntohs(ip4->ip_id)) : 0; } + { return ip4 ? ((ntohs(ip4->ip_off) & 0x4000) != 0) : 0; } + + /** + * Returns number of IP headers in packet (includes IPv6 extension headers). + */ + size_t NumHeaders() const + { return ip4 ? 1 : ip6_hdrs->Size(); } + + /** + * Returns an ip_hdr or ip6_hdr_chain RecordVal. + */ + RecordVal* BuildIPHdrVal() const; + + /** + * Returns a pkt_hdr RecordVal, which includes not only the IP header, but + * also upper-layer (tcp/udp/icmp) headers. + */ + RecordVal* BuildPktHdrVal() const; private: const struct ip* ip4; const struct ip6_hdr* ip6; -#ifdef BROv6 - uint32 src_addr[NUM_ADDR_WORDS]; - uint32 dst_addr[NUM_ADDR_WORDS]; -#endif - int del; + bool del; + const IPv6_Hdr_Chain* ip6_hdrs; }; #endif diff --git a/src/IPAddr.cc b/src/IPAddr.cc new file mode 100644 index 0000000000..0ba5589fff --- /dev/null +++ b/src/IPAddr.cc @@ -0,0 +1,286 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include +#include +#include "IPAddr.h" +#include "Reporter.h" +#include "Conn.h" +#include "DPM.h" +#include "bro_inet_ntop.h" + +const uint8_t IPAddr::v4_mapped_prefix[12] = { 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0xff, 0xff }; + +HashKey* BuildConnIDHashKey(const ConnID& id) + { + struct { + in6_addr ip1; + in6_addr ip2; + uint16 port1; + uint16 port2; + } key; + + // Lookup up connection based on canonical ordering, which is + // the smaller of and + // followed by the other. + if ( id.is_one_way || + addr_port_canon_lt(id.src_addr, id.src_port, id.dst_addr, id.dst_port) + ) + { + key.ip1 = id.src_addr.in6; + key.ip2 = id.dst_addr.in6; + key.port1 = id.src_port; + key.port2 = id.dst_port; + } + else + { + key.ip1 = id.dst_addr.in6; + key.ip2 = id.src_addr.in6; + key.port1 = id.dst_port; + key.port2 = id.src_port; + } + + return new HashKey(&key, sizeof(key)); + } + +HashKey* BuildExpectedConnHashKey(const ExpectedConn& c) + { + struct { + in6_addr orig; + in6_addr resp; + uint16 resp_p; + uint16 proto; + } key; + + key.orig = c.orig.in6; + key.resp = c.resp.in6; + key.resp_p = c.resp_p; + key.proto = c.proto; + + return new HashKey(&key, sizeof(key)); + } + +void IPAddr::Mask(int top_bits_to_keep) + { + if ( top_bits_to_keep < 0 || top_bits_to_keep > 128 ) + { + reporter->Error("Bad IPAddr::Mask value %d", top_bits_to_keep); + return; + } + + uint32_t tmp[4]; + memcpy(tmp, in6.s6_addr, sizeof(in6.s6_addr)); + + int word = 3; + int bits_to_chop = 128 - top_bits_to_keep; + + while ( bits_to_chop >= 32 ) + { + tmp[word] = 0; + --word; + bits_to_chop -= 32; + } + + uint32_t w = ntohl(tmp[word]); + w >>= bits_to_chop; + w <<= bits_to_chop; + tmp[word] = htonl(w); + + memcpy(in6.s6_addr, tmp, sizeof(in6.s6_addr)); + } + +void IPAddr::ReverseMask(int top_bits_to_chop) + { + if ( top_bits_to_chop < 0 || top_bits_to_chop > 128 ) + { + reporter->Error("Bad IPAddr::ReverseMask value %d", top_bits_to_chop); + return; + } + + uint32_t tmp[4]; + memcpy(tmp, in6.s6_addr, sizeof(in6.s6_addr)); + + int word = 0; + int bits_to_chop = top_bits_to_chop; + + while ( bits_to_chop >= 32 ) + { + tmp[word] = 0; + ++word; + bits_to_chop -= 32; + } + + uint32_t w = ntohl(tmp[word]); + w <<= bits_to_chop; + w >>= bits_to_chop; + tmp[word] = htonl(w); + + memcpy(in6.s6_addr, tmp, sizeof(in6.s6_addr)); + } + +void IPAddr::Init(const std::string& s) + { + if ( s.find(':') == std::string::npos ) // IPv4. + { + memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix)); + + // Parse the address directly instead of using inet_pton since + // some platforms have more sensitive implementations than others + // that can't e.g. handle leading zeroes. + int a[4]; + int n = sscanf(s.c_str(), "%d.%d.%d.%d", a+0, a+1, a+2, a+3); + + if ( n != 4 || a[0] < 0 || a[1] < 0 || a[2] < 0 || a[3] < 0 || + a[0] > 255 || a[1] > 255 || a[2] > 255 || a[3] > 255 ) + { + reporter->Error("Bad IP address: %s", s.c_str()); + memset(in6.s6_addr, 0, sizeof(in6.s6_addr)); + return; + } + + uint32_t addr = (a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]; + addr = htonl(addr); + memcpy(&in6.s6_addr[12], &addr, sizeof(uint32_t)); + } + + else + { + if ( inet_pton(AF_INET6, s.c_str(), in6.s6_addr) <=0 ) + { + reporter->Error("Bad IP address: %s", s.c_str()); + memset(in6.s6_addr, 0, sizeof(in6.s6_addr)); + } + } + } + +string IPAddr::AsString() const + { + if ( GetFamily() == IPv4 ) + { + char s[INET_ADDRSTRLEN]; + + if ( ! bro_inet_ntop(AF_INET, &in6.s6_addr[12], s, INET_ADDRSTRLEN) ) + return "> 24) & 0xff; + uint32_t a2 = (a >> 16) & 0xff; + uint32_t a1 = (a >> 8) & 0xff; + uint32_t a0 = a & 0xff; + snprintf(buf, sizeof(buf), "%u.%u.%u.%u.in-addr.arpa", a0, a1, a2, a3); + return buf; + } + else + { + static const char hex_digit[] = "0123456789abcdef"; + string ptr_name("ip6.arpa"); + uint32_t* p = (uint32_t*) in6.s6_addr; + + for ( unsigned int i = 0; i < 4; ++i ) + { + uint32 a = ntohl(p[i]); + for ( unsigned int j = 1; j <=8; ++j ) + { + ptr_name.insert(0, 1, '.'); + ptr_name.insert(0, 1, hex_digit[(a >> (32-j*4)) & 0x0f]); + } + } + + return ptr_name; + } + } + +IPPrefix::IPPrefix(const in4_addr& in4, uint8_t length) + : prefix(in4), length(96 + length) + { + if ( length > 32 ) + reporter->InternalError("Bad in4_addr IPPrefix length : %d", length); + + prefix.Mask(this->length); + } + +IPPrefix::IPPrefix(const in6_addr& in6, uint8_t length) + : prefix(in6), length(length) + { + if ( length > 128 ) + reporter->InternalError("Bad in6_addr IPPrefix length : %d", length); + + prefix.Mask(this->length); + } + +IPPrefix::IPPrefix(const IPAddr& addr, uint8_t length) + : prefix(addr) + { + if ( prefix.GetFamily() == IPv4 ) + { + if ( length > 32 ) + reporter->InternalError("Bad IPAddr(v4) IPPrefix length : %d", + length); + + this->length = length + 96; + } + + else + { + if ( length > 128 ) + reporter->InternalError("Bad IPAddr(v6) IPPrefix length : %d", + length); + + this->length = length; + } + + prefix.Mask(this->length); + } + +string IPPrefix::AsString() const + { + char l[16]; + + if ( prefix.GetFamily() == IPv4 ) + modp_uitoa10(length - 96, l); + else + modp_uitoa10(length, l); + + return prefix.AsString() +"/" + l; + } + diff --git a/src/IPAddr.h b/src/IPAddr.h new file mode 100644 index 0000000000..8e1921e07b --- /dev/null +++ b/src/IPAddr.h @@ -0,0 +1,586 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef IPADDR_H +#define IPADDR_H + +#include +#include +#include + +#include "BroString.h" +#include "Hash.h" +#include "util.h" +#include "Type.h" +#include "threading/SerialTypes.h" + +struct ConnID; +class ExpectedConn; + +typedef in_addr in4_addr; + +/** + * Class storing both IPv4 and IPv6 addresses. + */ +class IPAddr +{ +public: + /** + * Address family. + */ + typedef IPFamily Family; + + /** + * Byte order. + */ + enum ByteOrder { Host, Network }; + + /** + * Constructs the unspecified IPv6 address (all 128 bits zeroed). + */ + IPAddr() + { + memset(in6.s6_addr, 0, sizeof(in6.s6_addr)); + } + + /** + * Constructs an address instance from an IPv4 address. + * + * @param in6 The IPv6 address. + */ + explicit IPAddr(const in4_addr& in4) + { + memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix)); + memcpy(&in6.s6_addr[12], &in4.s_addr, sizeof(in4.s_addr)); + } + + /** + * Constructs an address instance from an IPv6 address. + * + * @param in6 The IPv6 address. + */ + explicit IPAddr(const in6_addr& arg_in6) : in6(arg_in6) { } + + /** + * Constructs an address instance from a string representation. + * + * @param s String containing an IP address as either a dotted IPv4 + * address or a hex IPv6 address. + */ + IPAddr(const std::string& s) + { + Init(s); + } + + /** + * Constructs an address instance from a string representation. + * + * @param s ASCIIZ string containing an IP address as either a + * dotted IPv4 address or a hex IPv6 address. + */ + IPAddr(const char* s) + { + Init(s); + } + + /** + * Constructs an address instance from a string representation. + * + * @param s String containing an IP address as either a dotted IPv4 + * address or a hex IPv6 address. + */ + IPAddr(const BroString& s) + { + Init(s.CheckString()); + } + + /** + * Constructs an address instance from a raw byte representation. + * + * @param family The address family. + * + * @param bytes A pointer to the raw byte representation. This must point + * to 4 bytes if \a family is IPv4, and to 16 bytes if \a family is + * IPv6. + * + * @param order Indicates whether the raw representation pointed to + * by \a bytes is stored in network or host order. + */ + IPAddr(Family family, const uint32_t* bytes, ByteOrder order); + + /** + * Copy constructor. + */ + IPAddr(const IPAddr& other) : in6(other.in6) { }; + + /** + * Destructor. + */ + ~IPAddr() { }; + + /** + * Returns the address' family. + */ + Family GetFamily() const + { + if ( memcmp(in6.s6_addr, v4_mapped_prefix, 12) == 0 ) + return IPv4; + else + return IPv6; + } + + /** + * Returns true if the address represents a loopback device. + */ + bool IsLoopback() const; + + /** + * Returns true if the address represents a multicast address. + */ + bool IsMulticast() const + { + if ( GetFamily() == IPv4 ) + return in6.s6_addr[12] == 224; + else + return in6.s6_addr[0] == 0xff; + } + + /** + * Returns true if the address represents a broadcast address. + */ + bool IsBroadcast() const + { + if ( GetFamily() == IPv4 ) + return ((in6.s6_addr[12] == 0xff) && (in6.s6_addr[13] == 0xff) + && (in6.s6_addr[14] == 0xff) && (in6.s6_addr[15] == 0xff)); + else + return false; + } + + /** + * Retrieves the raw byte representation of the address. + * + * @param bytes The pointer to which \a bytes points will be set to + * the address of the raw representation in network-byte order. + * The return value indicates how many 32-bit words are valid starting at + * that address. The pointer will be valid as long as the address instance + * exists. + * + * @return The number of 32-bit words the raw representation uses. This + * will be 1 for an IPv4 address and 4 for an IPv6 address. + */ + int GetBytes(const uint32_t** bytes) const + { + if ( GetFamily() == IPv4 ) + { + *bytes = (uint32_t*) &in6.s6_addr[12]; + return 1; + } + else + { + *bytes = (uint32_t*) in6.s6_addr; + return 4; + } + } + + /** + * Retrieves a copy of the IPv6 raw byte representation of the address. + * If the internal address is IPv4, then the copied bytes use the + * IPv4 to IPv6 address mapping to return a full 16 bytes. + * + * @param bytes The pointer to a memory location in which the + * raw bytes of the address are to be copied in network byte-order. + */ + void CopyIPv6(uint32_t* bytes) const + { + memcpy(bytes, in6.s6_addr, sizeof(in6.s6_addr)); + } + + /** + * Retrieves a copy of the IPv6 raw byte representation of the address. + * @see CopyIPv6(uint32_t) + */ + void CopyIPv6(in6_addr* arg_in6) const + { + memcpy(arg_in6->s6_addr, in6.s6_addr, sizeof(in6.s6_addr)); + } + + /** + * Retrieves a copy of the IPv4 raw byte representation of the address. + * The caller should verify the address is of the IPv4 family type + * beforehand. @see GetFamily(). + * + * @param in4 The pointer to a memory location in which the raw bytes + * of the address are to be copied in network byte-order. + */ + void CopyIPv4(in4_addr* in4) const + { + memcpy(&in4->s_addr, &in6.s6_addr[12], sizeof(in4->s_addr)); + } + + /** + * Returns a key that can be used to lookup the IP Address in a hash + * table. Passes ownership to caller. + */ + HashKey* GetHashKey() const + { + return new HashKey((void*)in6.s6_addr, sizeof(in6.s6_addr)); + } + + /** + * Masks out lower bits of the address. + * + * @param top_bits_to_keep The number of bits \a not to mask out, + * counting from the highest order bit. The value is always + * interpreted relative to the IPv6 bit width, even if the address + * is IPv4. That means if compute ``192.168.1.2/16``, you need to + * pass in 112 (i.e., 96 + 16). The value must be in the range from + * 0 to 128. + */ + void Mask(int top_bits_to_keep); + + /** + * Masks out top bits of the address. + * + * @param top_bits_to_chop The number of bits to mask out, counting + * from the highest order bit. The value is always interpreted relative + * to the IPv6 bit width, even if the address is IPv4. So to mask out + * the first 16 bits of an IPv4 address, pass in 112 (i.e., 96 + 16). + * The value must be in the range from 0 to 128. + */ + void ReverseMask(int top_bits_to_chop); + + /** + * Assignment operator. + */ + IPAddr& operator=(const IPAddr& other) + { + // No self-assignment check here because it's correct without it and + // makes the common case faster. + in6 = other.in6; + return *this; + } + + /** + * Bitwise OR operator returns the IP address resulting from the bitwise + * OR operation on the raw bytes of this address with another. + */ + IPAddr operator|(const IPAddr& other) + { + in6_addr result; + for ( int i = 0; i < 16; ++i ) + result.s6_addr[i] = this->in6.s6_addr[i] | other.in6.s6_addr[i]; + + return IPAddr(result); + } + + /** + * Returns a string representation of the address. IPv4 addresses + * will be returned in dotted representation, IPv6 addresses in + * compressed hex. + */ + string AsString() const; + + /** + * Returns a host-order, plain hex string representation of the address. + */ + string AsHexString() const; + + /** + * Returns a string representation of the address. This returns the + * same as AsString(). + */ + operator std::string() const { return AsString(); } + + /** + * Returns a reverse pointer name associated with the IP address. + * For example, 192.168.0.1's reverse pointer is 1.0.168.192.in-addr.arpa. + */ + string PtrName() const; + + /** + * Comparison operator for IP address. + */ + friend bool operator==(const IPAddr& addr1, const IPAddr& addr2) + { + return memcmp(&addr1.in6, &addr2.in6, sizeof(in6_addr)) == 0; + } + + friend bool operator!=(const IPAddr& addr1, const IPAddr& addr2) + { + return ! (addr1 == addr2); + } + + /** + * Comparison operator IP addresses. This defines a well-defined order for + * IP addresses. However, the order does not necessarily correspond to + * their numerical values. + */ + friend bool operator<(const IPAddr& addr1, const IPAddr& addr2) + { + return memcmp(&addr1.in6, &addr2.in6, sizeof(in6_addr)) < 0; + } + + /** Converts the address into the type used internally by the + * inter-thread communication. + */ + void ConvertToThreadingValue(threading::Value::addr_t* v) const; + + friend HashKey* BuildConnIDHashKey(const ConnID& id); + friend HashKey* BuildExpectedConnHashKey(const ExpectedConn& c); + + unsigned int MemoryAllocation() const { return padded_sizeof(*this); } + +private: + friend class IPPrefix; + + /** + * Initializes an address instance from a string representation. + * + * @param s String containing an IP address as either a dotted IPv4 + * address or a hex IPv6 address. + */ + void Init(const std::string& s); + + in6_addr in6; // IPv6 or v4-to-v6-mapped address + + static const uint8_t v4_mapped_prefix[12]; // top 96 bits of v4-mapped-addr +}; + +inline IPAddr::IPAddr(Family family, const uint32_t* bytes, ByteOrder order) + { + if ( family == IPv4 ) + { + memcpy(in6.s6_addr, v4_mapped_prefix, sizeof(v4_mapped_prefix)); + memcpy(&in6.s6_addr[12], bytes, sizeof(uint32_t)); + + if ( order == Host ) + { + uint32_t* p = (uint32_t*) &in6.s6_addr[12]; + *p = htonl(*p); + } + } + + else + { + memcpy(in6.s6_addr, bytes, sizeof(in6.s6_addr)); + + if ( order == Host ) + { + for ( unsigned int i = 0; i < 4; ++ i) + { + uint32_t* p = (uint32_t*) &in6.s6_addr[i*4]; + *p = htonl(*p); + } + } + } + } + +inline bool IPAddr::IsLoopback() const + { + if ( GetFamily() == IPv4 ) + return in6.s6_addr[12] == 127; + + else + return ((in6.s6_addr[0] == 0) && (in6.s6_addr[1] == 0) + && (in6.s6_addr[2] == 0) && (in6.s6_addr[3] == 0) + && (in6.s6_addr[4] == 0) && (in6.s6_addr[5] == 0) + && (in6.s6_addr[6] == 0) && (in6.s6_addr[7] == 0) + && (in6.s6_addr[8] == 0) && (in6.s6_addr[9] == 0) + && (in6.s6_addr[10] == 0) && (in6.s6_addr[11] == 0) + && (in6.s6_addr[12] == 0) && (in6.s6_addr[13] == 0) + && (in6.s6_addr[14] == 0) && (in6.s6_addr[15] == 1)); + } + +inline void IPAddr::ConvertToThreadingValue(threading::Value::addr_t* v) const + { + v->family = GetFamily(); + + switch ( v->family ) { + + case IPv4: + CopyIPv4(&v->in.in4); + return; + + case IPv6: + CopyIPv6(&v->in.in6); + return; + + // Can't be reached. + abort(); + } + } + +/** + * Returns a hash key for a given ConnID. Passes ownership to caller. + */ +HashKey* BuildConnIDHashKey(const ConnID& id); + +/** + * Returns a hash key for a given ExpectedConn instance. Passes ownership to caller. + */ +HashKey* BuildExpectedConnHashKey(const ExpectedConn& c); + +/** + * Class storing both IPv4 and IPv6 prefixes + * (i.e., \c 192.168.1.1/16 and \c FD00::/8. + */ +class IPPrefix +{ +public: + + /** + * Constructs a prefix 0/0. + */ + IPPrefix() : length(0) {} + + /** + * Constructs a prefix instance from an IPv4 address and a prefix + * length. + * + * @param in4 The IPv4 address. + * + * @param length The prefix length in the range from 0 to 32. + */ + IPPrefix(const in4_addr& in4, uint8_t length); + + /** + * Constructs a prefix instance from an IPv6 address and a prefix + * length. + * + * @param in6 The IPv6 address. + * + * @param length The prefix length in the range from 0 to 128. + */ + IPPrefix(const in6_addr& in6, uint8_t length); + + /** + * Constructs a prefix instance from an IPAddr object and prefix length. + * + * @param addr The IP address. + * + * @param length The prefix length in the range from 0 to 128 + */ + IPPrefix(const IPAddr& addr, uint8_t length); + + /** + * Copy constructor. + */ + IPPrefix(const IPPrefix& other) + : prefix(other.prefix), length(other.length) { } + + /** + * Destructor. + */ + ~IPPrefix() { } + + /** + * Returns the prefix in the form of an IP address. The address will + * have all bits not part of the prefixed set to zero. + */ + const IPAddr& Prefix() const { return prefix; } + + /** + * Returns the bit length of the prefix, relative to the 32 bits + * of an IPv4 prefix or relative to the 128 bits of an IPv6 prefix. + */ + uint8_t Length() const + { + return prefix.GetFamily() == IPv4 ? length - 96 : length; + } + + /** + * Returns the bit length of the prefix always relative to a full + * 128 bits of an IPv6 prefix (or IPv4 mapped to IPv6). + */ + uint8_t LengthIPv6() const { return length; } + + /** Returns true if the given address is part of the prefix. + * + * @param addr The address to test. + */ + bool Contains(const IPAddr& addr) const + { + IPAddr p(addr); + p.Mask(length); + return p == prefix; + } + /** + * Assignment operator. + */ + IPPrefix& operator=(const IPPrefix& other) + { + // No self-assignment check here because it's correct without it and + // makes the common case faster. + prefix = other.prefix; + length = other.length; + return *this; + } + + /** + * Returns a string representation of the prefix. IPv4 addresses + * will be returned in dotted representation, IPv6 addresses in + * compressed hex. + */ + string AsString() const; + + operator std::string() const { return AsString(); } + + /** + * Returns a key that can be used to lookup the IP Prefix in a hash + * table. Passes ownership to caller. + */ + HashKey* GetHashKey() const + { + struct { + in6_addr ip; + uint32 len; + } key; + + key.ip = prefix.in6; + key.len = Length(); + + return new HashKey(&key, sizeof(key)); + } + + /** Converts the prefix into the type used internally by the + * inter-thread communication. + */ + void ConvertToThreadingValue(threading::Value::subnet_t* v) const + { + v->length = length; + prefix.ConvertToThreadingValue(&v->prefix); + } + + unsigned int MemoryAllocation() const { return padded_sizeof(*this); } + + /** + * Comparison operator for IP prefix. + */ + friend bool operator==(const IPPrefix& net1, const IPPrefix& net2) + { + return net1.Prefix() == net2.Prefix() && net1.Length() == net2.Length(); + } + + /** + * Comparison operator IP prefixes. This defines a well-defined order for + * IP prefix. However, the order does not necessarily corresponding to their + * numerical values. + */ + friend bool operator<(const IPPrefix& net1, const IPPrefix& net2) + { + if ( net1.Prefix() < net2.Prefix() ) + return true; + + else if ( net1.Prefix() == net2.Prefix() ) + return net1.Length() < net2.Length(); + + else + return false; + } + +private: + IPAddr prefix; // We store it as an address with the non-prefix bits masked out via Mask(). + uint8_t length; // The bit length of the prefix relative to full IPv6 addr. +}; + +#endif diff --git a/src/IRC.cc b/src/IRC.cc index 0e3705a97d..1918300ba2 100644 --- a/src/IRC.cc +++ b/src/IRC.cc @@ -1,5 +1,3 @@ -// $Id: IRC.cc 4582 2007-07-04 01:14:09Z vern $ - // An IRC analyzer contributed by Roland Gruber. #include @@ -1190,15 +1188,10 @@ void IRC_Analyzer::DeliverStream(int length, const u_char* line, bool orig) if ( orig_status == REGISTERED && resp_status == REGISTERED && orig_zip_status == ACCEPT_ZIP && resp_zip_status == ACCEPT_ZIP ) { -#ifdef HAVE_LIBZ orig_zip_status = ZIP_LOADED; resp_zip_status = ZIP_LOADED; AddSupportAnalyzer(new ZIP_Analyzer(Conn(), true)); AddSupportAnalyzer(new ZIP_Analyzer(Conn(), false)); -#else - reporter->Error("IRC analyzer lacking libz support"); - Remove(); -#endif } return; diff --git a/src/IRC.h b/src/IRC.h index fb6e9869ae..0fe36957de 100644 --- a/src/IRC.h +++ b/src/IRC.h @@ -1,5 +1,3 @@ -// $Id: IRC.h 4582 2007-07-04 01:14:09Z vern $ - // An IRC analyzer contributed by Roland Gruber. #ifndef irc_h diff --git a/src/Ident.cc b/src/Ident.cc index 2231c50ae8..b2e82e5f12 100644 --- a/src/Ident.cc +++ b/src/Ident.cc @@ -1,5 +1,3 @@ -// $Id: Ident.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/Ident.h b/src/Ident.h index c87e98c6d4..a848d233e1 100644 --- a/src/Ident.h +++ b/src/Ident.h @@ -1,5 +1,3 @@ -// $Id: Ident.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef ident_h diff --git a/src/IntSet.cc b/src/IntSet.cc index a6c176f829..fb198f0e25 100644 --- a/src/IntSet.cc +++ b/src/IntSet.cc @@ -1,5 +1,3 @@ -// $Id: IntSet.cc 80 2004-07-14 20:15:50Z jason $ - #include "config.h" #ifdef HAVE_MEMORY_H diff --git a/src/IntSet.h b/src/IntSet.h index 412b06d418..ef58e8b12f 100644 --- a/src/IntSet.h +++ b/src/IntSet.h @@ -1,5 +1,3 @@ -// $Id: IntSet.h 80 2004-07-14 20:15:50Z jason $ - // A simple but fast data structure for sets of integers. // Only supported operations are insert, remove and membership test. // diff --git a/src/InterConn.cc b/src/InterConn.cc index 664982fd02..403081181a 100644 --- a/src/InterConn.cc +++ b/src/InterConn.cc @@ -1,5 +1,3 @@ -// $Id: InterConn.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/InterConn.h b/src/InterConn.h index 1f9ee12f62..d9cd10de27 100644 --- a/src/InterConn.h +++ b/src/InterConn.h @@ -1,5 +1,3 @@ -// $Id: InterConn.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef interconn_h diff --git a/src/List.cc b/src/List.cc index 2a28d4ae00..9a1af3fe4f 100644 --- a/src/List.cc +++ b/src/List.cc @@ -1,5 +1,3 @@ -// $Id: List.cc 1905 2005-12-14 03:27:33Z vern $ - #include "config.h" #include diff --git a/src/List.h b/src/List.h index 38afad35c9..bf87ade67d 100644 --- a/src/List.h +++ b/src/List.h @@ -1,5 +1,3 @@ -// $Id: List.h 463 2004-09-26 21:04:20Z vern $ - #ifndef list_h #define list_h diff --git a/src/LogMgr.h b/src/LogMgr.h deleted file mode 100644 index 033a6ba3fd..0000000000 --- a/src/LogMgr.h +++ /dev/null @@ -1,141 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. -// -// A class managing log writers and filters. - -#ifndef LOGMGR_H -#define LOGMGR_H - -#include "Val.h" -#include "EventHandler.h" -#include "RemoteSerializer.h" - -class SerializationFormat; - -// Description of a log field. -struct LogField { - string name; - TypeTag type; - - LogField() { } - LogField(const LogField& other) - : name(other.name), type(other.type) { } - - // (Un-)serialize. - bool Read(SerializationFormat* fmt); - bool Write(SerializationFormat* fmt) const; -}; - -// Values as logged by a writer. -struct LogVal { - TypeTag type; - bool present; // False for unset fields. - - // The following union is a subset of BroValUnion, including only the - // types we can log directly. - struct set_t { bro_int_t size; LogVal** vals; }; - typedef set_t vec_t; - - union _val { - bro_int_t int_val; - bro_uint_t uint_val; - uint32 addr_val[NUM_ADDR_WORDS]; - subnet_type subnet_val; - double double_val; - string* string_val; - set_t set_val; - vec_t vector_val; - } val; - - LogVal(TypeTag arg_type = TYPE_ERROR, bool arg_present = true) - : type(arg_type), present(arg_present) {} - ~LogVal(); - - // (Un-)serialize. - bool Read(SerializationFormat* fmt); - bool Write(SerializationFormat* fmt) const; - - // Returns true if the type can be logged the framework. If - // `atomic_only` is true, will not permit composite types. - static bool IsCompatibleType(BroType* t, bool atomic_only=false); - -private: - LogVal(const LogVal& other) { } -}; - -class LogWriter; -class RemoteSerializer; -class RotationTimer; - -class LogMgr { -public: - LogMgr(); - ~LogMgr(); - - // These correspond to the BiFs visible on the scripting layer. The - // actual BiFs just forward here. - bool CreateStream(EnumVal* id, RecordVal* stream); - bool EnableStream(EnumVal* id); - bool DisableStream(EnumVal* id); - bool AddFilter(EnumVal* id, RecordVal* filter); - bool RemoveFilter(EnumVal* id, StringVal* name); - bool RemoveFilter(EnumVal* id, string name); - bool Write(EnumVal* id, RecordVal* columns); - bool SetBuf(EnumVal* id, bool enabled); // Adjusts all writers. - bool Flush(EnumVal* id); // Flushes all writers.. - -protected: - friend class LogWriter; - friend class RemoteSerializer; - friend class RotationTimer; - - //// Function also used by the RemoteSerializer. - - // Takes ownership of fields. - LogWriter* CreateWriter(EnumVal* id, EnumVal* writer, string path, - int num_fields, LogField** fields); - - // Takes ownership of values.. - bool Write(EnumVal* id, EnumVal* writer, string path, - int num_fields, LogVal** vals); - - // Announces all instantiated writers to peer. - void SendAllWritersTo(RemoteSerializer::PeerID peer); - - //// Functions safe to use by writers. - - // Signals that a file has been rotated. - bool FinishedRotation(LogWriter* writer, string new_name, string old_name, - double open, double close, bool terminating); - - // Reports an error for the given writer. - void Error(LogWriter* writer, const char* msg); - - // Deletes the values as passed into Write(). - void DeleteVals(int num_fields, LogVal** vals); - -private: - struct Filter; - struct Stream; - struct WriterInfo; - - bool TraverseRecord(Stream* stream, Filter* filter, RecordType* rt, - TableVal* include, TableVal* exclude, string path, list indices); - - LogVal** RecordToFilterVals(Stream* stream, Filter* filter, - RecordVal* columns); - - LogVal* ValToLogVal(Val* val, BroType* ty = 0); - Stream* FindStream(EnumVal* id); - void RemoveDisabledWriters(Stream* stream); - void InstallRotationTimer(WriterInfo* winfo); - void Rotate(WriterInfo* info); - RecordVal* LookupRotationControl(EnumVal* writer, string path); - Filter* FindFilter(EnumVal* id, StringVal* filter); - WriterInfo* FindWriter(LogWriter* writer); - - vector streams; // Indexed by stream enum. -}; - -extern LogMgr* log_mgr; - -#endif diff --git a/src/LogWriter.cc b/src/LogWriter.cc deleted file mode 100644 index 8584a0b0b5..0000000000 --- a/src/LogWriter.cc +++ /dev/null @@ -1,158 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. - -#include "util.h" -#include "LogWriter.h" - -LogWriter::LogWriter() - { - buf = 0; - buf_len = 1024; - buffering = true; - disabled = false; - } - -LogWriter::~LogWriter() - { - if ( buf ) - free(buf); - - for(int i = 0; i < num_fields; ++i) - delete fields[i]; - - delete [] fields; - } - -bool LogWriter::Init(string arg_path, int arg_num_fields, - const LogField* const * arg_fields) - { - path = arg_path; - num_fields = arg_num_fields; - fields = arg_fields; - - if ( ! DoInit(arg_path, arg_num_fields, arg_fields) ) - { - disabled = true; - return false; - } - - return true; - } - -bool LogWriter::Write(int arg_num_fields, LogVal** vals) - { - // Double-check that the arguments match. If we get this from remote, - // something might be mixed up. - if ( num_fields != arg_num_fields ) - { - DBG_LOG(DBG_LOGGING, "Number of fields don't match in LogWriter::Write() (%d vs. %d)", - arg_num_fields, num_fields); - - DeleteVals(vals); - return false; - } - - for ( int i = 0; i < num_fields; ++i ) - { - if ( vals[i]->type != fields[i]->type ) - { - DBG_LOG(DBG_LOGGING, "Field type doesn't match in LogWriter::Write() (%d vs. %d)", - vals[i]->type, fields[i]->type); - DeleteVals(vals); - return false; - } - } - - bool result = DoWrite(num_fields, fields, vals); - - DeleteVals(vals); - - if ( ! result ) - disabled = true; - - return result; - } - -bool LogWriter::SetBuf(bool enabled) - { - if ( enabled == buffering ) - // No change. - return true; - - buffering = enabled; - - if ( ! DoSetBuf(enabled) ) - { - disabled = true; - return false; - } - - return true; - } - -bool LogWriter::Rotate(string rotated_path, double open, - double close, bool terminating) - { - if ( ! DoRotate(rotated_path, open, close, terminating) ) - { - disabled = true; - return false; - } - - return true; - } - -bool LogWriter::Flush() - { - if ( ! DoFlush() ) - { - disabled = true; - return false; - } - - return true; - } - -void LogWriter::Finish() - { - DoFinish(); - } - -const char* LogWriter::Fmt(const char* format, ...) - { - if ( ! buf ) - buf = (char*) malloc(buf_len); - - va_list al; - va_start(al, format); - int n = safe_vsnprintf(buf, buf_len, format, al); - va_end(al); - - if ( (unsigned int) n >= buf_len ) - { // Not enough room, grow the buffer. - buf_len = n + 32; - buf = (char*) realloc(buf, buf_len); - - // Is it portable to restart? - va_start(al, format); - n = safe_vsnprintf(buf, buf_len, format, al); - va_end(al); - } - - return buf; - } - -void LogWriter::Error(const char *msg) - { - log_mgr->Error(this, msg); - } - -void LogWriter::DeleteVals(LogVal** vals) - { - log_mgr->DeleteVals(num_fields, vals); - } - -bool LogWriter::FinishedRotation(string new_name, string old_name, double open, - double close, bool terminating) - { - return log_mgr->FinishedRotation(this, new_name, old_name, open, close, terminating); - } diff --git a/src/LogWriter.h b/src/LogWriter.h deleted file mode 100644 index 1d2f9fa4b2..0000000000 --- a/src/LogWriter.h +++ /dev/null @@ -1,192 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. -// -// Interface API for a log writer backend. The LogMgr creates a separate -// writer instance of pair of (writer type, output path). -// -// Note thay classes derived from LogWriter must be fully thread-safe and not -// use any non-thread-safe Bro functionality (which includes almost -// everything ...). In particular, do not use fmt() but LogWriter::Fmt()!. -// -// The one exception to this rule is the constructor: it is guaranteed to be -// executed inside the main thread and can thus in particular access global -// script variables. - -#ifndef LOGWRITER_H -#define LOGWRITER_H - -#include "LogMgr.h" -#include "BroString.h" - -class LogWriter { -public: - LogWriter(); - virtual ~LogWriter(); - - //// Interface methods to interact with the writer. Note that these - //// methods are not necessarily thread-safe and must be called only - //// from the main thread (which will typically mean only from the - //// LogMgr). In particular, they must not be called from the - //// writer's derived implementation. - - // One-time initialization of the writer to define the logged fields. - // Interpretation of "path" is left to the writer, and will be - // corresponding the value configured on the script-level. - // - // Returns false if an error occured, in which case the writer must - // not be used further. - // - // The new instance takes ownership of "fields", and will delete them - // when done. - bool Init(string path, int num_fields, const LogField* const * fields); - - // Writes one log entry. The method takes ownership of "vals" and - // will return immediately after queueing the write request, which is - // potentially before output has actually been written out. - // - // num_fields and the types of the LogVals must match what was passed - // to Init(). - // - // Returns false if an error occured, in which case the writer must - // not be used any further. - bool Write(int num_fields, LogVal** vals); - - // Sets the buffering status for the writer, if the writer supports - // that. (If not, it will be ignored). - bool SetBuf(bool enabled); - - // Flushes any currently buffered output, if the writer supports - // that. (If not, it will be ignored). - bool Flush(); - - // Triggers rotation, if the writer supports that. (If not, it will - // be ignored). - bool Rotate(string rotated_path, double open, double close, bool terminating); - - // Finishes writing to this logger regularly. Must not be called if - // an error has been indicated earlier. After calling this, no - // further writing must be performed. - void Finish(); - - //// Thread-safe methods that may be called from the writer - //// implementation. - - // The following methods return the information as passed to Init(). - const string Path() const { return path; } - int NumFields() const { return num_fields; } - const LogField* const * Fields() const { return fields; } - -protected: - // Methods for writers to override. If any of these returs false, it - // will be assumed that a fatal error has occured that prevents the - // writer from further operation. It will then be disabled and - // deleted. When return false, the writer should also report the - // error via Error(). Note that even if a writer does not support the - // functionality for one these methods (like rotation), it must still - // return true if that is not to be considered a fatal error. - // - // Called once for initialization of the writer. - virtual bool DoInit(string path, int num_fields, - const LogField* const * fields) = 0; - - // Called once per log entry to record. - virtual bool DoWrite(int num_fields, const LogField* const * fields, - LogVal** vals) = 0; - - // Called when the buffering status for this writer is changed. If - // buffering is disabled, the writer should attempt to write out - // information as quickly as possible even if doing so may have a - // performance impact. If enabled (which is the default), it may - // buffer data as helpful and write it out later in a way optimized - // for performance. The current buffering state can be queried via - // IsBuf(). - // - // A writer may ignore buffering changes if it doesn't fit with its - // semantics (but must still return true in that case). - virtual bool DoSetBuf(bool enabled) = 0; - - // Called to flush any currently buffered output. - // - // A writer may ignore flush requests if it doesn't fit with its - // semantics (but must still return true in that case). - virtual bool DoFlush() = 0; - - // Called when a log output is to be rotated. Most directly this only - // applies to writers writing into files, which should then close the - // current file and open a new one. However, a writer may also - // trigger other apppropiate actions if semantics are similar. - // - // Once rotation has finished, the implementation should call - // RotationDone() to signal the log manager that potential - // postprocessors can now run. - // - // "rotate_path" reflects the path to where the rotated output is to - // be moved, with specifics depending on the writer. It should - // generally be interpreted in a way consistent with that of "path" - // as passed into DoInit(). As an example, for file-based output, - // "rotate_path" could be the original filename extended with a - // timestamp indicating the time of the rotation. - // - // "open" and "close" are the network time's when the *current* file - // was opened and closed, respectively. - // - // "terminating" indicated whether the rotation request occurs due - // the main Bro prcoess terminating (and not because we've reach a - // regularly scheduled time for rotation). - // - // A writer may ignore rotation requests if it doesn't fit with its - // semantics (but must still return true in that case). - virtual bool DoRotate(string rotated_path, double open, double close, - bool terminating) = 0; - - // Called once on termination. Not called when any of the other - // methods has previously signaled an error, i.e., executing this - // method signals a regular shutdown of the writer. - virtual void DoFinish() = 0; - - //// Methods for writers to use. These are thread-safe. - - // A thread-safe version of fmt(). - const char* Fmt(const char* format, ...); - - // Returns the current buffering state. - bool IsBuf() { return buffering; } - - // Reports an error to the user. - void Error(const char *msg); - - // Signals to the log manager that a file has been rotated. - // - // new_name: The filename of the rotated file. old_name: The filename - // of the origina file. - // - // open/close: The timestamps when the original file was opened and - // closed, respectively. - // - // terminating: True if rotation request occured due to the main Bro - // process shutting down. - bool FinishedRotation(string new_name, string old_name, double open, - double close, bool terminating); - -private: - friend class LogMgr; - - // When an error occurs, we call this method to set a flag marking - // the writer as disabled. The LogMgr will check the flag later and - // remove the writer. - bool Disabled() { return disabled; } - - // Deletes the values as passed into Write(). - void DeleteVals(LogVal** vals); - - string path; - int num_fields; - const LogField* const * fields; - bool buffering; - bool disabled; - - // For implementing Fmt(). - char* buf; - unsigned int buf_len; -}; - -#endif diff --git a/src/LogWriterAscii.cc b/src/LogWriterAscii.cc deleted file mode 100644 index ad321dafaa..0000000000 --- a/src/LogWriterAscii.cc +++ /dev/null @@ -1,269 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. - -#include -#include - -#include "LogWriterAscii.h" -#include "NetVar.h" - -LogWriterAscii::LogWriterAscii() - { - file = 0; - - output_to_stdout = BifConst::LogAscii::output_to_stdout; - include_header = BifConst::LogAscii::include_header; - - separator_len = BifConst::LogAscii::separator->Len(); - separator = new char[separator_len]; - memcpy(separator, BifConst::LogAscii::separator->Bytes(), - separator_len); - - set_separator_len = BifConst::LogAscii::set_separator->Len(); - set_separator = new char[set_separator_len]; - memcpy(set_separator, BifConst::LogAscii::set_separator->Bytes(), - set_separator_len); - - empty_field_len = BifConst::LogAscii::empty_field->Len(); - empty_field = new char[empty_field_len]; - memcpy(empty_field, BifConst::LogAscii::empty_field->Bytes(), - empty_field_len); - - unset_field_len = BifConst::LogAscii::unset_field->Len(); - unset_field = new char[unset_field_len]; - memcpy(unset_field, BifConst::LogAscii::unset_field->Bytes(), - unset_field_len); - - header_prefix_len = BifConst::LogAscii::header_prefix->Len(); - header_prefix = new char[header_prefix_len]; - memcpy(header_prefix, BifConst::LogAscii::header_prefix->Bytes(), - header_prefix_len); - - } - -LogWriterAscii::~LogWriterAscii() - { - if ( file ) - fclose(file); - - delete [] separator; - delete [] set_separator; - delete [] empty_field; - delete [] unset_field; - delete [] header_prefix; - } - -bool LogWriterAscii::DoInit(string path, int num_fields, - const LogField* const * fields) - { - if ( output_to_stdout ) - path = "/dev/stdout"; - - fname = IsSpecial(path) ? path : path + ".log"; - - if ( ! (file = fopen(fname.c_str(), "w")) ) - { - Error(Fmt("cannot open %s: %s", fname.c_str(), - strerror(errno))); - - return false; - } - - if ( include_header ) - { - if ( fwrite(header_prefix, header_prefix_len, 1, file) != 1 ) - goto write_error; - - for ( int i = 0; i < num_fields; i++ ) - { - if ( i > 0 && - fwrite(separator, separator_len, 1, file) != 1 ) - goto write_error; - - const LogField* field = fields[i]; - - if ( fputs(field->name.c_str(), file) == EOF ) - goto write_error; - } - - if ( fputc('\n', file) == EOF ) - goto write_error; - } - - return true; - -write_error: - Error(Fmt("error writing to %s: %s", fname.c_str(), strerror(errno))); - return false; - } - -bool LogWriterAscii::DoFlush() - { - fflush(file); - return true; - } - -void LogWriterAscii::DoFinish() - { - } - -bool LogWriterAscii::DoWriteOne(ODesc* desc, LogVal* val, const LogField* field) - { - if ( ! val->present ) - { - desc->AddN(unset_field, unset_field_len); - return true; - } - - switch ( val->type ) { - - case TYPE_BOOL: - desc->Add(val->val.int_val ? "T" : "F"); - break; - - case TYPE_INT: - desc->Add(val->val.int_val); - break; - - case TYPE_COUNT: - case TYPE_COUNTER: - case TYPE_PORT: - desc->Add(val->val.uint_val); - break; - - case TYPE_SUBNET: - desc->Add(dotted_addr(val->val.subnet_val.net)); - desc->Add("/"); - desc->Add(val->val.subnet_val.width); - break; - - case TYPE_ADDR: - desc->Add(dotted_addr(val->val.addr_val)); - break; - - case TYPE_TIME: - case TYPE_INTERVAL: - char buf[32]; - snprintf(buf, sizeof(buf), "%.6f", val->val.double_val); - desc->Add(buf); - break; - - case TYPE_DOUBLE: - desc->Add(val->val.double_val); - break; - - case TYPE_ENUM: - case TYPE_STRING: - case TYPE_FILE: - case TYPE_FUNC: - { - int size = val->val.string_val->size(); - if ( size ) - desc->AddN(val->val.string_val->data(), val->val.string_val->size()); - else - desc->AddN(empty_field, empty_field_len); - break; - } - - case TYPE_TABLE: - { - if ( ! val->val.set_val.size ) - { - desc->AddN(empty_field, empty_field_len); - break; - } - - for ( int j = 0; j < val->val.set_val.size; j++ ) - { - if ( j > 0 ) - desc->AddN(set_separator, set_separator_len); - - if ( ! DoWriteOne(desc, val->val.set_val.vals[j], field) ) - return false; - } - - break; - } - - case TYPE_VECTOR: - { - if ( ! val->val.vector_val.size ) - { - desc->AddN(empty_field, empty_field_len); - break; - } - - for ( int j = 0; j < val->val.vector_val.size; j++ ) - { - if ( j > 0 ) - desc->AddN(set_separator, set_separator_len); - - if ( ! DoWriteOne(desc, val->val.vector_val.vals[j], field) ) - return false; - } - - break; - } - - default: - Error(Fmt("unsupported field format %d for %s", val->type, - field->name.c_str())); - return false; - } - - return true; - } - -bool LogWriterAscii::DoWrite(int num_fields, const LogField* const * fields, - LogVal** vals) - { - ODesc desc(DESC_READABLE); - desc.SetEscape(separator, separator_len); - - for ( int i = 0; i < num_fields; i++ ) - { - if ( i > 0 ) - desc.AddRaw(separator, separator_len); - - if ( ! DoWriteOne(&desc, vals[i], fields[i]) ) - return false; - } - - desc.AddRaw("\n", 1); - - if ( fwrite(desc.Bytes(), desc.Len(), 1, file) != 1 ) - { - Error(Fmt("error writing to %s: %s", fname.c_str(), strerror(errno))); - return false; - } - - if ( IsBuf() ) - fflush(file); - - return true; - } - -bool LogWriterAscii::DoRotate(string rotated_path, double open, - double close, bool terminating) - { - if ( IsSpecial(Path()) ) - // Don't rotate special files. - return true; - - fclose(file); - - string nname = rotated_path + ".log"; - rename(fname.c_str(), nname.c_str()); - - if ( ! FinishedRotation(nname, fname, open, close, terminating) ) - Error(Fmt("error rotating %s to %s", fname.c_str(), nname.c_str())); - - return DoInit(Path(), NumFields(), Fields()); - } - -bool LogWriterAscii::DoSetBuf(bool enabled) - { - // Nothing to do. - return true; - } - - diff --git a/src/LogWriterAscii.h b/src/LogWriterAscii.h deleted file mode 100644 index cceb685ff9..0000000000 --- a/src/LogWriterAscii.h +++ /dev/null @@ -1,55 +0,0 @@ -// See the file "COPYING" in the main distribution directory for copyright. -// -// Log writer for delimiter-separated ASCII logs. - -#ifndef LOGWRITERASCII_H -#define LOGWRITERASCII_H - -#include "LogWriter.h" - -class LogWriterAscii : public LogWriter { -public: - LogWriterAscii(); - ~LogWriterAscii(); - - static LogWriter* Instantiate() { return new LogWriterAscii; } - -protected: - virtual bool DoInit(string path, int num_fields, - const LogField* const * fields); - virtual bool DoWrite(int num_fields, const LogField* const * fields, - LogVal** vals); - virtual bool DoSetBuf(bool enabled); - virtual bool DoRotate(string rotated_path, double open, double close, - bool terminating); - virtual bool DoFlush(); - virtual void DoFinish(); - -private: - bool IsSpecial(string path) { return path.find("/dev/") == 0; } - bool DoWriteOne(ODesc* desc, LogVal* val, const LogField* field); - - FILE* file; - string fname; - - // Options set from the script-level. - bool output_to_stdout; - bool include_header; - - char* separator; - int separator_len; - - char* set_separator; - int set_separator_len; - - char* empty_field; - int empty_field_len; - - char* unset_field; - int unset_field_len; - - char* header_prefix; - int header_prefix_len; -}; - -#endif diff --git a/src/Login.cc b/src/Login.cc index 0a3849ccd0..e626fb3a0a 100644 --- a/src/Login.cc +++ b/src/Login.cc @@ -1,5 +1,3 @@ -// $Id: Login.cc 6724 2009-06-07 09:23:03Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -40,7 +38,7 @@ Login_Analyzer::Login_Analyzer(AnalyzerTag::Tag tag, Connection* conn) if ( ! re_skip_authentication ) { -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG HeapLeakChecker::Disabler disabler; #endif re_skip_authentication = init_RE(skip_authentication); diff --git a/src/MIME.cc b/src/MIME.cc index 3fe652d4cc..103cf149ef 100644 --- a/src/MIME.cc +++ b/src/MIME.cc @@ -1,5 +1,3 @@ -// $Id: MIME.cc 5906 2008-07-03 19:52:50Z vern $ - #include "config.h" #include "NetVar.h" @@ -875,11 +873,11 @@ void MIME_Entity::DataOctets(int len, const char* data) if ( data_buf_offset < 0 && ! GetDataBuffer() ) return; - while ( data_buf_offset < data_buf_length && len > 0 ) - { - data_buf_data[data_buf_offset++] = *data; - ++data; --len; - } + int n = min(data_buf_length - data_buf_offset, len); + memcpy(data_buf_data + data_buf_offset, data, n); + data += n; + data_buf_offset += n; + len -= n; if ( data_buf_offset == data_buf_length ) { diff --git a/src/MIME.h b/src/MIME.h index b5cdf556ac..52d943fb15 100644 --- a/src/MIME.h +++ b/src/MIME.h @@ -1,5 +1,3 @@ -// $Id: MIME.h 3526 2006-09-12 07:32:21Z vern $ - #ifndef mime_h #define mime_h @@ -97,6 +95,7 @@ public: virtual void EndOfData(); MIME_Entity* Parent() const { return parent; } + int MIMEContentType() const { return content_type; } StringVal* ContentType() const { return content_type_str; } StringVal* ContentSubType() const { return content_subtype_str; } int ContentTransferEncoding() const { return content_encoding; } diff --git a/src/NCP.cc b/src/NCP.cc index c065e48e87..edd882747c 100644 --- a/src/NCP.cc +++ b/src/NCP.cc @@ -1,5 +1,3 @@ -// $Id: NCP.cc 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -227,5 +225,7 @@ NCP_Analyzer::NCP_Analyzer(Connection* conn) NCP_Analyzer::~NCP_Analyzer() { delete session; + delete o_ncp; + delete r_ncp; } diff --git a/src/NCP.h b/src/NCP.h index 714d1879f8..1e783ee3ab 100644 --- a/src/NCP.h +++ b/src/NCP.h @@ -1,5 +1,3 @@ -// $Id: NCP.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef ncp_h diff --git a/src/NFA.cc b/src/NFA.cc index 74958823dc..4849755941 100644 --- a/src/NFA.cc +++ b/src/NFA.cc @@ -1,5 +1,3 @@ -// $Id: NFA.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/NFA.h b/src/NFA.h index 9dcb435d61..9877b8787c 100644 --- a/src/NFA.h +++ b/src/NFA.h @@ -1,5 +1,3 @@ -// $Id: NFA.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef nfa_h diff --git a/src/NFS.cc b/src/NFS.cc index 2951361baf..2911ee7f59 100644 --- a/src/NFS.cc +++ b/src/NFS.cc @@ -1,5 +1,3 @@ -// $Id: NFS.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include diff --git a/src/NFS.h b/src/NFS.h index 28a1d5c4ac..6a65143808 100644 --- a/src/NFS.h +++ b/src/NFS.h @@ -1,5 +1,3 @@ -// $Id: NFS.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef nfs_h diff --git a/src/NTP.cc b/src/NTP.cc index ac7d12fb6d..60b7e6202d 100644 --- a/src/NTP.cc +++ b/src/NTP.cc @@ -1,5 +1,3 @@ -// $Id: NTP.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/NTP.h b/src/NTP.h index c4ccdd644a..a22a7b231b 100644 --- a/src/NTP.h +++ b/src/NTP.h @@ -1,5 +1,3 @@ -// $Id: NTP.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef ntp_h diff --git a/src/NVT.cc b/src/NVT.cc index ad5e321595..5ba12ac32a 100644 --- a/src/NVT.cc +++ b/src/NVT.cc @@ -1,5 +1,3 @@ -// $Id: NVT.cc 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/NVT.h b/src/NVT.h index 63c0cc6620..61aa1ef740 100644 --- a/src/NVT.h +++ b/src/NVT.h @@ -1,5 +1,3 @@ -// $Id: NVT.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef nvt_h diff --git a/src/Net.cc b/src/Net.cc index df91521eee..5bfae2275b 100644 --- a/src/Net.cc +++ b/src/Net.cc @@ -1,5 +1,3 @@ -// $Id: Net.cc 6915 2009-09-22 05:04:17Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -44,7 +42,6 @@ extern int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); PList(PktSrc) pkt_srcs; // FIXME: We should really merge PktDumper and PacketDumper. -// It's on my to-do [Robin]. PktDumper* pkt_dumper = 0; int reading_live = 0; @@ -145,7 +142,7 @@ RETSIGTYPE watchdog(int /* signo */) return RETSIGVAL; } -void net_init(name_list& interfaces, name_list& readfiles, +void net_init(name_list& interfaces, name_list& readfiles, name_list& netflows, name_list& flowfiles, const char* writefile, const char* filter, const char* secondary_filter, int do_watchdog) @@ -250,12 +247,14 @@ void net_init(name_list& interfaces, name_list& readfiles, FlowSocketSrc* fs = new FlowSocketSrc(netflows[i]); if ( ! fs->IsOpen() ) + { reporter->Error("%s: problem with netflow socket %s - %s\n", prog, netflows[i], fs->ErrorMsg()); - else - { - io_sources.Register(fs); + delete fs; } + + else + io_sources.Register(fs); } } @@ -456,6 +455,7 @@ void net_run() // date on timers and events. network_time = ct; expire_timers(); + usleep(1); // Just yield. } } @@ -485,6 +485,8 @@ void net_run() // since Bro timers are not high-precision anyway.) if ( ! using_communication ) usleep(100000); + else + usleep(1000); // Flawfinder says about usleep: // diff --git a/src/Net.h b/src/Net.h index 337e50720f..9e68cc025b 100644 --- a/src/Net.h +++ b/src/Net.h @@ -1,5 +1,3 @@ -// $Id: Net.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef net_h @@ -75,6 +73,9 @@ extern bool terminating; // True if the remote serializer is to be activated. extern bool using_communication; +// Snaplen passed to libpcap. +extern int snaplen; + extern const struct pcap_pkthdr* current_hdr; extern const u_char* current_pkt; extern int current_dispatched; diff --git a/src/NetVar.cc b/src/NetVar.cc index cc40681494..59cc1cc633 100644 --- a/src/NetVar.cc +++ b/src/NetVar.cc @@ -1,5 +1,3 @@ -// $Id: NetVar.cc 6887 2009-08-20 05:17:33Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -18,7 +16,9 @@ RecordType* pcap_packet; RecordType* signature_state; EnumType* transport_proto; TableType* string_set; +TableType* string_array; TableType* count_set; +VectorType* string_vec; int watchdog_interval; @@ -47,15 +47,6 @@ int tcp_max_initial_window; int tcp_max_above_hole_without_any_acks; int tcp_excessive_data_without_further_acks; -int ssl_compare_cipherspecs; -int ssl_analyze_certificates; -int ssl_store_certificates; -int ssl_verify_certificates; -int ssl_store_key_material; -int ssl_max_cipherspec_size; -StringVal* ssl_store_cert_path; -StringVal* x509_trusted_cert_path; -TableType* cipher_suites_list; RecordType* x509_type; double non_analyzed_lifetime; @@ -192,8 +183,6 @@ StringVal* ssl_ca_certificate; StringVal* ssl_private_key; StringVal* ssl_passphrase; -StringVal* x509_crl_file; - Val* profiling_file; double profiling_interval; int expensive_profiling_multiple; @@ -213,11 +202,6 @@ int sig_max_group_size; int enable_syslog; -int use_connection_compressor; -int cc_handle_resets; -int cc_handle_only_syns; -int cc_instantiate_on_data; - TableType* irc_join_list; RecordType* irc_join_info; TableVal* irc_servers; @@ -330,6 +314,8 @@ void init_net_var() pcap_packet = internal_type("pcap_packet")->AsRecordType(); transport_proto = internal_type("transport_proto")->AsEnumType(); string_set = internal_type("string_set")->AsTableType(); + string_array = internal_type("string_array")->AsTableType(); + string_vec = internal_type("string_vec")->AsVectorType(); ignore_checksums = opt_internal_int("ignore_checksums"); partial_connection_ok = opt_internal_int("partial_connection_ok"); @@ -356,17 +342,7 @@ void init_net_var() tcp_excessive_data_without_further_acks = opt_internal_int("tcp_excessive_data_without_further_acks"); - ssl_compare_cipherspecs = opt_internal_int("ssl_compare_cipherspecs"); - ssl_analyze_certificates = opt_internal_int("ssl_analyze_certificates"); - ssl_store_certificates = opt_internal_int("ssl_store_certificates"); - ssl_verify_certificates = opt_internal_int("ssl_verify_certificates"); - ssl_store_key_material = opt_internal_int("ssl_store_key_material"); - ssl_max_cipherspec_size = opt_internal_int("ssl_max_cipherspec_size"); - - x509_trusted_cert_path = opt_internal_string("X509_trusted_cert_path"); - ssl_store_cert_path = opt_internal_string("ssl_store_cert_path"); x509_type = internal_type("X509")->AsRecordType(); - x509_crl_file = opt_internal_string("X509_crl_file"); non_analyzed_lifetime = opt_internal_double("non_analyzed_lifetime"); tcp_inactivity_timeout = opt_internal_double("tcp_inactivity_timeout"); @@ -523,12 +499,6 @@ void init_net_var() gap_report_freq = opt_internal_double("gap_report_freq"); - use_connection_compressor = - opt_internal_int("use_connection_compressor"); - cc_handle_resets = opt_internal_int("cc_handle_resets"); - cc_handle_only_syns = opt_internal_int("cc_handle_only_syns"); - cc_instantiate_on_data = opt_internal_int("cc_instantiate_on_data"); - irc_join_info = internal_type("irc_join_info")->AsRecordType(); irc_join_list = internal_type("irc_join_list")->AsTableType(); irc_servers = internal_val("irc_servers")->AsTableVal(); diff --git a/src/NetVar.h b/src/NetVar.h index b9667a19c9..425ea93e09 100644 --- a/src/NetVar.h +++ b/src/NetVar.h @@ -1,5 +1,3 @@ -// $Id: NetVar.h 6887 2009-08-20 05:17:33Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef netvar_h @@ -21,7 +19,9 @@ extern RecordType* SYN_packet; extern RecordType* pcap_packet; extern EnumType* transport_proto; extern TableType* string_set; +extern TableType* string_array; extern TableType* count_set; +extern VectorType* string_vec; extern int watchdog_interval; @@ -50,17 +50,7 @@ extern int tcp_max_initial_window; extern int tcp_max_above_hole_without_any_acks; extern int tcp_excessive_data_without_further_acks; -// see policy/ssl.bro for details -extern int ssl_compare_cipherspecs; -extern int ssl_analyze_certificates; -extern int ssl_store_certificates; -extern int ssl_verify_certificates; -extern int ssl_store_key_material; -extern int ssl_max_cipherspec_size; -extern StringVal* ssl_store_cert_path; -extern StringVal* x509_trusted_cert_path; extern RecordType* x509_type; -extern StringVal* x509_crl_file; extern double non_analyzed_lifetime; extern double tcp_inactivity_timeout; @@ -216,11 +206,6 @@ extern int sig_max_group_size; extern int enable_syslog; -extern int use_connection_compressor; -extern int cc_handle_resets; -extern int cc_handle_only_syns; -extern int cc_instantiate_on_data; - extern TableType* irc_join_list; extern RecordType* irc_join_info; extern TableVal* irc_servers; diff --git a/src/NetbiosSSN.cc b/src/NetbiosSSN.cc index 0bb135f59d..362d974956 100644 --- a/src/NetbiosSSN.cc +++ b/src/NetbiosSSN.cc @@ -1,5 +1,3 @@ -// $Id: NetbiosSSN.cc 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -112,7 +110,7 @@ int NetbiosSSN_Interpreter::ParseDatagram(const u_char* data, int len, return 0; } - + int NetbiosSSN_Interpreter::ParseBroadcast(const u_char* data, int len, int is_query) { @@ -133,6 +131,9 @@ int NetbiosSSN_Interpreter::ParseBroadcast(const u_char* data, int len, return 0; } + delete srcname; + delete dstname; + return 0; } diff --git a/src/NetbiosSSN.h b/src/NetbiosSSN.h index ba724fa2fb..7c4dd91b90 100644 --- a/src/NetbiosSSN.h +++ b/src/NetbiosSSN.h @@ -1,5 +1,3 @@ -// $Id: NetbiosSSN.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef netbios_ssn_h diff --git a/src/OSFinger.cc b/src/OSFinger.cc index e8fd929885..3368a8e40c 100644 --- a/src/OSFinger.cc +++ b/src/OSFinger.cc @@ -1,5 +1,3 @@ -// $Id: OSFinger.cc 5857 2008-06-26 23:00:03Z vern $ - /* Taken with permission from: @@ -65,15 +63,16 @@ OSFingerprint::OSFingerprint(FingerprintMode arg_mode) } } -bool OSFingerprint::CacheMatch(uint32 addr, int id) +bool OSFingerprint::CacheMatch(const IPAddr& addr, int id) { - HashKey key = HashKey(&addr, 1); + HashKey* key = addr.GetHashKey(); int* pid = new int; *pid=id; - int* prev = os_matches.Insert(&key, pid); + int* prev = os_matches.Insert(key, pid); bool ret = (prev ? *prev != id : 1); if (prev) delete prev; + delete key; return ret; } @@ -87,8 +86,8 @@ void OSFingerprint::collide(uint32 id) if (sig[id].ttl % 32 && sig[id].ttl != 255 && sig[id].ttl % 30) { problems=1; - reporter->Warning(fmt("OS fingerprinting: [!] Unusual TTL (%d) for signature '%s %s' (line %d).", - sig[id].ttl,sig[id].os,sig[id].desc,sig[id].line)); + reporter->Warning("OS fingerprinting: [!] Unusual TTL (%d) for signature '%s %s' (line %d).", + sig[id].ttl,sig[id].os,sig[id].desc,sig[id].line); } for (i=0;iWarning(fmt("OS fingerprinting: [!] Duplicate signature name: '%s %s' (line %d and %d).", - sig[i].os,sig[i].desc,sig[i].line,sig[id].line)); + reporter->Warning("OS fingerprinting: [!] Duplicate signature name: '%s %s' (line %d and %d).", + sig[i].os,sig[i].desc,sig[i].line,sig[id].line); } /* If TTLs are sufficiently away from each other, the risk of @@ -279,10 +278,10 @@ do_const: if (sig[id].opt[j] ^ sig[i].opt[j]) goto reloop; problems=1; - reporter->Warning(fmt("OS fingerprinting: [!] Signature '%s %s' (line %d)\n" + reporter->Warning("OS fingerprinting: [!] Signature '%s %s' (line %d)\n" " is already covered by '%s %s' (line %d).", sig[id].os,sig[id].desc,sig[id].line,sig[i].os,sig[i].desc, - sig[i].line)); + sig[i].line); reloop: ; diff --git a/src/OSFinger.h b/src/OSFinger.h index f1f9e492f2..0968fb5fd3 100644 --- a/src/OSFinger.h +++ b/src/OSFinger.h @@ -1,5 +1,3 @@ -// $Id: OSFinger.h 5857 2008-06-26 23:00:03Z vern $ - // Taken with permission from: // // p0f - passive OS fingerprinting (GNU LESSER GENERAL PUBLIC LICENSE) @@ -16,6 +14,7 @@ #include "util.h" #include "Dict.h" #include "Reporter.h" +#include "IPAddr.h" // Size limit for size wildcards. #define PACKET_BIG 100 @@ -90,7 +89,7 @@ public: int FindMatch(struct os_type* retval, uint16 tot, uint8 DF_flag, uint8 TTL, uint16 WSS, uint8 ocnt, uint8* op, uint16 MSS, uint8 win_scale, uint32 tstamp, uint32 quirks, uint8 ECN) const; - bool CacheMatch(uint32 addr, int id); + bool CacheMatch(const IPAddr& addr, int id); int Get_OS_From_SYN(struct os_type* retval, uint16 tot, uint8 DF_flag, uint8 TTL, uint16 WSS, @@ -105,7 +104,7 @@ protected: void Error(const char* msg) { - reporter->Error(msg); + reporter->Error("%s", msg); err = true; } diff --git a/src/Obj.cc b/src/Obj.cc index dfa8ed0148..0b82695f3d 100644 --- a/src/Obj.cc +++ b/src/Obj.cc @@ -1,5 +1,3 @@ -// $Id: Obj.cc 6752 2009-06-14 04:24:52Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -233,6 +231,8 @@ bool BroObj::DoUnserialize(UnserialInfo* info) { DO_UNSERIALIZE(SerialObj); + delete location; + UNSERIALIZE_OPTIONAL(location, Location::Unserialize(info)); return true; } diff --git a/src/Obj.h b/src/Obj.h index d5a60aa972..be0d91b398 100644 --- a/src/Obj.h +++ b/src/Obj.h @@ -1,5 +1,3 @@ -// $Id: Obj.h 6781 2009-06-28 00:50:04Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef obj_h diff --git a/src/Op.h b/src/Op.h index 7c8d4afe38..a628a6bb68 100644 --- a/src/Op.h +++ b/src/Op.h @@ -1,5 +1,3 @@ -// $Id: Op.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef op_h diff --git a/src/PIA.cc b/src/PIA.cc index 32c0b40fc5..9adb4ccab3 100644 --- a/src/PIA.cc +++ b/src/PIA.cc @@ -1,5 +1,3 @@ -// $Id: PIA.cc,v 1.1.2.14 2006/05/31 23:19:07 sommer Exp $ - #include "PIA.h" #include "RuleMatcher.h" #include "TCP_Reassembler.h" @@ -198,20 +196,20 @@ void PIA_TCP::FirstPacket(bool is_orig, const IP_Hdr* ip) ip4->ip_p = IPPROTO_TCP; // Cast to const so that it doesn't delete it. - ip4_hdr = new IP_Hdr((const struct ip*) ip4); + ip4_hdr = new IP_Hdr(ip4, false); } if ( is_orig ) { - copy_addr(Conn()->OrigAddr(), &ip4->ip_src.s_addr); - copy_addr(Conn()->RespAddr(), &ip4->ip_dst.s_addr); + Conn()->OrigAddr().CopyIPv4(&ip4->ip_src); + Conn()->RespAddr().CopyIPv4(&ip4->ip_dst); tcp4->th_sport = htons(Conn()->OrigPort()); tcp4->th_dport = htons(Conn()->RespPort()); } else { - copy_addr(Conn()->RespAddr(), &ip4->ip_src.s_addr); - copy_addr(Conn()->OrigAddr(), &ip4->ip_dst.s_addr); + Conn()->RespAddr().CopyIPv4(&ip4->ip_src); + Conn()->OrigAddr().CopyIPv4(&ip4->ip_dst); tcp4->th_sport = htons(Conn()->RespPort()); tcp4->th_dport = htons(Conn()->OrigPort()); } diff --git a/src/PIA.h b/src/PIA.h index 8a1079f617..907350bbdf 100644 --- a/src/PIA.h +++ b/src/PIA.h @@ -1,5 +1,3 @@ -// $Id:$ -// // An analyzer for application-layer protocol-detection. #ifndef PIA_H diff --git a/src/POP3.cc b/src/POP3.cc index b364541be1..3075e76507 100644 --- a/src/POP3.cc +++ b/src/POP3.cc @@ -1,5 +1,3 @@ -// $Id: POP3.cc 6782 2009-06-28 02:19:03Z vern $ - // This code contributed to Bro by Florian Schimandl, Hugh Dollman and // Robin Sommer. @@ -160,6 +158,7 @@ void POP3_Analyzer::ProcessRequest(int length, const char* line) if ( e >= end ) { Weird("pop3_malformed_auth_plain"); + delete decoded; return; } @@ -169,6 +168,7 @@ void POP3_Analyzer::ProcessRequest(int length, const char* line) if ( s >= end ) { Weird("pop3_malformed_auth_plain"); + delete decoded; return; } diff --git a/src/POP3.h b/src/POP3.h index 6ad0a7e755..8d09d5e686 100644 --- a/src/POP3.h +++ b/src/POP3.h @@ -1,5 +1,3 @@ -// $Id: POP3.h 3526 2006-09-12 07:32:21Z vern $ - // This code contributed to Bro by Florian Schimandl and Hugh Dollman. // // An analyser for the POP3 protocol. diff --git a/src/PacketDumper.cc b/src/PacketDumper.cc index d401cd63cb..84b22ff17c 100644 --- a/src/PacketDumper.cc +++ b/src/PacketDumper.cc @@ -1,5 +1,3 @@ -// $Id:$ -// // See the file "COPYING" in the main distribution directory for copyright. diff --git a/src/PacketDumper.h b/src/PacketDumper.h index b0d5943b36..baace47876 100644 --- a/src/PacketDumper.h +++ b/src/PacketDumper.h @@ -1,5 +1,3 @@ -// $Id:$ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef packetdumper_h diff --git a/src/PacketFilter.cc b/src/PacketFilter.cc index fa88350713..4fb3b1c8f7 100644 --- a/src/PacketFilter.cc +++ b/src/PacketFilter.cc @@ -1,13 +1,11 @@ -// $Id: PacketFilter.cc 967 2005-01-03 07:19:06Z vern $ - #include "PacketFilter.h" -void PacketFilter::AddSrc(addr_type src, uint32 tcp_flags, double probability) +void PacketFilter::AddSrc(const IPAddr& src, uint32 tcp_flags, double probability) { Filter* f = new Filter; f->tcp_flags = tcp_flags; f->probability = uint32(probability * RAND_MAX); - src_filter.Insert(src, NUM_ADDR_WORDS * 32, f); + src_filter.Insert(src, 128, f); } void PacketFilter::AddSrc(Val* src, uint32 tcp_flags, double probability) @@ -18,12 +16,12 @@ void PacketFilter::AddSrc(Val* src, uint32 tcp_flags, double probability) src_filter.Insert(src, f); } -void PacketFilter::AddDst(addr_type dst, uint32 tcp_flags, double probability) +void PacketFilter::AddDst(const IPAddr& dst, uint32 tcp_flags, double probability) { Filter* f = new Filter; f->tcp_flags = tcp_flags; f->probability = uint32(probability * RAND_MAX); - dst_filter.Insert(dst, NUM_ADDR_WORDS * 32, f); + dst_filter.Insert(dst, 128, f); } void PacketFilter::AddDst(Val* dst, uint32 tcp_flags, double probability) @@ -34,9 +32,9 @@ void PacketFilter::AddDst(Val* dst, uint32 tcp_flags, double probability) dst_filter.Insert(dst, f); } -bool PacketFilter::RemoveSrc(addr_type src) +bool PacketFilter::RemoveSrc(const IPAddr& src) { - return src_filter.Remove(src, NUM_ADDR_WORDS * 32) != 0; + return src_filter.Remove(src, 128) != 0; } bool PacketFilter::RemoveSrc(Val* src) @@ -44,9 +42,9 @@ bool PacketFilter::RemoveSrc(Val* src) return src_filter.Remove(src) != NULL; } -bool PacketFilter::RemoveDst(addr_type dst) +bool PacketFilter::RemoveDst(const IPAddr& dst) { - return dst_filter.Remove(dst, NUM_ADDR_WORDS * 32) != NULL; + return dst_filter.Remove(dst, 128) != NULL; } bool PacketFilter::RemoveDst(Val* dst) @@ -56,21 +54,11 @@ bool PacketFilter::RemoveDst(Val* dst) bool PacketFilter::Match(const IP_Hdr* ip, int len, int caplen) { -#ifdef BROv6 - Filter* f = (Filter*) src_filter.Lookup(ip->SrcAddr(), - NUM_ADDR_WORDS * 32); -#else - Filter* f = (Filter*) src_filter.Lookup(*ip->SrcAddr(), - NUM_ADDR_WORDS * 32); -#endif + Filter* f = (Filter*) src_filter.Lookup(ip->SrcAddr(), 128); if ( f ) return MatchFilter(*f, *ip, len, caplen); -#ifdef BROv6 - f = (Filter*) dst_filter.Lookup(ip->DstAddr(), NUM_ADDR_WORDS * 32); -#else - f = (Filter*) dst_filter.Lookup(*ip->DstAddr(), NUM_ADDR_WORDS * 32); -#endif + f = (Filter*) dst_filter.Lookup(ip->DstAddr(), 128); if ( f ) return MatchFilter(*f, *ip, len, caplen); @@ -83,9 +71,7 @@ bool PacketFilter::MatchFilter(const Filter& f, const IP_Hdr& ip, if ( ip.NextProto() == IPPROTO_TCP && f.tcp_flags ) { // Caution! The packet sanity checks have not been performed yet - const struct ip* ip4 = ip.IP4_Hdr(); - - int ip_hdr_len = ip4->ip_hl * 4; + int ip_hdr_len = ip.HdrLen(); len -= ip_hdr_len; // remove IP header caplen -= ip_hdr_len; @@ -94,8 +80,7 @@ bool PacketFilter::MatchFilter(const Filter& f, const IP_Hdr& ip, // Packet too short, will be dropped anyway. return false; - const struct tcphdr* tp = - (const struct tcphdr*) ((u_char*) ip4 + ip_hdr_len); + const struct tcphdr* tp = (const struct tcphdr*) ip.Payload(); if ( tp->th_flags & f.tcp_flags ) // At least one of the flags is set, so don't drop diff --git a/src/PacketFilter.h b/src/PacketFilter.h index 6a70504280..3d7a3aa3be 100644 --- a/src/PacketFilter.h +++ b/src/PacketFilter.h @@ -1,5 +1,3 @@ -// $Id: PacketFilter.h 80 2004-07-14 20:15:50Z jason $ -// // Provides some very limited but fast packet filter mechanisms #ifndef PACKETFILTER_H @@ -16,16 +14,16 @@ public: // Drops all packets from a particular source (which may be given // as an AddrVal or a SubnetVal) which hasn't any of TCP flags set // (TH_*) with the given probability (from 0..MAX_PROB). - void AddSrc(addr_type src, uint32 tcp_flags, double probability); + void AddSrc(const IPAddr& src, uint32 tcp_flags, double probability); void AddSrc(Val* src, uint32 tcp_flags, double probability); - void AddDst(addr_type src, uint32 tcp_flags, double probability); + void AddDst(const IPAddr& src, uint32 tcp_flags, double probability); void AddDst(Val* src, uint32 tcp_flags, double probability); // Removes the filter entry for the given src/dst // Returns false if filter doesn not exist. - bool RemoveSrc(addr_type src); + bool RemoveSrc(const IPAddr& src); bool RemoveSrc(Val* dst); - bool RemoveDst(addr_type dst); + bool RemoveDst(const IPAddr& dst); bool RemoveDst(Val* dst); // Returns true if packet matches a drop filter diff --git a/src/PacketSort.cc b/src/PacketSort.cc index 8beaa51474..a7e2b04572 100644 --- a/src/PacketSort.cc +++ b/src/PacketSort.cc @@ -1,5 +1,3 @@ -// $Id: PacketSort.cc 3228 2006-06-08 02:12:03Z vern $ - #include "IP.h" #include "PacketSort.h" @@ -29,13 +27,16 @@ PacketSortElement::PacketSortElement(PktSrc* arg_src, { const struct ip* ip = (const struct ip*) (pkt + hdr_size); if ( ip->ip_v == 4 ) - ip_hdr = new IP_Hdr(ip); + ip_hdr = new IP_Hdr(ip, false); + else if ( ip->ip_v == 6 && (caplen >= sizeof(struct ip6_hdr) + hdr_size) ) + ip_hdr = new IP_Hdr((const struct ip6_hdr*) ip, false, caplen - hdr_size); else - ip_hdr = new IP_Hdr((const struct ip6_hdr*) ip); + // Weird will be generated later in NetSessions::NextPacket. + return; if ( ip_hdr->NextProto() == IPPROTO_TCP && // Note: can't sort fragmented packets - (ip_hdr->FragField() & 0x3fff) == 0 ) + ( ! ip_hdr->IsFragment() ) ) { tcp_offset = hdr_size + ip_hdr->HdrLen(); if ( caplen >= tcp_offset + sizeof(struct tcphdr) ) @@ -67,7 +68,7 @@ PacketSortElement::PacketSortElement(PktSrc* arg_src, payload_length = ip_hdr->PayloadLen() - tp->th_off * 4; - key = id.BuildConnKey(); + key = BuildConnIDHashKey(id); is_tcp = 1; } diff --git a/src/PacketSort.h b/src/PacketSort.h index 6c6a4f4994..199da0732f 100644 --- a/src/PacketSort.h +++ b/src/PacketSort.h @@ -1,5 +1,3 @@ -// $Id: PacketSort.h 3228 2006-06-08 02:12:03Z vern $ - #ifndef packetsort_h #define packetsort_h diff --git a/src/PersistenceSerializer.cc b/src/PersistenceSerializer.cc index 60247c7519..d9baad05bb 100644 --- a/src/PersistenceSerializer.cc +++ b/src/PersistenceSerializer.cc @@ -1,5 +1,3 @@ -// $Id: PersistenceSerializer.cc 6752 2009-06-14 04:24:52Z vern $ - #include #include #include @@ -139,7 +137,7 @@ bool PersistenceSerializer::CheckForFile(UnserialInfo* info, const char* file, bool PersistenceSerializer::ReadAll(bool is_init, bool delete_files) { -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG HeapLeakChecker::Disabler disabler; #endif @@ -202,7 +200,13 @@ void PersistenceSerializer::GotEvent(const char* name, double time, void PersistenceSerializer::GotFunctionCall(const char* name, double time, Func* func, val_list* args) { - func->Call(args); + try + { + func->Call(args); + } + + catch ( InterpreterException& e ) + { /* Already reported. */ } } void PersistenceSerializer::GotStateAccess(StateAccess* s) diff --git a/src/PersistenceSerializer.h b/src/PersistenceSerializer.h index 572ab0238e..dcd712bf84 100644 --- a/src/PersistenceSerializer.h +++ b/src/PersistenceSerializer.h @@ -1,5 +1,3 @@ -// $Id: PersistenceSerializer.h 2698 2006-04-03 05:50:52Z vern $ -// // Implements persistance for Bro's data structures. #ifndef persistence_serializer_h diff --git a/src/PktSrc.cc b/src/PktSrc.cc index 23391c1ffa..615815b41b 100644 --- a/src/PktSrc.cc +++ b/src/PktSrc.cc @@ -1,5 +1,3 @@ -// $Id: PktSrc.cc 6951 2009-12-04 22:23:28Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include @@ -19,13 +17,11 @@ #include #endif -int snaplen = 8192; // really want "capture entire packet" - - PktSrc::PktSrc() { interface = readfile = 0; data = last_data = 0; + memset(&hdr, 0, sizeof(hdr)); hdr_size = 0; datalink = 0; netmask = 0xffffff00; @@ -80,7 +76,9 @@ int PktSrc::ExtractNextPacket() } data = last_data = pcap_next(pd, &hdr); - next_timestamp = hdr.ts.tv_sec + double(hdr.ts.tv_usec) / 1e6; + + if ( data ) + next_timestamp = hdr.ts.tv_sec + double(hdr.ts.tv_usec) / 1e6; if ( pseudo_realtime ) current_wallclock = current_time(true); @@ -384,6 +382,7 @@ void PktSrc::AddSecondaryTablePrograms() { delete program; Close(); + return; } SecondaryProgram* sp = new SecondaryProgram(program, se); @@ -492,7 +491,7 @@ PktInterfaceSrc::PktInterfaceSrc(const char* arg_interface, const char* filter, // Couldn't get header size. return; - reporter->Info("listening on %s\n", interface); + reporter->Info("listening on %s, capture length %d bytes\n", interface, snaplen); } else closed = true; diff --git a/src/PktSrc.h b/src/PktSrc.h index 04524ec405..70eef4dd00 100644 --- a/src/PktSrc.h +++ b/src/PktSrc.h @@ -1,5 +1,3 @@ -// $Id: PktSrc.h 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef pktsrc_h diff --git a/src/PolicyFile.cc b/src/PolicyFile.cc index 22a6a96cb6..9f67ee88a1 100644 --- a/src/PolicyFile.cc +++ b/src/PolicyFile.cc @@ -1,5 +1,3 @@ -// $Id: PolicyFile.cc 1473 2005-10-06 21:32:45Z vern $ - #include "config.h" #include @@ -90,7 +88,8 @@ bool LoadPolicyFileText(const char* policy_filename) // ### This code is not necessarily Unicode safe! // (probably fine with UTF-8) pf->filedata = new char[size+1]; - fread(pf->filedata, size, 1, f); + if ( fread(pf->filedata, size, 1, f) != 1 ) + reporter->InternalError("Failed to fread() file data"); pf->filedata[size] = 0; fclose(f); diff --git a/src/PolicyFile.h b/src/PolicyFile.h index ac040d5584..62c475a98b 100644 --- a/src/PolicyFile.h +++ b/src/PolicyFile.h @@ -1,5 +1,3 @@ -// $Id: PolicyFile.h 80 2004-07-14 20:15:50Z jason $ - // Functions for displaying the contents of policy files. // Mostly useful for debugging code that wants to show context. // diff --git a/src/Portmap.cc b/src/Portmap.cc index e806acdc7a..dd1049a361 100644 --- a/src/Portmap.cc +++ b/src/Portmap.cc @@ -1,5 +1,3 @@ -// $Id: Portmap.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/Portmap.h b/src/Portmap.h index cb2cb1293c..62e954bc80 100644 --- a/src/Portmap.h +++ b/src/Portmap.h @@ -1,5 +1,3 @@ -// $Id: Portmap.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef portmap_h diff --git a/src/PrefixTable.cc b/src/PrefixTable.cc index 03e1495957..58a488a9f1 100644 --- a/src/PrefixTable.cc +++ b/src/PrefixTable.cc @@ -1,36 +1,19 @@ -// $Id: PrefixTable.cc 1016 2005-01-31 21:23:50Z vern $ - #include "PrefixTable.h" #include "Reporter.h" -// IPv4 version. -inline static prefix_t* make_prefix(const uint32 addr, int width) +inline static prefix_t* make_prefix(const IPAddr& addr, int width) { prefix_t* prefix = (prefix_t*) safe_malloc(sizeof(prefix_t)); - memcpy(&prefix->add.sin, &addr, sizeof(prefix->add.sin)) ; - prefix->family = AF_INET; - prefix->bitlen = width; - prefix->ref_count = 1; - - return prefix; - } - -#ifdef BROv6 -inline static prefix_t* make_prefix(const uint32* addr, int width) - { - prefix_t* prefix = (prefix_t*) safe_malloc(sizeof(prefix_t)); - - memcpy(&prefix->add.sin6, addr, 4 * sizeof(uint32)); + addr.CopyIPv6(&prefix->add.sin6); prefix->family = AF_INET6; prefix->bitlen = width; prefix->ref_count = 1; return prefix; } -#endif -void* PrefixTable::Insert(const_addr_type addr, int width, void* data) +void* PrefixTable::Insert(const IPAddr& addr, int width, void* data) { prefix_t* prefix = make_prefix(addr, width); patricia_node_t* node = patricia_lookup(tree, prefix); @@ -57,12 +40,12 @@ void* PrefixTable::Insert(const Val* value, void* data) switch ( value->Type()->Tag() ) { case TYPE_ADDR: - return Insert(value->AsAddr(), NUM_ADDR_WORDS * 32, data); + return Insert(value->AsAddr(), 128, data); break; case TYPE_SUBNET: - return Insert(value->AsSubNet()->net, - value->AsSubNet()->width, data); + return Insert(value->AsSubNet().Prefix(), + value->AsSubNet().LengthIPv6(), data); break; default: @@ -71,7 +54,7 @@ void* PrefixTable::Insert(const Val* value, void* data) } } -void* PrefixTable::Lookup(const_addr_type addr, int width, bool exact) const +void* PrefixTable::Lookup(const IPAddr& addr, int width, bool exact) const { prefix_t* prefix = make_prefix(addr, width); patricia_node_t* node = @@ -91,12 +74,12 @@ void* PrefixTable::Lookup(const Val* value, bool exact) const switch ( value->Type()->Tag() ) { case TYPE_ADDR: - return Lookup(value->AsAddr(), NUM_ADDR_WORDS * 32, exact); + return Lookup(value->AsAddr(), 128, exact); break; case TYPE_SUBNET: - return Lookup(value->AsSubNet()->net, - value->AsSubNet()->width, exact); + return Lookup(value->AsSubNet().Prefix(), + value->AsSubNet().LengthIPv6(), exact); break; default: @@ -106,7 +89,7 @@ void* PrefixTable::Lookup(const Val* value, bool exact) const } } -void* PrefixTable::Remove(const_addr_type addr, int width) +void* PrefixTable::Remove(const IPAddr& addr, int width) { prefix_t* prefix = make_prefix(addr, width); patricia_node_t* node = patricia_search_exact(tree, prefix); @@ -130,11 +113,12 @@ void* PrefixTable::Remove(const Val* value) switch ( value->Type()->Tag() ) { case TYPE_ADDR: - return Remove(value->AsAddr(), NUM_ADDR_WORDS * 32); + return Remove(value->AsAddr(), 128); break; case TYPE_SUBNET: - return Remove(value->AsSubNet()->net, value->AsSubNet()->width); + return Remove(value->AsSubNet().Prefix(), + value->AsSubNet().LengthIPv6()); break; default: diff --git a/src/PrefixTable.h b/src/PrefixTable.h index b718b3c561..2e5f43a0a8 100644 --- a/src/PrefixTable.h +++ b/src/PrefixTable.h @@ -1,10 +1,9 @@ -// $Id: PrefixTable.h 969 2005-01-04 06:36:21Z vern $ - #ifndef PREFIXTABLE_H #define PREFIXTABLE_H #include "Val.h" #include "net_util.h" +#include "IPAddr.h" extern "C" { #include "patricia.h" @@ -26,7 +25,7 @@ public: // Addr in network byte order. If data is zero, acts like a set. // Returns ptr to old data if already existing. // For existing items without data, returns non-nil if found. - void* Insert(const_addr_type addr, int width, void* data = 0); + void* Insert(const IPAddr& addr, int width, void* data = 0); // Value may be addr or subnet. void* Insert(const Val* value, void* data = 0); @@ -34,11 +33,11 @@ public: // Returns nil if not found, pointer to data otherwise. // For items without data, returns non-nil if found. // If exact is false, performs exact rather than longest-prefix match. - void* Lookup(const_addr_type addr, int width, bool exact = false) const; + void* Lookup(const IPAddr& addr, int width, bool exact = false) const; void* Lookup(const Val* value, bool exact = false) const; // Returns pointer to data or nil if not found. - void* Remove(const_addr_type addr, int width); + void* Remove(const IPAddr& addr, int width); void* Remove(const Val* value); void Clear() { Clear_Patricia(tree, 0); } diff --git a/src/PriorityQueue.cc b/src/PriorityQueue.cc index d94ccba7d6..8db161b10a 100644 --- a/src/PriorityQueue.cc +++ b/src/PriorityQueue.cc @@ -1,5 +1,3 @@ -// $Id: PriorityQueue.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/PriorityQueue.h b/src/PriorityQueue.h index 45028553ce..87e10aa7ac 100644 --- a/src/PriorityQueue.h +++ b/src/PriorityQueue.h @@ -1,5 +1,3 @@ -// $Id: PriorityQueue.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef __PriorityQueue__ diff --git a/src/Queue.cc b/src/Queue.cc index a0de35777b..28bcb92405 100644 --- a/src/Queue.cc +++ b/src/Queue.cc @@ -1,5 +1,3 @@ -// $Id: Queue.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/Queue.h b/src/Queue.h index 293d74ba7a..c9a69ad926 100644 --- a/src/Queue.h +++ b/src/Queue.h @@ -1,5 +1,3 @@ -// $Id: Queue.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef queue_h diff --git a/src/RE.cc b/src/RE.cc index af72d84519..b6f1a1361f 100644 --- a/src/RE.cc +++ b/src/RE.cc @@ -1,5 +1,3 @@ -// $Id: RE.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/RE.h b/src/RE.h index f46f835649..a2fc709c88 100644 --- a/src/RE.h +++ b/src/RE.h @@ -1,5 +1,3 @@ -// $Id: RE.h 6781 2009-06-28 00:50:04Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef re_h diff --git a/src/RPC.cc b/src/RPC.cc index 02fb20a436..81fd6709b1 100644 --- a/src/RPC.cc +++ b/src/RPC.cc @@ -1,5 +1,3 @@ -// $Id: RPC.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include diff --git a/src/RPC.h b/src/RPC.h index 1b75b6cc48..0eee423460 100644 --- a/src/RPC.h +++ b/src/RPC.h @@ -1,5 +1,3 @@ -// $Id: RPC.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef rpc_h diff --git a/src/RSH.cc b/src/RSH.cc index cbbce944f5..ceef3ba7a4 100644 --- a/src/RSH.cc +++ b/src/RSH.cc @@ -1,5 +1,3 @@ -// $Id: RSH.cc 6219 2008-10-01 05:39:07Z vern $ - // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/RSH.h b/src/RSH.h index 8a6c5fde6f..136d0b07f1 100644 --- a/src/RSH.h +++ b/src/RSH.h @@ -1,5 +1,3 @@ -// $Id: RSH.h 6219 2008-10-01 05:39:07Z vern $ - // See the file "COPYING" in the main distribution directory for copyright. #ifndef rsh_h diff --git a/src/Reassem.cc b/src/Reassem.cc index 319fcbff3b..c3c19ff0e6 100644 --- a/src/Reassem.cc +++ b/src/Reassem.cc @@ -1,5 +1,3 @@ -// $Id: Reassem.cc 6703 2009-05-13 22:27:44Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include @@ -45,8 +43,7 @@ DataBlock::DataBlock(const u_char* data, int size, int arg_seq, unsigned int Reassembler::total_size = 0; -Reassembler::Reassembler(int init_seq, const uint32* ip_addr, - ReassemblerType arg_type) +Reassembler::Reassembler(int init_seq, ReassemblerType arg_type) { blocks = last_block = 0; trim_seq = last_reassem_seq = init_seq; diff --git a/src/Reassem.h b/src/Reassem.h index 1563732180..1f65059e02 100644 --- a/src/Reassem.h +++ b/src/Reassem.h @@ -1,11 +1,10 @@ -// $Id: Reassem.h 6703 2009-05-13 22:27:44Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef reassem_h #define reassem_h #include "Obj.h" +#include "IPAddr.h" class DataBlock { public: @@ -27,8 +26,7 @@ enum ReassemblerType { REASSEM_IP, REASSEM_TCP }; class Reassembler : public BroObj { public: - Reassembler(int init_seq, const uint32* ip_addr, - ReassemblerType arg_type); + Reassembler(int init_seq, ReassemblerType arg_type); virtual ~Reassembler(); void NewBlock(double t, int seq, int len, const u_char* data); diff --git a/src/RemoteSerializer.cc b/src/RemoteSerializer.cc index 814f387718..61be8a9e8f 100644 --- a/src/RemoteSerializer.cc +++ b/src/RemoteSerializer.cc @@ -1,5 +1,3 @@ -// $Id: RemoteSerializer.cc 6951 2009-12-04 22:23:28Z vern $ -// // Processes involved in the communication: // // (Local-Parent) <-> (Local-Child) <-> (Remote-Child) <-> (Remote-Parent) @@ -185,8 +183,11 @@ #include "Sessions.h" #include "File.h" #include "Conn.h" -#include "LogMgr.h" #include "Reporter.h" +#include "threading/SerialTypes.h" +#include "logging/Manager.h" +#include "IPAddr.h" +#include "bro_inet_ntop.h" extern "C" { #include "setsignal.h" @@ -387,6 +388,9 @@ inline void RemoteSerializer::SetupSerialInfo(SerialInfo* info, Peer* peer) peer->phase == Peer::RUNNING ) info->new_cache_strategy = true; + if ( (peer->caps & Peer::BROCCOLI_PEER) ) + info->broccoli_peer = true; + info->include_locations = false; } @@ -394,7 +398,7 @@ static bool sendToIO(ChunkedIO* io, ChunkedIO::Chunk* c) { if ( ! io->Write(c) ) { - reporter->Warning(fmt("can't send chunk: %s", io->Error())); + reporter->Warning("can't send chunk: %s", io->Error()); return false; } @@ -406,7 +410,7 @@ static bool sendToIO(ChunkedIO* io, char msg_type, RemoteSerializer::PeerID id, { if ( ! sendCMsg(io, msg_type, id) ) { - reporter->Warning(fmt("can't send message of type %d: %s", msg_type, io->Error())); + reporter->Warning("can't send message of type %d: %s", msg_type, io->Error()); return false; } @@ -421,7 +425,7 @@ static bool sendToIO(ChunkedIO* io, char msg_type, RemoteSerializer::PeerID id, { if ( ! sendCMsg(io, msg_type, id) ) { - reporter->Warning(fmt("can't send message of type %d: %s", msg_type, io->Error())); + reporter->Warning("can't send message of type %d: %s", msg_type, io->Error()); return false; } @@ -462,7 +466,7 @@ static inline const char* ip2a(uint32 ip) addr.s_addr = htonl(ip); - return inet_ntop(AF_INET, &addr, buffer, 32); + return bro_inet_ntop(AF_INET, &addr, buffer, 32); } static pid_t child_pid = 0; @@ -528,6 +532,8 @@ RemoteSerializer::RemoteSerializer() closed = false; terminating = false; in_sync = 0; + last_flush = 0; + received_logs = 0; } RemoteSerializer::~RemoteSerializer() @@ -668,8 +674,8 @@ void RemoteSerializer::Fork() } } -RemoteSerializer::PeerID RemoteSerializer::Connect(addr_type ip, uint16 port, - const char* our_class, double retry, bool use_ssl) +RemoteSerializer::PeerID RemoteSerializer::Connect(const IPAddr& ip, + uint16 port, const char* our_class, double retry, bool use_ssl) { if ( ! using_communication ) return true; @@ -677,16 +683,12 @@ RemoteSerializer::PeerID RemoteSerializer::Connect(addr_type ip, uint16 port, if ( ! initialized ) reporter->InternalError("remote serializer not initialized"); -#ifdef BROv6 - if ( ! is_v4_addr(ip) ) + if ( ip.GetFamily() == IPv6 ) Error("inter-Bro communication not supported over IPv6"); - uint32 ip4 = to_v4_addr(ip); -#else - uint32 ip4 = ip; -#endif - - ip4 = ntohl(ip4); + const uint32* bytes; + ip.GetBytes(&bytes); + uint32 ip4 = ntohl(*bytes); if ( ! child_pid ) Fork(); @@ -708,6 +710,21 @@ RemoteSerializer::PeerID RemoteSerializer::Connect(addr_type ip, uint16 port, return p->id; } +bool RemoteSerializer::CloseConnection(PeerID id) + { + if ( ! using_communication ) + return true; + + Peer* peer = LookupPeer(id, true); + if ( ! peer ) + { + reporter->Error("unknown peer id %d for closing connection", int(id)); + return false; + } + + return CloseConnection(peer); + } + bool RemoteSerializer::CloseConnection(Peer* peer) { if ( peer->suspended_processing ) @@ -736,14 +753,14 @@ bool RemoteSerializer::RequestSync(PeerID id, bool auth) Peer* peer = LookupPeer(id, true); if ( ! peer ) { - reporter->Error(fmt("unknown peer id %d for request sync", int(id))); + reporter->Error("unknown peer id %d for request sync", int(id)); return false; } if ( peer->phase != Peer::HANDSHAKE ) { - reporter->Error(fmt("can't request sync from peer; wrong phase %d", - peer->phase)); + reporter->Error("can't request sync from peer; wrong phase %d", + peer->phase); return false; } @@ -763,14 +780,14 @@ bool RemoteSerializer::RequestLogs(PeerID id) Peer* peer = LookupPeer(id, true); if ( ! peer ) { - reporter->Error(fmt("unknown peer id %d for request logs", int(id))); + reporter->Error("unknown peer id %d for request logs", int(id)); return false; } if ( peer->phase != Peer::HANDSHAKE ) { - reporter->Error(fmt("can't request logs from peer; wrong phase %d", - peer->phase)); + reporter->Error("can't request logs from peer; wrong phase %d", + peer->phase); return false; } @@ -788,14 +805,14 @@ bool RemoteSerializer::RequestEvents(PeerID id, RE_Matcher* pattern) Peer* peer = LookupPeer(id, true); if ( ! peer ) { - reporter->Error(fmt("unknown peer id %d for request sync", int(id))); + reporter->Error("unknown peer id %d for request sync", int(id)); return false; } if ( peer->phase != Peer::HANDSHAKE ) { - reporter->Error(fmt("can't request events from peer; wrong phase %d", - peer->phase)); + reporter->Error("can't request events from peer; wrong phase %d", + peer->phase); return false; } @@ -855,8 +872,8 @@ bool RemoteSerializer::CompleteHandshake(PeerID id) if ( p->phase != Peer::HANDSHAKE ) { - reporter->Error(fmt("can't complete handshake; wrong phase %d", - p->phase)); + reporter->Error("can't complete handshake; wrong phase %d", + p->phase); return false; } @@ -1124,7 +1141,7 @@ bool RemoteSerializer::SendCaptureFilter(PeerID id, const char* filter) if ( peer->phase != Peer::HANDSHAKE ) { - reporter->Error(fmt("can't sent capture filter to peer; wrong phase %d", peer->phase)); + reporter->Error("can't sent capture filter to peer; wrong phase %d", peer->phase); return false; } @@ -1201,24 +1218,21 @@ bool RemoteSerializer::SendCapabilities(Peer* peer) { if ( peer->phase != Peer::HANDSHAKE ) { - reporter->Error(fmt("can't sent capabilties to peer; wrong phase %d", - peer->phase)); + reporter->Error("can't sent capabilties to peer; wrong phase %d", + peer->phase); return false; } uint32 caps = 0; -#ifdef HAVE_LIBZ caps |= Peer::COMPRESSION; -#endif - caps |= Peer::PID_64BIT; caps |= Peer::NEW_CACHE_STRATEGY; return caps ? SendToChild(MSG_CAPS, peer, 3, caps, 0, 0) : true; } -bool RemoteSerializer::Listen(addr_type ip, uint16 port, bool expect_ssl) +bool RemoteSerializer::Listen(const IPAddr& ip, uint16 port, bool expect_ssl) { if ( ! using_communication ) return true; @@ -1226,16 +1240,12 @@ bool RemoteSerializer::Listen(addr_type ip, uint16 port, bool expect_ssl) if ( ! initialized ) reporter->InternalError("remote serializer not initialized"); -#ifdef BROv6 - if ( ! is_v4_addr(ip) ) + if ( ip.GetFamily() == IPv6 ) Error("inter-Bro communication not supported over IPv6"); - uint32 ip4 = to_v4_addr(ip); -#else - uint32 ip4 = ip; -#endif - - ip4 = ntohl(ip4); + const uint32* bytes; + ip.GetBytes(&bytes); + uint32 ip4 = ntohl(*bytes); if ( ! SendToChild(MSG_LISTEN, 0, 3, ip4, port, expect_ssl) ) return false; @@ -1290,7 +1300,14 @@ void RemoteSerializer::SendFinalSyncPoint() bool RemoteSerializer::Terminate() { + loop_over_list(peers, i) + { + FlushPrintBuffer(peers[i]); + FlushLogBuffer(peers[i]); + } + Log(LogInfo, fmt("terminating...")); + return terminating = SendToChild(MSG_TERMINATE, 0, 0); } @@ -1338,6 +1355,14 @@ double RemoteSerializer::NextTimestamp(double* local_network_time) { Poll(false); + if ( received_logs > 0 ) + { + // If we processed logs last time, assume there's more. + idle = false; + received_logs = 0; + return timer_mgr->Time(); + } + double et = events.length() ? events[0]->time : -1; double pt = packets.length() ? packets[0]->time : -1; @@ -1440,7 +1465,9 @@ void RemoteSerializer::Finish() while ( io->CanWrite() ); loop_over_list(peers, i) + { CloseConnection(peers[i]); + } } bool RemoteSerializer::Poll(bool may_block) @@ -1792,7 +1819,7 @@ RemoteSerializer::Peer* RemoteSerializer::AddPeer(uint32 ip, uint16 port, peer->sync_point = 0; peer->print_buffer = 0; peer->print_buffer_used = 0; - peer->log_buffer = 0; + peer->log_buffer = new char[LOG_BUFFER_SIZE]; peer->log_buffer_used = 0; peers.append(peer); @@ -2028,8 +2055,6 @@ bool RemoteSerializer::ProcessRequestLogs() Log(LogInfo, "peer requested logs", current_peer); current_peer->logs_requested = true; - current_peer->log_buffer = new char[LOG_BUFFER_SIZE]; - current_peer->log_buffer_used = 0; return true; } @@ -2085,11 +2110,9 @@ bool RemoteSerializer::ProcessPhaseDone() bool RemoteSerializer::HandshakeDone(Peer* peer) { -#ifdef HAVE_LIBZ if ( peer->caps & Peer::COMPRESSION && peer->comp_level > 0 ) if ( ! SendToChild(MSG_COMPRESS, peer, 1, peer->comp_level) ) return false; -#endif if ( ! (peer->caps & Peer::PID_64BIT) ) Log(LogInfo, "peer does not support 64bit PIDs; using compatibility mode", peer); @@ -2097,6 +2120,9 @@ bool RemoteSerializer::HandshakeDone(Peer* peer) if ( (peer->caps & Peer::NEW_CACHE_STRATEGY) ) Log(LogInfo, "peer supports keep-in-cache; using that", peer); + if ( (peer->caps & Peer::BROCCOLI_PEER) ) + Log(LogInfo, "peer is a Broccoli", peer); + if ( peer->logs_requested ) log_mgr->SendAllWritersTo(peer->id); @@ -2349,6 +2375,9 @@ bool RemoteSerializer::ProcessSerialization() current_peer->phase == Peer::RUNNING ) info.new_cache_strategy = true; + if ( current_peer->caps & Peer::BROCCOLI_PEER ) + info.broccoli_peer = true; + if ( ! forward_remote_state_changes ) ignore_accesses = true; @@ -2451,7 +2480,7 @@ bool RemoteSerializer::ProcessRemotePrint() return true; } -bool RemoteSerializer::SendLogCreateWriter(EnumVal* id, EnumVal* writer, string path, int num_fields, const LogField* const * fields) +bool RemoteSerializer::SendLogCreateWriter(EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Field* const * fields) { loop_over_list(peers, i) { @@ -2461,7 +2490,7 @@ bool RemoteSerializer::SendLogCreateWriter(EnumVal* id, EnumVal* writer, string return true; } -bool RemoteSerializer::SendLogCreateWriter(PeerID peer_id, EnumVal* id, EnumVal* writer, string path, int num_fields, const LogField* const * fields) +bool RemoteSerializer::SendLogCreateWriter(PeerID peer_id, EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Field* const * fields) { SetErrorDescr("logging"); @@ -2474,6 +2503,9 @@ bool RemoteSerializer::SendLogCreateWriter(PeerID peer_id, EnumVal* id, EnumVal* if ( peer->phase != Peer::HANDSHAKE && peer->phase != Peer::RUNNING ) return false; + if ( ! peer->logs_requested ) + return false; + BinarySerializationFormat fmt; fmt.StartWrite(); @@ -2492,23 +2524,30 @@ bool RemoteSerializer::SendLogCreateWriter(PeerID peer_id, EnumVal* id, EnumVal* goto error; } - c = new ChunkedIO::Chunk; - c->len = fmt.EndWrite(&c->data); - if ( ! SendToChild(MSG_LOG_CREATE_WRITER, peer, 0) ) goto error; + c = new ChunkedIO::Chunk; + c->data = 0; + c->len = fmt.EndWrite(&c->data); + if ( ! SendToChild(c) ) goto error; return true; error: + if ( c ) + { + delete c; + delete [] c->data; + } + FatalError(io->Error()); return false; } -bool RemoteSerializer::SendLogWrite(EnumVal* id, EnumVal* writer, string path, int num_fields, const LogVal* const * vals) +bool RemoteSerializer::SendLogWrite(EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Value* const * vals) { loop_over_list(peers, i) { @@ -2518,7 +2557,7 @@ bool RemoteSerializer::SendLogWrite(EnumVal* id, EnumVal* writer, string path, i return true; } -bool RemoteSerializer::SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, string path, int num_fields, const LogVal* const * vals) +bool RemoteSerializer::SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Value* const * vals) { if ( peer->phase != Peer::HANDSHAKE && peer->phase != Peer::RUNNING ) return false; @@ -2526,7 +2565,9 @@ bool RemoteSerializer::SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, st if ( ! peer->logs_requested ) return false; - assert(peer->log_buffer); + if ( ! peer->log_buffer ) + // Peer shutting down. + return false; // Serialize the log record entry. @@ -2554,11 +2595,17 @@ bool RemoteSerializer::SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, st len = fmt.EndWrite(&data); - // Do we have enough space in the buffer? If not, flush first. - if ( len > (LOG_BUFFER_SIZE - peer->log_buffer_used) ) + assert(len > 10); + + // Do we have not enough space in the buffer, or was the last flush a + // while ago? If so, flush first. + if ( len > (LOG_BUFFER_SIZE - peer->log_buffer_used) || (network_time - last_flush > 1.0) ) { if ( ! FlushLogBuffer(peer) ) + { + delete [] data; return false; + } } // If the data is actually larger than our complete buffer, just send it out. @@ -2570,7 +2617,8 @@ bool RemoteSerializer::SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, st peer->log_buffer_used += len; assert(peer->log_buffer_used <= LOG_BUFFER_SIZE); - FlushLogBuffer(peer); // FIXME: This should go away, but then the unit test fails. See #498. + delete [] data; + return true; error: @@ -2580,15 +2628,21 @@ error: bool RemoteSerializer::FlushLogBuffer(Peer* p) { + if ( ! p->logs_requested ) + return false; + + last_flush = network_time; + if ( p->state == Peer::CLOSING ) return false; if ( ! (p->log_buffer && p->log_buffer_used) ) return true; - SendToChild(MSG_LOG_WRITE, p, p->log_buffer, p->log_buffer_used); + char* data = new char[p->log_buffer_used]; + memcpy(data, p->log_buffer, p->log_buffer_used); + SendToChild(MSG_LOG_WRITE, p, data, p->log_buffer_used); - p->log_buffer = new char[LOG_BUFFER_SIZE]; p->log_buffer_used = 0; return true; } @@ -2598,11 +2652,17 @@ bool RemoteSerializer::ProcessLogCreateWriter() if ( current_peer->state == Peer::CLOSING ) return false; +#ifdef USE_PERFTOOLS_DEBUG + // Don't track allocations here, they'll be released only after the + // main loop exists. And it's just a tiny amount anyway. + HeapLeakChecker::Disabler disabler; +#endif + assert(current_args); EnumVal* id_val = 0; EnumVal* writer_val = 0; - LogField** fields = 0; + threading::Field** fields = 0; BinarySerializationFormat fmt; fmt.StartRead(current_args->data, current_args->len); @@ -2619,11 +2679,11 @@ bool RemoteSerializer::ProcessLogCreateWriter() if ( ! success ) goto error; - fields = new LogField* [num_fields]; + fields = new threading::Field* [num_fields]; for ( int i = 0; i < num_fields; i++ ) { - fields[i] = new LogField; + fields[i] = new threading::Field; if ( ! fields[i]->Read(&fmt) ) goto error; } @@ -2633,7 +2693,7 @@ bool RemoteSerializer::ProcessLogCreateWriter() id_val = new EnumVal(id, BifType::Enum::Log::ID); writer_val = new EnumVal(writer, BifType::Enum::Log::Writer); - if ( ! log_mgr->CreateWriter(id_val, writer_val, path, num_fields, fields) ) + if ( ! log_mgr->CreateWriter(id_val, writer_val, path, num_fields, fields, true, false) ) goto error; Unref(id_val); @@ -2664,7 +2724,7 @@ bool RemoteSerializer::ProcessLogWrite() // Unserialize one entry. EnumVal* id_val = 0; EnumVal* writer_val = 0; - LogVal** vals = 0; + threading::Value** vals = 0; int id, writer; string path; @@ -2678,11 +2738,11 @@ bool RemoteSerializer::ProcessLogWrite() if ( ! success ) goto error; - vals = new LogVal* [num_fields]; + vals = new threading::Value* [num_fields]; for ( int i = 0; i < num_fields; i++ ) { - vals[i] = new LogVal; + vals[i] = new threading::Value; if ( ! vals[i]->Read(&fmt) ) goto error; } @@ -2702,6 +2762,8 @@ bool RemoteSerializer::ProcessLogWrite() fmt.EndRead(); + ++received_logs; + return true; error: @@ -2774,7 +2836,13 @@ void RemoteSerializer::GotFunctionCall(const char* name, double time, return; } - function->Call(args); + try + { + function->Call(args); + } + + catch ( InterpreterException& e ) + { /* Already reported. */ } } void RemoteSerializer::GotID(ID* id, Val* val) @@ -2805,6 +2873,11 @@ void RemoteSerializer::GotID(ID* id, Val* val) (desc && *desc) ? desc : "not set"), current_peer); +#ifdef USE_PERFTOOLS_DEBUG + // May still be cached, but we don't care. + heap_checker->IgnoreObject(id); +#endif + Unref(id); return; } @@ -2882,25 +2955,37 @@ void RemoteSerializer::Log(LogLevel level, const char* msg) void RemoteSerializer::Log(LogLevel level, const char* msg, Peer* peer, LogSrc src) { + if ( peer ) + { + val_list* vl = new val_list(); + vl->append(peer->val->Ref()); + vl->append(new Val(level, TYPE_COUNT)); + vl->append(new Val(src, TYPE_COUNT)); + vl->append(new StringVal(msg)); + mgr.QueueEvent(remote_log_peer, vl); + } + else + { + val_list* vl = new val_list(); + vl->append(new Val(level, TYPE_COUNT)); + vl->append(new Val(src, TYPE_COUNT)); + vl->append(new StringVal(msg)); + mgr.QueueEvent(remote_log, vl); + } + +#ifdef DEBUG const int BUFSIZE = 1024; char buffer[BUFSIZE]; - int len = 0; if ( peer ) - len += snprintf(buffer + len, sizeof(buffer) - len, - "[#%d/%s:%d] ", int(peer->id), ip2a(peer->ip), - peer->port); + len += snprintf(buffer + len, sizeof(buffer) - len, "[#%d/%s:%d] ", + int(peer->id), ip2a(peer->ip), peer->port); len += safe_snprintf(buffer + len, sizeof(buffer) - len, "%s", msg); - val_list* vl = new val_list(); - vl->append(new Val(level, TYPE_COUNT)); - vl->append(new Val(src, TYPE_COUNT)); - vl->append(new StringVal(buffer)); - mgr.QueueEvent(remote_log, vl); - DEBUG_COMM(fmt("parent: %.6f %s", current_time(), buffer)); +#endif } void RemoteSerializer::RaiseEvent(EventHandlerPtr event, Peer* peer, @@ -2965,8 +3050,8 @@ bool RemoteSerializer::SendCMsgToChild(char msg_type, Peer* peer) { if ( ! sendCMsg(io, msg_type, peer ? peer->id : PEER_NONE) ) { - reporter->Warning(fmt("can't send message of type %d: %s", - msg_type, io->Error())); + reporter->Warning("can't send message of type %d: %s", + msg_type, io->Error()); return false; } return true; @@ -2976,12 +3061,14 @@ bool RemoteSerializer::SendToChild(char type, Peer* peer, char* str, int len) { DEBUG_COMM(fmt("parent: (->child) %s (#%" PRI_SOURCE_ID ", %s)", msgToStr(type), peer ? peer->id : PEER_NONE, str)); + if ( child_pid && sendToIO(io, type, peer ? peer->id : PEER_NONE, str, len) ) + return true; + + delete [] str; + if ( ! child_pid ) return false; - if ( sendToIO(io, type, peer ? peer->id : PEER_NONE, str, len) ) - return true; - if ( io->Eof() ) ChildDied(); @@ -2993,9 +3080,6 @@ bool RemoteSerializer::SendToChild(char type, Peer* peer, int nargs, ...) { va_list ap; - if ( ! child_pid ) - return false; - #ifdef DEBUG va_start(ap, nargs); DEBUG_COMM(fmt("parent: (->child) %s (#%" PRI_SOURCE_ID ",%s)", @@ -3003,12 +3087,18 @@ bool RemoteSerializer::SendToChild(char type, Peer* peer, int nargs, ...) va_end(ap); #endif - va_start(ap, nargs); - bool ret = sendToIO(io, type, peer ? peer->id : PEER_NONE, nargs, ap); - va_end(ap); + if ( child_pid ) + { + va_start(ap, nargs); + bool ret = sendToIO(io, type, peer ? peer->id : PEER_NONE, nargs, ap); + va_end(ap); - if ( ret ) - return true; + if ( ret ) + return true; + } + + if ( ! child_pid ) + return false; if ( io->Eof() ) ChildDied(); @@ -3021,12 +3111,14 @@ bool RemoteSerializer::SendToChild(ChunkedIO::Chunk* c) { DEBUG_COMM(fmt("parent: (->child) chunk of size %d", c->len)); + if ( child_pid && sendToIO(io, c) ) + return true; + + delete [] c->data; + if ( ! child_pid ) return false; - if ( sendToIO(io, c) ) - return true; - if ( io->Eof() ) ChildDied(); @@ -3038,13 +3130,22 @@ void RemoteSerializer::FatalError(const char* msg) { msg = fmt("fatal error, shutting down communication: %s", msg); Log(LogError, msg); - reporter->Error(msg); + reporter->Error("%s", msg); closed = true; kill(child_pid, SIGQUIT); child_pid = 0; using_communication = false; io->Clear(); + + loop_over_list(peers, i) + { + // Make perftools happy. + Peer* p = peers[i]; + delete [] p->log_buffer; + delete [] p->print_buffer; + p->log_buffer = p->print_buffer = 0; + } } bool RemoteSerializer::IsActive() @@ -3304,6 +3405,11 @@ void SocketComm::Run() small_timeout.tv_usec = io->CanWrite() || io->CanRead() ? 1 : 10; +#if 0 + if ( ! io->CanWrite() ) + usleep(10); +#endif + int a = select(max_fd + 1, &fd_read, &fd_write, &fd_except, &small_timeout); @@ -3637,11 +3743,6 @@ bool SocketComm::ProcessListen() bool SocketComm::ProcessParentCompress() { -#ifndef HAVE_LIBZ - InternalError("supposed to enable compression but don't have zlib"); - return false; -#else - assert(parent_args); uint32* args = (uint32*) parent_args->data; @@ -3665,7 +3766,6 @@ bool SocketComm::ProcessParentCompress() Log(fmt("enabling compression (level %d)", level), parent_peer); return true; -#endif } bool SocketComm::ProcessRemoteMessage(SocketComm::Peer* peer) @@ -3785,10 +3885,6 @@ bool SocketComm::ProcessPeerCompress(Peer* peer) { peer->state = MSG_NONE; -#ifndef HAVE_LIBZ - Error("peer compresses although we do not support it", peer); - return false; -#else if ( ! parent_peer->compressor ) { parent_peer->io = new CompressedChunkedIO(parent_peer->io); @@ -3800,7 +3896,6 @@ bool SocketComm::ProcessPeerCompress(Peer* peer) ((CompressedChunkedIO*) peer->io)->EnableDecompression(); Log("enabling decompression", peer); return true; -#endif } bool SocketComm::Connect(Peer* peer) diff --git a/src/RemoteSerializer.h b/src/RemoteSerializer.h index 5374e6f931..05d25ca525 100644 --- a/src/RemoteSerializer.h +++ b/src/RemoteSerializer.h @@ -1,5 +1,3 @@ -// $Id: RemoteSerializer.h 6951 2009-12-04 22:23:28Z vern $ -// // Communication between two Bro's. #ifndef REMOTE_SERIALIZER @@ -16,8 +14,11 @@ // FIXME: Change this to network byte order class IncrementalSendTimer; -class LogField; -class LogVal; + +namespace threading { + class Field; + class Value; +} // This class handles the communication done in Bro's main loop. class RemoteSerializer : public Serializer, public IOSource { @@ -34,7 +35,10 @@ public: static const PeerID PEER_NONE = SOURCE_LOCAL; // Connect to host (returns PEER_NONE on error). - PeerID Connect(addr_type ip, uint16 port, const char* our_class, double retry, bool use_ssl); + PeerID Connect(const IPAddr& ip, uint16 port, const char* our_class, double retry, bool use_ssl); + + // Close connection to host. + bool CloseConnection(PeerID peer); // Request all events matching pattern from remote side. bool RequestEvents(PeerID peer, RE_Matcher* pattern); @@ -59,7 +63,7 @@ public: bool CompleteHandshake(PeerID peer); // Start to listen. - bool Listen(addr_type ip, uint16 port, bool expect_ssl); + bool Listen(const IPAddr& ip, uint16 port, bool expect_ssl); // Stop it. bool StopListening(); @@ -98,13 +102,13 @@ public: bool SendPrintHookEvent(BroFile* f, const char* txt, size_t len); // Send a request to create a writer on a remote side. - bool SendLogCreateWriter(PeerID peer, EnumVal* id, EnumVal* writer, string path, int num_fields, const LogField* const * fields); + bool SendLogCreateWriter(PeerID peer, EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Field* const * fields); // Broadcasts a request to create a writer. - bool SendLogCreateWriter(EnumVal* id, EnumVal* writer, string path, int num_fields, const LogField* const * fields); + bool SendLogCreateWriter(EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Field* const * fields); // Broadcast a log entry to everybody interested. - bool SendLogWrite(EnumVal* id, EnumVal* writer, string path, int num_fields, const LogVal* const * vals); + bool SendLogWrite(EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Value* const * vals); // Synchronzizes time with all connected peers. Returns number of // current sync-point, or -1 on error. @@ -197,6 +201,7 @@ protected: static const int NO_CACHING = 2; static const int PID_64BIT = 4; static const int NEW_CACHE_STRATEGY = 8; + static const int BROCCOLI_PEER = 16; // Constants to remember to who did something. static const int NONE = 0; @@ -298,7 +303,7 @@ protected: bool SendID(SerialInfo* info, Peer* peer, const ID& id); bool SendCapabilities(Peer* peer); bool SendPacket(SerialInfo* info, Peer* peer, const Packet& p); - bool SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, string path, int num_fields, const LogVal* const * vals); + bool SendLogWrite(Peer* peer, EnumVal* id, EnumVal* writer, string path, int num_fields, const threading::Value* const * vals); void UnregisterHandlers(Peer* peer); void RaiseEvent(EventHandlerPtr event, Peer* peer, const char* arg = 0); @@ -323,6 +328,7 @@ private: PeerID current_id; char current_msgtype; ChunkedIO::Chunk* current_args; + double last_flush; id_list sync_ids; @@ -332,6 +338,7 @@ private: int propagate_accesses; bool ignore_accesses; bool terminating; + int received_logs; Peer* source_peer; PeerID id_counter; // Keeps track of assigned IDs. uint32 current_sync_point; diff --git a/src/Reporter.cc b/src/Reporter.cc index 053d6370d7..37470cd690 100644 --- a/src/Reporter.cc +++ b/src/Reporter.cc @@ -39,7 +39,7 @@ void Reporter::Info(const char* fmt, ...) { va_list ap; va_start(ap, fmt); - DoLog("", reporter_info, stderr, 0, 0, true, true, fmt, ap); + DoLog("", reporter_info, stderr, 0, 0, true, true, 0, fmt, ap); va_end(ap); } @@ -47,7 +47,7 @@ void Reporter::Warning(const char* fmt, ...) { va_list ap; va_start(ap, fmt); - DoLog("warning", reporter_warning, stderr, 0, 0, true, true, fmt, ap); + DoLog("warning", reporter_warning, stderr, 0, 0, true, true, 0, fmt, ap); va_end(ap); } @@ -56,7 +56,7 @@ void Reporter::Error(const char* fmt, ...) ++errors; va_list ap; va_start(ap, fmt); - DoLog("error", reporter_error, stderr, 0, 0, true, true, fmt, ap); + DoLog("error", reporter_error, stderr, 0, 0, true, true, 0, fmt, ap); va_end(ap); } @@ -66,7 +66,7 @@ void Reporter::FatalError(const char* fmt, ...) va_start(ap, fmt); // Always log to stderr. - DoLog("fatal error", 0, stderr, 0, 0, true, false, fmt, ap); + DoLog("fatal error", 0, stderr, 0, 0, true, false, 0, fmt, ap); va_end(ap); @@ -80,7 +80,7 @@ void Reporter::FatalErrorWithCore(const char* fmt, ...) va_start(ap, fmt); // Always log to stderr. - DoLog("fatal error", 0, stderr, 0, 0, true, false, fmt, ap); + DoLog("fatal error", 0, stderr, 0, 0, true, false, 0, fmt, ap); va_end(ap); @@ -88,13 +88,29 @@ void Reporter::FatalErrorWithCore(const char* fmt, ...) abort(); } +void Reporter::ExprRuntimeError(const Expr* expr, const char* fmt, ...) + { + ++errors; + + ODesc d; + expr->Describe(&d); + + PushLocation(expr->GetLocationInfo()); + va_list ap; + va_start(ap, fmt); + DoLog("expression error", reporter_error, stderr, 0, 0, true, true, d.Description(), fmt, ap); + va_end(ap); + PopLocation(); + throw InterpreterException(); + } + void Reporter::InternalError(const char* fmt, ...) { va_list ap; va_start(ap, fmt); // Always log to stderr. - DoLog("internal error", 0, stderr, 0, 0, true, false, fmt, ap); + DoLog("internal error", 0, stderr, 0, 0, true, false, 0, fmt, ap); va_end(ap); @@ -106,7 +122,7 @@ void Reporter::InternalWarning(const char* fmt, ...) { va_list ap; va_start(ap, fmt); - DoLog("internal warning", reporter_warning, stderr, 0, 0, true, true, fmt, ap); + DoLog("internal warning", reporter_warning, stderr, 0, 0, true, true, 0, fmt, ap); va_end(ap); } @@ -121,7 +137,7 @@ void Reporter::Syslog(const char* fmt, ...) va_end(ap); } -void Reporter::WeirdHelper(EventHandlerPtr event, Val* conn_val, const char* name, const char* addl, ...) +void Reporter::WeirdHelper(EventHandlerPtr event, Val* conn_val, const char* addl, const char* fmt_name, ...) { val_list* vl = new val_list(1); @@ -132,22 +148,22 @@ void Reporter::WeirdHelper(EventHandlerPtr event, Val* conn_val, const char* nam vl->append(new StringVal(addl)); va_list ap; - va_start(ap, addl); - DoLog("weird", event, stderr, 0, vl, false, false, name, ap); + va_start(ap, fmt_name); + DoLog("weird", event, stderr, 0, vl, false, false, 0, fmt_name, ap); va_end(ap); delete vl; } -void Reporter::WeirdFlowHelper(const uint32* orig, const uint32* resp, const char* name, ...) +void Reporter::WeirdFlowHelper(const IPAddr& orig, const IPAddr& resp, const char* fmt_name, ...) { val_list* vl = new val_list(2); vl->append(new AddrVal(orig)); vl->append(new AddrVal(resp)); va_list ap; - va_start(ap, name); - DoLog("weird", flow_weird, stderr, 0, vl, false, false, name, ap); + va_start(ap, fmt_name); + DoLog("weird", flow_weird, stderr, 0, vl, false, false, 0, fmt_name, ap); va_end(ap); delete vl; @@ -155,25 +171,25 @@ void Reporter::WeirdFlowHelper(const uint32* orig, const uint32* resp, const cha void Reporter::Weird(const char* name) { - WeirdHelper(net_weird, 0, name, 0); + WeirdHelper(net_weird, 0, 0, name); } void Reporter::Weird(Connection* conn, const char* name, const char* addl) { - WeirdHelper(conn_weird, conn->BuildConnVal(), name, addl); + WeirdHelper(conn_weird, conn->BuildConnVal(), addl, "%s", name); } void Reporter::Weird(Val* conn_val, const char* name, const char* addl) { - WeirdHelper(conn_weird, conn_val, name, addl); + WeirdHelper(conn_weird, conn_val, addl, "%s", name); } -void Reporter::Weird(const uint32* orig, const uint32* resp, const char* name) +void Reporter::Weird(const IPAddr& orig, const IPAddr& resp, const char* name) { - WeirdFlowHelper(orig, resp, name); + WeirdFlowHelper(orig, resp, "%s", name); } -void Reporter::DoLog(const char* prefix, EventHandlerPtr event, FILE* out, Connection* conn, val_list* addl, bool location, bool time, const char* fmt, va_list ap) +void Reporter::DoLog(const char* prefix, EventHandlerPtr event, FILE* out, Connection* conn, val_list* addl, bool location, bool time, const char* postfix, const char* fmt, va_list ap) { static char tmp[512]; @@ -235,6 +251,9 @@ void Reporter::DoLog(const char* prefix, EventHandlerPtr event, FILE* out, Conne int n = vsnprintf(buffer, size, fmt, aq); va_end(aq); + if ( postfix ) + n += strlen(postfix) + 10; // Add a bit of slack. + if ( n > -1 && n < size ) // We had enough space; break; @@ -247,6 +266,11 @@ void Reporter::DoLog(const char* prefix, EventHandlerPtr event, FILE* out, Conne FatalError("out of memory in Reporter"); } + if ( postfix ) + // Note, if you change this fmt string, adjust the additional + // buffer size above. + sprintf(buffer + strlen(buffer), " [%s]", postfix); + if ( event && via_events && ! in_error_handler ) { val_list* vl = new val_list; @@ -303,6 +327,12 @@ void Reporter::DoLog(const char* prefix, EventHandlerPtr event, FILE* out, Conne s += "\n"; fprintf(out, "%s", s.c_str()); + + if ( addl ) + { + loop_over_list(*addl, i) + Unref((*addl)[i]); + } } if ( alloced ) diff --git a/src/Reporter.h b/src/Reporter.h index bc919d3908..e610e1519e 100644 --- a/src/Reporter.h +++ b/src/Reporter.h @@ -9,11 +9,34 @@ #include #include "util.h" -#include "net_util.h" #include "EventHandler.h" +#include "IPAddr.h" class Connection; class Location; +class Reporter; + +// One cannot raise this exception directly, go through the +// Reporter's methods instead. + +class ReporterException { +protected: + friend class Reporter; + ReporterException() {} +}; + +class InterpreterException : public ReporterException { +protected: + friend class Reporter; + InterpreterException() {} +}; + +// Check printf-style variadic arguments if we can. +#if __GNUC__ +#define FMT_ATTR __attribute__((format(printf, 2, 3))) // sic! 1st is "this" I guess. +#else +#define FMT_ATTR +#endif class Reporter { public: @@ -22,44 +45,48 @@ public: // Report an informational message, nothing that needs specific // attention. - void Info(const char* fmt, ...); + void Info(const char* fmt, ...) FMT_ATTR; // Report a warning that may indicate a problem. - void Warning(const char* fmt, ...); + void Warning(const char* fmt, ...) FMT_ATTR; // Report a non-fatal error. Processing proceeds normally after the error // has been reported. - void Error(const char* fmt, ...); + void Error(const char* fmt, ...) FMT_ATTR; // Returns the number of errors reported so far. int Errors() { return errors; } // Report a fatal error. Bro will terminate after the message has been // reported. - void FatalError(const char* fmt, ...); + void FatalError(const char* fmt, ...) FMT_ATTR; // Report a fatal error. Bro will terminate after the message has been // reported and always generate a core dump. - void FatalErrorWithCore(const char* fmt, ...); + void FatalErrorWithCore(const char* fmt, ...) FMT_ATTR; + + // Report a runtime error in evaluating a Bro script expression. This + // function will not return but raise an InterpreterException. + void ExprRuntimeError(const Expr* expr, const char* fmt, ...); // Report a traffic weirdness, i.e., an unexpected protocol situation // that may lead to incorrectly processing a connnection. void Weird(const char* name); // Raises net_weird(). void Weird(Connection* conn, const char* name, const char* addl = ""); // Raises conn_weird(). void Weird(Val* conn_val, const char* name, const char* addl = ""); // Raises conn_weird(). - void Weird(const uint32* orig, const uint32* resp, const char* name); // Raises flow_weird(). + void Weird(const IPAddr& orig, const IPAddr& resp, const char* name); // Raises flow_weird(). // Syslog a message. This methods does nothing if we're running // offline from a trace. - void Syslog(const char* fmt, ...); + void Syslog(const char* fmt, ...) FMT_ATTR; // Report about a potential internal problem. Bro will continue // normally. - void InternalWarning(const char* fmt, ...); + void InternalWarning(const char* fmt, ...) FMT_ATTR; // Report an internal program error. Bro will terminate with a core // dump after the message has been reported. - void InternalError(const char* fmt, ...); + void InternalError(const char* fmt, ...) FMT_ATTR; // Toggle whether non-fatal messages should be reported through the // scripting layer rather on standard output. Fatal errors are always @@ -87,10 +114,14 @@ public: void EndErrorHandler() { --in_error_handler; } private: - void DoLog(const char* prefix, EventHandlerPtr event, FILE* out, Connection* conn, val_list* addl, bool location, bool time, const char* fmt, va_list ap); + void DoLog(const char* prefix, EventHandlerPtr event, FILE* out, + Connection* conn, val_list* addl, bool location, bool time, + const char* postfix, const char* fmt, va_list ap); - void WeirdHelper(EventHandlerPtr event, Val* conn_val, const char* name, const char* addl, ...); - void WeirdFlowHelper(const uint32* orig, const uint32* resp, const char* name, ...); + // The order if addl, name needs to be like that since fmt_name can + // contain format specifiers + void WeirdHelper(EventHandlerPtr event, Val* conn_val, const char* addl, const char* fmt_name, ...); + void WeirdFlowHelper(const IPAddr& orig, const IPAddr& resp, const char* fmt_name, ...); int errors; bool via_events; diff --git a/src/Rlogin.cc b/src/Rlogin.cc index 6dd1cc362d..1ad3f16d7e 100644 --- a/src/Rlogin.cc +++ b/src/Rlogin.cc @@ -1,5 +1,3 @@ -// $Id: Rlogin.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/Rlogin.h b/src/Rlogin.h index ae1946369c..f8ad480630 100644 --- a/src/Rlogin.h +++ b/src/Rlogin.h @@ -1,5 +1,3 @@ -// $Id: Rlogin.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef rlogin_h diff --git a/src/Rule.cc b/src/Rule.cc index f54a725320..e9847c1721 100644 --- a/src/Rule.cc +++ b/src/Rule.cc @@ -1,5 +1,3 @@ -// $Id: Rule.cc 6914 2009-09-22 00:35:24Z vern $ - #include "config.h" #include "Rule.h" diff --git a/src/Rule.h b/src/Rule.h index e95dadc074..959008fbf9 100644 --- a/src/Rule.h +++ b/src/Rule.h @@ -1,5 +1,3 @@ -// $Id: Rule.h 6914 2009-09-22 00:35:24Z vern $ - #ifndef rule_h #define rule_h diff --git a/src/RuleAction.cc b/src/RuleAction.cc index 9fe807ffb2..bf90c0681e 100644 --- a/src/RuleAction.cc +++ b/src/RuleAction.cc @@ -1,5 +1,3 @@ -// $Id: RuleAction.cc 5906 2008-07-03 19:52:50Z vern $ - #include using std::string; diff --git a/src/RuleAction.h b/src/RuleAction.h index 33d37bc6e2..a9feb0c314 100644 --- a/src/RuleAction.h +++ b/src/RuleAction.h @@ -1,5 +1,3 @@ -// $Id: RuleAction.h 5880 2008-06-30 17:42:45Z vern $ - #ifndef ruleaction_h #define ruleaction_h diff --git a/src/RuleCondition.cc b/src/RuleCondition.cc index 78dbee39cd..8852747cc4 100644 --- a/src/RuleCondition.cc +++ b/src/RuleCondition.cc @@ -1,5 +1,3 @@ -// $Id: RuleCondition.cc 6008 2008-07-23 00:24:22Z vern $ - #include "config.h" #include "RuleCondition.h" @@ -151,9 +149,19 @@ bool RuleConditionEval::DoMatch(Rule* rule, RuleEndpointState* state, else args.append(new StringVal("")); - Val* val = id->ID_Val()->AsFunc()->Call(&args); - bool result = val->AsBool(); - Unref(val); + bool result = 0; + + try + { + Val* val = id->ID_Val()->AsFunc()->Call(&args); + result = val->AsBool(); + Unref(val); + } + + catch ( InterpreterException& e ) + { + result = false; + } return result; } diff --git a/src/RuleCondition.h b/src/RuleCondition.h index a092543d62..b859930581 100644 --- a/src/RuleCondition.h +++ b/src/RuleCondition.h @@ -1,5 +1,3 @@ -// $Id: RuleCondition.h 80 2004-07-14 20:15:50Z jason $ - #ifndef rulecondition_h #define rulecondition_h diff --git a/src/RuleMatcher.cc b/src/RuleMatcher.cc index 1ca891883d..c9cf1f5c11 100644 --- a/src/RuleMatcher.cc +++ b/src/RuleMatcher.cc @@ -1,5 +1,3 @@ -// $Id: RuleMatcher.cc 6724 2009-06-07 09:23:03Z vern $ - #include #include "config.h" @@ -75,6 +73,9 @@ RuleHdrTest::RuleHdrTest(RuleHdrTest& h) copied_set->ids = orig_set->ids; loop_over_list(orig_set->patterns, l) copied_set->patterns.append(copy_string(orig_set->patterns[l])); + delete copied_set; + // TODO: Why do we create copied_set only to then + // never use it? } } @@ -190,7 +191,7 @@ void RuleMatcher::Delete(RuleHdrTest* node) bool RuleMatcher::ReadFiles(const name_list& files) { -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG HeapLeakChecker::Disabler disabler; #endif @@ -201,7 +202,7 @@ bool RuleMatcher::ReadFiles(const name_list& files) rules_in = search_for_file(files[i], "sig", 0, false, 0); if ( ! rules_in ) { - reporter->Error("Can't open signature file", files[i]); + reporter->Error("Can't open signature file %s", files[i]); return false; } @@ -1069,16 +1070,22 @@ static bool val_to_maskedval(Val* v, maskedvalue_list* append_to) break; case TYPE_SUBNET: -#ifdef BROv6 { - uint32* n = v->AsSubNet()->net; - uint32* m = v->AsSubNetVal()->Mask(); + const uint32* n; + uint32 m[4]; + v->AsSubNet().Prefix().GetBytes(&n); + v->AsSubNetVal()->Mask().CopyIPv6(m); + + for ( unsigned int i = 0; i < 4; ++i ) + m[i] = ntohl(m[i]); + bool is_v4_mask = m[0] == 0xffffffff && m[1] == m[0] && m[2] == m[0]; - if ( is_v4_addr(n) && is_v4_mask ) + if ( v->AsSubNet().Prefix().GetFamily() == IPv4 && + is_v4_mask ) { - mval->val = ntohl(to_v4_addr(n)); + mval->val = ntohl(*n); mval->mask = m[3]; } @@ -1089,10 +1096,6 @@ static bool val_to_maskedval(Val* v, maskedvalue_list* append_to) mval->mask = 0; } } -#else - mval->val = ntohl(v->AsSubNet()->net); - mval->mask = v->AsSubNetVal()->Mask(); -#endif break; default: @@ -1116,7 +1119,12 @@ void id_to_maskedvallist(const char* id, maskedvalue_list* append_to) val_list* vals = v->AsTableVal()->ConvertToPureList()->Vals(); loop_over_list(*vals, i ) if ( ! val_to_maskedval((*vals)[i], append_to) ) + { + delete_vals(vals); return; + } + + delete_vals(vals); } else diff --git a/src/RuleMatcher.h b/src/RuleMatcher.h index 085253c16e..5bba69e130 100644 --- a/src/RuleMatcher.h +++ b/src/RuleMatcher.h @@ -1,5 +1,3 @@ -// $Id: RuleMatcher.h 3526 2006-09-12 07:32:21Z vern $ - #ifndef sigs_h #define sigs_h diff --git a/src/SMB.cc b/src/SMB.cc index 5b3db68db9..edce2a69b8 100644 --- a/src/SMB.cc +++ b/src/SMB.cc @@ -1,5 +1,3 @@ -// $Id: SMB.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "NetVar.h" diff --git a/src/SMB.h b/src/SMB.h index 408fa91068..f7287efb79 100644 --- a/src/SMB.h +++ b/src/SMB.h @@ -1,5 +1,3 @@ -// $Id: SMB.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef smb_h diff --git a/src/SMTP.cc b/src/SMTP.cc index 5822d9d75f..85a3bc79dc 100644 --- a/src/SMTP.cc +++ b/src/SMTP.cc @@ -1,5 +1,3 @@ -// $Id: SMTP.cc 6782 2009-06-28 02:19:03Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -355,7 +353,6 @@ void SMTP_Analyzer::ProcessLine(int length, const char* line, bool orig) int ext_len; get_word(end_of_line - line, line, ext_len, ext); - line = skip_whitespace(line + ext_len, end_of_line); ProcessExtension(ext_len, ext); } } diff --git a/src/SMTP.h b/src/SMTP.h index 69a5bc3e24..5b15dc44c0 100644 --- a/src/SMTP.h +++ b/src/SMTP.h @@ -1,5 +1,3 @@ -// $Id: SMTP.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef smtp_h diff --git a/src/SMTP_cmd.def b/src/SMTP_cmd.def index 79667ba7bd..545136048d 100644 --- a/src/SMTP_cmd.def +++ b/src/SMTP_cmd.def @@ -1,5 +1,3 @@ -// $Id: SMTP_cmd.def 80 2004-07-14 20:15:50Z jason $ -// // Definitions of SMTP commands. SMTP_CMD_DEF(EHLO) diff --git a/src/SSH.cc b/src/SSH.cc index b4ca9aa153..3a8f468ae4 100644 --- a/src/SSH.cc +++ b/src/SSH.cc @@ -1,5 +1,3 @@ -// $Id: SSH.cc 6782 2009-06-28 02:19:03Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -52,23 +50,24 @@ void SSH_Analyzer::DeliverStream(int length, const u_char* data, bool is_orig) // SSH-.-\n // // We're interested in the "version" part here. - + if ( length < 4 || memcmp(line, "SSH-", 4) != 0 ) { Weird("malformed_ssh_identification"); ProtocolViolation("malformed ssh identification", line, length); return; } - + int i; for ( i = 4; i < length && line[i] != '-'; ++i ) ; - + if ( TCP() ) { if ( length >= i ) { - const uint32* dst; + IPAddr dst; + if ( is_orig ) dst = TCP()->Orig()->dst_addr; else diff --git a/src/SSH.h b/src/SSH.h index 503b1abcbe..ccdcd76929 100644 --- a/src/SSH.h +++ b/src/SSH.h @@ -1,5 +1,3 @@ -// $Id: SSH.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef ssh_h diff --git a/src/SSL-binpac.cc b/src/SSL-binpac.cc index ec1fd206f6..db9a7004d6 100644 --- a/src/SSL-binpac.cc +++ b/src/SSL-binpac.cc @@ -7,6 +7,7 @@ SSL_Analyzer_binpac::SSL_Analyzer_binpac(Connection* c) : TCP_ApplicationAnalyzer(AnalyzerTag::SSL, c) { interp = new binpac::SSL::SSL_Conn(this); + had_gap = false; } SSL_Analyzer_binpac::~SSL_Analyzer_binpac() @@ -37,11 +38,24 @@ void SSL_Analyzer_binpac::DeliverStream(int len, const u_char* data, bool orig) if ( TCP()->IsPartial() ) return; - interp->NewData(orig, data, data + len); + if ( had_gap ) + // XXX: If only one side had a content gap, we could still try to + // deliver data to the other side if the script layer can handle this. + return; + + try + { + interp->NewData(orig, data, data + len); + } + catch ( const binpac::Exception& e ) + { + ProtocolViolation(fmt("Binpac exception: %s", e.c_msg())); + } } void SSL_Analyzer_binpac::Undelivered(int seq, int len, bool orig) { TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); + had_gap = true; interp->NewGap(orig, len); } diff --git a/src/SSL-binpac.h b/src/SSL-binpac.h index 7d0c8d3939..8dab19d00c 100644 --- a/src/SSL-binpac.h +++ b/src/SSL-binpac.h @@ -30,6 +30,7 @@ public: protected: binpac::SSL::SSL_Conn* interp; + bool had_gap; }; diff --git a/src/SSLv2.cc b/src/SSLv2.cc deleted file mode 100644 index f699b7bfdb..0000000000 --- a/src/SSLv2.cc +++ /dev/null @@ -1,946 +0,0 @@ -// $Id: SSLv2.cc 5988 2008-07-19 07:02:12Z vern $ - -#include "SSLv2.h" -#include "SSLv3.h" - -// --- Initalization of static variables -------------------------------------- - -uint SSLv2_Interpreter::totalConnections = 0; -uint SSLv2_Interpreter::analyzedConnections = 0; -uint SSLv2_Interpreter::openedConnections = 0; -uint SSLv2_Interpreter::failedConnections = 0; -uint SSLv2_Interpreter::weirdConnections = 0; -uint SSLv2_Interpreter::totalRecords = 0; -uint SSLv2_Interpreter::clientHelloRecords = 0; -uint SSLv2_Interpreter::serverHelloRecords = 0; -uint SSLv2_Interpreter::clientMasterKeyRecords = 0; -uint SSLv2_Interpreter::errorRecords = 0; - - -// --- SSLv2_Interpreter ------------------------------------------------------- - -/*! - * The Constructor. - * - * \param proxy Pointer to the SSLProxy_Analyzer who created this instance. - */ -SSLv2_Interpreter::SSLv2_Interpreter(SSLProxy_Analyzer* proxy) -: SSL_Interpreter(proxy) - { - ++totalConnections; - records = 0; - bAnalyzedCounted = false; - connState = START; - - pServerCipherSpecs = 0; - pClientCipherSpecs = 0; - bClientWantsCachedSession = false; - usedCipherSpec = (SSLv2_CipherSpec) 0; - - pConnectionId = 0; - pChallenge = 0; - pSessionId = 0; - pMasterClearKey = 0; - pMasterEncryptedKey = 0; - pClientReadKey = 0; - pServerReadKey = 0; - } - -/*! - * The Destructor. - */ -SSLv2_Interpreter::~SSLv2_Interpreter() - { - if ( connState != CLIENT_MASTERKEY_SEEN && - connState != CACHED_SESSION && - connState != START && // we only complain if we saw some data - connState != ERROR_SEEN ) - ++failedConnections; - - if ( connState != CLIENT_MASTERKEY_SEEN && connState != CACHED_SESSION ) - ++weirdConnections; - - delete pServerCipherSpecs; - delete pClientCipherSpecs; - delete pConnectionId; - delete pChallenge; - delete pSessionId; - delete pMasterClearKey; - delete pMasterEncryptedKey; - delete pClientReadKey; - delete pServerReadKey; - } - -/*! - * This method implements SSL_Interpreter::BuildInterpreterEndpoints() - */ -void SSLv2_Interpreter::BuildInterpreterEndpoints() - { - orig = new SSLv2_Endpoint(this, 1); - resp = new SSLv2_Endpoint(this, 0); - } - -/*! - * This method prints some counters. - */ -void SSLv2_Interpreter::printStats() - { - printf("SSLv2:\n"); - printf("totalConnections = %u\n", totalConnections); - printf("analyzedConnections = %u\n", analyzedConnections); - printf("openedConnections = %u\n", openedConnections); - printf("failedConnections = %u\n", failedConnections); - printf("weirdConnections = %u\n", weirdConnections); - - printf("totalRecords = %u\n", totalRecords); - printf("clientHelloRecords = %u\n", clientHelloRecords); - printf("serverHelloRecords = %u\n", serverHelloRecords); - printf("clientMasterKeyRecords = %u\n", clientMasterKeyRecords); - printf("errorRecords = %u\n", errorRecords); - - printf("SSL_RecordBuilder::maxAllocCount = %u\n", SSL_RecordBuilder::maxAllocCount); - printf("SSL_RecordBuilder::maxFragmentCount = %u\n", SSL_RecordBuilder::maxFragmentCount); - printf("SSL_RecordBuilder::fragmentedHeaders = %u\n", SSL_RecordBuilder::fragmentedHeaders); - } - -/*! - * \return the current state of the ssl connection - */ -SSLv2_States SSLv2_Interpreter::ConnState() - { - return connState; - } - -/*! - * This method is called by SSLv2_Endpoint::Deliver(). It is the main entry - * point of this class. The header of the given SSLV2 record is analyzed and - * its contents are then passed to the corresponding analyzer method. After - * the record has been analyzed, the ssl connection state is updated. - * - * \param s Pointer to the endpoint which sent the record - * \param length length of SSLv2 record - * \param data pointer to SSLv2 record to analyze - */ -void SSLv2_Interpreter::NewSSLRecord(SSL_InterpreterEndpoint* s, - int length, const u_char* data) - { - ++records; - ++totalRecords; - - if ( ! bAnalyzedCounted ) - { - ++analyzedConnections; - bAnalyzedCounted = true; - } - - // We should see a maximum of 4 cleartext records. - if ( records == 5 ) - { // so this should never happen - Weird("SSLv2: Saw more than 4 records, skipping connection..."); - proxy->SetSkip(1); - return; - } - - // SSLv2 record header analysis - uint32 recordLength = 0; // data length of SSLv2 record - bool isEscape = false; - uint8 padding = 0; - const u_char* contents; - - if ( (data[0] & 0x80) > 0 ) - { // we have a two-byte record header - recordLength = ((data[0] & 0x7f) << 8) | data[1]; - contents = data + 2; - if ( recordLength + 2 != uint32(length) ) - { - // This should never happen, otherwise - // we have a bug in the SSL_RecordBuilder. - Weird("SSLv2: FATAL: recordLength doesn't match data block length!"); - connState = ERROR_REQUIRED; - proxy->SetSkip(1); - return; - } - } - else - { // We have a three-byte record header. - recordLength = ((data[0] & 0x3f) << 8) | data[1]; - isEscape = (data[0] & 0x40) != 0; - padding = data[2]; - contents = data + 3; - if ( recordLength + 3 != uint32(length) ) - { - // This should never happen, otherwise - // we have a bug in the SSL_RecordBuilder. - Weird("SSLv2: FATAL: recordLength doesn't match data block length!"); - connState = ERROR_REQUIRED; - proxy->SetSkip(1); - return; - } - - if ( padding == 0 && ! isEscape ) - Weird("SSLv2: 3 Byte record header, but no escape, no padding!"); - } - - if ( recordLength == 0 ) - { - Weird("SSLv2: Record length is zero (no record data)!"); - return; - } - - if ( isEscape ) - Weird("SSLv2: Record has escape bit set (security escape)!"); - - if ( padding > 0 && connState != CACHED_SESSION && - connState != CLIENT_MASTERKEY_SEEN ) - Weird("SSLv2 record with padding > 0 in cleartext!"); - - // MISSING: - // A final consistency check is done when a block cipher is used - // and the protocol is using encryption. The amount of data present - // in a record (RECORD-LENGTH))must be a multiple of the cipher's - // block size. If the received record is not a multiple of the - // cipher's block size then the record is considered damaged, and it - // is to be treated as if an "I/O Error" had occurred (i.e. an - // unrecoverable error is asserted and the connection is closed). - - switch ( connState ) { - case START: - // Only CLIENT-HELLLOs allowed here. - if ( contents[0] != SSLv2_MT_CLIENT_HELLO ) - { - Weird("SSLv2: First packet is not a CLIENT-HELLO!"); - analyzeRecord(s, recordLength, contents); - connState = ERROR_REQUIRED; - } - else - connState = ClientHelloRecord(s, recordLength, contents); - break; - - case CLIENT_HELLO_SEEN: - // Only SERVER-HELLOs or ERRORs allowed here. - if ( contents[0] == SSLv2_MT_SERVER_HELLO ) - connState = ServerHelloRecord(s, recordLength, contents); - else if ( contents[0] == SSLv2_MT_ERROR ) - connState = ErrorRecord(s, recordLength, contents); - else - { - Weird("SSLv2: State violation in CLIENT_HELLO_SEEN!"); - analyzeRecord(s, recordLength, contents); - connState = ERROR_REQUIRED; - } - break; - - case NEW_SESSION: - // We expect a client master key. - if ( contents[0] == SSLv2_MT_CLIENT_MASTER_KEY ) - connState = ClientMasterKeyRecord(s, recordLength, contents); - else if ( contents[0] == SSLv2_MT_ERROR ) - connState = ErrorRecord(s, recordLength, contents); - else - { - Weird("SSLv2: State violation in NEW_SESSION or encrypted record!"); - analyzeRecord(s, recordLength, contents); - connState = ERROR_REQUIRED; - } - - delete pServerCipherSpecs; - pServerCipherSpecs = 0; - break; - - case CACHED_SESSION: - delete pServerCipherSpecs; - pServerCipherSpecs = 0; - // No break here. - - case CLIENT_MASTERKEY_SEEN: - // If no error record, no further analysis. - if ( contents[0] == SSLv2_MT_ERROR && - recordLength == SSLv2_ERROR_RECORD_SIZE ) - connState = ErrorRecord(s, recordLength, contents); - else - { - // So we finished the cleartext handshake. - // Skip all further data. - - proxy->SetSkip(1); - ++openedConnections; - } - break; - - case ERROR_REQUIRED: - if ( contents[0] == SSLv2_MT_ERROR ) - connState = ErrorRecord(s, recordLength, contents); - else - { - // We lost tracking: this should not happen. - Weird("SSLv2: State inconsistency in ERROR_REQUIRED (lost tracking!)!"); - analyzeRecord(s, recordLength, contents); - connState = ERROR_REQUIRED; - } - break; - - case ERROR_SEEN: - // We don't have recoverable errors in cleartext phase, - // so we shouldn't see anymore packets. - Weird("SSLv2: Traffic after error record!"); - analyzeRecord(s, recordLength, contents); - break; - - default: - reporter->InternalError("SSLv2: unknown state"); - break; - } - } - -/*! - * This method is called whenever the connection tracking failed. It calls - * the corresponding analyzer method for the given SSLv2 record, but does not - * update the ssl connection state. - * - * \param s Pointer to the endpoint which sent the record - * \param length length of SSLv2 record - * \param data pointer to SSLv2 record to analyze - */ -void SSLv2_Interpreter::analyzeRecord(SSL_InterpreterEndpoint* s, - int length, const u_char* data) - { - switch ( data[0] ) { - case SSLv2_MT_ERROR: - ErrorRecord(s, length, data); - break; - - case SSLv2_MT_CLIENT_HELLO: - ClientHelloRecord(s, length, data); - break; - - case SSLv2_MT_CLIENT_MASTER_KEY: - ClientMasterKeyRecord(s, length, data); - break; - - case SSLv2_MT_SERVER_HELLO: - ServerHelloRecord(s, length, data); - break; - - case SSLv2_MT_CLIENT_FINISHED: - case SSLv2_MT_SERVER_VERIFY: - case SSLv2_MT_SERVER_FINISHED: - case SSLv2_MT_REQUEST_CERTIFICATE: - case SSLv2_MT_CLIENT_CERTIFICATE: - Weird("SSLv2: Encrypted record type seems to be in cleartext"); - break; - - default: - // Unknown record type. - Weird("SSLv2: Unknown record type or encrypted record"); - break; - } - } - -/*! - * This method analyses a SSLv2 CLIENT-HELLO record. - * - * \param s Pointer to the endpoint which sent the record - * \param length length of SSLv2 CLIENT-HELLO record - * \param data pointer to SSLv2 CLIENT-HELLO record to analyze - * - * \return the updated state of the current ssl connection - */ -SSLv2_States SSLv2_Interpreter::ClientHelloRecord(SSL_InterpreterEndpoint* s, - int recordLength, const u_char* recordData) - { - // This method gets the record's data (without the header). - ++clientHelloRecords; - - if ( s != orig ) - Weird("SSLv2: CLIENT-HELLO record from server!"); - - // There should not be any pending data in the SSLv2 reassembler, - // because the client should wait for a server response. - if ( ((SSLv2_Endpoint*) s)->isDataPending() ) - Weird("SSLv2: Pending data in SSL_RecordBuilder after CLIENT-HELLO!"); - - // Client hello minimum header size check. - if ( recordLength < SSLv2_CLIENT_HELLO_HEADER_SIZE ) - { - Weird("SSLv2: CLIENT-HELLO is too small!"); - return ERROR_REQUIRED; - } - - // Extract the data of the client hello header. - SSLv2_ClientHelloHeader ch; - ch.clientVersion = uint16(recordData[1] << 8) | recordData[2]; - ch.cipherSpecLength = uint16(recordData[3] << 8) | recordData[4]; - ch.sessionIdLength = uint16(recordData[5] << 8) | recordData[6]; - ch.challengeLength = uint16(recordData[7] << 8) | recordData[8]; - - if ( ch.clientVersion != SSLProxy_Analyzer::SSLv20 && - ch.clientVersion != SSLProxy_Analyzer::SSLv30 && - ch.clientVersion != SSLProxy_Analyzer::SSLv31 ) - { - Weird("SSLv2: Unsupported SSL-Version in CLIENT-HELLO"); - return ERROR_REQUIRED; - } - - if ( ch.challengeLength + ch.cipherSpecLength + ch.sessionIdLength + - SSLv2_CLIENT_HELLO_HEADER_SIZE != recordLength ) - { - Weird("SSLv2: Size inconsistency in CLIENT-HELLO"); - return ERROR_REQUIRED; - } - - // The CIPHER-SPECS-LENGTH must be > 0 and a multiple of 3. - if ( ch.cipherSpecLength == 0 || ch.cipherSpecLength % 3 != 0 ) - { - Weird("SSLv2: Nonconform CIPHER-SPECS-LENGTH in CLIENT-HELLO."); - return ERROR_REQUIRED; - } - - // The SESSION-ID-LENGTH must either be zero or 16. - if ( ch.sessionIdLength != 0 && ch.sessionIdLength != 16 ) - Weird("SSLv2: Nonconform SESSION-ID-LENGTH in CLIENT-HELLO."); - - if ( (ch.challengeLength < 16) || (ch.challengeLength > 32)) - Weird("SSLv2: Nonconform CHALLENGE-LENGTH in CLIENT-HELLO."); - - const u_char* ptr = recordData; - ptr += SSLv2_CLIENT_HELLO_HEADER_SIZE + ch.cipherSpecLength; - - pSessionId = new SSL_DataBlock(ptr, ch.sessionIdLength); - - // If decrypting, store the challenge. - if ( ssl_store_key_material && ch.challengeLength <= 32 ) - pChallenge = new SSL_DataBlock(ptr, ch.challengeLength); - - bClientWantsCachedSession = ch.sessionIdLength != 0; - - TableVal* currentCipherSuites = - analyzeCiphers(s, ch.cipherSpecLength, - recordData + SSLv2_CLIENT_HELLO_HEADER_SIZE); - - fire_ssl_conn_attempt(ch.clientVersion, currentCipherSuites); - - return CLIENT_HELLO_SEEN; - } - -/*! - * This method analyses a SSLv2 SERVER-HELLO record. - * - * \param s Pointer to the endpoint which sent the record - * \param length length of SSLv2 SERVER-HELLO record - * \param data pointer to SSLv2 SERVER-HELLO record to analyze - * - * \return the updated state of the current ssl connection - */ -SSLv2_States SSLv2_Interpreter::ServerHelloRecord(SSL_InterpreterEndpoint* s, - int recordLength, const u_char* recordData) - { - ++serverHelloRecords; - TableVal* currentCipherSuites = NULL; - - if ( s != resp ) - Weird("SSLv2: SERVER-HELLO from client!"); - - if ( recordLength < SSLv2_SERVER_HELLO_HEADER_SIZE ) - { - Weird("SSLv2: SERVER-HELLO is too small!"); - return ERROR_REQUIRED; - } - - // Extract the data of the client hello header. - SSLv2_ServerHelloHeader sh; - sh.sessionIdHit = recordData[1]; - sh.certificateType = recordData[2]; - sh.serverVersion = uint16(recordData[3] << 8) | recordData[4]; - sh.certificateLength = uint16(recordData[5] << 8) | recordData[6]; - sh.cipherSpecLength = uint16(recordData[7] << 8) | recordData[8]; - sh.connectionIdLength = uint16(recordData[9] << 8) | recordData[10]; - - if ( sh.serverVersion != SSLProxy_Analyzer::SSLv20 ) - { - Weird("SSLv2: Unsupported SSL-Version in SERVER-HELLO"); - return ERROR_REQUIRED; - } - - if ( sh.certificateLength + sh.cipherSpecLength + - sh.connectionIdLength + - SSLv2_SERVER_HELLO_HEADER_SIZE != recordLength ) - { - Weird("SSLv2: Size inconsistency in SERVER-HELLO"); - return ERROR_REQUIRED; - } - - // The length of the CONNECTION-ID must be between 16 and 32 bytes. - if ( sh.connectionIdLength < 16 || sh.connectionIdLength > 32 ) - Weird("SSLv2: Nonconform CONNECTION-ID-LENGTH in SERVER-HELLO"); - - // If decrypting, store the connection ID. - if ( ssl_store_key_material && sh.connectionIdLength <= 32 ) - { - const u_char* ptr = recordData; - - ptr += SSLv2_SERVER_HELLO_HEADER_SIZE + sh.cipherSpecLength + - sh.certificateLength; - - pConnectionId = new SSL_DataBlock(ptr, sh.connectionIdLength); - } - - if ( sh.sessionIdHit == 0 ) - { - // Generating reusing-connection event. - EventHandlerPtr event = ssl_session_insertion; - - if ( event ) - { - TableVal* sessionIDTable = - MakeSessionID( - recordData + - SSLv2_SERVER_HELLO_HEADER_SIZE + - sh.certificateLength + - sh.cipherSpecLength, - sh.connectionIdLength); - - val_list* vl = new val_list; - vl->append(proxy->BuildConnVal()); - vl->append(sessionIDTable); - - proxy->ConnectionEvent(ssl_session_insertion, vl); - } - } - - SSLv2_States nextState; - - if ( sh.sessionIdHit != 0 ) - { // we're using a cached session - - // There should not be any pending data in the SSLv2 - // reassembler, because the server should wait for a - // client response. - if ( ((SSLv2_Endpoint*) s)->isDataPending() ) - { - // But turns out some SSL Implementations do this - // when using a cached session. - } - - // Consistency check for SESSION-ID-HIT. - if ( ! bClientWantsCachedSession ) - Weird("SSLv2: SESSION-ID hit in SERVER-HELLO, but no SESSION-ID in CLIENT-HELLO!"); - - // If the SESSION-ID-HIT flag is non-zero then the - // CERTIFICATE-TYPE, CERTIFICATE-LENGTH and - // CIPHER-SPECS-LENGTH fields will be zero. - if ( sh.certificateType != 0 || sh.certificateLength != 0 || - sh.cipherSpecLength != 0 ) - Weird("SSLv2: SESSION-ID-HIT, but session data in SERVER-HELLO"); - - // Generate reusing-connection event. - if ( pSessionId ) - { - fire_ssl_conn_reused(pSessionId); - delete pSessionId; - pSessionId = 0; - } - - nextState = CACHED_SESSION; - } - else - { // we're starting a new session - - // There should not be any pending data in the SSLv2 - // reassembler, because the server should wait for - // a client response. - if ( ((SSLv2_Endpoint*) s)->isDataPending() ) - Weird("SSLv2: Pending data in SSL_RecordBuilder after SERVER-HELLO (new session)!"); - - // TODO: check certificate length ??? - if ( sh.certificateLength == 0 ) - Weird("SSLv2: No certificate in SERVER-HELLO!"); - - // The CIPHER-SPECS-LENGTH must be > zero and a multiple of 3. - if ( sh.cipherSpecLength == 0 ) - Weird("SSLv2: No CIPHER-SPECS in SERVER-HELLO!"); - - if ( sh.cipherSpecLength % 3 != 0 ) - { - Weird("SSLv2: Nonconform CIPHER-SPECS-LENGTH in SERVER-HELLO"); - return ERROR_REQUIRED; - } - - const u_char* ptr = recordData; - ptr += sh.certificateLength + SSLv2_SERVER_HELLO_HEADER_SIZE; - currentCipherSuites = analyzeCiphers(s, sh.cipherSpecLength, ptr); - - nextState = NEW_SESSION; - } - - // Check if at least one cipher is supported by the client. - if ( pClientCipherSpecs && pServerCipherSpecs ) - { - bool bFound = false; - for ( int i = 0; i < pClientCipherSpecs->len; i += 3 ) - { - for ( int j = 0; j < pServerCipherSpecs->len; j += 3 ) - { - if ( memcmp(pClientCipherSpecs + i, - pServerCipherSpecs + j, 3) == 0 ) - { - bFound = true; - i = pClientCipherSpecs->len; - break; - } - } - } - - if ( ! bFound ) - { - Weird("SSLv2: Client's and server's CIPHER-SPECS don't match!"); - nextState = ERROR_REQUIRED; - } - - delete pClientCipherSpecs; - pClientCipherSpecs = 0; - } - - // Certificate analysis. - if ( sh.certificateLength > 0 && ssl_analyze_certificates != 0 ) - { - analyzeCertificate(s, recordData + SSLv2_SERVER_HELLO_HEADER_SIZE, - sh.certificateLength, sh.certificateType, false); - } - - if ( nextState == NEW_SESSION ) - // generate server-reply event - fire_ssl_conn_server_reply(sh.serverVersion, currentCipherSuites); - - else if ( nextState == CACHED_SESSION ) - { // generate server-reply event - fire_ssl_conn_server_reply(sh.serverVersion, currentCipherSuites); - // Generate a connection-established event with a dummy - // cipher suite, since we can't remember session information - // (yet). - // Note: A new session identifier is sent encrypted in SSLv2! - fire_ssl_conn_established(sh.serverVersion, 0xABCD); - } - else - // Unref, since the table is not delivered to any event. - Unref(currentCipherSuites); - - return nextState; - } - -/*! - * This method analyses a SSLv2 CLIENT-MASTER-KEY record. - * - * \param s Pointer to the endpoint which sent the record - * \param length length of SSLv2 CLIENT-MASTER-KEY record - * \param data pointer to SSLv2 CLIENT-MASTER-KEY record to analyze - * - * \return the updated state of the current ssl connection - */ -SSLv2_States SSLv2_Interpreter:: - ClientMasterKeyRecord(SSL_InterpreterEndpoint* s, int recordLength, - const u_char* recordData) - { - ++clientMasterKeyRecords; - SSLv2_States nextState = CLIENT_MASTERKEY_SEEN; - - if ( s != orig ) - Weird("SSLv2: CLIENT-MASTER-KEY from server!"); - - if ( recordLength < SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE ) - { - Weird("SSLv2: CLIENT-MASTER-KEY is too small!"); - return ERROR_REQUIRED; - } - - // Extract the data of the client master key header. - SSLv2_ClientMasterKeyHeader cmk; - cmk.cipherKind = - ((recordData[1] << 16) | recordData[2] << 8) | recordData[3]; - cmk.clearKeyLength = uint16(recordData[4] << 8) | recordData[5]; - cmk.encryptedKeyLength = uint16(recordData[6] << 8) | recordData[7]; - cmk.keyArgLength = uint16(recordData[8] << 8) | recordData[9]; - - if ( cmk.clearKeyLength + cmk.encryptedKeyLength + cmk.keyArgLength + - SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE != recordLength ) - { - Weird("SSLv2: Size inconsistency in CLIENT-MASTER-KEY"); - return ERROR_REQUIRED; - } - - // Check if cipher is supported by the server. - if ( pServerCipherSpecs ) - { - bool bFound = false; - for ( int i = 0; i < pServerCipherSpecs->len; i += 3 ) - { - uint32 cipherSpec = - ((pServerCipherSpecs->data[i] << 16) | - pServerCipherSpecs->data[i+1] << 8) | - pServerCipherSpecs->data[i+2]; - - if ( cmk.cipherKind == cipherSpec ) - { - bFound = true; - break; - } - } - - if ( ! bFound ) - { - Weird("SSLv2: Client chooses unadvertised cipher in CLIENT-MASTER-KEY!"); - nextState = ERROR_REQUIRED; - } - else - nextState = CLIENT_MASTERKEY_SEEN; - - delete pServerCipherSpecs; - pServerCipherSpecs = 0; - } - - // TODO: check if cipher has been advertised before. - - SSL_CipherSpec* pCipherSpecTemp = 0; - - HashKey h(static_cast(cmk.cipherKind)); - pCipherSpecTemp = (SSL_CipherSpec*) SSL_CipherSpecDict.Lookup(&h); - if ( ! pCipherSpecTemp || ! (pCipherSpecTemp->flags & SSL_FLAG_SSLv20) ) - Weird("SSLv2: Unknown CIPHER-SPEC in CLIENT-MASTER-KEY!"); - else - { // check for conistency of clearKeyLength - if ( cmk.clearKeyLength * 8 != pCipherSpecTemp->clearKeySize ) - { - Weird("SSLv2: Inconsistency of clearKeyLength in CLIENT-MASTER-KEY!"); - // nextState = ERROR_REQUIRED; - } - - // TODO: check for consistency of encryptedKeyLength. - // TODO: check for consistency of keyArgLength. -// switch ( cmk.cipherKind ) -// { -// case SSL_CK_RC4_128_WITH_MD5: -// case SSL_CK_RC4_128_EXPORT40_WITH_MD5: -// if ( cmk.keyArgLength != 0 ) -// { -// Weird("SSLv2: Inconsistency of keyArgLength in CLIENT-MASTER-KEY!"); -// //nextState = ERROR_REQUIRED; -// } -// break; -// case SSL_CK_DES_64_CBC_WITH_MD5: -// case SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5: -// case SSL_CK_RC2_128_CBC_WITH_MD5: -// case SSL_CK_IDEA_128_CBC_WITH_MD5: -// case SSL_CK_DES_192_EDE3_CBC_WITH_MD5: -// if ( cmk.keyArgLength != 8 ) -// { -// Weird("SSLv2: Inconsistency of keyArgLength in CLIENT-MASTER-KEY!"); -// } -// break; -// } - } - - // Remember the used cipher spec. - usedCipherSpec = SSLv2_CipherSpec(cmk.cipherKind); - - // If decrypting, store the clear key part of the master key. - if ( ssl_store_key_material /* && cmk.clearKeyLength == 11 */ ) - { - pMasterClearKey = - new SSL_DataBlock((recordData + SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE), cmk.clearKeyLength); - - pMasterEncryptedKey = - new SSL_DataBlock((recordData + SSLv2_CLIENT_MASTER_KEY_HEADER_SIZE + cmk.clearKeyLength ), cmk.encryptedKeyLength); - } - - if ( nextState == CLIENT_MASTERKEY_SEEN ) - fire_ssl_conn_established(SSLProxy_Analyzer::SSLv20, - cmk.cipherKind); - - return nextState; - } - - -/*! - * This method analyses a SSLv2 ERROR record. - * - * \param s Pointer to the endpoint which sent the record - * \param length length of SSLv2 ERROR record - * \param data pointer to SSLv2 ERROR record to analyze - * - * \return the updated state of the current ssl connection - */ -SSLv2_States SSLv2_Interpreter::ErrorRecord(SSL_InterpreterEndpoint* s, - int recordLength, const u_char* recordData) - { - ++errorRecords; - - if ( unsigned(recordLength) != SSLv2_ERROR_RECORD_SIZE ) - { - Weird("SSLv2: Size mismatch in Error Record!"); - return ERROR_REQUIRED; - } - - SSLv2_ErrorRecord er; - er.errorCode = (recordData[1] << 8) | recordData[2]; - SSL3x_AlertLevel al = SSL3x_AlertLevel(255); - - switch ( er.errorCode ) { - case SSLv2_PE_NO_CIPHER: - // The client doesn't support a cipher which the server - // supports. Only from client to server and not recoverable! - al = SSL3x_ALERT_LEVEL_FATAL; - break; - - case SSLv2_PE_NO_CERTIFICATE: - if ( s == orig ) - // from client to server: not recoverable - al = SSL3x_ALERT_LEVEL_FATAL; - else - // from server to client: recoverable - al = SSL3x_ALERT_LEVEL_WARNING; - break; - - case SSLv2_PE_BAD_CERTIFICATE: - if ( s == orig ) - // from client to server: not recoverable - al = SSL3x_ALERT_LEVEL_FATAL; - else - // from server to client: recoverable - al = SSL3x_ALERT_LEVEL_WARNING; - break; - - case SSLv2_PE_UNSUPPORTED_CERTIFICATE_TYPE: - if ( s == orig ) - // from client to server: not recoverable - al = SSL3x_ALERT_LEVEL_FATAL; - else - // from server to client: recoverable - al = SSL3x_ALERT_LEVEL_WARNING; - break; - - default: - al = SSL3x_ALERT_LEVEL_FATAL; - break; - } - - fire_ssl_conn_alert(SSLProxy_Analyzer::SSLv20, al, er.errorCode); - - return ERROR_SEEN; - } - -/*! - * This method analyses a set of SSLv2 cipher suites. - * - * \param s Pointer to the endpoint which sent the cipher suites - * \param length length of cipher suites - * \param data pointer to cipher suites to analyze - * - * \return a pointer to a Bro TableVal (of type cipher_suites_list) which contains - * the cipher suites list of the current analyzed record - */ -TableVal* SSLv2_Interpreter::analyzeCiphers(SSL_InterpreterEndpoint* s, - int length, const u_char* data) - { - if ( length > MAX_CIPHERSPEC_SIZE ) - { - if ( s == orig ) - Weird("SSLv2: Client has CipherSpecs > MAX_CIPHERSPEC_SIZE"); - else - Weird("SSLv2: Server has CipherSpecs > MAX_CIPHERSPEC_SIZE"); - } - else - { // cipher specs are not too big - if ( ssl_compare_cipherspecs ) - { // store cipher specs for state analysis - if ( s == resp ) - pServerCipherSpecs = - new SSL_DataBlock(data, length); - else - pClientCipherSpecs = - new SSL_DataBlock(data, length); - } - } - - const u_char* pCipher = data; - bool bExtractCipherSuite = false; - TableVal* pCipherTable = 0; - - // We only extract the cipher suite when the corresponding - // ssl events are defined (otherwise we do work for nothing - // and suffer a memory leak). - // FIXME: This check needs to be done only once! - if ( (s == orig && ssl_conn_attempt) || - (s == resp && ssl_conn_server_reply) ) - { - pCipherTable = new TableVal(cipher_suites_list); - bExtractCipherSuite = true; - } - - for ( int i = 0; i < length; i += 3 ) - { - SSL_CipherSpec* pCurrentCipherSpec; - uint32 cipherSpecID = - ((pCipher[0] << 16) | pCipher[1] << 8) | pCipher[2]; - - // Check for unknown cipher specs. - HashKey h(static_cast(cipherSpecID)); - pCurrentCipherSpec = - (SSL_CipherSpec*) SSL_CipherSpecDict.Lookup(&h); - - if ( ! pCurrentCipherSpec ) - { - if ( s == orig ) - Weird("SSLv2: Unknown CIPHER-SPEC in CLIENT-HELLO!"); - else - Weird("SSLv2: Unknown CIPHER-SPEC in SERVER-HELLO!"); - } - - if ( bExtractCipherSuite ) - { - Val* index = new Val(cipherSpecID, TYPE_COUNT); - pCipherTable->Assign(index, 0); - Unref(index); - } - - pCipher += 3; - } - - return pCipherTable; - } - -// --- SSLv2_EndPoint --------------------------------------------------------- - -/*! - * The constructor. - * - * \param interpreter Pointer to the SSLv2 interpreter to whom this endpoint belongs to - * \param is_orig true if this is the originating endpoint of the ssl connection, - * false otherwise - */ -SSLv2_Endpoint::SSLv2_Endpoint(SSLv2_Interpreter* interpreter, int is_orig) -: SSL_InterpreterEndpoint(interpreter, is_orig) - { - sentRecords = 0; - } - -/*! - * The destructor. - */ -SSLv2_Endpoint::~SSLv2_Endpoint() - { - } - -/*! - * This method is called by the SSLProxy_Analyzer with a complete reassembled - * SSLv2 record. It passes the record to SSLv2_Interpreter::NewSSLRecord(). - * - * \param t reserved (always zero) - * \param seq reserved (always zero) - * \param len length of the data block containing the ssl record - * \param data pointer to the data block containing the ssl record - */ -void SSLv2_Endpoint::Deliver(int len, const u_char* data) - { - ++((SSLv2_Endpoint*)peer)->sentRecords; - - ((SSLv2_Interpreter*)interpreter)->NewSSLRecord(this, len, data); - } diff --git a/src/Scope.cc b/src/Scope.cc index 196937d984..4916cdbfce 100644 --- a/src/Scope.cc +++ b/src/Scope.cc @@ -1,5 +1,3 @@ -// $Id: Scope.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -129,7 +127,7 @@ ID* lookup_ID(const char* name, const char* curr_module, bool no_global, if ( id ) { if ( need_export && ! id->IsExport() && ! in_debug ) - reporter->Error("identifier is not exported:", + reporter->Error("identifier is not exported: %s", fullname.c_str()); Ref(id); @@ -219,5 +217,5 @@ Scope* current_scope() Scope* global_scope() { - return scopes[0]; + return scopes.length() == 0 ? 0 : scopes[0]; } diff --git a/src/Scope.h b/src/Scope.h index 1ed8d6da42..1ef58d871c 100644 --- a/src/Scope.h +++ b/src/Scope.h @@ -1,5 +1,3 @@ -// $Id: Scope.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef scope_h diff --git a/src/ScriptAnaly.cc b/src/ScriptAnaly.cc index 700c0ed4e8..bca75cc800 100644 --- a/src/ScriptAnaly.cc +++ b/src/ScriptAnaly.cc @@ -1,5 +1,3 @@ -// $Id: ScriptAnaly.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "Dict.h" diff --git a/src/ScriptAnaly.h b/src/ScriptAnaly.h index 180971e769..0561ecd389 100644 --- a/src/ScriptAnaly.h +++ b/src/ScriptAnaly.h @@ -1,5 +1,3 @@ -// $Id: ScriptAnaly.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef scriptanaly_h diff --git a/src/SerialInfo.h b/src/SerialInfo.h index 3ed2e91d26..aa4c382349 100644 --- a/src/SerialInfo.h +++ b/src/SerialInfo.h @@ -1,5 +1,3 @@ -// $Id: SerialInfo.h 6752 2009-06-14 04:24:52Z vern $ -// // Helper classes to pass data between serialization methods. #ifndef serialinfo_h @@ -17,6 +15,7 @@ public: pid_32bit = false; include_locations = true; new_cache_strategy = false; + broccoli_peer = false; } SerialInfo(const SerialInfo& info) @@ -30,6 +29,7 @@ public: pid_32bit = info.pid_32bit; include_locations = info.include_locations; new_cache_strategy = info.new_cache_strategy; + broccoli_peer = info.broccoli_peer; } // Parameters that control serialization. @@ -48,6 +48,11 @@ public: // If true, we support keeping objs in cache permanently. bool new_cache_strategy; + // If true, we're connecting to a Broccoli. If so, serialization + // specifics may be adapted for functionality Broccoli does not + // support. + bool broccoli_peer; + ChunkedIO::Chunk* chunk; // chunk written right before the serialization // Attributes set during serialization. @@ -72,6 +77,7 @@ public: print = 0; pid_32bit = false; new_cache_strategy = false; + broccoli_peer = false; } UnserialInfo(const UnserialInfo& info) @@ -88,6 +94,7 @@ public: print = info.print; pid_32bit = info.pid_32bit; new_cache_strategy = info.new_cache_strategy; + broccoli_peer = info.broccoli_peer; } // Parameters that control unserialization. @@ -108,6 +115,11 @@ public: // If true, we support keeping objs in cache permanently. bool new_cache_strategy; + // If true, we're connecting to a Broccoli. If so, serialization + // specifics may be adapted for functionality Broccoli does not + // support. + bool broccoli_peer; + // If a global ID already exits, of these policies is used. enum { Keep, // keep the old ID and ignore the new diff --git a/src/SerialObj.cc b/src/SerialObj.cc index cddb0b0963..a8ab969f5e 100644 --- a/src/SerialObj.cc +++ b/src/SerialObj.cc @@ -1,5 +1,3 @@ -// $Id: SerialObj.cc 7075 2010-09-13 02:39:38Z vern $ - #include "SerialObj.h" #include "Serializer.h" @@ -21,7 +19,7 @@ SerialObj* SerialObj::Instantiate(SerialType type) return o; } - reporter->Error(fmt("Unknown object type 0x%08x", type)); + reporter->Error("Unknown object type 0x%08x", type); return 0; } @@ -31,7 +29,7 @@ const char* SerialObj::ClassName(SerialType type) if ( f != names->end() ) return f->second; - reporter->Error(fmt("Unknown object type 0x%08x", type)); + reporter->Error("Unknown object type 0x%08x", type); return ""; } diff --git a/src/SerialObj.h b/src/SerialObj.h index 4a12d53fe6..c3dc65684c 100644 --- a/src/SerialObj.h +++ b/src/SerialObj.h @@ -1,5 +1,3 @@ -// $Id: SerialObj.h 6752 2009-06-14 04:24:52Z vern $ -// // Infrastructure for serializable objects. // // How to make objects of class Foo serializable: diff --git a/src/SerialTypes.h b/src/SerialTypes.h index 4d9b7a5880..c47ff19298 100644 --- a/src/SerialTypes.h +++ b/src/SerialTypes.h @@ -1,5 +1,3 @@ -// $Id: SerialTypes.h 6752 2009-06-14 04:24:52Z vern $ - #ifndef serialtypes_h #define serialtypes_h @@ -127,7 +125,7 @@ SERIAL_EXPR(FIELD_EXPR, 22) SERIAL_EXPR(HAS_FIELD_EXPR, 23) SERIAL_EXPR(RECORD_CONSTRUCTOR_EXPR, 24) SERIAL_EXPR(FIELD_ASSIGN_EXPR, 25) -SERIAL_EXPR(RECORD_MATCH_EXPR, 26) +// There used to be a SERIAL_EXPR(RECORD_MATCH_EXPR, 26) here SERIAL_EXPR(ARITH_COERCE_EXPR, 27) SERIAL_EXPR(RECORD_COERCE_EXPR, 28) SERIAL_EXPR(FLATTEN_EXPR, 29) diff --git a/src/SerializationFormat.cc b/src/SerializationFormat.cc index b229cbbc87..10dd4f29ea 100644 --- a/src/SerializationFormat.cc +++ b/src/SerializationFormat.cc @@ -1,5 +1,3 @@ -// $Id: SerializationFormat.cc 5873 2008-06-28 19:25:03Z vern $ - #include #include "net_util.h" @@ -232,6 +230,71 @@ bool BinarySerializationFormat::Read(string* v, const char* tag) return true; } +bool BinarySerializationFormat::Read(IPAddr* addr, const char* tag) + { + int n = 0; + if ( ! Read(&n, "addr-len") ) + return false; + + if ( n != 1 && n != 4 ) + return false; + + uint32_t raw[4]; + + for ( int i = 0; i < n; ++i ) + { + if ( ! Read(&raw[i], "addr-part") ) + return false; + + raw[i] = htonl(raw[i]); + } + + if ( n == 1 ) + *addr = IPAddr(IPv4, raw, IPAddr::Network); + else + *addr = IPAddr(IPv6, raw, IPAddr::Network); + + return true; + } + +bool BinarySerializationFormat::Read(IPPrefix* prefix, const char* tag) + { + IPAddr addr; + int len; + + if ( ! (Read(&addr, "prefix") && Read(&len, "width")) ) + return false; + + *prefix = IPPrefix(addr, len); + return true; + } + +bool BinarySerializationFormat::Read(struct in_addr* addr, const char* tag) + { + uint32_t* bytes = (uint32_t*) &addr->s_addr; + + if ( ! Read(&bytes[0], "addr4") ) + return false; + + bytes[0] = htonl(bytes[0]); + return true; + } + +bool BinarySerializationFormat::Read(struct in6_addr* addr, const char* tag) + { + uint32_t* bytes = (uint32_t*) &addr->s6_addr; + + for ( int i = 0; i < 4; ++i ) + { + if ( ! Read(&bytes[i], "addr6-part") ) + return false; + + bytes[i] = htonl(bytes[i]); + } + + return true; + } + bool BinarySerializationFormat::Write(char v, const char* tag) { DBG_LOG(DBG_SERIAL, "Write char %s [%s]", fmt_bytes(&v, 1), tag); @@ -301,6 +364,53 @@ bool BinarySerializationFormat::Write(const string& s, const char* tag) return Write(s.data(), s.size(), tag); } +bool BinarySerializationFormat::Write(const IPAddr& addr, const char* tag) + { + const uint32_t* raw; + int n = addr.GetBytes(&raw); + + assert(n == 1 || n == 4); + + if ( ! Write(n, "addr-len") ) + return false; + + for ( int i = 0; i < n; ++i ) + { + if ( ! Write(ntohl(raw[i]), "addr-part") ) + return false; + } + + return true; + } + +bool BinarySerializationFormat::Write(const IPPrefix& prefix, const char* tag) + { + return Write(prefix.Prefix(), "prefix") && Write(prefix.Length(), "width"); + } + +bool BinarySerializationFormat::Write(const struct in_addr& addr, const char* tag) + { + const uint32_t* bytes = (uint32_t*) &addr.s_addr; + + if ( ! Write(ntohl(bytes[0]), "addr4") ) + return false; + + return true; + } + +bool BinarySerializationFormat::Write(const struct in6_addr& addr, const char* tag) + { + const uint32_t* bytes = (uint32_t*) &addr.s6_addr; + + for ( int i = 0; i < 4; ++i ) + { + if ( ! Write(ntohl(bytes[i]), "addr6-part") ) + return false; + } + + return true; + } + bool BinarySerializationFormat::WriteOpenTag(const char* tag) { return true; @@ -391,6 +501,30 @@ bool XMLSerializationFormat::Read(string* s, const char* tag) return false; } +bool XMLSerializationFormat::Read(IPAddr* addr, const char* tag) + { + reporter->InternalError("no reading of xml"); + return false; + } + +bool XMLSerializationFormat::Read(IPPrefix* prefix, const char* tag) + { + reporter->InternalError("no reading of xml"); + return false; + } + +bool XMLSerializationFormat::Read(struct in_addr* addr, const char* tag) + { + reporter->InternalError("no reading of xml"); + return false; + } + +bool XMLSerializationFormat::Read(struct in6_addr* addr, const char* tag) + { + reporter->InternalError("no reading of xml"); + return false; + } + bool XMLSerializationFormat::Write(char v, const char* tag) { return WriteElem(tag, "char", &v, 1); @@ -471,6 +605,30 @@ bool XMLSerializationFormat::Write(const char* buf, int len, const char* tag) return WriteElem(tag, "string", buf, len); } +bool XMLSerializationFormat::Write(const IPAddr& addr, const char* tag) + { + reporter->InternalError("XML output of addresses not implemented"); + return false; + } + +bool XMLSerializationFormat::Write(const IPPrefix& prefix, const char* tag) + { + reporter->InternalError("XML output of prefixes not implemented"); + return false; + } + +bool XMLSerializationFormat::Write(const struct in_addr& addr, const char* tag) + { + reporter->InternalError("XML output of in_addr not implemented"); + return false; + } + +bool XMLSerializationFormat::Write(const struct in6_addr& addr, const char* tag) + { + reporter->InternalError("XML output of in6_addr not implemented"); + return false; + } + bool XMLSerializationFormat::WriteEncodedString(const char* s, int len) { while ( len-- ) diff --git a/src/SerializationFormat.h b/src/SerializationFormat.h index b9c7ec1549..f270b61bae 100644 --- a/src/SerializationFormat.h +++ b/src/SerializationFormat.h @@ -1,5 +1,3 @@ -// $Id: SerializationFormat.h 5873 2008-06-28 19:25:03Z vern $ -// // Implements different data formats for serialization. #ifndef SERIALIZATION_FORMAT @@ -11,6 +9,9 @@ using namespace std; #include "util.h" +class IPAddr; +class IPPrefix; + // Abstract base class. class SerializationFormat { public: @@ -30,6 +31,10 @@ public: virtual bool Read(bool* v, const char* tag) = 0; virtual bool Read(double* d, const char* tag) = 0; virtual bool Read(string* s, const char* tag) = 0; + virtual bool Read(IPAddr* addr, const char* tag) = 0; + virtual bool Read(IPPrefix* prefix, const char* tag) = 0; + virtual bool Read(struct in_addr* addr, const char* tag) = 0; + virtual bool Read(struct in6_addr* addr, const char* tag) = 0; // Returns number of raw bytes read since last call to StartRead(). int BytesRead() const { return bytes_read; } @@ -52,6 +57,10 @@ public: virtual bool Write(const char* s, const char* tag) = 0; virtual bool Write(const char* buf, int len, const char* tag) = 0; virtual bool Write(const string& s, const char* tag) = 0; + virtual bool Write(const IPAddr& addr, const char* tag) = 0; + virtual bool Write(const IPPrefix& prefix, const char* tag) = 0; + virtual bool Write(const struct in_addr& addr, const char* tag) = 0; + virtual bool Write(const struct in6_addr& addr, const char* tag) = 0; virtual bool WriteOpenTag(const char* tag) = 0; virtual bool WriteCloseTag(const char* tag) = 0; @@ -92,6 +101,10 @@ public: virtual bool Read(double* d, const char* tag); virtual bool Read(char** str, int* len, const char* tag); virtual bool Read(string* s, const char* tag); + virtual bool Read(IPAddr* addr, const char* tag); + virtual bool Read(IPPrefix* prefix, const char* tag); + virtual bool Read(struct in_addr* addr, const char* tag); + virtual bool Read(struct in6_addr* addr, const char* tag); virtual bool Write(int v, const char* tag); virtual bool Write(uint16 v, const char* tag); virtual bool Write(uint32 v, const char* tag); @@ -103,6 +116,10 @@ public: virtual bool Write(const char* s, const char* tag); virtual bool Write(const char* buf, int len, const char* tag); virtual bool Write(const string& s, const char* tag); + virtual bool Write(const IPAddr& addr, const char* tag); + virtual bool Write(const IPPrefix& prefix, const char* tag); + virtual bool Write(const struct in_addr& addr, const char* tag); + virtual bool Write(const struct in6_addr& addr, const char* tag); virtual bool WriteOpenTag(const char* tag); virtual bool WriteCloseTag(const char* tag); virtual bool WriteSeparator(); @@ -125,6 +142,10 @@ public: virtual bool Write(const char* s, const char* tag); virtual bool Write(const char* buf, int len, const char* tag); virtual bool Write(const string& s, const char* tag); + virtual bool Write(const IPAddr& addr, const char* tag); + virtual bool Write(const IPPrefix& prefix, const char* tag); + virtual bool Write(const struct in_addr& addr, const char* tag); + virtual bool Write(const struct in6_addr& addr, const char* tag); virtual bool WriteOpenTag(const char* tag); virtual bool WriteCloseTag(const char* tag); virtual bool WriteSeparator(); @@ -140,6 +161,10 @@ public: virtual bool Read(double* d, const char* tag); virtual bool Read(char** str, int* len, const char* tag); virtual bool Read(string* s, const char* tag); + virtual bool Read(IPAddr* addr, const char* tag); + virtual bool Read(IPPrefix* prefix, const char* tag); + virtual bool Read(struct in_addr* addr, const char* tag); + virtual bool Read(struct in6_addr* addr, const char* tag); private: // Encodes non-printable characters. diff --git a/src/Serializer.cc b/src/Serializer.cc index 96821408a5..06bbf73f48 100644 --- a/src/Serializer.cc +++ b/src/Serializer.cc @@ -1,5 +1,3 @@ -// $Id: Serializer.cc 6752 2009-06-14 04:24:52Z vern $ - #include #include #include @@ -911,7 +909,7 @@ bool FileSerializer::Read(UnserialInfo* info, const char* file, bool header) void FileSerializer::ReportError(const char* str) { - reporter->Error(str); + reporter->Error("%s", str); } void FileSerializer::GotID(ID* id, Val* val) @@ -1105,9 +1103,9 @@ void EventPlayer::Process() void Packet::Describe(ODesc* d) const { const IP_Hdr ip = IP(); - d->Add(dotted_addr(ip.SrcAddr())); + d->Add(ip.SrcAddr()); d->Add("->"); - d->Add(dotted_addr(ip.DstAddr())); + d->Add(ip.DstAddr()); } bool Packet::Serialize(SerialInfo* info) const @@ -1147,7 +1145,7 @@ Packet* Packet::Unserialize(UnserialInfo* info) if ( ! info->s->Read((char**) &tag, 0, "tag") ) return 0; - u_char* pkt; + char* pkt; int caplen; if ( ! info->s->Read((char**) &pkt, &caplen, "data") ) { @@ -1157,7 +1155,7 @@ Packet* Packet::Unserialize(UnserialInfo* info) hdr->caplen = uint32(caplen); p->hdr = hdr; - p->pkt = pkt; + p->pkt = (u_char*) pkt; p->tag = tag; p->hdr_size = get_link_header_size(p->link_type); diff --git a/src/Serializer.h b/src/Serializer.h index 857abc0980..e7396cb7f8 100644 --- a/src/Serializer.h +++ b/src/Serializer.h @@ -1,5 +1,3 @@ -// $Id: Serializer.h 6752 2009-06-14 04:24:52Z vern $ - #ifndef SERIALIZER_H #define SERIALIZER_H @@ -71,6 +69,8 @@ public: { return format->Read(const_cast(str), len, tag); } bool Read(string* s, const char* tag); + bool Read(IPAddr* a, const char* tag) { return format->Read(a, tag); } + bool Read(IPPrefix* p, const char* tag) { return format->Read(p, tag); } bool Write(const char* s, const char* tag) { return format->Write(s, tag); } @@ -78,6 +78,8 @@ public: { return format->Write(buf, len, tag); } bool Write(const string& s, const char* tag) { return format->Write(s.data(), s.size(), tag); } + bool Write(const IPAddr& a, const char* tag) { return format->Write(a, tag); } + bool Write(const IPPrefix& p, const char* tag) { return format->Write(p, tag); } bool WriteOpenTag(const char* tag) { return format->WriteOpenTag(tag); } @@ -123,7 +125,7 @@ protected: // This will be increased whenever there is an incompatible change // in the data format. - static const uint32 DATA_FORMAT_VERSION = 20; + static const uint32 DATA_FORMAT_VERSION = 22; ChunkedIO* io; @@ -263,7 +265,7 @@ public: virtual ~CloneSerializer() { } protected: - virtual void ReportError(const char* msg) { reporter->Error(msg); } + virtual void ReportError(const char* msg) { reporter->Error("%s", msg); } virtual void GotID(ID* id, Val* val) { } virtual void GotEvent(const char* name, double time, EventHandlerPtr event, val_list* args) { } @@ -413,7 +415,7 @@ public: } const IP_Hdr IP() const - { return IP_Hdr((struct ip *) (pkt + hdr_size)); } + { return IP_Hdr((struct ip *) (pkt + hdr_size), true); } void Describe(ODesc* d) const; diff --git a/src/Sessions.cc b/src/Sessions.cc index 47696a1651..7d829b602b 100644 --- a/src/Sessions.cc +++ b/src/Sessions.cc @@ -1,5 +1,3 @@ -// $Id: Sessions.cc 7075 2010-09-13 02:39:38Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. @@ -29,7 +27,6 @@ #include "InterConn.h" #include "Discard.h" #include "RuleMatcher.h" -#include "ConnCompressor.h" #include "DPM.h" #include "PacketSort.h" @@ -74,8 +71,8 @@ void TimerMgrExpireTimer::Dispatch(double t, int is_expire) NetSessions::NetSessions() { TypeList* t = new TypeList(); - t->Append(base_type(TYPE_COUNT)); // source IP address - t->Append(base_type(TYPE_COUNT)); // dest IP address + t->Append(base_type(TYPE_ADDR)); // source IP address + t->Append(base_type(TYPE_ADDR)); // dest IP address t->Append(base_type(TYPE_COUNT)); // source and dest ports ch = new CompositeHash(t); @@ -144,22 +141,12 @@ NetSessions::~NetSessions() delete SYN_OS_Fingerprinter; delete pkt_profiler; Unref(arp_analyzer); + delete discarder; + delete stp_manager; } void NetSessions::Done() { - delete stp_manager; - delete discarder; - } - -namespace // private namespace - { - bool looks_like_IPv4_packet(int len, const struct ip* ip_hdr) - { - if ( len < int(sizeof(struct ip)) ) - return false; - return ip_hdr->ip_v == 4 && ntohs(ip_hdr->ip_len) == len; - } } void NetSessions::DispatchPacket(double t, const struct pcap_pkthdr* hdr, @@ -226,24 +213,35 @@ void NetSessions::NextPacket(double t, const struct pcap_pkthdr* hdr, } const struct ip* ip = (const struct ip*) (pkt + hdr_size); + if ( ip->ip_v == 4 ) { - IP_Hdr ip_hdr(ip); + IP_Hdr ip_hdr(ip, false); DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size); } - else if ( arp_analyzer && arp_analyzer->IsARP(pkt, hdr_size) ) - arp_analyzer->NextPacket(t, hdr, pkt, hdr_size); + else if ( ip->ip_v == 6 ) + { + if ( caplen < sizeof(struct ip6_hdr) ) + { + Weird("truncated_IP", hdr, pkt); + return; + } + + IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt + hdr_size), false, caplen); + DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size); + } + + else if ( ARP_Analyzer::IsARP(pkt, hdr_size) ) + { + if ( arp_analyzer ) + arp_analyzer->NextPacket(t, hdr, pkt, hdr_size); + } else { -#ifdef BROv6 - IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt + hdr_size)); - DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size); -#else - Weird("non_IPv4_packet", hdr, pkt); + Weird("unknown_packet_type", hdr, pkt); return; -#endif } } @@ -282,9 +280,17 @@ void NetSessions::NextPacketSecondary(double /* t */, const struct pcap_pkthdr* StringVal* cmd_val = new StringVal(sp->Event()->Filter()); args->append(cmd_val); - args->append(BuildHeader(ip)); + IP_Hdr ip_hdr(ip, false); + args->append(ip_hdr.BuildPktHdrVal()); // ### Need to queue event here. - sp->Event()->Event()->Call(args); + try + { + sp->Event()->Event()->Call(args); + } + + catch ( InterpreterException& e ) + { /* Already reported. */ } + delete args; } } @@ -343,24 +349,6 @@ int NetSessions::CheckConnectionTag(Connection* conn) return 1; } - -static bool looks_like_IPv4_packet(int len, const struct ip* ip_hdr) - { - if ( (unsigned int) len < sizeof(struct ip) ) - return false; - - if ( ip_hdr->ip_v == 4 && ntohs(ip_hdr->ip_len) == len ) - return true; - else - return false; - } - -static inline void delete_tunnel_info(TunnelInfo *ti) - { - if ( ti ) - delete ti; - } - void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, const IP_Hdr* ip_hdr, const u_char* const pkt, int hdr_size) @@ -391,9 +379,8 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, return; FragReassembler* f = 0; - uint32 frag_field = ip_hdr->FragField(); - if ( (frag_field & 0x3fff) != 0 ) + if ( ip_hdr->IsFragment() ) { dump_this_packet = 1; // always record fragments @@ -404,12 +391,12 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, // Don't try to reassemble, that's doomed. // Discard all except the first fragment (which // is useful in analyzing header-only traces) - if ( (frag_field & 0x1fff) != 0 ) + if ( ip_hdr->FragOffset() != 0 ) return; } else { - f = NextFragment(t, ip_hdr, pkt + hdr_size, frag_field); + f = NextFragment(t, ip_hdr, pkt + hdr_size); const IP_Hdr* ih = f->ReassembledPkt(); if ( ! ih ) // It didn't reassemble into anything yet. @@ -426,11 +413,56 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, len -= ip_hdr_len; // remove IP header caplen -= ip_hdr_len; + // We stop building the chain when seeing IPPROTO_ESP so if it's + // there, it's always the last. + if ( ip_hdr->LastHeader() == IPPROTO_ESP ) + { + dump_this_packet = 1; + if ( esp_packet ) + { + val_list* vl = new val_list(); + vl->append(ip_hdr->BuildPktHdrVal()); + mgr.QueueEvent(esp_packet, vl); + } + Remove(f); + // Can't do more since upper-layer payloads are going to be encrypted. + return; + } + +#ifdef ENABLE_MOBILE_IPV6 + // We stop building the chain when seeing IPPROTO_MOBILITY so it's always + // last if present. + if ( ip_hdr->LastHeader() == IPPROTO_MOBILITY ) + { + dump_this_packet = 1; + + if ( ! ignore_checksums && mobility_header_checksum(ip_hdr) != 0xffff ) + { + Weird("bad_MH_checksum", hdr, pkt); + Remove(f); + return; + } + + if ( mobile_ipv6_message ) + { + val_list* vl = new val_list(); + vl->append(ip_hdr->BuildPktHdrVal()); + mgr.QueueEvent(mobile_ipv6_message, vl); + } + + if ( ip_hdr->NextProto() != IPPROTO_NONE ) + Weird("mobility_piggyback", hdr, pkt); + + Remove(f); + return; + } +#endif + TunnelInfo *tunnel_info = 0; - if ( tunnel_handler ) + if ( tunnel_handler ) { tunnel_info = tunnel_handler->DecapsulateTunnel(ip_hdr, len, caplen, hdr, pkt); - if (tunnel_info) + if (tunnel_info) { ip4 = tunnel_info->child->IP4_Hdr(); ip_hdr = tunnel_info->child; @@ -440,33 +472,11 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, } int proto = ip_hdr->NextProto(); - if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP && - proto != IPPROTO_ICMP ) - { - dump_this_packet = 1; - if ( f ) - Remove(f); - delete_tunnel_info(tunnel_info); - return; - } - uint32 min_hdr_len = (proto == IPPROTO_TCP) ? sizeof(struct tcphdr) : - (proto == IPPROTO_UDP ? sizeof(struct udphdr) : ICMP_MINLEN); - - if ( len < min_hdr_len ) + if ( CheckHeaderTrunc(proto, len, caplen, hdr, pkt) ) { - Weird("truncated_header", hdr, pkt); - if ( f ) - Remove(f); // ### - delete_tunnel_info(tunnel_info); - return; - } - if ( caplen < min_hdr_len ) - { - Weird("internally_truncated_header", hdr, pkt); - if ( f ) - Remove(f); // ### - delete_tunnel_info(tunnel_info); + delete tunnel_info; + Remove(f); return; } @@ -476,7 +486,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, id.src_addr = ip_hdr->SrcAddr(); id.dst_addr = ip_hdr->DstAddr(); Dictionary* d = 0; - bool pass_to_conn_compressor = false; switch ( proto ) { case IPPROTO_TCP: @@ -486,7 +495,6 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, id.dst_port = tp->th_dport; id.is_one_way = 0; d = &tcp_conns; - pass_to_conn_compressor = ip4 && use_connection_compressor; break; } @@ -505,7 +513,23 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, const struct icmp* icmpp = (const struct icmp *) data; id.src_port = icmpp->icmp_type; - id.dst_port = ICMP_counterpart(icmpp->icmp_type, + id.dst_port = ICMP4_counterpart(icmpp->icmp_type, + icmpp->icmp_code, + id.is_one_way); + + id.src_port = htons(id.src_port); + id.dst_port = htons(id.dst_port); + + d = &icmp_conns; + break; + } + + case IPPROTO_ICMPV6: + { + const struct icmp* icmpp = (const struct icmp *) data; + + id.src_port = icmpp->icmp_type; + id.dst_port = ICMP6_counterpart(icmpp->icmp_type, icmpp->icmp_code, id.is_one_way); @@ -517,14 +541,13 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, } default: - Weird(fmt("unknown_protocol %d", proto), hdr, pkt); - if ( f ) - Remove(f); - delete_tunnel_info(tunnel_info); + Weird(fmt("unknown_protocol_%d", proto), hdr, pkt); + delete tunnel_info; + Remove(f); return; } - HashKey* h = id.BuildConnKey(); + HashKey* h = BuildConnIDHashKey(id); if ( ! h ) reporter->InternalError("hash computation failed"); @@ -532,76 +555,76 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, // FIXME: The following is getting pretty complex. Need to split up // into separate functions. - if ( pass_to_conn_compressor ) - conn = conn_compressor->NextPacket(t, h, ip_hdr, hdr, pkt); + conn = (Connection*) d->Lookup(h); + if ( ! conn ) + { + conn = NewConn(h, t, &id, data, proto, tunnel_info); + if ( conn ) + d->Insert(h, conn); + } else { - conn = (Connection*) d->Lookup(h); - if ( ! conn ) + // We already know that connection. + int consistent = CheckConnectionTag(conn); + if ( consistent < 0 ) { + delete h; + delete tunnel_info; + Remove(f); + return; + } + + if ( ! consistent || conn->IsReuse(t, data) ) + { + if ( consistent ) + conn->Event(connection_reused, 0); + + Remove(conn); conn = NewConn(h, t, &id, data, proto, tunnel_info); if ( conn ) d->Insert(h, conn); } else - { - // We already know that connection. - int consistent = CheckConnectionTag(conn); - if ( consistent < 0 ) - { - delete h; - if ( f ) - Remove(f); - delete_tunnel_info(tunnel_info); - return; - } - - if ( ! consistent || conn->IsReuse(t, data) ) - { - if ( consistent ) - conn->Event(connection_reused, 0); - - Remove(conn); - conn = NewConn(h, t, &id, data, proto, tunnel_info); - if ( conn ) - d->Insert(h, conn); - } - else - delete h; - } - - if ( ! conn ) delete h; } if ( ! conn ) { - delete_tunnel_info(tunnel_info); - if ( f ) - Remove(f); + delete h; + delete tunnel_info; + Remove(f); return; } int record_packet = 1; // whether to record the packet at all int record_content = 1; // whether to record its data - int is_orig = addr_eq(id.src_addr, conn->OrigAddr()) && - id.src_port == conn->OrigPort(); + int is_orig = (id.src_addr == conn->OrigAddr()) && + (id.src_port == conn->OrigPort()); - if ( new_packet && ip4 ) - conn->Event(new_packet, 0, BuildHeader(ip4)); + Val* pkt_hdr_val = 0; + + if ( ipv6_ext_headers && ip_hdr->NumHeaders() > 1 ) + { + pkt_hdr_val = ip_hdr->BuildPktHdrVal(); + conn->Event(ipv6_ext_headers, 0, pkt_hdr_val); + } + + if ( new_packet ) + conn->Event(new_packet, 0, + pkt_hdr_val ? pkt_hdr_val->Ref() : ip_hdr->BuildPktHdrVal()); conn->NextPacket(t, is_orig, ip_hdr, len, caplen, data, record_packet, record_content, hdr, pkt, hdr_size); - if ( tunnel_info ) - delete tunnel_info; + delete tunnel_info; + if ( f ) { // Above we already recorded the fragment in its entirety. f->DeleteTimer(); - Remove(f); // ### + Remove(f); } else if ( record_packet ) @@ -617,110 +640,47 @@ void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr, } } -Val* NetSessions::BuildHeader(const struct ip* ip) +bool NetSessions::CheckHeaderTrunc(int proto, uint32 len, uint32 caplen, + const struct pcap_pkthdr* h, const u_char* p) { - static RecordType* pkt_hdr_type = 0; - static RecordType* ip_hdr_type = 0; - static RecordType* tcp_hdr_type = 0; - static RecordType* udp_hdr_type = 0; - static RecordType* icmp_hdr_type; - - if ( ! pkt_hdr_type ) - { - pkt_hdr_type = internal_type("pkt_hdr")->AsRecordType(); - ip_hdr_type = internal_type("ip_hdr")->AsRecordType(); - tcp_hdr_type = internal_type("tcp_hdr")->AsRecordType(); - udp_hdr_type = internal_type("udp_hdr")->AsRecordType(); - icmp_hdr_type = internal_type("icmp_hdr")->AsRecordType(); - } - - RecordVal* pkt_hdr = new RecordVal(pkt_hdr_type); - - RecordVal* ip_hdr = new RecordVal(ip_hdr_type); - - int ip_hdr_len = ip->ip_hl * 4; - int ip_pkt_len = ntohs(ip->ip_len); - - ip_hdr->Assign(0, new Val(ip->ip_hl * 4, TYPE_COUNT)); - ip_hdr->Assign(1, new Val(ip->ip_tos, TYPE_COUNT)); - ip_hdr->Assign(2, new Val(ip_pkt_len, TYPE_COUNT)); - ip_hdr->Assign(3, new Val(ntohs(ip->ip_id), TYPE_COUNT)); - ip_hdr->Assign(4, new Val(ip->ip_ttl, TYPE_COUNT)); - ip_hdr->Assign(5, new Val(ip->ip_p, TYPE_COUNT)); - ip_hdr->Assign(6, new AddrVal(ip->ip_src.s_addr)); - ip_hdr->Assign(7, new AddrVal(ip->ip_dst.s_addr)); - - pkt_hdr->Assign(0, ip_hdr); - - // L4 header. - const u_char* data = ((const u_char*) ip) + ip_hdr_len; - - int proto = ip->ip_p; + uint32 min_hdr_len = 0; switch ( proto ) { case IPPROTO_TCP: - { - const struct tcphdr* tp = (const struct tcphdr*) data; - RecordVal* tcp_hdr = new RecordVal(tcp_hdr_type); - - int tcp_hdr_len = tp->th_off * 4; - int data_len = ip_pkt_len - ip_hdr_len - tcp_hdr_len; - - tcp_hdr->Assign(0, new PortVal(ntohs(tp->th_sport), TRANSPORT_TCP)); - tcp_hdr->Assign(1, new PortVal(ntohs(tp->th_dport), TRANSPORT_TCP)); - tcp_hdr->Assign(2, new Val(uint32(ntohl(tp->th_seq)), TYPE_COUNT)); - tcp_hdr->Assign(3, new Val(uint32(ntohl(tp->th_ack)), TYPE_COUNT)); - tcp_hdr->Assign(4, new Val(tcp_hdr_len, TYPE_COUNT)); - tcp_hdr->Assign(5, new Val(data_len, TYPE_COUNT)); - tcp_hdr->Assign(6, new Val(tp->th_flags, TYPE_COUNT)); - tcp_hdr->Assign(7, new Val(ntohs(tp->th_win), TYPE_COUNT)); - - pkt_hdr->Assign(1, tcp_hdr); + min_hdr_len = sizeof(struct tcphdr); break; - } - case IPPROTO_UDP: - { - const struct udphdr* up = (const struct udphdr*) data; - RecordVal* udp_hdr = new RecordVal(udp_hdr_type); - - udp_hdr->Assign(0, new PortVal(ntohs(up->uh_sport), TRANSPORT_UDP)); - udp_hdr->Assign(1, new PortVal(ntohs(up->uh_dport), TRANSPORT_UDP)); - udp_hdr->Assign(2, new Val(ntohs(up->uh_ulen), TYPE_COUNT)); - - pkt_hdr->Assign(2, udp_hdr); + min_hdr_len = sizeof(struct udphdr); break; - } - case IPPROTO_ICMP: - { - const struct icmp* icmpp = (const struct icmp *) data; - RecordVal* icmp_hdr = new RecordVal(icmp_hdr_type); - - icmp_hdr->Assign(0, new Val(icmpp->icmp_type, TYPE_COUNT)); - - pkt_hdr->Assign(3, icmp_hdr); - break; - } - + case IPPROTO_ICMPV6: default: - { - // This is not a protocol we understand. - } + // Use for all other packets. + min_hdr_len = ICMP_MINLEN; } - return pkt_hdr; + if ( len < min_hdr_len ) + { + Weird("truncated_header", h, p); + return true; + } + + if ( caplen < min_hdr_len ) + { + Weird("internally_truncated_header", h, p); + return true; + } + + return false; } FragReassembler* NetSessions::NextFragment(double t, const IP_Hdr* ip, - const u_char* pkt, uint32 frag_field) + const u_char* pkt) { - uint32 src_addr = uint32(ip->SrcAddr4()); - uint32 dst_addr = uint32(ip->DstAddr4()); - uint32 frag_id = ntohs(ip->ID4()); // we actually could skip conv. + uint32 frag_id = ip->ID(); ListVal* key = new ListVal(TYPE_ANY); - key->Append(new Val(src_addr, TYPE_COUNT)); - key->Append(new Val(dst_addr, TYPE_COUNT)); + key->Append(new AddrVal(ip->SrcAddr())); + key->Append(new AddrVal(ip->DstAddr())); key->Append(new Val(frag_id, TYPE_COUNT)); HashKey* h = ch->ComputeHash(key, 1); @@ -730,7 +690,7 @@ FragReassembler* NetSessions::NextFragment(double t, const IP_Hdr* ip, FragReassembler* f = fragments.Lookup(h); if ( ! f ) { - f = new FragReassembler(this, ip, pkt, frag_field, h, t); + f = new FragReassembler(this, ip, pkt, h, t); fragments.Insert(h, f); Unref(key); return f; @@ -739,7 +699,7 @@ FragReassembler* NetSessions::NextFragment(double t, const IP_Hdr* ip, delete h; Unref(key); - f->AddFragment(t, ip, pkt, frag_field); + f->AddFragment(t, ip, pkt); return f; } @@ -755,7 +715,7 @@ int NetSessions::Get_OS_From_SYN(struct os_type* retval, quirks, ECN) : 0; } -bool NetSessions::CompareWithPreviousOSMatch(uint32 addr, int id) const +bool NetSessions::CompareWithPreviousOSMatch(const IPAddr& addr, int id) const { return SYN_OS_Fingerprinter ? SYN_OS_Fingerprinter->CacheMatch(addr, id) : 0; @@ -796,44 +756,30 @@ Connection* NetSessions::FindConnection(Val* v) // types, too. } - addr_type orig_addr = (*vl)[orig_h]->AsAddr(); - addr_type resp_addr = (*vl)[resp_h]->AsAddr(); + const IPAddr& orig_addr = (*vl)[orig_h]->AsAddr(); + const IPAddr& resp_addr = (*vl)[resp_h]->AsAddr(); PortVal* orig_portv = (*vl)[orig_p]->AsPortVal(); PortVal* resp_portv = (*vl)[resp_p]->AsPortVal(); ConnID id; -#ifdef BROv6 id.src_addr = orig_addr; id.dst_addr = resp_addr; -#else - id.src_addr = &orig_addr; - id.dst_addr = &resp_addr; -#endif id.src_port = htons((unsigned short) orig_portv->Port()); id.dst_port = htons((unsigned short) resp_portv->Port()); id.is_one_way = 0; // ### incorrect for ICMP connections - HashKey* h = id.BuildConnKey(); + HashKey* h = BuildConnIDHashKey(id); if ( ! h ) reporter->InternalError("hash computation failed"); Dictionary* d; if ( orig_portv->IsTCP() ) - { - if ( use_connection_compressor ) - { - Connection* conn = conn_compressor->Lookup(h); - delete h; - return conn; - } - else - d = &tcp_conns; - } + d = &tcp_conns; else if ( orig_portv->IsUDP() ) d = &udp_conns; else if ( orig_portv->IsICMP() ) @@ -886,17 +832,7 @@ void NetSessions::Remove(Connection* c) switch ( c->ConnTransport() ) { case TRANSPORT_TCP: - if ( use_connection_compressor && - conn_compressor->Remove(k) ) - // Note, if the Remove() returned false - // then the compressor doesn't know about - // this connection, which *should* mean that - // we never gave it the connection in the - // first place, and thus we should check - // the regular TCP table instead. - ; - - else if ( ! tcp_conns.RemoveEntry(k) ) + if ( ! tcp_conns.RemoveEntry(k) ) reporter->InternalError("connection missing"); break; @@ -922,6 +858,7 @@ void NetSessions::Remove(Connection* c) void NetSessions::Remove(FragReassembler* f) { + if ( ! f ) return; HashKey* k = f->Key(); if ( ! k ) reporter->InternalError("fragment block not in dictionary"); @@ -943,13 +880,8 @@ void NetSessions::Insert(Connection* c) // reference the old key for already existing connections. case TRANSPORT_TCP: - if ( use_connection_compressor ) - old = conn_compressor->Insert(c); - else - { - old = (Connection*) tcp_conns.Remove(c->Key()); - tcp_conns.Insert(c->Key(), c); - } + old = (Connection*) tcp_conns.Remove(c->Key()); + tcp_conns.Insert(c->Key(), c); break; case TRANSPORT_UDP: @@ -981,9 +913,6 @@ void NetSessions::Insert(Connection* c) void NetSessions::Drain() { - if ( use_connection_compressor ) - conn_compressor->Drain(); - IterCookie* cookie = tcp_conns.InitForIteration(); Connection* tc; @@ -1043,7 +972,7 @@ Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id, TunnelParent *tunnel_parent = 0; // Hmm... This is not great. - TransportProto tproto; + TransportProto tproto = TRANSPORT_UNKNOWN; switch ( proto ) { case IPPROTO_ICMP: tproto = TRANSPORT_ICMP; @@ -1054,6 +983,9 @@ Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id, case IPPROTO_UDP: tproto = TRANSPORT_UDP; break; + case IPPROTO_ICMPV6: + tproto = TRANSPORT_ICMP; + break; default: reporter->InternalError("unknown transport protocol"); break; @@ -1076,7 +1008,7 @@ Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id, // an analyzable connection. ConnID flip_id = *id; - const uint32* ta = flip_id.src_addr; + const IPAddr ta = flip_id.src_addr; flip_id.src_addr = flip_id.dst_addr; flip_id.dst_addr = ta; @@ -1100,10 +1032,7 @@ Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id, conn->AppendAddl(fmt("tag=%s", conn->GetTimerMgr()->GetTag().c_str())); - // If the connection compressor is active, it takes care of the - // new_connection/connection_external events for TCP connections. - if ( new_connection && - (tproto != TRANSPORT_TCP || ! use_connection_compressor) ) + if ( new_connection ) { conn->Event(new_connection, 0); diff --git a/src/Sessions.h b/src/Sessions.h index 9551ba5254..edbb7a8ffd 100644 --- a/src/Sessions.h +++ b/src/Sessions.h @@ -1,5 +1,3 @@ -// $Id: Sessions.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef sessions_h @@ -84,7 +82,7 @@ public: // Returns a reassembled packet, or nil if there are still // some missing fragments. FragReassembler* NextFragment(double t, const IP_Hdr* ip, - const u_char* pkt, uint32 frag_field); + const u_char* pkt); int Get_OS_From_SYN(struct os_type* retval, uint16 tot, uint8 DF_flag, uint8 TTL, uint16 WSS, @@ -92,7 +90,7 @@ public: uint32 tstamp, /* uint8 TOS, */ uint32 quirks, uint8 ECN) const; - bool CompareWithPreviousOSMatch(uint32 addr, int id) const; + bool CompareWithPreviousOSMatch(const IPAddr& addr, int id) const; // Looks up the connection referred to by the given Val, // which should be a conn_id record. Returns nil if there's @@ -195,10 +193,11 @@ protected: void Internal(const char* msg, const struct pcap_pkthdr* hdr, const u_char* pkt); - // Builds a record encapsulating a packet. This should be more - // general, including the equivalent of a union of tcp/udp/icmp - // headers . - Val* BuildHeader(const struct ip* ip); + // For a given protocol, checks whether the header's length as derived + // from lower-level headers or the length actually captured is less + // than that protocol's minimum header size. + bool CheckHeaderTrunc(int proto, uint32 len, uint32 caplen, + const struct pcap_pkthdr* hdr, const u_char* pkt); CompositeHash* ch; PDict(Connection) tcp_conns; diff --git a/src/SmithWaterman.cc b/src/SmithWaterman.cc index 3f27018550..ef329e49a5 100644 --- a/src/SmithWaterman.cc +++ b/src/SmithWaterman.cc @@ -1,5 +1,3 @@ -// $Id: SmithWaterman.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/SmithWaterman.h b/src/SmithWaterman.h index c8c80d09af..6ea191f5d9 100644 --- a/src/SmithWaterman.h +++ b/src/SmithWaterman.h @@ -1,5 +1,3 @@ -// $Id: SmithWaterman.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef smith_waterman_h diff --git a/src/StateAccess.cc b/src/StateAccess.cc index ef4c257f6b..2d0a8dfc5a 100644 --- a/src/StateAccess.cc +++ b/src/StateAccess.cc @@ -1,5 +1,3 @@ -// $Id: StateAccess.cc 6888 2009-08-20 18:23:11Z vern $ - #include "Val.h" #include "StateAccess.h" #include "Serializer.h" @@ -233,7 +231,7 @@ bool StateAccess::CheckOldSet(const char* op, ID* id, Val* index, bool StateAccess::MergeTables(TableVal* dst, Val* src) { - if ( ! src->Type()->Tag() == TYPE_TABLE ) + if ( src->Type()->Tag() != TYPE_TABLE ) { reporter->Error("type mismatch while merging tables"); return false; @@ -352,7 +350,7 @@ void StateAccess::Replay() v->AsRecordVal()->Assign(idx, op2 ? op2->Ref() : 0); } else - reporter->Error(fmt("access replay: unknown record field %s for assign", field)); + reporter->Error("access replay: unknown record field %s for assign", field); } else if ( t == TYPE_VECTOR ) @@ -413,7 +411,7 @@ void StateAccess::Replay() v->AsRecordVal()->Assign(idx, new_val, OP_INCR); } else - reporter->Error(fmt("access replay: unknown record field %s for assign", field)); + reporter->Error("access replay: unknown record field %s for assign", field); } else if ( t == TYPE_VECTOR ) @@ -680,7 +678,7 @@ bool StateAccess::DoUnserialize(UnserialInfo* info) target.id = new ID(name, SCOPE_GLOBAL, true); Ref(target.id); global_scope()->Insert(name, target.id); -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG heap_checker->IgnoreObject(target.id); #endif } diff --git a/src/StateAccess.h b/src/StateAccess.h index 1154756c83..bc5064602b 100644 --- a/src/StateAccess.h +++ b/src/StateAccess.h @@ -1,5 +1,3 @@ -// $Id: StateAccess.h 6781 2009-06-28 00:50:04Z vern $ -// // A class describing a state-modyfing access to a Value or an ID. #ifndef STATEACESSS_H diff --git a/src/Stats.cc b/src/Stats.cc index 28c0b38c22..c3035231e9 100644 --- a/src/Stats.cc +++ b/src/Stats.cc @@ -1,5 +1,3 @@ -// $Id: Stats.cc 7008 2010-03-25 02:42:20Z vern $ - #include "Conn.h" #include "File.h" #include "Event.h" @@ -8,8 +6,9 @@ #include "Stats.h" #include "Scope.h" #include "cq.h" -#include "ConnCompressor.h" - +#include "DNS_Mgr.h" +#include "Trigger.h" +#include "threading/Manager.h" int killed_by_inactivity = 0; @@ -129,19 +128,6 @@ void ProfileLogger::Log() expensive ? sessions->ConnectionMemoryUsageConnVals() / 1024 : 0 )); - const ConnCompressor::Sizes& cs = conn_compressor->Size(); - - file->Write(fmt("%.6f ConnCompressor: pending=%d pending_in_mem=%d full_conns=%d pending+real=%d mem=%dK avg=%.1f/%.1f\n", - network_time, - cs.pending_valid, - cs.pending_in_mem, - cs.connections, - cs.hash_table_size, - cs.memory / 1024, - cs.memory / double(cs.pending_valid), - cs.memory / double(cs.pending_in_mem) - )); - SessionStats s; sessions->GetStats(s); @@ -195,6 +181,19 @@ void ProfileLogger::Log() (timer_mgr->Size() * padded_sizeof(ConnectionTimer))) / 1024, network_time - timer_mgr->LastTimestamp())); + DNS_Mgr::Stats dstats; + dns_mgr->GetStats(&dstats); + + file->Write(fmt("%.06f DNS_Mgr: requests=%lu succesful=%lu failed=%lu pending=%lu cached_hosts=%lu cached_addrs=%lu\n", + network_time, + dstats.requests, dstats.successful, dstats.failed, dstats.pending, + dstats.cached_hosts, dstats.cached_addresses)); + + Trigger::Stats tstats; + Trigger::GetStats(&tstats); + + file->Write(fmt("%.06f Triggers: total=%lu pending=%lu\n", network_time, tstats.total, tstats.pending)); + unsigned int* current_timers = TimerMgr::CurrentTimers(); for ( int i = 0; i < NUM_TIMER_TYPES; ++i ) { @@ -204,6 +203,25 @@ void ProfileLogger::Log() current_timers[i])); } + file->Write(fmt("%0.6f Threads: current=%d\n", network_time, thread_mgr->NumThreads())); + + const threading::Manager::msg_stats_list& thread_stats = thread_mgr->GetMsgThreadStats(); + for ( threading::Manager::msg_stats_list::const_iterator i = thread_stats.begin(); + i != thread_stats.end(); ++i ) + { + threading::MsgThread::Stats s = i->second; + file->Write(fmt("%0.6f %-25s in=%" PRIu64 " out=%" PRIu64 " pending=%" PRIu64 "/%" PRIu64 + " (#queue r/w: in=%" PRIu64 "/%" PRIu64 " out=%" PRIu64 "/%" PRIu64 ")" + "\n", + network_time, + i->first.c_str(), + s.sent_in, s.sent_out, + s.pending_in, s.pending_out, + s.queue_in_stats.num_reads, s.queue_in_stats.num_writes, + s.queue_out_stats.num_reads, s.queue_out_stats.num_writes + )); + } + // Script-level state. unsigned int size, mem = 0; PDict(ID)* globals = global_scope()->Vars(); diff --git a/src/Stats.h b/src/Stats.h index 8acb7ef190..eeebfe2213 100644 --- a/src/Stats.h +++ b/src/Stats.h @@ -1,5 +1,3 @@ -// $Id: Stats.h 6703 2009-05-13 22:27:44Z vern $ -// // Classes that collect and report statistics. #ifndef STATS_H diff --git a/src/SteppingStone.cc b/src/SteppingStone.cc index 96652456bf..32850d82c6 100644 --- a/src/SteppingStone.cc +++ b/src/SteppingStone.cc @@ -1,5 +1,3 @@ -// $Id: SteppingStone.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/SteppingStone.h b/src/SteppingStone.h index 15165387f9..a47b268c83 100644 --- a/src/SteppingStone.h +++ b/src/SteppingStone.h @@ -1,5 +1,3 @@ -// $Id: SteppingStone.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef steppingstone_h diff --git a/src/Stmt.cc b/src/Stmt.cc index 80603a717b..582323bf91 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -1,5 +1,3 @@ -// $Id: Stmt.cc 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -260,6 +258,8 @@ static BroFile* print_stdout = 0; Val* PrintStmt::DoExec(val_list* vals, stmt_flow_type& /* flow */) const { + RegisterAccess(); + if ( ! print_stdout ) print_stdout = new BroFile(stdout); diff --git a/src/Stmt.h b/src/Stmt.h index bbfdd98bfd..7c3b42609b 100644 --- a/src/Stmt.h +++ b/src/Stmt.h @@ -1,5 +1,3 @@ -// $Id: Stmt.h 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef stmt_h @@ -54,6 +52,7 @@ public: void RegisterAccess() const { last_access = network_time; access_count++; } void AccessStats(ODesc* d) const; + uint32 GetAccessCount() const { return access_count; } virtual void Describe(ODesc* d) const; diff --git a/src/StmtEnums.h b/src/StmtEnums.h index c00b16112f..f431e3fea1 100644 --- a/src/StmtEnums.h +++ b/src/StmtEnums.h @@ -1,5 +1,3 @@ -// $Id: StmtEnums.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. diff --git a/src/TCP.cc b/src/TCP.cc index 4c56eb7ff9..57e4449bf8 100644 --- a/src/TCP.cc +++ b/src/TCP.cc @@ -1,5 +1,3 @@ -// $Id: TCP.cc 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include @@ -278,7 +276,7 @@ void TCP_Analyzer::ProcessSYN(const IP_Hdr* ip, const struct tcphdr* tp, uint32 tcp_hdr_len, int& seq_len, TCP_Endpoint* endpoint, TCP_Endpoint* peer, uint32 base_seq, uint32 ack_seq, - const uint32* orig_addr, + const IPAddr& orig_addr, int is_orig, TCP_Flags flags) { int len = seq_len; @@ -348,7 +346,7 @@ void TCP_Analyzer::ProcessSYN(const IP_Hdr* ip, const struct tcphdr* tp, // is_orig will be removed once we can do SYN-ACK fingerprinting. if ( OS_version_found && is_orig ) { - Val src_addr_val(orig_addr, TYPE_ADDR); + AddrVal src_addr_val(orig_addr); if ( generate_OS_version_event->Size() == 0 || generate_OS_version_event->Lookup(&src_addr_val) ) { @@ -416,7 +414,7 @@ int TCP_Analyzer::ProcessFlags(double t, uint32 tcp_hdr_len, int len, int& seq_len, TCP_Endpoint* endpoint, TCP_Endpoint* peer, uint32 base_seq, uint32 ack_seq, - const uint32* orig_addr, + const IPAddr& orig_addr, int is_orig, TCP_Flags flags) { if ( flags.SYN() ) @@ -991,8 +989,7 @@ void TCP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, if ( ! orig->did_close || ! resp->did_close ) Conn()->SetLastTime(t); - const uint32* orig_addr = Conn()->OrigAddr(); - const uint32* resp_addr = Conn()->RespAddr(); + const IPAddr orig_addr = Conn()->OrigAddr(); uint32 tcp_hdr_len = data - (const u_char*) tp; @@ -1206,7 +1203,7 @@ RecordVal* TCP_Analyzer::BuildOSVal(int is_orig, const IP_Hdr* ip, if ( ip->HdrLen() > 20 ) quirks |= QUIRK_IPOPT; - if ( ip->IP_ID() == 0 ) + if ( ip->ID() == 0 ) quirks |= QUIRK_ZEROID; if ( tcp->th_seq == 0 ) @@ -1333,7 +1330,7 @@ RecordVal* TCP_Analyzer::BuildOSVal(int is_orig, const IP_Hdr* ip, tstamp, quirks, uint8(tcp->th_flags & (TH_ECE|TH_CWR))); - if ( sessions->CompareWithPreviousOSMatch(ip->SrcAddr4(), id) ) + if ( sessions->CompareWithPreviousOSMatch(ip->SrcAddr(), id) ) { RecordVal* os = new RecordVal(OS_version); @@ -1945,11 +1942,11 @@ int TCPStats_Endpoint::DataSent(double /* t */, int seq, int len, int caplen, { if ( ++num_pkts == 1 ) { // First packet. - last_id = ntohs(ip->ID4()); + last_id = ip->ID(); return 0; } - int id = ntohs(ip->ID4()); + int id = ip->ID(); if ( id == last_id ) { diff --git a/src/TCP.h b/src/TCP.h index 1db8c1ed68..c84202fcf6 100644 --- a/src/TCP.h +++ b/src/TCP.h @@ -1,5 +1,3 @@ -// $Id: TCP.h 6782 2009-06-28 02:19:03Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef TCP_H @@ -8,6 +6,7 @@ #include "Analyzer.h" #include "TCP.h" #include "PacketDumper.h" +#include "IPAddr.h" // We define two classes here: // - TCP_Analyzer is the analyzer for the TCP protocol itself. @@ -130,7 +129,7 @@ protected: uint32 tcp_hdr_len, int& seq_len, TCP_Endpoint* endpoint, TCP_Endpoint* peer, uint32 base_seq, uint32 ack_seq, - const uint32* orig_addr, + const IPAddr& orig_addr, int is_orig, TCP_Flags flags); void ProcessFIN(double t, TCP_Endpoint* endpoint, int& seq_len, @@ -146,7 +145,7 @@ protected: uint32 tcp_hdr_len, int len, int& seq_len, TCP_Endpoint* endpoint, TCP_Endpoint* peer, uint32 base_seq, uint32 ack_seq, - const uint32* orig_addr, + const IPAddr& orig_addr, int is_orig, TCP_Flags flags); void TransitionFromInactive(double t, TCP_Endpoint* endpoint, diff --git a/src/TCP_Endpoint.cc b/src/TCP_Endpoint.cc index 6d74a1d818..69c08870d9 100644 --- a/src/TCP_Endpoint.cc +++ b/src/TCP_Endpoint.cc @@ -1,5 +1,3 @@ -// $Id: TCP_Endpoint.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "Net.h" @@ -34,13 +32,8 @@ TCP_Endpoint::TCP_Endpoint(TCP_Analyzer* arg_analyzer, int arg_is_orig) dst_addr = is_orig ? tcp_analyzer->Conn()->OrigAddr() : tcp_analyzer->Conn()->RespAddr(); -#ifdef BROv6 - checksum_base = ones_complement_checksum((void*) src_addr, 16, 0); - checksum_base = ones_complement_checksum((void*) dst_addr, 16, checksum_base); -#else - checksum_base = ones_complement_checksum((void*) src_addr, 4, 0); - checksum_base = ones_complement_checksum((void*) dst_addr, 4, checksum_base); -#endif + checksum_base = ones_complement_checksum(src_addr, 0); + checksum_base = ones_complement_checksum(dst_addr, checksum_base); // Note, for IPv6, strictly speaking this field is 32 bits // rather than 16 bits. But because the upper bits are all zero, // we get the same checksum either way. The same applies to diff --git a/src/TCP_Endpoint.h b/src/TCP_Endpoint.h index baae2037c4..52a757b256 100644 --- a/src/TCP_Endpoint.h +++ b/src/TCP_Endpoint.h @@ -1,10 +1,10 @@ -// $Id: TCP_Endpoint.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef tcpendpoint_h #define tcpendpoint_h +#include "IPAddr.h" + typedef enum { TCP_ENDPOINT_INACTIVE, // no SYN (or other packets) seen for this side TCP_ENDPOINT_SYN_SENT, // SYN seen, but no ack @@ -130,8 +130,8 @@ public: uint32 checksum_base; double start_time, last_time; - const uint32* src_addr; // the other endpoint - const uint32* dst_addr; // this endpoint + IPAddr src_addr; // the other endpoint + IPAddr dst_addr; // this endpoint uint32 window; // current congestion window (*scaled*, not pre-scaling) int window_scale; // from the TCP option uint32 window_ack_seq; // at which ack_seq number did we record 'window' diff --git a/src/TCP_Reassembler.cc b/src/TCP_Reassembler.cc index bbde905320..fb67dba7ee 100644 --- a/src/TCP_Reassembler.cc +++ b/src/TCP_Reassembler.cc @@ -1,5 +1,3 @@ -// $Id: TCP_Reassembler.cc,v 1.1.2.8 2006/05/31 01:52:02 sommer Exp $ - #include #include "Analyzer.h" @@ -31,7 +29,7 @@ TCP_Reassembler::TCP_Reassembler(Analyzer* arg_dst_analyzer, TCP_Analyzer* arg_tcp_analyzer, TCP_Reassembler::Type arg_type, bool arg_is_orig, TCP_Endpoint* arg_endp) -: Reassembler(1, arg_endp->dst_addr, REASSEM_TCP) + : Reassembler(1, REASSEM_TCP) { dst_analyzer = arg_dst_analyzer; tcp_analyzer = arg_tcp_analyzer; diff --git a/src/TCP_Reassembler.h b/src/TCP_Reassembler.h index 772c5f6f9c..cb1750e2a2 100644 --- a/src/TCP_Reassembler.h +++ b/src/TCP_Reassembler.h @@ -1,5 +1,3 @@ -// $Id: TCP_Reassembler.h,v 1.1.2.8 2006/05/31 01:52:02 sommer Exp $ - #ifndef TCP_REASSEMBLER_H #define TCP_REASSEMBLER_H diff --git a/src/Telnet.cc b/src/Telnet.cc index 91151fe735..62c7d7b500 100644 --- a/src/Telnet.cc +++ b/src/Telnet.cc @@ -1,5 +1,3 @@ -// $Id: Telnet.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/Telnet.h b/src/Telnet.h index 89150bcbc7..5675775789 100644 --- a/src/Telnet.h +++ b/src/Telnet.h @@ -1,5 +1,3 @@ -// $Id: Telnet.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef telnet_h diff --git a/src/Timer.cc b/src/Timer.cc index c7feb0bbd8..2e2fb09c6b 100644 --- a/src/Timer.cc +++ b/src/Timer.cc @@ -1,5 +1,3 @@ -// $Id: Timer.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" diff --git a/src/Timer.h b/src/Timer.h index c98aeefc22..bb6b8d56ae 100644 --- a/src/Timer.h +++ b/src/Timer.h @@ -1,5 +1,3 @@ -// $Id: Timer.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef timer_h diff --git a/src/Traverse.cc b/src/Traverse.cc index 733ceb450c..78eed27800 100644 --- a/src/Traverse.cc +++ b/src/Traverse.cc @@ -1,5 +1,3 @@ -// $Id: Traverse.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "Scope.h" diff --git a/src/Traverse.h b/src/Traverse.h index ea300fad18..3791a9bbdc 100644 --- a/src/Traverse.h +++ b/src/Traverse.h @@ -1,5 +1,3 @@ -// $Id: Traverse.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef traverse_h diff --git a/src/TraverseTypes.h b/src/TraverseTypes.h index 0cba17a5a9..b0528f34be 100644 --- a/src/TraverseTypes.h +++ b/src/TraverseTypes.h @@ -1,5 +1,3 @@ -// $Id: TraverseTypes.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef statictypes_h diff --git a/src/Trigger.cc b/src/Trigger.cc index 45d1959ee7..164f11b885 100644 --- a/src/Trigger.cc +++ b/src/Trigger.cc @@ -1,5 +1,3 @@ -// $Id: Trigger.cc 2359 2005-12-21 23:55:32Z vern $ - #include #include "Trigger.h" @@ -112,6 +110,8 @@ Trigger::Trigger(Expr* arg_cond, Stmt* arg_body, Stmt* arg_timeout_stmts, is_return = arg_is_return; location = arg_location; + ++total_triggers; + DBG_LOG(DBG_NOTIFIERS, "%s: instantiating", Name()); if ( is_return ) @@ -167,6 +167,7 @@ void Trigger::Init() } Trigger::TriggerList* Trigger::pending = 0; +unsigned long Trigger::total_triggers = 0; bool Trigger::Eval() { @@ -409,9 +410,15 @@ Val* Trigger::Lookup(const CallExpr* expr) return (i != cache.end()) ? i->second : 0; } -const char* Trigger::Name() +const char* Trigger::Name() const { assert(location); return fmt("%s:%d-%d", location->filename, location->first_line, location->last_line); } + +void Trigger::GetStats(Stats* stats) + { + stats->total = total_triggers; + stats->pending = pending ? pending->size() : 0; + } diff --git a/src/Trigger.h b/src/Trigger.h index 7f9931b033..8e04fb9189 100644 --- a/src/Trigger.h +++ b/src/Trigger.h @@ -1,5 +1,3 @@ -// $Id: Trigger.h 2359 2005-12-21 23:55:32Z vern $ - #ifndef TRIGGER_H #define TRIGGER_H @@ -62,13 +60,20 @@ public: virtual void Access(Val* val, const StateAccess& sa) { QueueTrigger(this); } - virtual const char* Name(); + virtual const char* Name() const; static void QueueTrigger(Trigger* trigger); // Evaluates all queued Triggers. static void EvaluatePending(); + struct Stats { + unsigned long total; + unsigned long pending; + }; + + static void GetStats(Stats* stats); + private: friend class TriggerTraversalCallback; friend class TriggerTimer; @@ -101,6 +106,8 @@ private: typedef list TriggerList; static TriggerList* pending; + + static unsigned long total_triggers; }; #endif diff --git a/src/TunnelHandler.cc b/src/TunnelHandler.cc index a7fbd4ce29..9debf79d9c 100644 --- a/src/TunnelHandler.cc +++ b/src/TunnelHandler.cc @@ -22,15 +22,13 @@ TunnelHandler::TunnelHandler(NetSessions *arg_s) TableVal *udp_tunnel_ports = BifConst::Tunnel::udp_tunnel_ports->AsTableVal(); // Find UDP ports we want to analyze. Store them in an array for faster // lookup. - for (int i=0; i< 65536; i++) + for ( int i = 0; i< 65536; i++ ) { - if (pv) + if ( pv ) Unref(pv); pv = new PortVal(i, TRANSPORT_UDP); - if (udp_tunnel_ports->Lookup(pv, false)) - { + if ( udp_tunnel_ports->Lookup(pv, false) ) udp_ports[i] = 1; - } else udp_ports[i] = 0; } @@ -42,35 +40,33 @@ TunnelInfo* TunnelHandler::DecapsulateTunnel(const IP_Hdr *ip_hdr, int len, int { TunnelInfo *tunnel_info = 0; - switch (ip_hdr->NextProto()) { -#ifdef BROv6 + switch ( ip_hdr->NextProto() ) { case IPPROTO_IPV6: /* 6in4 and 6to4 */ if ( BifConst::Tunnel::decapsulate_ip ) { - if (len < (int)sizeof(struct ip6_hdr) || caplen < (int)sizeof(struct ip6_hdr)) + if ( len < (int)sizeof(struct ip6_hdr) || + caplen < (int)sizeof(struct ip6_hdr) ) { s->Weird("truncated_header", hdr, pkt); return 0; } // TODO: check if IP6 header makes sense tunnel_info = new TunnelInfo(); - tunnel_info->child = new IP_Hdr((const struct ip6_hdr*)ip_hdr->Payload()); + tunnel_info->child = new IP_Hdr((const struct ip6_hdr*)ip_hdr->Payload(), false, caplen); tunnel_info->parent.tunneltype = BifEnum::Tunnel::IP6_IN_IP; tunnel_info->hdr_len = tunnel_info->child->HdrLen(); tunnel_info->SetParentIPs(ip_hdr); return tunnel_info; } break; -#endif // TODO: IP in IP. Find test traces first. IP proto 0 and/or 4 case IPPROTO_UDP: if ( BifConst::Tunnel::decapsulate_udp ) { - if (len < (int)sizeof(struct udphdr) || caplen < (int)sizeof(struct udphdr)) - { + if ( len < (int)sizeof(struct udphdr) || + caplen < (int)sizeof(struct udphdr) ) // No weird here. Main packet processing will raise it. return 0; - } return HandleUDP(ip_hdr, len, caplen); } @@ -101,13 +97,13 @@ TunnelInfo* TunnelHandler::HandleUDP(const IP_Hdr *ip_hdr, int len, int caplen) udp_ports[ntohs(uh->uh_dport)] ) { cand_ip_hdr = LookForIPHdr(data, datalen); - if (cand_ip_hdr) + if ( cand_ip_hdr ) { // Found and IP hdr directly in the UDP payload tunneltype = (cand_ip_hdr->IP4_Hdr()) ? BifEnum::Tunnel::IP4_IN_UDP : BifEnum::Tunnel::IP6_IN_UDP; } - else if (datalen >= 8) + else if ( datalen >= 8 ) { // Look for AYIAY tunnels u_char id_byte = data[0]; @@ -124,17 +120,17 @@ TunnelInfo* TunnelHandler::HandleUDP(const IP_Hdr *ip_hdr, int len, int caplen) datalen -= 8 + id_len + sig_len; data += 8 + id_len + sig_len; - if (datalen <= 0) + if ( datalen <= 0 ) return 0; cand_ip_hdr = LookForIPHdr(data, datalen); - if (cand_ip_hdr) + if ( cand_ip_hdr ) { hdr_len += 8 + id_len + sig_len; tunneltype = (cand_ip_hdr->IP4_Hdr()) ? BifEnum::Tunnel::IP4_IN_AYIAY : BifEnum::Tunnel::IP6_IN_AYIAY; } } - if (cand_ip_hdr) + if ( cand_ip_hdr ) { TunnelInfo *tunnel_info = new TunnelInfo(); tunnel_info->child = cand_ip_hdr; @@ -155,20 +151,18 @@ IP_Hdr* TunnelHandler::LookForIPHdr(const u_char *data, int datalen) return 0; const struct ip *ip4 = (const struct ip*)(data); - if (ip4->ip_v == 4) - cand_ip_hdr = new IP_Hdr((const struct ip*)ip4); -#ifdef BROv6 - else if (ip4->ip_v == 6 && (datalen > (int)sizeof(struct ip6_hdr))) - cand_ip_hdr = new IP_Hdr((const struct ip6_hdr*)data); -#endif + if ( ip4->ip_v == 4 ) + cand_ip_hdr = new IP_Hdr((const struct ip*)ip4, false); + else if ( ip4->ip_v == 6 && (datalen > (int)sizeof(struct ip6_hdr)) ) + cand_ip_hdr = new IP_Hdr((const struct ip6_hdr*)data, false, datalen); - if (cand_ip_hdr) + if ( cand_ip_hdr ) { - switch (cand_ip_hdr->NextProto()) { + switch ( cand_ip_hdr->NextProto() ) { case IPPROTO_UDP: case IPPROTO_TCP: case IPPROTO_ICMP: - if ((int)cand_ip_hdr->TotalLen() != datalen) + if ( (int)cand_ip_hdr->TotalLen() != datalen ) { delete cand_ip_hdr; cand_ip_hdr = 0; diff --git a/src/TunnelHandler.h b/src/TunnelHandler.h index b5c69b7eff..9f3f3614e7 100644 --- a/src/TunnelHandler.h +++ b/src/TunnelHandler.h @@ -6,6 +6,7 @@ #include #include "net_util.h" #include "IP.h" +#include "IPAddr.h" #include "Conn.h" #include "Sessions.h" #include "Val.h" @@ -16,15 +17,13 @@ public: { tunneltype = BifEnum::Tunnel::NONE; src_port = dst_port = 0; - for (int i=0; itunneltype; - copy_addr(other->src_addr, src_addr); - copy_addr(other->dst_addr, dst_addr); + src_addr = other->src_addr; + dst_addr = other->dst_addr; src_port = other->src_port; dst_port = other->dst_port; } @@ -33,7 +32,7 @@ public: { RecordVal *rv = new RecordVal(BifType::Record::Tunnel::Parent); TransportProto tproto; - switch(tunneltype) { + switch ( tunneltype ) { case BifEnum::Tunnel::IP6_IN_IP: case BifEnum::Tunnel::IP4_IN_IP: tproto = TRANSPORT_UNKNOWN; @@ -52,8 +51,8 @@ public: return rv; } - uint32 src_addr[NUM_ADDR_WORDS]; - uint32 dst_addr[NUM_ADDR_WORDS]; + IPAddr src_addr; + IPAddr dst_addr; uint16 src_port; uint16 dst_port; BifEnum::Tunnel::Tunneltype tunneltype; @@ -73,8 +72,8 @@ public: void SetParentIPs(const IP_Hdr *ip_hdr) { - copy_addr(ip_hdr->SrcAddr(), parent.src_addr); - copy_addr(ip_hdr->DstAddr(), parent.dst_addr); + parent.src_addr = ip_hdr->SrcAddr(); + parent.dst_addr = ip_hdr->DstAddr(); } void SetParentPorts(const struct udphdr *uh) { diff --git a/src/Type.cc b/src/Type.cc index c2ab7e85df..82221303af 100644 --- a/src/Type.cc +++ b/src/Type.cc @@ -1,5 +1,3 @@ -// $Id: Type.cc 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -878,74 +876,12 @@ void CommentedTypeDecl::DescribeReST(ODesc* d) const } } -RecordField::RecordField(int arg_base, int arg_offset, int arg_total_offset) - { - base = arg_base; - offset = arg_offset; - total_offset = arg_total_offset; - } - RecordType::RecordType(type_decl_list* arg_types) : BroType(TYPE_RECORD) { types = arg_types; - base = 0; - fields = 0; num_fields = types ? types->length() : 0; } -RecordType::RecordType(TypeList* arg_base, type_decl_list* refinements) - : BroType(TYPE_RECORD) - { - if ( refinements ) - arg_base->Append(new RecordType(refinements)); - - Init(arg_base); - } - -void RecordType::Init(TypeList* arg_base) - { - assert(false); // Is this ever used? - - base = arg_base; - - if ( ! base ) - Internal("empty RecordType"); - - fields = new PDict(RecordField)(ORDERED); - types = 0; - - type_list* t = base->Types(); - - loop_over_list(*t, i) - { - BroType* ti = (*t)[i]; - - if ( ti->Tag() != TYPE_RECORD ) - (*t)[i]->Error("non-record in base type list"); - - RecordType* rti = ti->AsRecordType(); - int n = rti->NumFields(); - - for ( int j = 0; j < n; ++j ) - { - const TypeDecl* tdij = rti->FieldDecl(j); - - if ( fields->Lookup(tdij->id) ) - { - reporter->Error("duplicate field", tdij->id); - continue; - } - - RecordField* rf = new RecordField(i, j, fields->Length()); - - if ( fields->Insert(tdij->id, rf) ) - Internal("duplicate field when constructing record"); - } - } - - num_fields = fields->Length(); - } - RecordType::~RecordType() { if ( types ) @@ -955,9 +891,6 @@ RecordType::~RecordType() delete types; } - - delete fields; - Unref(base); } int RecordType::HasField(const char* field) const @@ -973,17 +906,7 @@ BroType* RecordType::FieldType(const char* field) const BroType* RecordType::FieldType(int field) const { - if ( types ) - return (*types)[field]->type; - else - { - RecordField* rf = fields->NthEntry(field); - if ( ! rf ) - Internal("missing field in RecordType::FieldType"); - BroType* bt = (*base->Types())[rf->base]; - RecordType* rbt = bt->AsRecordType(); - return rbt->FieldType(rf->offset); - } + return (*types)[field]->type; } Val* RecordType::FieldDefault(int field) const @@ -1000,26 +923,14 @@ Val* RecordType::FieldDefault(int field) const int RecordType::FieldOffset(const char* field) const { - if ( types ) + loop_over_list(*types, i) { - loop_over_list(*types, i) - { - TypeDecl* td = (*types)[i]; - if ( streq(td->id, field) ) - return i; - } - - return -1; + TypeDecl* td = (*types)[i]; + if ( streq(td->id, field) ) + return i; } - else - { - RecordField* rf = fields->Lookup(field); - if ( ! rf ) - return -1; - else - return rf->total_offset; - } + return -1; } const char* RecordType::FieldName(int field) const @@ -1029,33 +940,12 @@ const char* RecordType::FieldName(int field) const const TypeDecl* RecordType::FieldDecl(int field) const { - if ( types ) - return (*types)[field]; - else - { - RecordField* rf = fields->NthEntry(field); - if ( ! rf ) - reporter->InternalError("missing field in RecordType::FieldDecl"); - - BroType* bt = (*base->Types())[rf->base]; - RecordType* rbt = bt->AsRecordType(); - return rbt->FieldDecl(rf->offset); - } + return (*types)[field]; } TypeDecl* RecordType::FieldDecl(int field) { - if ( types ) - return (*types)[field]; - else - { - RecordField* rf = fields->NthEntry(field); - if ( ! rf ) - Internal("missing field in RecordType::FieldDecl"); - BroType* bt = (*base->Types())[rf->base]; - RecordType* rbt = bt->AsRecordType(); - return rbt->FieldDecl(rf->offset); - } + return (*types)[field]; } void RecordType::Describe(ODesc* d) const @@ -1153,11 +1043,6 @@ void RecordType::DescribeFields(ODesc* d) const d->SP(); } } - else - { - d->AddCount(1); - base->Describe(d); - } } } @@ -1210,9 +1095,6 @@ bool RecordType::DoSerialize(SerialInfo* info) const else if ( ! SERIALIZE(false) ) return false; - SERIALIZE_OPTIONAL(base); - - // We don't serialize the fields as we can reconstruct them. return true; } @@ -1247,13 +1129,6 @@ bool RecordType::DoUnserialize(UnserialInfo* info) else types = 0; - BroType* type; - UNSERIALIZE_OPTIONAL(type, BroType::Unserialize(info, TYPE_LIST)); - base = (TypeList*) type; - - if ( base ) - Init(base); - return true; } @@ -1596,21 +1471,6 @@ bool VectorType::DoUnserialize(UnserialInfo* info) return yield_type != 0; } -BroType* refine_type(TypeList* base, type_decl_list* refinements) - { - type_list* t = base->Types(); - - if ( t->length() == 1 && ! refinements ) - { // Just a direct reference to a single type. - BroType* rt = (*t)[0]->Ref(); - Unref(base); - return rt; - } - - return new RecordType(base, refinements); - } - - BroType* base_type(TypeTag tag) { static BroType* base_types[NUM_TYPES]; @@ -1998,13 +1858,8 @@ BroType* merge_types(const BroType* t1, const BroType* t2) if ( t1->IsSet() ) return new SetType(tl3, 0); - else if ( tg1 == TYPE_TABLE ) - return new TableType(tl3, y3); else - { - reporter->InternalError("bad tag in merge_types"); - return 0; - } + return new TableType(tl3, y3); } case TYPE_FUNC: diff --git a/src/Type.h b/src/Type.h index 1d7637828d..e935ba2267 100644 --- a/src/Type.h +++ b/src/Type.h @@ -1,5 +1,3 @@ -// $Id: Type.h 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef type_h @@ -428,20 +426,9 @@ public: std::list* comments; }; -class RecordField { -public: - RecordField(int arg_base, int arg_offset, int arg_total_offset); - - int base; // which base element it belongs to - int offset; // where it is in that base - int total_offset; // where it is in the aggregate record -}; -declare(PDict,RecordField); - class RecordType : public BroType { public: RecordType(type_decl_list* types); - RecordType(TypeList* base, type_decl_list* refinements); ~RecordType(); @@ -475,15 +462,11 @@ public: void DescribeFieldsReST(ODesc* d, bool func_args) const; protected: - RecordType() { fields = 0; base = 0; types = 0; } - - void Init(TypeList* arg_base); + RecordType() { types = 0; } DECLARE_SERIAL(RecordType) int num_fields; - PDict(RecordField)* fields; - TypeList* base; type_decl_list* types; }; @@ -589,10 +572,6 @@ protected: BroType* yield_type; }; - -// Returns the given type refinement, or error_type() if it's illegal. -extern BroType* refine_type(TypeList* base, type_decl_list* refinements); - // Returns the BRO basic (non-parameterized) type with the given type. extern BroType* base_type(TypeTag tag); diff --git a/src/UDP.cc b/src/UDP.cc index 5331560eff..d85cb39edd 100644 --- a/src/UDP.cc +++ b/src/UDP.cc @@ -1,5 +1,3 @@ -// $Id: UDP.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include @@ -59,15 +57,15 @@ void UDP_Analyzer::DeliverPacket(int len, const u_char* data, bool is_orig, { bool bad = false; - if ( ip->IP4_Hdr() && chksum && - udp_checksum(ip->IP4_Hdr(), up, len) != 0xffff ) - bad = true; + if ( ip->IP4_Hdr() ) + { + if ( chksum && ! ValidateChecksum(ip, up, len) ) + bad = true; + } -#ifdef BROv6 - if ( ip->IP6_Hdr() && /* checksum is not optional for IPv6 */ - udp6_checksum(ip->IP6_Hdr(), up, len) != 0xffff ) + /* checksum is not optional for IPv6 */ + else if ( ! ValidateChecksum(ip, up, len) ) bad = true; -#endif if ( bad ) { @@ -208,4 +206,24 @@ unsigned int UDP_Analyzer::MemoryAllocation() const return Analyzer::MemoryAllocation() + padded_sizeof(*this) - 24; } +bool UDP_Analyzer::ValidateChecksum(const IP_Hdr* ip, const udphdr* up, int len) + { + uint32 sum; + if ( len % 2 == 1 ) + // Add in pad byte. + sum = htons(((const u_char*) up)[len - 1] << 8); + else + sum = 0; + + sum = ones_complement_checksum(ip->SrcAddr(), sum); + sum = ones_complement_checksum(ip->DstAddr(), sum); + // Note, for IPv6, strictly speaking the protocol and length fields are + // 32 bits rather than 16 bits. But because the upper bits are all zero, + // we get the same checksum either way. + sum += htons(IPPROTO_UDP); + sum += htons((unsigned short) len); + sum = ones_complement_checksum((void*) up, len, sum); + + return sum == 0xffff; + } diff --git a/src/UDP.h b/src/UDP.h index b04c5e3ef0..b93d4da97f 100644 --- a/src/UDP.h +++ b/src/UDP.h @@ -1,11 +1,10 @@ -// $Id: UDP.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef udp_h #define udp_h #include "Analyzer.h" +#include typedef enum { UDP_INACTIVE, // no packet seen @@ -33,6 +32,10 @@ protected: virtual bool IsReuse(double t, const u_char* pkt); virtual unsigned int MemoryAllocation() const; + // Returns true if the checksum is valid, false if not + static bool ValidateChecksum(const IP_Hdr* ip, const struct udphdr* up, + int len); + bro_int_t request_len, reply_len; private: diff --git a/src/Val.cc b/src/Val.cc index 2f4f6d2850..f3977789f2 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -1,5 +1,3 @@ -// $Id: Val.cc 6945 2009-11-27 19:25:10Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -27,7 +25,7 @@ #include "PrefixTable.h" #include "Conn.h" #include "Reporter.h" - +#include "IPAddr.h" Val::Val(Func* f) { @@ -207,29 +205,10 @@ bool Val::DoSerialize(SerialInfo* info) const val.string_val->Len()); case TYPE_INTERNAL_ADDR: - return SERIALIZE(NUM_ADDR_WORDS) -#ifdef BROv6 - && SERIALIZE(uint32(ntohl(val.addr_val[0]))) - && SERIALIZE(uint32(ntohl(val.addr_val[1]))) - && SERIALIZE(uint32(ntohl(val.addr_val[2]))) - && SERIALIZE(uint32(ntohl(val.addr_val[3]))); -#else - && SERIALIZE(uint32(ntohl(val.addr_val))); -#endif + return SERIALIZE(*val.addr_val); case TYPE_INTERNAL_SUBNET: - return info->s->WriteOpenTag("subnet") - && SERIALIZE(NUM_ADDR_WORDS) -#ifdef BROv6 - && SERIALIZE(uint32(ntohl(val.subnet_val.net[0]))) - && SERIALIZE(uint32(ntohl(val.subnet_val.net[1]))) - && SERIALIZE(uint32(ntohl(val.subnet_val.net[2]))) - && SERIALIZE(uint32(ntohl(val.subnet_val.net[3]))) -#else - && SERIALIZE(uint32(ntohl(val.subnet_val.net))) -#endif - && SERIALIZE(val.subnet_val.width) - && info->s->WriteCloseTag("subnet"); + return SERIALIZE(*val.subnet_val); case TYPE_INTERNAL_OTHER: // Derived classes are responsible for this. @@ -296,94 +275,15 @@ bool Val::DoUnserialize(UnserialInfo* info) case TYPE_INTERNAL_ADDR: { - int num_words; - if ( ! UNSERIALIZE(&num_words) ) - return false; - - if ( num_words != 1 && num_words != 4 ) - { - info->s->Error("bad address type"); - return false; - } - - uint32 a[4]; // big enough to hold either - - for ( int i = 0; i < num_words; ++i ) - { - if ( ! UNSERIALIZE(&a[i]) ) - return false; - - a[i] = htonl(a[i]); - } - -#ifndef BROv6 - if ( num_words == 4 ) - { - if ( a[0] || a[1] || a[2] ) - info->s->Warning("received IPv6 address, ignoring"); - ((AddrVal*) this)->Init(a[3]); - } - else - ((AddrVal*) this)->Init(a[0]); -#else - if ( num_words == 1 ) - ((AddrVal*) this)->Init(a[0]); - else - ((AddrVal*) this)->Init(a); -#endif + val.addr_val = new IPAddr(); + return UNSERIALIZE(val.addr_val); } - return true; case TYPE_INTERNAL_SUBNET: { - int num_words; - if ( ! UNSERIALIZE(&num_words) ) - return false; - - if ( num_words != 1 && num_words != 4 ) - { - info->s->Error("bad subnet type"); - return false; - } - - uint32 a[4]; // big enough to hold either - - for ( int i = 0; i < num_words; ++i ) - { - if ( ! UNSERIALIZE(&a[i]) ) - return false; - - a[i] = htonl(a[i]); - } - - int width; - if ( ! UNSERIALIZE(&width) ) - return false; - -#ifdef BROv6 - if ( num_words == 1 ) - { - a[3] = a[0]; - a[0] = a[1] = a[2] = 0; - } - - ((SubNetVal*) this)->Init(a, width); - -#else - if ( num_words == 4 ) - { - if ( a[0] || a[1] || a[2] ) - info->s->Warning("received IPv6 subnet, ignoring"); - a[0] = a[3]; - - if ( width > 32 ) - width -= 96; - } - - ((SubNetVal*) this)->Init(a[0], width); -#endif + val.subnet_val = new IPPrefix(); + return UNSERIALIZE(val.subnet_val); } - return true; case TYPE_INTERNAL_OTHER: // Derived classes are responsible for this. @@ -592,12 +492,10 @@ void Val::ValDescribe(ODesc* d) const case TYPE_INTERNAL_UNSIGNED: d->Add(val.uint_val); break; case TYPE_INTERNAL_DOUBLE: d->Add(val.double_val); break; case TYPE_INTERNAL_STRING: d->AddBytes(val.string_val); break; - case TYPE_INTERNAL_ADDR: d->Add(dotted_addr(val.addr_val)); break; + case TYPE_INTERNAL_ADDR: d->Add(val.addr_val->AsString().c_str()); break; case TYPE_INTERNAL_SUBNET: - d->Add(dotted_addr(val.subnet_val.net)); - d->Add("/"); - d->Add(val.subnet_val.width); + d->Add(val.subnet_val->AsString().c_str()); break; case TYPE_INTERNAL_ERROR: d->AddCS("error"); break; @@ -638,14 +536,16 @@ MutableVal::~MutableVal() { for ( list::iterator i = aliases.begin(); i != aliases.end(); ++i ) { - global_scope()->Remove((*i)->Name()); + if ( global_scope() ) + global_scope()->Remove((*i)->Name()); (*i)->ClearVal(); // just to make sure. Unref((*i)); } if ( id ) { - global_scope()->Remove(id->Name()); + if ( global_scope() ) + global_scope()->Remove(id->Name()); id->ClearVal(); // just to make sure. Unref(id); } @@ -706,7 +606,8 @@ ID* MutableVal::Bind() const ip = htonl(0x7f000001); // 127.0.0.1 safe_snprintf(name, MAX_NAME_SIZE, "#%s#%d#", - dotted_addr(ip), getpid()); + IPAddr(IPv4, &ip, IPAddr::Network)->AsString().c_str(), + getpid()); #else safe_snprintf(name, MAX_NAME_SIZE, "#%s#%d#", host, getpid()); #endif @@ -957,92 +858,41 @@ bool PortVal::DoUnserialize(UnserialInfo* info) AddrVal::AddrVal(const char* text) : Val(TYPE_ADDR) { - const char* colon = strchr(text, ':'); - - if ( colon ) - { -#ifdef BROv6 - Init(dotted_to_addr6(text)); -#else - reporter->Error("bro wasn't compiled with IPv6 support"); - Init(uint32(0)); -#endif - } - - else - Init(dotted_to_addr(text)); + val.addr_val = new IPAddr(text); } AddrVal::AddrVal(uint32 addr) : Val(TYPE_ADDR) { // ### perhaps do gethostbyaddr here? - Init(addr); + val.addr_val = new IPAddr(IPv4, &addr, IPAddr::Network); } -AddrVal::AddrVal(const uint32* addr) : Val(TYPE_ADDR) +AddrVal::AddrVal(const uint32 addr[4]) : Val(TYPE_ADDR) { - Init(addr); + val.addr_val = new IPAddr(IPv6, addr, IPAddr::Network); + } + +AddrVal::AddrVal(const IPAddr& addr) : Val(TYPE_ADDR) + { + val.addr_val = new IPAddr(addr); } AddrVal::~AddrVal() { -#ifdef BROv6 - delete [] val.addr_val; -#endif - } - -Val* AddrVal::SizeVal() const - { - uint32 addr; - -#ifdef BROv6 - if ( ! is_v4_addr(val.addr_val) ) - { - Error("|addr| for IPv6 addresses not supported"); - return new Val(0, TYPE_COUNT); - } - - addr = to_v4_addr(val.addr_val); -#else - addr = val.addr_val; -#endif - - addr = ntohl(addr); - - return new Val(addr, TYPE_COUNT); - } - -void AddrVal::Init(uint32 addr) - { -#ifdef BROv6 - val.addr_val = new uint32[4]; - val.addr_val[0] = val.addr_val[1] = val.addr_val[2] = 0; - val.addr_val[3] = addr; -#else - val.addr_val = addr; -#endif - } - -void AddrVal::Init(const uint32* addr) - { -#ifdef BROv6 - val.addr_val = new uint32[4]; - val.addr_val[0] = addr[0]; - val.addr_val[1] = addr[1]; - val.addr_val[2] = addr[2]; - val.addr_val[3] = addr[3]; -#else - val.addr_val = addr[0]; -#endif + delete val.addr_val; } unsigned int AddrVal::MemoryAllocation() const { -#ifdef BROv6 - return padded_sizeof(*this) + pad_size(4 * sizeof(uint32)); -#else - return padded_sizeof(*this); -#endif + return padded_sizeof(*this) + val.addr_val->MemoryAllocation(); + } + +Val* AddrVal::SizeVal() const + { + if ( val.addr_val->GetFamily() == IPv4 ) + return new Val(32, TYPE_COUNT); + else + return new Val(128, TYPE_COUNT); } IMPLEMENT_SERIAL(AddrVal, SER_ADDR_VAL); @@ -1059,209 +909,109 @@ bool AddrVal::DoUnserialize(UnserialInfo* info) return true; } -static uint32 parse_dotted(const char* text, int& dots) - { - int addr[4]; - uint32 a = 0; - dots = 0; - - if ( sscanf(text, "%d.%d.%d.%d", addr+0, addr+1, addr+2, addr+3) == 4 ) - { - a = (addr[0] << 24) | (addr[1] << 16) | - (addr[2] << 8) | addr[3]; - dots = 3; - } - - else if ( sscanf(text, "%d.%d.%d", addr+0, addr+1, addr+2) == 3 ) - { - a = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8); - dots = 2; - } - - else if ( sscanf(text, "%d.%d", addr+0, addr+1) == 2 ) - { - a = (addr[0] << 24) | (addr[1] << 16); - dots = 1; - } - - else - reporter->InternalError("scanf failed in parse_dotted()"); - - for ( int i = 0; i <= dots; ++i ) - { - if ( addr[i] < 0 || addr[i] > 255 ) - { - reporter->Error("bad dotted address", text); - break; - } - } - - return a; - } - SubNetVal::SubNetVal(const char* text) : Val(TYPE_SUBNET) { - const char* sep = strchr(text, '/'); - if ( ! sep ) - Internal("separator missing in SubNetVal::SubNetVal"); + string s(text); + size_t slash_loc = s.find('/'); - Init(text, atoi(sep+1)); + if ( slash_loc == string::npos ) + { + reporter->Error("Bad string in SubNetVal ctor: %s", text); + val.subnet_val = new IPPrefix(); + } + else + { + val.subnet_val = new IPPrefix(s.substr(0, slash_loc), + atoi(s.substr(slash_loc + 1).c_str())); + } } SubNetVal::SubNetVal(const char* text, int width) : Val(TYPE_SUBNET) { - Init(text, width); + val.subnet_val = new IPPrefix(text, width); } SubNetVal::SubNetVal(uint32 addr, int width) : Val(TYPE_SUBNET) { - Init(addr, width); + IPAddr a(IPv4, &addr, IPAddr::Network); + val.subnet_val = new IPPrefix(a, width); } -#ifdef BROv6 SubNetVal::SubNetVal(const uint32* addr, int width) : Val(TYPE_SUBNET) { - Init(addr, width); - } -#endif - -void SubNetVal::Init(const char* text, int width) - { -#ifdef BROv6 - if ( width <= 0 || width > 128 ) -#else - if ( width <= 0 || width > 32 ) -#endif - Error("bad subnet width"); - - int dots; - uint32 a = parse_dotted(text, dots); - - Init(uint32(htonl(a)), width); + IPAddr a(IPv6, addr, IPAddr::Network); + val.subnet_val = new IPPrefix(a, width); } - -void SubNetVal::Init(uint32 addr, int width) +SubNetVal::SubNetVal(const IPAddr& addr, int width) : Val(TYPE_SUBNET) { -#ifdef BROv6 - Internal("SubNetVal::Init called on 4-byte address w/ BROv6"); -#else - val.subnet_val.net = mask_addr(addr, uint32(width)); - val.subnet_val.width = width; -#endif + val.subnet_val = new IPPrefix(addr, width); } -void SubNetVal::Init(const uint32* addr, int width) +SubNetVal::~SubNetVal() { -#ifdef BROv6 - const uint32* a = mask_addr(addr, uint32(width)); + delete val.subnet_val; + } - val.subnet_val.net[0] = a[0]; - val.subnet_val.net[1] = a[1]; - val.subnet_val.net[2] = a[2]; - val.subnet_val.net[3] = a[3]; +const IPAddr& SubNetVal::Prefix() const + { + return val.subnet_val->Prefix(); + } - if ( is_v4_addr(addr) && width <= 32 ) - val.subnet_val.width = width + 96; - else - val.subnet_val.width = width; -#else - Internal("SubNetVal::Init called on 16-byte address w/o BROv6"); -#endif +int SubNetVal::Width() const + { + return val.subnet_val->Length(); + } + +unsigned int SubNetVal::MemoryAllocation() const + { + return padded_sizeof(*this) + val.subnet_val->MemoryAllocation(); } Val* SubNetVal::SizeVal() const { - int retained; -#ifdef BROv6 - retained = 128 - Width(); -#else - retained = 32 - Width(); -#endif - + int retained = 128 - val.subnet_val->LengthIPv6(); return new Val(pow(2.0, double(retained)), TYPE_DOUBLE); } void SubNetVal::ValDescribe(ODesc* d) const { - d->Add(dotted_addr(val.subnet_val.net, d->Style() == ALTERNATIVE_STYLE)); - d->Add("/"); -#ifdef BROv6 - if ( is_v4_addr(val.subnet_val.net) ) - d->Add(val.subnet_val.width - 96); - else -#endif - d->Add(val.subnet_val.width); + d->Add(string(*val.subnet_val).c_str()); } -addr_type SubNetVal::Mask() const +IPAddr SubNetVal::Mask() const { - if ( val.subnet_val.width == 0 ) + if ( val.subnet_val->Length() == 0 ) { // We need to special-case a mask width of zero, since // the compiler doesn't guarantee that 1 << 32 yields 0. -#ifdef BROv6 - uint32* m = new uint32[4]; - for ( int i = 0; i < 4; ++i ) + uint32 m[4]; + for ( unsigned int i = 0; i < 4; ++i ) m[i] = 0; - - return m; -#else - return 0; -#endif + IPAddr rval(IPv6, m, IPAddr::Host); + return rval; } -#ifdef BROv6 - uint32* m = new uint32[4]; + uint32 m[4]; uint32* mp = m; uint32 w; - for ( w = val.subnet_val.width; w >= 32; w -= 32 ) - *(mp++) = 0xffffffff; + for ( w = val.subnet_val->Length(); w >= 32; w -= 32 ) + *(mp++) = 0xffffffff; *mp = ~((1 << (32 - w)) - 1); while ( ++mp < m + 4 ) - *mp = 0; + *mp = 0; - return m; - -#else - return ~((1 << (32 - val.subnet_val.width)) - 1); -#endif + IPAddr rval(IPv6, m, IPAddr::Host); + return rval; } -bool SubNetVal::Contains(const uint32 addr) const +bool SubNetVal::Contains(const IPAddr& addr) const { -#ifdef BROv6 - Internal("SubNetVal::Contains called on 4-byte address w/ BROv6"); - return false; -#else - return ntohl(val.subnet_val.net) == (ntohl(addr) & Mask()); -#endif - } - -bool SubNetVal::Contains(const uint32* addr) const - { -#ifdef BROv6 - const uint32* net = val.subnet_val.net; - const uint32* a = addr; - uint32 m; - - for ( m = val.subnet_val.width; m > 32; m -= 32 ) - { - if ( *net != *a ) - return false; - - ++net; - ++a; - } - - uint32 mask = ~((1 << (32 - m)) - 1); - return ntohl(*net) == (ntohl(*a) & mask); -#else - return Contains(addr[3]); -#endif + IPAddr a(addr); + return val.subnet_val->Contains(a); } IMPLEMENT_SERIAL(SubNetVal, SER_SUBNET_VAL); @@ -1463,6 +1213,7 @@ TableVal* ListVal::ConvertToSet() const loop_over_list(vals, i) t->Assign(vals[i], 0); + Unref(s); return t; } @@ -1582,6 +1333,7 @@ TableVal::TableVal(TableType* t, Attributes* a) : MutableVal(t) void TableVal::Init(TableType* t) { + ::Ref(t); table_type = t; expire_expr = 0; expire_time = 0; @@ -1604,6 +1356,7 @@ TableVal::~TableVal() if ( timer ) timer_mgr->Cancel(timer); + Unref(table_type); delete table_hash; delete AsTable(); delete subnets; @@ -2004,7 +1757,16 @@ Val* TableVal::Default(Val* index) else vl->append(index->Ref()); - Val* result = f->Call(vl); + Val* result = 0; + + try + { + result = f->Call(vl); + } + + catch ( InterpreterException& e ) + { /* Already reported. */ } + delete vl; if ( ! result ) @@ -2115,7 +1877,7 @@ Val* TableVal::Delete(const Val* index) Val* va = v ? (v->Value() ? v->Value() : this->Ref()) : 0; if ( subnets && ! subnets->Remove(index) ) - reporter->InternalError( "index not in prefix table" ); + reporter->InternalError("index not in prefix table"); if ( LoggingAccess() ) { @@ -2157,7 +1919,7 @@ Val* TableVal::Delete(const HashKey* k) { Val* index = table_hash->RecoverVals(k); if ( ! subnets->Remove(index) ) - reporter->InternalError( "index not in prefix table" ); + reporter->InternalError("index not in prefix table"); Unref(index); } @@ -2374,10 +2136,13 @@ void TableVal::DoExpire(double t) (v = tbl->NextEntry(k, expire_cookie)); ++i ) { if ( v->ExpireAccessTime() == 0 ) + { // This happens when we insert val while network_time - // hasn't been initialized yet (e.g. in bro_init()). - // We correct the timestamp now. - v->SetExpireAccess(network_time); + // hasn't been initialized yet (e.g. in bro_init()), and + // also when bro_start_network_time hasn't been initialized + // (e.g. before first packet). The expire_access_time is + // correct, so we just need to wait. + } else if ( v->ExpireAccessTime() + expire_time < t ) { @@ -2414,7 +2179,7 @@ void TableVal::DoExpire(double t) { Val* index = RecoverIndex(k); if ( ! subnets->Remove(index) ) - reporter->InternalError( "index not in prefix table" ); + reporter->InternalError("index not in prefix table"); Unref(index); } @@ -2463,10 +2228,20 @@ double TableVal::CallExpireFunc(Val* idx) vl->append(idx); - Val* vs = expire_expr->Eval(0)->AsFunc()->Call(vl); - double secs = vs->AsInterval(); - Unref(vs); - delete vl; + double secs; + + try + { + Val* vs = expire_expr->Eval(0)->AsFunc()->Call(vl); + secs = vs->AsInterval(); + Unref(vs); + delete vl; + } + + catch ( InterpreterException& e ) + { + secs = 0; + } return secs; } @@ -2497,7 +2272,7 @@ bool TableVal::DoSerialize(SerialInfo* info) const IterCookie* c; TableEntryVal* v; // current value bool did_index; // already wrote the val's index - }* state; + }* state = 0; PDict(TableEntryVal)* tbl = const_cast(this)->AsNonConstTable(); @@ -2863,7 +2638,7 @@ Val* RecordVal::LookupWithDefault(int field) const return record_type->FieldDefault(field); } -RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr) const +RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr, bool allow_orphaning) const { if ( ! record_promotion_compatible(t->AsRecordType(), Type()->AsRecordType()) ) return 0; @@ -2883,6 +2658,9 @@ RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr) const if ( t_i < 0 ) { + if ( allow_orphaning ) + continue; + char buf[512]; safe_snprintf(buf, sizeof(buf), "orphan field \"%s\" in initialization", @@ -2916,7 +2694,7 @@ RecordVal* RecordVal::CoerceTo(const RecordType* t, Val* aggr) const return ar; } -RecordVal* RecordVal::CoerceTo(RecordType* t) +RecordVal* RecordVal::CoerceTo(RecordType* t, bool allow_orphaning) { if ( same_type(Type(), t) ) { @@ -2924,7 +2702,7 @@ RecordVal* RecordVal::CoerceTo(RecordType* t) return this; } - return CoerceTo(t, 0); + return CoerceTo(t, 0, allow_orphaning); } void RecordVal::Describe(ODesc* d) const @@ -3104,10 +2882,6 @@ void EnumVal::ValDescribe(ODesc* d) const if ( ! ename ) ename = ""; - const char* module_offset = strstr(ename, "::"); - if ( module_offset ) - ename = module_offset + 2; - d->Add(ename); } @@ -3455,20 +3229,10 @@ int same_atomic_val(const Val* v1, const Val* v2) return v1->InternalDouble() == v2->InternalDouble(); case TYPE_INTERNAL_STRING: return Bstr_eq(v1->AsString(), v2->AsString()); - case TYPE_INTERNAL_ADDR: - { - const addr_type& a1 = v1->AsAddr(); - const addr_type& a2 = v2->AsAddr(); -#ifdef BROv6 - return addr_eq(a1, a2); -#else - return addr_eq(&a1, &a2); -#endif - } - + return v1->AsAddr() == v2->AsAddr(); case TYPE_INTERNAL_SUBNET: - return subnet_eq(v1->AsSubNet(), v2->AsSubNet()); + return v1->AsSubNet() == v2->AsSubNet(); default: reporter->InternalError("same_atomic_val called for non-atomic value"); diff --git a/src/Val.h b/src/Val.h index c9f780a738..ed79f04671 100644 --- a/src/Val.h +++ b/src/Val.h @@ -1,5 +1,3 @@ -// $Id: Val.h 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef val_h @@ -20,6 +18,7 @@ #include "ID.h" #include "Scope.h" #include "StateAccess.h" +#include "IPAddr.h" class Val; class Func; @@ -55,11 +54,11 @@ typedef union { // Used for count, counter, port, subnet. bro_uint_t uint_val; - // Used for addr, net - addr_type addr_val; + // Used for addr + IPAddr* addr_val; // Used for subnet - subnet_type subnet_val; + IPPrefix* subnet_val; // Used for double, time, interval. double double_val; @@ -228,10 +227,10 @@ public: CONST_ACCESSOR(TYPE_PATTERN, RE_Matcher*, re_val, AsPattern) CONST_ACCESSOR(TYPE_VECTOR, vector*, vector_val, AsVector) - const subnet_type* AsSubNet() const + const IPPrefix& AsSubNet() const { CHECK_TAG(type->Tag(), TYPE_SUBNET, "Val::SubNet", type_name) - return &val.subnet_val; + return *val.subnet_val; } BroType* AsType() const @@ -240,12 +239,11 @@ public: return type; } - // ... in network byte order - const addr_type AsAddr() const + const IPAddr& AsAddr() const { if ( type->Tag() != TYPE_ADDR ) BadTag("Val::AsAddr", type_name(type->Tag())); - return val.addr_val; + return *val.addr_val; } #define ACCESSOR(tag, ctype, accessor, name) \ @@ -263,10 +261,17 @@ public: ACCESSOR(TYPE_PATTERN, RE_Matcher*, re_val, AsPattern) ACCESSOR(TYPE_VECTOR, vector*, vector_val, AsVector) - subnet_type* AsSubNet() + const IPPrefix& AsSubNet() { CHECK_TAG(type->Tag(), TYPE_SUBNET, "Val::SubNet", type_name) - return &val.subnet_val; + return *val.subnet_val; + } + + const IPAddr& AsAddr() + { + if ( type->Tag() != TYPE_ADDR ) + BadTag("Val::AsAddr", type_name(type->Tag())); + return *val.addr_val; } // Gives fast access to the bits of something that is one of @@ -284,6 +289,7 @@ public: CONVERTER(TYPE_PATTERN, PatternVal*, AsPatternVal) CONVERTER(TYPE_PORT, PortVal*, AsPortVal) CONVERTER(TYPE_SUBNET, SubNetVal*, AsSubNetVal) + CONVERTER(TYPE_ADDR, AddrVal*, AsAddrVal) CONVERTER(TYPE_TABLE, TableVal*, AsTableVal) CONVERTER(TYPE_RECORD, RecordVal*, AsRecordVal) CONVERTER(TYPE_LIST, ListVal*, AsListVal) @@ -301,6 +307,7 @@ public: CONST_CONVERTER(TYPE_PATTERN, PatternVal*, AsPatternVal) CONST_CONVERTER(TYPE_PORT, PortVal*, AsPortVal) CONST_CONVERTER(TYPE_SUBNET, SubNetVal*, AsSubNetVal) + CONST_CONVERTER(TYPE_ADDR, AddrVal*, AsAddrVal) CONST_CONVERTER(TYPE_TABLE, TableVal*, AsTableVal) CONST_CONVERTER(TYPE_RECORD, RecordVal*, AsRecordVal) CONST_CONVERTER(TYPE_LIST, ListVal*, AsListVal) @@ -502,13 +509,9 @@ protected: #define NUM_PORT_SPACES 4 #define PORT_SPACE_MASK 0x30000 -#define TCP_PORT_MASK 0x10000 -#define UDP_PORT_MASK 0x20000 -#define ICMP_PORT_MASK 0x30000 - -typedef enum { - TRANSPORT_UNKNOWN, TRANSPORT_TCP, TRANSPORT_UDP, TRANSPORT_ICMP, -} TransportProto; +#define TCP_PORT_MASK 0x10000 +#define UDP_PORT_MASK 0x20000 +#define ICMP_PORT_MASK 0x30000 class PortVal : public Val { public: @@ -555,8 +558,9 @@ public: Val* SizeVal() const; // Constructor for address already in network order. - AddrVal(uint32 addr); - AddrVal(const uint32* addr); + AddrVal(uint32 addr); // IPv4. + AddrVal(const uint32 addr[4]); // IPv6. + AddrVal(const IPAddr& addr); unsigned int MemoryAllocation() const; @@ -566,9 +570,6 @@ protected: AddrVal(TypeTag t) : Val(t) { } AddrVal(BroType* t) : Val(t) { } - void Init(uint32 addr); - void Init(const uint32* addr); - DECLARE_SERIAL(AddrVal); }; @@ -576,30 +577,25 @@ class SubNetVal : public Val { public: SubNetVal(const char* text); SubNetVal(const char* text, int width); - SubNetVal(uint32 addr, int width); // for address already massaged - SubNetVal(const uint32* addr, int width); // ditto + SubNetVal(uint32 addr, int width); // IPv4. + SubNetVal(const uint32 addr[4], int width); // IPv6. + SubNetVal(const IPAddr& addr, int width); + ~SubNetVal(); Val* SizeVal() const; - int Width() const { return val.subnet_val.width; } - addr_type Mask() const; // returns host byte order + const IPAddr& Prefix() const; + int Width() const; + IPAddr Mask() const; - bool Contains(const uint32 addr) const; - bool Contains(const uint32* addr) const; + bool Contains(const IPAddr& addr) const; - unsigned int MemoryAllocation() const - { - return Val::MemoryAllocation() + padded_sizeof(*this) - padded_sizeof(Val); - } + unsigned int MemoryAllocation() const; protected: friend class Val; SubNetVal() {} - void Init(const char* text, int width); - void Init(uint32 addr, int width); - void Init(const uint32 *addr, int width); - void ValDescribe(ODesc* d) const; DECLARE_SERIAL(SubNetVal); @@ -871,7 +867,7 @@ protected: DECLARE_SERIAL(TableVal); - const TableType* table_type; + TableType* table_type; CompositeHash* table_hash; Attributes* attrs; double expire_time; @@ -909,8 +905,11 @@ public: // *aggr* is optional; if non-zero, we add to it. See // Expr::InitVal(). We leave it out in the non-const version to make // the choice unambigious. - RecordVal* CoerceTo(const RecordType* other, Val* aggr) const; - RecordVal* CoerceTo(RecordType* other); + // + // The *allow_orphaning* parameter allows for a record to be demoted + // down to a record type that contains less fields. + RecordVal* CoerceTo(const RecordType* other, Val* aggr, bool allow_orphaning = false) const; + RecordVal* CoerceTo(RecordType* other, bool allow_orphaning = false); unsigned int MemoryAllocation() const; void DescribeReST(ODesc* d) const; diff --git a/src/Var.cc b/src/Var.cc index 390b6b3684..d54d94a078 100644 --- a/src/Var.cc +++ b/src/Var.cc @@ -1,5 +1,3 @@ -// $Id: Var.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -204,7 +202,8 @@ Stmt* add_local(ID* id, BroType* t, init_class c, Expr* init, Ref(id); Stmt* stmt = - new ExprStmt(new AssignExpr(new NameExpr(id), init, 0)); + new ExprStmt(new AssignExpr(new NameExpr(id), init, 0, 0, + id->Attrs() ? id->Attrs()->Attrs() : 0 )); stmt->SetLocationInfo(init->GetLocationInfo()); return stmt; diff --git a/src/Var.h b/src/Var.h index 6b4ddaece2..8b9866ed2d 100644 --- a/src/Var.h +++ b/src/Var.h @@ -1,5 +1,3 @@ -// $Id: Var.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef var_h diff --git a/src/X509.cc b/src/X509.cc deleted file mode 100644 index 783bccdad1..0000000000 --- a/src/X509.cc +++ /dev/null @@ -1,265 +0,0 @@ -// $Id: X509.cc 6724 2009-06-07 09:23:03Z vern $ - -#include - -#include "X509.h" -#include "config.h" - -// ### NOTE: while d2i_X509 does not take a const u_char** pointer, -// here we assume d2i_X509 does not write to , so it is safe to -// convert data to a non-const pointer. Could some X509 guru verify -// this? - -X509* d2i_X509_(X509** px, const u_char** in, int len) - { -#ifdef OPENSSL_D2I_X509_USES_CONST_CHAR - return d2i_X509(px, in, len); -#else - return d2i_X509(px, (u_char**)in, len); -#endif - } - -X509_STORE* X509_Cert::ctx = 0; -X509_LOOKUP* X509_Cert::lookup = 0; -X509_STORE_CTX X509_Cert::csc; -bool X509_Cert::bInited = false; - -// TODO: Check if Key < 768 Bits => Weakness! -// FIXME: Merge verify and verifyChain. - -void X509_Cert::sslCertificateEvent(Contents_SSL* e, X509* pCert) - { - EventHandlerPtr event = ssl_certificate; - if ( ! event ) - return; - - char tmp[256]; - RecordVal* pX509Cert = new RecordVal(x509_type); - - X509_NAME_oneline(X509_get_issuer_name(pCert), tmp, sizeof tmp); - pX509Cert->Assign(0, new StringVal(tmp)); - X509_NAME_oneline(X509_get_subject_name(pCert), tmp, sizeof tmp); - pX509Cert->Assign(1, new StringVal(tmp)); - pX509Cert->Assign(2, new AddrVal(e->Conn()->OrigAddr())); - - val_list* vl = new val_list; - vl->append(e->BuildConnVal()); - vl->append(pX509Cert); - vl->append(new Val(e->IsOrig(), TYPE_BOOL)); - - e->Conn()->ConnectionEvent(event, e, vl); - } - -void X509_Cert::sslCertificateError(Contents_SSL* e, int error_numbe) - { - Val* err_str = new StringVal(X509_verify_cert_error_string(csc.error)); - val_list* vl = new val_list; - - vl->append(e->BuildConnVal()); - vl->append(new Val(csc.error, TYPE_INT)); - vl->append(err_str); - - e->Conn()->ConnectionEvent(ssl_X509_error, e, vl); - } - -int X509_Cert::init() - { -#if 0 - OpenSSL_add_all_algorithms(); -#endif - - ctx = X509_STORE_new(); - int flag = 0; - int ret = 0; - - if ( x509_trusted_cert_path && - x509_trusted_cert_path->AsString()->Len() > 0 ) - { // add the path(s) for the local CA's certificates - const BroString* pString = x509_trusted_cert_path->AsString(); - - lookup = X509_STORE_add_lookup(ctx, X509_LOOKUP_hash_dir()); - if ( ! lookup ) - { - reporter->Error("X509_Cert::init(): initing lookup failed\n"); - flag = 1; - } - - int i = X509_LOOKUP_add_dir(lookup, - (const char*) pString->Bytes(), - X509_FILETYPE_PEM); - if ( ! i ) - { - reporter->Error("X509_Cert::init(): error adding lookup directory\n"); - ret = 0; - } - } - else - { - printf("X509: Using the default trusted cert path.\n"); - X509_STORE_set_default_paths(ctx); - } - - // Add crl functionality - will only add if defined and - // X509_STORE_add_lookup was successful. - if ( ! flag && x509_crl_file && x509_crl_file->AsString()->Len() > 0 ) - { - const BroString* rString = x509_crl_file->AsString(); - - if ( X509_load_crl_file(lookup, (const char*) rString->Bytes(), - X509_FILETYPE_PEM) != 1 ) - { - reporter->Error("X509_Cert::init(): error reading CRL file\n"); - ret = 1; - } - -#if 0 - // Note, openssl version must be > 0.9.7(a). - X509_STORE_set_flags(ctx, - X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); -#endif - } - - bInited = true; - return ret; - } - -int X509_Cert::verify(Contents_SSL* e, const u_char* data, uint32 len) - { - if ( ! bInited ) - init(); - - X509* pCert = d2i_X509_(NULL, &data, len); - if ( ! pCert ) - { - // 5 = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY - sslCertificateError(e, 5); - return -1; - } - - sslCertificateEvent(e, pCert); - - X509_STORE_CTX_init(&csc, ctx, pCert, 0); - X509_STORE_CTX_set_time(&csc, 0, (time_t) network_time); - int i = X509_verify_cert(&csc); - X509_STORE_CTX_cleanup(&csc); - int ret = 0; - - int ext = X509_get_ext_count(pCert); - - if ( ext > 0 ) - { - TableVal* x509ex = new TableVal(x509_extension); - val_list* vl = new val_list; - char buf[256]; - - for ( int k = 0; k < ext; ++k ) - { - X509_EXTENSION* ex = X509_get_ext(pCert, k); - ASN1_OBJECT* obj = X509_EXTENSION_get_object(ex); - i2t_ASN1_OBJECT(buf, sizeof(buf), obj); - - Val* index = new Val(k+1, TYPE_COUNT); - Val* value = new StringVal(strlen(buf), buf); - x509ex->Assign(index, value); - Unref(index); - // later we can do critical extensions like: - // X509_EXTENSION_get_critical(ex); - } - - vl->append(e->BuildConnVal()); - vl->append(x509ex); - e->Conn()->ConnectionEvent(process_X509_extensions, e, vl); - } - - if ( ! i ) - { - sslCertificateError(e, csc.error); - ret = csc.error; - } - else - ret = 0; - - delete pCert; - return ret; - } - -int X509_Cert::verifyChain(Contents_SSL* e, const u_char* data, uint32 len) - { - if ( ! bInited ) - init(); - - // Gets an ssl3x cert chain (could be one single cert, too, - // but in chain format). - - // Init the stack. - STACK_OF(X509)* untrustedCerts = sk_X509_new_null(); - if ( ! untrustedCerts ) - { - // Internal error allocating stack of untrusted certs. - // 11 = X509_V_ERR_OUT_OF_MEM - sslCertificateError(e, 11); - return -1; - } - - // NOT AGAIN!!! - // Extract certificates and put them into an OpenSSL Stack. - uint tempLength = 0; - int certCount = 0; - X509* pCert = 0; // base cert, this one is to be verified - - while ( tempLength < len ) - { - ++certCount; - uint32 certLength = - uint32((data[tempLength + 0] << 16) | - data[tempLength + 1] << 8) | - data[tempLength + 2]; - - // Points to current cert. - const u_char* pCurrentCert = &data[tempLength+3]; - - X509* pTemp = d2i_X509_(0, &pCurrentCert, certLength); - if ( ! pTemp ) - { // error is somewhat of a misnomer - // 5 = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY - sslCertificateError(e, 5); - //FIXME: free ptrs - return -1; - } - - if ( certCount == 1 ) - // The first certificate goes directly into the ctx. - pCert = pTemp; - else - // The remaining certificates (if any) are put into - // the list of untrusted certificates - sk_X509_push(untrustedCerts, pTemp); - - tempLength += certLength + 3; - } - - sslCertificateEvent(e, pCert); - - X509_STORE_CTX_init(&csc, ctx, pCert, untrustedCerts); - X509_STORE_CTX_set_time(&csc, 0, (time_t) network_time); - int i = X509_verify_cert(&csc); - X509_STORE_CTX_cleanup(&csc); - //X509_STORE_CTX_free(&csc); - int ret = 0; - - if ( ! i ) - { - sslCertificateError(e, csc.error); - ret = csc.error; - } - else - ret = 0; - - delete pCert; - // Free the stack, incuding. contents. - - // FIXME: could this break Bro's memory tracking? - sk_X509_pop_free(untrustedCerts, X509_free); - - return ret; - } diff --git a/src/XDR.cc b/src/XDR.cc index 53e9a4b2dd..96d855ddbd 100644 --- a/src/XDR.cc +++ b/src/XDR.cc @@ -1,5 +1,3 @@ -// $Id: XDR.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include diff --git a/src/XDR.h b/src/XDR.h index 2c6e1d69ac..65192d6067 100644 --- a/src/XDR.h +++ b/src/XDR.h @@ -1,5 +1,3 @@ -// $Id: XDR.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef xdr_h diff --git a/src/ZIP.cc b/src/ZIP.cc index 84643c2874..0ebe93abe6 100644 --- a/src/ZIP.cc +++ b/src/ZIP.cc @@ -1,11 +1,7 @@ -// $Id: ZIP.cc,v 1.1.4.2 2006/05/31 21:49:29 sommer Exp $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "ZIP.h" -#ifdef HAVE_LIBZ - ZIP_Analyzer::ZIP_Analyzer(Connection* conn, bool orig, Method arg_method) : TCP_SupportAnalyzer(AnalyzerTag::Zip, conn, orig) { @@ -91,4 +87,3 @@ void ZIP_Analyzer::DeliverStream(int len, const u_char* data, bool orig) } while ( zip->avail_out == 0 ); } -#endif diff --git a/src/ZIP.h b/src/ZIP.h index 3debb6c3c8..6a8a180d1a 100644 --- a/src/ZIP.h +++ b/src/ZIP.h @@ -1,5 +1,3 @@ -// $Id: ZIP.h,v 1.1.4.2 2006/05/31 21:49:29 sommer Exp $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef zip_h @@ -7,8 +5,6 @@ #include "config.h" -#ifdef HAVE_LIBZ - #include "zlib.h" #include "TCP.h" @@ -31,4 +27,3 @@ protected: }; #endif -#endif diff --git a/src/bif_arg.cc b/src/bif_arg.cc index 5900c117eb..a4772e4d73 100644 --- a/src/bif_arg.cc +++ b/src/bif_arg.cc @@ -1,5 +1,3 @@ -// $Id: bif_arg.cc 3234 2006-06-08 02:38:11Z vern $ - #include "config.h" #include diff --git a/src/bif_arg.h b/src/bif_arg.h index 0462f6e173..4ba6fa0c4f 100644 --- a/src/bif_arg.h +++ b/src/bif_arg.h @@ -1,5 +1,3 @@ -// $Id: bif_arg.h 3234 2006-06-08 02:38:11Z vern $ - #ifndef bif_arg_h #define bif_arg_h diff --git a/src/bif_type.def b/src/bif_type.def index e9bf22eafc..5d9963ffc9 100644 --- a/src/bif_type.def +++ b/src/bif_type.def @@ -1,8 +1,6 @@ -// $Id: bif_type.def 5083 2007-11-28 17:42:58Z vern $ - // DEFINE_BIF_TYPE(id, bif_type, bro_type, c_type, accessor, constructor) -DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "addr_type", "%s->AsAddr()", "new AddrVal(%s)") +DEFINE_BIF_TYPE(TYPE_ADDR, "addr", "addr", "AddrVal*", "%s->AsAddrVal()", "%s") DEFINE_BIF_TYPE(TYPE_ANY, "any", "any", "Val*", "%s", "%s") DEFINE_BIF_TYPE(TYPE_BOOL, "bool", "bool", "int", "%s->AsBool()", "new Val(%s, TYPE_BOOL)") DEFINE_BIF_TYPE(TYPE_CONN_ID, "conn_id", "conn_id", "Val*", "%s", "%s") diff --git a/src/binpac-lib.pac b/src/binpac-lib.pac index 4e95a1a3db..2c501d90a4 100644 --- a/src/binpac-lib.pac +++ b/src/binpac-lib.pac @@ -1,5 +1,3 @@ -# $Id:$ - %extern{ #include diff --git a/src/binpac.pac b/src/binpac.pac index 8704fb5a61..ae601ce6b9 100644 --- a/src/binpac.pac +++ b/src/binpac.pac @@ -1,5 +1,3 @@ -# $Id:$ - # Prototypes for functions implemented in binpac-lib.pac. function bytestring_to_int(s: const_bytestring, base: int): int; diff --git a/src/binpac_bro-lib.pac b/src/binpac_bro-lib.pac index 20648e2d4f..c7cee6dc98 100644 --- a/src/binpac_bro-lib.pac +++ b/src/binpac_bro-lib.pac @@ -1,5 +1,3 @@ -# $Id:$ - %extern{ #include "util.h" %} diff --git a/src/binpac_bro.h b/src/binpac_bro.h index ffeb4ff28d..dcdbe94f57 100644 --- a/src/binpac_bro.h +++ b/src/binpac_bro.h @@ -1,5 +1,3 @@ -// $Id:$ - #ifndef binpac_bro_h #define binpac_bro_h diff --git a/src/bittorrent-analyzer.pac b/src/bittorrent-analyzer.pac index 7e8678b7de..3bc6d90230 100644 --- a/src/bittorrent-analyzer.pac +++ b/src/bittorrent-analyzer.pac @@ -1,5 +1,3 @@ -# $Id:$ -# # This code contributed by Nadi Sarrar. connection BitTorrent_Conn(bro_analyzer: BroAnalyzer) { @@ -12,25 +10,25 @@ flow BitTorrent_Flow(is_orig: bool) { %member{ bool handshake_ok; - uint64 _next_message_offset; + //uint64 _next_message_offset; %} %init{ handshake_ok = false; - _next_message_offset = 0; + //_next_message_offset = 0; %} - function next_message_offset(): uint64 - %{ - return &_next_message_offset; - %} + #function next_message_offset(): uint64 + # %{ + # return &_next_message_offset; + # %} - function increment_next_message_offset(go: bool, len: uint32): bool - %{ - if ( go ) - _next_message_offset += len; - return true; - %} + #function increment_next_message_offset(go: bool, len: uint32): bool + # %{ + # if ( go ) + # _next_message_offset += len; + # return true; + # %} function is_handshake_delivered(): bool %{ diff --git a/src/bittorrent-protocol.pac b/src/bittorrent-protocol.pac index 8bd1652cfa..76bbafbf20 100644 --- a/src/bittorrent-protocol.pac +++ b/src/bittorrent-protocol.pac @@ -1,5 +1,3 @@ -# $Id:$ -# # This code contributed by Nadi Sarrar. enum BitTorrent_peer_msg_type { @@ -24,8 +22,8 @@ type BitTorrent_Handshake = record { } &length = 68, &let { validate: bool = $context.flow.validate_handshake(pstrlen, pstr); - incoffsetffset: bool = - $context.flow.increment_next_message_offset(true, 68); + #incoffsetffset: bool = + # $context.flow.increment_next_message_offset(true, 68); deliver: bool = $context.flow.deliver_handshake(reserved, info_hash, peer_id); }; @@ -74,8 +72,8 @@ type BitTorrent_PieceHeader(len: uint32) = record { index: uint32; begin: uint32; } &let { - incoffset: bool = - $context.flow.increment_next_message_offset(true, len + 5); + #incoffset: bool = + # $context.flow.increment_next_message_offset(true, len + 5); }; type BitTorrent_Piece(len: uint32) = record { @@ -136,9 +134,9 @@ type BitTorrent_Message = record { default -> message_id: BitTorrent_MessageID(len.len); }; } &length = 4 + len.len, &let { - incoffset: bool = $context.flow.increment_next_message_offset( - len.len == 0 || message_id.id != TYPE_PIECE, - 4 + len.len); + #incoffset: bool = $context.flow.increment_next_message_offset( + # len.len == 0 || message_id.id != TYPE_PIECE, + # 4 + len.len); }; type BitTorrent_PDU = case $context.flow.is_handshake_delivered() of { diff --git a/src/bro.bif b/src/bro.bif index e4d0f2092b..f76704cfe6 100644 --- a/src/bro.bif +++ b/src/bro.bif @@ -1,6 +1,8 @@ -# $Id: bro.bif 7075 2010-09-13 02:39:38Z vern $ -# -# Definitions of Bro built-in functions. +##! A collection of built-in functions that implement a variety of things +##! such as general programming algorithms, string processing, math functions, +##! introspection, type conversion, file/directory manipulation, packet +##! filtering, inter-process communication and controlling protocol analyzer +##! behavior. %%{ // C segment #include @@ -12,6 +14,7 @@ #include #include "Reporter.h" +#include "IPAddr.h" using namespace std; @@ -176,35 +179,8 @@ static void do_fmt(const char*& fmt, Val* v, ODesc* d) // This makes only a very slight difference, so not // clear it would e worth the hassle. - addr_type u = v->AsAddr(); -#ifdef BROv6 - // We explicitly convert the address to host order - // in a copy, because if we just call ntohl() for - // our invocation on snprintf() below, on some systems - // it turns a 32-bit value (Linux), whereas on - // others it returns a long (FreeBSD); the latter - // gets us in trouble if we have longs > 32 bits, - // because then the format specifier needs to be %lx - // rather than %x ....... what a pain! - // - // Also note that we don't change u in-place because - // that would alter the byte order of the underlying - // value. (Speaking of which, I'm not clear on why - // we're allowed to assign a const addr_type to an - // addr_type above, both g++ allows it.) - uint32 host_order_u[4]; - host_order_u[0] = ntohl(u[0]); - host_order_u[1] = ntohl(u[1]); - host_order_u[2] = ntohl(u[2]); - host_order_u[3] = ntohl(u[3]); - - snprintf(out_buf, sizeof(out_buf), "%08x%08x%08x%08x", - host_order_u[0], host_order_u[1], - host_order_u[2], host_order_u[3]); -#else - u = ntohl(u); - snprintf(out_buf, sizeof(out_buf), "%08x", u); -#endif + snprintf(out_buf, sizeof(out_buf), "%s", + v->AsAddr().AsHexString().c_str()); } else if ( ! check_fmt_type(t, ok_d_fmt) ) @@ -319,470 +295,48 @@ static int next_fmt(const char*& fmt, val_list* args, ODesc* d, int& n) } %%} -function length%(v: any%): count - %{ - TableVal* tv = v->Type()->Tag() == TYPE_TABLE ? v->AsTableVal() : 0; - - if ( tv ) - return new Val(tv->Size(), TYPE_COUNT); - - else if ( v->Type()->Tag() == TYPE_VECTOR ) - return new Val(v->AsVectorVal()->Size(), TYPE_COUNT); - - else - { - builtin_error("length() requires a table/set/vector argument"); - return new Val(0, TYPE_COUNT); - } - %} - -function same_object%(o1: any, o2: any%): bool - %{ - return new Val(o1 == o2, TYPE_BOOL); - %} - -function clear_table%(v: any%): any - %{ - if ( v->Type()->Tag() == TYPE_TABLE ) - v->AsTableVal()->RemoveAll(); - else - builtin_error("clear_table() requires a table/set argument"); - - return 0; - %} - -function cat%(...%): string - %{ - ODesc d; - loop_over_list(@ARG@, i) - @ARG@[i]->Describe(&d); - - BroString* s = new BroString(1, d.TakeBytes(), d.Len()); - s->SetUseFreeToDelete(true); - - return new StringVal(s); - %} - -function record_type_to_vector%(rt: string%): string_vec - %{ - VectorVal* result = - new VectorVal(internal_type("string_vec")->AsVectorType()); - - RecordType *type = internal_type(rt->CheckString())->AsRecordType(); - - if ( type ) - { - for ( int i = 0; i < type->NumFields(); ++i ) - { - StringVal* val = new StringVal(type->FieldName(i)); - result->Assign(i+1, val, 0); - } - } - - return result; - %} - - -function cat_sep%(sep: string, def: string, ...%): string - %{ - ODesc d; - int pre_size = 0; - - loop_over_list(@ARG@, i) - { - // Skip named parameters. - if ( i < 2 ) - continue; - - if ( i > 2 ) - d.Add(sep->CheckString(), 0); - - Val* v = @ARG@[i]; - if ( v->Type()->Tag() == TYPE_STRING && ! v->AsString()->Len() ) - v = def; - - v->Describe(&d); - } - - BroString* s = new BroString(1, d.TakeBytes(), d.Len()); - s->SetUseFreeToDelete(true); - - return new StringVal(s); - %} - -function fmt%(...%): string - %{ - if ( @ARGC@ == 0 ) - return new StringVal(""); - - Val* fmt_v = @ARG@[0]; - if ( fmt_v->Type()->Tag() != TYPE_STRING ) - return bro_cat(frame, @ARGS@); - - const char* fmt = fmt_v->AsString()->CheckString(); - ODesc d; - int n = 0; - - while ( next_fmt(fmt, @ARGS@, &d, n) ) - ; - - if ( n < @ARGC@ - 1 ) - builtin_error("too many arguments for format", fmt_v); - - else if ( n >= @ARGC@ ) - builtin_error("too few arguments for format", fmt_v); - - BroString* s = new BroString(1, d.TakeBytes(), d.Len()); - s->SetUseFreeToDelete(true); - - return new StringVal(s); - %} - -function type_name%(t: any%): string - %{ - ODesc d; - t->Type()->Describe(&d); - - BroString* s = new BroString(1, d.TakeBytes(), d.Len()); - s->SetUseFreeToDelete(true); - - return new StringVal(s); - %} - -function to_int%(str: string%): int - %{ - const char* s = str->CheckString(); - char* end_s; - - long l = strtol(s, &end_s, 10); - int i = int(l); - -#if 0 - // Not clear we should complain. For example, is " 205 " - // a legal conversion? - if ( s[0] == '\0' || end_s[0] != '\0' ) - builtin_error("bad conversion to integer", @ARG@[0]); -#endif - - return new Val(i, TYPE_INT); - %} - -function int_to_count%(n: int%): count - %{ - if ( n < 0 ) - { - builtin_error("bad conversion to count", @ARG@[0]); - n = 0; - } - return new Val(n, TYPE_COUNT); - %} - -function double_to_count%(d: double%): count - %{ - if ( d < 0.0 ) - builtin_error("bad conversion to count", @ARG@[0]); - - return new Val(bro_uint_t(rint(d)), TYPE_COUNT); - %} - -function to_count%(str: string%): count - %{ - const char* s = str->CheckString(); - char* end_s; - - uint64 u = (uint64) strtoll(s, &end_s, 10); - - if ( s[0] == '\0' || end_s[0] != '\0' ) - { - builtin_error("bad conversion to count", @ARG@[0]); - u = 0; - } - - return new Val(u, TYPE_COUNT); - %} - -function interval_to_double%(i: interval%): double - %{ - return new Val(i, TYPE_DOUBLE); - %} - -function time_to_double%(t: time%): double - %{ - return new Val(t, TYPE_DOUBLE); - %} - -function double_to_time%(d: double%): time - %{ - return new Val(d, TYPE_TIME); - %} - -function double_to_interval%(d: double%): interval - %{ - return new Val(d, TYPE_INTERVAL); - %} - -function addr_to_count%(a: addr%): count - %{ -#ifdef BROv6 - if ( ! is_v4_addr(a) ) - { - builtin_error("conversion of non-IPv4 address to count", @ARG@[0]); - return new Val(0, TYPE_COUNT); - } - - uint32 addr = to_v4_addr(a); -#else - uint32 addr = a; -#endif - return new Val(ntohl(addr), TYPE_COUNT); - %} - -function port_to_count%(p: port%): count - %{ - return new Val(p->Port(), TYPE_COUNT); - %} - -function count_to_port%(c: count, t: transport_proto%): port - %{ - return new PortVal(c, (TransportProto)(t->InternalInt())); - %} - -function floor%(d: double%): double - %{ - return new Val(floor(d), TYPE_DOUBLE); - %} - -function to_addr%(ip: string%): addr - %{ - char* s = ip->AsString()->Render(); - Val* ret = new AddrVal(s); - delete [] s; - return ret; - %} - -function count_to_v4_addr%(ip: count%): addr - %{ - if ( ip > 4294967295 ) - { - builtin_error("conversion of non-IPv4 count to addr", @ARG@[0]); - return new AddrVal(uint32(0)); - } - - return new AddrVal(htonl(uint32(ip))); - %} - -# Interprets the first 4 bytes of 'b' as an IPv4 address in network order. -function raw_bytes_to_v4_addr%(b: string%): addr - %{ - uint32 a = 0; - - if ( b->Len() < 4 ) - builtin_error("too short a string as input to raw_bytes_to_v4_addr()"); - - else - { - const u_char* bp = b->Bytes(); - a = (bp[0] << 24) | (bp[1] << 16) | (bp[2] << 8) | bp[3]; - } - - return new AddrVal(htonl(a)); - %} - -function to_port%(num: count, proto: transport_proto%): port - %{ - return new PortVal(num, (TransportProto)proto->AsEnum()); - %} - -function mask_addr%(a: addr, top_bits_to_keep: count%): subnet - %{ - return new SubNetVal(mask_addr(a, top_bits_to_keep), top_bits_to_keep); - %} - -# Take some top bits (e.g. subnet address) from a1 and the other -# bits (intra-subnet part) from a2 and merge them to get a new address. -# This is useful for anonymizing at subnet level while preserving -# serial scans. -function remask_addr%(a1: addr, a2: addr, top_bits_from_a1: count%): addr - %{ -#ifdef BROv6 - if ( ! is_v4_addr(a1) || ! is_v4_addr(a2) ) - { - builtin_error("cannot use remask_addr on IPv6 addresses"); - return new AddrVal(a1); - } - - uint32 x1 = to_v4_addr(a1); - uint32 x2 = to_v4_addr(a2); -#else - uint32 x1 = a1; - uint32 x2 = a2; -#endif - return new AddrVal( - mask_addr(x1, top_bits_from_a1) | - (x2 ^ mask_addr(x2, top_bits_from_a1)) ); - %} - -function is_tcp_port%(p: port%): bool - %{ - return new Val(p->IsTCP(), TYPE_BOOL); - %} - -function is_udp_port%(p: port%): bool - %{ - return new Val(p->IsUDP(), TYPE_BOOL); - %} - -function is_icmp_port%(p: port%): bool - %{ - return new Val(p->IsICMP(), TYPE_BOOL); - %} - -function reading_live_traffic%(%): bool - %{ - return new Val(reading_live, TYPE_BOOL); - %} - -function reading_traces%(%): bool - %{ - return new Val(reading_traces, TYPE_BOOL); - %} - -function open%(f: string%): file - %{ - const char* file = f->CheckString(); - - if ( streq(file, "-") ) - return new Val(new BroFile(stdout, "-", "w")); - else - return new Val(new BroFile(file, "w")); - %} - -function open_for_append%(f: string%): file - %{ - return new Val(new BroFile(f->CheckString(), "a")); - %} - -function close%(f: file%): bool - %{ - return new Val(f->Close(), TYPE_BOOL); - %} - -function write_file%(f: file, data: string%): bool - %{ - if ( ! f ) - return new Val(0, TYPE_BOOL); - - return new Val(f->Write((const char*) data->Bytes(), data->Len()), - TYPE_BOOL); - %} - -function set_buf%(f: file, buffered: bool%): any - %{ - f->SetBuf(buffered); - return new Val(0, TYPE_VOID); - %} - -function flush_all%(%): bool - %{ - return new Val(fflush(0) == 0, TYPE_BOOL); - %} - -function mkdir%(f: string%): bool - %{ - const char* filename = f->CheckString(); - if ( mkdir(filename, 0777) < 0 && errno != EEXIST ) - { - builtin_error("cannot create directory", @ARG@[0]); - return new Val(0, TYPE_BOOL); - } - else - return new Val(1, TYPE_BOOL); - %} - -function active_file%(f: file%): bool - %{ - return new Val(f->IsOpen(), TYPE_BOOL); - %} - -function active_connection%(id: conn_id%): bool - %{ - Connection* c = sessions->FindConnection(id); - return new Val(c ? 1 : 0, TYPE_BOOL); - %} - -# Note, you *must* first make sure that the connection is active -# (e.g., by calling active_connection()) before invoking this. -function connection_record%(cid: conn_id%): connection - %{ - Connection* c = sessions->FindConnection(cid); - if ( c ) - return c->BuildConnVal(); - else - { - // Hard to recover from this until we have union types ... - builtin_error("connection ID not a known connection (fatal)", cid); - exit(0); - return 0; - } - %} - -%%{ -EnumVal* map_conn_type(TransportProto tp) - { - switch ( tp ) { - case TRANSPORT_UNKNOWN: - return new EnumVal(0, transport_proto); - break; - - case TRANSPORT_TCP: - return new EnumVal(1, transport_proto); - break; - - case TRANSPORT_UDP: - return new EnumVal(2, transport_proto); - break; - - case TRANSPORT_ICMP: - return new EnumVal(3, transport_proto); - break; - - default: - reporter->InternalError("bad connection type in map_conn_type()"); - } - - // Cannot be reached; - assert(false); - return 0; // Make compiler happy. - } -%%} - -function get_conn_transport_proto%(cid: conn_id%): transport_proto - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - { - builtin_error("unknown connection id in get_conn_transport_proto()", cid); - return new EnumVal(0, transport_proto); - } - - return map_conn_type(c->ConnTransport()); - %} - -function get_port_transport_proto%(p: port%): transport_proto - %{ - return map_conn_type(p->PortType()); - %} - +# =========================================================================== +# +# Core +# +# =========================================================================== + +## Returns the current wall-clock time. +## +## In general, you should use :bro:id:`network_time` instead +## unless you are using Bro for non-networking uses (such as general +## scripting; not particularly recommended), because otherwise your script +## may behave very differently on live traffic versus played-back traffic +## from a save file. +## +## Returns: The wall-clock time. +## +## .. bro:see:: network_time function current_time%(%): time %{ return new Val(current_time(), TYPE_TIME); %} +## Returns the timestamp of the last packet processed. This function returns +## the timestamp of the most recently read packet, whether read from a +## live network interface or from a save file. +## +## Returns: The timestamp of the packet processed. +## +## .. bro:see:: current_time function network_time%(%): time %{ return new Val(network_time, TYPE_TIME); %} +## Returns a system environment variable. +## +## var: The name of the variable whose value to request. +## +## Returns: The system environment variable identified by *var*, or an empty +## string if it is not defined. +## +## .. bro:see:: setenv function getenv%(var: string%): string %{ const char* env_val = getenv(var->CheckString()); @@ -791,40 +345,42 @@ function getenv%(var: string%): string return new StringVal(env_val); %} -function sqrt%(x: double%): double +## Sets a system environment variable. +## +## var: The name of the variable. +## +## val: The (new) value of the variable *var*. +## +## Returns: True on success. +## +## .. bro:see:: getenv +function setenv%(var: string, val: string%): bool %{ - if ( x < 0 ) - { - reporter->Error("negative sqrt argument"); - return new Val(-1.0, TYPE_DOUBLE); - } + int result = setenv(var->AsString()->CheckString(), + val->AsString()->CheckString(), 1); - return new Val(sqrt(x), TYPE_DOUBLE); + if ( result < 0 ) + return new Val(0, TYPE_BOOL); + return new Val(1, TYPE_BOOL); %} -function exp%(d: double%): double +## Shuts down the Bro process immediately. +## +## code: The exit code to return with. +## +## .. bro:see:: terminate +function exit%(code: int%): any %{ - return new Val(exp(d), TYPE_DOUBLE); - %} - -# Natural log. -function ln%(d: double%): double - %{ - return new Val(log(d), TYPE_DOUBLE); - %} - -# Common log. -function log10%(d: double%): double - %{ - return new Val(log10(d), TYPE_DOUBLE); - %} - -function exit%(%): int - %{ - exit(0); + exit(code); return 0; %} +## Gracefully shut down Bro by terminating outstanding processing. +## +## Returns: True after successful termination and false when Bro is still in +## the process of shutting down. +## +## .. bro:see:: exit bro_is_terminating function terminate%(%): bool %{ if ( terminating ) @@ -881,12 +437,41 @@ static int do_system(const char* s) } %%} +## Invokes a command via the ``system`` function of the OS. +## The command runs in the background with ``stdout`` redirecting to +## ``stderr``. Here is a usage example: +## ``system(fmt("rm \"%s\"", str_shell_escape(sniffed_data)));`` +## +## str: The command to execute. +## +## Returns: The return value from the OS ``system`` function. +## +## .. bro:see:: system_env str_shell_escape piped_exec +## +## .. note:: +## +## Note that this corresponds to the status of backgrounding the +## given command, not to the exit status of the command itself. A +## value of 127 corresponds to a failure to execute ``sh``, and -1 +## to an internal system failure. function system%(str: string%): int %{ int result = do_system(str->CheckString()); return new Val(result, TYPE_INT); %} +## Invokes a command via the ``system`` function of the OS with a prepared +## environment. The function is essentially the same as :bro:id:`system`, +## but changes the environment before invoking the command. +## +## str: The command to execute. +## +## env: A :bro:type:`set` or :bro:type:`table` with the environment variables +## in the form of key-value pairs (where the value is optional). +## +## Returns: The return value from the OS ``system`` function. +## +## .. bro:see:: system str_shell_escape piped_exec function system_env%(str: string, env: any%): int %{ if ( env->Type()->Tag() != TYPE_TABLE ) @@ -905,816 +490,43 @@ function system_env%(str: string, env: any%): int return new Val(result, TYPE_INT); %} - -%%{ -static Val* parse_eftp(const char* line) - { - RecordVal* r = new RecordVal(ftp_port); - - int net_proto = 0; // currently not used - uint32 addr = 0; - int port = 0; - int good = 0; - - if ( line ) - { - while ( isspace(*line) ) // skip whitespace - ++line; - - char delimiter = *line; - good = 1; - char* next_delim; - - ++line; // cut off delimiter - net_proto = strtol(line, &next_delim, 10); // currently ignored - if ( *next_delim != delimiter ) - good = 0; - - line = next_delim + 1; - if ( *line != delimiter ) // default of 0 is ok - { - addr = dotted_to_addr(line); - if ( addr == 0 ) - good = 0; - } - - // FIXME: check for garbage between IP and delimiter. - line = strchr(line, delimiter); - - ++line; // now the port - port = strtol(line, &next_delim, 10); - if ( *next_delim != delimiter ) - good = 0; - } - - r->Assign(0, new AddrVal(addr)); - r->Assign(1, new PortVal(port, TRANSPORT_TCP)); - r->Assign(2, new Val(good, TYPE_BOOL)); - - return r; - } -%%} - -%%{ -static Val* parse_port(const char* line) - { - RecordVal* r = new RecordVal(ftp_port); - - int bytes[6]; - if ( line && sscanf(line, "%d,%d,%d,%d,%d,%d", - &bytes[0], &bytes[1], &bytes[2], - &bytes[3], &bytes[4], &bytes[5]) == 6 ) - { - int good = 1; - - for ( int i = 0; i < 6; ++i ) - if ( bytes[i] < 0 || bytes[i] > 255 ) - { - good = 0; - break; - } - - uint32 addr = (bytes[0] << 24) | (bytes[1] << 16) | - (bytes[2] << 8) | bytes[3]; - uint32 port = (bytes[4] << 8) | bytes[5]; - - // Since port is unsigned, no need to check for < 0. - if ( port > 65535 ) - { - port = 0; - good = 0; - } - - r->Assign(0, new AddrVal(htonl(addr))); - r->Assign(1, new PortVal(port, TRANSPORT_TCP)); - r->Assign(2, new Val(good, TYPE_BOOL)); - } - else - { - r->Assign(0, new AddrVal(uint32(0))); - r->Assign(1, new PortVal(0, TRANSPORT_TCP)); - r->Assign(2, new Val(0, TYPE_BOOL)); - } - - return r; - } -%%} - -# Returns true if the given connection exists, false otherwise. -function connection_exists%(c: conn_id%): bool +## Opens a program with ``popen`` and writes a given string to the returned +## stream to send it to the opened process's stdin. +## +## program: The program to execute. +## +## to_write: Data to pipe to the opened program's process via ``stdin``. +## +## Returns: True on success. +## +## .. bro:see:: system system_env +function piped_exec%(program: string, to_write: string%): bool %{ - if ( sessions->FindConnection(c) ) - return new Val(1, TYPE_BOOL); - else - return new Val(0, TYPE_BOOL); - %} + const char* prog = program->CheckString(); -# For a given connection ID, returns the corresponding "connection" record. -# Generates a run-time error and returns a dummy value if the connection -# doesn't exist. -function lookup_connection%(cid: conn_id%): connection - %{ - Connection* conn = sessions->FindConnection(cid); - if ( conn ) - return conn->BuildConnVal(); - - builtin_error("connection ID not a known connection", cid); - - // Return a dummy connection record. - RecordVal* c = new RecordVal(connection_type); - - RecordVal* id_val = new RecordVal(conn_id); - id_val->Assign(0, new AddrVal((unsigned int) 0)); - id_val->Assign(1, new PortVal(ntohs(0), TRANSPORT_UDP)); - id_val->Assign(2, new AddrVal((unsigned int) 0)); - id_val->Assign(3, new PortVal(ntohs(0), TRANSPORT_UDP)); - c->Assign(0, id_val); - - RecordVal* orig_endp = new RecordVal(endpoint); - orig_endp->Assign(0, new Val(0, TYPE_COUNT)); - orig_endp->Assign(1, new Val(int(0), TYPE_COUNT)); - - RecordVal* resp_endp = new RecordVal(endpoint); - resp_endp->Assign(0, new Val(0, TYPE_COUNT)); - resp_endp->Assign(1, new Val(int(0), TYPE_COUNT)); - - c->Assign(1, orig_endp); - c->Assign(2, resp_endp); - - c->Assign(3, new Val(network_time, TYPE_TIME)); - c->Assign(4, new Val(0.0, TYPE_INTERVAL)); - c->Assign(5, new TableVal(string_set)); // service - c->Assign(6, new StringVal("")); // addl - c->Assign(7, new Val(0, TYPE_COUNT)); // hot - c->Assign(8, new StringVal("")); // history - - return c; - %} - -function skip_further_processing%(cid: conn_id%): bool - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - return new Val(0, TYPE_BOOL); - - c->SetSkip(1); - return new Val(1, TYPE_BOOL); - %} - -function set_record_packets%(cid: conn_id, do_record: bool%): bool - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - return new Val(0, TYPE_BOOL); - - c->SetRecordPackets(do_record); - return new Val(1, TYPE_BOOL); - %} - -function set_contents_file%(cid: conn_id, direction: count, f: file%): bool - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - return new Val(0, TYPE_BOOL); - - c->GetRootAnalyzer()->SetContentsFile(direction, f); - return new Val(1, TYPE_BOOL); - %} - -function get_contents_file%(cid: conn_id, direction: count%): file - %{ - Connection* c = sessions->FindConnection(cid); - BroFile* f = c ? c->GetRootAnalyzer()->GetContentsFile(direction) : 0; - - if ( f ) - { - Ref(f); - return new Val(f); - } - - // Return some sort of error value. - if ( ! c ) - builtin_error("unknown connection id in get_contents_file()", cid); - else - builtin_error("no contents file for given direction"); - - return new Val(new BroFile(stderr, "-", "w")); - %} - -function get_file_name%(f: file%): string - %{ + FILE* f = popen(prog, "w"); if ( ! f ) - return new StringVal(""); - - return new StringVal(f->Name()); - %} - -# Set an individual inactivity timeout for this connection -# (overrides the global inactivity_timeout). Returns previous -# timeout interval. -function set_inactivity_timeout%(cid: conn_id, t: interval%): interval - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - return new Val(0, TYPE_INTERVAL); - - double old_timeout = c->InactivityTimeout(); - c->SetInactivityTimeout(t); - - return new Val(old_timeout, TYPE_INTERVAL); - %} - -function get_login_state%(cid: conn_id%): count - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) + { + reporter->Error("Failed to popen %s", prog); return new Val(0, TYPE_BOOL); + } - Analyzer* la = c->FindAnalyzer(AnalyzerTag::Login); - if ( ! la ) + const u_char* input_data = to_write->Bytes(); + int input_data_len = to_write->Len(); + + int bytes_written = fwrite(input_data, 1, input_data_len, f); + + pclose(f); + + if ( bytes_written != input_data_len ) + { + reporter->Error("Failed to write all given data to %s", prog); return new Val(0, TYPE_BOOL); + } - return new Val(int(static_cast(la)->LoginState()), - TYPE_COUNT); - %} - -function set_login_state%(cid: conn_id, new_state: count%): bool - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - return new Val(0, TYPE_BOOL); - - Analyzer* la = c->FindAnalyzer(AnalyzerTag::Login); - if ( ! la ) - return new Val(0, TYPE_BOOL); - - static_cast(la)->SetLoginState(login_state(new_state)); return new Val(1, TYPE_BOOL); %} -%%{ -#include "TCP.h" -%%} - -function get_orig_seq%(cid: conn_id%): count - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - return new Val(0, TYPE_COUNT); - - if ( c->ConnTransport() != TRANSPORT_TCP ) - return new Val(0, TYPE_COUNT); - - Analyzer* tc = c->FindAnalyzer(AnalyzerTag::TCP); - if ( tc ) - return new Val(static_cast(tc)->OrigSeq(), - TYPE_COUNT); - else - { - reporter->Error("connection does not have TCP analyzer"); - return new Val(0, TYPE_COUNT); - } - %} - -function get_resp_seq%(cid: conn_id%): count - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - return new Val(0, TYPE_COUNT); - - if ( c->ConnTransport() != TRANSPORT_TCP ) - return new Val(0, TYPE_COUNT); - - Analyzer* tc = c->FindAnalyzer(AnalyzerTag::TCP); - if ( tc ) - return new Val(static_cast(tc)->RespSeq(), - TYPE_COUNT); - else - { - reporter->Error("connection does not have TCP analyzer"); - return new Val(0, TYPE_COUNT); - } - %} - -# These convert addresses <-> n3.n2.n1.n0.in-addr.arpa -function ptr_name_to_addr%(s: string%): addr - %{ - int a[4]; - uint32 addr; - - if ( sscanf(s->CheckString(), - "%d.%d.%d.%d.in-addr.arpa", - a, a+1, a+2, a+3) != 4 ) - { - builtin_error("bad PTR name", @ARG@[0]); - addr = 0; - } - else - addr = (a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]; - - return new AddrVal(htonl(addr)); - %} - -function addr_to_ptr_name%(a: addr%): string - %{ - // ## Question: - // uint32 addr = ntohl((*args)[0]->InternalUnsigned()); - uint32 addr; -#ifdef BROv6 - if ( is_v4_addr(a) ) - addr = a[3]; - else - { - builtin_error("conversion of non-IPv4 address to net", @ARG@[0]); - addr = 0; - } -#else - addr = a; -#endif - - addr = ntohl(addr); - uint32 a3 = (addr >> 24) & 0xff; - uint32 a2 = (addr >> 16) & 0xff; - uint32 a1 = (addr >> 8) & 0xff; - uint32 a0 = addr & 0xff; - - char buf[256]; - sprintf(buf, "%u.%u.%u.%u.in-addr.arpa", a0, a1, a2, a3); - - return new StringVal(buf); - %} - -# Transforms n0.n1.n2.n3 -> addr. -function parse_dotted_addr%(s: string%): addr - %{ - return new AddrVal(dotted_to_addr(s->CheckString())); - %} - -function parse_ftp_port%(s: string%): ftp_port - %{ - return parse_port(s->CheckString()); - %} - -function parse_eftp_port%(s: string%): ftp_port - %{ - return parse_eftp(s->CheckString()); - %} - -function parse_ftp_pasv%(str: string%): ftp_port - %{ - const char* s = str->CheckString(); - const char* line = strchr(s, '('); - if ( line ) - ++line; // move past '(' - else if ( (line = strstr(s, "PORT")) ) - line += 5; // Skip over - else if ( (line = strchr(s, ',')) ) - { // Look for comma-separated list. - while ( --line >= s && isdigit(*line) ) - ; // Back up over preceding digits. - ++line; // now points to first digit, or beginning of s - } - - return parse_port(line); - %} - -function parse_ftp_epsv%(str: string%): ftp_port - %{ - const char* s = str->CheckString(); - const char* line = strchr(s, '('); - if ( line ) - ++line; // move past '(' - return parse_eftp(line); - %} - -function fmt_ftp_port%(a: addr, p: port%): string - %{ -#ifdef BROv6 - if ( ! is_v4_addr(a) ) - builtin_error("conversion of non-IPv4 address to net", @ARG@[0]); - - uint32 addr = to_v4_addr(a); -#else - uint32 addr = a; -#endif - addr = ntohl(addr); - uint32 pn = p->Port(); - return new StringVal(fmt("%d,%d,%d,%d,%d,%d", - addr >> 24, (addr >> 16) & 0xff, - (addr >> 8) & 0xff, addr & 0xff, - pn >> 8, pn & 0xff)); - %} - -function decode_netbios_name%(name: string%): string - %{ - char buf[16]; - char result[16]; - const u_char* s = name->Bytes(); - int i, j; - - for ( i = 0, j = 0; i < 16; ++i ) - { - char c0 = (j < name->Len()) ? toupper(s[j++]) : 'A'; - char c1 = (j < name->Len()) ? toupper(s[j++]) : 'A'; - buf[i] = ((c0 - 'A') << 4) + (c1 - 'A'); - } - - for ( i = 0; i < 15; ++i ) - { - if ( isalnum(buf[i]) || ispunct(buf[i]) || - // \x01\x02 is seen in at least one case as the first two bytes. - // I think that any \x01 and \x02 should always be passed through. - buf[i] < 3 ) - result[i] = buf[i]; - else - break; - } - - return new StringVal(i, result); - %} - -function decode_netbios_name_type%(name: string%): count - %{ - const u_char* s = name->Bytes(); - char return_val = ((toupper(s[30]) - 'A') << 4) + (toupper(s[31]) - 'A'); - return new Val(return_val, TYPE_COUNT); - %} - -%%{ -#include "HTTP.h" - -const char* conn_id_string(Val* c) - { - Val* id = (*(c->AsRecord()))[0]; - const val_list* vl = id->AsRecord(); - - addr_type orig_h = (*vl)[0]->AsAddr(); - uint32 orig_p = (*vl)[1]->AsPortVal()->Port(); - addr_type resp_h = (*vl)[2]->AsAddr(); - uint32 resp_p = (*vl)[3]->AsPortVal()->Port(); - - return fmt("%s/%u -> %s/%u\n", dotted_addr(orig_h), orig_p, dotted_addr(resp_h), resp_p); - } -%%} - -# Skip data of the HTTP entity on the connection -function skip_http_entity_data%(c: connection, is_orig: bool%): any - %{ - AnalyzerID id = mgr.CurrentAnalyzer(); - if ( id ) - { - Analyzer* ha = c->FindAnalyzer(id); - - if ( ha ) - { - if ( ha->GetTag() == AnalyzerTag::HTTP ) - static_cast(ha)->SkipEntityData(is_orig); - else - reporter->Error("non-HTTP analyzer associated with connection record"); - } - else - reporter->Error("could not find analyzer for skip_http_entity_data"); - - } - else - reporter->Error("no analyzer associated with connection record"); - - return 0; - %} - -# Unescape all characters in the URI, i.e. decode every %xx group. -# -# Note that unescaping reserved characters may cause loss of -# information (see below). -# -# RFC 2396: A URI is always in an "escaped" form, since escaping or -# unescaping a completed URI might change its semantics. Normally, -# the only time escape encodings can safely be made is when the URI -# is being created from its component parts. - -function unescape_URI%(URI: string%): string - %{ - const u_char* line = URI->Bytes(); - const u_char* const line_end = line + URI->Len(); - - return new StringVal(unescape_URI(line, line_end, 0)); - %} - -%%{ -#include "SMTP.h" -%%} - -# Skip smtp_data till next mail -function skip_smtp_data%(c: connection%): any - %{ - Analyzer* sa = c->FindAnalyzer(AnalyzerTag::SMTP); - if ( sa ) - static_cast(sa)->SkipData(); - return 0; - %} - - -function bytestring_to_hexstr%(bytestring: string%): string - %{ - bro_uint_t len = bytestring->AsString()->Len(); - const u_char* bytes = bytestring->AsString()->Bytes(); - char hexstr[(2 * len) + 1]; - - hexstr[0] = 0; - for ( bro_uint_t i = 0; i < len; ++i ) - snprintf(hexstr + (2 * i), 3, "%.2hhx", bytes[i]); - - return new StringVal(hexstr); - %} - -%%{ -extern const char* bro_version(); -%%} - -function net_stats%(%): NetStats - %{ - unsigned int recv = 0; - unsigned int drop = 0; - unsigned int link = 0; - - loop_over_list(pkt_srcs, i) - { - PktSrc* ps = pkt_srcs[i]; - - struct PktSrc::Stats stat; - ps->Statistics(&stat); - recv += stat.received; - drop += stat.dropped; - link += stat.link; - } - - RecordVal* ns = new RecordVal(net_stats); - ns->Assign(0, new Val(recv, TYPE_COUNT)); - ns->Assign(1, new Val(drop, TYPE_COUNT)); - ns->Assign(2, new Val(link, TYPE_COUNT)); - - return ns; - %} - -function resource_usage%(%): bro_resources - %{ - struct rusage r; - - if ( getrusage(RUSAGE_SELF, &r) < 0 ) - reporter->InternalError("getrusage() failed in bro_resource_usage()"); - - double elapsed_time = current_time() - bro_start_time; - - double user_time = - double(r.ru_utime.tv_sec) + double(r.ru_utime.tv_usec) / 1e6; - double system_time = - double(r.ru_stime.tv_sec) + double(r.ru_stime.tv_usec) / 1e6; - - RecordVal* res = new RecordVal(bro_resources); - int n = 0; - - res->Assign(n++, new StringVal(bro_version())); - -#ifdef DEBUG - res->Assign(n++, new Val(1, TYPE_COUNT)); -#else - res->Assign(n++, new Val(0, TYPE_COUNT)); -#endif - - res->Assign(n++, new Val(bro_start_time, TYPE_TIME)); - - res->Assign(n++, new IntervalVal(elapsed_time, Seconds)); - res->Assign(n++, new IntervalVal(user_time, Seconds)); - res->Assign(n++, new IntervalVal(system_time, Seconds)); - - unsigned int total_mem; - get_memory_usage(&total_mem, 0); - res->Assign(n++, new Val(unsigned(total_mem), TYPE_COUNT)); - - res->Assign(n++, new Val(unsigned(r.ru_minflt), TYPE_COUNT)); - res->Assign(n++, new Val(unsigned(r.ru_majflt), TYPE_COUNT)); - res->Assign(n++, new Val(unsigned(r.ru_nswap), TYPE_COUNT)); - res->Assign(n++, new Val(unsigned(r.ru_inblock), TYPE_COUNT)); - res->Assign(n++, new Val(unsigned(r.ru_oublock), TYPE_COUNT)); - res->Assign(n++, new Val(unsigned(r.ru_nivcsw), TYPE_COUNT)); - - SessionStats s; - if ( sessions ) - sessions->GetStats(s); - -#define ADD_STAT(x) \ - res->Assign(n++, new Val(unsigned(sessions ? x : 0), TYPE_COUNT)); - - ADD_STAT(s.num_TCP_conns); - ADD_STAT(s.num_UDP_conns); - ADD_STAT(s.num_ICMP_conns); - ADD_STAT(s.num_fragments); - ADD_STAT(s.num_packets); - ADD_STAT(s.num_timers); - ADD_STAT(s.num_events_queued); - ADD_STAT(s.num_events_dispatched); - ADD_STAT(s.max_TCP_conns); - ADD_STAT(s.max_UDP_conns); - ADD_STAT(s.max_ICMP_conns); - ADD_STAT(s.max_fragments); - ADD_STAT(s.max_timers); - - return res; - %} - -function get_matcher_stats%(%): matcher_stats - %{ - RuleMatcher::Stats s; - memset(&s, 0, sizeof(s)); - - if ( rule_matcher ) - rule_matcher->GetStats(&s); - - RecordVal* r = new RecordVal(matcher_stats); - r->Assign(0, new Val(s.matchers, TYPE_COUNT)); - r->Assign(1, new Val(s.dfa_states, TYPE_COUNT)); - r->Assign(2, new Val(s.computed, TYPE_COUNT)); - r->Assign(3, new Val(s.mem, TYPE_COUNT)); - r->Assign(4, new Val(s.hits, TYPE_COUNT)); - r->Assign(5, new Val(s.misses, TYPE_COUNT)); - r->Assign(6, new Val(s.avg_nfa_states, TYPE_COUNT)); - - return r; - %} - -function get_gap_summary%(%): gap_info - %{ - RecordVal* r = new RecordVal(gap_info); - r->Assign(0, new Val(tot_ack_events, TYPE_COUNT)); - r->Assign(1, new Val(tot_ack_bytes, TYPE_COUNT)); - r->Assign(2, new Val(tot_gap_events, TYPE_COUNT)); - r->Assign(3, new Val(tot_gap_bytes, TYPE_COUNT)); - - return r; - %} - -function val_size%(v: any%): count - %{ - return new Val(v->MemoryAllocation(), TYPE_COUNT); - %} - -function global_sizes%(%): var_sizes - %{ - TableVal* sizes = new TableVal(var_sizes); - PDict(ID)* globals = global_scope()->Vars(); - IterCookie* c = globals->InitForIteration(); - - ID* id; - while ( (id = globals->NextEntry(c)) ) - if ( id->HasVal() && ! id->IsInternalGlobal() ) - { - Val* id_name = new StringVal(id->Name()); - Val* id_size = new Val(id->ID_Val()->MemoryAllocation(), - TYPE_COUNT); - sizes->Assign(id_name, id_size); - Unref(id_name); - } - - return sizes; - %} - -function global_ids%(%): id_table - %{ - TableVal* ids = new TableVal(id_table); - PDict(ID)* globals = global_scope()->Vars(); - IterCookie* c = globals->InitForIteration(); - - ID* id; - while ( (id = globals->NextEntry(c)) ) - { - if ( id->IsInternalGlobal() ) - continue; - - RecordVal* rec = new RecordVal(script_id); - rec->Assign(0, new StringVal(type_name(id->Type()->Tag()))); - rec->Assign(1, new Val(id->IsExport(), TYPE_BOOL)); - rec->Assign(2, new Val(id->IsConst(), TYPE_BOOL)); - rec->Assign(3, new Val(id->IsEnumConst(), TYPE_BOOL)); - rec->Assign(4, new Val(id->IsRedefinable(), TYPE_BOOL)); - - if ( id->HasVal() ) - { - Val* val = id->ID_Val(); - Ref(val); - rec->Assign(5, val); - } - - Val* id_name = new StringVal(id->Name()); - ids->Assign(id_name, rec); - Unref(id_name); - } - - return ids; - %} - -function record_fields%(rec: any%): record_field_table - %{ - TableVal* fields = new TableVal(record_field_table); - - RecordVal* rv = rec->AsRecordVal(); - RecordType* rt = rv->Type()->AsRecordType(); - - if ( rt->Tag() != TYPE_RECORD ) - { - reporter->Error("non-record passed to record_fields"); - return fields; - } - - for ( int i = 0; i < rt->NumFields(); ++i ) - { - BroType* ft = rt->FieldType(i); - TypeDecl* fd = rt->FieldDecl(i); - Val* fv = rv->Lookup(i); - - if ( fv ) - Ref(fv); - - bool logged = (fd->attrs && fd->FindAttr(ATTR_LOG) != 0); - - RecordVal* nr = new RecordVal(record_field); - nr->Assign(0, new StringVal(type_name(rt->Tag()))); - nr->Assign(1, new Val(logged, TYPE_BOOL)); - nr->Assign(2, fv); - nr->Assign(3, rt->FieldDefault(i)); - - Val* field_name = new StringVal(rt->FieldName(i)); - fields->Assign(field_name, nr); - Unref(field_name); - } - - return fields; - %} - -%%{ -#include "Anon.h" -%%} - -# Preserve prefix as original one in anonymization. -function preserve_prefix%(a: addr, width: count%): any - %{ - AnonymizeIPAddr* ip_anon = ip_anonymizer[PREFIX_PRESERVING_A50]; - if ( ip_anon ) - { -#ifdef BROv6 - if ( ! is_v4_addr(a) ) - builtin_error("preserve_prefix() not supported for IPv6 addresses"); - else - ip_anon->PreservePrefix(a[3], width); -#else - ip_anon->PreservePrefix(a, width); -#endif - } - - - return 0; - %} - -function preserve_subnet%(a: subnet%): any - %{ - DEBUG_MSG("%s/%d\n", dotted_addr(a->AsAddr()), a->Width()); - AnonymizeIPAddr* ip_anon = ip_anonymizer[PREFIX_PRESERVING_A50]; - if ( ip_anon ) - { -#ifdef BROv6 - if ( ! is_v4_addr(a->AsAddr()) ) - builtin_error("preserve_subnet() not supported for IPv6 addresses"); - else - ip_anon->PreservePrefix(a->AsAddr()[3], a->Width()); -#else - ip_anon->PreservePrefix(a->AsAddr(), a->Width()); -#endif - } - - return 0; - %} - -# Anonymize given IP address. -function anonymize_addr%(a: addr, cl: IPAddrAnonymizationClass%): addr - %{ - int anon_class = cl->InternalInt(); - if ( anon_class < 0 || anon_class >= NUM_ADDR_ANONYMIZATION_CLASSES ) - builtin_error("anonymize_addr(): invalid ip addr anonymization class"); - -#ifdef BROv6 - if ( ! is_v4_addr(a) ) - { - builtin_error("anonymize_addr() not supported for IPv6 addresses"); - return 0; - } - else - return new AddrVal(anonymize_ip(a[3], - (enum ip_addr_anonymization_class_t) anon_class)); -#else - return new AddrVal(anonymize_ip(a, - (enum ip_addr_anonymization_class_t) anon_class)); -#endif - %} - %%{ static void hash_md5_val(val_list& vlist, unsigned char digest[16]) { @@ -1748,6 +560,17 @@ static void hmac_md5_val(val_list& vlist, unsigned char digest[16]) } %%} +## Computes the MD5 hash value of the provided list of arguments. +## +## Returns: The MD5 hash value of the concatenated arguments. +## +## .. bro:see:: md5_hmac md5_hash_init md5_hash_update md5_hash_finish +## +## .. note:: +## +## This function performs a one-shot computation of its arguments. +## For incremental hash computation, see :bro:id:`md5_hash_init` and +## friends. function md5_hash%(...%): string %{ unsigned char digest[16]; @@ -1755,6 +578,13 @@ function md5_hash%(...%): string return new StringVal(md5_digest_print(digest)); %} +## Computes an HMAC-MD5 hash value of the provided list of arguments. The HMAC +## secret key is generated from available entropy when Bro starts up, or it can +## be specified for repeatability using the ``-K`` command line flag. +## +## Returns: The HMAC-MD5 hash value of the concatenated arguments. +## +## .. bro:see:: md5_hash md5_hash_init md5_hash_update md5_hash_finish function md5_hmac%(...%): string %{ unsigned char digest[16]; @@ -1775,6 +605,20 @@ BroString* convert_index_to_string(Val* index) } %%} +## Initializes MD5 state to enable incremental hash computation. After +## initializing the MD5 state with this function, you can feed data to +## :bro:id:`md5_hash_update` and finally need to call :bro:id:`md5_hash_finish` +## to finish the computation and get the final hash value. +## +## For example, when computing incremental MD5 values of transferred files in +## multiple concurrent HTTP connections, one would call ``md5_hash_init(c$id)`` +## once before invoking ``md5_hash_update(c$id, some_more_data)`` in the +## :bro:id:`http_entity_data` event handler. When all data has arrived, a call +## to :bro:id:`md5_hash_finish` returns the final hash value. +## +## index: The unique identifier to associate with this hash computation. +## +## .. bro:see:: md5_hash md5_hmac md5_hash_update md5_hash_finish function md5_hash_init%(index: any%): bool %{ BroString* s = convert_index_to_string(index); @@ -1792,6 +636,15 @@ function md5_hash_init%(index: any%): bool return new Val(status, TYPE_BOOL); %} +## Update the MD5 value associated with a given index. It is required to +## call :bro:id:`md5_hash_init` once before calling this +## function. +## +## index: The unique identifier to associate with this hash computation. +## +## data: The data to add to the hash computation. +## +## .. bro:see:: md5_hash md5_hmac md5_hash_init md5_hash_finish function md5_hash_update%(index: any, data: string%): bool %{ BroString* s = convert_index_to_string(index); @@ -1807,6 +660,13 @@ function md5_hash_update%(index: any, data: string%): bool return new Val(status, TYPE_BOOL); %} +## Returns the final MD5 digest of an incremental hash computation. +## +## index: The unique identifier of this hash computation. +## +## Returns: The hash value associated with the computation at *index*. +## +## .. bro:see:: md5_hash md5_hmac md5_hash_init md5_hash_update function md5_hash_finish%(index: any%): string %{ BroString* s = convert_index_to_string(index); @@ -1826,7 +686,18 @@ function md5_hash_finish%(index: any%): string return printable_digest; %} -# Wrappings for rand() and srand() +## Generates a random number. +## +## max: The maximum value the random number. +## +## Returns: a random positive integer in the interval *[0, max)*. +## +## .. bro:see:: srand +## +## .. note:: +## +## This function is a wrapper about the function ``rand`` provided by +## the OS. function rand%(max: count%): count %{ int result; @@ -1834,547 +705,333 @@ function rand%(max: count%): count return new Val(result, TYPE_COUNT); %} +## Sets the seed for subsequent :bro:id:`rand` calls. +## +## seed: The seed for the PRNG. +## +## .. bro:see:: rand +## +## .. note:: +## +## This function is a wrapper about the function ``srand`` provided +## by the OS. function srand%(seed: count%): any %{ srand(seed); return 0; %} -function decode_base64%(s: string%): string +%%{ +#include +%%} + +## Send a string to syslog. +## +## s: The string to log via syslog +function syslog%(s: string%): any %{ - BroString* t = decode_base64(s->AsString()); - if ( t ) - return new StringVal(t); - else - { - reporter->Error("error in decoding string %s", @ARG@[0]); - return new StringVal(""); - } + reporter->Syslog("%s", s->CheckString()); + return 0; %} %%{ -#include "DCE_RPC.h" - -typedef struct { - uint32 time_low; - uint16 time_mid; - uint16 time_hi_and_version; - uint8 clock_seq_hi_and_reserved; - uint8 clock_seq_low; - uint8 node[6]; -} bro_uuid_t; +extern "C" { +#include +} %%} -function uuid_to_string%(uuid: string%): string +## Determines the MIME type of a piece of data using ``libmagic``. +## +## data: The data to find the MIME type for. +## +## return_mime: If true, the function returns a short MIME type string (e.g., +## ``text/plain`` instead of a more elaborate textual description. +## +## Returns: The MIME type of *data*. +function identify_data%(data: string, return_mime: bool%): string %{ - if ( uuid->Len() != 16 ) - return new StringVal(""); + const char* descr = ""; - bro_uuid_t* id = (bro_uuid_t*) uuid->Bytes(); + static magic_t magic_mime = 0; + static magic_t magic_descr = 0; - static char s[1024]; - char* sp = s; + magic_t* magic = return_mime ? &magic_mime : &magic_descr; - sp += snprintf(sp, s + sizeof(s) - sp, - "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", - id->time_low, id->time_mid, id->time_hi_and_version, - id->clock_seq_hi_and_reserved, id->clock_seq_low, - id->node[0], - id->node[1], - id->node[2], - id->node[3], - id->node[4], - id->node[5]); - - return new StringVal(s); - %} - - -# The following functions convert strings into patterns at run-time. As the -# computed NFAs and DFAs cannot be cleanly deallocated (at least for now), -# they can only be used at initialization time. - -function merge_pattern%(p1: pattern, p2: pattern%): pattern - %{ - if ( bro_start_network_time != 0.0 ) + if( ! *magic ) { - builtin_error("merge_pattern can only be called at init time"); - return 0; + *magic = magic_open(return_mime ? MAGIC_MIME : MAGIC_NONE); + + if ( ! *magic ) + { + reporter->Error("can't init libmagic: %s", magic_error(*magic)); + return new StringVal(""); + } + + if ( magic_load(*magic, 0) < 0 ) + { + reporter->Error("can't load magic file: %s", magic_error(*magic)); + magic_close(*magic); + *magic = 0; + return new StringVal(""); + } } - RE_Matcher* re = new RE_Matcher(); - re->AddPat(p1->PatternText()); - re->AddPat(p2->PatternText()); - re->Compile(); - return new PatternVal(re); + descr = magic_buffer(*magic, data->Bytes(), data->Len()); + + return new StringVal(descr); %} %%{ -char* to_pat_str(int sn, const char* ss) - { - const char special_re_char[] = "^$-:\"\\/|*+?.(){}[]"; - - char* pat = new char[sn * 4 + 1]; - int pat_len = 0; - - for ( int i = 0; i < sn; ++i ) - { - if ( ! strchr(special_re_char, ss[i]) ) - pat[pat_len++] = ss[i]; - else - { - pat[pat_len++] = '\\'; - pat[pat_len++] = ss[i]; - } - } - pat[pat_len] = '\0'; - return pat; - } +#include +static map entropy_states; %%} -function convert_for_pattern%(s: string%): string +## Performs an entropy test on the given data. +## See http://www.fourmilab.ch/random. +## +## data: The data to compute the entropy for. +## +## Returns: The result of the entropy test, which contains the following +## fields. +## +## - ``entropy``: The information density expressed as a number of +## bits per character. +## +## - ``chi_square``: The chi-square test value expressed as an +## absolute number and a percentage which indicates how +## frequently a truly random sequence would exceed the value +## calculated, i.e., the degree to which the sequence tested is +## suspected of being non-random. +## +## If the percentage is greater than 99% or less than 1%, the +## sequence is almost certainly not random. If the percentage is +## between 99% and 95% or between 1% and 5%, the sequence is +## suspect. Percentages between 90\% and 95\% and 5\% and 10\% +## indicate the sequence is "almost suspect." +## +## - ``mean``: The arithmetic mean of all the bytes. If the data +## are close to random, it should be around 127.5. +## +## - ``monte_carlo_pi``: Each successive sequence of six bytes is +## used as 24-bit *x* and *y* coordinates within a square. If +## the distance of the randomly-generated point is less than the +## radius of a circle inscribed within the square, the six-byte +## sequence is considered a "hit." The percentage of hits can +## be used to calculate the value of pi. For very large streams +## the value will approach the correct value of pi if the +## sequence is close to random. +## +## - ``serial_correlation``: This quantity measures the extent to +## which each byte in the file depends upon the previous byte. +## For random sequences this value will be close to zero. +## +## .. bro:see:: entropy_test_init entropy_test_add entropy_test_finish +function find_entropy%(data: string%): entropy_test_result %{ - char* t = to_pat_str(s->Len(), (const char*)(s->Bytes())); - StringVal* ret = new StringVal(t); - delete [] t; - return ret; + double montepi, scc, ent, mean, chisq; + montepi = scc = ent = mean = chisq = 0.0; + RecordVal* ent_result = new RecordVal(entropy_test_result); + RandTest *rt = new RandTest(); + + rt->add((char*) data->Bytes(), data->Len()); + rt->end(&ent, &chisq, &mean, &montepi, &scc); + delete rt; + + ent_result->Assign(0, new Val(ent, TYPE_DOUBLE)); + ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE)); + ent_result->Assign(2, new Val(mean, TYPE_DOUBLE)); + ent_result->Assign(3, new Val(montepi, TYPE_DOUBLE)); + ent_result->Assign(4, new Val(scc, TYPE_DOUBLE)); + return ent_result; %} -function string_to_pattern%(s: string, convert: bool%): pattern +## Initializes data structures for incremental entropy calculation. +## +## index: An arbitrary unique value per distinct computation. +## +## Returns: True on success. +## +## .. bro:see:: find_entropy entropy_test_add entropy_test_finish +function entropy_test_init%(index: any%): bool %{ - if ( bro_start_network_time != 0.0 ) + BroString* s = convert_index_to_string(index); + int status = 0; + + if ( entropy_states.count(*s) < 1 ) { - builtin_error("string_to_pattern can only be called at init time"); - return 0; + entropy_states[*s] = new RandTest(); + status = 1; } - const char* ss = (const char*) (s->Bytes()); - int sn = s->Len(); - char* pat; + delete s; + return new Val(status, TYPE_BOOL); + %} + +## Adds data to an incremental entropy calculation. Before using this function, +## one needs to invoke :bro:id:`entropy_test_init`. +## +## data: The data to add to the entropy calculation. +## +## index: An arbitrary unique value that identifies a particular entropy +## computation. +## +## Returns: True on success. +## +## .. bro:see:: find_entropy entropy_test_add entropy_test_finish +function entropy_test_add%(index: any, data: string%): bool + %{ + BroString* s = convert_index_to_string(index); + int status = 0; + + if ( entropy_states.count(*s) > 0 ) + { + entropy_states[*s]->add((char*) data->Bytes(), data->Len()); + status = 1; + } + + delete s; + return new Val(status, TYPE_BOOL); + %} + +## Finishes an incremental entropy calculation. Before using this function, +## one needs to initialize the computation with :bro:id:`entropy_test_init` and +## add data to it via :bro:id:`entropy_test_add`. +## +## index: An arbitrary unique value that identifies a particular entropy +## computation. +## +## Returns: The result of the entropy test. See :bro:id:`find_entropy` for a +## description of the individual components. +## +## .. bro:see:: find_entropy entropy_test_init entropy_test_add +function entropy_test_finish%(index: any%): entropy_test_result + %{ + BroString* s = convert_index_to_string(index); + double montepi, scc, ent, mean, chisq; + montepi = scc = ent = mean = chisq = 0.0; + RecordVal* ent_result = new RecordVal(entropy_test_result); + + if ( entropy_states.count(*s) > 0 ) + { + RandTest *rt = entropy_states[*s]; + rt->end(&ent, &chisq, &mean, &montepi, &scc); + entropy_states.erase(*s); + delete rt; + } + + ent_result->Assign(0, new Val(ent, TYPE_DOUBLE)); + ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE)); + ent_result->Assign(2, new Val(mean, TYPE_DOUBLE)); + ent_result->Assign(3, new Val(montepi, TYPE_DOUBLE)); + ent_result->Assign(4, new Val(scc, TYPE_DOUBLE)); + + delete s; + return ent_result; + %} + +## Creates an identifier that is unique with high probability. +## +## prefix: A custom string prepended to the result. +## +## .. bro:see:: unique_id_from +function unique_id%(prefix: string%) : string + %{ + char tmp[20]; + uint64 uid = calculate_unique_id(UID_POOL_DEFAULT_SCRIPT); + return new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62, prefix->CheckString())); + %} + +## Creates an identifier that is unique with high probability. +## +## pool: A seed for determinism. +## +## prefix: A custom string prepended to the result. +## +## .. bro:see:: unique_id +function unique_id_from%(pool: int, prefix: string%) : string + %{ + pool += UID_POOL_CUSTOM_SCRIPT; // Make sure we don't conflict with internal pool. + + char tmp[20]; + uint64 uid = calculate_unique_id(pool); + return new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62, prefix->CheckString())); + %} + +# =========================================================================== +# +# Generic Programming +# +# =========================================================================== + +## Removes all elements from a set or table. +## +## v: The set or table +## +## Returns: The cleared set/table or 0 if *v* is not a set/table type. +function clear_table%(v: any%): any + %{ + if ( v->Type()->Tag() == TYPE_TABLE ) + v->AsTableVal()->RemoveAll(); + else + builtin_error("clear_table() requires a table/set argument"); + + return 0; + %} + +## Returns the number of elements in a container. This function works with all +## container types, i.e., sets, tables, and vectors. +## +## v: The container whose elements are counted. +## +## Returns: The number of elements in *v*. +function length%(v: any%): count + %{ + TableVal* tv = v->Type()->Tag() == TYPE_TABLE ? v->AsTableVal() : 0; + + if ( tv ) + return new Val(tv->Size(), TYPE_COUNT); + + else if ( v->Type()->Tag() == TYPE_VECTOR ) + return new Val(v->AsVectorVal()->Size(), TYPE_COUNT); - if ( convert ) - pat = to_pat_str(sn, ss); else { - pat = new char[sn+1]; - memcpy(pat, ss, sn); - pat[sn] = '\0'; + builtin_error("length() requires a table/set/vector argument"); + return new Val(0, TYPE_COUNT); } - - RE_Matcher* re = new RE_Matcher(pat); - delete [] pat; - re->Compile(); - return new PatternVal(re); %} -# Precompile a pcap filter. -function precompile_pcap_filter%(id: PcapFilterID, s: string%): bool +## Checks whether two objects reference the same internal object. This function +## uses equality comparison of C++ raw pointer values to determine if the two +## objects are the same. +## +## o1: The first object. +## +## o2: The second object. +## +## Returns: True if *o1* and *o2* are equal. +function same_object%(o1: any, o2: any%): bool %{ - bool success = true; - - loop_over_list(pkt_srcs, i) - { - pkt_srcs[i]->ClearErrorMsg(); - - if ( ! pkt_srcs[i]->PrecompileFilter(id->ForceAsInt(), - s->CheckString()) ) - { - reporter->Error( "precompile_pcap_filter: %s", - pkt_srcs[i]->ErrorMsg() ); - success = false; - } - } - - return new Val(success, TYPE_BOOL); + return new Val(o1 == o2, TYPE_BOOL); %} -# Install precompiled pcap filter. -function install_pcap_filter%(id: PcapFilterID%): bool +## Returns the number bytes that a value occupies in memory. +## +## v: The value +## +## Returns: The number of bytes that *v* occupies. +function val_size%(v: any%): count %{ - bool success = true; - - loop_over_list(pkt_srcs, i) - { - pkt_srcs[i]->ClearErrorMsg(); - - if ( ! pkt_srcs[i]->SetFilter(id->ForceAsInt()) ) - success = false; - } - - return new Val(success, TYPE_BOOL); + return new Val(v->MemoryAllocation(), TYPE_COUNT); %} -# If last pcap function failed, returns a descriptive error message -function pcap_error%(%): string - %{ - loop_over_list(pkt_srcs, i) - { - const char* err = pkt_srcs[i]->ErrorMsg(); - if ( *err ) - return new StringVal(err); - } - - return new StringVal("no error"); - %} - -# Install filter to drop packets from a source (addr/subnet) with a given -# probability (0.0-1.0) if none of the given TCP flags is set. -function install_src_addr_filter%(ip: addr, tcp_flags: count, prob: double%) : bool - %{ - sessions->GetPacketFilter()->AddSrc(ip, tcp_flags, prob); - return new Val(1, TYPE_BOOL); - %} - -function install_src_net_filter%(snet: subnet, tcp_flags: count, prob: double%) : bool - %{ - sessions->GetPacketFilter()->AddSrc(snet, tcp_flags, prob); - return new Val(1, TYPE_BOOL); - %} - -# Remove the filter for the source. -function uninstall_src_addr_filter%(ip: addr%) : bool - %{ - return new Val(sessions->GetPacketFilter()->RemoveSrc(ip), TYPE_BOOL); - %} - -function uninstall_src_net_filter%(snet: subnet%) : bool - %{ - return new Val(sessions->GetPacketFilter()->RemoveSrc(snet), TYPE_BOOL); - %} - -# Same for destination. -function install_dst_addr_filter%(ip: addr, tcp_flags: count, prob: double%) : bool - %{ - sessions->GetPacketFilter()->AddDst(ip, tcp_flags, prob); - return new Val(1, TYPE_BOOL); - %} - -function install_dst_net_filter%(snet: subnet, tcp_flags: count, prob: double%) : bool - %{ - sessions->GetPacketFilter()->AddDst(snet, tcp_flags, prob); - return new Val(1, TYPE_BOOL); - %} - -function uninstall_dst_addr_filter%(ip: addr%) : bool - %{ - return new Val(sessions->GetPacketFilter()->RemoveDst(ip), TYPE_BOOL); - %} - -function uninstall_dst_net_filter%(snet: subnet%) : bool - %{ - return new Val(sessions->GetPacketFilter()->RemoveDst(snet), TYPE_BOOL); - %} - -function checkpoint_state%(%) : bool - %{ - return new Val(persistence_serializer->WriteState(true), TYPE_BOOL); - %} - -function dump_config%(%) : bool - %{ - return new Val(persistence_serializer->WriteConfig(true), TYPE_BOOL); - %} - -function rescan_state%(%) : bool - %{ - return new Val(persistence_serializer->ReadAll(false, true), TYPE_BOOL); - %} - -function capture_events%(filename: string%) : bool - %{ - if ( ! event_serializer ) - event_serializer = new FileSerializer(); - else - event_serializer->Close(); - - return new Val(event_serializer->Open( - (const char*) filename->CheckString()), TYPE_BOOL); - %} - -function capture_state_updates%(filename: string%) : bool - %{ - if ( ! state_serializer ) - state_serializer = new FileSerializer(); - else - state_serializer->Close(); - - return new Val(state_serializer->Open( - (const char*) filename->CheckString()), TYPE_BOOL); - %} - -function connect%(ip: addr, p: port, our_class: string, retry: interval, ssl: bool%) : count - %{ - return new Val(uint32(remote_serializer->Connect(ip, p->Port(), - our_class->CheckString(), retry, ssl)), - TYPE_COUNT); - %} - -function request_remote_events%(p: event_peer, handlers: pattern%) : bool - %{ - RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); - return new Val(remote_serializer->RequestEvents(id, handlers), - TYPE_BOOL); - %} - -function request_remote_sync%(p: event_peer, auth: bool%) : bool - %{ - RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); - return new Val(remote_serializer->RequestSync(id, auth), TYPE_BOOL); - %} - -function request_remote_logs%(p: event_peer%) : bool - %{ - RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); - return new Val(remote_serializer->RequestLogs(id), TYPE_BOOL); - %} - -function set_accept_state%(p: event_peer, accept: bool%) : bool - %{ - RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); - return new Val(remote_serializer->SetAcceptState(id, accept), - TYPE_BOOL); - %} - -function set_compression_level%(p: event_peer, level: count%) : bool - %{ - RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); - return new Val(remote_serializer->SetCompressionLevel(id, level), - TYPE_BOOL); - %} - -function listen%(ip: addr, p: port, ssl: bool %) : bool - %{ - return new Val(remote_serializer->Listen(ip, p->Port(), ssl), TYPE_BOOL); - %} - -function is_remote_event%(%) : bool - %{ - return new Val(mgr.CurrentSource() != SOURCE_LOCAL, TYPE_BOOL); - %} - -function send_state%(p: event_peer%) : bool - %{ - RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); - return new Val(persistence_serializer->SendState(id, true), TYPE_BOOL); - %} - -# Send the value of the given global ID to the peer (which might -# then install it locally). -function send_id%(p: event_peer, id: string%) : bool - %{ - RemoteSerializer::PeerID pid = p->AsRecordVal()->Lookup(0)->AsCount(); - - ID* i = global_scope()->Lookup(id->CheckString()); - if ( ! i ) - { - reporter->Error(fmt("send_id: no global id %s", id->CheckString())); - return new Val(0, TYPE_BOOL); - } - - SerialInfo info(remote_serializer); - return new Val(remote_serializer->SendID(&info, pid, *i), TYPE_BOOL); - %} - -# Gracely shut down communication. -function terminate_communication%(%) : bool - %{ - return new Val(remote_serializer->Terminate(), TYPE_BOOL); - %} - -function complete_handshake%(p: event_peer%) : bool - %{ - RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); - return new Val(remote_serializer->CompleteHandshake(id), TYPE_BOOL); - %} - -function send_ping%(p: event_peer, seq: count%) : bool - %{ - RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); - return new Val(remote_serializer->SendPing(id, seq), TYPE_BOOL); - %} - -function send_current_packet%(p: event_peer%) : bool - %{ - Packet pkt(""); - - if ( ! current_pktsrc || - ! current_pktsrc->GetCurrentPacket(&pkt.hdr, &pkt.pkt) ) - return new Val(0, TYPE_BOOL); - - RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); - - pkt.time = pkt.hdr->ts.tv_sec + double(pkt.hdr->ts.tv_usec) / 1e6; - pkt.hdr_size = current_pktsrc->HdrSize(); - pkt.link_type = current_pktsrc->LinkType(); - - SerialInfo info(remote_serializer); - return new Val(remote_serializer->SendPacket(&info, id, pkt), TYPE_BOOL); - %} - -function do_profiling%(%) : bool - %{ - if ( profiling_logger ) - profiling_logger->Log(); - - return new Val(1, TYPE_BOOL); - %} - -function get_event_peer%(%) : event_peer - %{ - SourceID src = mgr.CurrentSource(); - - if ( src == SOURCE_LOCAL ) - { - RecordVal* p = mgr.GetLocalPeerVal(); - Ref(p); - return p; - } - - if ( ! remote_serializer ) - reporter->InternalError("remote_serializer not initialized"); - - Val* v = remote_serializer->GetPeerVal(src); - if ( ! v ) - { - reporter->Error(fmt("peer %d does not exist anymore", int(src))); - RecordVal* p = mgr.GetLocalPeerVal(); - Ref(p); - return p; - } - - return v; - %} - -function get_local_event_peer%(%) : event_peer - %{ - RecordVal* p = mgr.GetLocalPeerVal(); - Ref(p); - return p; - %} - - -function send_capture_filter%(p: event_peer, s: string%) : bool - %{ - RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); - return new Val(remote_serializer->SendCaptureFilter(id, s->CheckString()), TYPE_BOOL); - %} - -function make_connection_persistent%(c: connection%) : bool - %{ - c->MakePersistent(); - return new Val(1, TYPE_BOOL); - %} - -function is_local_interface%(ip: addr%) : bool - %{ - static uint32* addrs; - static int len = -1; - - if ( len < 0 ) - { - char host[MAXHOSTNAMELEN]; - - strcpy(host, "localhost"); - gethostname(host, MAXHOSTNAMELEN); - host[MAXHOSTNAMELEN-1] = '\0'; - - struct hostent* ent = gethostbyname(host); - - for ( len = 0; ent->h_addr_list[len]; ++len ) - ; - - addrs = new uint32[len + 1]; - for ( int i = 0; i < len; i++ ) - addrs[i] = *(uint32*) ent->h_addr_list[i]; - - addrs[len++] = 0x0100007f; // 127.0.0.1 - } - -#ifdef BROv6 - if ( ! is_v4_addr(ip) ) - { - builtin_error("is_local_interface() only supports IPv4 addresses"); - return new Val(0, TYPE_BOOL); - } - - uint32 ip4 = to_v4_addr(ip); -#else - uint32 ip4 = ip; -#endif - - for ( int i = 0; i < len; i++ ) - if ( addrs[i] == ip4 ) - return new Val(1, TYPE_BOOL); - - return new Val(0, TYPE_BOOL); - %} - -function dump_current_packet%(file_name: string%) : bool - %{ - const struct pcap_pkthdr* hdr; - const u_char* pkt; - - if ( ! current_pktsrc || - ! current_pktsrc->GetCurrentPacket(&hdr, &pkt) ) - return new Val(0, TYPE_BOOL); - - if ( ! addl_pkt_dumper ) - addl_pkt_dumper = new PktDumper(0, true); - - addl_pkt_dumper->Open(file_name->CheckString()); - addl_pkt_dumper->Dump(hdr, pkt); - - return new Val(! addl_pkt_dumper->IsError(), TYPE_BOOL); - %} - -function get_current_packet%(%) : pcap_packet - %{ - const struct pcap_pkthdr* hdr; - const u_char* data; - RecordVal* pkt = new RecordVal(pcap_packet); - - if ( ! current_pktsrc || - ! current_pktsrc->GetCurrentPacket(&hdr, &data) ) - { - pkt->Assign(0, new Val(0, TYPE_COUNT)); - pkt->Assign(1, new Val(0, TYPE_COUNT)); - pkt->Assign(2, new Val(0, TYPE_COUNT)); - pkt->Assign(3, new Val(0, TYPE_COUNT)); - pkt->Assign(4, new StringVal("")); - return pkt; - } - - pkt->Assign(0, new Val(uint32(hdr->ts.tv_sec), TYPE_COUNT)); - pkt->Assign(1, new Val(uint32(hdr->ts.tv_usec), TYPE_COUNT)); - pkt->Assign(2, new Val(hdr->caplen, TYPE_COUNT)); - pkt->Assign(3, new Val(hdr->len, TYPE_COUNT)); - pkt->Assign(4, new StringVal(hdr->caplen, (const char*) data)); - - return pkt; - %} - -function dump_packet%(pkt: pcap_packet, file_name: string%) : bool - %{ - struct pcap_pkthdr hdr; - const val_list* pkt_vl = pkt->AsRecord(); - - hdr.ts.tv_sec = (*pkt_vl)[0]->AsCount(); - hdr.ts.tv_usec = (*pkt_vl)[1]->AsCount(); - hdr.caplen = (*pkt_vl)[2]->AsCount(); - hdr.len = (*pkt_vl)[3]->AsCount(); - - if ( ! addl_pkt_dumper ) - addl_pkt_dumper = new PktDumper(0, true); - - addl_pkt_dumper->Open(file_name->CheckString()); - addl_pkt_dumper->Dump(&hdr, (*pkt_vl)[4]->AsString()->Bytes()); - - return new Val(addl_pkt_dumper->IsError(), TYPE_BOOL); - %} - -# The return value is the old size of the vector. -# ### Need better type checking on the argument here and in subsequent -# vector builtins -- probably need to update "bif" code generator. +## Resizes a vector. +## +## aggr: The vector instance. +## +## newsize: The new size of *aggr*. +## +## Returns: The old size of *aggr* and 0 if *aggr* is not a :bro:type:`vector`. function resize%(aggr: any, newsize: count%) : count %{ if ( aggr->Type()->Tag() != TYPE_VECTOR ) @@ -2386,7 +1043,14 @@ function resize%(aggr: any, newsize: count%) : count return new Val(aggr->AsVectorVal()->Resize(newsize), TYPE_COUNT); %} -# Returns true if any element is T. +## Tests whether a boolean vector (``vector of bool``) has *any* true +## element. +## +## v: The boolean vector instance. +## +## Returns: True if any element in *v* is true. +## +## .. bro:see:: all_set function any_set%(v: any%) : bool %{ if ( v->Type()->Tag() != TYPE_VECTOR || @@ -2404,7 +1068,18 @@ function any_set%(v: any%) : bool return new Val(false, TYPE_BOOL); %} -# Returns true if all elements are T (missing counts as F). +## Tests whether *all* elements of a boolean vector (``vector of bool``) are +## true. +## +## v: The boolean vector instance. +## +## Returns: True iff all elements in *v* are true. +## +## .. bro:see:: any_set +## +## .. note:: +## +## Missing elements count as false. function all_set%(v: any%) : bool %{ if ( v->Type()->Tag() != TYPE_VECTOR || @@ -2422,9 +1097,6 @@ function all_set%(v: any%) : bool return new Val(true, TYPE_BOOL); %} -# sort() takes a vector and comparison function on the elements and -# sorts the vector in place. It returns the original vector. - %%{ static Func* sort_function_comp = 0; static Val** index_map = 0; // used for indirect sorting to support order() @@ -2475,6 +1147,16 @@ bool indirect_int_sort_function(int a, int b) } %%} +## Sorts a vector in place. The second argument is a comparison function that +## takes two arguments: if the vector type is \verb|vector of T|, then the +## comparison function must be ``function(a: T, b: T): bool``, which returns +## ``a < b`` for some type-specific notion of the less-than operator. +## +## v: The vector instance to sort. +## +## Returns: The original vector. +## +## .. bro:see:: order function sort%(v: any, ...%) : any %{ v->Ref(); // we always return v @@ -2528,6 +1210,15 @@ function sort%(v: any, ...%) : any return v; %} +## Returns the order of the elements in a vector according to some +## comparison function. See :bro:id:`sort` for details about the comparison +## function. +## +## v: The vector whose order to compute. +## +## Returns: A ``vector of count`` with the indices of the ordered elements. +## +## .. bro:see:: sort function order%(v: any, ...%) : index_vec %{ VectorVal* result_v = @@ -2605,65 +1296,696 @@ function order%(v: any, ...%) : index_vec return result_v; %} -%%{ -// Experimental code to add support for IDMEF XML output based on -// notices. For now, we're implementing it as a builtin you can call on an -// notices record. +# =========================================================================== +# +# String Processing +# +# =========================================================================== -#ifdef USE_IDMEF -extern "C" { -#include -} -#endif - -#include - -char* port_to_string(PortVal* port) - { - char buf[256]; // to hold sprintf results on port numbers - snprintf(buf, sizeof(buf), "%u", port->Port()); - return copy_string(buf); - } - -%%} - -function generate_idmef%(src_ip: addr, src_port: port, - dst_ip: addr, dst_port: port%) : bool +## Returns the concatenation of the string representation of its arguments. The +## arguments can be of any type. For example, ``cat("foo", 3, T)`` returns +## ``"foo3T"``. +## +## Returns: A string concatentation of all arguments. +function cat%(...%): string %{ -#ifdef USE_IDMEF - xmlNodePtr message = - newIDMEF_Message(newAttribute("version","1.0"), - newAlert(newCreateTime(NULL), - newSource( - newNode(newAddress( - newAttribute("category","ipv4-addr"), - newSimpleElement("address", - copy_string(dotted_addr(src_ip))), - NULL), NULL), - newService( - newSimpleElement("port", - port_to_string(src_port)), - NULL), NULL), - newTarget( - newNode(newAddress( - newAttribute("category","ipv4-addr"), - newSimpleElement("address", - copy_string(dotted_addr(dst_ip))), - NULL), NULL), - newService( - newSimpleElement("port", - port_to_string(dst_port)), - NULL), NULL), NULL), NULL); + ODesc d; + loop_over_list(@ARG@, i) + @ARG@[i]->Describe(&d); - // if ( validateCurrentDoc() ) - printCurrentMessage(stderr); - return new Val(1, TYPE_BOOL); -#else - builtin_error("Bro was not configured for IDMEF support"); - return new Val(0, TYPE_BOOL); -#endif + BroString* s = new BroString(1, d.TakeBytes(), d.Len()); + s->SetUseFreeToDelete(true); + + return new StringVal(s); %} +## Concatenates all arguments, with a separator placed between each one. This +## function is similar to :bro:id:`cat`, but places a separator between each +## given argument. If any of the variable arguments is an empty string it is +## replaced by a given default string instead. +## +## sep: The separator to place betwen each argument. +## +## def: The default string to use when an argument is the empty string. +## +## Returns: A concatenation of all arguments with *sep* between each one and +## empty strings replaced with *def*. +## +## .. bro:see:: cat string_cat cat_string_array cat_string_array_n +function cat_sep%(sep: string, def: string, ...%): string + %{ + ODesc d; + int pre_size = 0; + + loop_over_list(@ARG@, i) + { + // Skip named parameters. + if ( i < 2 ) + continue; + + if ( i > 2 ) + d.Add(sep->CheckString(), 0); + + Val* v = @ARG@[i]; + if ( v->Type()->Tag() == TYPE_STRING && ! v->AsString()->Len() ) + v = def; + + v->Describe(&d); + } + + BroString* s = new BroString(1, d.TakeBytes(), d.Len()); + s->SetUseFreeToDelete(true); + + return new StringVal(s); + %} + +## Produces a formatted string à la ``printf``. The first argument is the +## *format string* and specifies how subsequent arguments are converted for +## output. It is composed of zero or more directives: ordinary characters (not +## ``%``), which are copied unchanged to the output, and conversion +## specifications, each of which fetches zero or more subsequent arguments. +## Conversion specifications begin with ``%`` and the arguments must properly +## correspond to the specifier. After the ``%``, the following characters +## may appear in sequence: +## +## - ``%``: Literal ``%`` +## +## - ``-``: Left-align field +## +## - ``[0-9]+``: The field width (< 128) +## +## - ``.``: Precision of floating point specifiers ``[efg]`` (< 128) +## +## - ``A``: Escape NUL bytes, i.e., replace ``0`` with ``\0`` +## +## - ``[DTdxsefg]``: Format specifier +## +## - ``[DT]``: ISO timestamp with microsecond precision +## +## - ``d``: Signed/Unsigned integer (using C-style ``%lld|``/``%llu`` +## for ``int``/``count``) +## +## - ``x``: Unsigned hexadecimal (using C-style ``%llx``); +## addresses/ports are converted to host-byte order +## +## - ``s``: Escaped string +## +## - ``[efg]``: Double +## +## Returns: Given no arguments, :bro:id:`fmt` returns an empty string. Given a +## non-string first argument, :bro:id:`fmt` returns the concatenation +## of all its arguments, per :bro:id:`cat`. Finally, given the wrong +## number of additional arguments for the given format specifier, +## :bro:id:`fmt` generates a run-time error. +## +## .. bro:see:: cat cat_sep string_cat cat_string_array cat_string_array_n +function fmt%(...%): string + %{ + if ( @ARGC@ == 0 ) + return new StringVal(""); + + Val* fmt_v = @ARG@[0]; + if ( fmt_v->Type()->Tag() != TYPE_STRING ) + return bro_cat(frame, @ARGS@); + + const char* fmt = fmt_v->AsString()->CheckString(); + ODesc d; + int n = 0; + + while ( next_fmt(fmt, @ARGS@, &d, n) ) + ; + + if ( n < @ARGC@ - 1 ) + builtin_error("too many arguments for format", fmt_v); + + else if ( n >= @ARGC@ ) + builtin_error("too few arguments for format", fmt_v); + + BroString* s = new BroString(1, d.TakeBytes(), d.Len()); + s->SetUseFreeToDelete(true); + + return new StringVal(s); + %} + +# =========================================================================== +# +# Math +# +# =========================================================================== + +## Chops off any decimal digits of the given double, i.e., computes the +## "floor" of it. For example, ``floor(3.14)`` returns ``3.0``. +## +## d: The :bro:type:`double` to manipulate. +## +## Returns: The next lowest integer of *d* as :bro:type:`double`. +## +## .. bro:see:: sqrt exp ln log10 +function floor%(d: double%): double + %{ + return new Val(floor(d), TYPE_DOUBLE); + %} + +## Computes the square root of a :bro:type:`double`. +## +## x: The number to compute the square root of. +## +## Returns: The square root of *x*. +## +## .. bro:see:: floor exp ln log10 +function sqrt%(x: double%): double + %{ + if ( x < 0 ) + { + reporter->Error("negative sqrt argument"); + return new Val(-1.0, TYPE_DOUBLE); + } + + return new Val(sqrt(x), TYPE_DOUBLE); + %} + +## Computes the exponential function. +## +## d: The argument to the exponential function. +## +## Returns: *e* to the power of *d*. +## +## .. bro:see:: floor sqrt ln log10 +function exp%(d: double%): double + %{ + return new Val(exp(d), TYPE_DOUBLE); + %} + +## Computes the natural logarithm of a number. +## +## d: The argument to the logarithm. +## +## Returns: The natural logarithm of *d*. +## +## .. bro:see:: exp floor sqrt log10 +function ln%(d: double%): double + %{ + return new Val(log(d), TYPE_DOUBLE); + %} + +## Computes the common logarithm of a number. +## +## d: The argument to the logarithm. +## +## Returns: The common logarithm of *d*. +## +## .. bro:see:: exp floor sqrt ln +function log10%(d: double%): double + %{ + return new Val(log10(d), TYPE_DOUBLE); + %} + +# =========================================================================== +# +# Introspection +# +# =========================================================================== + +## Determines whether *c* has been received externally. For example, +## Broccoli or the Time Machine can send packets to Bro via a mechanism that +## one step lower than sending events. This function checks whether the packets +## of a connection stem from one of these external *packet sources*. +## +## c: The connection to test. +## +## Returns: True if *c* has been received externally. +function is_external_connection%(c: connection%) : bool + %{ + return new Val(c && c->IsExternal(), TYPE_BOOL); + %} + +## Returns the ID of the analyzer which raised the current event. +## +## Returns: The ID of the analyzer which raised hte current event, or 0 if +## none. +function current_analyzer%(%) : count + %{ + return new Val(mgr.CurrentAnalyzer(), TYPE_COUNT); + %} + +## Returns Bro's process ID. +## +## Returns: Bro's process ID. +function getpid%(%) : count + %{ + return new Val(getpid(), TYPE_COUNT); + %} + +%%{ +extern const char* bro_version(); +%%} + +## Returns the Bro version string. +## +## Returns: Bro's version, e.g., 2.0-beta-47-debug. +function bro_version%(%): string + %{ + return new StringVal(bro_version()); + %} + +## Converts a record type name to a vector of strings, where each element is +## the name of a record field. Nested records are flattened. +## +## rt: The name of the record type. +## +## Returns: A string vector with the field names of *rt*. +function record_type_to_vector%(rt: string%): string_vec + %{ + VectorVal* result = + new VectorVal(internal_type("string_vec")->AsVectorType()); + + RecordType *type = internal_type(rt->CheckString())->AsRecordType(); + + if ( type ) + { + for ( int i = 0; i < type->NumFields(); ++i ) + { + StringVal* val = new StringVal(type->FieldName(i)); + result->Assign(i+1, val, 0); + } + } + + return result; + %} + +## Returns the type name of an arbitrary Bro variable. +## +## t: An arbitrary object. +## +## Returns: The type name of *t*. +function type_name%(t: any%): string + %{ + ODesc d; + t->Type()->Describe(&d); + + BroString* s = new BroString(1, d.TakeBytes(), d.Len()); + s->SetUseFreeToDelete(true); + + return new StringVal(s); + %} + +## Checks whether Bro reads traffic from one or more network interfaces (as +## opposed to from a network trace in a file). Note that this function returns +## true even after Bro has stopped reading network traffic, for example due to +## receiving a termination signal. +## +## Returns: True if reading traffic from a network interface. +## +## .. bro:see:: reading_traces +function reading_live_traffic%(%): bool + %{ + return new Val(reading_live, TYPE_BOOL); + %} + +## Checks whether Bro reads traffic from a trace file (as opposed to from a +## network interface). +## +## Returns: True if reading traffic from a network trace. +## +## .. bro:see:: reading_live_traffic +function reading_traces%(%): bool + %{ + return new Val(reading_traces, TYPE_BOOL); + %} + +## Returns statistics about the number of packets *(i)* received by Bro, +## *(ii)* dropped, and *(iii)* seen on the link (not always available). +## +## Returns: A record of packet statistics. +## +## .. bro:see:: do_profiling +## resource_usage +## get_matcher_stats +## dump_rule_stats +## get_gap_summary +function net_stats%(%): NetStats + %{ + unsigned int recv = 0; + unsigned int drop = 0; + unsigned int link = 0; + + loop_over_list(pkt_srcs, i) + { + PktSrc* ps = pkt_srcs[i]; + + struct PktSrc::Stats stat; + ps->Statistics(&stat); + recv += stat.received; + drop += stat.dropped; + link += stat.link; + } + + RecordVal* ns = new RecordVal(net_stats); + ns->Assign(0, new Val(recv, TYPE_COUNT)); + ns->Assign(1, new Val(drop, TYPE_COUNT)); + ns->Assign(2, new Val(link, TYPE_COUNT)); + + return ns; + %} + +## Returns Bro process statistics, such as real/user/sys CPU time, memory +## usage, page faults, number of TCP/UDP/ICMP connections, timers, and events +## queued/dispatched. +## +## Returns: A record with resource usage statistics. +## +## .. bro:see:: do_profiling +## net_stats +## get_matcher_stats +## dump_rule_stats +## get_gap_summary +function resource_usage%(%): bro_resources + %{ + struct rusage r; + + if ( getrusage(RUSAGE_SELF, &r) < 0 ) + reporter->InternalError("getrusage() failed in bro_resource_usage()"); + + double elapsed_time = current_time() - bro_start_time; + + double user_time = + double(r.ru_utime.tv_sec) + double(r.ru_utime.tv_usec) / 1e6; + double system_time = + double(r.ru_stime.tv_sec) + double(r.ru_stime.tv_usec) / 1e6; + + RecordVal* res = new RecordVal(bro_resources); + int n = 0; + + res->Assign(n++, new StringVal(bro_version())); + +#ifdef DEBUG + res->Assign(n++, new Val(1, TYPE_COUNT)); +#else + res->Assign(n++, new Val(0, TYPE_COUNT)); +#endif + + res->Assign(n++, new Val(bro_start_time, TYPE_TIME)); + + res->Assign(n++, new IntervalVal(elapsed_time, Seconds)); + res->Assign(n++, new IntervalVal(user_time, Seconds)); + res->Assign(n++, new IntervalVal(system_time, Seconds)); + + unsigned int total_mem; + get_memory_usage(&total_mem, 0); + res->Assign(n++, new Val(unsigned(total_mem), TYPE_COUNT)); + + res->Assign(n++, new Val(unsigned(r.ru_minflt), TYPE_COUNT)); + res->Assign(n++, new Val(unsigned(r.ru_majflt), TYPE_COUNT)); + res->Assign(n++, new Val(unsigned(r.ru_nswap), TYPE_COUNT)); + res->Assign(n++, new Val(unsigned(r.ru_inblock), TYPE_COUNT)); + res->Assign(n++, new Val(unsigned(r.ru_oublock), TYPE_COUNT)); + res->Assign(n++, new Val(unsigned(r.ru_nivcsw), TYPE_COUNT)); + + SessionStats s; + if ( sessions ) + sessions->GetStats(s); + +#define ADD_STAT(x) \ + res->Assign(n++, new Val(unsigned(sessions ? x : 0), TYPE_COUNT)); + + ADD_STAT(s.num_TCP_conns); + ADD_STAT(s.num_UDP_conns); + ADD_STAT(s.num_ICMP_conns); + ADD_STAT(s.num_fragments); + ADD_STAT(s.num_packets); + ADD_STAT(s.num_timers); + ADD_STAT(s.num_events_queued); + ADD_STAT(s.num_events_dispatched); + ADD_STAT(s.max_TCP_conns); + ADD_STAT(s.max_UDP_conns); + ADD_STAT(s.max_ICMP_conns); + ADD_STAT(s.max_fragments); + ADD_STAT(s.max_timers); + + return res; + %} + +## Returns statistics about the regular expression engine, such as the number +## of distinct matchers, DFA states, DFA state transitions, memory usage of +## DFA states, cache hits/misses, and average number of NFA states across all +## matchers. +## +## Returns: A record with matcher statistics. +## +## .. bro:see:: do_profiling +## net_stats +## resource_usage +## dump_rule_stats +## get_gap_summary +function get_matcher_stats%(%): matcher_stats + %{ + RuleMatcher::Stats s; + memset(&s, 0, sizeof(s)); + + if ( rule_matcher ) + rule_matcher->GetStats(&s); + + RecordVal* r = new RecordVal(matcher_stats); + r->Assign(0, new Val(s.matchers, TYPE_COUNT)); + r->Assign(1, new Val(s.dfa_states, TYPE_COUNT)); + r->Assign(2, new Val(s.computed, TYPE_COUNT)); + r->Assign(3, new Val(s.mem, TYPE_COUNT)); + r->Assign(4, new Val(s.hits, TYPE_COUNT)); + r->Assign(5, new Val(s.misses, TYPE_COUNT)); + r->Assign(6, new Val(s.avg_nfa_states, TYPE_COUNT)); + + return r; + %} + +## Returns statistics about TCP gaps. +## +## Returns: A record with TCP gap statistics. +## +## .. bro:see:: do_profiling +## net_stats +## resource_usage +## dump_rule_stats +## get_matcher_stats +function get_gap_summary%(%): gap_info + %{ + RecordVal* r = new RecordVal(gap_info); + r->Assign(0, new Val(tot_ack_events, TYPE_COUNT)); + r->Assign(1, new Val(tot_ack_bytes, TYPE_COUNT)); + r->Assign(2, new Val(tot_gap_events, TYPE_COUNT)); + r->Assign(3, new Val(tot_gap_bytes, TYPE_COUNT)); + + return r; + %} + +## Generates a table of the size of all global variables. The table index is +## the variable name and the value the variable size in bytes. +## +## Returns: A table that maps variable names to their sizes. +## +## .. bro:see:: global_ids +function global_sizes%(%): var_sizes + %{ + TableVal* sizes = new TableVal(var_sizes); + PDict(ID)* globals = global_scope()->Vars(); + IterCookie* c = globals->InitForIteration(); + + ID* id; + while ( (id = globals->NextEntry(c)) ) + if ( id->HasVal() && ! id->IsInternalGlobal() ) + { + Val* id_name = new StringVal(id->Name()); + Val* id_size = new Val(id->ID_Val()->MemoryAllocation(), + TYPE_COUNT); + sizes->Assign(id_name, id_size); + Unref(id_name); + } + + return sizes; + %} + +## Generates a table with information about all global identifiers. The table +## value is a record containing the type name of the identifier, whether it is +## exported, a constant, an enum constant, redefinable, and its value (if it +## has one). +## +## Returns: A table that maps identifier names to information about them. +## +## .. bro:see:: global_sizes +function global_ids%(%): id_table + %{ + TableVal* ids = new TableVal(id_table); + PDict(ID)* globals = global_scope()->Vars(); + IterCookie* c = globals->InitForIteration(); + + ID* id; + while ( (id = globals->NextEntry(c)) ) + { + if ( id->IsInternalGlobal() ) + continue; + + RecordVal* rec = new RecordVal(script_id); + rec->Assign(0, new StringVal(type_name(id->Type()->Tag()))); + rec->Assign(1, new Val(id->IsExport(), TYPE_BOOL)); + rec->Assign(2, new Val(id->IsConst(), TYPE_BOOL)); + rec->Assign(3, new Val(id->IsEnumConst(), TYPE_BOOL)); + rec->Assign(4, new Val(id->IsRedefinable(), TYPE_BOOL)); + + if ( id->HasVal() ) + { + Val* val = id->ID_Val(); + Ref(val); + rec->Assign(5, val); + } + + Val* id_name = new StringVal(id->Name()); + ids->Assign(id_name, rec); + Unref(id_name); + } + + return ids; + %} + +## Returns the value of a global identifier. +## +## id: The global identifier. +## +## Returns the value of *id*. If *id* does not describe a valid identifier, the +## function returns the string ``""`` or ``""``. +function lookup_ID%(id: string%) : any + %{ + ID* i = global_scope()->Lookup(id->CheckString()); + if ( ! i ) + return new StringVal(""); + + if ( ! i->ID_Val() ) + return new StringVal(""); + + return i->ID_Val()->Ref(); + %} + +## Generates meta data about a record fields. The returned information +## includes the field name, whether it is logged, its value (if it has one), +## and its default value (if specified). +## +## rec: The record to inspect. +## +## Returns: A table that describes the fields of a record. +function record_fields%(rec: any%): record_field_table + %{ + TableVal* fields = new TableVal(record_field_table); + + RecordVal* rv = rec->AsRecordVal(); + RecordType* rt = rv->Type()->AsRecordType(); + + if ( rt->Tag() != TYPE_RECORD ) + { + reporter->Error("non-record passed to record_fields"); + return fields; + } + + for ( int i = 0; i < rt->NumFields(); ++i ) + { + BroType* ft = rt->FieldType(i); + TypeDecl* fd = rt->FieldDecl(i); + Val* fv = rv->Lookup(i); + + if ( fv ) + Ref(fv); + + bool logged = (fd->attrs && fd->FindAttr(ATTR_LOG) != 0); + + RecordVal* nr = new RecordVal(record_field); + nr->Assign(0, new StringVal(type_name(rt->Tag()))); + nr->Assign(1, new Val(logged, TYPE_BOOL)); + nr->Assign(2, fv); + nr->Assign(3, rt->FieldDefault(i)); + + Val* field_name = new StringVal(rt->FieldName(i)); + fields->Assign(field_name, nr); + Unref(field_name); + } + + return fields; + %} + +## Enables detailed collections of statistics about CPU/memory usage, +## connections, TCP states/reassembler, DNS lookups, timers, and script-level +## state. The script variable :bro:id:`profiling_file` holds the name of the +## file. +## +## .. bro:see:: net_stats +## resource_usage +## get_matcher_stats +## dump_rule_stats +## get_gap_summary +function do_profiling%(%) : any + %{ + if ( profiling_logger ) + profiling_logger->Log(); + + return 0; + %} + +## Checks whether a given IP address belongs to a local interface. +## +## ip: The IP address to check. +## +## Returns: True if *ip* belongs to a local interface. +function is_local_interface%(ip: addr%) : bool + %{ + if ( ip->AsAddr().IsLoopback() ) + return new Val(1, TYPE_BOOL); + + list addrs; + + char host[MAXHOSTNAMELEN]; + + strcpy(host, "localhost"); + gethostname(host, MAXHOSTNAMELEN); + host[MAXHOSTNAMELEN-1] = '\0'; + + struct hostent* ent = gethostbyname2(host, AF_INET); + + if ( ent ) + { + for ( unsigned int len = 0; ent->h_addr_list[len]; ++len ) + addrs.push_back(IPAddr(IPv4, (uint32*)ent->h_addr_list[len], + IPAddr::Network)); + } + + ent = gethostbyname2(host, AF_INET6); + + if ( ent ) + { + for ( unsigned int len = 0; ent->h_addr_list[len]; ++len ) + addrs.push_back(IPAddr(IPv6, (uint32*)ent->h_addr_list[len], + IPAddr::Network)); + } + + list::const_iterator it; + for ( it = addrs.begin(); it != addrs.end(); ++it ) + { + if ( *it == ip->AsAddr() ) + return new Val(1, TYPE_BOOL); + } + + return new Val(0, TYPE_BOOL); + %} + +## Write rule matcher statistics (DFA states, transitions, memory usage, cache +## hits/misses) to a file. +## +## f: The file to write to. +## +## Returns: True (unconditionally). +## +## .. bro:see:: do_profiling +## resource_usage +## get_matcher_stats +## net_stats +## get_gap_summary +## +## .. todo:: The return value should be changed to any or check appropriately. function dump_rule_stats%(f: file%): bool %{ if ( rule_matcher ) @@ -2672,90 +1994,990 @@ function dump_rule_stats%(f: file%): bool return new Val(1, TYPE_BOOL); %} +## Checks wheter Bro is terminating. +## +## Returns: True if Bro is in the process of shutting down. +## +## .. bro:see: terminate function bro_is_terminating%(%): bool %{ return new Val(terminating, TYPE_BOOL); %} -function rotate_file%(f: file%): rotate_info +## Returns the hostname of the machine Bro runs on. +## +## Returns: The hostname of the machine Bro runs on. +function gethostname%(%) : string %{ - RecordVal* info = f->Rotate(); - if ( info ) - return info; + char buffer[MAXHOSTNAMELEN]; + if ( gethostname(buffer, MAXHOSTNAMELEN) < 0 ) + strcpy(buffer, ""); - // Record indicating error. - info = new RecordVal(rotate_info); - info->Assign(0, new StringVal("")); - info->Assign(1, new StringVal("")); - info->Assign(2, new Val(0, TYPE_TIME)); - info->Assign(3, new Val(0, TYPE_TIME)); - - return info; + buffer[MAXHOSTNAMELEN-1] = '\0'; + return new StringVal(buffer); %} -function rotate_file_by_name%(f: string%): rotate_info +## Returns whether an address is IPv4 or not. +## +## a: the address to check. +## +## Returns: true if *a* is an IPv4 address, else false. +function is_v4_addr%(a: addr%): bool %{ - RecordVal* info = new RecordVal(rotate_info); - - bool is_pkt_dumper = false; - bool is_addl_pkt_dumper = false; - - // Special case: one of current dump files. - if ( pkt_dumper && streq(pkt_dumper->FileName(), f->CheckString()) ) - { - is_pkt_dumper = true; - pkt_dumper->Close(); - } - - if ( addl_pkt_dumper && - streq(addl_pkt_dumper->FileName(), f->CheckString()) ) - { - is_addl_pkt_dumper = true; - addl_pkt_dumper->Close(); - } - - FILE* file = rotate_file(f->CheckString(), info); - if ( ! file ) - { - // Record indicating error. - info->Assign(0, new StringVal("")); - info->Assign(1, new StringVal("")); - info->Assign(2, new Val(0, TYPE_TIME)); - info->Assign(3, new Val(0, TYPE_TIME)); - return info; - } - - fclose(file); - - if ( is_pkt_dumper ) - { - info->Assign(2, new Val(pkt_dumper->OpenTime(), TYPE_TIME)); - pkt_dumper->Open(); - } - - if ( is_addl_pkt_dumper ) - info->Assign(2, new Val(addl_pkt_dumper->OpenTime(), TYPE_TIME)); - - return info; + if ( a->AsAddr().GetFamily() == IPv4 ) + return new Val(1, TYPE_BOOL); + else + return new Val(0, TYPE_BOOL); %} -function calc_next_rotate%(i: interval%) : interval +## Returns whether an address is IPv6 or not. +## +## a: the address to check. +## +## Returns: true if *a* is an IPv6 address, else false. +function is_v6_addr%(a: addr%): bool %{ - const char* base_time = log_rotate_base_time ? - log_rotate_base_time->AsString()->CheckString() : 0; - return new Val(calc_next_rotate(i, base_time), TYPE_INTERVAL); + if ( a->AsAddr().GetFamily() == IPv6 ) + return new Val(1, TYPE_BOOL); + else + return new Val(0, TYPE_BOOL); %} -function file_size%(f: string%) : double +# =========================================================================== +# +# Conversion +# +# =========================================================================== + +## Converts the *data* field of :bro:type:`ip6_routing` records that have +## *rtype* of 0 into a vector of addresses. +## +## s: The *data* field of an :bro:type:`ip6_routing` record that has +## an *rtype* of 0. +## +## Returns: The vector of addresses contained in the routing header data. +function routing0_data_to_addrs%(s: string%): addr_vec %{ - struct stat s; + VectorVal* rval = new VectorVal(new VectorType(base_type(TYPE_ADDR))); - if ( stat(f->CheckString(), &s) < 0 ) - return new Val(-1.0, TYPE_DOUBLE); + int len = s->Len(); + const u_char* bytes = s->Bytes(); + bytes += 4; // go past 32-bit reserved field + len -= 4; - return new Val(double(s.st_size), TYPE_DOUBLE); + if ( ( len % 16 ) != 0 ) + reporter->Warning("Bad ip6_routing data length: %d", s->Len()); + + while ( len > 0 ) + { + IPAddr a(IPv6, (const uint32*) bytes, IPAddr::Network); + rval->Assign(rval->Size(), new AddrVal(a), 0); + bytes += 16; + len -= 16; + } + + return rval; %} +## Converts a :bro:type:`addr` to a :bro:type:`index_vec`. +## +## a: The address to convert into a vector of counts. +## +## Returns: A vector containing the host-order address representation, +## four elements in size for IPv6 addresses, or one element for IPv4. +## +## .. bro:see:: counts_to_addr +function addr_to_counts%(a: addr%): index_vec + %{ + VectorVal* rval = new VectorVal(new VectorType(base_type(TYPE_COUNT))); + const uint32* bytes; + int len = a->AsAddr().GetBytes(&bytes); + + for ( int i = 0; i < len; ++i ) + rval->Assign(i, new Val(ntohl(bytes[i]), TYPE_COUNT), 0); + + return rval; + %} + +## Converts a :bro:type:`index_vec` to a :bro:type:`addr`. +## +## v: The vector containing host-order IP address representation, +## one element for IPv4 addresses, four elements for IPv6 addresses. +## +## Returns: An IP address. +## +## .. bro:see:: addr_to_counts +function counts_to_addr%(v: index_vec%): addr + %{ + if ( v->AsVector()->size() == 1 ) + { + return new AddrVal(htonl((*v->AsVector())[0]->AsCount())); + } + else if ( v->AsVector()->size() == 4 ) + { + uint32 bytes[4]; + for ( int i = 0; i < 4; ++i ) + bytes[i] = htonl((*v->AsVector())[i]->AsCount()); + return new AddrVal(bytes); + } + else + { + builtin_error("invalid vector size", @ARG@[0]); + uint32 bytes[4]; + memset(bytes, 0, sizeof(bytes)); + return new AddrVal(bytes); + } + %} + +## Converts a :bro:type:`string` to a :bro:type:`int`. +## +## str: The :bro:type:`string` to convert. +## +## Returns: The :bro:type:`string` *str* as :bro:type:`int`. +## +## .. bro:see:: to_addr to_port to_subnet +function to_int%(str: string%): int + %{ + const char* s = str->CheckString(); + char* end_s; + + long l = strtol(s, &end_s, 10); + int i = int(l); + +#if 0 + // Not clear we should complain. For example, is " 205 " + // a legal conversion? + if ( s[0] == '\0' || end_s[0] != '\0' ) + builtin_error("bad conversion to integer", @ARG@[0]); +#endif + + return new Val(i, TYPE_INT); + %} + + +## Converts a (positive) :bro:type:`int` to a :bro:type:`count`. +## +## n: The :bro:type:`int` to convert. +## +## Returns: The :bro:type:`int` *n* as unsigned integer or 0 if *n* < 0. +function int_to_count%(n: int%): count + %{ + if ( n < 0 ) + { + builtin_error("bad conversion to count", @ARG@[0]); + n = 0; + } + return new Val(n, TYPE_COUNT); + %} + +## Converts a :bro:type:`double` to a :bro:type:`count`. +## +## d: The :bro:type:`double` to convert. +## +## Returns: The :bro:type:`double` *d* as unsigned integer or 0 if *d* < 0.0. +## +## .. bro:see:: double_to_time +function double_to_count%(d: double%): count + %{ + if ( d < 0.0 ) + builtin_error("bad conversion to count", @ARG@[0]); + + return new Val(bro_uint_t(rint(d)), TYPE_COUNT); + %} + +## Converts a :bro:type:`string` to a :bro:type:`count`. +## +## str: The :bro:type:`string` to convert. +## +## Returns: The :bro:type:`string` *str* as unsigned integer or if in invalid +## format. +## +## .. bro:see:: to_addr to_int to_port to_subnet +function to_count%(str: string%): count + %{ + const char* s = str->CheckString(); + char* end_s; + + uint64 u = (uint64) strtoll(s, &end_s, 10); + + if ( s[0] == '\0' || end_s[0] != '\0' ) + { + builtin_error("bad conversion to count", @ARG@[0]); + u = 0; + } + + return new Val(u, TYPE_COUNT); + %} + +## Converts an :bro:type:`interval` to a :bro:type:`double`. +## +## i: The :bro:type:`interval` to convert. +## +## Returns: The :bro:type:`interval` *i* as :bro:type:`double`. +## +## .. bro:see:: double_to_interval +function interval_to_double%(i: interval%): double + %{ + return new Val(i, TYPE_DOUBLE); + %} + +## Converts a :bro:type:`time` value to a :bro:type:`double`. +## +## t: The :bro:type:`interval` to convert. +## +## Returns: The :bro:type:`time` value *t* as :bro:type:`double`. +## +## .. bro:see:: double_to_time +function time_to_double%(t: time%): double + %{ + return new Val(t, TYPE_DOUBLE); + %} + +## Converts a :bro:type:`time` value to a :bro:type:`double`. +## +## t: The :bro:type:`interval` to convert. +## +## Returns: The :bro:type:`time` value *t* as :bro:type:`double`. +## +## .. bro:see:: time_to_double double_to_count +function double_to_time%(d: double%): time + %{ + return new Val(d, TYPE_TIME); + %} + +## Converts a :bro:type:`double` to an :bro:type:`interval`. +## +## d: The :bro:type:`double` to convert. +## +## Returns: The :bro:type:`double` *d* as :bro:type:`interval`. +## +## .. bro:see:: interval_to_double +function double_to_interval%(d: double%): interval + %{ + return new Val(d, TYPE_INTERVAL); + %} + +## Converts a :bro:type:`port` to a :bro:type:`count`. +## +## p: The :bro:type:`port` to convert. +## +## Returns: The :bro:type:`port` *p* as :bro:type:`count`. +## +## .. bro:see:: count_to_port +function port_to_count%(p: port%): count + %{ + return new Val(p->Port(), TYPE_COUNT); + %} + +## Converts a :bro:type:`count` and ``transport_proto`` to a :bro:type:`port`. +## +## num: The :bro:type:`port` number. +## +## proto: The transport protocol. +## +## Returns: The :bro:type:`count` *c* as :bro:type:`port`. +## +## .. bro:see:: port_to_count +function count_to_port%(num: count, proto: transport_proto%): port + %{ + return new PortVal(num, (TransportProto)proto->AsEnum()); + %} + +## Converts a :bro:type:`string` to an :bro:type:`addr`. +## +## ip: The :bro:type:`string` to convert. +## +## Returns: The :bro:type:`string` *ip* as :bro:type:`addr` or the unspecified +## address ``::`` if the input string does not parse correctly. +## +## .. bro:see:: to_count to_int to_port count_to_v4_addr raw_bytes_to_v4_addr +## to_subnet +function to_addr%(ip: string%): addr + %{ + char* s = ip->AsString()->Render(); + Val* ret = new AddrVal(s); + delete [] s; + return ret; + %} + +## Converts a :bro:type:`string` to a :bro:type:`subnet`. +## +## sn: The subnet to convert. +## +## Returns: The *sn* string as a :bro:type:`subnet` or the unspecified subnet +## ``::/0`` if the input string does not parse correctly. +## +## .. bro:see:: to_count to_int to_port count_to_v4_addr raw_bytes_to_v4_addr +## to_addr +function to_subnet%(sn: string%): subnet + %{ + char* s = sn->AsString()->Render(); + Val* ret = new SubNetVal(s); + delete [] s; + return ret; + %} + +## Converts a :bro:type:`count` to an :bro:type:`addr`. +## +## ip: The :bro:type:`count` to convert. +## +## Returns: The :bro:type:`count` *ip* as :bro:type:`addr`. +## +## .. bro:see:: raw_bytes_to_v4_addr to_addr to_subnet +function count_to_v4_addr%(ip: count%): addr + %{ + if ( ip > 4294967295LU ) + { + builtin_error("conversion of non-IPv4 count to addr", @ARG@[0]); + return new AddrVal(uint32(0)); + } + + return new AddrVal(htonl(uint32(ip))); + %} + +## Converts a :bro:type:`string` of bytes into an IP address. In particular, +## this function interprets the first 4 bytes of the string as an IPv4 address +## in network order. +## +## b: The raw bytes (:bro:type:`string`) to convert. +## +## Returns: The byte :bro:type:`string` *ip* as :bro:type:`addr`. +## +## .. bro:see:: raw_bytes_to_v4_addr to_addr to_subnet +function raw_bytes_to_v4_addr%(b: string%): addr + %{ + uint32 a = 0; + + if ( b->Len() < 4 ) + builtin_error("too short a string as input to raw_bytes_to_v4_addr()"); + + else + { + const u_char* bp = b->Bytes(); + a = (bp[0] << 24) | (bp[1] << 16) | (bp[2] << 8) | bp[3]; + } + + return new AddrVal(htonl(a)); + %} + +## Converts a :bro:type:`string` to an :bro:type:`port`. +## +## s: The :bro:type:`string` to convert. +## +## Returns: A :bro:type:`port` converted from *s*. +## +## .. bro:see:: to_addr to_count to_int to_subnet +function to_port%(s: string%): port + %{ + int port = 0; + if ( s->Len() < 10 ) + { + char* slash; + port = strtol(s->CheckString(), &slash, 10); + if ( port ) + { + ++slash; + if ( streq(slash, "tcp") ) + return new PortVal(port, TRANSPORT_TCP); + else if ( streq(slash, "udp") ) + return new PortVal(port, TRANSPORT_UDP); + else if ( streq(slash, "icmp") ) + return new PortVal(port, TRANSPORT_ICMP); + } + } + + builtin_error("wrong port format, must be /[0-9]{1,5}\\/(tcp|udp|icmp)/"); + return new PortVal(port, TRANSPORT_UNKNOWN); + %} + +## Converts a reverse pointer name to an address. For example, +## ``1.0.168.192.in-addr.arpa`` to ``192.168.0.1``. +## +## s: The string with the reverse pointer name. +## +## Returns: The IP address corresponding to *s*. +## +## .. bro:see:: addr_to_ptr_name parse_dotted_addr +function ptr_name_to_addr%(s: string%): addr + %{ + if ( s->Len() != 72 ) + { + int a[4]; + uint32 addr; + char ss[13]; // this will contain "in-addr.arpa" + + if ( sscanf(s->CheckString(), + "%d.%d.%d.%d.%12s", + a, a+1, a+2, a+3, ss) != 5 + || strcmp(ss, "in-addr.arpa") != 0 ) + { + builtin_error("bad PTR name", @ARG@[0]); + addr = 0; + } + else + addr = (a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]; + + return new AddrVal(htonl(addr)); + } + else + { + uint32 addr6[4]; + uint32 b[32]; + char ss[9]; // this will contain "ip6.arpa" + if ( sscanf(s->CheckString(), + "%1x.%1x.%1x.%1x.%1x.%1x.%1x.%1x." + "%1x.%1x.%1x.%1x.%1x.%1x.%1x.%1x." + "%1x.%1x.%1x.%1x.%1x.%1x.%1x.%1x." + "%1x.%1x.%1x.%1x.%1x.%1x.%1x.%1x.%8s", + b+31, b+30, b+29, b+28, b+27, b+26, b+25, b+24, + b+23, b+22, b+21, b+20, b+19, b+18, b+17, b+16, + b+15, b+14, b+13, b+12, b+11, b+10, b+9, b+8, + b+7, b+6, b+5, b+4, b+3, b+2, b+1, b, ss) != 33 + || strcmp(ss, "ip6.arpa") != 0 ) + { + builtin_error("bad PTR name", @ARG@[0]); + memset(addr6, 0, sizeof addr6); + } + else + { + for ( unsigned int i = 0; i < 4; ++i ) + { + uint32 a = 0; + for ( unsigned int j = 1; j <= 8; ++j ) + a |= b[8*i+j-1] << (32-j*4); + + addr6[i] = htonl(a); + } + } + + return new AddrVal(addr6); + } + %} + +## Converts an IP address to a reverse pointer name. For example, +## ``192.168.0.1`` to ``1.0.168.192.in-addr.arpa``. +## +## a: The IP address to convert to a reverse pointer name. +## +## Returns: The reverse pointer representation of *a*. +## +## .. bro:see:: ptr_name_to_addr parse_dotted_addr +function addr_to_ptr_name%(a: addr%): string + %{ + return new StringVal(a->AsAddr().PtrName().c_str()); + %} + +# Transforms n0.n1.n2.n3 -> addr. + +## Converts a decimal dotted IP address in a :bro:type:`string` to an +## :bro:type:`addr` type. +## +## s: The IP address in the form ``n0.n1.n2.n3``. +## +## Returns: The IP address as type :bro:type:`addr`. +## +## .. bro:see:: addr_to_ptr_name parse_dotted_addr +function parse_dotted_addr%(s: string%): addr + %{ + IPAddr a(s->CheckString()); + return new AddrVal(a); + %} + +%%{ +static Val* parse_port(const char* line) + { + RecordVal* r = new RecordVal(ftp_port); + + int bytes[6]; + if ( line && sscanf(line, "%d,%d,%d,%d,%d,%d", + &bytes[0], &bytes[1], &bytes[2], + &bytes[3], &bytes[4], &bytes[5]) == 6 ) + { + int good = 1; + + for ( int i = 0; i < 6; ++i ) + if ( bytes[i] < 0 || bytes[i] > 255 ) + { + good = 0; + break; + } + + uint32 addr = (bytes[0] << 24) | (bytes[1] << 16) | + (bytes[2] << 8) | bytes[3]; + uint32 port = (bytes[4] << 8) | bytes[5]; + + // Since port is unsigned, no need to check for < 0. + if ( port > 65535 ) + { + port = 0; + good = 0; + } + + r->Assign(0, new AddrVal(htonl(addr))); + r->Assign(1, new PortVal(port, TRANSPORT_TCP)); + r->Assign(2, new Val(good, TYPE_BOOL)); + } + else + { + r->Assign(0, new AddrVal(uint32(0))); + r->Assign(1, new PortVal(0, TRANSPORT_TCP)); + r->Assign(2, new Val(0, TYPE_BOOL)); + } + + return r; + } + +static Val* parse_eftp(const char* line) + { + RecordVal* r = new RecordVal(ftp_port); + + int net_proto = 0; // currently not used + IPAddr addr; // unspecified IPv6 address (all 128 bits zero) + int port = 0; + int good = 0; + + if ( line ) + { + while ( isspace(*line) ) // skip whitespace + ++line; + + char delimiter = *line; + char* next_delim; + + if ( *line ) + { + good = 1; + ++line; // skip delimiter + + net_proto = strtol(line, &next_delim, 10); + if ( *next_delim != delimiter ) + good = 0; + + line = next_delim; + if ( *line ) + ++line; + + if ( *line && *line != delimiter ) + { + const char* nptr = strchr(line, delimiter); + if ( nptr == NULL ) + { + nptr = line + strlen(line); + good = 0; + } + + string s(line, nptr-line); // extract IP address + IPAddr tmp(s); + // on error, "tmp" will have all 128 bits zero + if ( tmp == addr ) + good = 0; + + addr = tmp; + } + + line = strchr(line, delimiter); + + if ( line != NULL ) + { + ++line; // now the port + port = strtol(line, &next_delim, 10); + if ( *next_delim != delimiter ) + good = 0; + } + + } + + } + + r->Assign(0, new AddrVal(addr)); + r->Assign(1, new PortVal(port, TRANSPORT_TCP)); + r->Assign(2, new Val(good, TYPE_BOOL)); + + return r; + } +%%} + +## Converts a string representation of the FTP PORT command to an ``ftp_port``. +## +## s: The string of the FTP PORT command, e.g., ``"10,0,0,1,4,31"``. +## +## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]`` +## +## .. bro:see:: parse_eftp_port parse_ftp_pasv parse_ftp_epsv fmt_ftp_port +function parse_ftp_port%(s: string%): ftp_port + %{ + return parse_port(s->CheckString()); + %} + +## Converts a string representation of the FTP EPRT command to an ``ftp_port``. +## (see `RFC 2428 `_). +## The format is ``EPRT``, +## where ```` is a delimiter in the ASCII range 33-126 (usually ``|``). +## +## s: The string of the FTP EPRT command, e.g., ``"|1|10.0.0.1|1055|"``. +## +## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]`` +## +## .. bro:see:: parse_ftp_port parse_ftp_pasv parse_ftp_epsv fmt_ftp_port +function parse_eftp_port%(s: string%): ftp_port + %{ + return parse_eftp(s->CheckString()); + %} + +## Converts the result of the FTP PASV command to an ``ftp_port``. +## +## str: The string containing the result of the FTP PASV command. +## +## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]`` +## +## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_epsv fmt_ftp_port +function parse_ftp_pasv%(str: string%): ftp_port + %{ + const char* s = str->CheckString(); + const char* line = strchr(s, '('); + if ( line ) + ++line; // move past '(' + else if ( (line = strstr(s, "PORT")) ) + line += 5; // Skip over + else if ( (line = strchr(s, ',')) ) + { // Look for comma-separated list. + while ( --line >= s && isdigit(*line) ) + ; // Back up over preceding digits. + ++line; // now points to first digit, or beginning of s + } + + return parse_port(line); + %} + +## Converts the result of the FTP EPSV command to an ``ftp_port``. +## See `RFC 2428 `_. +## The format is `` ()``, where ```` is a +## delimiter in the ASCII range 33-126 (usually ``|``). +## +## str: The string containing the result of the FTP EPSV command. +## +## Returns: The FTP PORT, e.g., ``[h=10.0.0.1, p=1055/tcp, valid=T]`` +## +## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv fmt_ftp_port +function parse_ftp_epsv%(str: string%): ftp_port + %{ + const char* s = str->CheckString(); + const char* line = strchr(s, '('); + if ( line ) + ++line; // move past '(' + return parse_eftp(line); + %} + +## Formats an IP address and TCP port as an FTP PORT command. For example, +## ``10.0.0.1`` and ``1055/tcp`` yields ``"10,0,0,1,4,31"``. +## +## a: The IP address. +## +## p: The TCP port. +## +## Returns: The FTP PORT string. +## +## .. bro:see:: parse_ftp_port parse_eftp_port parse_ftp_pasv parse_ftp_epsv +function fmt_ftp_port%(a: addr, p: port%): string + %{ + const uint32* addr; + int len = a->AsAddr().GetBytes(&addr); + if ( len == 1 ) + { + uint32 a = ntohl(addr[0]); + uint32 pn = p->Port(); + return new StringVal(fmt("%d,%d,%d,%d,%d,%d", + a >> 24, (a >> 16) & 0xff, + (a >> 8) & 0xff, a & 0xff, + pn >> 8, pn & 0xff)); + } + else + { + builtin_error("conversion of non-IPv4 address in fmt_ftp_port", + @ARG@[0]); + return new StringVal(""); + } + %} + +## Decode a NetBIOS name. See http://support.microsoft.com/kb/194203. +## +## name: The encoded NetBIOS name, e.g., ``"FEEIEFCAEOEFFEECEJEPFDCAEOEBENEF:``. +## +## Returns: The decoded NetBIOS name, e.g., ``"THE NETBIOS NAME"``. +## +## .. bro:see:: decode_netbios_name_type +function decode_netbios_name%(name: string%): string + %{ + char buf[16]; + char result[16]; + const u_char* s = name->Bytes(); + int i, j; + + for ( i = 0, j = 0; i < 16; ++i ) + { + char c0 = (j < name->Len()) ? toupper(s[j++]) : 'A'; + char c1 = (j < name->Len()) ? toupper(s[j++]) : 'A'; + buf[i] = ((c0 - 'A') << 4) + (c1 - 'A'); + } + + for ( i = 0; i < 15; ++i ) + { + if ( isalnum(buf[i]) || ispunct(buf[i]) || + // \x01\x02 is seen in at least one case as the first two bytes. + // I think that any \x01 and \x02 should always be passed through. + buf[i] < 3 ) + result[i] = buf[i]; + else + break; + } + + return new StringVal(i, result); + %} + +## Converts a NetBIOS name type to its corresonding numeric value. +## See http://support.microsoft.com/kb/163409. +## +## name: The NetBIOS name type. +## +## Returns: The numeric value of *name*. +## +## .. bro:see:: decode_netbios_name +function decode_netbios_name_type%(name: string%): count + %{ + const u_char* s = name->Bytes(); + char return_val = ((toupper(s[30]) - 'A') << 4) + (toupper(s[31]) - 'A'); + return new Val(return_val, TYPE_COUNT); + %} + +## Converts a string of bytes into its hexadecimal representation, e.g., +## ``"04"`` to ``"3034"``. +## +## bytestring: The string of bytes. +## +## Returns: The hexadecimal reprsentation of *bytestring*. +## +## .. bro:see:: hexdump +function bytestring_to_hexstr%(bytestring: string%): string + %{ + bro_uint_t len = bytestring->AsString()->Len(); + const u_char* bytes = bytestring->AsString()->Bytes(); + char hexstr[(2 * len) + 1]; + + hexstr[0] = 0; + for ( bro_uint_t i = 0; i < len; ++i ) + snprintf(hexstr + (2 * i), 3, "%.2hhx", bytes[i]); + + return new StringVal(hexstr); + %} + +## Decodes a Base64-encoded string. +## +## s: The Base64-encoded string. +## +## Returns: The decoded version of *s*. +## +## .. bro:see:: decode_base64_custom +function decode_base64%(s: string%): string + %{ + BroString* t = decode_base64(s->AsString()); + if ( t ) + return new StringVal(t); + else + { + reporter->Error("error in decoding string %s", s->CheckString()); + return new StringVal(""); + } + %} + +## Decodes a Base64-encoded string with a custom alphabet. +## +## s: The Base64-encoded string. +## +## a: The custom alphabet. The empty string indicates the default alphabet. The +## lengh of *a* must bt 64. For example, a custom alphabet could be +## ``"!#$%&/(),-.:;<>@[]^ `_{|}~abcdefghijklmnopqrstuvwxyz0123456789+?"``. +## +## Returns: The decoded version of *s*. +## +## .. bro:see:: decode_base64 +function decode_base64_custom%(s: string, a: string%): string + %{ + BroString* t = decode_base64(s->AsString(), a->AsString()); + if ( t ) + return new StringVal(t); + else + { + reporter->Error("error in decoding string %s", s->CheckString()); + return new StringVal(""); + } + %} + +%%{ +#include "DCE_RPC.h" + +typedef struct { + uint32 time_low; + uint16 time_mid; + uint16 time_hi_and_version; + uint8 clock_seq_hi_and_reserved; + uint8 clock_seq_low; + uint8 node[6]; +} bro_uuid_t; +%%} + +## Converts a bytes representation of a UUID into its string form. For example, +## given a string of 16 bytes, it produces an output string in this format: +## ``550e8400-e29b-41d4-a716-446655440000``. +## See ``_. +## +## uuid: The 16 bytes of the UUID. +## +## Returns: The string representation of *uuid*. +function uuid_to_string%(uuid: string%): string + %{ + if ( uuid->Len() != 16 ) + return new StringVal(""); + + bro_uuid_t* id = (bro_uuid_t*) uuid->Bytes(); + + static char s[1024]; + char* sp = s; + + sp += snprintf(sp, s + sizeof(s) - sp, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + id->time_low, id->time_mid, id->time_hi_and_version, + id->clock_seq_hi_and_reserved, id->clock_seq_low, + id->node[0], + id->node[1], + id->node[2], + id->node[3], + id->node[4], + id->node[5]); + + return new StringVal(s); + %} + +## Merges and compiles two regular expressions at initialization time. +## +## p1: The first pattern. +## +## p2: The second pattern. +## +## Returns: The compiled pattern of the concatentation of *p1* and *p2*. +## +## .. bro:see:: convert_for_pattern string_to_pattern +## +## .. note:: +## +## This function must be called at Bro startup time, e.g., in the event +## :bro:id:`bro_init`. +function merge_pattern%(p1: pattern, p2: pattern%): pattern + %{ + if ( bro_start_network_time != 0.0 ) + { + builtin_error("merge_pattern can only be called at init time"); + return 0; + } + + RE_Matcher* re = new RE_Matcher(); + re->AddPat(p1->PatternText()); + re->AddPat(p2->PatternText()); + re->Compile(); + return new PatternVal(re); + %} + +%%{ +char* to_pat_str(int sn, const char* ss) + { + const char special_re_char[] = "^$-:\"\\/|*+?.(){}[]"; + + char* pat = new char[sn * 4 + 1]; + int pat_len = 0; + + for ( int i = 0; i < sn; ++i ) + { + if ( ! strchr(special_re_char, ss[i]) ) + pat[pat_len++] = ss[i]; + else + { + pat[pat_len++] = '\\'; + pat[pat_len++] = ss[i]; + } + } + pat[pat_len] = '\0'; + return pat; + } +%%} + +## Escapes a string so that it becomes a valid :bro:type:`pattern` and can be +## used with the :bro:id:`string_to_pattern`. Any character from the set +## ``^$-:"\/|*+?.(){}[]`` is prefixed with a ``\``. +## +## s: The string to escape. +## +## Returns: An escaped version of *s* that has the structure of a valid +## :bro:type:`pattern`. +## +## .. bro:see:: merge_pattern string_to_pattern +## +function convert_for_pattern%(s: string%): string + %{ + char* t = to_pat_str(s->Len(), (const char*)(s->Bytes())); + StringVal* ret = new StringVal(t); + delete [] t; + return ret; + %} + +## Converts a :bro:type:`string` into a :bro:type:`pattern`. +## +## s: The string to convert. +## +## convert: If true, *s* is first passed through the function +## :bro:id:`convert_for_pattern` to escape special characters of +## patterns. +## +## Returns: *s* as :bro:type:`pattern`. +## +## .. bro:see:: convert_for_pattern merge_pattern +## +## .. note:: +## +## This function must be called at Bro startup time, e.g., in the event +## :bro:id:`bro_init`. +function string_to_pattern%(s: string, convert: bool%): pattern + %{ + if ( bro_start_network_time != 0.0 ) + { + builtin_error("string_to_pattern can only be called at init time"); + return 0; + } + + const char* ss = (const char*) (s->Bytes()); + int sn = s->Len(); + char* pat; + + if ( convert ) + pat = to_pat_str(sn, ss); + else + { + pat = new char[sn+1]; + memcpy(pat, ss, sn); + pat[sn] = '\0'; + } + + RE_Matcher* re = new RE_Matcher(pat); + delete [] pat; + re->Compile(); + return new PatternVal(re); + %} + +## Formats a given time value according to a format string. +## +## fmt: The format string. See ``man strftime`` for the syntax. +## +## d: The time value. +## +## Returns: The time *d* formatted according to *fmt*. function strftime%(fmt: string, d: time%) : string %{ static char buffer[128]; @@ -2768,27 +2990,369 @@ function strftime%(fmt: string, d: time%) : string return new StringVal(buffer); %} -function match_signatures%(c: connection, pattern_type: int, s: string, - bol: bool, eol: bool, - from_orig: bool, clear: bool%) : bool +# =========================================================================== +# +# Network Type Processing +# +# =========================================================================== + +## Masks an address down to the number of given upper bits. For example, +## ``mask_addr(1.2.3.4, 18)`` returns ``1.2.0.0``. +## +## a: The address to mask. +## +## top_bits_to_keep: The number of top bits to keep in *a*; must be greater +## than 0 and less than 33. +## +## Returns: The address *a* masked down to *top_bits_to_keep* bits. +## +## .. bro:see:: remask_addr +function mask_addr%(a: addr, top_bits_to_keep: count%): subnet %{ - if ( ! rule_matcher ) - return new Val(0, TYPE_BOOL); - - c->Match((Rule::PatternType) pattern_type, s->Bytes(), s->Len(), - from_orig, bol, eol, clear); - - return new Val(1, TYPE_BOOL); + return new SubNetVal(a->AsAddr(), top_bits_to_keep); %} -function gethostname%(%) : string +## Takes some top bits (e.g., subnet address) from one address and the other +## bits (intra-subnet part) from a second address and merges them to get a new +## address. This is useful for anonymizing at subnet level while preserving +## serial scans. +## +## a1: The address to mask with *top_bits_from_a1*. +## +## a2: The address to take the remaining bits from. +## +## top_bits_from_a1: The number of top bits to keep in *a1*; must be greater +## than 0 and less than 129. This value is always interpreted +## relative to the IPv6 bit width (v4-mapped addresses start +## at bit number 96). +## +## Returns: The address *a* masked down to *top_bits_to_keep* bits. +## +## .. bro:see:: mask_addr +function remask_addr%(a1: addr, a2: addr, top_bits_from_a1: count%): addr %{ - char buffer[MAXHOSTNAMELEN]; - if ( gethostname(buffer, MAXHOSTNAMELEN) < 0 ) - strcpy(buffer, ""); + IPAddr addr1(a1->AsAddr()); + addr1.Mask(top_bits_from_a1); + IPAddr addr2(a2->AsAddr()); + addr2.ReverseMask(top_bits_from_a1); + return new AddrVal(addr1|addr2); + %} - buffer[MAXHOSTNAMELEN-1] = '\0'; - return new StringVal(buffer); +## Checks whether a given :bro:type:`port` has TCP as transport protocol. +## +## p: The :bro:type:`port` to check. +## +## Returns: True iff *p* is a TCP port. +## +## .. bro:see:: is_udp_port is_icmp_port +function is_tcp_port%(p: port%): bool + %{ + return new Val(p->IsTCP(), TYPE_BOOL); + %} + +## Checks whether a given :bro:type:`port` has UDP as transport protocol. +## +## p: The :bro:type:`port` to check. +## +## Returns: True iff *p* is a UDP port. +## +## .. bro:see:: is_icmp_port is_tcp_port +function is_udp_port%(p: port%): bool + %{ + return new Val(p->IsUDP(), TYPE_BOOL); + %} + +## Checks whether a given :bro:type:`port` has ICMP as transport protocol. +## +## p: The :bro:type:`port` to check. +## +## Returns: True iff *p* is a ICMP port. +## +## .. bro:see:: is_tcp_port is_udp_port +function is_icmp_port%(p: port%): bool + %{ + return new Val(p->IsICMP(), TYPE_BOOL); + %} + +%%{ +EnumVal* map_conn_type(TransportProto tp) + { + switch ( tp ) { + case TRANSPORT_UNKNOWN: + return new EnumVal(0, transport_proto); + break; + + case TRANSPORT_TCP: + return new EnumVal(1, transport_proto); + break; + + case TRANSPORT_UDP: + return new EnumVal(2, transport_proto); + break; + + case TRANSPORT_ICMP: + return new EnumVal(3, transport_proto); + break; + + default: + reporter->InternalError("bad connection type in map_conn_type()"); + } + + // Cannot be reached; + assert(false); + return 0; // Make compiler happy. + } +%%} + +## Extracts the transport protocol from a connection. +## +## cid: The connection identifier. +## +## Returns: The transport protocol of the connection identified by *id*. +## +## .. bro:see:: get_port_transport_proto +## get_orig_seq get_resp_seq +function get_conn_transport_proto%(cid: conn_id%): transport_proto + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + { + builtin_error("unknown connection id in get_conn_transport_proto()", cid); + return new EnumVal(0, transport_proto); + } + + return map_conn_type(c->ConnTransport()); + %} + +## Extracts the transport protocol from a :bro:type:`port`. +## +## p: The port. +## +## Returns: The transport protocol of the port *p*. +## +## .. bro:see:: get_conn_transport_proto +## get_orig_seq get_resp_seq +function get_port_transport_proto%(p: port%): transport_proto + %{ + return map_conn_type(p->PortType()); + %} + +## Checks whether a connection is (still) active. +## +## c: The connection id to check. +## +## Returns: True if the connection identified by *c* exists. +## +## .. bro:see:: lookup_connection +function connection_exists%(c: conn_id%): bool + %{ + if ( sessions->FindConnection(c) ) + return new Val(1, TYPE_BOOL); + else + return new Val(0, TYPE_BOOL); + %} + +## Returns the :bro:type:`connection` record for a given connection identifier. +## +## cid: The connection ID. +## +## Returns: The :bro:type:`connection` record for *cid*. If *cid* does not point +## to an existing connection, the function generates a run-time error +## and returns a dummy value. +## +## .. bro:see:: connection_exists +function lookup_connection%(cid: conn_id%): connection + %{ + Connection* conn = sessions->FindConnection(cid); + if ( conn ) + return conn->BuildConnVal(); + + builtin_error("connection ID not a known connection", cid); + + // Return a dummy connection record. + RecordVal* c = new RecordVal(connection_type); + + RecordVal* id_val = new RecordVal(conn_id); + id_val->Assign(0, new AddrVal((unsigned int) 0)); + id_val->Assign(1, new PortVal(ntohs(0), TRANSPORT_UDP)); + id_val->Assign(2, new AddrVal((unsigned int) 0)); + id_val->Assign(3, new PortVal(ntohs(0), TRANSPORT_UDP)); + c->Assign(0, id_val); + + RecordVal* orig_endp = new RecordVal(endpoint); + orig_endp->Assign(0, new Val(0, TYPE_COUNT)); + orig_endp->Assign(1, new Val(int(0), TYPE_COUNT)); + + RecordVal* resp_endp = new RecordVal(endpoint); + resp_endp->Assign(0, new Val(0, TYPE_COUNT)); + resp_endp->Assign(1, new Val(int(0), TYPE_COUNT)); + + c->Assign(1, orig_endp); + c->Assign(2, resp_endp); + + c->Assign(3, new Val(network_time, TYPE_TIME)); + c->Assign(4, new Val(0.0, TYPE_INTERVAL)); + c->Assign(5, new TableVal(string_set)); // service + c->Assign(6, new StringVal("")); // addl + c->Assign(7, new Val(0, TYPE_COUNT)); // hot + c->Assign(8, new StringVal("")); // history + + return c; + %} + +%%{ +#include "HTTP.h" + +const char* conn_id_string(Val* c) + { + Val* id = (*(c->AsRecord()))[0]; + const val_list* vl = id->AsRecord(); + + const IPAddr& orig_h = (*vl)[0]->AsAddr(); + uint32 orig_p = (*vl)[1]->AsPortVal()->Port(); + const IPAddr& resp_h = (*vl)[2]->AsAddr(); + uint32 resp_p = (*vl)[3]->AsPortVal()->Port(); + + return fmt("%s/%u -> %s/%u\n", orig_h.AsString().c_str(), orig_p, + resp_h.AsString().c_str(), resp_p); + } +%%} + +## Skips the data of the HTTP entity. +## +## c: The HTTP connection. +## +## is_orig: If true, the client data is skipped and the server data otherwise. +## +## .. bro:see:: skip_smtp_data +function skip_http_entity_data%(c: connection, is_orig: bool%): any + %{ + AnalyzerID id = mgr.CurrentAnalyzer(); + if ( id ) + { + Analyzer* ha = c->FindAnalyzer(id); + + if ( ha ) + { + if ( ha->GetTag() == AnalyzerTag::HTTP ) + static_cast(ha)->SkipEntityData(is_orig); + else + reporter->Error("non-HTTP analyzer associated with connection record"); + } + else + reporter->Error("could not find analyzer for skip_http_entity_data"); + + } + else + reporter->Error("no analyzer associated with connection record"); + + return 0; + %} + +## Unescapes all characters in a URI, i.e., decodes every ``%xx`` group. +## +## URI: The URI to unescape. +## +## Returns: The unescaped URI with all ``%xx`` groups decoded. +## +## .. note:: +## +## Unescaping reserved characters may cause loss of information. RFC 2396: +## A URI is always in an "escaped" form, since escaping or unescaping a +## completed URI might change its semantics. Normally, the only time +## escape encodings can safely be made is when the URI is being created +## from its component parts. +function unescape_URI%(URI: string%): string + %{ + const u_char* line = URI->Bytes(); + const u_char* const line_end = line + URI->Len(); + + return new StringVal(unescape_URI(line, line_end, 0)); + %} + +## Writes the current packet to a file. +## +## file_name: The name of the file to write the packet to. +## +## Returns: True on success. +## +## .. bro:see:: dump_packet get_current_packet send_current_packet +function dump_current_packet%(file_name: string%) : bool + %{ + const struct pcap_pkthdr* hdr; + const u_char* pkt; + + if ( ! current_pktsrc || + ! current_pktsrc->GetCurrentPacket(&hdr, &pkt) ) + return new Val(0, TYPE_BOOL); + + if ( ! addl_pkt_dumper ) + addl_pkt_dumper = new PktDumper(0, true); + + addl_pkt_dumper->Open(file_name->CheckString()); + addl_pkt_dumper->Dump(hdr, pkt); + + return new Val(! addl_pkt_dumper->IsError(), TYPE_BOOL); + %} + +## Returns the currently processed PCAP packet. +## +## Returns: The currently processed packet, which is as a record +## containing the timestamp, ``snaplen``, and packet data. +## +## .. bro:see:: dump_current_packet dump_packet send_current_packet +function get_current_packet%(%) : pcap_packet + %{ + const struct pcap_pkthdr* hdr; + const u_char* data; + RecordVal* pkt = new RecordVal(pcap_packet); + + if ( ! current_pktsrc || + ! current_pktsrc->GetCurrentPacket(&hdr, &data) ) + { + pkt->Assign(0, new Val(0, TYPE_COUNT)); + pkt->Assign(1, new Val(0, TYPE_COUNT)); + pkt->Assign(2, new Val(0, TYPE_COUNT)); + pkt->Assign(3, new Val(0, TYPE_COUNT)); + pkt->Assign(4, new StringVal("")); + return pkt; + } + + pkt->Assign(0, new Val(uint32(hdr->ts.tv_sec), TYPE_COUNT)); + pkt->Assign(1, new Val(uint32(hdr->ts.tv_usec), TYPE_COUNT)); + pkt->Assign(2, new Val(hdr->caplen, TYPE_COUNT)); + pkt->Assign(3, new Val(hdr->len, TYPE_COUNT)); + pkt->Assign(4, new StringVal(hdr->caplen, (const char*) data)); + + return pkt; + %} + +## Writes a given packet to a file. +## +## pkt: The PCAP packet. +## +## file_name: The name of the file to write *pkt* to. +## +## Returns: True on success +## +## .. bro:see:: get_current_packet dump_current_packet send_current_packet +function dump_packet%(pkt: pcap_packet, file_name: string%) : bool + %{ + struct pcap_pkthdr hdr; + const val_list* pkt_vl = pkt->AsRecord(); + + hdr.ts.tv_sec = (*pkt_vl)[0]->AsCount(); + hdr.ts.tv_usec = (*pkt_vl)[1]->AsCount(); + hdr.caplen = (*pkt_vl)[2]->AsCount(); + hdr.len = (*pkt_vl)[3]->AsCount(); + + if ( ! addl_pkt_dumper ) + addl_pkt_dumper = new PktDumper(0, true); + + addl_pkt_dumper->Open(file_name->CheckString()); + addl_pkt_dumper->Dump(&hdr, (*pkt_vl)[4]->AsString()->Bytes()); + + return new Val(addl_pkt_dumper->IsError(), TYPE_BOOL); %} %%{ @@ -2814,13 +3378,15 @@ public: // Overridden from DNS_Mgr:Lookup:Callback. virtual void Resolved(const char* name) { - trigger->Cache(call, new StringVal(name)); + Val* result = new StringVal(name); + trigger->Cache(call, result); + Unref(result); trigger->Release(); } virtual void Resolved(TableVal* addrs) { - Ref(addrs); + // No Ref() for addrs. trigger->Cache(call, addrs); trigger->Release(); } @@ -2828,12 +3394,19 @@ public: virtual void Timeout() { if ( lookup_name ) - trigger->Cache(call, new StringVal("<\?\?\?>")); + { + Val* result = new StringVal("<\?\?\?>"); + trigger->Cache(call, result); + Unref(result); + } + else { ListVal* lv = new ListVal(TYPE_ADDR); lv->Append(new AddrVal("0.0.0.0")); - trigger->Cache(call, lv->ConvertToSet()); + Val* result = lv->ConvertToSet(); + trigger->Cache(call, result); + Unref(result); Unref(lv); } @@ -2847,8 +3420,15 @@ private: }; %%} -# These two functions issue DNS lookups asynchronously and delay the -# function result. Therefore, they can only be called inside a when-condition. +## Issues an asynchronous reverse DNS lookup and delays the function result. +## This function can therefore only be called inside a ``when`` condition, +## e.g., ``when ( local host = lookup_addr(10.0.0.1) ) { f(host); }``. +## +## host: The IP address to lookup. +## +## Returns: The DNS name of *host*. +## +## .. bro:see:: lookup_hostname function lookup_addr%(host: addr%) : string %{ // FIXME: It should be easy to adapt the function to synchronous @@ -2864,32 +3444,20 @@ function lookup_addr%(host: addr%) : string frame->SetDelayed(); trigger->Hold(); -#ifdef BROv6 - if ( ! is_v4_addr(host) ) - { - // FIXME: This is a temporary work-around until we get this - // fixed. We warn the user once, and always trigger a timeout. - // Ticket #355 records the problem. - static bool warned = false; - if ( ! warned ) - { - reporter->Warning("lookup_addr() only supports IPv4 addresses currently"); - warned = true; - } - - trigger->Timeout(); - return 0; - } - - dns_mgr->AsyncLookupAddr(to_v4_addr(host), + dns_mgr->AsyncLookupAddr(host->AsAddr(), new LookupHostCallback(trigger, frame->GetCall(), true)); -#else - dns_mgr->AsyncLookupAddr(host, - new LookupHostCallback(trigger, frame->GetCall(), true)); -#endif return 0; %} +## Issues an asynchronous DNS lookup and delays the function result. +## This function can therefore only be called inside a ``when`` condition, +## e.g., ``when ( local h = lookup_hostname("www.bro-ids.org") ) { f(h); }``. +## +## host: The hostname to lookup. +## +## Returns: A set of DNS A records associated with *host*. +## +## .. bro:see:: lookup_addr function lookup_hostname%(host: string%) : addr_set %{ // FIXME: Is should be easy to adapt the function to synchronous @@ -2910,204 +3478,133 @@ function lookup_hostname%(host: string%) : addr_set return 0; %} -# Stop Bro's packet processing. -function suspend_processing%(%) : any - %{ - net_suspend_processing(); - return 0; - %} - -# Resume Bro's packet processing. -function continue_processing%(%) : any - %{ - net_continue_processing(); - return 0; - %} - -%%{ -#include "DPM.h" -%%} - -# Schedule analyzer for a future connection. -function expect_connection%(orig: addr, resp: addr, resp_p: port, - analyzer: count, tout: interval%) : bool - %{ - dpm->ExpectConnection(orig, resp, resp_p->Port(), resp_p->PortType(), - (AnalyzerTag::Tag) analyzer, tout, 0); - return new Val(1, TYPE_BOOL); - %} - -# Disables the analyzer which raised the current event (if the analyzer -# belongs to the given connection). -function disable_analyzer%(cid: conn_id, aid: count%) : bool - %{ - Connection* c = sessions->FindConnection(cid); - if ( ! c ) - { - reporter->Error("cannot find connection"); - return new Val(0, TYPE_BOOL); - } - - Analyzer* a = c->FindAnalyzer(aid); - if ( ! a ) - { - reporter->Error("connection does not have analyzer specified to disable"); - return new Val(0, TYPE_BOOL); - } - - a->Remove(); - return new Val(1, TYPE_BOOL); - %} - -# Translate analyzer type into an ASCII string. -function analyzer_name%(aid: count%) : string - %{ - return new StringVal(Analyzer::GetTagName((AnalyzerTag::Tag) aid)); - %} - -function lookup_ID%(id: string%) : any - %{ - ID* i = global_scope()->Lookup(id->CheckString()); - if ( ! i ) - return new StringVal(""); - - if ( ! i->ID_Val() ) - return new StringVal(""); - - return i->ID_Val()->Ref(); - %} - -# Stop propagating &synchronized accesses. -function suspend_state_updates%(%) : any - %{ - if ( remote_serializer ) - remote_serializer->SuspendStateUpdates(); - return 0; - %} - -# Resume propagating &synchronized accesses. -function resume_state_updates%(%) : any - %{ - if ( remote_serializer ) - remote_serializer->ResumeStateUpdates(); - return 0; - %} - -# Return ID of analyzer which raised current event, or 0 if none. -function current_analyzer%(%) : count - %{ - return new Val(mgr.CurrentAnalyzer(), TYPE_COUNT); - %} - -# Returns Bro's process id. -function getpid%(%) : count - %{ - return new Val(getpid(), TYPE_COUNT); - %} -%%{ -#include -%%} - -function syslog%(s: string%): any - %{ - reporter->Syslog("%s", s->CheckString()); - return 0; - %} - %%{ #ifdef USE_GEOIP extern "C" { #include } + +static GeoIP* open_geoip_db(GeoIPDBTypes type) + { + GeoIP* geoip = 0; + + if ( GeoIP_db_avail(type) ) + geoip = GeoIP_open_type(type, GEOIP_MEMORY_CACHE); + + if ( ! geoip ) + reporter->Warning("Failed to open GeoIP database: %s", + GeoIPDBFileName[type]); + return geoip; + } + #endif %%} -# Return a record with the city, region, and country of an IPv4 address. +## Performs a geo-lookup of an IP address. +## Requires Bro to be built with ``libgeoip``. +## +## a: The IP address to lookup. +## +## Returns: A record with country, region, city, latitude, and longitude. +## +## .. bro:see:: lookup_asn function lookup_location%(a: addr%) : geo_location %{ RecordVal* location = new RecordVal(geo_location); #ifdef USE_GEOIP + static bool geoip_initialized = false; static GeoIP* geoip = 0; static GeoIP* geoip_v6 = 0; - static bool geoip_initialized = false; + static bool have_city_db = false; + static bool have_cityv6_db = false; GeoIPRecord* gir = 0; + const char* cc = 0; if ( ! geoip_initialized ) { geoip_initialized = true; - geoip = GeoIP_open_type(GEOIP_CITY_EDITION_REV0, - GEOIP_MEMORY_CACHE); + geoip = open_geoip_db(GEOIP_CITY_EDITION_REV0); + if ( ! geoip ) { - builtin_error("can't initialize GeoIP City database.. trying Country version"); - geoip = GeoIP_open_type(GEOIP_COUNTRY_EDITION, - GEOIP_MEMORY_CACHE); + geoip = open_geoip_db(GEOIP_COUNTRY_EDITION); if ( ! geoip ) - builtin_error("can't initialize GeoIP Country database"); + builtin_error("Can't initialize GeoIP City/Country database"); + else + reporter->Warning("Fell back to GeoIP Country database"); } + else + have_city_db = true; -#ifdef BROv6 -#ifdef GEOIP_COUNTRY_EDITION_V6 - geoip_v6 = GeoIP_open_type(GEOIP_COUNTRY_EDITION_V6, - GEOIP_MEMORY_CACHE); +#ifdef HAVE_GEOIP_CITY_EDITION_REV0_V6 + geoip_v6 = open_geoip_db(GEOIP_CITY_EDITION_REV0_V6); + if ( geoip_v6 ) + have_cityv6_db = true; +#endif + +#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6 if ( ! geoip_v6 ) - builtin_error("can't initialize the GeoIPv6 Country database"); -#endif + geoip_v6 = open_geoip_db(GEOIP_COUNTRY_EDITION_V6); #endif + if ( ! geoip_v6 ) + builtin_error("Can't initialize GeoIPv6 City/Country database"); } -#ifdef BROv6 -#ifdef GEOIP_COUNTRY_EDITION_V6 - if ( geoip_v6 && ! is_v4_addr(a) ) - gir = GeoIP_record_by_ipnum_v6(geoip_v6, geoipv6_t(a)); +#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6 + if ( geoip_v6 && a->AsAddr().GetFamily() == IPv6 ) + { + geoipv6_t ga; + a->AsAddr().CopyIPv6(&ga); + if ( have_cityv6_db ) + gir = GeoIP_record_by_ipnum_v6(geoip_v6, ga); + else + cc = GeoIP_country_code_by_ipnum_v6(geoip_v6, ga); + } else #endif - if ( geoip && is_v4_addr(a) ) + + if ( geoip && a->AsAddr().GetFamily() == IPv4 ) { - uint32 addr = to_v4_addr(a); - gir = GeoIP_record_by_ipnum(geoip, ntohl(addr)); + const uint32* bytes; + a->AsAddr().GetBytes(&bytes); + if ( have_city_db ) + gir = GeoIP_record_by_ipnum(geoip, ntohl(*bytes)); + else + cc = GeoIP_country_code_by_ipnum(geoip, ntohl(*bytes)); } -#else - if ( geoip ) - gir = GeoIP_record_by_ipnum(geoip, ntohl(a)); -#endif if ( gir ) { if ( gir->country_code ) location->Assign(0, new StringVal(gir->country_code)); - else - location->Assign(0, new StringVal("")); if ( gir->region ) location->Assign(1, new StringVal(gir->region)); - else - location->Assign(1, new StringVal("")); if ( gir->city ) location->Assign(2, new StringVal(gir->city)); - else - location->Assign(2, new StringVal("")); if ( gir->latitude ) location->Assign(3, new Val(gir->latitude, TYPE_DOUBLE)); - else - location->Assign(3, new Val(0.0, TYPE_DOUBLE)); if ( gir->longitude ) location->Assign(4, new Val(gir->longitude, TYPE_DOUBLE)); - else - location->Assign(4, new Val(0.0, TYPE_DOUBLE)); GeoIPRecord_delete(gir); return location; } -#else + else if ( cc ) + { + location->Assign(0, new StringVal(cc)); + return location; + } + +#else // not USE_GEOIP static int missing_geoip_reported = 0; if ( ! missing_geoip_reported ) @@ -3120,15 +3617,17 @@ function lookup_location%(a: addr%) : geo_location // We can get here even if we have GeoIP support if we weren't // able to initialize it or it didn't return any information for // the address. - location->Assign(0, new StringVal("")); - location->Assign(1, new StringVal("")); - location->Assign(2, new StringVal("")); - location->Assign(3, new Val(0.0, TYPE_DOUBLE)); - location->Assign(4, new Val(0.0, TYPE_DOUBLE)); return location; %} +## Performs an AS lookup of an IP address. +## +## a: The IP address to lookup. +## +## Returns: The number of the AS that contains *a*. +## +## .. bro:see:: lookup_location function lookup_asn%(a: addr%) : count %{ #ifdef USE_GEOIP @@ -3139,30 +3638,30 @@ function lookup_asn%(a: addr%) : count if ( ! geoip_asn_initialized ) { geoip_asn_initialized = true; - geoip_asn = GeoIP_open_type(GEOIP_ASNUM_EDITION, - GEOIP_MEMORY_CACHE); + geoip_asn = open_geoip_db(GEOIP_ASNUM_EDITION); if ( ! geoip_asn ) - builtin_error("can't initialize GeoIP ASNUM database"); + builtin_error("Can't initialize GeoIP ASNUM database"); } if ( geoip_asn ) { -#ifdef BROv6 - // IPv6 support showed up in 1.4.5. -#ifdef GEOIP_COUNTRY_EDITION_V6 - if ( ! is_v4_addr(a) ) - gir = GeoIP_name_by_ipnum_v6(geoip_asn, geoipv6_t(a)); +#ifdef HAVE_GEOIP_COUNTRY_EDITION_V6 + if ( a->AsAddr().GetFamily() == IPv6 ) + { + geoipv6_t ga; + a->AsAddr().CopyIPv6(&ga); + gir = GeoIP_name_by_ipnum_v6(geoip_asn, ga); + } else #endif - if ( is_v4_addr(a) ) + + if ( a->AsAddr().GetFamily() == IPv4 ) { - uint32 addr = to_v4_addr(a); - gir = GeoIP_name_by_ipnum(geoip_asn, ntohl(addr)); + const uint32* bytes; + a->AsAddr().GetBytes(&bytes); + gir = GeoIP_name_by_ipnum(geoip_asn, ntohl(*bytes)); } -#else - gir = GeoIP_name_by_ipnum(geoip_asn, ntohl(a)); -#endif } if ( gir ) @@ -3171,7 +3670,8 @@ function lookup_asn%(a: addr%) : count // the first two characters: "AS". return new Val(atoi(gir+2), TYPE_COUNT); } -#else + +#else // not USE_GEOIP static int missing_geoip_reported = 0; if ( ! missing_geoip_reported ) @@ -3187,184 +3687,13 @@ function lookup_asn%(a: addr%) : count return new Val(0, TYPE_COUNT); %} -# Returns true if connection has been received externally. -function is_external_connection%(c: connection%) : bool - %{ - return new Val(c && c->IsExternal(), TYPE_BOOL); - %} - -# Function equivalent of the &disable_print_hook attribute. -function disable_print_hook%(f: file%): any - %{ - f->DisablePrintHook(); - return 0; - %} - -# Function equivalent of the &raw_output attribute. -function enable_raw_output%(f: file%): any - %{ - f->EnableRawOutput(); - return 0; - %} - -%%{ -#ifdef HAVE_LIBMAGIC -extern "C" { -#include -} -#endif -%%} - -function identify_data%(data: string, return_mime: bool%): string - %{ - const char* descr = ""; - -#ifdef HAVE_LIBMAGIC - static magic_t magic_mime = 0; - static magic_t magic_descr = 0; - - magic_t* magic = return_mime ? &magic_mime : &magic_descr; - - if( ! *magic ) - { - *magic = magic_open(return_mime ? MAGIC_MIME : MAGIC_NONE); - - if ( ! *magic ) - { - reporter->Error(fmt("can't init libmagic: %s", magic_error(*magic))); - return new StringVal(""); - } - - if ( magic_load(*magic, 0) < 0 ) - { - reporter->Error(fmt("can't load magic file: %s", magic_error(*magic))); - magic_close(*magic); - *magic = 0; - return new StringVal(""); - } - } - - descr = magic_buffer(*magic, data->Bytes(), data->Len()); -#endif - - return new StringVal(descr); - %} - -function enable_event_group%(group: string%) : any - %{ - event_registry->EnableGroup(group->CheckString(), true); - return 0; - %} - -function disable_event_group%(group: string%) : any - %{ - event_registry->EnableGroup(group->CheckString(), false); - return 0; - %} - - -%%{ -#include -static map entropy_states; -%%} - -function find_entropy%(data: string%): entropy_test_result - %{ - double montepi, scc, ent, mean, chisq; - montepi = scc = ent = mean = chisq = 0.0; - RecordVal* ent_result = new RecordVal(entropy_test_result); - RandTest *rt = new RandTest(); - - rt->add((char*) data->Bytes(), data->Len()); - rt->end(&ent, &chisq, &mean, &montepi, &scc); - delete rt; - - ent_result->Assign(0, new Val(ent, TYPE_DOUBLE)); - ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE)); - ent_result->Assign(2, new Val(mean, TYPE_DOUBLE)); - ent_result->Assign(3, new Val(montepi, TYPE_DOUBLE)); - ent_result->Assign(4, new Val(scc, TYPE_DOUBLE)); - return ent_result; - %} - -function entropy_test_init%(index: any%): bool - %{ - BroString* s = convert_index_to_string(index); - int status = 0; - - if ( entropy_states.count(*s) < 1 ) - { - entropy_states[*s] = new RandTest(); - status = 1; - } - - delete s; - return new Val(status, TYPE_BOOL); - %} - -function entropy_test_add%(index: any, data: string%): bool - %{ - BroString* s = convert_index_to_string(index); - int status = 0; - - if ( entropy_states.count(*s) > 0 ) - { - entropy_states[*s]->add((char*) data->Bytes(), data->Len()); - status = 1; - } - - delete s; - return new Val(status, TYPE_BOOL); - %} - -function entropy_test_finish%(index: any%): entropy_test_result - %{ - BroString* s = convert_index_to_string(index); - double montepi, scc, ent, mean, chisq; - montepi = scc = ent = mean = chisq = 0.0; - RecordVal* ent_result = new RecordVal(entropy_test_result); - - if ( entropy_states.count(*s) > 0 ) - { - RandTest *rt = entropy_states[*s]; - rt->end(&ent, &chisq, &mean, &montepi, &scc); - entropy_states.erase(*s); - delete rt; - } - - ent_result->Assign(0, new Val(ent, TYPE_DOUBLE)); - ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE)); - ent_result->Assign(2, new Val(mean, TYPE_DOUBLE)); - ent_result->Assign(3, new Val(montepi, TYPE_DOUBLE)); - ent_result->Assign(4, new Val(scc, TYPE_DOUBLE)); - - delete s; - return ent_result; - %} - -function bro_has_ipv6%(%) : bool - %{ -#ifdef BROv6 - return new Val(1, TYPE_BOOL); -#else - return new Val(0, TYPE_BOOL); -#endif - %} - -function unique_id%(prefix: string%) : string - %{ - char tmp[20]; - uint64 uid = calculate_unique_id(); - return new StringVal(uitoa_n(uid, tmp, sizeof(tmp), 62, prefix->CheckString())); - %} - %%{ #include #include #include // This is the indexed map of X509 certificate stores. -static map x509_stores; +static map x509_stores; // ### NOTE: while d2i_X509 does not take a const u_char** pointer, // here we assume d2i_X509 does not write to , so it is safe to @@ -3383,15 +3712,29 @@ X509* d2i_X509_(X509** px, const u_char** in, int len) %%} +## Verifies a certificate. +## +## der_cert: The X.509 certificate in DER format. +## +## cert_stack: Specifies a certificate chain to validate against, with index 0 +## typically being the root CA. Bro uses the Mozilla root CA list +## by default. +## +## root_certs: A list of additional root certificates that extends +## *cert_stack*. +## +## Returns: A status code of the verification which can be converted into an +## ASCII string via :bro:id:`x509_err2str`. +## +## .. bro:see:: x509_err2str function x509_verify%(der_cert: string, cert_stack: string_vec, root_certs: table_string_of_string%): count %{ X509_STORE* ctx = 0; int i = 0; // If this certificate store was built previously, just reuse the old one. - BroString* s = convert_index_to_string(root_certs); - if ( x509_stores.count(*s) > 0 ) - ctx = x509_stores[*s]; + if ( x509_stores.count(root_certs) > 0 ) + ctx = x509_stores[root_certs]; if ( ! ctx ) // lookup to see if we have this one built already! { @@ -3416,9 +3759,8 @@ function x509_verify%(der_cert: string, cert_stack: string_vec, root_certs: tabl delete idxs; // Save the newly constructed certificate store into the cacheing map. - x509_stores[*s] = ctx; + x509_stores[root_certs] = ctx; } - delete s; const uint8 *cert_data = der_cert->Bytes(); X509* cert = d2i_X509_(NULL, &cert_data, der_cert->Len()); @@ -3465,12 +3807,25 @@ function x509_verify%(der_cert: string, cert_stack: string_vec, root_certs: tabl return new Val((uint64) csc.error, TYPE_COUNT); %} +## Converts a certificate verification error code into an ASCII string. +## +## err_num: The error code. +## +## Returns: A string representation of *err_num*. +## +## .. bro:see:: x509_verify function x509_err2str%(err_num: count%): string %{ return new StringVal(X509_verify_cert_error_string(err_num)); %} -function NFS3::mode2string%(mode: count%): string +## Converts UNIX file permissions given by a mode to an ASCII string. +## +## mode: The permisssions, e.g., 644 or 755. +## +## Returns: A string representation of *mode* in the format +## ``rw[xsS]rw[xsS]rw[xtT]``. +function file_mode%(mode: count%): string %{ char str[12]; char *p = str; @@ -3556,41 +3911,1004 @@ function NFS3::mode2string%(mode: count%): string return new StringVal(str); %} -## Opens a program with popen() and writes a given string to the returned -## stream to send it to the opened process's stdin. -## program: a string naming the program to execute -## to_write: a string to pipe to the opened program's process over stdin -## Returns: F if popen'ing the program failed, else T -function piped_exec%(program: string, to_write: string%): bool +# =========================================================================== +# +# Controlling Analyzer Behavior +# +# =========================================================================== + +%%{ +#include "DPM.h" +%%} + +## Schedules an analyzer for a future connection from a given IP address and +## port. The function ignores the scheduling request if the connection did +## not occur within the specified time interval. +## +## orig: The IP address originating a connection in the future. +## +## resp: The IP address responding to a connection from *orig*. +## +## resp_p: The destination port at *resp*. +## +## analyzer: The analyzer ID. +## +## tout: The timeout interval after which to ignore the scheduling request. +## +## Returns: True (unconditionally). +## +## .. bro:see:: disable_analyzer analyzer_name +## +## .. todo:: The return value should be changed to any. +function expect_connection%(orig: addr, resp: addr, resp_p: port, + analyzer: count, tout: interval%) : any %{ - const char* prog = program->CheckString(); - - FILE* f = popen(prog, "w"); - if ( ! f ) - { - reporter->Error("Failed to popen %s", prog); - return new Val(0, TYPE_BOOL); - } - - const u_char* input_data = to_write->Bytes(); - int input_data_len = to_write->Len(); - - int bytes_written = fwrite(input_data, 1, input_data_len, f); - - pclose(f); - - if ( bytes_written != input_data_len ) - { - reporter->Error("Failed to write all given data to %s", prog); - return new Val(0, TYPE_BOOL); - } - + dpm->ExpectConnection(orig->AsAddr(), resp->AsAddr(), resp_p->Port(), + resp_p->PortType(), (AnalyzerTag::Tag) analyzer, tout, 0); return new Val(1, TYPE_BOOL); %} -## Enables the communication system. Note that by default, -## communication is off until explicitly enabled, and all other calls -## to communication-related BiFs' will be ignored until done so. +## Disables the analyzer which raised the current event (if the analyzer +## belongs to the given connection). +## +## cid: The connection identifier. +## +## aid: The analyzer ID. +## +## Returns: True if the connection identified by *cid* exists and has analyzer +## *aid*. +## +## .. bro:see:: expect_connection analyzer_name +function disable_analyzer%(cid: conn_id, aid: count%) : bool + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + { + reporter->Error("cannot find connection"); + return new Val(0, TYPE_BOOL); + } + + Analyzer* a = c->FindAnalyzer(aid); + if ( ! a ) + { + reporter->Error("connection does not have analyzer specified to disable"); + return new Val(0, TYPE_BOOL); + } + + a->Remove(); + return new Val(1, TYPE_BOOL); + %} + +## Translate an analyzer type to an ASCII string. +## +## aid: The analyzer ID. +## +## Returns: The analyzer *aid* as string. +## +## .. bro:see:: expect_connection disable_analyzer current_analyzer +function analyzer_name%(aid: count%) : string + %{ + return new StringVal(Analyzer::GetTagName((AnalyzerTag::Tag) aid)); + %} + +## Informs Bro that it should skip any further processing of the contents of +## a given connection. In particular, Bro will refrain from reassembling the +## TCP byte stream and from generating events relating to any analyzers that +## have been processing the connection. +## +## cid: The connection ID. +## +## Returns: False if *id* does not point to an active connection and true +## otherwise. +## +## .. note:: +## +## Bro will still generate connection-oriented events such as +## :bro:id:`connection_finished`. +function skip_further_processing%(cid: conn_id%): bool + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_BOOL); + + c->SetSkip(1); + return new Val(1, TYPE_BOOL); + %} + +## Controls whether packet contents belonging to a connection should be +## recorded (when ``-w`` option is provided on the command line). +## +## cid: The connection identifier. +## +## do_record: True to enable packet contens and false to disable for the +## connection identified by *cid*. +## +## Returns: False if *id* does not point to an active connection and true +## otherwise. +## +## .. bro:see:: skip_further_processing +## +## .. note:: +## +## This is independent of whether Bro processes the packets of this +## connection, which is controlled separately by +## :bro:id:`skip_further_processing`. +## +## .. bro:see: get_contents_file set_contents_file +function set_record_packets%(cid: conn_id, do_record: bool%): bool + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_BOOL); + + c->SetRecordPackets(do_record); + return new Val(1, TYPE_BOOL); + %} + +## Associates a file handle with a connection for writing TCP byte stream +## contents. +## +## cid: The connection ID. +## +## direction: Controls what sides of the connection to record. The argument can +## take one the four values: +## +## - ``CONTENTS_NONE``: Stop recording the connection's content. +## - ``CONTENTS_ORIG``: Record the data sent by the connection +## originator (often the client). +## - ``CONTENTS_RESP``: Record the data sent by the connection +## responder (often the server). +## - ``CONTENTS_BOTH``: Record the data sent in both directions. +## Results in the two directions being +## intermixed in the file, in the order the +## data was seen by Bro. +## +## f: The file handle of the file to write the contents to. +## +## Returns: Returns false if *id* does not point to an active connection and +## true otherwise. +## +## .. note:: +## +## The data recorded to the file reflects the byte stream, not the +## contents of individual packets. Reordering and duplicates are +## removed. If any data is missing, the recording stops at the +## missing data; this can happen, e.g., due to an +## :bro:id:`ack_above_hole` event. +## +## .. bro:see: get_contents_file set_record_packets +function set_contents_file%(cid: conn_id, direction: count, f: file%): bool + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_BOOL); + + c->GetRootAnalyzer()->SetContentsFile(direction, f); + return new Val(1, TYPE_BOOL); + %} + +## Returns the file handle of the contents file of a connection. +## +## cid: The connection ID. +## +## direction: Controls what sides of the connection to record. SEe +## :bro:id:`set_contents_file` for possible values. +## +## Returns: The :bro:type:`file` handle for the contentents file of the +## connection identified by *cid*. If the connection exists +## but no contents file for *direction*, the function generates a +## error and returns a file handle to ``stderr``. +## +## .. bro:see: set_contents_file set_record_packets +function get_contents_file%(cid: conn_id, direction: count%): file + %{ + Connection* c = sessions->FindConnection(cid); + BroFile* f = c ? c->GetRootAnalyzer()->GetContentsFile(direction) : 0; + + if ( f ) + { + Ref(f); + return new Val(f); + } + + // Return some sort of error value. + if ( ! c ) + builtin_error("unknown connection id in get_contents_file()", cid); + else + builtin_error("no contents file for given direction"); + + return new Val(new BroFile(stderr, "-", "w")); + %} + +## Sets an individual inactivity timeout for a connection and thus +## overrides the global inactivity timeout. +## +## cid: The connection ID. +## +## t: The new inactivity timeout for the connection identified by *cid*. +## +## Returns: The previous timeout interval. +function set_inactivity_timeout%(cid: conn_id, t: interval%): interval + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_INTERVAL); + + double old_timeout = c->InactivityTimeout(); + c->SetInactivityTimeout(t); + + return new Val(old_timeout, TYPE_INTERVAL); + %} + +## Returns the state of the given login (Telnet or Rlogin) connection. +## +## cid: The connection ID. +## +## Returns: False if the connection is not active or is not tagged as a +## login analyzer. Otherwise the function returns the state, which can +## be one of: +## +## - ``LOGIN_STATE_AUTHENTICATE``: The connection is in its +## initial authentication dialog. +## - ``OGIN_STATE_LOGGED_IN``: The analyzer believes the user has +## successfully authenticated. +## - ``LOGIN_STATE_SKIP``: The analyzer has skipped any further +## processing of the connection. +## - ``LOGIN_STATE_CONFUSED``: The analyzer has concluded that it +## does not correctly know the state of the connection, and/or +## the username associated with it. +## +## .. bro:see: set_login_state +function get_login_state%(cid: conn_id%): count + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_BOOL); + + Analyzer* la = c->FindAnalyzer(AnalyzerTag::Login); + if ( ! la ) + return new Val(0, TYPE_BOOL); + + return new Val(int(static_cast(la)->LoginState()), + TYPE_COUNT); + %} + +## Sets the login state of a connection with a login analyzer. +## +## cid: The connection ID. +## +## new_state: The new state of the login analyzer. See +## :bro:id:`get_login_state` for possible values. +## +## Returns: Returns false if *cid* is not an active connection +## or does not tagged as login analyzer, and true otherwise. +## +## .. bro:see: get_login_state +function set_login_state%(cid: conn_id, new_state: count%): bool + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_BOOL); + + Analyzer* la = c->FindAnalyzer(AnalyzerTag::Login); + if ( ! la ) + return new Val(0, TYPE_BOOL); + + static_cast(la)->SetLoginState(login_state(new_state)); + return new Val(1, TYPE_BOOL); + %} + +%%{ +#include "TCP.h" +%%} + +## Get the originator sequence number of a TCP connection. Sequence numbers +## are absolute (i.e., they reflect the values seen directly in packet headers; +## they are not relative to the beginning of the connection). +## +## cid: The connection ID. +## +## Returns: The highest sequence number sent by a connection's originator, or 0 +## if *cid* does not point to an active TCP connection. +## +## .. bro:see:: get_resp_seq +function get_orig_seq%(cid: conn_id%): count + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_COUNT); + + if ( c->ConnTransport() != TRANSPORT_TCP ) + return new Val(0, TYPE_COUNT); + + Analyzer* tc = c->FindAnalyzer(AnalyzerTag::TCP); + if ( tc ) + return new Val(static_cast(tc)->OrigSeq(), + TYPE_COUNT); + else + { + reporter->Error("connection does not have TCP analyzer"); + return new Val(0, TYPE_COUNT); + } + %} + +## Get the responder sequence number of a TCP connection. Sequence numbers +## are absolute (i.e., they reflect the values seen directly in packet headers; +## they are not relative to the beginning of the connection). +## +## cid: The connection ID. +## +## Returns: The highest sequence number sent by a connection's responder, or 0 +## if *cid* does not point to an active TCP connection. +## +## .. bro:see:: get_orig_seq +function get_resp_seq%(cid: conn_id%): count + %{ + Connection* c = sessions->FindConnection(cid); + if ( ! c ) + return new Val(0, TYPE_COUNT); + + if ( c->ConnTransport() != TRANSPORT_TCP ) + return new Val(0, TYPE_COUNT); + + Analyzer* tc = c->FindAnalyzer(AnalyzerTag::TCP); + if ( tc ) + return new Val(static_cast(tc)->RespSeq(), + TYPE_COUNT); + else + { + reporter->Error("connection does not have TCP analyzer"); + return new Val(0, TYPE_COUNT); + } + %} + +%%{ +#include "SMTP.h" +%%} + +## Skips SMTP data until the next email in a connection. +## +## c: The SMTP connection. +## +## .. bro:see:: skip_http_entity_data +function skip_smtp_data%(c: connection%): any + %{ + Analyzer* sa = c->FindAnalyzer(AnalyzerTag::SMTP); + if ( sa ) + static_cast(sa)->SkipData(); + return 0; + %} + +## Enables all event handlers in a given group. One can tag event handlers with +## the :bro:attr:`&group` attribute to logically group them together, e.g, +## ``event foo() &group="bar"``. This function enables all event handlers that +## belong to such a group. +## +## group: The group. +## +## .. bro:see:: disable_event_group +function enable_event_group%(group: string%) : any + %{ + event_registry->EnableGroup(group->CheckString(), true); + return 0; + %} + +## Disables all event handlers in a given group. +## +## group: The group. +## +## .. bro:see:: enable_event_group +function disable_event_group%(group: string%) : any + %{ + event_registry->EnableGroup(group->CheckString(), false); + return 0; + %} + +# =========================================================================== +# +# Files and Directories +# +# =========================================================================== + +## Opens a file for writing. If a file with the same name already exists, this +## function overwrites it (as opposed to :bro:id:`open_for_append`). +## +## f: The path to the file. +## +## Returns: A :bro:type:`file` handle for subsequent operations. +## +## .. bro:see;: active_file open_for_append close write_file +## get_file_name set_buf flush_all mkdir enable_raw_output +function open%(f: string%): file + %{ + const char* file = f->CheckString(); + + if ( streq(file, "-") ) + return new Val(new BroFile(stdout, "-", "w")); + else + return new Val(new BroFile(file, "w")); + %} + +## Opens a file for writing or appending. If a file with the same name already +## exists, this function appends to it (as opposed to :bro:id:`open`). +## +## f: The path to the file. +## +## Returns: A :bro:type:`file` handle for subsequent operations. +## +## .. bro:see;: active_file open close write_file +## get_file_name set_buf flush_all mkdir enable_raw_output +function open_for_append%(f: string%): file + %{ + return new Val(new BroFile(f->CheckString(), "a")); + %} + +## Closes an open file and flushes any buffered content. +## exists, this function appends to it (as opposed to :bro:id:`open`). +## +## f: A :bro:type:`file` handle to an open file. +## +## Returns: True on success. +## +## .. bro:see;: active_file open open_for_append write_file +## get_file_name set_buf flush_all mkdir enable_raw_output +function close%(f: file%): bool + %{ + return new Val(f->Close(), TYPE_BOOL); + %} + +## Writes data to an open file. +## +## f: A :bro:type:`file` handle to an open file. +## +## data: The data to write to *f*. +## +## Returns: True on success. +## +## .. bro:see;: active_file open open_for_append close +## get_file_name set_buf flush_all mkdir enable_raw_output +function write_file%(f: file, data: string%): bool + %{ + if ( ! f ) + return new Val(0, TYPE_BOOL); + + return new Val(f->Write((const char*) data->Bytes(), data->Len()), + TYPE_BOOL); + %} + +## Alters the buffering behavior of a file. +## +## f: A :bro:type:`file` handle to an open file. +## +## buffered: When true, *f* is fully buffered, i.e., bytes are saved in a +## buffered until the block size has been reached. When +## false, *f* is line buffered, i.e., bytes are saved up until a +## newline occurs. +## +## .. bro:see;: active_file open open_for_append close +## get_file_name write_file flush_all mkdir enable_raw_output +function set_buf%(f: file, buffered: bool%): any + %{ + f->SetBuf(buffered); + return new Val(0, TYPE_VOID); + %} + +## Flushes all open files to disk. +## +## Returns: True on success. +## +## .. bro:see;: active_file open open_for_append close +## get_file_name write_file set_buf mkdir enable_raw_output +function flush_all%(%): bool + %{ + return new Val(fflush(0) == 0, TYPE_BOOL); + %} + +## Creates a new directory. +## +## f: The directory name. +## +## Returns: Returns true if the operation succeeds and false if the +## creation fails or if *f* exists already. +## +## .. bro:see;: active_file open_for_append close write_file +## get_file_name set_buf flush_all enable_raw_output +function mkdir%(f: string%): bool + %{ + const char* filename = f->CheckString(); + if ( mkdir(filename, 0777) < 0 && errno != EEXIST ) + { + builtin_error("cannot create directory", @ARG@[0]); + return new Val(0, TYPE_BOOL); + } + else + return new Val(1, TYPE_BOOL); + %} + +## Checks whether a given file is open. +## +## f: The file to check. +## +## Returns: True if *f* is an open :bro:type:`file`. +## +## .. todo:: Rename to ``is_open``. +function active_file%(f: file%): bool + %{ + return new Val(f->IsOpen(), TYPE_BOOL); + %} + +## Gets the filename associated with a file handle. +## +## f: The file handle to inquire the name for. +## +## Returns: The filename associated with *f*. +## +## .. bro:see:: open +function get_file_name%(f: file%): string + %{ + if ( ! f ) + return new StringVal(""); + + return new StringVal(f->Name()); + %} + +## Rotates a file. +## +## f: An open file handle. +## +## Returns: Rotations statistics which include the original file name, the name +## after the rotation, and the time when *f* was opened/closed. +## +## .. bro:see:: rotate_file_by_name calc_next_rotate +function rotate_file%(f: file%): rotate_info + %{ + RecordVal* info = f->Rotate(); + if ( info ) + return info; + + // Record indicating error. + info = new RecordVal(rotate_info); + info->Assign(0, new StringVal("")); + info->Assign(1, new StringVal("")); + info->Assign(2, new Val(0, TYPE_TIME)); + info->Assign(3, new Val(0, TYPE_TIME)); + + return info; + %} + +## Rotates a file identified by its name. +## +## f: The name of the file to rotate +## +## Returns: Rotations statistics which include the original file name, the name +## after the rotation, and the time when *f* was opened/closed. +## +## .. bro:see:: rotate_file calc_next_rotate +function rotate_file_by_name%(f: string%): rotate_info + %{ + RecordVal* info = new RecordVal(rotate_info); + + bool is_pkt_dumper = false; + bool is_addl_pkt_dumper = false; + + // Special case: one of current dump files. + if ( pkt_dumper && streq(pkt_dumper->FileName(), f->CheckString()) ) + { + is_pkt_dumper = true; + pkt_dumper->Close(); + } + + if ( addl_pkt_dumper && + streq(addl_pkt_dumper->FileName(), f->CheckString()) ) + { + is_addl_pkt_dumper = true; + addl_pkt_dumper->Close(); + } + + FILE* file = rotate_file(f->CheckString(), info); + if ( ! file ) + { + // Record indicating error. + info->Assign(0, new StringVal("")); + info->Assign(1, new StringVal("")); + info->Assign(2, new Val(0, TYPE_TIME)); + info->Assign(3, new Val(0, TYPE_TIME)); + return info; + } + + fclose(file); + + if ( is_pkt_dumper ) + { + info->Assign(2, new Val(pkt_dumper->OpenTime(), TYPE_TIME)); + pkt_dumper->Open(); + } + + if ( is_addl_pkt_dumper ) + info->Assign(2, new Val(addl_pkt_dumper->OpenTime(), TYPE_TIME)); + + return info; + %} + +## Calculates the duration until the next time a file is to be rotated, based +## on a given rotate interval. +## +## i: The rotate interval to base the calculation on. +## +## Returns: The duration until the next file rotation time. +## +## .. bro:see:: rotate_file rotate_file_by_name +function calc_next_rotate%(i: interval%) : interval + %{ + const char* base_time = log_rotate_base_time ? + log_rotate_base_time->AsString()->CheckString() : 0; + return new Val(calc_next_rotate(i, base_time), TYPE_INTERVAL); + %} + +## Returns the size of a given file. +## +## f: The name of the file whose size to lookup. +## +## Returns: The size of *f* in bytes. +function file_size%(f: string%) : double + %{ + struct stat s; + + if ( stat(f->CheckString(), &s) < 0 ) + return new Val(-1.0, TYPE_DOUBLE); + + return new Val(double(s.st_size), TYPE_DOUBLE); + %} + +## Disables sending :bro:id:`print_hook` events to remote peers for a given +## file. This function is equivalent to :bro:attr:`&disable_print_hook`. In a +## distributed setup, communicating Bro instances generate the event +## :bro:id:`print_hook` for each print statement and send it to the remote +## side. When disabled for a particular file, these events will not be +## propagated to other peers. +## +## f: The file to disable :bro:id:`print_hook` events for. +## +## .. bro:see:: enable_raw_output +function disable_print_hook%(f: file%): any + %{ + f->DisablePrintHook(); + return 0; + %} + +## Prevents escaping of non-ASCII character when writing to a file. +## This function is equivalent to :bro:attr:`&disable_print_hook`. +## +## f: The file to disable raw output for. +## +## .. bro:see:: disable_print_hook +function enable_raw_output%(f: file%): any + %{ + f->EnableRawOutput(); + return 0; + %} + +# =========================================================================== +# +# Packet Filtering +# +# =========================================================================== + +## Precompiles a PCAP filter and binds it to a given identifier. +## +## id: The PCAP identifier to reference the filter *s* later on. +## +## s: The PCAP filter. See ``man tcpdump`` for valid expressions. +## +## Returns: True if *s* is valid and precompiles successfully. +## +## .. bro:see:: install_pcap_filter +## install_src_addr_filter +## install_src_net_filter +## uninstall_src_addr_filter +## uninstall_src_net_filter +## install_dst_addr_filter +## install_dst_net_filter +## uninstall_dst_addr_filter +## uninstall_dst_net_filter +## pcap_error +function precompile_pcap_filter%(id: PcapFilterID, s: string%): bool + %{ + bool success = true; + + loop_over_list(pkt_srcs, i) + { + pkt_srcs[i]->ClearErrorMsg(); + + if ( ! pkt_srcs[i]->PrecompileFilter(id->ForceAsInt(), + s->CheckString()) ) + { + reporter->Error("precompile_pcap_filter: %s", + pkt_srcs[i]->ErrorMsg()); + success = false; + } + } + + return new Val(success, TYPE_BOOL); + %} + +## Installs a PCAP filter that has been precompiled with +## :bro:id:`precompile_pcap_filter`. +## +## id: The PCAP filter id of a precompiled filter. +## +## Returns: True if the filter associated with *id* has been installed +## successfully. +## +## .. bro:see:: precompile_pcap_filter +## install_src_addr_filter +## install_src_net_filter +## uninstall_src_addr_filter +## uninstall_src_net_filter +## install_dst_addr_filter +## install_dst_net_filter +## uninstall_dst_addr_filter +## uninstall_dst_net_filter +## pcap_error +function install_pcap_filter%(id: PcapFilterID%): bool + %{ + bool success = true; + + loop_over_list(pkt_srcs, i) + { + pkt_srcs[i]->ClearErrorMsg(); + + if ( ! pkt_srcs[i]->SetFilter(id->ForceAsInt()) ) + success = false; + } + + return new Val(success, TYPE_BOOL); + %} + +## Returns a string representation of the last PCAP error. +## +## Returns: A descriptive error message of the PCAP function that failed. +## +## .. bro:see:: precompile_pcap_filter +## install_pcap_filter +## install_src_addr_filter +## install_src_net_filter +## uninstall_src_addr_filter +## uninstall_src_net_filter +## install_dst_addr_filter +## install_dst_net_filter +## uninstall_dst_addr_filter +## uninstall_dst_net_filter +function pcap_error%(%): string + %{ + loop_over_list(pkt_srcs, i) + { + const char* err = pkt_srcs[i]->ErrorMsg(); + if ( *err ) + return new StringVal(err); + } + + return new StringVal("no error"); + %} + +## Installs a filter to drop packets from a given IP source address with +## a certain probability if none of a given set of TCP flags are set. +## Note that for IPv6 packets with a Destination options header that has +## the Home Address option, this filters out against that home address. +## +## ip: The IP address to drop. +## +## tcp_flags: If none of these TCP flags are set, drop packets from *ip* with +## probability *prob*. +## +## prob: The probability [0.0, 1.0] used to drop packets from *ip*. +## +## Returns: True (unconditionally). +## +## .. bro:see:: precompile_pcap_filter +## install_pcap_filter +## install_src_net_filter +## uninstall_src_addr_filter +## uninstall_src_net_filter +## install_dst_addr_filter +## install_dst_net_filter +## uninstall_dst_addr_filter +## uninstall_dst_net_filter +## pcap_error +## +## .. todo:: The return value should be changed to any. +function install_src_addr_filter%(ip: addr, tcp_flags: count, prob: double%) : bool + %{ + sessions->GetPacketFilter()->AddSrc(ip->AsAddr(), tcp_flags, prob); + return new Val(1, TYPE_BOOL); + %} + +## Installs a filter to drop packets originating from a given subnet with +## a certain probability if none of a given set of TCP flags are set. +## +## snet: The subnet to drop packets from. +## +## tcp_flags: If none of these TCP flags are set, drop packets from *snet* with +## probability *prob*. +## +## prob: The probability [0.0, 1.0] used to drop packets from *snet*. +## +## Returns: True (unconditionally). +## +## .. bro:see:: precompile_pcap_filter +## install_pcap_filter +## install_src_addr_filter +## uninstall_src_addr_filter +## uninstall_src_net_filter +## install_dst_addr_filter +## install_dst_net_filter +## uninstall_dst_addr_filter +## uninstall_dst_net_filter +## pcap_error +## +## .. todo:: The return value should be changed to any. +function install_src_net_filter%(snet: subnet, tcp_flags: count, prob: double%) : bool + %{ + sessions->GetPacketFilter()->AddSrc(snet, tcp_flags, prob); + return new Val(1, TYPE_BOOL); + %} + +## Removes a source address filter. +## +## ip: The IP address for which a source filter was previously installed. +## +## Returns: True on success. +## +## .. bro:see:: precompile_pcap_filter +## install_pcap_filter +## install_src_addr_filter +## install_src_net_filter +## uninstall_src_net_filter +## install_dst_addr_filter +## install_dst_net_filter +## uninstall_dst_addr_filter +## uninstall_dst_net_filter +## pcap_error +function uninstall_src_addr_filter%(ip: addr%) : bool + %{ + return new Val(sessions->GetPacketFilter()->RemoveSrc(ip->AsAddr()), TYPE_BOOL); + %} + +## Removes a source subnet filter. +## +## snet: The subnet for which a source filter was previously installed. +## +## Returns: True on success. +## +## .. bro:see:: precompile_pcap_filter +## install_pcap_filter +## install_src_addr_filter +## install_src_net_filter +## uninstall_src_addr_filter +## install_dst_addr_filter +## install_dst_net_filter +## uninstall_dst_addr_filter +## uninstall_dst_net_filter +## pcap_error +function uninstall_src_net_filter%(snet: subnet%) : bool + %{ + return new Val(sessions->GetPacketFilter()->RemoveSrc(snet), TYPE_BOOL); + %} + +## Installs a filter to drop packets destined to a given IP address with +## a certain probability if none of a given set of TCP flags are set. +## Note that for IPv6 packets with a routing type header and non-zero +## segments left, this filters out against the final destination of the +## packet according to the routing extension header. +## +## ip: Drop packets to this IP address. +## +## tcp_flags: If none of these TCP flags are set, drop packets to *ip* with +## probability *prob*. +## +## prob: The probability [0.0, 1.0] used to drop packets to *ip*. +## +## Returns: True (unconditionally). +## +## .. bro:see:: precompile_pcap_filter +## install_pcap_filter +## install_src_addr_filter +## install_src_net_filter +## uninstall_src_addr_filter +## uninstall_src_net_filter +## install_dst_net_filter +## uninstall_dst_addr_filter +## uninstall_dst_net_filter +## pcap_error +## +## .. todo:: The return value should be changed to any. +function install_dst_addr_filter%(ip: addr, tcp_flags: count, prob: double%) : bool + %{ + sessions->GetPacketFilter()->AddDst(ip->AsAddr(), tcp_flags, prob); + return new Val(1, TYPE_BOOL); + %} + +## Installs a filter to drop packets destined to a given subnet with +## a certain probability if none of a given set of TCP flags are set. +## +## snet: Drop packets to this subnet. +## +## tcp_flags: If none of these TCP flags are set, drop packets to *snet* with +## probability *prob*. +## +## prob: The probability [0.0, 1.0] used to drop packets to *snet*. +## +## Returns: True (unconditionally). +## +## .. bro:see:: precompile_pcap_filter +## install_pcap_filter +## install_src_addr_filter +## install_src_net_filter +## uninstall_src_addr_filter +## uninstall_src_net_filter +## install_dst_addr_filter +## uninstall_dst_addr_filter +## uninstall_dst_net_filter +## pcap_error +## +## .. todo:: The return value should be changed to any. +function install_dst_net_filter%(snet: subnet, tcp_flags: count, prob: double%) : bool + %{ + sessions->GetPacketFilter()->AddDst(snet, tcp_flags, prob); + return new Val(1, TYPE_BOOL); + %} + +## Removes a destination address filter. +## +## ip: The IP address for which a destination filter was previously installed. +## +## Returns: True on success. +## +## .. bro:see:: precompile_pcap_filter +## install_pcap_filter +## install_src_addr_filter +## install_src_net_filter +## uninstall_src_addr_filter +## uninstall_src_net_filter +## install_dst_addr_filter +## install_dst_net_filter +## uninstall_dst_net_filter +## pcap_error +function uninstall_dst_addr_filter%(ip: addr%) : bool + %{ + return new Val(sessions->GetPacketFilter()->RemoveDst(ip->AsAddr()), TYPE_BOOL); + %} + +## Removes a destination subnet filter. +## +## snet: The subnet for which a destination filter was previously installed. +## +## Returns: True on success. +## +## .. bro:see:: precompile_pcap_filter +## install_pcap_filter +## install_src_addr_filter +## install_src_net_filter +## uninstall_src_addr_filter +## uninstall_src_net_filter +## install_dst_addr_filter +## install_dst_net_filter +## uninstall_dst_addr_filter +## pcap_error +function uninstall_dst_net_filter%(snet: subnet%) : bool + %{ + return new Val(sessions->GetPacketFilter()->RemoveDst(snet), TYPE_BOOL); + %} + +# =========================================================================== +# +# Communication +# +# =========================================================================== + +## Enables the communication system. By default, the communication is off until +## explicitly enabled, and all other calls to communication-related functions +## will be ignored until done so. function enable_communication%(%): any %{ if ( bro_start_network_time != 0.0 ) @@ -3607,3 +4925,617 @@ function enable_communication%(%): any remote_serializer->Init(); return 0; %} + +## Flushes in-memory state tagged with the :bro:attr:`&persistent` attribute +## to disk. The function writes the state to the file ``.state/state.bst`` in +## the directory where Bro was started. +## +## Returns: True on success. +## +## .. bro:see:: rescan_state +function checkpoint_state%(%) : bool + %{ + return new Val(persistence_serializer->WriteState(true), TYPE_BOOL); + %} + +## Reads persistent state from the \texttt{.state} directory and populates the +## in-memory data structures accordingly. This function is the dual to +## :bro:id:`checkpoint_state`. +## +## Returns: True on success. +## +## .. bro:see:: checkpoint_state +function rescan_state%(%) : bool + %{ + return new Val(persistence_serializer->ReadAll(false, true), TYPE_BOOL); + %} + +## Writes the binary event stream generated by the core to a given file. +## Use the ``-x `` command line switch to replay saved events. +## +## filename: The name of the file which stores the events. +## +## Returns: True if opening the target file succeeds. +## +## .. bro:see:: capture_state_updates +function capture_events%(filename: string%) : bool + %{ + if ( ! event_serializer ) + event_serializer = new FileSerializer(); + else + event_serializer->Close(); + + return new Val(event_serializer->Open( + (const char*) filename->CheckString()), TYPE_BOOL); + %} + +## Writes state updates generated by :bro:attr:`&synchronized` variables to a +## file. +## +## filename: The name of the file which stores the state updates. +## +## Returns: True if opening the target file succeeds. +## +## .. bro:see:: capture_events +function capture_state_updates%(filename: string%) : bool + %{ + if ( ! state_serializer ) + state_serializer = new FileSerializer(); + else + state_serializer->Close(); + + return new Val(state_serializer->Open( + (const char*) filename->CheckString()), TYPE_BOOL); + %} + +## Establishes a connection to a remote Bro or Broccoli instance. +## +## ip: The IP address of the remote peer. +## +## port: The port of the remote peer. +## +## our_class: If an non-empty string, the remote (listening) peer checks it +## against its class name in its peer table and terminates the +## connection if they don't match. +## +## retry: If the connection fails, try to reconnect with the peer after this +## time interval. +## +## ssl: If true, uses SSL to encrypt the session. +## +## Returns: A locally unique ID of the new peer. +## +## .. bro:see:: disconnect +## listen +## request_remote_events +## request_remote_sync +## request_remote_logs +## request_remote_events +## set_accept_state +## set_compression_level +## send_state +## send_id +function connect%(ip: addr, p: port, our_class: string, retry: interval, ssl: bool%) : count + %{ + return new Val(uint32(remote_serializer->Connect(ip->AsAddr(), p->Port(), + our_class->CheckString(), retry, ssl)), + TYPE_COUNT); + %} + +## Terminate the connection with a peer. +## +## p: The peer ID return from :bro:id:`connect`. +## +## Returns: True on success. +## +## .. bro:see:: connect listen +function disconnect%(p: event_peer%) : bool + %{ + RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); + return new Val(remote_serializer->CloseConnection(id), TYPE_BOOL); + %} + +## Subscribes to all events from a remote peer whose names match a given +## pattern. +## +## p: The peer ID return from :bro:id:`connect`. +## +## handlers: The pattern describing the events to request from peer *p*. +## +## Returns: True on success. +## +## .. bro:see:: request_remote_sync +## request_remote_logs +## set_accept_state +function request_remote_events%(p: event_peer, handlers: pattern%) : bool + %{ + RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); + return new Val(remote_serializer->RequestEvents(id, handlers), + TYPE_BOOL); + %} + +## Requests synchronization of IDs with a remote peer. +## +## p: The peer ID return from :bro:id:`connect`. +## +## auth: If true, the local instance considers its current state authoritative +## and sends it to *p* right after the handshake. +## +## Returns: True on success. +## +## .. bro:see:: request_remote_events +## request_remote_logs +## set_accept_state +function request_remote_sync%(p: event_peer, auth: bool%) : bool + %{ + RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); + return new Val(remote_serializer->RequestSync(id, auth), TYPE_BOOL); + %} + +## Requests logs from a remote peer. +## +## p: The peer ID return from :bro:id:`connect`. +## +## Returns: True on success. +## +## .. bro:see:: request_remote_events +## request_remote_sync +function request_remote_logs%(p: event_peer%) : bool + %{ + RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); + return new Val(remote_serializer->RequestLogs(id), TYPE_BOOL); + %} + +## Sets a boolean flag whether Bro accepts state from a remote peer. +## +## p: The peer ID return from :bro:id:`connect`. +## +## Returns: True on success. +## +## .. bro:see:: request_remote_events +## request_remote_sync +## set_compression_level +function set_accept_state%(p: event_peer, accept: bool%) : bool + %{ + RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); + return new Val(remote_serializer->SetAcceptState(id, accept), + TYPE_BOOL); + %} + +## Sets the compression level of the session with a remote peer. +## +## p: The peer ID return from :bro:id:`connect`. +## +## level: Allowed values are in the range *[0, 9]*, where 0 is the default and +## means no compression. +## +## Returns: True on success. +## +## .. bro:see:: set_accept_state +function set_compression_level%(p: event_peer, level: count%) : bool + %{ + RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); + return new Val(remote_serializer->SetCompressionLevel(id, level), + TYPE_BOOL); + %} + +## Listens on address a given IP address and port for remote connections. +## +## ip: The IP address to bind to. +## +## p: The TCP port to listen to. +## +## ssl: If true, Bro uses SSL to encrypt the session. +## +## Returns: True on success. +## +## .. bro:see:: connect disconnect +function listen%(ip: addr, p: port, ssl: bool %) : bool + %{ + return new Val(remote_serializer->Listen(ip->AsAddr(), p->Port(), ssl), TYPE_BOOL); + %} + +## Checks whether the last raised event came from a remote peer. +## +## Returns: True if the last raised event came from a remote peer. +function is_remote_event%(%) : bool + %{ + return new Val(mgr.CurrentSource() != SOURCE_LOCAL, TYPE_BOOL); + %} + +## Sends all persistent state to a remote peer. +## +## p: The peer ID return from :bro:id:`connect`. +## +## Returns: True on success. +## +## .. bro:see:: send_id send_ping send_current_packet send_capture_filter +function send_state%(p: event_peer%) : bool + %{ + RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); + return new Val(persistence_serializer->SendState(id, true), TYPE_BOOL); + %} + +## Sends a global identifier to a remote peer, which them might install it +## locally. +## +## p: The peer ID return from :bro:id:`connect`. +## +## id: The identifier to send. +## +## Returns: True on success. +## +## .. bro:see:: send_state send_ping send_current_packet send_capture_filter +function send_id%(p: event_peer, id: string%) : bool + %{ + RemoteSerializer::PeerID pid = p->AsRecordVal()->Lookup(0)->AsCount(); + + ID* i = global_scope()->Lookup(id->CheckString()); + if ( ! i ) + { + reporter->Error("send_id: no global id %s", id->CheckString()); + return new Val(0, TYPE_BOOL); + } + + SerialInfo info(remote_serializer); + return new Val(remote_serializer->SendID(&info, pid, *i), TYPE_BOOL); + %} + +## Gracefully finishes communication by first making sure that all remaining +## data from parent and child has been sent out. +## +## Returns: True if the termination process has been started successfully. +function terminate_communication%(%) : bool + %{ + return new Val(remote_serializer->Terminate(), TYPE_BOOL); + %} + +## Signals a remote peer that the local Bro instance finished the initial +## handshake. +## +## p: The peer ID return from :bro:id:`connect`. +## +## Returns: True on success. +function complete_handshake%(p: event_peer%) : bool + %{ + RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); + return new Val(remote_serializer->CompleteHandshake(id), TYPE_BOOL); + %} + +## Sends a ping event to a remote peer. In combination with an event handler +## for :bro:id:`remote_pong`, this function can be used to measure latency +## between two peers. +## +## p: The peer ID return from :bro:id:`connect`. +## +## seq: A sequence number (also included by :bro:id:`remote_pong`). +## +## Returns: True if sending the ping succeeds. +## +## .. bro:see:: send_state send_id send_current_packet send_capture_filter +function send_ping%(p: event_peer, seq: count%) : bool + %{ + RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); + return new Val(remote_serializer->SendPing(id, seq), TYPE_BOOL); + %} + +## Sends the currently processed packet to a remote peer. +## +## p: The peer ID return from :bro:id:`connect`. +## +## Returns: True if sending the packet succeeds. +## +## .. bro:see:: send_id send_state send_ping send_capture_filter +## dump_packet dump_current_packet get_current_packet +function send_current_packet%(p: event_peer%) : bool + %{ + Packet pkt(""); + + if ( ! current_pktsrc || + ! current_pktsrc->GetCurrentPacket(&pkt.hdr, &pkt.pkt) ) + return new Val(0, TYPE_BOOL); + + RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); + + pkt.time = pkt.hdr->ts.tv_sec + double(pkt.hdr->ts.tv_usec) / 1e6; + pkt.hdr_size = current_pktsrc->HdrSize(); + pkt.link_type = current_pktsrc->LinkType(); + + SerialInfo info(remote_serializer); + return new Val(remote_serializer->SendPacket(&info, id, pkt), TYPE_BOOL); + %} + +## Returns the peer who generated the last event. +## +## Returns: The ID of the peer who genereated the last event. +## +## .. bro:see:: get_local_event_peer +function get_event_peer%(%) : event_peer + %{ + SourceID src = mgr.CurrentSource(); + + if ( src == SOURCE_LOCAL ) + { + RecordVal* p = mgr.GetLocalPeerVal(); + Ref(p); + return p; + } + + if ( ! remote_serializer ) + reporter->InternalError("remote_serializer not initialized"); + + Val* v = remote_serializer->GetPeerVal(src); + if ( ! v ) + { + reporter->Error("peer %d does not exist anymore", int(src)); + RecordVal* p = mgr.GetLocalPeerVal(); + Ref(p); + return p; + } + + return v; + %} + +## Returns the local peer ID. +## +## Returns: The peer ID of the local Bro instance. +## +## .. bro:see:: get_event_peer +function get_local_event_peer%(%) : event_peer + %{ + RecordVal* p = mgr.GetLocalPeerVal(); + Ref(p); + return p; + %} + +## Sends a capture filter to a remote peer. +## +## p: The peer ID return from :bro:id:`connect`. +## +## s: The capture filter. +## +## Returns: True if sending the packet succeeds. +## +## .. bro:see:: send_id send_state send_ping send_current_packet +function send_capture_filter%(p: event_peer, s: string%) : bool + %{ + RemoteSerializer::PeerID id = p->AsRecordVal()->Lookup(0)->AsCount(); + return new Val(remote_serializer->SendCaptureFilter(id, s->CheckString()), TYPE_BOOL); + %} + +## Stops Bro's packet processing. This function is used to synchronize +## distributed trace processing with communication enabled +## (*pseudo-realtime* mode). +## +## .. bro:see: continue_processing suspend_state_updates resume_state_updates +function suspend_processing%(%) : any + %{ + net_suspend_processing(); + return 0; + %} + +## Resumes Bro's packet processing. +## +## .. bro:see: suspend_processing suspend_state_updates resume_state_updates +function continue_processing%(%) : any + %{ + net_continue_processing(); + return 0; + %} + +## Stops propagating :bro:attr:`&synchronized` accesses. +## +## .. bro:see: suspend_processing continue_processing resume_state_updates +function suspend_state_updates%(%) : any + %{ + if ( remote_serializer ) + remote_serializer->SuspendStateUpdates(); + return 0; + %} + +## Resumes propagating :bro:attr:`&synchronized` accesses. +## +## .. bro:see: suspend_processing continue_processing suspend_state_updates +function resume_state_updates%(%) : any + %{ + if ( remote_serializer ) + remote_serializer->ResumeStateUpdates(); + return 0; + %} + +# =========================================================================== +# +# Internal Functions +# +# =========================================================================== + +## Manually triggers the signature engine for a given connection. +## This is an internal function. +function match_signatures%(c: connection, pattern_type: int, s: string, + bol: bool, eol: bool, + from_orig: bool, clear: bool%) : bool + %{ + if ( ! rule_matcher ) + return new Val(0, TYPE_BOOL); + + c->Match((Rule::PatternType) pattern_type, s->Bytes(), s->Len(), + from_orig, bol, eol, clear); + + return new Val(1, TYPE_BOOL); + %} + +# =========================================================================== +# +# Deprecated Functions +# +# =========================================================================== + +%%{ +#include "Anon.h" +%%} + +## Preserves the prefix of an IP address in anonymization. +## +## a: The address to preserve. +## +## width: The number of bits from the top that should remain intact. +## +## .. bro:see:: preserve_subnet anonymize_addr +## +## .. todo:: Currently dysfunctional. +function preserve_prefix%(a: addr, width: count%): any + %{ + AnonymizeIPAddr* ip_anon = ip_anonymizer[PREFIX_PRESERVING_A50]; + if ( ip_anon ) + { + if ( a->AsAddr().GetFamily() == IPv6 ) + builtin_error("preserve_prefix() not supported for IPv6 addresses"); + else + { + const uint32* bytes; + a->AsAddr().GetBytes(&bytes); + ip_anon->PreservePrefix(*bytes, width); + } + } + + + return 0; + %} + +## Preserves the prefix of a subnet in anonymization. +## +## a: The subnet to preserve. +## +## width: The number of bits from the top that should remain intact. +## +## .. bro:see:: preserve_prefix anonymize_addr +## +## .. todo:: Currently dysfunctional. +function preserve_subnet%(a: subnet%): any + %{ + DEBUG_MSG("%s/%d\n", a->Prefix().AsString().c_str(), a->Width()); + AnonymizeIPAddr* ip_anon = ip_anonymizer[PREFIX_PRESERVING_A50]; + if ( ip_anon ) + { + if ( a->AsSubNet().Prefix().GetFamily() == IPv6 ) + builtin_error("preserve_subnet() not supported for IPv6 addresses"); + else + { + const uint32* bytes; + a->AsSubNet().Prefix().GetBytes(&bytes); + ip_anon->PreservePrefix(*bytes, a->AsSubNet().Length()); + } + } + + return 0; + %} + +## Anonymizes an IP address. +## +## a: The address to anonymize. +## +## cl: The anonymization class, which can take on three different values: +## +## - ``ORIG_ADDR``: Tag *a* as an originator address. +## +## - ``RESP_ADDR``: Tag *a* as an responder address. +## +## - ``OTHER_ADDR``: Tag *a* as an arbitrary address. +## +## Returns: An anonymized version of *a*. +## +## .. bro:see:: preserve_prefix preserve_subnet +## +## .. todo:: Currently dysfunctional. +function anonymize_addr%(a: addr, cl: IPAddrAnonymizationClass%): addr + %{ + int anon_class = cl->InternalInt(); + if ( anon_class < 0 || anon_class >= NUM_ADDR_ANONYMIZATION_CLASSES ) + builtin_error("anonymize_addr(): invalid ip addr anonymization class"); + + if ( a->AsAddr().GetFamily() == IPv6 ) + { + builtin_error("anonymize_addr() not supported for IPv6 addresses"); + return 0; + } + else + { + const uint32* bytes; + a->AsAddr().GetBytes(&bytes); + return new AddrVal(anonymize_ip(*bytes, + (enum ip_addr_anonymization_class_t) anon_class)); + } + %} + +## Deprecated. Will be removed. +function dump_config%(%) : bool + %{ + return new Val(persistence_serializer->WriteConfig(true), TYPE_BOOL); + %} + +## Deprecated. Will be removed. +function make_connection_persistent%(c: connection%) : any + %{ + c->MakePersistent(); + return 0; + %} + +%%{ +// Experimental code to add support for IDMEF XML output based on +// notices. For now, we're implementing it as a builtin you can call on an +// notices record. + +#ifdef USE_IDMEF +extern "C" { +#include +} +#endif + +#include + +char* port_to_string(PortVal* port) + { + char buf[256]; // to hold sprintf results on port numbers + snprintf(buf, sizeof(buf), "%u", port->Port()); + return copy_string(buf); + } + +%%} + +## Deprecated. Will be removed. +function generate_idmef%(src_ip: addr, src_port: port, + dst_ip: addr, dst_port: port%) : bool + %{ +#ifdef USE_IDMEF + xmlNodePtr message = + newIDMEF_Message(newAttribute("version","1.0"), + newAlert(newCreateTime(NULL), + newSource( + newNode(newAddress( + newAttribute("category","ipv4-addr"), + newSimpleElement("address", + copy_string(src_ip->AsAddr().AsString().c_str())), + NULL), NULL), + newService( + newSimpleElement("port", + port_to_string(src_port)), + NULL), NULL), + newTarget( + newNode(newAddress( + newAttribute("category","ipv4-addr"), + newSimpleElement("address", + copy_string(dst_ip->AsAddr().AsString().c_str())), + NULL), NULL), + newService( + newSimpleElement("port", + port_to_string(dst_port)), + NULL), NULL), NULL), NULL); + + // if ( validateCurrentDoc() ) + printCurrentMessage(stderr); + return new Val(1, TYPE_BOOL); +#else + builtin_error("Bro was not configured for IDMEF support"); + return new Val(0, TYPE_BOOL); +#endif + %} diff --git a/src/bro.pac b/src/bro.pac index 169f7c27ef..b622041c12 100644 --- a/src/bro.pac +++ b/src/bro.pac @@ -1,5 +1,3 @@ -# $Id:$ - %extern{ #include "binpac_bro.h" %} diff --git a/src/bro_inet_ntop.c b/src/bro_inet_ntop.c new file mode 100644 index 0000000000..c66c1daeda --- /dev/null +++ b/src/bro_inet_ntop.c @@ -0,0 +1,189 @@ +/* Taken/adapted from FreeBSD 9.0.0 inet_ntop.c (CVS revision 1.3.16.1.2.1) */ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "bro_inet_ntop.h" + +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +/*% + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *bro_inet_ntop4(const u_char *src, char *dst, socklen_t size); +static const char *bro_inet_ntop6(const u_char *src, char *dst, socklen_t size); + +/* char * + * bro_inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +bro_inet_ntop(int af, const void * __restrict src, char * __restrict dst, + socklen_t size) +{ + switch (af) { + case AF_INET: + return (bro_inet_ntop4(src, dst, size)); + case AF_INET6: + return (bro_inet_ntop6(src, dst, size)); + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * bro_inet_ntop4(src, dst, size) + * format an IPv4 address + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. Modified by Jon Siwek, 2012, to replace strlcpy + */ +static const char * +bro_inet_ntop4(const u_char *src, char *dst, socklen_t size) +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + int l; + + l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]); + if (l <= 0 || (socklen_t) l >= size) { + errno = ENOSPC; + return (NULL); + } + strncpy(dst, tmp, size - 1); + dst[size - 1] = 0; + return (dst); +} + +/* const char * + * bro_inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. Modified by Jon Siwek, 2012, for IPv4-translated format + */ +static const char * +bro_inet_ntop6(const u_char *src, char *dst, socklen_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < NS_IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + best.len = 0; + cur.base = -1; + cur.len = 0; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && (best.len == 6 || + (best.len == 7 && words[7] != 0x0001) || + (best.len == 5 && words[5] == 0xffff) || + (best.len == 4 && words[4] == 0xffff && words[5] == 0))) { + if (!bro_inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + tp += sprintf(tp, "%x", words[i]); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((socklen_t)(tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} diff --git a/src/bro_inet_ntop.h b/src/bro_inet_ntop.h new file mode 100644 index 0000000000..00326b092e --- /dev/null +++ b/src/bro_inet_ntop.h @@ -0,0 +1,18 @@ +#ifndef BRO_INET_NTOP_H +#define BRO_INET_NTOP_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +const char * +bro_inet_ntop(int af, const void * __restrict src, char * __restrict dst, + socklen_t size); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/bsd-getopt-long.c b/src/bsd-getopt-long.c index 5b3cc093b0..7ecb064fc8 100644 --- a/src/bsd-getopt-long.c +++ b/src/bsd-getopt-long.c @@ -1,5 +1,3 @@ -/* $Id: bsd-getopt-long.c 1362 2005-09-12 19:49:08Z vern $ */ - /* $OpenBSD: getopt_long.c,v 1.17 2004/06/03 18:46:52 millert Exp $ */ /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ diff --git a/src/bsd-getopt-long.h b/src/bsd-getopt-long.h index e2c381f3b7..c94589afaa 100644 --- a/src/bsd-getopt-long.h +++ b/src/bsd-getopt-long.h @@ -1,5 +1,3 @@ -/* $Id: bsd-getopt-long.h 1361 2005-09-12 19:48:26Z vern $ */ - /* $OpenBSD: getopt_long.c,v 1.13 2003/06/03 01:52:40 millert Exp $ */ /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ diff --git a/src/builtin-func.l b/src/builtin-func.l index 9e69adc69d..1d61f31734 100644 --- a/src/builtin-func.l +++ b/src/builtin-func.l @@ -1,6 +1,4 @@ %{ -// $Id: builtin-func.l 6015 2008-07-23 05:42:37Z vern $ - #include #include #include "bif_arg.h" diff --git a/src/const.bif b/src/const.bif index 447812a902..0ebd210a95 100644 --- a/src/const.bif +++ b/src/const.bif @@ -1,6 +1,6 @@ -# $Id: const.bif 3929 2007-01-14 00:37:59Z vern $ - -# Documentation and default values for these are located in policy/bro.init. +##! Declaration of various scripting-layer constants that the Bro core uses +##! internally. Documentation and default values for the scripting-layer +##! variables themselves are found in :doc:`/scripts/base/init-bare`. const ignore_keep_alive_rexmit: bool; const skip_http_data: bool; diff --git a/src/cq.c b/src/cq.c index b669dabd35..c5405e526a 100644 --- a/src/cq.c +++ b/src/cq.c @@ -2,11 +2,6 @@ * See the file "COPYING" in the main distribution directory for copyright. */ -#ifndef lint -static const char rcsid[] = - "@(#) $Id: cq.c 6219 2008-10-01 05:39:07Z vern $ (LBL)"; -#endif - #include #include diff --git a/src/cq.h b/src/cq.h index 38c5204f0c..540cccde74 100644 --- a/src/cq.h +++ b/src/cq.h @@ -1,5 +1,3 @@ -/* @(#) $Id: cq.h 80 2004-07-14 20:15:50Z jason $ (LBL) */ - struct cq_handle *cq_init(double, double); void cq_destroy(struct cq_handle *); int cq_enqueue(struct cq_handle *, double, void *); diff --git a/src/dce_rpc-analyzer.pac b/src/dce_rpc-analyzer.pac index 353c9f3795..ddc99abd8e 100644 --- a/src/dce_rpc-analyzer.pac +++ b/src/dce_rpc-analyzer.pac @@ -1,5 +1,3 @@ -# $Id:$ - # DCE/RPC protocol data unit. type DCE_RPC_PDU = record { diff --git a/src/dce_rpc-protocol.pac b/src/dce_rpc-protocol.pac index 77c7aaff62..a7bfcb5368 100644 --- a/src/dce_rpc-protocol.pac +++ b/src/dce_rpc-protocol.pac @@ -1,5 +1,3 @@ -# $Id: dce_rpc-protocol.pac,v 1.1.4.2 2006/06/02 15:13:09 rpang Exp $ -# # Definitions for DCE RPC. enum dce_rpc_ptype { diff --git a/src/dce_rpc.pac b/src/dce_rpc.pac index 58c2250c26..cbcd0cbdc4 100644 --- a/src/dce_rpc.pac +++ b/src/dce_rpc.pac @@ -1,5 +1,3 @@ -# $Id: dce_rpc.pac 4608 2007-07-05 18:23:58Z vern $ - %include binpac.pac %include bro.pac diff --git a/src/dce_rpc_simple.pac b/src/dce_rpc_simple.pac index ff495a2e2b..f31c2a078b 100644 --- a/src/dce_rpc_simple.pac +++ b/src/dce_rpc_simple.pac @@ -1,5 +1,3 @@ -# $Id:$ - %include bro.pac analyzer DCE_RPC_Simple withcontext {}; diff --git a/src/dhcp-analyzer.pac b/src/dhcp-analyzer.pac index ef8b888330..5267075445 100644 --- a/src/dhcp-analyzer.pac +++ b/src/dhcp-analyzer.pac @@ -1,5 +1,3 @@ -# $Id:$ - connection DHCP_Conn(bro_analyzer: BroAnalyzer) { upflow = DHCP_Flow(true); downflow = DHCP_Flow(false); @@ -57,33 +55,18 @@ flow DHCP_Flow(is_orig: bool) { vector::const_iterator ptr; // Requested IP address to the server. -#ifdef BROv6 - ::uint32 req_addr[4], serv_addr[4]; - - req_addr[0] = req_addr[1] = req_addr[2] = req_addr[3] = 0; - serv_addr[0] = serv_addr[1] = serv_addr[2] = serv_addr[3] = 0; -#else - addr_type req_addr = 0, serv_addr = 0; -#endif + ::uint32 req_addr = 0, serv_addr = 0; for ( ptr = options->begin(); ptr != options->end() && ! (*ptr)->last(); ++ptr ) { switch ( (*ptr)->code() ) { case REQ_IP_OPTION: -#ifdef BROv6 - req_addr[3] = htonl((*ptr)->info()->req_addr()); -#else req_addr = htonl((*ptr)->info()->req_addr()); -#endif break; case SERV_ID_OPTION: -#ifdef BROv6 - serv_addr[3] = htonl((*ptr)->info()->serv_addr()); -#else serv_addr = htonl((*ptr)->info()->serv_addr()); -#endif break; } } @@ -93,13 +76,14 @@ flow DHCP_Flow(is_orig: bool) { case DHCPDISCOVER: BifEvent::generate_dhcp_discover(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), - dhcp_msg_val_->Ref(), req_addr); + dhcp_msg_val_->Ref(), new AddrVal(req_addr)); break; case DHCPREQUEST: BifEvent::generate_dhcp_request(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), - dhcp_msg_val_->Ref(), req_addr, serv_addr); + dhcp_msg_val_->Ref(), new AddrVal(req_addr), + new AddrVal(serv_addr)); break; case DHCPDECLINE: @@ -131,15 +115,7 @@ flow DHCP_Flow(is_orig: bool) { // RFC 1533 allows a list of router addresses. TableVal* router_list = 0; -#ifdef BROv6 - ::uint32 subnet_mask[4], serv_addr[4]; - - subnet_mask[0] = subnet_mask[1] = - subnet_mask[2] = subnet_mask[3] = 0; - serv_addr[0] = serv_addr[1] = serv_addr[2] = serv_addr[3] = 0; -#else - addr_type subnet_mask = 0, serv_addr = 0; -#endif + ::uint32 subnet_mask = 0, serv_addr = 0; uint32 lease = 0; @@ -148,13 +124,7 @@ flow DHCP_Flow(is_orig: bool) { { switch ( (*ptr)->code() ) { case SUBNET_OPTION: -#ifdef BROv6 - subnet_mask[0] = - subnet_mask[1] = subnet_mask[2] = 0; - subnet_mask[3] = htonl((*ptr)->info()->mask()); -#else subnet_mask = htonl((*ptr)->info()->mask()); -#endif break; case ROUTER_OPTION: @@ -172,14 +142,8 @@ flow DHCP_Flow(is_orig: bool) { vector* rlist = (*ptr)->info()->router_list(); uint32 raddr = (*rlist)[i]; -#ifdef BROv6 - ::uint32 tmp_addr[4]; - tmp_addr[0] = tmp_addr[1] = tmp_addr[2] = 0; - tmp_addr[3] = htonl(raddr); -#else ::uint32 tmp_addr; tmp_addr = htonl(raddr); -#endif // index starting from 1 Val* index = new Val(i + 1, TYPE_COUNT); router_list->Assign(index, new AddrVal(tmp_addr)); @@ -193,11 +157,7 @@ flow DHCP_Flow(is_orig: bool) { break; case SERV_ID_OPTION: -#ifdef BROv6 - serv_addr[3] = htonl((*ptr)->info()->serv_addr()); -#else serv_addr = htonl((*ptr)->info()->serv_addr()); -#endif break; } } @@ -206,15 +166,15 @@ flow DHCP_Flow(is_orig: bool) { case DHCPOFFER: BifEvent::generate_dhcp_offer(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), - dhcp_msg_val_->Ref(), subnet_mask, - router_list, lease, serv_addr); + dhcp_msg_val_->Ref(), new AddrVal(subnet_mask), + router_list, lease, new AddrVal(serv_addr)); break; case DHCPACK: BifEvent::generate_dhcp_ack(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), - dhcp_msg_val_->Ref(), subnet_mask, - router_list, lease, serv_addr); + dhcp_msg_val_->Ref(), new AddrVal(subnet_mask), + router_list, lease, new AddrVal(serv_addr)); break; case DHCPNAK: diff --git a/src/dhcp-protocol.pac b/src/dhcp-protocol.pac index 46cceb56c6..d77780b1b3 100644 --- a/src/dhcp-protocol.pac +++ b/src/dhcp-protocol.pac @@ -1,5 +1,3 @@ -# $Id:$ - # DHCP Message Type according to RFC 1533. # Refer to RFC 2131 for op types. diff --git a/src/dhcp.pac b/src/dhcp.pac index 852433a410..9e9d7755a4 100644 --- a/src/dhcp.pac +++ b/src/dhcp.pac @@ -1,5 +1,3 @@ -# $Id:$ - %include bro.pac analyzer DHCP withcontext { diff --git a/src/dns-analyzer.pac b/src/dns-analyzer.pac index 72bda3165f..e92b6ef709 100644 --- a/src/dns-analyzer.pac +++ b/src/dns-analyzer.pac @@ -1,5 +1,3 @@ -# $Id:$ - %extern{ #include %} @@ -218,44 +216,42 @@ flow DNS_Flow switch ( rr->rr_type() ) { case TYPE_A: + if ( dns_A_reply ) + { + ::uint32 addr = rd->type_a(); + BifEvent::generate_dns_A_reply(connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + dns_msg_val_->Ref(), build_dns_answer(rr), + new AddrVal(htonl(addr))); + } + break; + case TYPE_A6: - case TYPE_AAAA: - if ( ! dns_A_reply ) - break; - -#ifdef BROv6 - ::uint32 addr[4]; -#else - addr_type addr; -#endif - - if ( rr->rr_type() == TYPE_A ) + if ( dns_A6_reply ) { -#ifdef BROv6 - addr[0] = addr[1] = addr[2] = 0; - addr[3] = htonl(rd->type_a()); -#else - addr = htonl(rd->type_a()); -#endif - } - - else - { -#ifdef BROv6 - for ( int i = 0; i < 4; ++i ) + ::uint32 addr[4]; + for ( unsigned int i = 0; i < 4; ++i ) addr[i] = htonl((*rd->type_aaaa())[i]); -#else - addr = htonl((*rd->type_aaaa())[3]); -#endif - } - // For now, we treat A6 and AAAA as A's. Given the - // above fixes for BROv6, we can probably now introduce - // their own events. (It's not clear A6 is needed - - // do we actually encounter it in practice?) - BifEvent::generate_dns_A_reply(connection()->bro_analyzer(), - connection()->bro_analyzer()->Conn(), - dns_msg_val_->Ref(), build_dns_answer(rr), addr); + BifEvent::generate_dns_A6_reply(connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + dns_msg_val_->Ref(), build_dns_answer(rr), + new AddrVal(addr)); + } + break; + + case TYPE_AAAA: + if ( dns_AAAA_reply ) + { + ::uint32 addr[4]; + for ( unsigned int i = 0; i < 4; ++i ) + addr[i] = htonl((*rd->type_aaaa())[i]); + + BifEvent::generate_dns_AAAA_reply(connection()->bro_analyzer(), + connection()->bro_analyzer()->Conn(), + dns_msg_val_->Ref(), build_dns_answer(rr), + new AddrVal(addr)); + } break; case TYPE_NS: diff --git a/src/dns-protocol.pac b/src/dns-protocol.pac index d5b8036e11..fbeb9d0fa3 100644 --- a/src/dns-protocol.pac +++ b/src/dns-protocol.pac @@ -1,5 +1,3 @@ -# $Id:$ - enum DNS_answer_type { DNS_QUESTION, DNS_ANSWER, diff --git a/src/dns.pac b/src/dns.pac index dc5ca586f8..aeffdf0bc7 100644 --- a/src/dns.pac +++ b/src/dns.pac @@ -1,5 +1,3 @@ -# $Id:$ - %include bro.pac analyzer DNS withcontext { diff --git a/src/dns_tcp.pac b/src/dns_tcp.pac index f2c7f5f523..d31ff58c6e 100644 --- a/src/dns_tcp.pac +++ b/src/dns_tcp.pac @@ -1,5 +1,3 @@ -# $Id:$ - %extern{ #include "dns_pac.h" // for DNS_Conn %} diff --git a/src/epmapper.pac b/src/epmapper.pac index c9eea3c139..7fbaf47418 100644 --- a/src/epmapper.pac +++ b/src/epmapper.pac @@ -1,5 +1,3 @@ -# $Id:$ - type epmapper_lookup_req = record { inquiry_type : uint32; # object : uuid_p_t; diff --git a/src/event.bif b/src/event.bif index c3c11b6a7e..1ce8907f0b 100644 --- a/src/event.bif +++ b/src/event.bif @@ -1,483 +1,6425 @@ -# $Id: event.bif 6942 2009-11-16 03:54:08Z vern $ +##! The events that the C/C++ core of Bro can generate. This is mostly +##! consisting of high-level network events that protocol analyzers detect, +##! but there are also several general-utility events generated by internal +##! Bro frameworks. +# +# Documentation conventions: +# +# - Use past tense for activity that has already occured. +# +# - List parameters with an empty line in between. +# +# - Within the description, reference other parameters of the same events +# as *arg*. +# +# - Order: +# +# - Short initial sentence (which doesn't need to be a sentence), +# starting with "Generated ..." +# +# - Description +# +# - Parameters +# +# - .. bro:see:: +# +# - .. note:: +# +# - .. todo:: + +## Generated at Bro initialization time. The event engine generates this +## event just before normal input processing begins. It can be used to execute +## one-time initialization code at startup. At the time a handler runs, Bro will +## have executed any global initializations and statements. +## +## .. bro:see:: bro_done +## +## .. note:: +## +## When a ``bro_init`` handler executes, Bro has not yet seen any input packets +## and therefore :bro:id:`network_time` is not initialized yet. An artifact +## of that is that any timer installed in a ``bro_init`` handler will fire +## immediately with the first packet. The standard way to work around that is to +## ignore the first time the timer fires and immediately reschedule. +## event bro_init%(%); + +## Generated at Bro termination time. The event engine generates this event when +## Bro is about to terminate, either due to having exhausted reading its input +## trace file(s), receiving a termination signal, or because Bro was run without +## a network input source and has finished executing any global statements. +## +## .. bro:see:: bro_init +## +## .. note:: +## +## If Bro terminates due to an invocation of :bro:id:`exit`, then this event is +## not generated. event bro_done%(%); +## Generated when an internal DNS lookup reduces the same result as last time. +## Bro keeps an internal DNS cache for host names and IP addresses it has +## already resolved. This event is generated when subsequent lookup returns +## the same result as stored in the cache. +## +## dm: A record describing the new resolver result (which matches the old one). +## +## .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified event dns_mapping_valid%(dm: dns_mapping%); + +## Generated when an internal DNS lookup got no answer even though it had succeeded he +## past. Bro keeps an internal DNS cache for host names and IP addresses it has +## already resolved. This event is generated when a subsequent lookup does not +## produce an answer even though we have already stored a result in the cache. +## +## dm: A record describing the old resolver result. +## +## .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_valid event dns_mapping_unverified%(dm: dns_mapping%); + +## Generated when an internal DNS lookup succeeed but an earlier attempt not. had +## had succeeded he past. Bro keeps an internal DNS cache for host names and IP +## addresses it has already resolved. This event is generated when a subsequent +## lookup produces an answer for a query that was marked as failed in the cache. +## +## dm: A record describing the new resolver result. +## +## .. bro:see:: dns_mapping_altered dns_mapping_lost_name dns_mapping_unverified +## dns_mapping_valid event dns_mapping_new_name%(dm: dns_mapping%); + +## Generated when an internal DNS lookup returned zero answers even though it +## had succeeded he past. Bro keeps an internal DNS cache for host names and IP +## addresses it has already resolved. This event is generated when for a subsequent +## lookup we received answer that however was empty even though we have +## already stored a result in the cache. +## +## dm: A record describing the old resolver result. +## +## .. bro:see:: dns_mapping_altered dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid event dns_mapping_lost_name%(dm: dns_mapping%); -event dns_mapping_name_changed%(old_dm: dns_mapping, new_dm: dns_mapping%); + +## Generated when an internal DNS lookup produced a different result than in +## past. Bro keeps an internal DNS cache for host names and IP addresses it has +## already resolved. This event is generated when a subsequent lookup returns +## a different answer than we have stored in the cache. +## +## dm: A record describing the new resolver result. +## +## old_addrs: Addresses that used to be part of the returned set for the query +## described by *dm*, but are not anymore. +## +## new_addrs: Addresses that did not use to be part of the returned set for the +## query described by *dm*, but now are. +## +## .. bro:see:: dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid event dns_mapping_altered%(dm: dns_mapping, old_addrs: addr_set, new_addrs: addr_set%); +## Generated for every new connection. The event is raised with the first packet +## of a previously unknown connection. Bro uses a flow-based definition of +## "connection" here that includes not only TCP sessions but also UDP and ICMP +## flows. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_rejected connection_reset connection_reused +## connection_state_remove connection_status_update connection_timeout +## expected_connection_seen new_connection_contents partial_connection +## +## .. note:: +## +## Handling this event is potentially expensive. For example, during a SYN +## flooding attack, every spoofed SYN packet will lead to a new +## event. event new_connection%(c: connection%); + +## Generated when reassembly starts for a TCP connection. The event is raised +## at the moment when Bro's TCP analyzer enables stream reassembly for a +## connection. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_rejected connection_reset connection_reused +## connection_state_remove connection_status_update connection_timeout +## expected_connection_seen new_connection partial_connection event new_connection_contents%(c: connection%); -event new_packet%(c: connection, p: pkt_hdr%); + +## Generated for an unsuccessful connection attempt. The event is raised when an +## originator unsuccessfully attempted to establish a connection. "Unsuccessful" +## is defined as at least :bro:id:`tcp_attempt_delay` seconds having elapsed since +## the originator first sent a connection establishment packet to the destination +## without seeing a reply. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_established +## connection_external connection_finished connection_first_ACK +## connection_half_finished connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection event connection_attempt%(c: connection%); + +## Generated for an established TCP connection. The event is raised when the +## initial 3-way TCP handshake has successfully finished for a connection. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_external connection_finished connection_first_ACK +## connection_half_finished connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection event connection_established%(c: connection%); + +## Generated for a new active TCP connection if Bro did not see the initial +## handshake. The event is raised when Bro has observed traffic from each endpoint, +## but the activity did not begin with the usual connection establishment. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_rejected connection_reset connection_reused +## connection_state_remove connection_status_update connection_timeout +## expected_connection_seen new_connection new_connection_contents +## event partial_connection%(c: connection%); + +## Generated when a previously inactive endpoint attempts to close a TCP connection +## via a normal FIN handshake or an abort RST sequence. When the endpoint sent +## one of these packets, Bro waits :bro:id:`tcp_partial_close_delay` prior +## to generating the event, to give the other endpoint a chance to close the +## connection normally. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection event connection_partial_close%(c: connection%); + +## Generated for a TCP connection that finished normally. The event is raised +## when a regular FIN handshake from both endpoints was observed. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_first_ACK +## connection_half_finished connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection event connection_finished%(c: connection%); + +## Generated when one endpoint of a TCP connection attempted to gracefully close +## the connection, but the other endpoint is in the TCP_INACTIVE state. This can +## happen due to split routing, in which Bro only sees one side of a connection. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection event connection_half_finished%(c: connection%); + +## Generated for a rejected TCP connection. The event is raised when an originator +## attempted to setup a TCP connection but the responder replied with a RST packet +## denying it. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection +## +## c: The connection. +## +## .. note:: +## +## If the responder does not respond at all, :bro:id:`connection_attempt` is +## raised instead. If the responder initially accepts the connection but aborts +## it later, Bro first generates :bro:id:`connection_established` and then +## :bro:id:`connection_reset`. event connection_rejected%(c: connection%); + +## Generated when an endpoint aborted a TCP connection. The event is raised +## when one endpoint of an established TCP connection aborted by sending a RST +## packet. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_rejected connection_reused +## connection_state_remove connection_status_update connection_timeout +## expected_connection_seen new_connection new_connection_contents +## partial_connection event connection_reset%(c: connection%); + +## Generated for each still-open connection when Bro terminates. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection bro_done event connection_pending%(c: connection%); + +## Generated when a connection's internal state is about to be removed from +## memory. Bro generates this event reliably once for every connection when it +## is about to delete the internal state. As such, the event is well-suited for +## scrip-level cleanup that needs to be performed for every connection. The +## ``connection_state_remove`` event is generated not only for TCP sessions but +## also for UDP and ICMP flows. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_rejected connection_reset connection_reused +## connection_status_update connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection udp_inactivity_timeout +## tcp_inactivity_timeout icmp_inactivity_timeout conn_stats event connection_state_remove%(c: connection%); + +## Generated for a SYN packet. Bro raises this event for every SYN packet seen by +## its TCP analyzer. +## +## c: The connection. +## +## pkt: Information extracted from the SYN packet. +## +## .. bro:see:: connection_EOF connection_attempt connection_established +## connection_external connection_finished connection_first_ACK +## connection_half_finished connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection +## +## .. note:: +## +## This event has quite low-level semantics and can potentially be expensive to +## generate. It should only be used if one really needs the specific information +## passed into the handler via the ``pkt`` argument. If not, handling one of the +## other ``connection_*`` events is typically the better approach. event connection_SYN_packet%(c: connection, pkt: SYN_packet%); + +## Generated for the first ACK packet seen for a TCP connection from +## its *orginator*. +## +## c: The connection. +## +## pkt: Information extracted from the SYN packet. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_half_finished connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection +## +## .. note:: +## +## This event has quite low-level semantics and should be used only rarely. event connection_first_ACK%(c: connection%); + +## Generated when a TCP connection timed out. This event is raised when no activity +## was seen for an interval of at least :bro:id:`tcp_connection_linger`, and +## either one endpoint has already closed the connection or one side never +## never became active. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_rejected connection_reset connection_reused +## connection_state_remove connection_status_update expected_connection_seen +## new_connection new_connection_contents partial_connection +## +## .. note:: +## +## The precise semantics of this event can be unintuitive as it only +## covers a subset of cases where a connection times out. Often, handling +## :bro:id:`connection_state_remove` is the better option. That one will be +## generated reliably when an interval of ``tcp_inactivity_timeout`` has passed +## with out any activity seen (but also for all other ways a connection may +## terminate). event connection_timeout%(c: connection%); + +## Generated when a connection 4-tuple is reused. The event is raised when Bro +## sees a new TCP session or UDP flow using a 4-tuple matching that of an earlier +## connection it still consideres active. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_rejected connection_reset connection_state_remove +## connection_status_update connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection event connection_reused%(c: connection%); + +## Generated in regular intervals during the life time of a connection. The +## events is raised each ``connection_status_update_interval`` seconds +## and can be used to check conditions on a regular basis. +## +## c: The connection. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_rejected connection_reset connection_reused +## connection_state_remove connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection event connection_status_update%(c: connection%); + +## Generated at the end of reassembled TCP connections. The TCP reassembler +## raised the event once for each endpoint of a connection when it finished +## reassembling the corresponding side of the communication. +## +## c: The connection. +## +## is_orig: True if the event is raised for the originator side. +## +## .. bro:see:: connection_SYN_packet connection_attempt connection_established +## connection_external connection_finished connection_first_ACK +## connection_half_finished connection_partial_close connection_pending +## connection_rejected connection_reset connection_reused connection_state_remove +## connection_status_update connection_timeout expected_connection_seen +## new_connection new_connection_contents partial_connection event connection_EOF%(c: connection, is_orig: bool%); + +## Generated for a new connection received from the communication subsystem. Remote +## peers can inject packets into Bro's packet loop, for example via :doc:`Broccoli +## `. The communication systems raises this event +## with the first packet of a connection coming in this way. event connection_external%(c: connection, tag: string%); + +## Generated when a connected is seen that has previously marked as being expected. +## The function :bro:id:`expect_connection` tells Bro to expect a particular +## connection to come up, and which analyzer to associate with it. Once the +## first packet of such a connection is indeed seen, this event is raised. +## +## c: The connection. +## +## a: The analyzer that was scheduled for the connection with the +## :bro:id:`expect_connection` call. When the event is raised, that +## analyzer will already have been activated to process the connection. The +## ``count`` is one of the ``ANALYZER_*`` constants, e.g., ``ANALYZER_HTTP``. +## +## .. bro:see:: connection_EOF connection_SYN_packet connection_attempt +## connection_established connection_external connection_finished +## connection_first_ACK connection_half_finished connection_partial_close +## connection_pending connection_rejected connection_reset connection_reused +## connection_state_remove connection_status_update connection_timeout +## new_connection new_connection_contents partial_connection +## +## .. todo: We don't have a good way to document the automatically generated +## ``ANALYZER_*`` constants right now. event expected_connection_seen%(c: connection, a: count%); +## Generated for every packet Bro sees. This is a very low-level and expensive +## event that should be avoided when at all possible. Is's usually infeasible to +## handle when processing even medium volumes of traffic in real-time. That +## said, if you work from a trace and want to do some packet-level analysis, +## it may come in handy. +## +## c: The connection the packet is part of. +## +## p: Information from the header of the packet that triggered the event. +## +## .. bro:see:: tcp_packet packet_contents +event new_packet%(c: connection, p: pkt_hdr%); + +## Generated for every IPv6 packet that contains extension headers. +## This is potentially an expensive event to handle if analysiing IPv6 traffic +## that happens to utilize extension headers frequently. +## +## c: The connection the packet is part of. +## +## p: Information from the header of the packet that triggered the event. +## +## .. bro:see:: new_packet tcp_packet packet_contents esp_packet +event ipv6_ext_headers%(c: connection, p: pkt_hdr%); + +## Generated for any packets using the IPv6 Encapsulating Security Payload (ESP) +## extension header. +## +## p: Information from the header of the packet that triggered the event. +## +## .. bro:see:: new_packet tcp_packet ipv6_ext_headers +event esp_packet%(p: pkt_hdr%); + +## Generated for any packet using a Mobile IPv6 Mobility Header. +## +## p: Information from the header of the packet that triggered the event. +## +## .. bro:see:: new_packet tcp_packet ipv6_ext_headers +event mobile_ipv6_message%(p: pkt_hdr%); + +## Generated for every packet that has non-empty transport-layer payload. This is a +## very low-level and expensive event that should be avoided when at all possible. +## It's usually infeasible to handle when processing even medium volumes of +## traffic in real-time. It's even worse than :bro:id:`new_packet`. That said, if +## you work from a trace and want to do some packet-level analysis, it may come in +## handy. +## +## c: The connection the packet is part of. +## +## contants: The raw transport-layer payload. +## +## .. bro:see:: new_packet tcp_packet +event packet_contents%(c: connection, contents: string%); + +## Generated for every TCP packet. This is a very low-level and expensive event +## that should be avoided when at all possible. It's usually infeasible to handle +## when processing even medium volumes of traffic in real-time. It's slightly +## better than :bro:id:`new_packet` because it affects only TCP, but not much. That +## said, if you work from a trace and want to do some packet-level analysis, it may +## come in handy. +## +## c: The connection the packet is part of. +## +## is_orig: True if the packet was sent by the connection's originator. +## +## flags: A string with the packet's TCP flags. In the string, each character +## corresponds to one set flag, as follows: ``S`` -> SYN; ``F`` -> FIN; +## ``R`` -> RST; ``A`` -> ACK; ``P`` -> PUSH. +## +## seq: The packet's TCP sequence number. +## +## ack: The packet's ACK number. +## +## len: The length of the TCP payload, as specified in the packet header. +## +## payload: The raw TCP payload. Note that this may less than *len* if the packet +## was not fully captured. +## +## .. bro:see:: new_packet packet_contents tcp_option tcp_contents tcp_rexmit +event tcp_packet%(c: connection, is_orig: bool, flags: string, seq: count, ack: count, len: count, payload: string%); + +## Generated for each option found in a TCP header. Like many of the ``tcp_*`` +## events, this is a very low-level event and potentially expensive as it may +## be raised very often. +## +## c: The connection the packet is part of. +## +## is_orig: True if the packet was sent by the connection's originator. +## +## opt: The numerical option number, as found in the TCP header. +## +## optlen: The length of the options value. +## +## .. bro:see:: tcp_packet tcp_contents tcp_rexmit +## +## .. note:: There is currently no way to get the actual option value, if any. +event tcp_option%(c: connection, is_orig: bool, opt: count, optlen: count%); + +## Generated for each chunk of reassembled TCP payload. When content delivery is +## enabled for a TCP connection (via :bro:id:`tcp_content_delivery_ports_orig`, +## :bro:id:`tcp_content_delivery_ports_resp`, +## :bro:id:`tcp_content_deliver_all_orig`, +## :bro:id:`tcp_content_deliver_all_resp`), this event is raised for each chunk +## of in-order payload reconstructed from the packet stream. Note that this event +## is potentially expensive if many connections carry signficant amounts of data as +## then all that needs to be passed on to the scripting layer. +## +## c: The connection the payload is part of. +## +## is_orig: True if the packet was sent by the connection's originator. +## +## seq: The sequence number corresponding to the first byte of the payload +## chunk. +## +## payload: The raw payload, which will be non-empty. +## +## .. bro:see:: tcp_packet tcp_option tcp_rexmit +## tcp_content_delivery_ports_orig tcp_content_delivery_ports_resp +## tcp_content_deliver_all_resp tcp_content_deliver_all_orig +## +## .. note:: +## +## The payload received by this event is the same that is also passed into +## application-layer protocol analyzers internally. Subsequent invocations of +## this event for the same connection receive non-overlapping in-order chunks +## of its TCP payload stream. It is however undefined what size each chunk +## has; while Bro passes the data on as soon as possible, specifics depend on +## network-level effects such as latency, acknowledgements, reordering, etc. +event tcp_contents%(c: connection, is_orig: bool, seq: count, contents: string%); + +## Generated +event tcp_rexmit%(c: connection, is_orig: bool, seq: count, len: count, data_in_flight: count, window: count%); + +## Generated when Bro detects a TCP retransmission inconsistency. When +## reassemling TCP stream, Bro buffers all payload until it seens the responder +## acking it. If during time, the sender resends a chunk of payload but with +## content than originally, this event will be raised. +## +## c: The connection showing the inconsistency. +## +## t1: The original payload. +## +## t2: The new payload. +## +## .. bro:see:: tcp_rexmit tcp_contents +event rexmit_inconsistency%(c: connection, t1: string, t2: string%); + +## Generated when a TCP endpoint acknowledges payload that Bro did never see. +## +## c: The connection. +## +## .. bro:see:: content_gap +## +## .. note:: +## +## Seeing an acknowledgment indicates that the responder of the connection +## says it has received the corresponding data. If Bro did not, it must have +## either missed one or more packets, or the responder's TCP stack is broken +## (which isn't unheard of). In practice, one will always see a few of these +## events in any larger volume of network traffic. If there are lots of them, +## however, that typically means that there is a problem with the monitoring +## infrastructure such as a tap dropping packets, split routing on the path, or +## reordering at the tap. +## +## This event reports similar situations as :bro:id:`content_gap`, though their +## specifics differ slightly. Often, however, both will be raised for the same +## connection if some of its data is missing. We should eventually merge +## the two. +event ack_above_hole%(c: connection%); + +## Generated when Bro detects a gap in a reassembled TCP payload stream. This event +## is raised when Bro, while reassemling a payload stream, determines that a chunk +## of payload is missing (e.g., because the responder has already acknowledged it, +## even though Bro didn't see it). +## +## c: The connection. +## +## is_orig: True if the gap is on the originator's side. +## +## seq: The sequence number where the gap starts. +## +## length: The number of bytes missing. +## +## .. bro:see:: ack_above_hole +## +## .. note:: +## +## Content gaps tend to occur occasionally for various reasons, including broken +## TCP stacks. If, however, one finds lots of them, that typically means that +## there is a problem with the monitoring infrastructure such as a tap dropping +## packets, split routing on the path, or reordering at the tap. +## +## This event reports similar situations as :bro:id:`ack_above_hole`, though +## their specifics differ slightly. Often, however, both will be raised for +## connection if some of its data is missing. We should eventually merge the +## two. +event content_gap%(c: connection, is_orig: bool, seq: count, length: count%); + +## Summarizes the amount of missing TCP payload at regular intervals. Internally, +## Bro tracks (1) the number of :bro:id:`ack_above_hole` events, including the +## numer of bytes missing; and (2) the total number of TCP acks seen, with the +## total volume of bytes that have been acked. This event reports these statistics +## in :bro:id:`gap_report_freq` intervals for the purpose of determining packet +## loss. +## +## dt: The time that has past since the last ``gap_report`` interval. +## +## info: The gap statistics. +## +## .. bro:see:: content_gap ack_above_hole +## +## .. note:: +## +## Bro comes with a script :doc:`/scripts/policy/misc/capture-loss` that uses +## this event to estimate packet loss and report when a predefined threshold is +## exceeded. +event gap_report%(dt: interval, info: gap_info%); + + +## Generated when a protocol analyzer confirms that a connection is indeed +## using that protocol. Bro's dynamic protocol detection heuristically activates +## analyzers as soon as it believe a connection *could* be using a particular +## protocol. It is then left to the corresponding analyzer to verify whether that +## is indeed the case; if so, this event will be generated. +## +## c: The connection. +## +## atype: The type of the analyzer confirming that its protocol is in +## use. The value is one of the ``ANALYZER_*`` constants. For example, +## ``ANALYZER_HTTP`` means the HTTP analyzers determined that it's indeed +## parsing an HTTP connection. +## +## aid: A unique integer ID identifying the specific *instance* of the +## analyzer *atype* that is analyzing the connection ``c``. The ID can +## be used to reference the analyzer when using builtin functions like +## :bro:id:`disable_analyzer`. +## +## .. bro:see:: protocol_violation +## +## .. note:: +## +## Bro's default scripts use this event to determine the ``service`` column of +## :bro:type:`Conn::Info`: once confirmed, the protocol will be listed there +## (and thus in ``conn.log``). event protocol_confirmation%(c: connection, atype: count, aid: count%); + +## Generated when a protocol analyzer determines that a connection it is parsing +## is not conforming to the protocol it expects. Bro's dynamic protocol detection +## heuristically activates analyzers as soon as it believe a connection *could* be +## using a particular protocol. It is then left to the corresponding analyzer to +## verify whether that is indeed the case; if not, the analyzer will trigger this +## event. +## +## c: The connection. +## +## atype: The type of the analyzer confirming that its protocol is in +## use. The value is one of the ``ANALYZER_*`` constants. For example, +## ``ANALYZER_HTTP`` means the HTTP analyzers determined that it's indeed +## parsing an HTTP connection. +## +## aid: A unique integer ID identifying the specific *instance* of the +## analyzer *atype* that is analyzing the connection ``c``. The ID can +## be used to reference the analyzer when using builtin functions like +## :bro:id:`disable_analyzer`. +## +## .. bro:see:: protocol_confirmation +## +## .. note:: +## +## Bro's default scripts use this event to disable an analyzer via +## :bro:id:`disable_analyzer` if it's parsing the wrong protocol. That's however +## a script-level decision and not done automatically by the event eninge. event protocol_violation%(c: connection, atype: count, aid: count, reason: string%); -event packet_contents%(c: connection, contents: string%); -event tcp_packet%(c: connection, is_orig: bool, flags: string, seq: count, ack: count, len: count, payload: string%); -event tcp_option%(c: connection, is_orig: bool, opt: count, optlen: count%); -event tcp_contents%(c: connection, is_orig: bool, seq: count, contents: string%); -event tcp_rexmit%(c: connection, is_orig: bool, seq: count, len: count, data_in_flight: count, window: count%); +## Generated for each packet sent by a UDP flow's originator. This a potentially +## expsensive event due to the volume of UDP traffic and should be used with care. +## +## u: The connection record for the corresponding UDP flow. +## +## .. bro:see:: udp_contents udp_reply udp_session_done event udp_request%(u: connection%); -event udp_reply%(u: connection%); -event udp_contents%(u: connection, is_orig: bool, contents: string%); -event udp_session_done%(u: connection%); -event icmp_sent%(c: connection, icmp: icmp_conn%); -event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); -event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); -event icmp_unreachable%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); -event icmp_time_exceeded%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); -event icmp_redirect%(c: connection, icmp: icmp_conn, a: addr%); -event conn_stats%(c: connection, os: endpoint_stats, rs: endpoint_stats%); -event conn_weird%(name: string, c: connection, addl: string%); -event flow_weird%(name: string, src: addr, dst: addr%); -event net_weird%(name: string%); -event load_sample%(samples: load_sample_info, CPU: interval, dmem: int%); -event rexmit_inconsistency%(c: connection, t1: string, t2: string%); -event ack_above_hole%(c: connection%); -event content_gap%(c: connection, is_orig: bool, seq: count, length: count%); -event gap_report%(dt: interval, info: gap_info%); -event inconsistent_option%(c: connection%); -event bad_option%(c: connection%); -event bad_option_termination%(c: connection%); +## Generated for each packet sent by a UDP flow's responder. This a potentially +## expsensive event due to the volume of UDP traffic and should be used with care. +## +## u: The connection record for the corresponding UDP flow. +## +## .. bro:see:: udp_contents udp_request udp_session_done +event udp_reply%(u: connection%); + +## Generated for UDP packets to pass on their payload. As the number of UDP +## packets can be very large, this event is normally raised only for those on +## ports configured in :bro:id:`udp_content_delivery_ports_orig` (for packets sent +## by the flow's orgininator) or :bro:id:`udp_content_delivery_ports_resp` (for +## packets sent by the flow's responder). However, delivery can be enabled for all +## UDP request and reply packets by setting :bro:id:`udp_content_deliver_all_orig` +## or :bro:id:`udp_content_deliver_all_resp`, respectively. Note that this event is +## also raised for all matching UDP packets, including empty ones. +## +## u: The connection record for the corresponding UDP flow. +## +## is_orig: True if the event is raised for the originator side. +## +## .. bro:see:: udp_reply udp_request udp_session_done +## udp_content_deliver_all_orig udp_content_deliver_all_resp +## udp_content_delivery_ports_orig udp_content_delivery_ports_resp +event udp_contents%(u: connection, is_orig: bool, contents: string%); + +## Generated when a UDP session for a supported protocol has finished. Some of +## Bro's application-layer UDP analyzers flag the end of a session by raising this +## event. Currently, the analyzers for DNS, NTP, Netbios, and Syslog support this. +## +## u: The connection record for the corresponding UDP flow. +## +## .. bro:see:: udp_contents udp_reply udp_request +event udp_session_done%(u: connection%); + +## Generated for all ICMP messages that are not handled separetely with dedicated +## ICMP events. Bro's ICMP analyzer handles a number of ICMP messages directly +## with dedicated events. This handlers acts as a fallback for those it doesn't. +## The *icmp* record provides more information about the message. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard +## connection record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect +## icmp_time_exceeded icmp_unreachable +event icmp_sent%(c: connection, icmp: icmp_conn%); + +## Generated for ICMP *echo request* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard +## connection record *c*. +## +## id: The *echo request* identifier. +## +## seq: The *echo request* sequence number. +## +## payload: The message-specific data of the packet payload, i.e., everything after +## the first 8 bytes of the ICMP header. +## +## .. bro:see:: icmp_echo_reply icmp_redirect icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_echo_request%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); + +## Generated for ICMP *echo reply* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## id: The *echo reply* identifier. +## +## seq: The *echo reply* sequence number. +## +## payload: The message-specific data of the packet payload, i.e., everything after +## the first 8 bytes of the ICMP header. +## +## .. bro:see:: icmp_echo_request icmp_redirect icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_echo_reply%(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string%); + +## Generated for all ICMP error messages that are not handled separately with dedicated +## ICMP events. Bro's ICMP analyzer handles a number of ICMP messages directly +## with dedicated events. This handler acts as a fallback for those it doesn't. +## The *icmp* record provides more information about the message. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard +## connection record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect +## icmp_time_exceeded icmp_unreachable +event icmp_error_message%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + +## Generated for ICMP *destination unreachable* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## code: The ICMP code of the *unreachable* message. +## +## context: A record with specifics of the original packet that the message refers +## to. *Unreachable* messages should include the original IP header from the packet +## that triggered them, and Bro parses that into the *context* structure. Note +## that if the *unreachable* includes only a partial IP header for some reason, no +## fields of *context* will be filled out. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect icmp_sent +## icmp_time_exceeded +event icmp_unreachable%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + +## Generated for ICMP *packet too big* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## code: The ICMP code of the *too big* message. +## +## context: A record with specifics of the original packet that the message refers +## to. *Too big* messages should include the original IP header from the packet +## that triggered them, and Bro parses that into the *context* structure. Note +## that if the *too big* includes only a partial IP header for some reason, no +## fields of *context* will be filled out. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect icmp_sent +## icmp_time_exceeded +event icmp_packet_too_big%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + +## Generated for ICMP *time exceeded* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## code: The ICMP code of the *exceeded* message. +## +## context: A record with specifics of the original packet that the message refers +## to. *Unreachable* messages should include the original IP header from the packet +## that triggered them, and Bro parses that into the *context* structure. Note that +## if the *exceeded* includes only a partial IP header for some reason, no fields +## of *context* will be filled out. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect icmp_sent +## icmp_unreachable +event icmp_time_exceeded%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + +## Generated for ICMP *parameter problem* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## code: The ICMP code of the *parameter problem* message. +## +## context: A record with specifics of the original packet that the message refers +## to. *Parameter problem* messages should include the original IP header from the packet +## that triggered them, and Bro parses that into the *context* structure. Note that +## if the *parameter problem* includes only a partial IP header for some reason, no fields +## of *context* will be filled out. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_redirect icmp_sent +## icmp_unreachable +event icmp_parameter_problem%(c: connection, icmp: icmp_conn, code: count, context: icmp_context%); + +## Generated for ICMP *router solicitation* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_router_solicitation%(c: connection, icmp: icmp_conn%); + +## Generated for ICMP *router advertisement* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_router_advertisement%(c: connection, icmp: icmp_conn, hop_limit: count, managed: bool, router_lifetime: count, reachable_time: interval, retrans_timer: interval%); + +## Generated for ICMP *neighbor solicitation* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_neighbor_solicitation%(c: connection, icmp: icmp_conn, tgt:addr%); + +## Generated for ICMP *neighbor advertisement* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_neighbor_advertisement%(c: connection, icmp: icmp_conn, tgt:addr%); + +## Generated for ICMP *redirect* messages. +## +## See `Wikipedia +## `__ for more +## information about the ICMP protocol. +## +## c: The connection record for the corresponding ICMP flow. +## +## icmp: Additional ICMP-specific information augmenting the standard connection +## record *c*. +## +## a: The new destination address the message is redirecting to. +## +## .. bro:see:: icmp_echo_reply icmp_echo_request icmp_sent +## icmp_time_exceeded icmp_unreachable +event icmp_redirect%(c: connection, icmp: icmp_conn, tgt: addr, dest: addr%); + +## Generated when a TCP connection terminated, passing on statistics about the +## two endpoints. This event is always generated when Bro flushes the internal +## connection state, independent of how a connection terminates. +## +## c: The connection. +## +## os: Statistics for the originator endpoint. +## +## rs: Statistics for the responder endpoint. +## +## .. bro:see:: connection_state_remove +event conn_stats%(c: connection, os: endpoint_stats, rs: endpoint_stats%); + +## Generated for unexpected activity related to a specific connection. When +## Bro's packet analysis encounters activity that does not conform to a protocol's +## specification, it raises one of the ``*_weird`` events to report that. This +## event is raised if the activity is tied directly to a specific connection. +## +## name: A unique name for the specific type of "weird" situation. Bro's default +## scripts use this name in filtering policies that specify which "weirds" are +## worth reporting. +## +## c: The corresponding connection. +## +## addl: Optional additional context further describing the situation. +## +## .. bro:see:: flow_weird net_weird +## +## .. note:: "Weird" activity is much more common in real-world network traffic +## than one would intuitively expect. While in principle, any protocol violation +## could be an attack attempt, it's much more likely that an endpoint's +## implementation interprets an RFC quite liberally. +event conn_weird%(name: string, c: connection, addl: string%); + +## Generated for unexpected activity related to a pair of hosts, but independent +## of a specific connection. When Bro's packet analysis encounters activity that +## does not conform to a protocol's specification, it raises one of the ``*_weird`` +## event to report that. This event is raised if the activity is related to a +## pair of hosts, yet not to a specific connection between them. +## +## name: A unique name for the specific type of "weird" situation. Bro's default +## scripts use this name in filtering policies that specify which "weirds" are +## worth reporting. +## +## src: The source address corresponding to the activity. +## +## dst: The destination address corresponding to the activity. +## +## .. bro:see:: conn_weird net_weird +## +## .. note:: "Weird" activity is much more common in real-world network traffic +## than one would intuitively expect. While in principle, any protocol violation +## could be an attack attempt, it's much more likely that an endpoint's +## implementation interprets an RFC quite liberally. +event flow_weird%(name: string, src: addr, dst: addr%); + +## Generated for unexpected activity that is not tied to a specific connection +## or pair of hosts. When Bro's packet analysis encounters activity that +## does not conform to a protocol's specification, it raises one of the +## ``*_weird`` event to report that. This event is raised if the activity is +## not tied directly to a specific connection or pair of hosts. +## +## name: A unique name for the specific type of "weird" situation. Bro's default +## scripts use this name in filtering policies that specify which "weirds" are +## worth reporting. +## +## .. bro:see:: flow_weird +## +## .. note:: "Weird" activity is much more common in real-world network traffic +## than one would intuitively expect. While in principle, any protocol violation +## could be an attack attempt, it's much more likely that an endpoint's +## implementation interprets an RFC quite liberally. +event net_weird%(name: string%); + +## Generated regularly for the purpose of profiling Bro's processing. This event +## is raised for every :bro:id:`load_sample_freq` packet. For these packets, +## Bro records script-level functions executed during their processing as well as +## further internal locations. By sampling the processing in this form, one can +## understand where Bro spends its time. +## +## samples: A set with functions and locations seens during the processing of +## the sampled packet. +## +## CPU: The CPU time spent on processing the sampled. +## +## dmem: The difference in memory usage caused by processing the sampled packet. +event load_sample%(samples: load_sample_info, CPU: interval, dmem: int%); + +## Generated for ARP requests. +## +## See `Wikipedia `__ for +## more information about the ARP protocol. +## +## mac_src: The request's source MAC address. +## +## mac_dst: The request's destination MAC address. +## +## SPA: The sender protocol address. +## +## SHA: The sender hardware address. +## +## TPA: The target protocol address. +## +## THA: The target hardware address. +## +## .. bro:see:: arp_reply bad_arp event arp_request%(mac_src: string, mac_dst: string, SPA: addr, SHA: string, TPA: addr, THA: string%); + +## Generated for ARP replies. +## +## See `Wikipedia `__ for +## more information about the ARP protocol. +## +## mac_src: The replies's source MAC address. +## +## mac_dst: The replies's destination MAC address. +## +## SPA: The sender protocol address. +## +## SHA: The sender hardware address. +## +## TPA: The target protocol address. +## +## THA: The target hardware address. +## +## .. bro:see:: arp_request bad_arp event arp_reply%(mac_src: string, mac_dst: string, SPA: addr, SHA: string, TPA: addr, THA: string%); + +## Generated for ARP packets that Bro cannot interpret. Examples are packets with +## non-standard hardware address formats or hardware addresses that not match the +## originator of the packet. +## +## SPA: The sender protocol address. +## +## SHA: The sender hardware address. +## +## TPA: The target protocol address. +## +## THA: The target hardware address. +## +## explanation: A short description of why the ARP packet is considered "bad". +## +## .. bro:see:: arp_reply arp_request +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event bad_arp%(SPA: addr, SHA: string, TPA: addr, THA: string, explanation: string%); +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_have bittorrent_peer_interested bittorrent_peer_keep_alive +## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird event bittorrent_peer_handshake%(c: connection, is_orig: bool, reserved: string, info_hash: string, peer_id: string%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird event bittorrent_peer_keep_alive%(c: connection, is_orig: bool%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown bittorrent_peer_weird event bittorrent_peer_choke%(c: connection, is_orig: bool%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request +## bittorrent_peer_unknown bittorrent_peer_weird event bittorrent_peer_unchoke%(c: connection, is_orig: bool%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_keep_alive +## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird event bittorrent_peer_interested%(c: connection, is_orig: bool%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_piece bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird event bittorrent_peer_not_interested%(c: connection, is_orig: bool%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_interested bittorrent_peer_keep_alive +## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird event bittorrent_peer_have%(c: connection, is_orig: bool, piece_index: count%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_cancel bittorrent_peer_choke bittorrent_peer_handshake +## bittorrent_peer_have bittorrent_peer_interested bittorrent_peer_keep_alive +## bittorrent_peer_not_interested bittorrent_peer_piece bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird event bittorrent_peer_bitfield%(c: connection, is_orig: bool, bitfield: string%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird event bittorrent_peer_request%(c: connection, is_orig: bool, index: count, begin: count, length: count%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_port +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird event bittorrent_peer_piece%(c: connection, is_orig: bool, index: count, begin: count, piece_length: count%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown bittorrent_peer_weird event bittorrent_peer_cancel%(c: connection, is_orig: bool, index: count, begin: count, length: count%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_request bittorrent_peer_unchoke bittorrent_peer_unknown +## bittorrent_peer_weird event bittorrent_peer_port%(c: connection, is_orig: bool, listen_port: port%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_weird event bittorrent_peer_unknown%(c: connection, is_orig: bool, message_id: count, data: string%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown event bittorrent_peer_weird%(c: connection, is_orig: bool, msg: string%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown bittorrent_peer_weird event bt_tracker_request%(c: connection, uri: string, headers: bt_tracker_headers%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown bittorrent_peer_weird event bt_tracker_response%(c: connection, status: count, headers: bt_tracker_headers, peers: bittorrent_peer_set, benc: bittorrent_benc_dir%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown bittorrent_peer_weird event bt_tracker_response_not_ok%(c: connection, status: count, headers: bt_tracker_headers%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the BitTorrent protocol. +## +## .. bro:see:: bittorrent_peer_bitfield bittorrent_peer_cancel bittorrent_peer_choke +## bittorrent_peer_handshake bittorrent_peer_have bittorrent_peer_interested +## bittorrent_peer_keep_alive bittorrent_peer_not_interested bittorrent_peer_piece +## bittorrent_peer_port bittorrent_peer_request bittorrent_peer_unchoke +## bittorrent_peer_unknown bittorrent_peer_weird event bt_tracker_weird%(c: connection, is_orig: bool, msg: string%); +## Generated for Finger requests. +## +## See `Wikipedia `__ for more +## information about the Finger protocol. +## +## c: The connection. +## +## full: True if verbose information is requested (``/W`` switch). +## +## username: The request's user name. +## +## hostname: The request's host name. +## +## .. bro:see:: finger_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event finger_request%(c: connection, full: bool, username: string, hostname: string%); + +## Generated for Finger replies. +## +## See `Wikipedia `__ for more +## information about the Finger protocol. +## +## c: The connection. +## +## reply_line: The reply as returned by the server +## +## .. bro:see:: finger_request +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event finger_reply%(c: connection, reply_line: string%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the Gnutella protocol. +## +## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_http_notify +## gnutella_not_establish gnutella_partial_binary_msg gnutella_signature_found +## +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event gnutella_text_msg%(c: connection, orig: bool, headers: string%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the Gnutella protocol. +## +## .. bro:see:: gnutella_establish gnutella_http_notify gnutella_not_establish +## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event gnutella_binary_msg%(c: connection, orig: bool, msg_type: count, ttl: count, hops: count, msg_len: count, payload: string, payload_len: count, trunc: bool, complete: bool%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the Gnutella protocol. +## +## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_http_notify +## gnutella_not_establish gnutella_signature_found gnutella_text_msg +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event gnutella_partial_binary_msg%(c: connection, orig: bool, msg: string, len: count%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the Gnutella protocol. +## +## .. bro:see:: gnutella_binary_msg gnutella_http_notify gnutella_not_establish +## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event gnutella_establish%(c: connection%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the Gnutella protocol. +## +## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_http_notify +## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event gnutella_not_establish%(c: connection%); + +## TODO. +## +## See `Wikipedia `__ for more +## information about the Gnutella protocol. +## +## .. bro:see:: gnutella_binary_msg gnutella_establish gnutella_not_establish +## gnutella_partial_binary_msg gnutella_signature_found gnutella_text_msg +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event gnutella_http_notify%(c: connection%); +## Generated for Ident requests. +## +## See `Wikipedia `__ for more +## information about the Ident protocol. +## +## c: The connection. +## +## lport: The request's local port. +## +## rport: The request's remote port. +## +## .. bro:see:: ident_error ident_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event ident_request%(c: connection, lport: port, rport: port%); + +## Generated for Ident replies. +## +## See `Wikipedia `__ for more +## information about the Ident protocol. +## +## c: The connection. +## +## lport: The corresponding request's local port. +## +## rport: The corresponding request's remote port. +## +## user_id: The user id returned by the reply. +## +## system: The operating system returned by the reply. +## +## .. bro:see:: ident_error ident_request +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event ident_reply%(c: connection, lport: port, rport: port, user_id: string, system: string%); + +## Generated for Ident error replies. +## +## See `Wikipedia `__ for more +## information about the Ident protocol. +## +## c: The connection. +## +## lport: The corresponding request's local port. +## +## rport: The corresponding request's remote port. +## +## line: The error description returned by the reply. +## +## .. bro:see:: ident_reply ident_request +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event ident_error%(c: connection, lport: port, rport: port, line: string%); +## Generated for Telnet/Rlogin login failures. The *login* analyzer inspects +## Telnet/Rlogin sessions to heuristically extract username and password +## information as well as the text returned by the login server. This event is +## raised if a login attempt appears to have been unsuccessful. +## +## c: The connection. +## +## user: The user name tried. +## +## client_user: For Telnet connections, this is an empty string, but for Rlogin +## connections, it is the client name passed in the initial authentication +## information (to check against .rhosts). +## +## password: The password tried. +## +## line: line is the line of text that led the analyzer to conclude that the +## authentication had failed. +## +## .. bro:see:: login_confused login_confused_text login_display login_input_line +## login_output_line login_prompt login_success login_terminal direct_login_prompts +## get_login_state login_failure_msgs login_non_failure_msgs login_prompts login_success_msgs +## login_timeouts set_login_state +## +## .. note:: The login analyzer depends on a set of script-level variables that +## need to configured with patterns identifying login attempts. This configuration +## has not yet been ported over from Bro 1.5 to Bro 2.x, and the analyzer is +## therefore not directly usable at the moment. +## +## .. todo: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event login_failure%(c: connection, user: string, client_user: string, password: string, line: string%); + +## Generated for successful Telnet/Rlogin logins. The *login* analyzer inspects +## Telnet/Rlogin sessions to heuristically extract username and password +## information as well as the text returned by the login server. This event is +## raised if a login attempt appears to have been successful. +## +## c: The connection. +## +## user: The user name used. +## +## client_user: For Telnet connections, this is an empty string, but for Rlogin +## connections, it is the client name passed in the initial authentication +## information (to check against .rhosts). +## +## password: The password used. +## +## line: line is the line of text that led the analyzer to conclude that the +## authentication had succeeded. +## +## .. bro:see:: login_confused login_confused_text login_display login_failure +## login_input_line login_output_line login_prompt login_terminal +## direct_login_prompts get_login_state login_failure_msgs login_non_failure_msgs +## login_prompts login_success_msgs login_timeouts set_login_state +## +## .. note:: The login analyzer depends on a set of script-level variables that +## need to configured with patterns identifying login attempts. This configuration +## has not yet been ported over from Bro 1.5 to Bro 2.x, and the analyzer is +## therefore not directly usable at the moment. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event login_success%(c: connection, user: string, client_user: string, password: string, line: string%); + +## Generated for lines of input on Telnet/Rlogin sessions. The line will have +## control characters (such as in-band Telnet options) removed. +## +## c: The connection. +## +## line: The input line. +## +## .. bro:see:: login_confused login_confused_text login_display login_failure +## login_output_line login_prompt login_success login_terminal rsh_request +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event login_input_line%(c: connection, line: string%); + +## Generated for lines of output on Telnet/Rlogin sessions. The line will have +## control characters (such as in-band Telnet options) removed. +## +## c: The connection. +## +## line: The ouput line. +## +## .. bro:see:: login_confused login_confused_text login_display login_failure +## login_input_line login_prompt login_success login_terminal rsh_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event login_output_line%(c: connection, line: string%); + +## Generated when tracking of Telnet/Rlogin authentication failed. As Bro's *login* +## analyzer uses a number of heuristics to extract authentication information, it +## may become confused. If it can no longer correctly track the authentication +## dialog, it raised this event. +## +## c: The connection. +## +## msg: Gives the particular problem the heuristics detected (for example, +## ``multiple_login_prompts`` means that the engine saw several login prompts in +## a row, without the type-ahead from the client side presumed necessary to cause +## them) +## +## line: The line of text that caused the heuristics to conclude they were +## confused. +## +## .. bro:see:: login_confused_text login_display login_failure login_input_line login_output_line +## login_prompt login_success login_terminal direct_login_prompts get_login_state +## login_failure_msgs login_non_failure_msgs login_prompts login_success_msgs +## login_timeouts set_login_state +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event login_confused%(c: connection, msg: string, line: string%); + +## Generated after getting confused while tracking a Telnet/Rlogin authentication +## dialog. The *login* analyzer generates this even for every line of user input +## after it has reported :bro:id:`login_confused` for a connection. +## +## c: The connection. +## +## line: The line the user typed. +## +## .. bro:see:: login_confused login_display login_failure login_input_line +## login_output_line login_prompt login_success login_terminal direct_login_prompts +## get_login_state login_failure_msgs login_non_failure_msgs login_prompts +## login_success_msgs login_timeouts set_login_state +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event login_confused_text%(c: connection, line: string%); + +## Generated for clients transmitting a terminal type in an Telnet session. This +## information is extracted out of environment variables sent as Telnet options. +## +## c: The connection. +## +## terminal: The TERM value transmitted. +## +## .. bro:see:: login_confused login_confused_text login_display login_failure +## login_input_line login_output_line login_prompt login_success +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event login_terminal%(c: connection, terminal: string%); + +## Generated for clients transmitting a X11 DISPLAY in a Telnet session. This +## information is extracted out of environment variables sent as Telnet options. +## +## c: The connection. +## +## terminal: The DISPLAY transmitted. +## +## .. bro:see:: login_confused login_confused_text login_failure login_input_line +## login_output_line login_prompt login_success login_terminal +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event login_display%(c: connection, display: string%); -event login_prompt%(c: connection, prompt: string%); -event rsh_request%(c: connection, client_user: string, server_user: string, line: string, new_session: bool%); -event rsh_reply%(c: connection, client_user: string, server_user: string, line: string%); -event excessive_line%(c: connection%); + +## Generated when a Telnet authentication has been successful. The Telnet protocol +## includes options for negotiating authentication. When such an option is sent +## from client to server and the server replies that it accepts the authentication, +## then the event engine generates this event. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## name: The authenticated name. +## +## c: The connection. +## +## .. bro:see:: authentication_rejected authentication_skipped login_success +## +## .. note:: This event inspects the corresponding Telnet option while :bro:id:`login_success` +## heuristically determines success by watching session data. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event authentication_accepted%(name: string, c: connection%); + +## Generated when a Telnet authentication has been unsuccessful. The Telnet +## protocol includes options for negotiating authentication. When such an option +## is sent from client to server and the server replies that it did not accept the +## authentication, then the event engine generates this event. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## name: The attempted authentication name. +## +## c: The connection. +## +## .. bro:see:: authentication_accepted authentication_skipped login_failure +## +## .. note:: This event inspects the corresponding Telnet option while :bro:id:`login_success` +## heuristically determines failure by watching session +## data. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event authentication_rejected%(name: string, c: connection%); + +## Generated when for Telnet/Rlogin sessions when a pattern match indicates +## that no authentication is performed. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## c: The connection. +## +## .. bro:see:: authentication_accepted authentication_rejected direct_login_prompts +## get_login_state login_failure_msgs login_non_failure_msgs login_prompts +## login_success_msgs login_timeouts set_login_state +## +## .. note:: The login analyzer depends on a set of script-level variables that +## need to be configured with patterns identifying actvity. This configuration has +## not yet been ported over from Bro 1.5 to Bro 2.x, and the analyzer is therefore +## not directly usable at the moment. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event authentication_skipped%(c: connection%); + +## Generated for clients transmitting a terminal prompt in a Telnet session. This +## information is extracted out of environment variables sent as Telnet options. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## c: The connection. +## +## terminal: The TTYPROMPT transmitted. +## +## .. bro:see:: login_confused login_confused_text login_display login_failure +## login_input_line login_output_line login_success login_terminal +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. +event login_prompt%(c: connection, prompt: string%); + +## Generated for Telnet sessions when encryption is activated. The Telnet protoco; +## includes options for negotiating encryption. When such a series of options is +## successfully negotiated, the event engine generates this event. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## c: The connection. +## +## .. bro:see:: authentication_accepted authentication_rejected authentication_skipped +## login_confused login_confused_text login_display login_failure login_input_line +## login_output_line login_prompt login_success login_terminal event activating_encryption%(c: connection%); +## Generated for inconsistent Telnet options observed. Telnet options are specified +## by the client and server stating which options they are willing to support +## vs. which they are not, and then instructing one another which in fact they +## should or should not use for the current connection. If the event engine sees +## a peer violate either what the other peer has instructed it to do, or what it +## itself offered in terms of options in the past, then the engine generates an +## inconsistent_option event. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## c: The connection. +## +## .. bro:see:: bad_option bad_option_termination authentication_accepted +## authentication_rejected authentication_skipped login_confused +## login_confused_text login_display login_failure login_input_line +## login_output_line login_prompt login_success login_terminal +event inconsistent_option%(c: connection%); + +## Generated for an ill-formed or unrecognized Telnet option. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## c: The connection. +## +## .. bro:see:: inconsistent_option bad_option_termination authentication_accepted +## authentication_rejected authentication_skipped login_confused +## login_confused_text login_display login_failure login_input_line +## login_output_line login_prompt login_success login_terminal +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. +event bad_option%(c: connection%); + +## Generated for a Telnet option that's incorrectly terminated. +## +## See `Wikipedia `__ for more information +## about the Telnet protocol. +## +## .. bro:see:: inconsistent_option bad_option authentication_accepted +## authentication_rejected authentication_skipped login_confused +## login_confused_text login_display login_failure login_input_line +## login_output_line login_prompt login_success login_terminal +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. +event bad_option_termination%(c: connection%); + +## Generated for client side commands on an RSH connection. +## +## See `RFC 1258 `__ for more information about +## the Rlogin/Rsh protocol. +## +## c: The connection. +## +## client_user: The client-side user name as sent in the initial protocol +## handshake. +## +## client_user: The server-side user name as sent in the initial protocol +## handshake. +## +## line: The command line sent in the request. +## +## new_session: True if this is the first command of the Rsh session. +## +## .. bro:see:: rsh_reply login_confused login_confused_text login_display +## login_failure login_input_line login_output_line login_prompt login_success +## login_terminal +## +## .. note: For historical reasons, these events are separate from the ``login_`` +## events. Ideally, they would all be handled uniquely. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. +event rsh_request%(c: connection, client_user: string, server_user: string, line: string, new_session: bool%); + +## Generated for client side commands on an RSH connection. +## +## See `RFC 1258 `__ for more information about +## the Rlogin/Rsh protocol. +## +## c: The connection. +## +## client_user: The client-side user name as sent in the initial protocol +## handshake. +## +## client_user: The server-side user name as sent in the initial protocol +## handshake. +## +## line: The command line sent in the request. +## +## new_session: True if this is the first command of the Rsh session. +## +## .. bro:see:: rsh_request login_confused login_confused_text login_display +## login_failure login_input_line login_output_line login_prompt login_success +## login_terminal +## +## .. note: For historical reasons, these events are separate from the ``login_`` +## events. Ideally, they would all be handled uniquely. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. +event rsh_reply%(c: connection, client_user: string, server_user: string, line: string%); + +## Generated for client-side FTP commands. +## +## See `Wikipedia `__ for more +## information about the FTP protocol. +## +## c: The connection. +## +## command: The FTP command issued by the client (without any arguments). +## +## arg: The arguments going with the command. +## +## .. bro:see:: ftp_reply fmt_ftp_port parse_eftp_port +## parse_ftp_epsv parse_ftp_pasv parse_ftp_port event ftp_request%(c: connection, command: string, arg: string%) &group="ftp"; + +## Generated for server-side FTP replies. +## +## See `Wikipedia `__ for more +## information about the FTP protocol. +## +## c: The connection. +## +## code: The numerical response code the server responded with. +## +## msg: The textual message of the response. +## +## cont_resp: True if the reply line is tagged as being continued to the next line. +## If so, further events will be raised and a handler may want to reassemle the +## pieces before processing the response any further. +## +## .. bro:see:: ftp_request fmt_ftp_port parse_eftp_port +## parse_ftp_epsv parse_ftp_pasv parse_ftp_port event ftp_reply%(c: connection, code: count, msg: string, cont_resp: bool%) &group="ftp"; +## Generated for client-side SMTP commands. +## +## See `Wikipedia `__ +## for more information about the SMTP protocol. +## +## c: The connection. +## +## is_orig: True if the sender of the command is the originator of the TCP +## connection. Note that this is not redundant: the SMTP ``TURN`` command allows +## client and server to flip roles on established SMTP sessions, and hence a +## "request" might still come from the TCP-level responder. In practice, however, +## that will rarely happen as TURN is considered insecure and rarely used. +## +## command: The request's command, without any arguments. +## +## arg: The request command's arguments. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_entity_data mime_event mime_one_header mime_segment_data +## smtp_data smtp_reply +## +## .. note:: Bro does not support the newer ETRN extension yet. event smtp_request%(c: connection, is_orig: bool, command: string, arg: string%) &group="smtp"; + +## Generated for server-side SMTP commands. +## +## See `Wikipedia `__ +## for more information about the SMTP protocol. +## +## c: The connection. +## +## is_orig: True if the sender of the command is the originator of the TCP +## connection. Note that this is not redundant: the SMTP ``TURN`` command +## allows client and server to flip roles on established SMTP sessions, +## and hence a "reply" might still come from the TCP-level originator. In +## practice, however, that will rarely happen as TURN is considered insecure +## and rarely used. +## +## code: The reply's numerical code. +## +## msg: The reply's textual description. +## +## cont_resp: True if the reply line is tagged as being continued to the next line. +## If so, further events will be raised and a handler may want to reassemle the +## pieces before processing the response any further. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_entity_data mime_event mime_one_header mime_segment_data +## smtp_data smtp_request +## +## .. note:: Bro doesn't support the newer ETRN extension yet. event smtp_reply%(c: connection, is_orig: bool, code: count, cmd: string, msg: string, cont_resp: bool%) &group="smtp"; + +## Generated for DATA transmitted on SMTP sessions. This event is raised for +## subsequent chunks of raw data following the ``DATA`` SMTP command until the +## corresponding end marker ``.`` is seen. A handler may want to reassembly +## the pieces as they come in if stream-analysis is required. +## +## See `Wikipedia `__ +## for more information about the SMTP protocol. +## +## c: The connection. +## +## is_orig: True if the sender of the data is the originator of the TCP +## connection. +## +## data: The raw data. Note that the size of each chunk is undefined and +## depends on specifics of the underlying TCP connection. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_entity_data mime_event mime_one_header mime_segment_data +## smtp_reply smtp_request skip_smtp_data +## +## .. note:: This event received the unprocessed raw data. There is a separate +## set ``mime_*`` events that strip out the outer MIME-layer of emails and provide +## structured access to their content. event smtp_data%(c: connection, is_orig: bool, data: string%) &group="smtp"; + +## Generated for unexpected activity on SMTP sessions. The SMTP analyzer tracks the +## state of SMTP sessions and reports commands and other activity with this event +## that it sees even though it would not expect so at the current point of the +## communication. +## +## See `Wikipedia `__ +## for more information about the SMTP protocol. +## +## c: The connection. +## +## is_orig: True if the sender of the unexpected activity is the originator of the +## TCP connection. +## +## msg: A descriptive message of what was unexpected. +## +## detail: The actual SMTP line triggering the event. +## +## .. bro:see:: smtp_data smtp_request smtp_reply event smtp_unexpected%(c: connection, is_orig: bool, msg: string, detail: string%) &group="smtp"; +## Generated when starting to parse a email MIME entity. MIME is a +## protocol-independent data format for encoding text and files, along with +## corresponding meta-data, for transmission. Bro raises this event when it begin +## parsing a MIME entity extracted from an email protocol. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia +## `__ for more information about the ARP +## protocol. +## +## c: The connection. +## +## .. bro:see:: mime_all_data mime_all_headers mime_content_hash mime_end_entity +## mime_entity_data mime_event mime_one_header mime_segment_data smtp_data +## http_begin_entity +## +## .. note:: Bro also extracts MIME entities from HTTP session. For those, however, +## it raises :bro:id:`http_begin_entity` instead. event mime_begin_entity%(c: connection%); -event mime_next_entity%(c: connection%); + +## Generated when finishing parsing an email MIME entity. MIME is a +## protocol-independent data format for encoding text and files, along with +## corresponding meta-data, for transmission. Bro raises this event when it +## finished parsing a MIME entity extracted from an email protocol. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia +## `__ for more information about the ARP +## protocol. +## +## c: The connection. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_entity_data mime_event mime_one_header mime_segment_data smtp_data +## http_end_entity +## +## .. note:: Bro also extracts MIME entities from HTTP session. For those, however, +## it raises :bro:id:`http_end_entity` instead. event mime_end_entity%(c: connection%); + +## Generated for individual MIME headers extracted from email MIME +## entities. MIME is a protocol-independent data format for encoding text and +## files, along with corresponding meta-data, for transmission. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia +## `__ for more information about the ARP +## protocol. +## +## c: The connection. +## +## h: The parsed MIME header. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_entity_data mime_event mime_segment_data +## http_header http_all_headers +## +## .. note:: Bro also extracts MIME headers from HTTP sessions. For those, however, +## it raises :bro:id:`http_header` instead. event mime_one_header%(c: connection, h: mime_header_rec%); + +## Generated for MIME headers extracted from email MIME entities, passing all +## headers at once. MIME is a protocol-independent data format for encoding text +## and files, along with corresponding meta-data, for transmission. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia +## `__ for more information about the ARP +## protocol. +## +## c: The connection. +## +## hlist: A *table* containing all headers extracted from the current entity. +## The table is indexed by the position of the header (1 for the first, 2 for the +## second, etc.). +## +## .. bro:see:: mime_all_data mime_begin_entity mime_content_hash mime_end_entity +## mime_entity_data mime_event mime_one_header mime_segment_data +## http_header http_all_headers +## +## .. note:: Bro also extracts MIME headers from HTTP sessions. For those, however, +## it raises :bro:id:`http_header` instead. event mime_all_headers%(c: connection, hlist: mime_header_list%); + +## Generated for chunks of decoded MIME data from email MIME entities. MIME +## is a protocol-independent data format for encoding text and files, along with +## corresponding meta-data, for transmission. As Bro parses the data of an entity, +## it raises a sequence of these events, each coming as soon as a new chunk of +## data is available. In contrast, there is also :bro:id:`mime_entity_data`, which +## passes all of an entities data at once in a single block. While the latter is +## more convinient to handle, ``mime_segment_data`` is more efficient as Bro does +## not need to buffer the data. Thus, if possible, this event should be prefered. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia +## `__ for more information about the ARP +## protocol. +## +## c: The connection. +## +## length: The length of *data*. +## +## data: The raw data of one segment of the current entity. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_entity_data mime_event mime_one_header http_entity_data +## mime_segment_length mime_segment_overlap_length +## +## .. note:: Bro also extracts MIME data from HTTP sessions. For those, however, it +## raises :bro:id:`http_entity_data` (sic!) instead. event mime_segment_data%(c: connection, length: count, data: string%); + +## Generated for data decoded from an email MIME entity. This event delivers +## the complete content of a single MIME entity. In contrast, there is also +## :bro:id:`mime_segment_data`, which passes on a sequence of data chunks as +## they. come in. While ``mime_entity_data`` is more convinient to handle, +## ``mime_segment_data`` is more efficient as Bro does not need to buffer the data. +## Thus, if possible, the latter should be prefered. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia +## `__ for more information about the ARP +## protocol. +## +## c: The connection. +## +## length: The length of *data*. +## +## data: The raw data of the complete entity. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_event mime_one_header mime_segment_data +## +## .. note:: While Bro also decodes MIME entities extracted from HTTP +## sessions, there's no corresponding event for that currently. event mime_entity_data%(c: connection, length: count, data: string%); + +## Generated for passing on all data decoded from an single email MIME +## message. If an email message has more than one MIME entity, this event +## combines all their data into a single value for analysis. Note that because +## of the potentially significant buffering necessary, using this event can be +## expensive. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia +## `__ for more information about the ARP +## protocol. +## +## c: The connection. +## +## length: The length of *data*. +## +## data: The raw data of all MIME entities concatenated. +## +## .. bro:see:: mime_all_headers mime_begin_entity mime_content_hash mime_end_entity +## mime_entity_data mime_event mime_one_header mime_segment_data +## +## .. note:: While Bro also decodes MIME entities extracted from HTTP +## sessions, there's no corresponding event for that currently. event mime_all_data%(c: connection, length: count, data: string%); + +## Generated for errors found when decoding email MIME entities. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia +## `__ for more information about the ARP +## protocol. +## +## event_type: A string describing the general category of the problem found (e.g., +## ``illegal format``). +## +## detail: Further more detailed description of the error. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_content_hash +## mime_end_entity mime_entity_data mime_one_header mime_segment_data http_event +## +## .. note:: Bro also extracts MIME headers from HTTP sessions. For those, however, +## it raises :bro:id:`http_event` instead. event mime_event%(c: connection, event_type: string, detail: string%); + +## Generated for decoded MIME entities extracted from email meessage, passing on +## their MD5 checksums. Bro computes the MD5 over the complete decoded data of +## each MIME entity. +## +## Bro's MIME analyzer for emails currently supports SMTP and POP3. See `Wikipedia +## `__ for more information about the ARP +## protocol. +## +## c: The connection. +## +## content_len: The length of entity being hashed. +## +## hash_value: The MD5 hash. +## +## .. bro:see:: mime_all_data mime_all_headers mime_begin_entity mime_end_entity +## mime_entity_data mime_event mime_one_header mime_segment_data +## +## .. note:: While Bro also decodes MIME entities extracted from HTTP +## sessions, there's no corresponding event for that currently. event mime_content_hash%(c: connection, content_len: count, hash_value: string%); -# Generated for each RPC request / reply *pair* (if there is no reply, the event -# will be generated on timeout). +## Generated for RPC request/reply *pairs*. The RPC analyzer associates request +## and reply by their transactions identifiers and raise this event once both +## have been seen. If there's not reply, the will still be generated eventually +## on timeout. In that case, *status* will be set to :bro:enum:`RPC_TIMEOUT`. +## +## See `Wikipedia `__ for more information +## about the ONC RPC protocol. +## c: The connection. +## +## xid: The transaction identifier allowing to match requests with replies. +## +## prog: The remote program to call. +## +## ver: The version of the remote program to call. +## +## proc: The procedure of the remote program to call. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## start_time: Then time when the *call* was seen. +## +## call_len: The size of the *call_body* PDU. +## +## reply_len: The size of the *reply_body* PDU. +## +## .. bro:see:: rpc_call rpc_reply dce_rpc_bind dce_rpc_message dce_rpc_request +## dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event rpc_dialogue%(c: connection, prog: count, ver: count, proc: count, status: rpc_status, start_time: time, call_len: count, reply_len: count%); -# Generated for each (correctly formed) RPC_CALL message received. + +## Generated for RPC *call* messages. +## +## See `Wikipedia `__ for more information +## about the ONC RPC protocol. +## +## c: The connection. +## +## xid: The transaction identifier allowing to match requests with replies. +## +## prog: The remote program to call. +## +## ver: The version of the remote program to call. +## +## proc: The procedure of the remote program to call. +## +## call_len: The size of the *call_body* PDU. +## +## .. bro:see:: rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message dce_rpc_request +## dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event rpc_call%(c: connection, xid: count, prog: count, ver: count, proc: count, call_len: count%); -# Generated for each (correctly formed) RPC_REPLY message received. + +## Generated for RPC *reply* messages. +## +## See `Wikipedia `__ for more information +## about the ONC RPC protocol. +## +## c: The connection. +## +## xid: The transaction identifier allowing to match requests with replies. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## reply_len: The size of the *reply_body* PDU. +## +## .. bro:see:: rpc_call rpc_dialogue dce_rpc_bind dce_rpc_message dce_rpc_request +## dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event rpc_reply%(c: connection, xid: count, status: rpc_status, reply_len: count%); +## Generated for Portmapper requests of type *null*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the service. +## +## r: The RPC connection. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit +## pm_request_dump pm_request_getport pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_request_null%(r: connection%); + +## Generated for Portmapper request/reply dialogues of type *set*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the service. +## +## r: The RPC connection. +## +## m: The argument to the request. +## +## success: True if the request was successful, according to the corresponding +## reply. If no reply was seen, this will be false once the request times out. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit +## pm_request_dump pm_request_getport pm_request_null pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_request_set%(r: connection, m: pm_mapping, success: bool%); + +## Generated for Portmapper request/reply dialogues of type *unset*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the service. +## +## r: The RPC connection. +## +## m: The argument to the request. +## +## success: True if the request was successful, according to the corresponding +## reply. If no reply was seen, this will be false once the request times out. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit +## pm_request_dump pm_request_getport pm_request_null pm_request_set rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_request_unset%(r: connection, m: pm_mapping, success: bool%); + +## Generated for Portmapper request/reply dialogues of type *getport*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the service. +## +## r: The RPC connection. +## +## pr: The argument to the request. +## +## p: The port returned by the server. +## +## success: True if the request was successful, according to the corresponding +## reply. If no reply was seen, this will be false once the request times out. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit +## pm_request_dump pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_request_getport%(r: connection, pr: pm_port_request, p: port%); + +## Generated for Portmapper request/reply dialogues of type *dump*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the service. +## +## r: The RPC connection. +## +## m: The mappings returned by the server. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_request_dump%(r: connection, m: pm_mappings%); + +## Generated for Portmapper request/reply dialogues of type *callit*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## m: The argument to the request. +## +## p: The port value returned by the call. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_bad_port pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_request_callit%(r: connection, call: pm_callit_request, p: port%); + +## Generated for failed Portmapper requests of type *null*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_attempt_null%(r: connection, status: rpc_status%); + +## Generated for failed Portmapper requests of type *set*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## m: The argument to the original request. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_attempt_set%(r: connection, status: rpc_status, m: pm_mapping%); + +## Generated for failed Portmapper requests of type *unset*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## m: The argument to the original request. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_bad_port pm_request_callit pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_attempt_unset%(r: connection, status: rpc_status, m: pm_mapping%); + +## Generated for failed Portmapper requests of type *getport*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## pr: The argument to the original request. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_null +## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_attempt_getport%(r: connection, status: rpc_status, pr: pm_port_request%); + +## Generated for failed Portmapper requests of type *dump*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_getport pm_attempt_null +## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_attempt_dump%(r: connection, status: rpc_status%); + +## Generated for failed Portmapper requests of type *callit*. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## status: The status of the reply, which should be one of the index values of +## :bro:id:`RPC_status`. +## +## call: The argument to the original request. +## +## .. bro:see:: epm_map_response pm_attempt_dump pm_attempt_getport pm_attempt_null +## pm_attempt_set pm_attempt_unset pm_bad_port pm_request_callit pm_request_dump +## pm_request_getport pm_request_null pm_request_set pm_request_unset rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_attempt_callit%(r: connection, status: rpc_status, call: pm_callit_request%); + +## Generated for Portmapper requests or replies that include an invalid port +## number. Since ports are represented by unsigned 4-byte integers, they can stray +## outside the allowed range of 0--65535 by being >= 65536. If so, this event is +## generated. +## +## Portmapper is a service running on top of RPC. See `Wikipedia +## `__ for more information about the +## service. +## +## r: The RPC connection. +## +## bad_p: The invalid port value. +## +## .. bro:see:: epm_map_response pm_attempt_callit pm_attempt_dump pm_attempt_getport +## pm_attempt_null pm_attempt_set pm_attempt_unset pm_request_callit +## pm_request_dump pm_request_getport pm_request_null pm_request_set +## pm_request_unset rpc_call rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pm_bad_port%(r: connection, bad_p: count%); -# Events for the NFS analyzer. An event is generated if we have received a -# Call (request) / Response pair (or in case of a time out). info$rpc_stat and -# info$nfs_stat show whether the request was successful. The request record is -# always filled out, however, the reply record(s) might not be set or might only -# be partially set. See the comments for the record types in bro.init to see which -# reply fields are set when. +## Generated for NFSv3 request/reply dialogues of type *null*. The event is +## generated once we have either seen both the request and its corresponding reply, +## or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_read nfs_proc_readdir nfs_proc_readlink +## nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event nfs_proc_null%(c: connection, info: NFS3::info_t%); -event nfs_proc_not_implemented%(c: connection, info: NFS3::info_t, proc: NFS3::proc_t%); +## Generated for NFSv3 request/reply dialogues of type *getattr*. The event is +## generated once we have either seen both the request and its corresponding reply, +## or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## attr: The attributes returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status +## rpc_call rpc_dialogue rpc_reply file_mode +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event nfs_proc_getattr%(c: connection, info: NFS3::info_t, fh: string, attrs: NFS3::fattr_t%); + +## Generated for NFSv3 request/reply dialogues of type *lookup*. The event is +## generated once we have either seen both the request and its corresponding reply, +## or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: The arguments passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status +## rpc_call rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event nfs_proc_lookup%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::lookup_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *read*. The event is +## generated once we have either seen both the request and its corresponding reply, +## or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## req: The arguments passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_remove nfs_proc_rmdir +## nfs_proc_write nfs_reply_status rpc_call rpc_dialogue rpc_reply +## NFS3::return_data NFS3::return_data_first_only NFS3::return_data_max +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event nfs_proc_read%(c: connection, info: NFS3::info_t, req: NFS3::readargs_t, rep: NFS3::read_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *readlink*. The event is +## generated once we have either seen both the request and its corresponding reply, +## or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## fh: The file handle passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event nfs_proc_readlink%(c: connection, info: NFS3::info_t, fh: string, rep: NFS3::readlink_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *write*. The event is +## generated once we have either seen both the request and its corresponding reply, +## or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## fh: The file handle passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_reply_status rpc_call +## rpc_dialogue rpc_reply NFS3::return_data NFS3::return_data_first_only +## NFS3::return_data_max +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event nfs_proc_write%(c: connection, info: NFS3::info_t, req: NFS3::writeargs_t, rep: NFS3::write_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *create*. The event is +## generated once we have either seen both the request and its corresponding reply, +## or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## fh: The file handle passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status +## rpc_call rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event nfs_proc_create%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::newobj_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *mkdir*. The event is +## generated once we have either seen both the request and its corresponding reply, +## or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## fh: The file handle passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status +## rpc_call rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event nfs_proc_mkdir%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::newobj_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *remove*. The event is +## generated once we have either seen both the request and its corresponding reply, +## or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## fh: The file handle passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event nfs_proc_remove%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::delobj_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *rmdir*. The event is +## generated once we have either seen both the request and its corresponding reply, +## or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## fh: The file handle passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_write nfs_reply_status rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event nfs_proc_rmdir%(c: connection, info: NFS3::info_t, req: NFS3::diropargs_t, rep: NFS3::delobj_reply_t%); + +## Generated for NFSv3 request/reply dialogues of type *readdir*. The event is +## generated once we have either seen both the request and its corresponding reply, +## or an unanswered request has timed out. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## fh: The file handle passed in the request. +## +## rep: The response returned in the reply. The values may not be valid if the +## request was unsuccessful. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readlink +## nfs_proc_remove nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event nfs_proc_readdir%(c: connection, info: NFS3::info_t, req: NFS3::readdirargs_t, rep: NFS3::readdir_reply_t%); -# Generated for each NFS reply message we receive, giving just gives the status. +## Generated for NFS3 request/reply dialogues of a type that Bro's NFS3 analyzer +## does not implement. +## +## NFS is a service running on top of RPC. See `Wikipedia +## `__ for more +## information about the service. +## +## c: The RPC connection. +## +## info: Reports the status of the dialogue, along with some meta information. +## +## proc: The procedure called that Bro does not implement. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_null nfs_proc_read nfs_proc_readdir nfs_proc_readlink nfs_proc_remove +## nfs_proc_rmdir nfs_proc_write nfs_reply_status rpc_call rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. +event nfs_proc_not_implemented%(c: connection, info: NFS3::info_t, proc: NFS3::proc_t%); + +## Generated for each NFS3 reply message received, reporting just the +## status included. +## +## info: Reports the status included in the reply. +## +## .. bro:see:: nfs_proc_create nfs_proc_getattr nfs_proc_lookup nfs_proc_mkdir +## nfs_proc_not_implemented nfs_proc_null nfs_proc_read nfs_proc_readdir +## nfs_proc_readlink nfs_proc_remove nfs_proc_rmdir nfs_proc_write rpc_call +## rpc_dialogue rpc_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event nfs_reply_status%(n: connection, info: NFS3::info_t%); +## Generated for all NTP messages. Different from many other of Bro's events, this +## one is generated for both client-side and server-side messages. +## +## See `Wikipedia `__ for more +## information about the NTP protocol. +## +## u: The connection record describing the corresponding UDP flow. +## +## msg: The parsed NTP message. +## +## excess: The raw bytes of any optional parts of the NTP packet. Bro does not +## further parse any optional fields. +## +## .. bro:see:: ntp_session_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event ntp_message%(u: connection, msg: ntp_msg, excess: string%); +## Generated for all NetBIOS SSN and DGM messages. Bro's NetBIOS analyzer processes +## the NetBIOS session service running on TCP port 139, and (despite its name!) the +## NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be a TCP or UDP, depending on the type of the +## NetBIOS session. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## msg_type: The general type of message, as defined in Section 4.3.1 of `RFC 1002 +## `__. +## +## data_len: The length of the message's payload. +## +## .. bro:see:: netbios_session_accepted netbios_session_keepalive +## netbios_session_raw_message netbios_session_rejected netbios_session_request +## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's SMB +## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event netbios_session_message%(c: connection, is_orig: bool, msg_type: count, data_len: count%); + +## Generated for NetBIOS messages of type *session request*. Bro's NetBIOS analyzer +## processes the NetBIOS session service running on TCP port 139, and (despite its +## name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be a TCP or UDP, depending on the type of the +## NetBIOS session. +## +## msg: The raw payload of the message sent, excluding the common NetBIOS +## header. +## +## .. bro:see:: netbios_session_accepted netbios_session_keepalive +## netbios_session_message netbios_session_raw_message netbios_session_rejected +## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's SMB +## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event netbios_session_request%(c: connection, msg: string%); + +## Generated for NetBIOS messages of type *positive session response*. Bro's +## NetBIOS analyzer processes the NetBIOS session service running on TCP port 139, +## and (despite its name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be a TCP or UDP, depending on the type of the +## NetBIOS session. +## +## msg: The raw payload of the message sent, excluding the common NetBIOS +## header. +## +## .. bro:see:: netbios_session_keepalive netbios_session_message +## netbios_session_raw_message netbios_session_rejected netbios_session_request +## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's SMB +## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event netbios_session_accepted%(c: connection, msg: string%); + +## Generated for NetBIOS messages of type *negative session response*. Bro's +## NetBIOS analyzer processes the NetBIOS session service running on TCP port 139, +## and (despite its name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be a TCP or UDP, depending on the type of the +## NetBIOS session. +## +## msg: The raw payload of the message sent, excluding the common NetBIOS +## header. +## +## .. bro:see:: netbios_session_accepted netbios_session_keepalive +## netbios_session_message netbios_session_raw_message netbios_session_request +## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's SMB +## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event netbios_session_rejected%(c: connection, msg: string%); + +## Generated for NetBIOS message of type *session message* that are not carrying +## SMB payload. +## +## NetBIOS analyzer processes the NetBIOS session service running on TCP port 139, +## and (despite its name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be a TCP or UDP, depending on the type of the +## NetBIOS session. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## msg: The raw payload of the message sent, excluding the common NetBIOS +## header (i.e., the ``user_data``). +## +## .. bro:see:: netbios_session_accepted netbios_session_keepalive +## netbios_session_message netbios_session_rejected netbios_session_request +## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's SMB +## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: This is an oddly named event. In fact, it's probably an odd event to +## have to begin with. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event netbios_session_raw_message%(c: connection, is_orig: bool, msg: string%); + +## Generated for NetBIOS messages of type *retarget response*. Bro's NetBIOS +## analyzer processes the NetBIOS session service running on TCP port 139, and +## (despite its name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be a TCP or UDP, depending on the type of the +## NetBIOS session. +## +## msg: The raw payload of the message sent, excluding the common NetBIOS header. +## +## .. bro:see:: netbios_session_accepted netbios_session_keepalive +## netbios_session_message netbios_session_raw_message netbios_session_rejected +## netbios_session_request decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's SMB +## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo: This is an oddly named event. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event netbios_session_ret_arg_resp%(c: connection, msg: string%); + +## Generated for NetBIOS messages of type *keep-alive*. Bro's NetBIOS analyzer +## processes the NetBIOS session service running on TCP port 139, and (despite its +## name!) the NetBIOS datagram service on UDP port 138. +## +## See `Wikipedia `__ for more information +## about NetBIOS. `RFC 1002 `__ describes +## the packet format for NetBIOS over TCP/IP, which Bro parses. +## +## c: The connection, which may be a TCP or UDP, depending on the type of the +## NetBIOS session. +## +## msg: The raw payload of the message sent, excluding the common NetBIOS header. +## +## .. bro:see:: netbios_session_accepted netbios_session_message +## netbios_session_raw_message netbios_session_rejected netbios_session_request +## netbios_session_ret_arg_resp decode_netbios_name decode_netbios_name_type +## +## .. note:: These days, NetBIOS is primarily used as a transport mechanism for +## `SMB/CIFS `__. Bro's SMB +## anlyzer parses both SMB-over-NetBIOS and SMB-over-TCP on port 445. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event netbios_session_keepalive%(c: connection, msg: string%); +## Generated for all SMB/CIFS messages. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## is_orig: True if the message was sent by the originator of the underlying +## transport-level connection. +## +## cmd: A string mmenonic of the SMB command code. +## +## body_length: The length of the SMB message body, i.e. the data starting after +## the SMB header. +## +## body: The raw SMB message body, i.e., the data starting after the SMB header. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 +## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx smb_error +## smb_get_dfs_referral +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_message%(c: connection, hdr: smb_hdr, is_orig: bool, cmd: string, body_length: count, body: string%); + +## Generated for SMB/CIFS messages of type *tree connect andx*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## path: The ``path`` attribute specified in the message. +## +## service: The ``service`` attribute specified in the message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_tree_connect_andx%(c: connection, hdr: smb_hdr, path: string, service: string%); + +## Generated for SMB/CIFS messages of type *tree disconnect*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## path: The ``path`` attribute specified in the message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 +## smb_com_tree_connect_andx smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_tree_disconnect%(c: connection, hdr: smb_hdr%); + +## Generated for SMB/CIFS messages of type *nt create andx*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## name: The ``name`` attribute specified in the message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_read_andx +## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_nt_create_andx%(c: connection, hdr: smb_hdr, name: string%); + +## Generated for SMB/CIFS messages of type *nt transaction*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## trans: The parsed transaction header. +## +## data: The raw transaction data. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe +## smb_com_trans_rap smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_transaction%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); + +## Generated for SMB/CIFS messages of type *nt transaction 2*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## trans: The parsed transaction header. +## +## data: The raw transaction data. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe +## smb_com_trans_rap smb_com_transaction smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_transaction2%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); + +## Generated for SMB/CIFS messages of type *transaction mailslot*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## trans: The parsed transaction header. +## +## data: The raw transaction data. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_trans_mailslot%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); + +## Generated for SMB/CIFS messages of type *transaction rap*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## trans: The parsed transaction header. +## +## data: The raw transaction data. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_transaction smb_com_transaction2 +## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx smb_error +## smb_get_dfs_referral smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_trans_rap%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); + +## Generated for SMB/CIFS messages of type *transaction pipe*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## trans: The parsed transaction header. +## +## data: The raw transaction data. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_trans_pipe%(c: connection, hdr: smb_hdr, trans: smb_trans, data: smb_trans_data, is_orig: bool%); + +## Generated for SMB/CIFS messages of type *read andx*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## data: Always empty. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_read_andx%(c: connection, hdr: smb_hdr, data: string%); + +## Generated for SMB/CIFS messages of type *read andx*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## data: Always empty. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 +## smb_com_tree_connect_andx smb_com_tree_disconnect smb_error +## smb_get_dfs_referral smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_write_andx%(c: connection, hdr: smb_hdr, data: string%); + +## Generated for SMB/CIFS messages of type *get dfs referral*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## max_referral_level: The ``max_referral_level`` attribute specified in the +## message. +## +## file_name: The ``filene_name`` attribute specified in the message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 +## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx smb_error +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_get_dfs_referral%(c: connection, hdr: smb_hdr, max_referral_level: count, file_name: string%); + +## Generated for SMB/CIFS messages of type *negotiate*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx smb_com_setup_andx +## smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap smb_com_transaction +## smb_com_transaction2 smb_com_tree_connect_andx smb_com_tree_disconnect +## smb_com_write_andx smb_error smb_get_dfs_referral smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_negotiate%(c: connection, hdr: smb_hdr%); + +## Generated for SMB/CIFS messages of type *negotiate response*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## dialect_index: The ``dialect`` indicated in the message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_nt_create_andx smb_com_read_andx smb_com_setup_andx +## smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap smb_com_transaction +## smb_com_transaction2 smb_com_tree_connect_andx smb_com_tree_disconnect +## smb_com_write_andx smb_error smb_get_dfs_referral smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_negotiate_response%(c: connection, hdr: smb_hdr, dialect_index: count%); + +## Generated for SMB/CIFS messages of type *setup andx*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_setup_andx%(c: connection, hdr: smb_hdr%); + +## Generated for SMB/CIFS messages of type *generic andx*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## .. bro:see:: smb_com_close smb_com_logoff_andx smb_com_negotiate +## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx +## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_generic_andx%(c: connection, hdr: smb_hdr%); + +## Generated for SMB/CIFS messages of type *close*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## .. bro:see:: smb_com_generic_andx smb_com_logoff_andx smb_com_negotiate +## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx +## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_close%(c: connection, hdr: smb_hdr%); + +## Generated for SMB/CIFS messages of type *logoff andx*. +## +## See `Wikipedia `__ for more +## information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses both +## SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_negotiate +## smb_com_negotiate_response smb_com_nt_create_andx smb_com_read_andx +## smb_com_setup_andx smb_com_trans_mailslot smb_com_trans_pipe smb_com_trans_rap +## smb_com_transaction smb_com_transaction2 smb_com_tree_connect_andx +## smb_com_tree_disconnect smb_com_write_andx smb_error smb_get_dfs_referral +## smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_com_logoff_andx%(c: connection, hdr: smb_hdr%); + +## Generated for SMB/CIFS messages that indicate an error. This event is triggered +## by an SMB header including a status that signals an error. +## +## c: The connection. +## +## hdr: The parsed header of the SMB message. +## +## cmd: The SMB command code. +## +## cmd_str: A string mmenonic of the SMB command code. +## +## body: The raw SMB message body, i.e., the data starting after the SMB header. +## +## .. bro:see:: smb_com_close smb_com_generic_andx smb_com_logoff_andx +## smb_com_negotiate smb_com_negotiate_response smb_com_nt_create_andx +## smb_com_read_andx smb_com_setup_andx smb_com_trans_mailslot +## smb_com_trans_pipe smb_com_trans_rap smb_com_transaction smb_com_transaction2 +## smb_com_tree_connect_andx smb_com_tree_disconnect smb_com_write_andx +## smb_get_dfs_referral smb_message +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event smb_error%(c: connection, hdr: smb_hdr, cmd: count, cmd_str: string, data: string%); +## Generated for all DNS messages. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## is_orig: True if the message was sent by the originator of the connection. +## +## msg: The parsed DNS message header. +## +## len: The length of the message's raw representation (i.e, the DNS payload). +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_query_reply dns_rejected +## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth event dns_message%(c: connection, is_orig: bool, msg: dns_msg, len: count%) &group="dns"; + +## Generated for DNS requests. For requests with multiple queries, this event +## is raised once for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## query: The queried name. +## +## qtype: The queried resource record type. +## +## qclass: The queried resource record class. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth event dns_request%(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count%) &group="dns"; -event dns_full_request%(%) &group="dns"; + +## Generated for DNS replies that reject a query. This event is raised if a DNS +## reply either indicates failure via its status code or does not pass on any +## answers to a query. Note that all of the event's paramaters are parsed out of +## the reply; there's no stateful correlation with the query. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## query: The queried name. +## +## qtype: The queried resource record type. +## +## qclass: The queried resource record class. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth event dns_rejected%(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count%) &group="dns"; -event dns_A_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &group="dns"; -event dns_AAAA_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr, astr: string%) &group="dns"; -event dns_NS_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns"; -event dns_CNAME_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns"; -event dns_PTR_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns"; -event dns_SOA_reply%(c: connection, msg: dns_msg, ans: dns_answer, soa: dns_soa%) &group="dns"; -event dns_WKS_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns"; -event dns_HINFO_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns"; -event dns_MX_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string, preference: count%) &group="dns"; -event dns_TXT_reply%(c: connection, msg: dns_msg, ans: dns_answer, str: string%) &group="dns"; -event dns_SRV_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns"; -event dns_EDNS%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns"; -event dns_EDNS_addl%(c: connection, msg: dns_msg, ans: dns_edns_additional%) &group="dns"; -event dns_TSIG_addl%(c: connection, msg: dns_msg, ans: dns_tsig_additional%) &group="dns"; - -# Generated at the end of processing a DNS packet. -event dns_end%(c: connection, msg: dns_msg%) &group="dns"; +## Generated for DNS replies with an *ok* status code but no question section. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## query: The queried name. +## +## qtype: The queried resource record type. +## +## qclass: The queried resource record class. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_rejected +## dns_request non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth event dns_query_reply%(c: connection, msg: dns_msg, query: string, qtype: count, qclass: count%) &group="dns"; -# Generated when a port 53 UDP message cannot be parsed as a DNS request. +## Generated when the DNS analyzer processes what seems to be a non-DNS packets. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The raw DNS payload. +## +## .. note:: This event is deprecated and superseded by Bro's dynamic protocol +## detection framework. event non_dns_request%(c: connection, msg: string%) &group="dns"; +## Generated for DNS replies of type *A*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## a: The address returned by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A6_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply +## dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply +## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_A_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &group="dns"; + +## Generated for DNS replies of type *AAAA*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## a: The address returned by the reply. +## +## .. bro:see:: dns_A_reply dns_A6_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply +## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl +## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request +## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_AAAA_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &group="dns"; + +## Generated for DNS replies of type *A6*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## a: The address returned by the reply. +## +## .. bro:see:: dns_A_reply dns_AAAA_reply dns_CNAME_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply +## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl +## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request +## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_A6_reply%(c: connection, msg: dns_msg, ans: dns_answer, a: addr%) &group="dns"; + +## Generated for DNS replies of type *NS*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## name: The name returned by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply +## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_NS_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns"; + +## Generated for DNS replies of type *CNAME*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## name: The name returned by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_EDNS_addl dns_HINFO_reply dns_MX_reply +## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl +## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request +## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_CNAME_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns"; + +## Generated for DNS replies of type *PTR*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## name: The name returned by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_SOA_reply dns_SRV_reply +## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_PTR_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string%) &group="dns"; + +## Generated for DNS replies of type *CNAME*. For replies with multiple answers, +## an individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## soa: The parsed SOA value +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SRV_reply +## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_SOA_reply%(c: connection, msg: dns_msg, ans: dns_answer, soa: dns_soa%) &group="dns"; + +## Generated for DNS replies of type *WKS*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_WKS_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns"; + +## Generated for DNS replies of type *HINFO*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## name: The name returned by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl dns_MX_reply +## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl +## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request +## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_HINFO_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns"; + +## Generated for DNS replies of type *MX*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## name: The name returned by the reply. +## +## preference: The preference for *name* specificed by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply +## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_MX_reply%(c: connection, msg: dns_msg, ans: dns_answer, name: string, preference: count%) &group="dns"; + +## Generated for DNS replies of type *TXT*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## str: The textual information returned by the reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_TXT_reply%(c: connection, msg: dns_msg, ans: dns_answer, str: string%) &group="dns"; + +## Generated for DNS replies of type *SRV*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The type-independent part of the parsed answer record. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_SRV_reply%(c: connection, msg: dns_msg, ans: dns_answer%) &group="dns"; + +## Generated for DNS replies of type *EDNS*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The parsed EDNS reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_HINFO_reply dns_MX_reply +## dns_NS_reply dns_PTR_reply dns_SOA_reply dns_SRV_reply dns_TSIG_addl +## dns_TXT_reply dns_WKS_reply dns_end dns_full_request dns_mapping_altered +## dns_mapping_lost_name dns_mapping_new_name dns_mapping_unverified +## dns_mapping_valid dns_message dns_query_reply dns_rejected dns_request +## non_dns_request dns_max_queries dns_session_timeout dns_skip_addl +## dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_EDNS_addl%(c: connection, msg: dns_msg, ans: dns_edns_additional%) &group="dns"; + +## Generated for DNS replies of type *TSIG*. For replies with multiple answers, an +## individual event of the corresponding type is raised for each. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## ans: The parsed TSIG reply. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TXT_reply dns_WKS_reply dns_end dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_TSIG_addl%(c: connection, msg: dns_msg, ans: dns_tsig_additional%) &group="dns"; + +## Generated at the end of processing a DNS packet. This event is the last +## ``dns_*`` event that will be raised for a DNS query/reply and signals that +## all resource records have been passed on. +## +## See `Wikipedia `__ for more +## information about the DNS protocol. Bro analyzes both UDP and TCP DNS sessions. +## +## c: The connection, which may be UDP or TCP depending on the type of the +## transport-layer session being analyzed. +## +## msg: The parsed DNS message header. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_full_request +## dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +event dns_end%(c: connection, msg: dns_msg%) &group="dns"; + +## Generated for DHCP messages of type *discover*. +## +## See `Wikipedia +## `__ for more +## information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow.. +## +## msg: The parsed type-indepedent part of the DHCP message. +## +## req_addr: The specific address requested by the client. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request dns_max_queries dns_session_timeout +## dns_skip_addl dns_skip_all_addl dns_skip_all_auth dns_skip_auth +## +## .. note: Bro does not support broadcast packets (as used by the DHCP protocol). +## It treats broadcast addresses just like any other and associates packets into +## transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event dhcp_discover%(c: connection, msg: dhcp_msg, req_addr: addr%); + +## Generated for DHCP messages of type *offer*. +## +## See `Wikipedia +## `__ for more +## information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow.. +## +## mask: The subnet mask specified by the mesage. +## +## router: The list of routers specified by the message. +## +## lease: The least interval specificed by the message. +## +## serv_addr: The server address specified by the message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note: Bro does not support broadcast packets (as used by the DHCP protocol). +## It treats broadcast addresses just like any other and associates packets into +## transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event dhcp_offer%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr%); + +## Generated for DHCP messages of type *request*. +## +## See `Wikipedia +## `__ for more +## information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow.. +## +## msg: The parsed type-indepedent part of the DHCP message. +## +## req_addr: The client address specified by the message. +## +## serv_addr: The server address specified by the message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note: Bro does not support broadcast packets (as used by the DHCP protocol). +## It treats broadcast addresses just like any other and associates packets into +## transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event dhcp_request%(c: connection, msg: dhcp_msg, req_addr: addr, serv_addr: addr%); + +## Generated for DHCP messages of type *decline*. +## +## See `Wikipedia +## `__ for more +## information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow.. +## +## msg: The parsed type-indepedent part of the DHCP message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note: Bro does not support broadcast packets (as used by the DHCP protocol). +## It treats broadcast addresses just like any other and associates packets into +## transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event dhcp_decline%(c: connection, msg: dhcp_msg%); + +## Generated for DHCP messages of type *acknowledgment*. +## +## See `Wikipedia +## `__ for more +## information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow.. +## +## msg: The parsed type-indepedent part of the DHCP message. +## +## mask: The subnet mask specified by the mesage. +## +## router: The list of routers specified by the message. +## +## lease: The least interval specificed by the message. +## +## serv_addr: The server address specified by the message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note: Bro does not support broadcast packets (as used by the DHCP protocol). +## It treats broadcast addresses just like any other and associates packets into +## transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event dhcp_ack%(c: connection, msg: dhcp_msg, mask: addr, router: dhcp_router_list, lease: interval, serv_addr: addr%); + +## Generated for DHCP messages of type *negative acknowledgment*. +## +## See `Wikipedia +## `__ for more +## information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow.. +## +## msg: The parsed type-indepedent part of the DHCP message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note: Bro does not support broadcast packets (as used by the DHCP protocol). +## It treats broadcast addresses just like any other and associates packets into +## transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event dhcp_nak%(c: connection, msg: dhcp_msg%); + +## Generated for DHCP messages of type *release*. +## +## See `Wikipedia +## `__ for more +## information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow.. +## +## msg: The parsed type-indepedent part of the DHCP message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note: Bro does not support broadcast packets (as used by the DHCP protocol). +## It treats broadcast addresses just like any other and associates packets into +## transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event dhcp_release%(c: connection, msg: dhcp_msg%); + +## Generated for DHCP messages of type *inform*. +## +## See `Wikipedia +## `__ for more +## information about the DHCP protocol. +## +## c: The connection record describing the underlying UDP flow.. +## +## msg: The parsed type-indepedent part of the DHCP message. +## +## .. bro:see:: dns_AAAA_reply dns_A_reply dns_CNAME_reply dns_EDNS_addl +## dns_HINFO_reply dns_MX_reply dns_NS_reply dns_PTR_reply dns_SOA_reply +## dns_SRV_reply dns_TSIG_addl dns_TXT_reply dns_WKS_reply dns_end +## dns_full_request dns_mapping_altered dns_mapping_lost_name dns_mapping_new_name +## dns_mapping_unverified dns_mapping_valid dns_message dns_query_reply +## dns_rejected dns_request non_dns_request +## +## .. note: Bro does not support broadcast packets (as used by the DHCP protocol). +## It treats broadcast addresses just like any other and associates packets into +## transport-level flows in the same way as usual. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event dhcp_inform%(c: connection, msg: dhcp_msg%); +## Generated for HTTP requests. Bro supports persistent and pipelined HTTP sessions +## and raises corresponding events as it parses client/server dialogues. This event +## is generated as soon as a request's initial line has been parsed, and before any +## :bro:id:`http_header` events are raised. +## +## See `Wikipedia `__ for +## more information about the HTTP protocol. +## +## c: The connection. +## +## method: The HTTP method extracted from the request (e.g., ``GET``, ``POST``). +## +## original_URI: The unprocessed URI as specified in the request. +## +## unescaped_URI: The URI with all percent-encodings decoded. +## +## version: The version number specified in the request (e.g., ``1.1``). +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_entity_data http_event http_header http_message_done http_reply http_stats +## truncate_http_URI event http_request%(c: connection, method: string, original_URI: string, unescaped_URI: string, version: string%) &group="http-request"; + +## Generated for HTTP replies. Bro supports persistent and pipelined HTTP sessions +## and raises corresponding events as it parses client/server dialogues. This event +## is generated as soon as a reply's initial line has been parsed, and before any +## :bro:id:`http_header` events are raised. +## +## See `Wikipedia `__ for +## more information about the HTTP protocol. +## +## c: The connection. +## +## version: The version number specified in the reply (e.g., ``1.1``). +## +## code: The numerical response code returned by the server. +## +## reason: The textual description returned by the server along with *code*. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_entity_data http_event http_header http_message_done http_request +## http_stats event http_reply%(c: connection, version: string, code: count, reason: string%) &group="http-reply"; + +## Generated for HTTP headers. Bro supports persistent and pipelined HTTP sessions +## and raises corresponding events as it parses client/server dialogues. +## +## See `Wikipedia `__ for +## more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the header was sent by the originator of the TCP connection. +## +## name: The name of the header. +## +## value: The value of the header. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_entity_data http_event http_message_done http_reply http_request +## http_stats +## +## .. note:: This event is also raised for headers found in nested body entities. event http_header%(c: connection, is_orig: bool, name: string, value: string%) &group="http-header"; + +## Generated for HTTP headers, passing on all headers of an HTTP message at once. +## Bro supports persistent and pipelined HTTP sessions and raises corresponding +## events as it parses client/server dialogues. +## +## See `Wikipedia `__ for +## more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the header was sent by the originator of the TCP connection. +## +## hlist: A *table* containing all headers extracted from the current entity. +## The table is indexed by the position of the header (1 for the first, 2 for the +## second, etc.). +## +## .. bro:see:: http_begin_entity http_content_type http_end_entity http_entity_data +## http_event http_header http_message_done http_reply http_request http_stats +## +## .. note:: This event is also raised for headers found in nested body entities. event http_all_headers%(c: connection, is_orig: bool, hlist: mime_header_list%) &group="http-header"; + +## Generated when starting to parse an HTTP body entity. This event is generated +## at least once for each non-empty (client or server) HTTP body; and potentially +## more than once if the body contains further nested MIME entities. Bro raises +## this event just before it starts parsing each entity's content. +## +## See `Wikipedia `__ for +## more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the entity was was sent by the originator of the TCP +## connection. +## +## .. bro:see:: http_all_headers http_content_type http_end_entity http_entity_data +## http_event http_header http_message_done http_reply http_request http_stats +## mime_begin_entity event http_begin_entity%(c: connection, is_orig: bool%) &group="http-body"; + +## Generated when finishing parsing an HTTP body entity. This event is generated +## at least once for each non-empty (client or server) HTTP body; and potentially +## more than once if the body contains further nested MIME entities. Bro raises +## this event at the point when it has finished parsing an entity's content. +## +## See `Wikipedia `__ for +## more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the entity was was sent by the originator of the TCP +## connection. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_entity_data +## http_event http_header http_message_done http_reply http_request +## http_stats mime_end_entity event http_end_entity%(c: connection, is_orig: bool%) &group="http-body"; -event http_content_type%(c: connection, is_orig: bool, ty: string, subty: string%) &group="http-body"; + +## Generated when parsing an HTTP body entity, passing on the data. This event +## can potentially be raised many times for each entity, each time passing a +## chunk of the data of not further defined size. +## +## A common idiom for using this event is to first *reassemble* the data +## at the scripting layer by concatening it to a successvily growing +## string; and only perform further content analysis once the corresponding +## :bro:id:`http_end_entity` event has been raised. Note, however, that doing so +## can be quite expensive for HTTP tranders. At the very least, one should +## impose an upper size limit on how much data is being buffered. +## +## See `Wikipedia `__ for +## more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the entity was was sent by the originator of the TCP +## connection. +## +## length: The length of *data*. +## +## data: One chunk of raw entity data. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_event http_header http_message_done http_reply http_request http_stats +## mime_entity_data http_entity_data_delivery_size skip_http_data event http_entity_data%(c: connection, is_orig: bool, length: count, data: string%) &group="http-body"; + +## Generated for reporting an HTTP bodie's content type. This event is +## generated at the end of parsing an HTTP header, passing on the MIME +## type as specified by the ``Content-Type`` header. If that header is +## missing, this event is still raised with a default value of ``text/plain``. +## +## See `Wikipedia `__ for +## more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the entity was was sent by the originator of the TCP +## connection. +## +## ty: The main type. +## +## subty: The subtype. +## +## .. bro:see:: http_all_headers http_begin_entity http_end_entity http_entity_data +## http_event http_header http_message_done http_reply http_request http_stats +## +## .. note:: This event is also raised for headers found in nested body +## entities. +event http_content_type%(c: connection, is_orig: bool, ty: string, subty: string%) &group="http-body"; + +## Generated once at the end of parsing an HTTP message. Bro supports persistent +## and pipelined HTTP sessions and raises corresponding events as it parses +## client/server dialogues. A "message" is one top-level HTTP entity, such as a +## complete request or reply. Each message can have further nested sub-entities +## inside. This event is raised once all sub-entities belonging to a top-level +## message have been processed (and their corresponding ``http_entity_*`` events +## generated). +## +## See `Wikipedia `__ for +## more information about the HTTP protocol. +## +## c: The connection. +## +## is_orig: True if the entity was was sent by the originator of the TCP +## connection. +## +## stat: Further meta information about the message. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_entity_data http_event http_header http_reply http_request http_stats event http_message_done%(c: connection, is_orig: bool, stat: http_message_stat%) &group="http-body"; + +## Generated for errors found when decoding HTTP requests or replies. +## +## See `Wikipedia `__ for +## more information about the HTTP protocol. +## +## c: The connection. +## +## event_type: A string describing the general category of the problem found (e.g., +## ``illegal format``). +## +## detail: Further more detailed description of the error. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_entity_data http_header http_message_done http_reply http_request +## http_stats mime_event event http_event%(c: connection, event_type: string, detail: string%); + +## Generated at the end of an HTTP session to report statistics about it. This +## event is raised after all of an HTTP session's requests and replies have been +## fully processed. +## +## c: The connection. +## +## stats: Statistics summarizing HTTP-level properties of the finished connection. +## +## .. bro:see:: http_all_headers http_begin_entity http_content_type http_end_entity +## http_entity_data http_event http_header http_message_done http_reply +## http_request event http_stats%(c: connection, stats: http_stats_rec%); +## Generated when seeing an SSH client's version identification. The SSH protocol +## starts with a clear-test handshake message that reports client and server +## protocol/software versions. This event provides access to what the client +## sent. +## +## +## See `Wikipedia `__ for more +## information about the SSH protocol. +## +## c: The connection. +## +## version: The version string the client sent (e.g., `SSH-2.0-libssh-0.11`). +## +## .. bro:see:: ssh_server_version +## +## .. note:: As everything after the initial version handshake proceeds encrypted, +## Bro cannot further analyze SSH sessions. event ssh_client_version%(c: connection, version: string%); + +## Generated when seeing an SSH server's version identification. The SSH protocol +## starts with a clear-test handshake message that reports client and server +## protocol/software versions. This event provides access to what the server +## sent. +## +## See `Wikipedia `__ for more +## information about the SSH protocol. +## +## c: The connection. +## +## version: The version string the server sent (e.g., +## ``SSH-1.99-OpenSSH_3.9p1``). +## +## .. bro:see:: ssh_client_version +## +## .. note:: As everything coming after the initial version handshake proceeds +## encrypted, Bro cannot further analyze SSH sessions. event ssh_server_version%(c: connection, version: string%); +## Generated for an SSL/TLS client's initial *hello* message. SSL/TLS sessions +## start with an unencrypted handshake, and Bro extracts as much information out +## that it as it can. This event provides access to the initial information sent by +## the client. +## +## See `Wikipedia `__ for +## more information about the SSL/TLS protocol. +## +## c: The connection. +## +## version: The protocol version as extracted from the client's +## message. The values are standardized as part of the SSL/TLS protocol. The +## :bro:id:`SSL::version_strings` table maps them to descriptive names. +## +## possible_ts: The current time as sent by the client. Note that SSL/TLS does not +## require clocks to be set correctly, so treat with care. +## +## session_id: The session ID sent by the client (if any). +## +## ciphers: The list of ciphers the client offered to use. The values are +## standardized as part of the SSL/TLS protocol. The :bro:id:`SSL::cipher_desc` table +## maps them to descriptive names. +## +## .. bro:see:: ssl_alert ssl_established ssl_extension ssl_server_hello +## ssl_session_ticket_handshake x509_certificate x509_error x509_extension event ssl_client_hello%(c: connection, version: count, possible_ts: time, session_id: string, ciphers: count_set%); + +## Generated for an SSL/TLS servers's initial *hello* message. SSL/TLS sessions +## start with an unencrypted handshake, and Bro extracts as much information out +## of that as it can. This event provides access to the initial information sent by +## the client. +## +## See `Wikipedia `__ for +## more information about the SSL/TLS protocol. +## +## c: The connection. +## +## version: The protocol version as extracted from the servers's message. +## The values are standardized as part of the SSL/TLS protocol. The +## :bro:id:`SSL::version_strings` table maps them to descriptive names. +## +## possible_ts: The current time as sent by the server. Note that SSL/TLS does not +## require clocks to be set correctly, so treat with care. +## +## session_id: The session ID as sent back by the server (if any). +## +## cipher: The cipher chosen by the server. The values are standardized as part +## of the SSL/TLS protocol. The :bro:id:`SSL::cipher_desc` table maps them to +## descriptive names. +## +## comp_method: The compression method chosen by the client. The values are +## standardized as part of the SSL/TLS protocol. +## +## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension +## ssl_session_ticket_handshake x509_certificate x509_error x509_extension event ssl_server_hello%(c: connection, version: count, possible_ts: time, session_id: string, cipher: count, comp_method: count%); -event ssl_extension%(c: connection, code: count, val: string%); + +## Generated for SSL/TLS extensions seen in an initial handshake. SSL/TLS sessions +## start with an unencrypted handshake, and Bro extracts as much information out of +## that as it can. This event provides access to any extensions either side sents +## as part of extended *hello* message. +## +## c: The connection. +## +## is_orig: True if event is raised for originator side of the connection. +## +## code: The numerical code of the extension. The values are standardized as +## part of the SSL/TLS protocol. The :bro:id:`SSL::extensions` table maps them to +## descriptive names. +## +## val: The raw extension value that was sent in the message. +## +## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_server_hello +## ssl_session_ticket_handshake x509_certificate x509_error x509_extension +event ssl_extension%(c: connection, is_orig: bool, code: count, val: string%); + +## Generated at the end of an SSL/TLS handshake. SSL/TLS sessions start with +## an unencrypted handshake, and Bro extracts as much information out of that as +## it can. This event signals the time when an SSL/TLS has finished the handshake +## and its endpoints consider it as fully established. Typically, everything from +## now on will be encrypted. +## +## See `Wikipedia `__ for +## more information about the SSL/TLS protocol. +## +## c: The connection. +## +## .. bro:see:: ssl_alert ssl_client_hello ssl_extension ssl_server_hello +## ssl_session_ticket_handshake x509_certificate x509_error x509_extension event ssl_established%(c: connection%); -event ssl_alert%(c: connection, level: count, desc: count%); -event x509_certificate%(c: connection, cert: X509, is_server: bool, chain_idx: count, chain_len: count, der_cert: string%); -event x509_extension%(c: connection, data: string%); -event x509_error%(c: connection, err: count%); +## Generated for SSL/TLS alert records. SSL/TLS sessions start with an unencrypted +## handshake, and Bro extracts as much information out of that as it can. If during +## that handshake, an endpoint encounteres a fatal error, it sends an *alert* +## record, that it turns triggers this event. After an *alert*, any endpoint +## may close the connection immediately. +## +## See `Wikipedia `__ for +## more information about the SSL/TLS protocol. +## +## c: The connection. +## +## is_orig: True if event is raised for originator side of the connection. +## +## level: The severity level, as sent in the *alert*. The values are defined as +## part of the SSL/TLS protocol. +## +## desc: A numerical value identifying the cause of the *alert*. The values are +## defined as part of the SSL/TLS protocol. +## +## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello +## ssl_session_ticket_handshake x509_certificate x509_error x509_extension +event ssl_alert%(c: connection, is_orig: bool, level: count, desc: count%); -event stp_create_endp%(c: connection, e: int, is_orig: bool%); -event stp_resume_endp%(e: int%); -event stp_correlate_pair%(e1: int, e2: int%); -event stp_remove_pair%(e1: int, e2: int%); -event stp_remove_endp%(e: int%); +## Generated for SSL/TLS handshake messages that are a part of the stateless-server +## session resumption mechanism. SSL/TLS sessions start with an unencrypted +## handshake, and Bro extracts as much information out of that as it can. This +## event is raised when an SSL/TLS server passes session ticket to the client that +## can later be used for resuming the session. The mechanism is described in +## :rfc:`4507` +## +## See `Wikipedia `__ for +## more information about the SSL/TLS protocol. +## +## c: The connection. +## +## ticket_lifetime_hint: A hint from the server about how long the ticket +## should be stored by the client. +## +## ticket: The raw ticket data. +## +## .. bro:see:: ssl_client_hello ssl_established ssl_extension ssl_server_hello +## x509_certificate x509_error x509_extension ssl_alert +event ssl_session_ticket_handshake%(c: connection, ticket_lifetime_hint: count, ticket: string%); +## Generated for x509 certificates seen in SSL/TLS connections. During the initial +## SSL/TLS handshake, certificates are exchanged in the clear. Bro raises this +## event for each certificate seen (including both a site's primary cert, and +## further certs sent as part of the validation chain). +## +## See `Wikipedia `__ for more information about +## the X.509 format. +## +## c: The connection. +## +## is_orig: True if event is raised for originator side of the connection. +## +## cert: The parsed certificate. +## +## chain_idx: The index in the validation chain that this cert has. Index zero +## indicates an endpoints primary cert, while higher indices +## indicate the place in the validation chain (which has length +## *chain_len*). +## +## chain_len: The total length of the validation chain that this cert is part +## of. +## +## der_cert: The complete cert encoded in `DER +## `__ format. +## +## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension +## ssl_server_hello x509_error x509_extension x509_verify +event x509_certificate%(c: connection, is_orig: bool, cert: X509, chain_idx: count, chain_len: count, der_cert: string%); + +## Generated for X.509 extensions seen in a certificate. +## +## See `Wikipedia `__ for more information about +## the X.509 format. +## +## c: The connection. +## +## is_orig: True if event is raised for originator side of the connection. +## +## data: The raw data associated with the extension. +## +## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension +## ssl_server_hello x509_certificate x509_error x509_verify +event x509_extension%(c: connection, is_orig: bool, data: string%); + +## Generated when errors occur during parsing an X.509 certificate. +## +## See `Wikipedia `__ for more information about +## the X.509 format. +## +## c: The connection. +## +## is_orig: True if event is raised for originator side of the connection. +## +## err: An error code describing what went wrong. :bro:id:`SSL::x509_errors` maps +## error codes to a textual description. +## +## .. bro:see:: ssl_alert ssl_client_hello ssl_established ssl_extension +## ssl_server_hello x509_certificate x509_extension x509_err2str x509_verify +event x509_error%(c: connection, is_orig: bool, err: count%); + +## TODO. +## +## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_request +## dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event dce_rpc_message%(c: connection, is_orig: bool, ptype: dce_rpc_ptype, msg: string%); + +## TODO. +## +## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_message dce_rpc_request +## dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event dce_rpc_bind%(c: connection, uuid: string%); + +## TODO. +## +## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message +## dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event dce_rpc_request%(c: connection, opnum: count, stub: string%); + +## TODO. +## +## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message +## dce_rpc_request rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event dce_rpc_response%(c: connection, opnum: count, stub: string%); -# DCE/RPC endpoint mapper events. +## TODO. +## +## .. bro:see:: rpc_call rpc_dialogue rpc_reply dce_rpc_bind dce_rpc_message +## dce_rpc_request dce_rpc_response rpc_timeout +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event epm_map_response%(c: connection, uuid: string, p: port, h: addr%); -# "length" is the length of body (not including the frame header) +## Generated for NCP requests (Netware Core Protocol). +## +## See `Wikipedia `__ for more +## information about the NCP protocol. +## +## c: The connection. +## +## frame_type: The frame type, as specified by the protocol. +## +## length: The length of the request body, excluding the frame header, +## +## func: The requested function, as specified by the protocol. +## +## .. bro:see:: ncp_reply +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event ncp_request%(c: connection, frame_type: count, length: count, func: count%); + +## Generated for NCP replies (Netware Core Protocol). +## +## See `Wikipedia `__ for more +## information about the NCP protocol. +## +## c: The connection. +## +## frame_type: The frame type, as specified by the protocol. +## +## length: The length of the request body, excluding the frame header, +## +## req_frame: The frame type from the corresponding request. +## +## req_frame: The function code from the corresponding request. +## +## completion_code: The replie's completion code, as specified by the protocol. +## +## .. bro:see:: ncp_request +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event ncp_reply%(c: connection, frame_type: count, length: count, req_frame: count, req_func: count, completion_code: count%); -event interconn_stats%(c: connection, os: interconn_endp_stats, rs: interconn_endp_stats%); -event interconn_remove_conn%(c: connection%); - -event backdoor_stats%(c: connection, os: backdoor_endp_stats, rs: backdoor_endp_stats%); -event backdoor_remove_conn%(c: connection%); -event ssh_signature_found%(c: connection, is_orig: bool%); -event telnet_signature_found%(c: connection, is_orig: bool, len: count%); -event rlogin_signature_found%(c: connection, is_orig: bool, num_null: count, len: count%); -event root_backdoor_signature_found%(c: connection%); -event ftp_signature_found%(c: connection%); -event napster_signature_found%(c: connection%); -event gnutella_signature_found%(c: connection%); -event kazaa_signature_found%(c: connection%); -event http_signature_found%(c: connection%); -event http_proxy_signature_found%(c: connection%); -event smtp_signature_found%(c: connection%); -event irc_signature_found%(c: connection%); -event gaobot_signature_found%(c: connection%); - +## Generated for client-side commands on POP3 connections. +## +## See `Wikipedia `__ for more information about +## the POP3 protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP connection. +## +## command: The command sent. +## +## arg: The argument to the command. +## +## .. bro:see:: pop3_data pop3_login_failure pop3_login_success pop3_reply +## pop3_terminate pop3_unexpected +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pop3_request%(c: connection, is_orig: bool, command: string, arg: string%); + +## Generated for server-side replies to commands on POP3 connections. +## +## See `Wikipedia `__ for more information about +## the POP3 protocol. +## +## c: The connection. +## +## is_orig: True if the command was sent by the originator of the TCP connection. +## +## cmd: The success indicator sent by the server. This corresponds to the +## first token on the line sent, and should be either ``OK`` or ``ERR``. +## +## msg: The textual description the server sent along with *cmd*. +## +## arg: The argument to the command. +## +## .. bro:see:: pop3_data pop3_login_failure pop3_login_success pop3_request +## pop3_terminate pop3_unexpected +## +## .. todo: This event is receiving odd parameters, should unify. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pop3_reply%(c: connection, is_orig: bool, cmd: string, msg: string%); + +## Generated for server-side multi-lines responses on POP3 connections. POP3 +## connection use multi-line responses to send buld data, such as the actual +## mails. This event is generated once for each line that's part of such a +## response. +## +## See `Wikipedia `__ for more information about +## the POP3 protocol. +## +## c: The connection. +## +## is_orig: True if the data was sent by the originator of the TCP connection. +## +## data: The data sent. +## +## .. bro:see:: pop3_login_failure pop3_login_success pop3_reply pop3_request +## pop3_terminate pop3_unexpected +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pop3_data%(c: connection, is_orig: bool, data: string%); + +## Generated for errors encountered on POP3 sessions. If the POP3 analyzers finds +## state transition that do not confirm to the protocol specification, or other +## situations it can't handle, it raises this event. +## +## See `Wikipedia `__ for more information about +## the POP3 protocol. +## +## c: The connection. +## +## is_orig: True if the data was sent by the originator of the TCP connection. +## +## msg: A textual description of the situation. +## +## detail: The input that triggered the event. +## +## .. bro:see:: pop3_data pop3_login_failure pop3_login_success pop3_reply pop3_request +## pop3_terminate +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pop3_unexpected%(c: connection, is_orig: bool, msg: string, detail: string%); + +## Generated when POP3 connection go encrypted. While POP3 is by default a +## clear-text protocol, extensions exist to switch to encryption. This event is +## generated if that happens and the analyzers then stops processing the +## connection. +## +## See `Wikipedia `__ for more information about +## the POP3 protocol. +## +## c: The connection. +## +## is_orig: Always false. +## +## msg: A descriptive message why processing was stopped. +## +## .. bro:see:: pop3_data pop3_login_failure pop3_login_success pop3_reply pop3_request +## pop3_unexpected +## +## .. note:: Currently, only the ``STARTLS`` command is recognized and +## triggers this. +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pop3_terminate%(c: connection, is_orig: bool, msg: string%); + +## Generated for successful authentications on POP3 connections. +## +## See `Wikipedia `__ for more information about +## the POP3 protocol. +## +## c: The connection. +## +## is_orig: Always false. +## +## user: The user name used for authentication. The event is only generated if +## a non-empty user name was used. +## +## password: The password used for authentication. +## +## .. bro:see:: pop3_data pop3_login_failure pop3_reply pop3_request pop3_terminate +## pop3_unexpected +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pop3_login_success%(c: connection, is_orig: bool, user: string, password: string%); + +## Generated for unsuccessful authentications on POP3 connections. +## +## See `Wikipedia `__ for more information about +## the POP3 protocol. +## +## c: The connection. +## +## is_orig: Always false. +## +## user: The user name attempted for authentication. The event is only generated if +## a non-empty user name was used. +## +## password: The password attempted for authentication. +## +## .. bro:see:: pop3_data pop3_login_success pop3_reply pop3_request pop3_terminate +## pop3_unexpected +## +## .. todo:: Bro's current default configuration does not activate the protocol +## analyzer that generates this event; the corresponding script has not yet +## been ported to Bro 2.x. To still enable this event, one needs to add a +## corresponding entry to :bro:see:`dpd_config` or a DPD payload signature. event pop3_login_failure%(c: connection, is_orig: bool, user: string, password: string%); + +## Generated for all client-side IRC commands. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: Always true. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## command: The command. +## +## arguments: The arguments for the command. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +## +## .. note:: This event is generated only for message that originate at the +## clients-side. Commands coming in from remote trigger the ge:bro:id:`irc_message` +## event instead. event irc_request%(c: connection, is_orig: bool, prefix: string, command: string, arguments: string%); + +## Generated for all IRC replies. IRC replies are sent in response to a +## request and come with a reply code. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## prefix: The optional prefix comming with the reply. IRC uses the prefix to +## indicate the true origin of a message. +## +## code: The reply code, as specified by the protocol. +## +## params: The reply's parameters. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message event irc_reply%(c: connection, is_orig: bool, prefix: string, code: count, params: string%); + +## Generated for IRC commands forwarded from the server to the client. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: Always false. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## command: The command. +## +## arguments: The arguments for the command. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +## +## .. note:: +## +## This event is generated only for messages that are forwarded by the server +## to the client. Commands coming from client trigger the :bro:id:`irc_request` +## event instead. event irc_message%(c: connection, is_orig: bool, prefix: string, command: string, message: string%); + +## Generated for IRC messages of type *quit*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## nick: The nick name coming with the message. +## +## message: The text included with the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message event irc_quit_message%(c: connection, is_orig: bool, nick: string, message: string%); + +## Generated for IRC messages of type *privmsg*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## source: The source of the private communication. +## +## target: The target of the private communication. +## +## message: The text of communication. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message event irc_privmsg_message%(c: connection, is_orig: bool, source: string, target: string, message: string%); + +## Generated for IRC messages of type *notice*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## source: The source of the private communication. +## +## target: The target of the private communication. +## +## message: The text of communication. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message event irc_notice_message%(c: connection, is_orig: bool, source: string, target: string, message: string%); + +## Generated for IRC messages of type *squery*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## source: The source of the private communication. +## +## target: The target of the private communication. +## +## message: The text of communication. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message event irc_squery_message%(c: connection, is_orig: bool, source: string, target: string, message: string%); + +## Generated for IRC messages of type *join*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## info_list: The user information coming with the command. +## +## message: The text of communication. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message event irc_join_message%(c: connection, is_orig: bool, info_list: irc_join_list%); + +## Generated for IRC messages of type *part*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## nick: The nickname coming with the message. +## +## chans: The set of channels affected. +## +## message: The text coming with the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_password_message event irc_part_message%(c: connection, is_orig: bool, nick: string, chans: string_set, message: string%); + +## Generated for IRC messages of type *nick*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## who: The user changing its nickname. +## +## newnick: The new nickname. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message event irc_nick_message%(c: connection, is_orig: bool, who: string, newnick: string%); + +## Generated when a server rejects an IRC nickname. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invite_message irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message event irc_invalid_nick%(c: connection, is_orig: bool%); + +## Generated for an IRC reply of type *luserclient*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## users: The number of users as returned in the reply. +## +## services: The number of services as returned in the reply. +## +## servers: The number of servers as returned in the reply. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message event irc_network_info%(c: connection, is_orig: bool, users: count, services: count, servers: count%); + +## Generated for an IRC reply of type *luserme*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## users: The number of users as returned in the reply. +## +## services: The number of services as returned in the reply. +## +## servers: The number of servers as returned in the reply. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message event irc_server_info%(c: connection, is_orig: bool, users: count, services: count, servers: count%); + +## Generated for an IRC reply of type *luserchannels*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## chans: The number of channels as returned in the reply. +## +## .. bro:see:: irc_channel_topic irc_dcc_message irc_error_message irc_global_users +## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message event irc_channel_info%(c: connection, is_orig: bool, chans: count%); + +## Generated for an IRC reply of type *whoreply*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## target_nick: The target nick name. +## +## channel: The channel. +## +## user: The user. +## +## host: The host. +## +## server: The server. +## +## nick: The nick name. +## +## params: The parameters. +## +## hops: The hop count. +## +## real_name: The real name. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message event irc_who_line%(c: connection, is_orig: bool, target_nick: string, channel: string, user: string, host: string, server: string, nick: string, params: string, hops: count, real_name: string%); -event irc_who_message%(c: connection, is_orig: bool, mask: string, oper: bool%); -event irc_whois_message%(c: connection, is_orig: bool, server: string, users: string%); -event irc_whois_user_line%(c: connection, is_orig: bool, nick: string, - user: string, host: string, real_name: string%); -event irc_whois_operator_line%(c: connection, is_orig: bool, nick: string%); -event irc_whois_channel_line%(c: connection, is_orig: bool, nick: string, - chans: string_set%); -event irc_oper_message%(c: connection, is_orig: bool, user: string, password: string%); -event irc_oper_response%(c: connection, is_orig: bool, got_oper: bool%); -event irc_kick_message%(c: connection, is_orig: bool, prefix: string, - chans: string, users: string, comment: string%); -event irc_error_message%(c: connection, is_orig: bool, prefix: string, message: string%); -event irc_invite_message%(c: connection, is_orig: bool, prefix: string, - nickname: string, channel: string%); -event irc_mode_message%(c: connection, is_orig: bool, prefix: string, params: string%); -event irc_squit_message%(c: connection, is_orig: bool, prefix: string, - server: string, message: string%); + + +## Generated for an IRC reply of type *namereply*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## c_type: The channel type. +## +## channel: The channel. +## +## users: The set of users. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message event irc_names_info%(c: connection, is_orig: bool, c_type: string, channel: string, users: string_set%); + +## Generated for an IRC reply of type *whoisoperator*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## nick: The nick name specified in the reply. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_whois_operator_line%(c: connection, is_orig: bool, nick: string%); + +## Generated for an IRC reply of type *whoischannels*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## nick: The nick name specified in the reply. +## +## chans: The set of channels returned. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_whois_channel_line%(c: connection, is_orig: bool, nick: string, + chans: string_set%); + +## Generated for an IRC reply of type *whoisuser*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## nick: The nick name specified in the reply. +## +## user: The user name specified in the reply. +## +## host: The host name specified in the reply. +## +## user: The user name specified in the reply. +## +## real_name: The real name specified in the reply. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_whois_user_line%(c: connection, is_orig: bool, nick: string, + user: string, host: string, real_name: string%); + +## Generated for IRC replies of type *youreoper* and *nooperhost*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## got_oper: True if the *oper* command was executed successfully +## (*youreport*) and false otherwise (*nooperhost*). +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_part_message +## irc_password_message +event irc_oper_response%(c: connection, is_orig: bool, got_oper: bool%); + +## Generated for an IRC reply of type *globalusers*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## msg: The message coming with the reply. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_global_users%(c: connection, is_orig: bool, prefix: string, msg: string%); + +## Generated for an IRC reply of type *topic*. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## channel: The channel name specified in the reply. +## +## topic: The topic specified in the reply. +## +## .. bro:see:: irc_channel_info irc_dcc_message irc_error_message irc_global_users +## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_channel_topic%(c: connection, is_orig: bool, channel: string, topic: string%); + +## Generated for IRC messages of type *who*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## is_orig: True if the command what sent by the originator of the TCP connection. +## +## mask: The mask specified in the message. +## +## oper: True if the operator flag was set. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_who_message%(c: connection, is_orig: bool, mask: string, oper: bool%); + +## Generated for IRC messages of type *whois*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_whois_message%(c: connection, is_orig: bool, server: string, users: string%); + +## Generated for IRC messages of type *oper*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## user: The user specified in the message. +## +## password: The password specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_response irc_part_message +## irc_password_message +event irc_oper_message%(c: connection, is_orig: bool, user: string, password: string%); + +## Generated for IRC messages of type *kick*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## chans: The channels specified in the message. +## +## users: The users specified in the message. +## +## comment: The comment specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_kick_message%(c: connection, is_orig: bool, prefix: string, + chans: string, users: string, comment: string%); + +## Generated for IRC messages of type *error*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## message: The textual description specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_global_users +## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_error_message%(c: connection, is_orig: bool, prefix: string, message: string%); + +## Generated for IRC messages of type *invite*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## nickname: The nick name specified in the message. +## +## channel: The channel specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_invite_message%(c: connection, is_orig: bool, prefix: string, + nickname: string, channel: string%); + +## Generated for IRC messages of type *mode*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## params: The parameters coming with the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message +event irc_mode_message%(c: connection, is_orig: bool, prefix: string, params: string%); + +## Generated for IRC messages of type *squit*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## server: The server specified in the message. +## +## messate: The textual description specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message +event irc_squit_message%(c: connection, is_orig: bool, prefix: string, + server: string, message: string%); + +## Generated for IRC messages of type *dcc*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## prefix: The optional prefix coming with the command. IRC uses the prefix to +## indicate the true origin of a message. +## +## target: The target specified in the message. +## +## dcc_type: The DCC type specified in the message. +## +## argument: The argument specified in the message. +## +## address: The address specified in the message. +## +## dest_port: The destination port specified in the message. +## +## size: The size specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_error_message irc_global_users +## irc_invalid_nick irc_invite_message irc_join_message irc_kick_message +## irc_message irc_mode_message irc_names_info irc_network_info irc_nick_message +## irc_notice_message irc_oper_message irc_oper_response irc_part_message +## irc_password_message event irc_dcc_message%(c: connection, is_orig: bool, prefix: string, target: string, dcc_type: string, argument: string, address: addr, dest_port: count, size: count%); -event irc_global_users%(c: connection, is_orig: bool, prefix: string, msg: string%); + +## Generated for IRC messages of type *user*. This event is generated for messages +## coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## user: The user specified in the message. +## +## host: The host name specified in the message. +## +## server: The server name specified in the message. +## +## real_name: The real name specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message irc_password_message event irc_user_message%(c: connection, is_orig: bool, user: string, host: string, server: string, real_name: string%); -event irc_channel_topic%(c: connection, is_orig: bool, channel: string, topic: string%); + +## Generated for IRC messages of type *password*. This event is generated for +## messages coming from both the client and the server. +## +## See `Wikipedia `__ for more +## information about the IRC protocol. +## +## c: The connection. +## +## password: The password specified in the message. +## +## .. bro:see:: irc_channel_info irc_channel_topic irc_dcc_message irc_error_message +## irc_global_users irc_invalid_nick irc_invite_message irc_join_message +## irc_kick_message irc_message irc_mode_message irc_names_info irc_network_info +## irc_nick_message irc_notice_message irc_oper_message irc_oper_response +## irc_part_message event irc_password_message%(c: connection, is_orig: bool, password: string%); +## TODO. +## +## .. bro:see:: event file_transferred%(c: connection, prefix: string, descr: string, mime_type: string%); -event file_virus%(c: connection, virname: string%); +## Generated for monitored Syslog messages. +## +## See `Wikipedia `__ for more +## information about the Syslog protocol. +## +## c: The connection record for the underlying transport-layer session/flow. +## +## facility: The "facility" included in the message. +## +## severity: The "severity" included in the message. +## +## msg: The message logged. +## +## .. note:: Bro currently parses only UDP syslog traffic. Support for TCP syslog +## will be added soon. event syslog_message%(c: connection, facility: count, severity: count, msg: string%); +## Generated when a signature matches. Bro's signature engine provide +## high-performance pattern matching separately from the normal script processing. +## If a signature with an ``event`` action matches, this event is raised. +## +## See the :doc:`user manual ` for more information about Bro's +## signature engine. +## +## state: Context about the match, including which signatures triggered the +## event and the connection for which the match was found. +## +## msg: The message passed to the ``event`` signature action. +## +## data; The last chunk of input that triggered the match. Note that the specifics +## here are no well-defined as Bro does not buffer any input. If a match is split +## across packet boundaries, only the last chunk triggering the will be passed on +## to the event. event signature_match%(state: signature_state, msg: string, data: string%); -# Generated if a handler finds an identification of the software -# used on a system. +## Generated when a protocol analyzer finds an identification of a software +## used on a system. This is a protocol-independent event that is fed by +## different analyzers. For example, the HTTP analyzer reports user-agent and +## server software by raising this event, assuming it can parse it (if not, +## :bro:id:`software_parse_error` will be generated instead). +## +## c: The connection. +## +## host: The host running the reported software. +## +## s: A description of the software found. +## +## descr: The raw (unparsed) software identification string as extracted from the +## protocol. +## +## .. bro:see:: software_parse_error software_unparsed_version_found OS_version_found event software_version_found%(c: connection, host: addr, s: software, descr: string%); -# Generated if a handler finds a version but cannot parse it. +## Generated when a protocol analyzer finds an identification of a software used on +## a system but cannot parse it. This is a protocol-independent event that is fed +## by different analyzers. For example, the HTTP analyzer reports user-agent and +## server software by raising this event if it cannot parse them directly (if canit +## :bro:id:`software_version_found` will be generated instead). +## +## c: The connection. +## +## host: The host running the reported software. +## +## descr: The raw (unparsed) software identification string as extracted from the +## protocol. +## +## .. bro:see:: software_version_found software_unparsed_version_found +## OS_version_found event software_parse_error%(c: connection, host: addr, descr: string%); -# Generated once for each raw (unparsed) software identification. +## Generated when a protocol analyzer finds an identification of a software +## used on a system. This is a protocol-independent event that is fed by +## different analyzers. For example, the HTTP analyzer reports user-agent and +## server software by raising this event. Different from +## :bro:id:`software_version_found` and :bro:id:`software_parse_error`, this +## event is always raised, independent of whether Bro can parse the version +## string. +## +## c: The connection. +## +## host: The host running the reported software. +## +## descr: The software identification string as extracted from the protocol. +## +## .. bro:see:: software_parse_error software_version_found OS_version_found event software_unparsed_version_found%(c: connection, host: addr, str: string%); -# Generated when an operating system has been fingerprinted. +## Generated when an operating system has been fingerprinted. Bro uses `p0f +## `__ to fingerprint endpoints passively, +## and it raises this event for each system identified. The p0f fingerprints are +## defined by :bro:id:`passive_fingerprint_file`. +## +## .. bro:see:: passive_fingerprint_file software_parse_error +## software_version_found software_unparsed_version_found +## generate_OS_version_event event OS_version_found%(c: connection, host: addr, OS: OS_version%); -# Generated when an IP address gets mapped for the first time. -event anonymization_mapping%(orig: addr, mapped: addr%); - -# Generated when a connection to a remote Bro has been established. +## Generated when a connection to a remote Bro has been established. This event +## is intended primarily for use by Bro's communication framework, but it can also +## trigger additional code if helpful. +## +## p: A record describing the peer. +## +## .. bro:see:: remote_capture_filter remote_connection_closed remote_connection_error +## remote_connection_handshake_done remote_event_registered remote_log remote_pong +## remote_state_access_performed remote_state_inconsistency print_hook event remote_connection_established%(p: event_peer%); -# Generated when a connection to a remote Bro has been closed. +## Generated when a connection to a remote Bro has been closed. This event is +## intended primarily for use by Bro's communication framework, but it can +## also trigger additional code if helpful. +## +## p: A record describing the peer. +## +## .. bro:see:: remote_capture_filter remote_connection_error +## remote_connection_established remote_connection_handshake_done +## remote_event_registered remote_log remote_pong remote_state_access_performed +## remote_state_inconsistency print_hook event remote_connection_closed%(p: event_peer%); -# Generated when a remote connection's handshake has been completed. +## Generated when a remote connection's initial handshake has been completed. This +## event is intended primarily for use by Bro's communication framework, but it can +## also trigger additional code if helpful. +## +## p: A record describing the peer. +## +## .. bro:see:: remote_capture_filter remote_connection_closed remote_connection_error +## remote_connection_established remote_event_registered remote_log remote_pong +## remote_state_access_performed remote_state_inconsistency print_hook event remote_connection_handshake_done%(p: event_peer%); -# Generated for each event registered by a remote peer. +## Generated for each event registered by a remote peer. This event is intended +## primarily for use by Bro's communication framework, but it can also trigger +## additional code if helpful. +## +## p: A record describing the peer. +## +## .. bro:see:: remote_capture_filter remote_connection_closed +## remote_connection_error remote_connection_established +## remote_connection_handshake_done remote_log remote_pong +## remote_state_access_performed remote_state_inconsistency print_hook event remote_event_registered%(p: event_peer, name: string%); -# Generated when a connection to a remote Bro causes some error. +## Generated when a connection to a remote Bro encountered an error. This event +## is intended primarily for use by Bro's communication framework, but it can also +## trigger additional code if helpful. +## +## p: A record describing the peer. +## +## reason: A textual description of the error. +## +## .. bro:see:: remote_capture_filter remote_connection_closed +## remote_connection_established remote_connection_handshake_done +## remote_event_registered remote_log remote_pong remote_state_access_performed +## remote_state_inconsistency print_hook event remote_connection_error%(p: event_peer, reason: string%); -# Generated when a remote peer sends us some capture filter. + + +## Generated when a remote peer sent us a capture filter. While this event is +## intended primarily for use by Bro's communication framework, it can also trigger +## additional code if helpful. +## +## p: A record describing the peer. +## +## filter: The filter string sent by the peer. +## +## .. bro:see:: remote_connection_closed remote_connection_error +## remote_connection_established remote_connection_handshake_done +## remote_event_registered remote_log remote_pong remote_state_access_performed +## remote_state_inconsistency print_hook event remote_capture_filter%(p: event_peer, filter: string%); -# Generated after a call to send_state() when all data has been successfully -# sent to the remote side. +## Generated after a call to :bro:id:`send_state` when all data has been +## successfully sent to the remote side. While this event is +## intended primarily for use by Bro's communication framework, it can also trigger +## additional code if helpful. +## +## p: A record describing the remote peer. +## +## .. bro:see:: remote_capture_filter remote_connection_closed +## remote_connection_error remote_connection_established +## remote_connection_handshake_done remote_event_registered remote_log remote_pong +## remote_state_access_performed remote_state_inconsistency print_hook event finished_send_state%(p: event_peer%); -# Generated if state synchronization detects an inconsistency. +## Generated if state synchronization detects an inconsistency. While this event +## is intended primarily for use by Bro's communication framework, it can also +## trigger additional code if helpful. This event is only raised if +## :bro:id:`remote_check_sync_consistency` is false. +## +## operation: The textual description of the state operation performed. +## +## id: The name of the Bro script identifier that was operated on. +## +## expected_old: A textual representation of the value of *id* that was expected to +## be found before the operation was carried out. +## +## real_old: A textual representation of the value of *id* that was actually found +## before the operation was carried out. The difference between +## *real_old* and *expected_old* is the inconsistency being reported. +## +## .. bro:see:: remote_capture_filter remote_connection_closed +## remote_connection_error remote_connection_established +## remote_connection_handshake_done remote_event_registered remote_log remote_pong +## remote_state_access_performed print_hook remote_check_sync_consistency event remote_state_inconsistency%(operation: string, id: string, expected_old: string, real_old: string%); -# Generated for communication log message. +## Generated for communication log messages. While this event is +## intended primarily for use by Bro's communication framework, it can also trigger +## additional code if helpful. +## +## level: The log level, which is either :bro:id:`REMOTE_LOG_INFO` or +## :bro:id:`REMOTE_LOG_ERROR`. +## +## src: The component of the comminication system that logged the message. +## Currently, this will be one of :bro:id:`REMOTE_SRC_CHILD` (Bro's +## child process), :bro:id:`REMOTE_SRC_PARENT` (Bro's main process), or +## :bro:id:`REMOTE_SRC_SCRIPT` (the script level). +## +## msg: The message logged. +## +## .. bro:see:: remote_capture_filter remote_connection_closed remote_connection_error +## remote_connection_established remote_connection_handshake_done +## remote_event_registered remote_pong remote_state_access_performed +## remote_state_inconsistency print_hook remote_log_peer event remote_log%(level: count, src: count, msg: string%); -# Generated when a remote peer has answered to our ping. +## Generated for communication log messages. While this event is +## intended primarily for use by Bro's communication framework, it can also trigger +## additional code if helpful. This event is equivalent to +## :bro:see:`remote_log` except the message is with respect to a certain peer. +## +## p: A record describing the remote peer. +## +## level: The log level, which is either :bro:id:`REMOTE_LOG_INFO` or +## :bro:id:`REMOTE_LOG_ERROR`. +## +## src: The component of the comminication system that logged the message. +## Currently, this will be one of :bro:id:`REMOTE_SRC_CHILD` (Bro's +## child process), :bro:id:`REMOTE_SRC_PARENT` (Bro's main process), or +## :bro:id:`REMOTE_SRC_SCRIPT` (the script level). +## +## msg: The message logged. +## +## .. bro:see:: remote_capture_filter remote_connection_closed remote_connection_error +## remote_connection_established remote_connection_handshake_done +## remote_event_registered remote_pong remote_state_access_performed +## remote_state_inconsistency print_hook remote_log +event remote_log_peer%(p: event_peer, level: count, src: count, msg: string%); + +## Generated when a remote peer has answered to our ping. This event is part of +## Bro's infrastructure for measuring communication latency. One can send a ping +## by calling :bro:id:`send_ping` and when a corresponding reply is received, this +## event will be raised. +## +## p: The peer sending us the pong. +## +## seq: The sequence number passed to the original :bro:id:`send_ping` call. +## The number is sent back by the peer in its response. +## +## d1: The time interval between sending the ping and receiving the pong. This +## is the latency of the complete path. +## +## d2: The time interval between sending out the ping to the network and its +## reception at the peer. This is the network latency. +## +## d3: The time interval between when the peer's child process received the +## ping and when its parent process sent the pong. This is the +## processing latency at the the peer. +## +## .. bro:see:: remote_capture_filter remote_connection_closed remote_connection_error +## remote_connection_established remote_connection_handshake_done +## remote_event_registered remote_log remote_state_access_performed +## remote_state_inconsistency print_hook event remote_pong%(p: event_peer, seq: count, d1: interval, d2: interval, d3: interval%); -# Generated each time a remote state access has been replayed locally -# (primarily for debugging). +## Generated each time a remote state access has been replayed locally. This event +## is primarily intended for debugging. measurments. +## +## id: The name of the Bro script variable that's being operated on. +## +## v: The new value of the variable. +## +## .. bro:see:: remote_capture_filter remote_connection_closed remote_connection_error +## remote_connection_established remote_connection_handshake_done +## remote_event_registered remote_log remote_pong remote_state_inconsistency +## print_hook event remote_state_access_performed%(id: string, v: any%); -# Generated each time profiling_file is updated. "expensive" means that -# this event corresponds to heavier-weight profiling as indicated by the -# expensive_profiling_multiple variable. +## Generated each time Bro's internal profiling log is updated. The file is +## defined by :bro:id:`profiling_file`, and its update frequency by +## :bro:id:`profiling_interval` and :bro:id:`expensive_profiling_multiple`. +## +## f: The profiling file. +## +## expensive: True if this event corresponds to heavier-weight profiling as +## indicated by the :bro:id:`expensive_profiling_multiple` variable. +## +## .. bro:see:: profiling_interval expensive_profiling_multiple event profiling_update%(f: file, expensive: bool%); +## Generated each time Bro's script interpreter opens a file. This event is +## triggered only for files opened via :bro:id:`open`, and in particular not for +## normal log files as created by a log writers. +## +## f: The opened file. event file_opened%(f: file%); -# Each print statement generates an event. -event print_hook%(f:file, s: string%); - -# Generated for &rotate_interval. -event rotate_interval%(f: file%); - -# Generated for &rotate_size. -event rotate_size%(f: file%); - +## Generated for a received NetFlow v5 header. Bro's NetFlow processor raises this +## event whenever it either receives a NetFlow header on the port it's listening +## on, or reads one from a trace file. +## +## h: The parsed NetFlow header. +## +## .. bro:see:: netflow_v5_record event netflow_v5_header%(h: nf_v5_header%); + +## Generated for a received NetFlow v5 record. Bro's NetFlow processor raises this +## event whenever it either receives a NetFlow record on the port it's listening +## on, or reads one from a trace file. +## +## h: The parsed NetFlow header. +## +## .. bro:see:: netflow_v5_record event netflow_v5_record%(r: nf_v5_record%); -# Different types of reporter messages. These won't be called -# recursively. +## Raised for informational messages reported via Bro's reporter framework. Such +## messages may be generated internally by the event engine and also by other +## scripts calling :bro:id:`Reporter::info`. +## +## t: The time the message was passed to the reporter. +## +## msg: The message itself. +## +## location: A (potentially empty) string describing a location associated with the +## message. +## +## .. bro:see:: reporter_warning reporter_error Reporter::info Reporter::warning +## Reporter::error +## +## .. note:: Bro will not call reporter events recursively. If the handler of any +## reporter event triggers a new reporter message itself, the output will go to +## ``stderr`` instead. event reporter_info%(t: time, msg: string, location: string%) &error_handler; + +## Raised for warnings reported via Bro's reporter framework. Such messages may +## be generated internally by the event engine and also by other scripts calling +## :bro:id:`Reporter::warning`. +## +## t: The time the warning was passed to the reporter. +## +## msg: The warning message. +## +## location: A (potentially empty) string describing a location associated with the +## warning. +## +## .. bro:see:: reporter_info reporter_error Reporter::info Reporter::warning +## Reporter::error +## +## .. note:: Bro will not call reporter events recursively. If the handler of any +## reporter event triggers a new reporter message itself, the output will go to +## ``stderr`` instead. event reporter_warning%(t: time, msg: string, location: string%) &error_handler; + +## Raised for errors reported via Bro's reporter framework. Such messages may +## be generated internally by the event engine and also by other scripts calling +## :bro:id:`Reporter::error`. +## +## t: The time the error was passed to the reporter. +## +## msg: The error message. +## +## location: A (potentially empty) string describing a location associated with the +## error. +## +## .. bro:see:: reporter_info reporter_warning Reporter::info Reporter::warning +## Reporter::error +## +## .. note:: Bro will not call reporter events recursively. If the handler of any +## reporter event triggers a new reporter message itself, the output will go to +## ``stderr`` instead. event reporter_error%(t: time, msg: string, location: string%) &error_handler; -# Raised for each policy script loaded. +## Raised for each policy script loaded by the script interpreter. +## +## path: The full path to the script loaded. +## +## level: The "nesting level": zero for a top-level Bro script and incremented +## recursively for each ``@load``. event bro_script_loaded%(path: string, level: count%); + +## Deprecated. Will be removed. +event stp_create_endp%(c: connection, e: int, is_orig: bool%); + +# ##### Internal events. Not further documented. + +## Event internal to the stepping stone detector. +event stp_resume_endp%(e: int%); + +## Event internal to the stepping stone detector. +event stp_correlate_pair%(e1: int, e2: int%); + +## Event internal to the stepping stone detector. +event stp_remove_pair%(e1: int, e2: int%); + +## Event internal to the stepping stone detector. +event stp_remove_endp%(e: int%); + +# ##### Deprecated events. Proposed for removal. + +## Deprecated. Will be removed. +event interconn_stats%(c: connection, os: interconn_endp_stats, rs: interconn_endp_stats%); + +## Deprecated. Will be removed. +event interconn_remove_conn%(c: connection%); + +## Deprecated. Will be removed. +event backdoor_stats%(c: connection, os: backdoor_endp_stats, rs: backdoor_endp_stats%); + +## Deprecated. Will be removed. +event backdoor_remove_conn%(c: connection%); + +## Deprecated. Will be removed. +event ssh_signature_found%(c: connection, is_orig: bool%); + +## Deprecated. Will be removed. +event telnet_signature_found%(c: connection, is_orig: bool, len: count%); + +## Deprecated. Will be removed. +event rlogin_signature_found%(c: connection, is_orig: bool, num_null: count, len: count%); + +## Deprecated. Will be removed. +event root_backdoor_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event ftp_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event napster_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event gnutella_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event kazaa_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event http_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event http_proxy_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event smtp_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event irc_signature_found%(c: connection%); + +## Deprecated. Will be removed. +event gaobot_signature_found%(c: connection%); + +## Deprecated. Will be removed. +## +## .. todo:: Unclear what this event is for; it's never raised. We should just +## remove it. +event dns_full_request%(%) &group="dns"; + +## Deprecated. Will be removed. +event anonymization_mapping%(orig: addr, mapped: addr%); + +## Deprecated. Will be removed. +event rotate_interval%(f: file%); + +## Deprecated. Will be removed. +event rotate_size%(f: file%); + +## Deprecated. Will be removed. +event print_hook%(f:file, s: string%); diff --git a/src/http-analyzer.pac b/src/http-analyzer.pac index c1a4dd7b26..e12be59438 100644 --- a/src/http-analyzer.pac +++ b/src/http-analyzer.pac @@ -1,5 +1,3 @@ -# $Id:$ - %extern{ #include diff --git a/src/http-protocol.pac b/src/http-protocol.pac index 1c9f4b4c17..e4487a75e3 100644 --- a/src/http-protocol.pac +++ b/src/http-protocol.pac @@ -1,5 +1,3 @@ -# $Id:$ - enum ExpectBody { BODY_EXPECTED, BODY_NOT_EXPECTED, diff --git a/src/http.pac b/src/http.pac index 217215e998..38e6ad0b5e 100644 --- a/src/http.pac +++ b/src/http.pac @@ -1,5 +1,3 @@ -# $Id:$ - %include binpac.pac %include bro.pac diff --git a/src/input.h b/src/input.h index 8af7a35445..8fcceb256b 100644 --- a/src/input.h +++ b/src/input.h @@ -1,5 +1,3 @@ -// $Id: input.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef input_h diff --git a/src/logging.bif b/src/logging.bif index 0e48633d5a..c8960b4e38 100644 --- a/src/logging.bif +++ b/src/logging.bif @@ -1,18 +1,16 @@ -# Internal functions and types used by the logging framework. +##! Internal functions and types used by the logging framework. module Log; %%{ -#include "LogMgr.h" #include "NetVar.h" + +#include "logging/Manager.h" %%} type Filter: record; type Stream: record; type RotationInfo: record; -type RotationControl: record; - -const Log::rotation_control: RotationControl; function Log::__create_stream%(id: Log::ID, stream: Log::Stream%) : bool %{ diff --git a/src/LogMgr.cc b/src/logging/Manager.cc similarity index 63% rename from src/LogMgr.cc rename to src/logging/Manager.cc index 950de24a8f..9437f0099f 100644 --- a/src/LogMgr.cc +++ b/src/logging/Manager.cc @@ -2,31 +2,42 @@ #include -#include "LogMgr.h" -#include "Event.h" -#include "EventHandler.h" -#include "NetVar.h" -#include "Net.h" +#include "../Event.h" +#include "../EventHandler.h" +#include "../NetVar.h" +#include "../Net.h" -#include "LogWriterAscii.h" +#include "threading/SerialTypes.h" + +#include "Manager.h" +#include "WriterFrontend.h" +#include "WriterBackend.h" + +#include "writers/Ascii.h" +#include "writers/None.h" + +using namespace logging; +using threading::Value; +using threading::Field; // Structure describing a log writer type. -struct LogWriterDefinition { +struct WriterDefinition { bro_int_t type; // The type. const char *name; // Descriptive name for error messages. bool (*init)(); // An optional one-time initialization function. - LogWriter* (*factory)(); // A factory function creating instances. + WriterBackend* (*factory)(WriterFrontend* frontend); // A factory function creating instances. }; // Static table defining all availabel log writers. -LogWriterDefinition log_writers[] = { - { BifEnum::Log::WRITER_ASCII, "Ascii", 0, LogWriterAscii::Instantiate }, +WriterDefinition log_writers[] = { + { BifEnum::Log::WRITER_NONE, "None", 0, writer::None::Instantiate }, + { BifEnum::Log::WRITER_ASCII, "Ascii", 0, writer::Ascii::Instantiate }, // End marker, don't touch. - { BifEnum::Log::WRITER_DEFAULT, "None", 0, (LogWriter* (*)())0 } + { BifEnum::Log::WRITER_DEFAULT, "None", 0, (WriterBackend* (*)(WriterFrontend* frontend))0 } }; -struct LogMgr::Filter { +struct Manager::Filter { string name; EnumVal* id; Func* pred; @@ -36,9 +47,11 @@ struct LogMgr::Filter { EnumVal* writer; bool local; bool remote; + double interval; + Func* postprocessor; int num_fields; - LogField** fields; + Field** fields; // Vector indexed by field number. Each element is a list of record // indices defining a path leading to the value across potential @@ -48,14 +61,16 @@ struct LogMgr::Filter { ~Filter(); }; -struct LogMgr::WriterInfo { +struct Manager::WriterInfo { EnumVal* type; double open_time; Timer* rotation_timer; - LogWriter *writer; + double interval; + Func* postprocessor; + WriterFrontend* writer; }; -struct LogMgr::Stream { +struct Manager::Stream { EnumVal* id; bool enabled; string name; @@ -72,315 +87,7 @@ struct LogMgr::Stream { ~Stream(); }; -bool LogField::Read(SerializationFormat* fmt) - { - int t; - - bool success = (fmt->Read(&name, "name") && fmt->Read(&t, "type")); - type = (TypeTag) t; - - return success; - } - -bool LogField::Write(SerializationFormat* fmt) const - { - return (fmt->Write(name, "name") && fmt->Write((int)type, "type")); - } - -LogVal::~LogVal() - { - if ( (type == TYPE_ENUM || type == TYPE_STRING || type == TYPE_FILE || type == TYPE_FUNC) - && present ) - delete val.string_val; - - if ( type == TYPE_TABLE && present ) - { - for ( int i = 0; i < val.set_val.size; i++ ) - delete val.set_val.vals[i]; - - delete [] val.set_val.vals; - } - - if ( type == TYPE_VECTOR && present ) - { - for ( int i = 0; i < val.vector_val.size; i++ ) - delete val.vector_val.vals[i]; - - delete [] val.vector_val.vals; - } - } - -bool LogVal::IsCompatibleType(BroType* t, bool atomic_only) - { - if ( ! t ) - return false; - - switch ( t->Tag() ) { - case TYPE_BOOL: - case TYPE_INT: - case TYPE_COUNT: - case TYPE_COUNTER: - case TYPE_PORT: - case TYPE_SUBNET: - case TYPE_ADDR: - case TYPE_DOUBLE: - case TYPE_TIME: - case TYPE_INTERVAL: - case TYPE_ENUM: - case TYPE_STRING: - case TYPE_FILE: - case TYPE_FUNC: - return true; - - case TYPE_RECORD: - return ! atomic_only; - - case TYPE_TABLE: - { - if ( atomic_only ) - return false; - - if ( ! t->IsSet() ) - return false; - - return IsCompatibleType(t->AsSetType()->Indices()->PureType()); - } - - case TYPE_VECTOR: - { - if ( atomic_only ) - return false; - - return IsCompatibleType(t->AsVectorType()->YieldType()); - } - - default: - return false; - } - - return false; - } - -bool LogVal::Read(SerializationFormat* fmt) - { - int ty; - - if ( ! (fmt->Read(&ty, "type") && fmt->Read(&present, "present")) ) - return false; - - type = (TypeTag)(ty); - - if ( ! present ) - return true; - - switch ( type ) { - case TYPE_BOOL: - case TYPE_INT: - return fmt->Read(&val.int_val, "int"); - - case TYPE_COUNT: - case TYPE_COUNTER: - case TYPE_PORT: - return fmt->Read(&val.uint_val, "uint"); - - case TYPE_SUBNET: - { - uint32 net[4]; - if ( ! (fmt->Read(&net[0], "net0") && - fmt->Read(&net[1], "net1") && - fmt->Read(&net[2], "net2") && - fmt->Read(&net[3], "net3") && - fmt->Read(&val.subnet_val.width, "width")) ) - return false; - -#ifdef BROv6 - val.subnet_val.net[0] = net[0]; - val.subnet_val.net[1] = net[1]; - val.subnet_val.net[2] = net[2]; - val.subnet_val.net[3] = net[3]; -#else - val.subnet_val.net = net[0]; -#endif - return true; - } - - case TYPE_ADDR: - { - uint32 addr[4]; - if ( ! (fmt->Read(&addr[0], "addr0") && - fmt->Read(&addr[1], "addr1") && - fmt->Read(&addr[2], "addr2") && - fmt->Read(&addr[3], "addr3")) ) - return false; - - val.addr_val[0] = addr[0]; -#ifdef BROv6 - val.addr_val[1] = addr[1]; - val.addr_val[2] = addr[2]; - val.addr_val[3] = addr[3]; -#endif - return true; - } - - case TYPE_DOUBLE: - case TYPE_TIME: - case TYPE_INTERVAL: - return fmt->Read(&val.double_val, "double"); - - case TYPE_ENUM: - case TYPE_STRING: - case TYPE_FILE: - case TYPE_FUNC: - { - val.string_val = new string; - return fmt->Read(val.string_val, "string"); - } - - case TYPE_TABLE: - { - if ( ! fmt->Read(&val.set_val.size, "set_size") ) - return false; - - val.set_val.vals = new LogVal* [val.set_val.size]; - - for ( int i = 0; i < val.set_val.size; ++i ) - { - val.set_val.vals[i] = new LogVal; - - if ( ! val.set_val.vals[i]->Read(fmt) ) - return false; - } - - return true; - } - - case TYPE_VECTOR: - { - if ( ! fmt->Read(&val.vector_val.size, "vector_size") ) - return false; - - val.vector_val.vals = new LogVal* [val.vector_val.size]; - - for ( int i = 0; i < val.vector_val.size; ++i ) - { - val.vector_val.vals[i] = new LogVal; - - if ( ! val.vector_val.vals[i]->Read(fmt) ) - return false; - } - - return true; - } - - default: - reporter->InternalError("unsupported type %s in LogVal::Write", type_name(type)); - } - - return false; - } - -bool LogVal::Write(SerializationFormat* fmt) const - { - if ( ! (fmt->Write((int)type, "type") && - fmt->Write(present, "present")) ) - return false; - - if ( ! present ) - return true; - - switch ( type ) { - case TYPE_BOOL: - case TYPE_INT: - return fmt->Write(val.int_val, "int"); - - case TYPE_COUNT: - case TYPE_COUNTER: - case TYPE_PORT: - return fmt->Write(val.uint_val, "uint"); - - case TYPE_SUBNET: - { - uint32 net[4]; -#ifdef BROv6 - net[0] = val.subnet_val.net[0]; - net[1] = val.subnet_val.net[1]; - net[2] = val.subnet_val.net[2]; - net[3] = val.subnet_val.net[3]; -#else - net[0] = val.subnet_val.net; - net[1] = net[2] = net[3] = 0; -#endif - return fmt->Write(net[0], "net0") && - fmt->Write(net[1], "net1") && - fmt->Write(net[2], "net2") && - fmt->Write(net[3], "net3") && - fmt->Write(val.subnet_val.width, "width"); - } - - case TYPE_ADDR: - { - uint32 addr[4]; - addr[0] = val.addr_val[0]; -#ifdef BROv6 - addr[1] = val.addr_val[1]; - addr[2] = val.addr_val[2]; - addr[3] = val.addr_val[3]; -#else - addr[1] = addr[2] = addr[3] = 0; -#endif - return fmt->Write(addr[0], "addr0") && - fmt->Write(addr[1], "addr1") && - fmt->Write(addr[2], "addr2") && - fmt->Write(addr[3], "addr3"); - } - - case TYPE_DOUBLE: - case TYPE_TIME: - case TYPE_INTERVAL: - return fmt->Write(val.double_val, "double"); - - case TYPE_ENUM: - case TYPE_STRING: - case TYPE_FILE: - case TYPE_FUNC: - return fmt->Write(*val.string_val, "string"); - - case TYPE_TABLE: - { - if ( ! fmt->Write(val.set_val.size, "set_size") ) - return false; - - for ( int i = 0; i < val.set_val.size; ++i ) - { - if ( ! val.set_val.vals[i]->Write(fmt) ) - return false; - } - - return true; - } - - case TYPE_VECTOR: - { - if ( ! fmt->Write(val.vector_val.size, "vector_size") ) - return false; - - for ( int i = 0; i < val.vector_val.size; ++i ) - { - if ( ! val.vector_val.vals[i]->Write(fmt) ) - return false; - } - - return true; - } - - default: - reporter->InternalError("unsupported type %s in LogVal::REad", type_name(type)); - } - - return false; - } - -LogMgr::Filter::~Filter() +Manager::Filter::~Filter() { for ( int i = 0; i < num_fields; ++i ) delete fields[i]; @@ -390,7 +97,7 @@ LogMgr::Filter::~Filter() Unref(path_val); } -LogMgr::Stream::~Stream() +Manager::Stream::~Stream() { Unref(columns); @@ -398,9 +105,6 @@ LogMgr::Stream::~Stream() { WriterInfo* winfo = i->second; - if ( ! winfo ) - continue; - if ( winfo->rotation_timer ) timer_mgr->Cancel(winfo->rotation_timer); @@ -413,17 +117,73 @@ LogMgr::Stream::~Stream() delete *f; } -LogMgr::LogMgr() +Manager::Manager() { } -LogMgr::~LogMgr() +Manager::~Manager() { for ( vector::iterator s = streams.begin(); s != streams.end(); ++s ) delete *s; } -LogMgr::Stream* LogMgr::FindStream(EnumVal* id) +WriterBackend* Manager::CreateBackend(WriterFrontend* frontend, bro_int_t type) + { + WriterDefinition* ld = log_writers; + + while ( true ) + { + if ( ld->type == BifEnum::Log::WRITER_DEFAULT ) + { + reporter->Error("unknow writer when creating writer"); + return 0; + } + + if ( ld->type != type ) + { + // Not the right one. + ++ld; + continue; + } + + // If the writer has an init function, call it. + if ( ld->init ) + { + if ( (*ld->init)() ) + // Clear the init function so that we won't + // call it again later. + ld->init = 0; + else + { + // Init failed, disable by deleting factory + // function. + ld->factory = 0; + + DBG_LOG(DBG_LOGGING, "failed to init writer class %s", + ld->name); + + return false; + } + } + + if ( ! ld->factory ) + // Oops, we can't instantiate this guy. + return 0; + + // All done. + break; + } + + assert(ld->factory); + + WriterBackend* backend = (*ld->factory)(frontend); + assert(backend); + + frontend->ty_name = ld->name; + return backend; + } + +Manager::Stream* Manager::FindStream(EnumVal* id) { unsigned int idx = id->AsEnum(); @@ -433,7 +193,7 @@ LogMgr::Stream* LogMgr::FindStream(EnumVal* id) return streams[idx]; } -LogMgr::WriterInfo* LogMgr::FindWriter(LogWriter* writer) +Manager::WriterInfo* Manager::FindWriter(WriterFrontend* writer) { for ( vector::iterator s = streams.begin(); s != streams.end(); ++s ) { @@ -452,14 +212,15 @@ LogMgr::WriterInfo* LogMgr::FindWriter(LogWriter* writer) return 0; } -void LogMgr::RemoveDisabledWriters(Stream* stream) +void Manager::RemoveDisabledWriters(Stream* stream) { list disabled; for ( Stream::WriterMap::iterator j = stream->writers.begin(); j != stream->writers.end(); j++ ) { - if ( j->second && j->second->writer->Disabled() ) + if ( j->second->writer->Disabled() ) { + j->second->writer->Stop(); delete j->second; disabled.push_back(j->first); } @@ -469,7 +230,7 @@ void LogMgr::RemoveDisabledWriters(Stream* stream) stream->writers.erase(*j); } -bool LogMgr::CreateStream(EnumVal* id, RecordVal* sval) +bool Manager::CreateStream(EnumVal* id, RecordVal* sval) { RecordType* rtype = sval->Type()->AsRecordType(); @@ -489,7 +250,7 @@ bool LogMgr::CreateStream(EnumVal* id, RecordVal* sval) if ( ! (columns->FieldDecl(i)->FindAttr(ATTR_LOG)) ) continue; - if ( ! LogVal::IsCompatibleType(columns->FieldType(i)) ) + if ( ! threading::Value::IsCompatibleType(columns->FieldType(i)) ) { reporter->Error("type of field '%s' is not support for logging output", columns->FieldName(i)); @@ -561,7 +322,7 @@ bool LogMgr::CreateStream(EnumVal* id, RecordVal* sval) return true; } -bool LogMgr::EnableStream(EnumVal* id) +bool Manager::EnableStream(EnumVal* id) { Stream* stream = FindStream(id); @@ -577,7 +338,7 @@ bool LogMgr::EnableStream(EnumVal* id) return true; } -bool LogMgr::DisableStream(EnumVal* id) +bool Manager::DisableStream(EnumVal* id) { Stream* stream = FindStream(id); @@ -594,7 +355,7 @@ bool LogMgr::DisableStream(EnumVal* id) } // Helper for recursive record field unrolling. -bool LogMgr::TraverseRecord(Stream* stream, Filter* filter, RecordType* rt, +bool Manager::TraverseRecord(Stream* stream, Filter* filter, RecordType* rt, TableVal* include, TableVal* exclude, string path, list indices) { for ( int i = 0; i < rt->NumFields(); ++i ) @@ -688,9 +449,9 @@ bool LogMgr::TraverseRecord(Stream* stream, Filter* filter, RecordType* rt, filter->indices.push_back(new_indices); - filter->fields = (LogField**) + filter->fields = (Field**) realloc(filter->fields, - sizeof(LogField) * ++filter->num_fields); + sizeof(Field) * ++filter->num_fields); if ( ! filter->fields ) { @@ -698,16 +459,23 @@ bool LogMgr::TraverseRecord(Stream* stream, Filter* filter, RecordType* rt, return false; } - LogField* field = new LogField(); + Field* field = new Field(); field->name = new_path; field->type = t->Tag(); + + if ( field->type == TYPE_TABLE ) + field->subtype = t->AsSetType()->Indices()->PureType()->Tag(); + + else if ( field->type == TYPE_VECTOR ) + field->subtype = t->AsVectorType()->YieldType()->Tag(); + filter->fields[filter->num_fields - 1] = field; } return true; } -bool LogMgr::AddFilter(EnumVal* id, RecordVal* fval) +bool Manager::AddFilter(EnumVal* id, RecordVal* fval) { RecordType* rtype = fval->Type()->AsRecordType(); @@ -732,6 +500,8 @@ bool LogMgr::AddFilter(EnumVal* id, RecordVal* fval) Val* path_func = fval->LookupWithDefault(rtype->FieldOffset("path_func")); Val* log_local = fval->LookupWithDefault(rtype->FieldOffset("log_local")); Val* log_remote = fval->LookupWithDefault(rtype->FieldOffset("log_remote")); + Val* interv = fval->LookupWithDefault(rtype->FieldOffset("interv")); + Val* postprocessor = fval->LookupWithDefault(rtype->FieldOffset("postprocessor")); Filter* filter = new Filter; filter->name = name->AsString()->CheckString(); @@ -741,12 +511,16 @@ bool LogMgr::AddFilter(EnumVal* id, RecordVal* fval) filter->writer = writer->Ref()->AsEnumVal(); filter->local = log_local->AsBool(); filter->remote = log_remote->AsBool(); + filter->interval = interv->AsInterval(); + filter->postprocessor = postprocessor ? postprocessor->AsFunc() : 0; Unref(name); Unref(pred); Unref(path_func); Unref(log_local); Unref(log_remote); + Unref(interv); + Unref(postprocessor); // Build the list of fields that the filter wants included, including // potentially rolling out fields. @@ -772,20 +546,9 @@ bool LogMgr::AddFilter(EnumVal* id, RecordVal* fval) else { - // If no path is given, use the Stream ID as the default but - // strip the namespace. - const char* s = stream->name.c_str(); - const char* e = s + strlen(s); - - const char* t = strstr(s, "::"); - if ( t ) - s = t + 2; - - string path(s, e); - std::transform(path.begin(), path.end(), path.begin(), ::tolower); - - filter->path = path; - filter->path_val = new StringVal(path.c_str()); + // If no path is given, it's derived based upon the value returned by + // the first call to the filter's path_func (during first write). + filter->path_val = 0; } // Remove any filter with the same name we might already have. @@ -808,7 +571,7 @@ bool LogMgr::AddFilter(EnumVal* id, RecordVal* fval) for ( int i = 0; i < filter->num_fields; i++ ) { - LogField* field = filter->fields[i]; + Field* field = filter->fields[i]; DBG_LOG(DBG_LOGGING, " field %10s: %s", field->name.c_str(), type_name(field->type)); } @@ -817,12 +580,12 @@ bool LogMgr::AddFilter(EnumVal* id, RecordVal* fval) return true; } -bool LogMgr::RemoveFilter(EnumVal* id, StringVal* name) +bool Manager::RemoveFilter(EnumVal* id, StringVal* name) { return RemoveFilter(id, name->AsString()->CheckString()); } -bool LogMgr::RemoveFilter(EnumVal* id, string name) +bool Manager::RemoveFilter(EnumVal* id, string name) { Stream* stream = FindStream(id); if ( ! stream ) @@ -849,7 +612,7 @@ bool LogMgr::RemoveFilter(EnumVal* id, string name) return true; } -bool LogMgr::Write(EnumVal* id, RecordVal* columns) +bool Manager::Write(EnumVal* id, RecordVal* columns) { bool error = false; @@ -889,9 +652,18 @@ bool LogMgr::Write(EnumVal* id, RecordVal* columns) // to log this record. val_list vl(1); vl.append(columns->Ref()); - Val* v = filter->pred->Call(&vl); - int result = v->AsBool(); - Unref(v); + + int result = 1; + + try + { + Val* v = filter->pred->Call(&vl); + result = v->AsBool(); + Unref(v); + } + + catch ( InterpreterException& e ) + { /* Already reported. */ } if ( ! result ) continue; @@ -901,9 +673,37 @@ bool LogMgr::Write(EnumVal* id, RecordVal* columns) { val_list vl(3); vl.append(id->Ref()); - vl.append(filter->path_val->Ref()); - vl.append(columns->Ref()); - Val* v = filter->path_func->Call(&vl); + + Val* path_arg; + if ( filter->path_val ) + path_arg = filter->path_val->Ref(); + else + path_arg = new StringVal(""); + + vl.append(path_arg); + + Val* rec_arg; + BroType* rt = filter->path_func->FType()->Args()->FieldType("rec"); + + if ( rt->Tag() == TYPE_RECORD ) + rec_arg = columns->CoerceTo(rt->AsRecordType(), true); + else + // Can be TYPE_ANY here. + rec_arg = columns->Ref(); + + vl.append(rec_arg); + + Val* v = 0; + + try + { + v = filter->path_func->Call(&vl); + } + + catch ( InterpreterException& e ) + { + return false; + } if ( ! v->Type()->Tag() == TYPE_STRING ) { @@ -912,6 +712,12 @@ bool LogMgr::Write(EnumVal* id, RecordVal* columns) return false; } + if ( ! filter->path_val ) + { + filter->path = v->AsString()->CheckString(); + filter->path_val = v->Ref(); + } + path = v->AsString()->CheckString(); Unref(v); @@ -925,76 +731,42 @@ bool LogMgr::Write(EnumVal* id, RecordVal* columns) Stream::WriterMap::iterator w = stream->writers.find(Stream::WriterPathPair(filter->writer->AsEnum(), path)); - LogWriter* writer = 0; + WriterFrontend* writer = 0; if ( w != stream->writers.end() ) // We know this writer already. - writer = w->second ? w->second->writer : 0; + writer = w->second->writer; else { // No, need to create one. - // Copy the fields for LogWriter::Init() as it will take - // ownership. - LogField** arg_fields = new LogField*[filter->num_fields]; + // Copy the fields for WriterFrontend::Init() as it + // will take ownership. + Field** arg_fields = new Field*[filter->num_fields]; for ( int j = 0; j < filter->num_fields; ++j ) - arg_fields[j] = new LogField(*filter->fields[j]); + arg_fields[j] = new Field(*filter->fields[j]); - if ( filter->local ) + writer = CreateWriter(stream->id, filter->writer, + path, filter->num_fields, + arg_fields, filter->local, filter->remote); + + if ( ! writer ) { - writer = CreateWriter(stream->id, filter->writer, - path, filter->num_fields, - arg_fields); - - if ( ! writer ) - { - Unref(columns); - return false; - } + Unref(columns); + return false; } - else - // Insert a null pointer into the map to make - // sure we don't try creating it again. - stream->writers.insert(Stream::WriterMap::value_type( - Stream::WriterPathPair(filter->writer->AsEnum(), path), 0)); - if ( filter->remote ) - remote_serializer->SendLogCreateWriter(stream->id, - filter->writer, - path, - filter->num_fields, - arg_fields); } // Alright, can do the write now. - if ( filter->local || filter->remote ) - { - LogVal** vals = RecordToFilterVals(stream, filter, columns); - - if ( filter->remote ) - remote_serializer->SendLogWrite(stream->id, - filter->writer, - path, - filter->num_fields, - vals); - - if ( filter->local ) - { - assert(writer); - - // Write takes ownership of vals. - if ( ! writer->Write(filter->num_fields, vals) ) - error = true; - } - - else - DeleteVals(filter->num_fields, vals); - - } + threading::Value** vals = RecordToFilterVals(stream, filter, columns); + // Write takes ownership of vals. + assert(writer); + writer->Write(filter->num_fields, vals); #ifdef DEBUG DBG_LOG(DBG_LOGGING, "Wrote record to filter '%s' on stream '%s'", @@ -1010,15 +782,15 @@ bool LogMgr::Write(EnumVal* id, RecordVal* columns) return true; } -LogVal* LogMgr::ValToLogVal(Val* val, BroType* ty) +threading::Value* Manager::ValToLogVal(Val* val, BroType* ty) { if ( ! ty ) ty = val->Type(); if ( ! val ) - return new LogVal(ty->Tag(), false); + return new threading::Value(ty->Tag(), false); - LogVal* lval = new LogVal(ty->Tag()); + threading::Value* lval = new threading::Value(ty->Tag()); switch ( lval->type ) { case TYPE_BOOL: @@ -1041,23 +813,17 @@ LogVal* LogMgr::ValToLogVal(Val* val, BroType* ty) break; case TYPE_PORT: - lval->val.uint_val = val->AsPortVal()->Port(); + lval->val.port_val.port = val->AsPortVal()->Port(); + lval->val.port_val.proto = val->AsPortVal()->PortType(); break; case TYPE_SUBNET: - lval->val.subnet_val = *val->AsSubNet(); + val->AsSubNet().ConvertToThreadingValue(&lval->val.subnet_val); break; case TYPE_ADDR: - { - addr_type t = val->AsAddr(); -#ifdef BROv6 - copy_addr(t, lval->val.addr_val); -#else - copy_addr(&t, lval->val.addr_val); -#endif + val->AsAddr().ConvertToThreadingValue(&lval->val.addr_val); break; - } case TYPE_DOUBLE: case TYPE_TIME: @@ -1098,7 +864,7 @@ LogVal* LogMgr::ValToLogVal(Val* val, BroType* ty) set = new ListVal(TYPE_INT); lval->val.set_val.size = set->Length(); - lval->val.set_val.vals = new LogVal* [lval->val.set_val.size]; + lval->val.set_val.vals = new threading::Value* [lval->val.set_val.size]; for ( int i = 0; i < lval->val.set_val.size; i++ ) lval->val.set_val.vals[i] = ValToLogVal(set->Index(i)); @@ -1112,7 +878,7 @@ LogVal* LogMgr::ValToLogVal(Val* val, BroType* ty) VectorVal* vec = val->AsVectorVal(); lval->val.vector_val.size = vec->Size(); lval->val.vector_val.vals = - new LogVal* [lval->val.vector_val.size]; + new threading::Value* [lval->val.vector_val.size]; for ( int i = 0; i < lval->val.vector_val.size; i++ ) { @@ -1131,10 +897,10 @@ LogVal* LogMgr::ValToLogVal(Val* val, BroType* ty) return lval; } -LogVal** LogMgr::RecordToFilterVals(Stream* stream, Filter* filter, +Value** Manager::RecordToFilterVals(Stream* stream, Filter* filter, RecordVal* columns) { - LogVal** vals = new LogVal*[filter->num_fields]; + Value** vals = new Value*[filter->num_fields]; for ( int i = 0; i < filter->num_fields; ++i ) { @@ -1153,7 +919,7 @@ LogVal** LogMgr::RecordToFilterVals(Stream* stream, Filter* filter, if ( ! val ) { // Value, or any of its parents, is not set. - vals[i] = new LogVal(filter->fields[i]->type, false); + vals[i] = new Value(filter->fields[i]->type, false); break; } } @@ -1165,8 +931,8 @@ LogVal** LogMgr::RecordToFilterVals(Stream* stream, Filter* filter, return vals; } -LogWriter* LogMgr::CreateWriter(EnumVal* id, EnumVal* writer, string path, - int num_fields, LogField** fields) +WriterFrontend* Manager::CreateWriter(EnumVal* id, EnumVal* writer, string path, + int num_fields, const Field* const* fields, bool local, bool remote) { Stream* stream = FindStream(id); @@ -1177,67 +943,50 @@ LogWriter* LogMgr::CreateWriter(EnumVal* id, EnumVal* writer, string path, Stream::WriterMap::iterator w = stream->writers.find(Stream::WriterPathPair(writer->AsEnum(), path)); - if ( w != stream->writers.end() && w->second ) + if ( w != stream->writers.end() ) // If we already have a writer for this. That's fine, we just // return it. return w->second->writer; - // Need to instantiate a new writer. + WriterFrontend* writer_obj = new WriterFrontend(id, writer, local, remote); + assert(writer_obj); - LogWriterDefinition* ld = log_writers; - - while ( true ) - { - if ( ld->type == BifEnum::Log::WRITER_DEFAULT ) - { - reporter->Error("unknow writer when creating writer"); - return 0; - } - - if ( ld->type == writer->AsEnum() ) - break; - - if ( ! ld->factory ) - // Oops, we can't instantiate this guy. - return 0; - - // If the writer has an init function, call it. - if ( ld->init ) - { - if ( (*ld->init)() ) - // Clear the init function so that we won't - // call it again later. - ld->init = 0; - else - // Init failed, disable by deleting factory - // function. - ld->factory = 0; - - DBG_LOG(DBG_LOGGING, "failed to init writer class %s", - ld->name); - - return false; - } - - ++ld; - } - - assert(ld->factory); - LogWriter* writer_obj = (*ld->factory)(); - - if ( ! writer_obj->Init(path, num_fields, fields) ) - { - DBG_LOG(DBG_LOGGING, "failed to init instance of writer %s", - ld->name); - - return 0; - } + writer_obj->Init(path, num_fields, fields); WriterInfo* winfo = new WriterInfo; winfo->type = writer->Ref()->AsEnumVal(); winfo->writer = writer_obj; winfo->open_time = network_time; winfo->rotation_timer = 0; + winfo->interval = 0; + winfo->postprocessor = 0; + + // Search for a corresponding filter for the writer/path pair and use its + // rotation settings. If no matching filter is found, fall back on + // looking up the logging framework's default rotation interval. + bool found_filter_match = false; + list::const_iterator it; + + for ( it = stream->filters.begin(); it != stream->filters.end(); ++it ) + { + Filter* f = *it; + if ( f->writer->AsEnum() == writer->AsEnum() && + f->path == winfo->writer->Path() ) + { + found_filter_match = true; + winfo->interval = f->interval; + winfo->postprocessor = f->postprocessor; + break; + } + } + + if ( ! found_filter_match ) + { + ID* id = global_scope()->Lookup("Log::default_rotation_interval"); + assert(id); + winfo->interval = id->ID_Val()->AsInterval(); + } + InstallRotationTimer(winfo); stream->writers.insert( @@ -1247,16 +996,17 @@ LogWriter* LogMgr::CreateWriter(EnumVal* id, EnumVal* writer, string path, return writer_obj; } -void LogMgr::DeleteVals(int num_fields, LogVal** vals) +void Manager::DeleteVals(int num_fields, Value** vals) { + // Note this code is duplicated in WriterBackend::DeleteVals(). for ( int i = 0; i < num_fields; i++ ) delete vals[i]; delete [] vals; } -bool LogMgr::Write(EnumVal* id, EnumVal* writer, string path, int num_fields, - LogVal** vals) +bool Manager::Write(EnumVal* id, EnumVal* writer, string path, int num_fields, + Value** vals) { Stream* stream = FindStream(id); @@ -1266,7 +1016,7 @@ bool LogMgr::Write(EnumVal* id, EnumVal* writer, string path, int num_fields, #ifdef DEBUG ODesc desc; id->Describe(&desc); - DBG_LOG(DBG_LOGGING, "unknown stream %s in LogMgr::Write()", + DBG_LOG(DBG_LOGGING, "unknown stream %s in Manager::Write()", desc.Description()); #endif DeleteVals(num_fields, vals); @@ -1288,23 +1038,23 @@ bool LogMgr::Write(EnumVal* id, EnumVal* writer, string path, int num_fields, #ifdef DEBUG ODesc desc; id->Describe(&desc); - DBG_LOG(DBG_LOGGING, "unknown writer %s in LogMgr::Write()", + DBG_LOG(DBG_LOGGING, "unknown writer %s in Manager::Write()", desc.Description()); #endif DeleteVals(num_fields, vals); return false; } - bool success = (w->second ? w->second->writer->Write(num_fields, vals) : true); + w->second->writer->Write(num_fields, vals); DBG_LOG(DBG_LOGGING, - "Wrote pre-filtered record to path '%s' on stream '%s' [%s]", - path.c_str(), stream->name.c_str(), (success ? "ok" : "error")); + "Wrote pre-filtered record to path '%s' on stream '%s'", + path.c_str(), stream->name.c_str()); - return success; + return true; } -void LogMgr::SendAllWritersTo(RemoteSerializer::PeerID peer) +void Manager::SendAllWritersTo(RemoteSerializer::PeerID peer) { for ( vector::iterator s = streams.begin(); s != streams.end(); ++s ) { @@ -1316,10 +1066,7 @@ void LogMgr::SendAllWritersTo(RemoteSerializer::PeerID peer) for ( Stream::WriterMap::iterator i = stream->writers.begin(); i != stream->writers.end(); i++ ) { - if ( ! i->second ) - continue; - - LogWriter* writer = i->second->writer; + WriterFrontend* writer = i->second->writer; EnumVal writer_val(i->first.first, BifType::Enum::Log::Writer); remote_serializer->SendLogCreateWriter(peer, (*s)->id, @@ -1331,7 +1078,7 @@ void LogMgr::SendAllWritersTo(RemoteSerializer::PeerID peer) } } -bool LogMgr::SetBuf(EnumVal* id, bool enabled) +bool Manager::SetBuf(EnumVal* id, bool enabled) { Stream* stream = FindStream(id); if ( ! stream ) @@ -1339,17 +1086,14 @@ bool LogMgr::SetBuf(EnumVal* id, bool enabled) for ( Stream::WriterMap::iterator i = stream->writers.begin(); i != stream->writers.end(); i++ ) - { - if ( i->second ) - i->second->writer->SetBuf(enabled); - } + i->second->writer->SetBuf(enabled); RemoveDisabledWriters(stream); return true; } -bool LogMgr::Flush(EnumVal* id) +bool Manager::Flush(EnumVal* id) { Stream* stream = FindStream(id); if ( ! stream ) @@ -1360,26 +1104,26 @@ bool LogMgr::Flush(EnumVal* id) for ( Stream::WriterMap::iterator i = stream->writers.begin(); i != stream->writers.end(); i++ ) - { - if ( i->second ) - i->second->writer->Flush(); - } + i->second->writer->Flush(); RemoveDisabledWriters(stream); return true; } -void LogMgr::Error(LogWriter* writer, const char* msg) +void Manager::Terminate() { - reporter->Error(fmt("error with writer for %s: %s", - writer->Path().c_str(), msg)); + for ( vector::iterator s = streams.begin(); s != streams.end(); ++s ) + { + if ( *s ) + Flush((*s)->id); + } } // Timer which on dispatching rotates the filter. class RotationTimer : public Timer { public: - RotationTimer(double t, LogMgr::WriterInfo* arg_winfo, bool arg_rotate) + RotationTimer(double t, Manager::WriterInfo* arg_winfo, bool arg_rotate) : Timer(t, TIMER_ROTATE) { winfo = arg_winfo; @@ -1391,7 +1135,7 @@ public: void Dispatch(double t, int is_expire); protected: - LogMgr::WriterInfo* winfo; + Manager::WriterInfo* winfo; bool rotate; }; @@ -1415,23 +1159,7 @@ void RotationTimer::Dispatch(double t, int is_expire) } } -RecordVal* LogMgr::LookupRotationControl(EnumVal* writer, string path) - { - TableVal* rc = BifConst::Log::rotation_control->AsTableVal(); - - ListVal* index = new ListVal(TYPE_ANY); - index->Append(writer->Ref()); - index->Append(new StringVal(path.c_str())); - - Val* r = rc->Lookup(index); - assert(r); - - Unref(index); - - return r->AsRecordVal(); - } - -void LogMgr::InstallRotationTimer(WriterInfo* winfo) +void Manager::InstallRotationTimer(WriterInfo* winfo) { if ( terminating ) return; @@ -1442,13 +1170,7 @@ void LogMgr::InstallRotationTimer(WriterInfo* winfo) winfo->rotation_timer = 0; } - RecordVal* rc = - LookupRotationControl(winfo->type, winfo->writer->Path()); - - assert(rc); - - int idx = rc->Type()->AsRecordType()->FieldOffset("interv"); - double rotation_interval = rc->LookupWithDefault(idx)->AsInterval(); + double rotation_interval = winfo->interval; if ( rotation_interval ) { @@ -1479,7 +1201,7 @@ void LogMgr::InstallRotationTimer(WriterInfo* winfo) } } -void LogMgr::Rotate(WriterInfo* winfo) +void Manager::Rotate(WriterInfo* winfo) { DBG_LOG(DBG_LOGGING, "Rotating %s at %.6f", winfo->writer->Path().c_str(), network_time); @@ -1499,19 +1221,15 @@ void LogMgr::Rotate(WriterInfo* winfo) winfo->writer->Rotate(tmp, winfo->open_time, network_time, terminating); } -bool LogMgr::FinishedRotation(LogWriter* writer, string new_name, string old_name, +bool Manager::FinishedRotation(WriterFrontend* writer, string new_name, string old_name, double open, double close, bool terminating) { DBG_LOG(DBG_LOGGING, "Finished rotating %s at %.6f, new name %s", writer->Path().c_str(), network_time, new_name.c_str()); WriterInfo* winfo = FindWriter(writer); - assert(winfo); - - RecordVal* rc = - LookupRotationControl(winfo->type, winfo->writer->Path()); - - assert(rc); + if ( ! winfo ) + return true; // Create the RotationInfo record. RecordVal* info = new RecordVal(BifType::Record::Log::RotationInfo); @@ -1522,15 +1240,12 @@ bool LogMgr::FinishedRotation(LogWriter* writer, string new_name, string old_nam info->Assign(4, new Val(close, TYPE_TIME)); info->Assign(5, new Val(terminating, TYPE_BOOL)); - int idx = rc->Type()->AsRecordType()->FieldOffset("postprocessor"); - assert(idx >= 0); - - Val* func = rc->Lookup(idx); + Func* func = winfo->postprocessor; if ( ! func ) { ID* id = global_scope()->Lookup("Log::__default_rotation_postprocessor"); assert(id); - func = id->ID_Val(); + func = id->ID_Val()->AsFunc(); } assert(func); @@ -1538,9 +1253,19 @@ bool LogMgr::FinishedRotation(LogWriter* writer, string new_name, string old_nam // Call the postprocessor function. val_list vl(1); vl.append(info); - Val* v = func->AsFunc()->Call(&vl); - int result = v->AsBool(); - Unref(v); + + int result = 0; + + try + { + Val* v = func->Call(&vl); + result = v->AsBool(); + Unref(v); + } + + catch ( InterpreterException& e ) + { /* Already reported. */ } + return result; } diff --git a/src/logging/Manager.h b/src/logging/Manager.h new file mode 100644 index 0000000000..bf097c5e1a --- /dev/null +++ b/src/logging/Manager.h @@ -0,0 +1,205 @@ +// See the file "COPYING" in the main distribution directory for copyright. +// +// A class managing log writers and filters. + +#ifndef LOGGING_MANAGER_H +#define LOGGING_MANAGER_H + +#include "../Val.h" +#include "../EventHandler.h" +#include "../RemoteSerializer.h" + +class SerializationFormat; +class RemoteSerializer; +class RotationTimer; + +namespace logging { + + +class WriterBackend; +class WriterFrontend; +class RotationFinishedMessage; + +/** + * Singleton class for managing log streams. + */ +class Manager { +public: + /** + * Constructor. + */ + Manager(); + + /** + * Destructor. + */ + ~Manager(); + + /** + * Creates a new log stream. + * + * @param id The enum value corresponding the log stream. + * + * @param stream A record of script type \c Log::Stream. + * + * This method corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ + bool CreateStream(EnumVal* id, RecordVal* stream); + + /** + * Enables a log log stream. + * + * @param id The enum value corresponding the log stream. + * + * This method corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ + bool EnableStream(EnumVal* id); + + /** + * Disables a log stream. + * + * @param id The enum value corresponding the log stream. + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ + bool DisableStream(EnumVal* id); + + /** + * Adds a filter to a log stream. + * + * @param id The enum value corresponding the log stream. + * + * @param filter A record of script type \c Log::Filter. + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ + bool AddFilter(EnumVal* id, RecordVal* filter); + + /** + * Removes a filter from a log stream. + * + * @param id The enum value corresponding the log stream. + * + * @param name The name of the filter to remove. + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ + bool RemoveFilter(EnumVal* id, StringVal* name); + + /** + * Removes a filter from a log stream. + * + * @param id The enum value corresponding the log stream. + * + * @param name The name of the filter to remove. + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ + bool RemoveFilter(EnumVal* id, string name); + + /** + * Write a record to a log stream. + * + * @param id The enum value corresponding the log stream. + * + * @param colums A record of the type defined for the stream's + * columns. + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ + bool Write(EnumVal* id, RecordVal* columns); + + /** + * Sets log streams buffering state. This adjusts all associated + * writers to the new state. + * + * @param id The enum value corresponding the log stream. + * + * @param enabled False to disable buffering (default is enabled). + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ + bool SetBuf(EnumVal* id, bool enabled); + + /** + * Flushes a log stream. This flushed all associated writers. + * + * @param id The enum value corresponding the log stream. + * + * This methods corresponds directly to the internal BiF defined in + * logging.bif, which just forwards here. + */ + bool Flush(EnumVal* id); + + /** + * Prepares the log manager to terminate. This will flush all log + * stream. + */ + void Terminate(); + +protected: + friend class WriterFrontend; + friend class RotationFinishedMessage; + friend class ::RemoteSerializer; + friend class ::RotationTimer; + + // Instantiates a new WriterBackend of the given type (note that + // doing so creates a new thread!). + WriterBackend* CreateBackend(WriterFrontend* frontend, bro_int_t type); + + //// Function also used by the RemoteSerializer. + + // Takes ownership of fields. + WriterFrontend* CreateWriter(EnumVal* id, EnumVal* writer, string path, + int num_fields, const threading::Field* const* fields, + bool local, bool remote); + + // Takes ownership of values.. + bool Write(EnumVal* id, EnumVal* writer, string path, + int num_fields, threading::Value** vals); + + // Announces all instantiated writers to peer. + void SendAllWritersTo(RemoteSerializer::PeerID peer); + + // Signals that a file has been rotated. + bool FinishedRotation(WriterFrontend* writer, string new_name, string old_name, + double open, double close, bool terminating); + + // Deletes the values as passed into Write(). + void DeleteVals(int num_fields, threading::Value** vals); + +private: + struct Filter; + struct Stream; + struct WriterInfo; + + bool TraverseRecord(Stream* stream, Filter* filter, RecordType* rt, + TableVal* include, TableVal* exclude, string path, list indices); + + threading::Value** RecordToFilterVals(Stream* stream, Filter* filter, + RecordVal* columns); + + threading::Value* ValToLogVal(Val* val, BroType* ty = 0); + Stream* FindStream(EnumVal* id); + void RemoveDisabledWriters(Stream* stream); + void InstallRotationTimer(WriterInfo* winfo); + void Rotate(WriterInfo* info); + Filter* FindFilter(EnumVal* id, StringVal* filter); + WriterInfo* FindWriter(WriterFrontend* writer); + + vector streams; // Indexed by stream enum. +}; + +} + +extern logging::Manager* log_mgr; + +#endif diff --git a/src/logging/WriterBackend.cc b/src/logging/WriterBackend.cc new file mode 100644 index 0000000000..7c71c09604 --- /dev/null +++ b/src/logging/WriterBackend.cc @@ -0,0 +1,281 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include "util.h" +#include "threading/SerialTypes.h" + +#include "WriterBackend.h" +#include "WriterFrontend.h" + +// Messages sent from backend to frontend (i.e., "OutputMessages"). + +using threading::Value; +using threading::Field; + +namespace logging { + +class RotationFinishedMessage : public threading::OutputMessage +{ +public: + RotationFinishedMessage(WriterFrontend* writer, string new_name, string old_name, + double open, double close, bool terminating) + : threading::OutputMessage("RotationFinished", writer), + new_name(new_name), old_name(old_name), open(open), + close(close), terminating(terminating) { } + + virtual bool Process() + { + return log_mgr->FinishedRotation(Object(), new_name, old_name, open, close, terminating); + } + +private: + string new_name; + string old_name; + double open; + double close; + bool terminating; +}; + +class FlushWriteBufferMessage : public threading::OutputMessage +{ +public: + FlushWriteBufferMessage(WriterFrontend* writer) + : threading::OutputMessage("FlushWriteBuffer", writer) {} + + virtual bool Process() { Object()->FlushWriteBuffer(); return true; } +}; + +class DisableMessage : public threading::OutputMessage +{ +public: + DisableMessage(WriterFrontend* writer) + : threading::OutputMessage("Disable", writer) {} + + virtual bool Process() { Object()->SetDisable(); return true; } +}; + +} + +// Backend methods. + +using namespace logging; + +WriterBackend::WriterBackend(WriterFrontend* arg_frontend) : MsgThread() + { + path = ""; + num_fields = 0; + fields = 0; + buffering = true; + frontend = arg_frontend; + + SetName(frontend->Name()); + } + +WriterBackend::~WriterBackend() + { + if ( fields ) + { + for(int i = 0; i < num_fields; ++i) + delete fields[i]; + + delete [] fields; + } + } + +void WriterBackend::DeleteVals(int num_writes, Value*** vals) + { + for ( int j = 0; j < num_writes; ++j ) + { + // Note this code is duplicated in Manager::DeleteVals(). + for ( int i = 0; i < num_fields; i++ ) + delete vals[j][i]; + + delete [] vals[j]; + } + + delete [] vals; + } + +bool WriterBackend::FinishedRotation(string new_name, string old_name, + double open, double close, bool terminating) + { + SendOut(new RotationFinishedMessage(frontend, new_name, old_name, open, close, terminating)); + return true; + } + +void WriterBackend::DisableFrontend() + { + SendOut(new DisableMessage(frontend)); + } + +bool WriterBackend::Init(string arg_path, int arg_num_fields, const Field* const* arg_fields) + { + path = arg_path; + num_fields = arg_num_fields; + fields = arg_fields; + + string name = Fmt("%s/%s", path.c_str(), frontend->Name().c_str()); + + SetName(name); + + if ( ! DoInit(arg_path, arg_num_fields, arg_fields) ) + { + DisableFrontend(); + return false; + } + + return true; + } + +bool WriterBackend::Write(int arg_num_fields, int num_writes, Value*** vals) + { + // Double-check that the arguments match. If we get this from remote, + // something might be mixed up. + if ( num_fields != arg_num_fields ) + { + +#ifdef DEBUG + const char* msg = Fmt("Number of fields don't match in WriterBackend::Write() (%d vs. %d)", + arg_num_fields, num_fields); + Debug(DBG_LOGGING, msg); +#endif + + DeleteVals(num_writes, vals); + DisableFrontend(); + return false; + } + +#ifdef DEBUG + // Double-check all the types match. + for ( int j = 0; j < num_writes; j++ ) + { + for ( int i = 0; i < num_fields; ++i ) + { + if ( vals[j][i]->type != fields[i]->type ) + { + const char* msg = Fmt("Field type doesn't match in WriterBackend::Write() (%d vs. %d)", + vals[j][i]->type, fields[i]->type); + Debug(DBG_LOGGING, msg); + + DisableFrontend(); + DeleteVals(num_writes, vals); + return false; + } + } + } +#endif + + bool success = true; + + for ( int j = 0; j < num_writes; j++ ) + { + success = DoWrite(num_fields, fields, vals[j]); + + if ( ! success ) + break; + } + + DeleteVals(num_writes, vals); + + if ( ! success ) + DisableFrontend(); + + return success; + } + +bool WriterBackend::SetBuf(bool enabled) + { + if ( enabled == buffering ) + // No change. + return true; + + buffering = enabled; + + if ( ! DoSetBuf(enabled) ) + { + DisableFrontend(); + return false; + } + + return true; + } + +bool WriterBackend::Rotate(string rotated_path, double open, + double close, bool terminating) + { + if ( ! DoRotate(rotated_path, open, close, terminating) ) + { + DisableFrontend(); + return false; + } + + return true; + } + +bool WriterBackend::Flush() + { + if ( ! DoFlush() ) + { + DisableFrontend(); + return false; + } + + return true; + } + +bool WriterBackend::Finish() + { + if ( ! DoFlush() ) + { + DisableFrontend(); + return false; + } + + return true; + } + +bool WriterBackend::DoHeartbeat(double network_time, double current_time) + { + MsgThread::DoHeartbeat(network_time, current_time); + + SendOut(new FlushWriteBufferMessage(frontend)); + + return true; + } + +string WriterBackend::Render(const threading::Value::addr_t& addr) const + { + if ( addr.family == IPv4 ) + { + char s[INET_ADDRSTRLEN]; + + if ( inet_ntop(AF_INET, &addr.in.in4, s, INET_ADDRSTRLEN) == NULL ) + return ""; + else + return s; + } + else + { + char s[INET6_ADDRSTRLEN]; + + if ( inet_ntop(AF_INET6, &addr.in.in6, s, INET6_ADDRSTRLEN) == NULL ) + return ""; + else + return s; + } + } + +string WriterBackend::Render(const threading::Value::subnet_t& subnet) const + { + char l[16]; + + if ( subnet.prefix.family == IPv4 ) + modp_uitoa10(subnet.length - 96, l); + else + modp_uitoa10(subnet.length, l); + + string s = Render(subnet.prefix) + "/" + l; + + return s; + } + + diff --git a/src/logging/WriterBackend.h b/src/logging/WriterBackend.h new file mode 100644 index 0000000000..eea0927fd2 --- /dev/null +++ b/src/logging/WriterBackend.h @@ -0,0 +1,319 @@ +// See the file "COPYING" in the main distribution directory for copyright. +// +// Bridge class between main process and writer threads. + +#ifndef LOGGING_WRITERBACKEND_H +#define LOGGING_WRITERBACKEND_H + +#include "Manager.h" + +#include "threading/MsgThread.h" + +namespace logging { + +/** + * Base class for writer implementation. When the logging::Manager creates a + * new logging filter, it instantiates a WriterFrontend. That then in turn + * creates a WriterBackend of the right type. The frontend then forwards + * messages over the backend as its methods are called. + * + * All of this methods must be called only from the corresponding child + * thread (the constructor and destructor are the exceptions.) + */ +class WriterBackend : public threading::MsgThread +{ +public: + /** + * Constructor. + * + * @param frontend The frontend writer that created this backend. The + * *only* purpose of this value is to be passed back via messages as + * a argument to callbacks. One must not otherwise access the + * frontend, it's running in a different thread. + * + * @param name A descriptive name for writer's type (e.g., \c Ascii). + * + */ + WriterBackend(WriterFrontend* frontend); + + /** + * Destructor. + */ + virtual ~WriterBackend(); + + /** + * One-time initialization of the writer to define the logged fields. + * + * @param path A string left to the interpretation of the writer + * implementation; it corresponds to the value configured on the + * script-level for the logging filter. + * + * @param num_fields The number of log fields for the stream. + * + * @param fields An array of size \a num_fields with the log fields. + * The methods takes ownership of the array. + * + * @return False if an error occured. + */ + bool Init(string path, int num_fields, const threading::Field* const* fields); + + /** + * Writes one log entry. + * + * @param num_fields: The number of log fields for this stream. The + * value must match what was passed to Init(). + * + * @param An array of size \a num_fields with the log values. Their + * types musst match with the field passed to Init(). The method + * takes ownership of \a vals.. + * + * Returns false if an error occured, in which case the writer must + * not be used any further. + * + * @return False if an error occured. + */ + bool Write(int num_fields, int num_writes, threading::Value*** vals); + + /** + * Sets the buffering status for the writer, assuming the writer + * supports that. (If not, it will be ignored). + * + * @param enabled False if buffering is to be disabled (by default + * it's on). + * + * @return False if an error occured. + */ + bool SetBuf(bool enabled); + + /** + * Flushes any currently buffered output, assuming the writer + * supports that. (If not, it will be ignored). + * + * @return False if an error occured. + */ + bool Flush(); + + /** + * Triggers rotation, if the writer supports that. (If not, it will + * be ignored). + * + * @return False if an error occured. + */ + bool Rotate(string rotated_path, double open, double close, bool terminating); + + /** + * Finishes writing to this logger in a regularl fashion. Must not be + * called if an error has been indicated earlier. After calling this, + * no further writing must be performed. + * + * @return False if an error occured. + */ + bool Finish(); + + /** + * Disables the frontend that has instantiated this backend. Once + * disabled,the frontend will not send any further message over. + */ + void DisableFrontend(); + + /** + * Returns the log path as passed into the constructor. + */ + const string Path() const { return path; } + + /** + * Returns the number of log fields as passed into the constructor. + */ + int NumFields() const { return num_fields; } + + /** + * Returns the log fields as passed into the constructor. + */ + const threading::Field* const * Fields() const { return fields; } + + /** + * Returns the current buffering state. + * + * @return True if buffering is enabled. + */ + bool IsBuf() { return buffering; } + + /** + * Signals that a file has been rotated. This must be called by a + * writer's implementation of DoRotate() once rotation has finished. + * + * Most of the parameters should be passed through from DoRotate(). + * + * @param new_name The filename of the rotated file. + * + * @param old_name The filename of the original file. + * + * @param open: The timestamp when the original file was opened. + * + * @param close: The timestamp when the origina file was closed. + * + * @param terminating: True if the original rotation request occured + * due to the main Bro process shutting down. + */ + bool FinishedRotation(string new_name, string old_name, + double open, double close, bool terminating); + + /** Helper method to render an IP address as a string. + * + * @param addr The address. + * + * @return An ASCII representation of the address. + */ + string Render(const threading::Value::addr_t& addr) const; + + /** Helper method to render an subnet value as a string. + * + * @param addr The address. + * + * @return An ASCII representation of the address. + */ + string Render(const threading::Value::subnet_t& subnet) const; + +protected: + /** + * Writer-specific intialization method. + * + * A writer implementation must override this method. If it returns + * false, it will be assumed that a fatal error has occured that + * prevents the writer from further operation; it will then be + * disabled and eventually deleted. When returning false, an + * implementation should also call Error() to indicate what happened. + */ + virtual bool DoInit(string path, int num_fields, + const threading::Field* const* fields) = 0; + + /** + * Writer-specific output method implementing recording of fone log + * entry. + * + * A writer implementation must override this method. If it returns + * false, it will be assumed that a fatal error has occured that + * prevents the writer from further operation; it will then be + * disabled and eventually deleted. When returning false, an + * implementation should also call Error() to indicate what happened. + */ + virtual bool DoWrite(int num_fields, const threading::Field* const* fields, + threading::Value** vals) = 0; + + /** + * Writer-specific method implementing a change of fthe buffering + * state. If buffering is disabled, the writer should attempt to + * write out information as quickly as possible even if doing so may + * have a performance impact. If enabled (which is the default), it + * may buffer data as helpful and write it out later in a way + * optimized for performance. The current buffering state can be + * queried via IsBuf(). + * + * A writer implementation must override this method but it can just + * ignore calls if buffering doesn't align with its semantics. + * + * If the method returns false, it will be assumed that a fatal error + * has occured that prevents the writer from further operation; it + * will then be disabled and eventually deleted. When returning + * false, an implementation should also call Error() to indicate what + * happened. + */ + virtual bool DoSetBuf(bool enabled) = 0; + + /** + * Writer-specific method implementing flushing of its output. + * + * A writer implementation must override this method but it can just + * ignore calls if flushing doesn't align with its semantics. + * + * If the method returns false, it will be assumed that a fatal error + * has occured that prevents the writer from further operation; it + * will then be disabled and eventually deleted. When returning + * false, an implementation should also call Error() to indicate what + * happened. + */ + virtual bool DoFlush() = 0; + + /** + * Writer-specific method implementing log rotation. Most directly + * this only applies to writers writing into files, which should then + * close the current file and open a new one. However, a writer may + * also trigger other apppropiate actions if semantics are similar. * + * Once rotation has finished, the implementation must call + * FinishedRotation() to signal the log manager that potential + * postprocessors can now run. + * + * A writer implementation must override this method but it can just + * ignore calls if flushing doesn't align with its semantics. It + * still needs to call FinishedRotation() though. + * + * If the method returns false, it will be assumed that a fatal error + * has occured that prevents the writer from further operation; it + * will then be disabled and eventually deleted. When returning + * false, an implementation should also call Error() to indicate what + * happened. + * + * @param rotate_path Reflects the path to where the rotated output + * is to be moved, with specifics depending on the writer. It should + * generally be interpreted in a way consistent with that of \c path + * as passed into DoInit(). As an example, for file-based output, \c + * rotate_path could be the original filename extended with a + * timestamp indicating the time of the rotation. + * + * @param open The network time when the *current* file was opened. + * + * @param close The network time when the *current* file was closed. + * + * @param terminating Indicates whether the rotation request occurs + * due the main Bro prcoess terminating (and not because we've + * reached a regularly scheduled time for rotation). + */ + virtual bool DoRotate(string rotated_path, double open, double close, + bool terminating) = 0; + + /** + * Writer-specific method implementing log output finalization at + * termination. Not called when any of the other methods has + * previously signaled an error, i.e., executing this method signals + * a regular shutdown of the writer. + * + * A writer implementation must override this method but it can just + * ignore calls if flushing doesn't align with its semantics. + * + * If the method returns false, it will be assumed that a fatal error + * has occured that prevents the writer from further operation; it + * will then be disabled and eventually deleted. When returning + * false, an implementation should also call Error() to indicate what + * happened. + */ + virtual bool DoFinish() = 0; + + /** + * Triggered by regular heartbeat messages from the main thread. + * + * This method can be overridden but once must call + * WriterBackend::DoHeartbeat(). + */ + virtual bool DoHeartbeat(double network_time, double current_time); + +private: + /** + * Deletes the values as passed into Write(). + */ + void DeleteVals(int num_writes, threading::Value*** vals); + + // Frontend that instantiated us. This object must not be access from + // this class, it's running in a different thread! + WriterFrontend* frontend; + + string path; // Log path. + int num_fields; // Number of log fields. + const threading::Field* const* fields; // Log fields. + bool buffering; // True if buffering is enabled. +}; + + +} + +#endif + diff --git a/src/logging/WriterFrontend.cc b/src/logging/WriterFrontend.cc new file mode 100644 index 0000000000..c100e99f90 --- /dev/null +++ b/src/logging/WriterFrontend.cc @@ -0,0 +1,279 @@ + +#include "Net.h" +#include "threading/SerialTypes.h" + +#include "WriterFrontend.h" +#include "WriterBackend.h" + +using threading::Value; +using threading::Field; + +namespace logging { + +// Messages sent from frontend to backend (i.e., "InputMessages"). + +class InitMessage : public threading::InputMessage +{ +public: + InitMessage(WriterBackend* backend, const string path, const int num_fields, const Field* const* fields) + : threading::InputMessage("Init", backend), + path(path), num_fields(num_fields), fields(fields) { } + + virtual bool Process() { return Object()->Init(path, num_fields, fields); } + +private: + const string path; + const int num_fields; + const Field * const* fields; +}; + +class RotateMessage : public threading::InputMessage +{ +public: + RotateMessage(WriterBackend* backend, WriterFrontend* frontend, const string rotated_path, const double open, + const double close, const bool terminating) + : threading::InputMessage("Rotate", backend), + frontend(frontend), + rotated_path(rotated_path), open(open), + close(close), terminating(terminating) { } + + virtual bool Process() { return Object()->Rotate(rotated_path, open, close, terminating); } + +private: + WriterFrontend* frontend; + const string rotated_path; + const double open; + const double close; + const bool terminating; +}; + +class WriteMessage : public threading::InputMessage +{ +public: + WriteMessage(WriterBackend* backend, int num_fields, int num_writes, Value*** vals) + : threading::InputMessage("Write", backend), + num_fields(num_fields), num_writes(num_writes), vals(vals) {} + + virtual bool Process() { return Object()->Write(num_fields, num_writes, vals); } + +private: + int num_fields; + int num_writes; + Value ***vals; +}; + +class SetBufMessage : public threading::InputMessage +{ +public: + SetBufMessage(WriterBackend* backend, const bool enabled) + : threading::InputMessage("SetBuf", backend), + enabled(enabled) { } + + virtual bool Process() { return Object()->SetBuf(enabled); } + +private: + const bool enabled; +}; + +class FlushMessage : public threading::InputMessage +{ +public: + FlushMessage(WriterBackend* backend) + : threading::InputMessage("Flush", backend) {} + + virtual bool Process() { return Object()->Flush(); } +}; + +class FinishMessage : public threading::InputMessage +{ +public: + FinishMessage(WriterBackend* backend) + : threading::InputMessage("Finish", backend) {} + + virtual bool Process() { return Object()->Finish(); } +}; + +} + +// Frontend methods. + +using namespace logging; + +WriterFrontend::WriterFrontend(EnumVal* arg_stream, EnumVal* arg_writer, bool arg_local, bool arg_remote) + { + stream = arg_stream; + writer = arg_writer; + Ref(stream); + Ref(writer); + + disabled = initialized = false; + buf = true; + local = arg_local; + remote = arg_remote; + write_buffer = 0; + write_buffer_pos = 0; + ty_name = ""; + + if ( local ) + { + backend = log_mgr->CreateBackend(this, writer->AsEnum()); + assert(backend); + backend->Start(); + } + + else + backend = 0; + } + +WriterFrontend::~WriterFrontend() + { + Unref(stream); + Unref(writer); + } + +string WriterFrontend::Name() const + { + if ( path.size() ) + return ty_name; + + return ty_name + "/" + path; + } + +void WriterFrontend::Stop() + { + FlushWriteBuffer(); + SetDisable(); + + if ( backend ) + backend->Stop(); + } + +void WriterFrontend::Init(string arg_path, int arg_num_fields, const Field* const * arg_fields) + { + if ( disabled ) + return; + + if ( initialized ) + reporter->InternalError("writer initialize twice"); + + path = arg_path; + num_fields = arg_num_fields; + fields = arg_fields; + + initialized = true; + + if ( backend ) + backend->SendIn(new InitMessage(backend, arg_path, arg_num_fields, arg_fields)); + + if ( remote ) + remote_serializer->SendLogCreateWriter(stream, + writer, + arg_path, + arg_num_fields, + arg_fields); + + } + +void WriterFrontend::Write(int num_fields, Value** vals) + { + if ( disabled ) + return; + + if ( remote ) + remote_serializer->SendLogWrite(stream, + writer, + path, + num_fields, + vals); + + if ( ! backend ) + { + DeleteVals(vals); + return; + } + + if ( ! write_buffer ) + { + // Need new buffer. + write_buffer = new Value**[WRITER_BUFFER_SIZE]; + write_buffer_pos = 0; + } + + write_buffer[write_buffer_pos++] = vals; + + if ( write_buffer_pos >= WRITER_BUFFER_SIZE || ! buf || terminating ) + // Buffer full (or no bufferin desired or termiating). + FlushWriteBuffer(); + + } + +void WriterFrontend::FlushWriteBuffer() + { + if ( ! write_buffer_pos ) + // Nothing to do. + return; + + if ( backend ) + backend->SendIn(new WriteMessage(backend, num_fields, write_buffer_pos, write_buffer)); + + // Clear buffer (no delete, we pass ownership to child thread.) + write_buffer = 0; + write_buffer_pos = 0; + } + +void WriterFrontend::SetBuf(bool enabled) + { + if ( disabled ) + return; + + buf = enabled; + + if ( backend ) + backend->SendIn(new SetBufMessage(backend, enabled)); + + if ( ! buf ) + // Make sure no longer buffer any still queued data. + FlushWriteBuffer(); + } + +void WriterFrontend::Flush() + { + if ( disabled ) + return; + + FlushWriteBuffer(); + + if ( backend ) + backend->SendIn(new FlushMessage(backend)); + } + +void WriterFrontend::Rotate(string rotated_path, double open, double close, bool terminating) + { + if ( disabled ) + return; + + FlushWriteBuffer(); + + if ( backend ) + backend->SendIn(new RotateMessage(backend, this, rotated_path, open, close, terminating)); + } + +void WriterFrontend::Finish() + { + if ( disabled ) + return; + + FlushWriteBuffer(); + + if ( backend ) + backend->SendIn(new FinishMessage(backend)); + } + +void WriterFrontend::DeleteVals(Value** vals) + { + // Note this code is duplicated in Manager::DeleteVals(). + for ( int i = 0; i < num_fields; i++ ) + delete vals[i]; + + delete [] vals; + } diff --git a/src/logging/WriterFrontend.h b/src/logging/WriterFrontend.h new file mode 100644 index 0000000000..b83250a5b8 --- /dev/null +++ b/src/logging/WriterFrontend.h @@ -0,0 +1,222 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef LOGGING_WRITERFRONTEND_H +#define LOGGING_WRITERFRONTEND_H + +#include "Manager.h" + +#include "threading/MsgThread.h" + +namespace logging { + +class WriterBackend; + +/** + * Bridge class between the logging::Manager and backend writer threads. The + * Manager instantiates one \a WriterFrontend for each open logging filter. + * Each frontend in turns instantiates a WriterBackend-derived class + * internally that's specific to the particular output format. That backend + * runs in a new thread, and it receives messages from the frontend that + * correspond to method called by the manager. + * + */ +class WriterFrontend { +public: + /** + * Constructor. + * + * stream: The logging stream. + * + * writer: The backend writer type, with the value corresponding to the + * script-level \c Log::Writer enum (e.g., \a WRITER_ASCII). The + * frontend will internally instantiate a WriterBackend of the + * corresponding type. + * + * local: If true, the writer will instantiate a local backend. + * + * remote: If true, the writer will forward all data to remote + * clients. + * + * Frontends must only be instantiated by the main thread. + */ + WriterFrontend(EnumVal* stream, EnumVal* writer, bool local, bool remote); + + /** + * Destructor. + * + * Frontends must only be destroyed by the main thread. + */ + virtual ~WriterFrontend(); + + /** + * Stops all output to this writer. Calling this methods disables all + * message forwarding to the backend and stops the backend thread. + * + * This method must only be called from the main thread. + */ + void Stop(); + + /** + * Initializes the writer. + * + * This method generates a message to the backend writer and triggers + * the corresponding message there. If the backend method fails, it + * sends a message back that will asynchronously call Disable(). + * + * See WriterBackend::Init() for arguments. The method takes + * ownership of \a fields. + * + * This method must only be called from the main thread. + */ + void Init(string path, int num_fields, const threading::Field* const* fields); + + /** + * Write out a record. + * + * This method generates a message to the backend writer and triggers + * the corresponding message there. If the backend method fails, it + * sends a message back that will asynchronously call Disable(). + * + * As an optimization, if buffering is enabled (which is the default) + * this method may buffer several writes and send them over to the + * backend in bulk with a single message. An explicit bulk write of + * all currently buffered data can be triggered with + * FlushWriteBuffer(). The backend writer triggers this with a + * message at every heartbeat. + * + * See WriterBackend::Writer() for arguments (except that this method + * takes only a single record, not an array). The method takes + * ownership of \a vals. + * + * This method must only be called from the main thread. + */ + void Write(int num_fields, threading::Value** vals); + + /** + * Sets the buffering state. + * + * This method generates a message to the backend writer and triggers + * the corresponding message there. If the backend method fails, it + * sends a message back that will asynchronously call Disable(). + * + * See WriterBackend::SetBuf() for arguments. + * + * This method must only be called from the main thread. + */ + void SetBuf(bool enabled); + + /** + * Flushes the output. + * + * This method generates a message to the backend writer and triggers + * the corresponding message there. In addition, it also triggers + * FlushWriteBuffer(). If the backend method fails, it sends a + * message back that will asynchronously call Disable(). + * + * This method must only be called from the main thread. + */ + void Flush(); + + /** + * Triggers log rotation. + * + * This method generates a message to the backend writer and triggers + * the corresponding message there. If the backend method fails, it + * sends a message back that will asynchronously call Disable(). + * + * See WriterBackend::Rotate() for arguments. + * + * This method must only be called from the main thread. + */ + void Rotate(string rotated_path, double open, double close, bool terminating); + + /** + * Finalizes writing to this tream. + * + * This method generates a message to the backend writer and triggers + * the corresponding message there. If the backend method fails, it + * sends a message back that will asynchronously call Disable(). + * + * This method must only be called from the main thread. + */ + void Finish(); + + /** + * Explicitly triggers a transfer of all potentially buffered Write() + * operations over to the backend. + * + * This method must only be called from the main thread. + */ + void FlushWriteBuffer(); + + /** + * Disables the writer frontend. From now on, all method calls that + * would normally send message over to the backend, turn into no-ops. + * Note though that it does not stop the backend itself, use Stop() + * to do thast as well (this method is primarily for use as callback + * when the backend wants to disable the frontend). + * + * Disabled frontend will eventually be discarded by the + * logging::Manager. + * + * This method must only be called from the main thread. + */ + void SetDisable() { disabled = true; } + + /** + * Returns true if the writer frontend has been disabled with SetDisable(). + */ + bool Disabled() { return disabled; } + + /** + * Returns the log path as passed into the constructor. + */ + const string Path() const { return path; } + + /** + * Returns the number of log fields as passed into the constructor. + */ + int NumFields() const { return num_fields; } + + /** + * Returns a descriptive name for the writer, including the type of + * the backend and the path used. + * + * This method is safe to call from any thread. + */ + string Name() const; + + /** + * Returns the log fields as passed into the constructor. + */ + const threading::Field* const * Fields() const { return fields; } + +protected: + friend class Manager; + + void DeleteVals(threading::Value** vals); + + EnumVal* stream; + EnumVal* writer; + + WriterBackend* backend; // The backend we have instanatiated. + bool disabled; // True if disabled. + bool initialized; // True if initialized. + bool buf; // True if buffering is enabled (default). + bool local; // True if logging locally. + bool remote; // True if loggin remotely. + + string ty_name; // Name of the backend type. Set by the manager. + string path; // The log path. + int num_fields; // The number of log fields. + const threading::Field* const* fields; // The log fields. + + // Buffer for bulk writes. + static const int WRITER_BUFFER_SIZE = 1000; + int write_buffer_pos; // Position of next write in buffer. + threading::Value*** write_buffer; // Buffer of size WRITER_BUFFER_SIZE. +}; + +} + +#endif diff --git a/src/logging/writers/Ascii.cc b/src/logging/writers/Ascii.cc new file mode 100644 index 0000000000..0759e60a82 --- /dev/null +++ b/src/logging/writers/Ascii.cc @@ -0,0 +1,356 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include +#include + +#include "NetVar.h" +#include "threading/SerialTypes.h" + +#include "Ascii.h" + +using namespace logging; +using namespace writer; +using threading::Value; +using threading::Field; + +Ascii::Ascii(WriterFrontend* frontend) : WriterBackend(frontend) + { + file = 0; + + output_to_stdout = BifConst::LogAscii::output_to_stdout; + include_header = BifConst::LogAscii::include_header; + + separator_len = BifConst::LogAscii::separator->Len(); + separator = new char[separator_len]; + memcpy(separator, BifConst::LogAscii::separator->Bytes(), + separator_len); + + set_separator_len = BifConst::LogAscii::set_separator->Len(); + set_separator = new char[set_separator_len]; + memcpy(set_separator, BifConst::LogAscii::set_separator->Bytes(), + set_separator_len); + + empty_field_len = BifConst::LogAscii::empty_field->Len(); + empty_field = new char[empty_field_len]; + memcpy(empty_field, BifConst::LogAscii::empty_field->Bytes(), + empty_field_len); + + unset_field_len = BifConst::LogAscii::unset_field->Len(); + unset_field = new char[unset_field_len]; + memcpy(unset_field, BifConst::LogAscii::unset_field->Bytes(), + unset_field_len); + + header_prefix_len = BifConst::LogAscii::header_prefix->Len(); + header_prefix = new char[header_prefix_len]; + memcpy(header_prefix, BifConst::LogAscii::header_prefix->Bytes(), + header_prefix_len); + + desc.EnableEscaping(); + desc.AddEscapeSequence(separator, separator_len); + } + +Ascii::~Ascii() + { + if ( file ) + fclose(file); + + delete [] separator; + delete [] set_separator; + delete [] empty_field; + delete [] unset_field; + delete [] header_prefix; + } + +bool Ascii::WriteHeaderField(const string& key, const string& val) + { + string str = string(header_prefix, header_prefix_len) + + key + string(separator, separator_len) + val + "\n"; + + return (fwrite(str.c_str(), str.length(), 1, file) == 1); + } + +bool Ascii::DoInit(string path, int num_fields, + const Field* const * fields) + { + if ( output_to_stdout ) + path = "/dev/stdout"; + + fname = IsSpecial(path) ? path : path + "." + LogExt(); + + if ( ! (file = fopen(fname.c_str(), "w")) ) + { + Error(Fmt("cannot open %s: %s", fname.c_str(), + strerror(errno))); + + return false; + } + + if ( include_header ) + { + string str = string(header_prefix, header_prefix_len) + + "separator " // Always use space as separator here. + + get_escaped_string(string(separator, separator_len), false) + + "\n"; + + if( fwrite(str.c_str(), str.length(), 1, file) != 1 ) + goto write_error; + + if ( ! (WriteHeaderField("set_separator", get_escaped_string( + string(set_separator, set_separator_len), false)) && + WriteHeaderField("empty_field", get_escaped_string( + string(empty_field, empty_field_len), false)) && + WriteHeaderField("unset_field", get_escaped_string( + string(unset_field, unset_field_len), false)) && + WriteHeaderField("path", get_escaped_string(path, false))) ) + goto write_error; + + string names; + string types; + + for ( int i = 0; i < num_fields; ++i ) + { + if ( i > 0 ) + { + names += string(separator, separator_len); + types += string(separator, separator_len); + } + + const Field* field = fields[i]; + names += field->name; + types += type_name(field->type); + if ( (field->type == TYPE_TABLE) || (field->type == TYPE_VECTOR) ) + { + types += "["; + types += type_name(field->subtype); + types += "]"; + } + } + + if ( ! (WriteHeaderField("fields", names) + && WriteHeaderField("types", types)) ) + goto write_error; + } + + return true; + +write_error: + Error(Fmt("error writing to %s: %s", fname.c_str(), strerror(errno))); + return false; + } + +bool Ascii::DoFlush() + { + fflush(file); + return true; + } + +bool Ascii::DoFinish() + { + return true; + } + +bool Ascii::DoWriteOne(ODesc* desc, Value* val, const Field* field) + { + if ( ! val->present ) + { + desc->AddN(unset_field, unset_field_len); + return true; + } + + switch ( val->type ) { + + case TYPE_BOOL: + desc->Add(val->val.int_val ? "T" : "F"); + break; + + case TYPE_INT: + desc->Add(val->val.int_val); + break; + + case TYPE_COUNT: + case TYPE_COUNTER: + desc->Add(val->val.uint_val); + break; + + case TYPE_PORT: + desc->Add(val->val.port_val.port); + break; + + case TYPE_SUBNET: + desc->Add(Render(val->val.subnet_val)); + break; + + case TYPE_ADDR: + desc->Add(Render(val->val.addr_val)); + break; + + case TYPE_TIME: + case TYPE_INTERVAL: + char buf[256]; + modp_dtoa(val->val.double_val, buf, 6); + desc->Add(buf); + break; + + case TYPE_DOUBLE: + desc->Add(val->val.double_val); + break; + + case TYPE_ENUM: + case TYPE_STRING: + case TYPE_FILE: + case TYPE_FUNC: + { + int size = val->val.string_val->size(); + const char* data = val->val.string_val->data(); + + if ( ! size ) + { + desc->AddN(empty_field, empty_field_len); + break; + } + + if ( size == unset_field_len && memcmp(data, unset_field, size) == 0 ) + { + // The value we'd write out would match exactly the + // place-holder we use for unset optional fields. We + // escape the first character so that the output + // won't be ambigious. + static const char hex_chars[] = "0123456789abcdef"; + char hex[6] = "\\x00"; + hex[2] = hex_chars[((*data) & 0xf0) >> 4]; + hex[3] = hex_chars[(*data) & 0x0f]; + desc->AddRaw(hex, 4); + + ++data; + --size; + } + + if ( size ) + desc->AddN(data, size); + + break; + } + + case TYPE_TABLE: + { + if ( ! val->val.set_val.size ) + { + desc->AddN(empty_field, empty_field_len); + break; + } + + desc->AddEscapeSequence(set_separator, set_separator_len); + for ( int j = 0; j < val->val.set_val.size; j++ ) + { + if ( j > 0 ) + desc->AddRaw(set_separator, set_separator_len); + + if ( ! DoWriteOne(desc, val->val.set_val.vals[j], field) ) + { + desc->RemoveEscapeSequence(set_separator, set_separator_len); + return false; + } + } + desc->RemoveEscapeSequence(set_separator, set_separator_len); + + break; + } + + case TYPE_VECTOR: + { + if ( ! val->val.vector_val.size ) + { + desc->AddN(empty_field, empty_field_len); + break; + } + + desc->AddEscapeSequence(set_separator, set_separator_len); + for ( int j = 0; j < val->val.vector_val.size; j++ ) + { + if ( j > 0 ) + desc->AddRaw(set_separator, set_separator_len); + + if ( ! DoWriteOne(desc, val->val.vector_val.vals[j], field) ) + { + desc->RemoveEscapeSequence(set_separator, set_separator_len); + return false; + } + } + desc->RemoveEscapeSequence(set_separator, set_separator_len); + + break; + } + + default: + Error(Fmt("unsupported field format %d for %s", val->type, + field->name.c_str())); + return false; + } + + return true; + } + +bool Ascii::DoWrite(int num_fields, const Field* const * fields, + Value** vals) + { + if ( ! file ) + DoInit(Path(), NumFields(), Fields()); + + desc.Clear(); + + for ( int i = 0; i < num_fields; i++ ) + { + if ( i > 0 ) + desc.AddRaw(separator, separator_len); + + if ( ! DoWriteOne(&desc, vals[i], fields[i]) ) + return false; + } + + desc.AddRaw("\n", 1); + + if ( fwrite(desc.Bytes(), desc.Len(), 1, file) != 1 ) + { + Error(Fmt("error writing to %s: %s", fname.c_str(), strerror(errno))); + return false; + } + + if ( IsBuf() ) + fflush(file); + + return true; + } + +bool Ascii::DoRotate(string rotated_path, double open, double close, bool terminating) + { + // Don't rotate special files or if there's not one currently open. + if ( ! file || IsSpecial(Path()) ) + return true; + + fclose(file); + file = 0; + + string nname = rotated_path + "." + LogExt(); + rename(fname.c_str(), nname.c_str()); + + if ( ! FinishedRotation(nname, fname, open, close, terminating) ) + { + Error(Fmt("error rotating %s to %s", fname.c_str(), nname.c_str())); + return false; + } + + return true; + } + +bool Ascii::DoSetBuf(bool enabled) + { + // Nothing to do. + return true; + } + +string Ascii::LogExt() + { + const char* ext = getenv("BRO_LOG_SUFFIX"); + if ( ! ext ) ext = "log"; + return ext; + } diff --git a/src/logging/writers/Ascii.h b/src/logging/writers/Ascii.h new file mode 100644 index 0000000000..6f507aff01 --- /dev/null +++ b/src/logging/writers/Ascii.h @@ -0,0 +1,65 @@ +// See the file "COPYING" in the main distribution directory for copyright. +// +// Log writer for delimiter-separated ASCII logs. + +#ifndef LOGGING_WRITER_ASCII_H +#define LOGGING_WRITER_ASCII_H + +#include "../WriterBackend.h" + +namespace logging { namespace writer { + +class Ascii : public WriterBackend { +public: + Ascii(WriterFrontend* frontend); + ~Ascii(); + + static WriterBackend* Instantiate(WriterFrontend* frontend) + { return new Ascii(frontend); } + static string LogExt(); + +protected: + virtual bool DoInit(string path, int num_fields, + const threading::Field* const* fields); + virtual bool DoWrite(int num_fields, const threading::Field* const* fields, + threading::Value** vals); + virtual bool DoSetBuf(bool enabled); + virtual bool DoRotate(string rotated_path, double open, + double close, bool terminating); + virtual bool DoFlush(); + virtual bool DoFinish(); + +private: + bool IsSpecial(string path) { return path.find("/dev/") == 0; } + bool DoWriteOne(ODesc* desc, threading::Value* val, const threading::Field* field); + bool WriteHeaderField(const string& key, const string& value); + + FILE* file; + string fname; + ODesc desc; + + // Options set from the script-level. + bool output_to_stdout; + bool include_header; + + char* separator; + int separator_len; + + char* set_separator; + int set_separator_len; + + char* empty_field; + int empty_field_len; + + char* unset_field; + int unset_field_len; + + char* header_prefix; + int header_prefix_len; +}; + +} +} + + +#endif diff --git a/src/logging/writers/None.cc b/src/logging/writers/None.cc new file mode 100644 index 0000000000..a9a7872f85 --- /dev/null +++ b/src/logging/writers/None.cc @@ -0,0 +1,18 @@ + +#include "None.h" + +using namespace logging; +using namespace writer; + +bool None::DoRotate(string rotated_path, double open, double close, bool terminating) + { + if ( ! FinishedRotation(string("/dev/null"), Path(), open, close, terminating)) + { + Error(Fmt("error rotating %s", Path().c_str())); + return false; + } + + return true; + } + + diff --git a/src/logging/writers/None.h b/src/logging/writers/None.h new file mode 100644 index 0000000000..cce48953d1 --- /dev/null +++ b/src/logging/writers/None.h @@ -0,0 +1,36 @@ +// See the file "COPYING" in the main distribution directory for copyright. +// +// Dummy log writer that just discards everything (but still pretends to rotate). + +#ifndef LOGGING_WRITER_NONE_H +#define LOGGING_WRITER_NONE_H + +#include "../WriterBackend.h" + +namespace logging { namespace writer { + +class None : public WriterBackend { +public: + None(WriterFrontend* frontend) : WriterBackend(frontend) {} + ~None() {}; + + static WriterBackend* Instantiate(WriterFrontend* frontend) + { return new None(frontend); } + +protected: + virtual bool DoInit(string path, int num_fields, + const threading::Field* const * fields) { return true; } + + virtual bool DoWrite(int num_fields, const threading::Field* const* fields, + threading::Value** vals) { return true; } + virtual bool DoSetBuf(bool enabled) { return true; } + virtual bool DoRotate(string rotated_path, double open, + double close, bool terminating); + virtual bool DoFlush() { return true; } + virtual bool DoFinish() { return true; } +}; + +} +} + +#endif diff --git a/src/main.cc b/src/main.cc index 100305d811..ff33a3859d 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1,5 +1,3 @@ -// $Id: main.cc 6829 2009-07-09 09:12:59Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -31,7 +29,6 @@ extern "C" void OPENSSL_add_all_algorithms_conf(void); #include "Event.h" #include "File.h" #include "Reporter.h" -#include "LogMgr.h" #include "Net.h" #include "NetVar.h" #include "Var.h" @@ -46,12 +43,18 @@ extern "C" void OPENSSL_add_all_algorithms_conf(void); #include "PersistenceSerializer.h" #include "EventRegistry.h" #include "Stats.h" -#include "ConnCompressor.h" #include "DPM.h" #include "BroDoc.h" +#include "Brofiler.h" + +#include "threading/Manager.h" +#include "logging/Manager.h" +#include "logging/writers/Ascii.h" #include "binpac_bro.h" +Brofiler brofiler; + #ifndef HAVE_STRSEP extern "C" { char* strsep(char**, const char*); @@ -62,7 +65,7 @@ extern "C" { #include "setsignal.h" }; -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG HeapLeakChecker* heap_checker = 0; int perftools_leaks = 0; int perftools_profile = 0; @@ -73,7 +76,8 @@ char* writefile = 0; name_list prefixes; DNS_Mgr* dns_mgr; TimerMgr* timer_mgr; -LogMgr* log_mgr; +logging::Manager* log_mgr = 0; +threading::Manager* thread_mgr = 0; Stmt* stmts; EventHandlerPtr net_done = 0; RuleMatcher* rule_matcher = 0; @@ -93,11 +97,11 @@ int do_notice_analysis = 0; int rule_bench = 0; int generate_documentation = 0; SecondaryPath* secondary_path = 0; -ConnCompressor* conn_compressor = 0; extern char version[]; char* command_line_policy = 0; vector params; char* proc_status_file = 0; +int snaplen = 0; // this gets set from the scripting-layer's value int FLAGS_use_binpac = false; @@ -145,7 +149,6 @@ void usage() fprintf(stderr, " -g|--dump-config | dump current config into .state dir\n"); fprintf(stderr, " -h|--help|-? | command line help\n"); fprintf(stderr, " -i|--iface | read from given interface\n"); - fprintf(stderr, " -Z|--doc-scripts | generate documentation for all loaded scripts\n"); fprintf(stderr, " -p|--prefix | add given prefix to policy file resolution\n"); fprintf(stderr, " -r|--readfile | read from given tcpdump file\n"); fprintf(stderr, " -y|--flowfile [=] | read from given flow file\n"); @@ -172,8 +175,9 @@ void usage() fprintf(stderr, " -T|--re-level | set 'RE_level' for rules\n"); fprintf(stderr, " -U|--status-file | Record process status in file\n"); fprintf(stderr, " -W|--watchdog | activate watchdog timer\n"); + fprintf(stderr, " -Z|--doc-scripts | generate documentation for all loaded scripts\n"); -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG fprintf(stderr, " -m|--mem-leaks | show leaks [perftools]\n"); fprintf(stderr, " -M|--mem-profile | record heap [perftools]\n"); #endif @@ -194,6 +198,8 @@ void usage() fprintf(stderr, " $BRO_PREFIXES | prefix list (%s)\n", bro_prefixes()); fprintf(stderr, " $BRO_DNS_FAKE | disable DNS lookups (%s)\n", bro_dns_fake()); fprintf(stderr, " $BRO_SEED_FILE | file to load seeds from (not set)\n"); + fprintf(stderr, " $BRO_LOG_SUFFIX | ASCII log file extension (.%s)\n", logging::writer::Ascii::LogExt().c_str()); + fprintf(stderr, " $BRO_PROFILER_FILE | Output file for script execution statistics (not set)\n"); exit(1); } @@ -229,6 +235,8 @@ void done_with_network() dpm->Done(); timer_mgr->Expire(); + dns_mgr->Flush(); + mgr.Drain(); mgr.Drain(); if ( remote_serializer ) @@ -236,7 +244,7 @@ void done_with_network() net_finish(1); -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG if ( perftools_profile ) { @@ -258,6 +266,8 @@ void terminate_bro() terminating = true; + brofiler.WriteStats(); + EventHandlerPtr bro_done = internal_handler("bro_done"); if ( bro_done ) mgr.QueueEvent(bro_done, new val_list); @@ -278,6 +288,9 @@ void terminate_bro() if ( remote_serializer ) remote_serializer->LogStats(); + log_mgr->Terminate(); + thread_mgr->Terminate(); + delete timer_mgr; delete dns_mgr; delete persistence_serializer; @@ -286,10 +299,10 @@ void terminate_bro() delete state_serializer; delete event_registry; delete secondary_path; - delete conn_compressor; delete remote_serializer; delete dpm; delete log_mgr; + delete thread_mgr; delete reporter; } @@ -318,6 +331,13 @@ RETSIGTYPE sig_handler(int signo) { set_processing_status("TERMINATING", "sig_handler"); signal_val = signo; + + if ( thread_mgr->Terminating() && (signal_val == SIGTERM || signal_val == SIGINT) ) + // If the thread manager is already terminating (i.e., + // waiting for child threads to exit), another term signal + // will send the threads a kill. + thread_mgr->KillThreads(); + return RETSIGVAL; } @@ -333,6 +353,8 @@ static void bro_new_handler() int main(int argc, char** argv) { + brofiler.ReadStats(); + bro_argc = argc; bro_argv = new char* [argc]; @@ -350,6 +372,7 @@ int main(int argc, char** argv) char* seed_load_file = getenv("BRO_SEED_FILE"); char* seed_save_file = 0; char* user_pcap_filter = 0; + char* debug_streams = 0; int bare_mode = false; int seed = 0; int dump_cfg = false; @@ -367,7 +390,6 @@ int main(int argc, char** argv) {"filter", required_argument, 0, 'f'}, {"help", no_argument, 0, 'h'}, {"iface", required_argument, 0, 'i'}, - {"print-scripts", no_argument, 0, 'l'}, {"doc-scripts", no_argument, 0, 'Z'}, {"prefix", required_argument, 0, 'p'}, {"readfile", required_argument, 0, 'r'}, @@ -402,7 +424,7 @@ int main(int argc, char** argv) #ifdef USE_IDMEF {"idmef-dtd", required_argument, 0, 'n'}, #endif -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG {"mem-leaks", no_argument, 0, 'm'}, {"mem-profile", no_argument, 0, 'M'}, #endif @@ -441,10 +463,10 @@ int main(int argc, char** argv) opterr = 0; char opts[256]; - safe_strncpy(opts, "B:D:e:f:I:i:K:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGLOPSWbdghvZ", + safe_strncpy(opts, "B:D:e:f:I:i:K:l:n:p:R:r:s:T:t:U:w:x:X:y:Y:z:CFGLOPSWbdghvZ", sizeof(opts)); -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG strncat(opts, "mM", 2); #endif @@ -454,7 +476,7 @@ int main(int argc, char** argv) case 'b': bare_mode = true; break; - + case 'd': fprintf(stderr, "Policy file debugging ON.\n"); g_policy_debug = true; @@ -600,7 +622,7 @@ int main(int argc, char** argv) exit(0); break; -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG case 'm': perftools_leaks = 1; break; @@ -632,9 +654,7 @@ int main(int argc, char** argv) #endif case 'B': -#ifdef DEBUG - debug_logger.EnableStreams(optarg); -#endif + debug_streams = optarg; break; case 0: @@ -652,7 +672,14 @@ int main(int argc, char** argv) set_processing_status("INITIALIZING", "main"); bro_start_time = current_time(true); + reporter = new Reporter(); + thread_mgr = new threading::Manager(); + +#ifdef DEBUG + if ( debug_streams ) + debug_logger.EnableStreams(debug_streams); +#endif init_random_seed(seed, (seed_load_file && *seed_load_file ? seed_load_file : 0) , seed_save_file); // DEBUG_MSG("HMAC key: %s\n", md5_digest_print(shared_hmac_md5_key)); @@ -713,7 +740,7 @@ int main(int argc, char** argv) persistence_serializer = new PersistenceSerializer(); remote_serializer = new RemoteSerializer(); event_registry = new EventRegistry(); - log_mgr = new LogMgr(); + log_mgr = new logging::Manager(); if ( events_file ) event_player = new EventPlayer(events_file); @@ -731,14 +758,14 @@ int main(int argc, char** argv) // nevertheless reported; see perftools docs), thus // we suppress some messages here. -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG { HeapLeakChecker::Disabler disabler; #endif yyparse(); -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG } #endif @@ -799,8 +826,6 @@ int main(int argc, char** argv) delete [] script_rule_files; - conn_compressor = new ConnCompressor(); - if ( g_policy_debug ) // ### Add support for debug command file. dbg_init_debugger(0); @@ -821,12 +846,14 @@ int main(int argc, char** argv) } } + snaplen = internal_val("snaplen")->AsCount(); + // Initialize the secondary path, if it's needed. secondary_path = new SecondaryPath(); if ( dns_type != DNS_PRIME ) net_init(interfaces, read_files, netflows, flow_files, - writefile, "tcp or udp or icmp", + writefile, "", secondary_path->Filter(), do_watchdog); BroFile::SetDefaultRotation(log_rotate_interval, log_max_size); @@ -932,9 +959,8 @@ int main(int argc, char** argv) if ( dead_handlers->length() > 0 && check_for_unused_event_handlers ) { - reporter->Warning("event handlers never invoked:"); for ( int i = 0; i < dead_handlers->length(); ++i ) - reporter->Warning("\t", (*dead_handlers)[i]); + reporter->Warning("event handler never invoked: %s", (*dead_handlers)[i]); } delete dead_handlers; @@ -946,7 +972,7 @@ int main(int argc, char** argv) { reporter->Info("invoked event handlers:"); for ( int i = 0; i < alive_handlers->length(); ++i ) - reporter->Info((*alive_handlers)[i]); + reporter->Info("%s", (*alive_handlers)[i]); } delete alive_handlers; @@ -986,12 +1012,14 @@ int main(int argc, char** argv) have_pending_timers = ! reading_traces && timer_mgr->Size() > 0; + io_sources.Register(thread_mgr, true); + if ( io_sources.Size() > 0 || have_pending_timers ) { if ( profiling_logger ) profiling_logger->Log(); -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG if ( perftools_leaks ) heap_checker = new HeapLeakChecker("net_run"); diff --git a/src/make_dbg_constants.pl b/src/make_dbg_constants.pl index d4781dccf6..29efac8050 100644 --- a/src/make_dbg_constants.pl +++ b/src/make_dbg_constants.pl @@ -1,5 +1,3 @@ -# $Id: make_dbg_constants.pl 80 2004-07-14 20:15:50Z jason $ -# # Build the DebugCmdConstants.h and DebugCmdInfoConstants.h files from the # DebugCmdInfoConstants.in file. # diff --git a/src/malloc.c b/src/malloc.c deleted file mode 100644 index 809e19aa4e..0000000000 --- a/src/malloc.c +++ /dev/null @@ -1,5061 +0,0 @@ -/* - This is a version (aka dlmalloc) of malloc/free/realloc written by - Doug Lea and released to the public domain, as explained at - http://creativecommons.org/licenses/publicdomain. Send questions, - comments, complaints, performance data, etc to dl@cs.oswego.edu - -* Version 2.8.3 Thu Sep 22 11:16:15 2005 Doug Lea (dl at gee) - - Note: There may be an updated version of this malloc obtainable at - ftp://gee.cs.oswego.edu/pub/misc/malloc.c - Check before installing! - -* Quickstart - - This library is all in one file to simplify the most common usage: - ftp it, compile it (-O3), and link it into another program. All of - the compile-time options default to reasonable values for use on - most platforms. You might later want to step through various - compile-time and dynamic tuning options. - - For convenience, an include file for code using this malloc is at: - ftp://gee.cs.oswego.edu/pub/misc/malloc-2.8.3.h - You don't really need this .h file unless you call functions not - defined in your system include files. The .h file contains only the - excerpts from this file needed for using this malloc on ANSI C/C++ - systems, so long as you haven't changed compile-time options about - naming and tuning parameters. If you do, then you can create your - own malloc.h that does include all settings by cutting at the point - indicated below. Note that you may already by default be using a C - library containing a malloc that is based on some version of this - malloc (for example in linux). You might still want to use the one - in this file to customize settings or to avoid overheads associated - with library versions. - -* Vital statistics: - - Supported pointer/size_t representation: 4 or 8 bytes - size_t MUST be an unsigned type of the same width as - pointers. (If you are using an ancient system that declares - size_t as a signed type, or need it to be a different width - than pointers, you can use a previous release of this malloc - (e.g. 2.7.2) supporting these.) - - Alignment: 8 bytes (default) - This suffices for nearly all current machines and C compilers. - However, you can define MALLOC_ALIGNMENT to be wider than this - if necessary (up to 128bytes), at the expense of using more space. - - Minimum overhead per allocated chunk: 4 or 8 bytes (if 4byte sizes) - 8 or 16 bytes (if 8byte sizes) - Each malloced chunk has a hidden word of overhead holding size - and status information, and additional cross-check word - if FOOTERS is defined. - - Minimum allocated size: 4-byte ptrs: 16 bytes (including overhead) - 8-byte ptrs: 32 bytes (including overhead) - - Even a request for zero bytes (i.e., malloc(0)) returns a - pointer to something of the minimum allocatable size. - The maximum overhead wastage (i.e., number of extra bytes - allocated than were requested in malloc) is less than or equal - to the minimum size, except for requests >= mmap_threshold that - are serviced via mmap(), where the worst case wastage is about - 32 bytes plus the remainder from a system page (the minimal - mmap unit); typically 4096 or 8192 bytes. - - Security: static-safe; optionally more or less - The "security" of malloc refers to the ability of malicious - code to accentuate the effects of errors (for example, freeing - space that is not currently malloc'ed or overwriting past the - ends of chunks) in code that calls malloc. This malloc - guarantees not to modify any memory locations below the base of - heap, i.e., static variables, even in the presence of usage - errors. The routines additionally detect most improper frees - and reallocs. All this holds as long as the static bookkeeping - for malloc itself is not corrupted by some other means. This - is only one aspect of security -- these checks do not, and - cannot, detect all possible programming errors. - - If FOOTERS is defined nonzero, then each allocated chunk - carries an additional check word to verify that it was malloced - from its space. These check words are the same within each - execution of a program using malloc, but differ across - executions, so externally crafted fake chunks cannot be - freed. This improves security by rejecting frees/reallocs that - could corrupt heap memory, in addition to the checks preventing - writes to statics that are always on. This may further improve - security at the expense of time and space overhead. (Note that - FOOTERS may also be worth using with MSPACES.) - - By default detected errors cause the program to abort (calling - "abort()"). You can override this to instead proceed past - errors by defining PROCEED_ON_ERROR. In this case, a bad free - has no effect, and a malloc that encounters a bad address - caused by user overwrites will ignore the bad address by - dropping pointers and indices to all known memory. This may - be appropriate for programs that should continue if at all - possible in the face of programming errors, although they may - run out of memory because dropped memory is never reclaimed. - - If you don't like either of these options, you can define - CORRUPTION_ERROR_ACTION and USAGE_ERROR_ACTION to do anything - else. And if if you are sure that your program using malloc has - no errors or vulnerabilities, you can define INSECURE to 1, - which might (or might not) provide a small performance improvement. - - Thread-safety: NOT thread-safe unless USE_LOCKS defined - When USE_LOCKS is defined, each public call to malloc, free, - etc is surrounded with either a pthread mutex or a win32 - spinlock (depending on WIN32). This is not especially fast, and - can be a major bottleneck. It is designed only to provide - minimal protection in concurrent environments, and to provide a - basis for extensions. If you are using malloc in a concurrent - program, consider instead using ptmalloc, which is derived from - a version of this malloc. (See http://www.malloc.de). - - System requirements: Any combination of MORECORE and/or MMAP/MUNMAP - This malloc can use unix sbrk or any emulation (invoked using - the CALL_MORECORE macro) and/or mmap/munmap or any emulation - (invoked using CALL_MMAP/CALL_MUNMAP) to get and release system - memory. On most unix systems, it tends to work best if both - MORECORE and MMAP are enabled. On Win32, it uses emulations - based on VirtualAlloc. It also uses common C library functions - like memset. - - Compliance: I believe it is compliant with the Single Unix Specification - (See http://www.unix.org). Also SVID/XPG, ANSI C, and probably - others as well. - -* Overview of algorithms - - This is not the fastest, most space-conserving, most portable, or - most tunable malloc ever written. However it is among the fastest - while also being among the most space-conserving, portable and - tunable. Consistent balance across these factors results in a good - general-purpose allocator for malloc-intensive programs. - - In most ways, this malloc is a best-fit allocator. Generally, it - chooses the best-fitting existing chunk for a request, with ties - broken in approximately least-recently-used order. (This strategy - normally maintains low fragmentation.) However, for requests less - than 256bytes, it deviates from best-fit when there is not an - exactly fitting available chunk by preferring to use space adjacent - to that used for the previous small request, as well as by breaking - ties in approximately most-recently-used order. (These enhance - locality of series of small allocations.) And for very large requests - (>= 256Kb by default), it relies on system memory mapping - facilities, if supported. (This helps avoid carrying around and - possibly fragmenting memory used only for large chunks.) - - All operations (except malloc_stats and mallinfo) have execution - times that are bounded by a constant factor of the number of bits in - a size_t, not counting any clearing in calloc or copying in realloc, - or actions surrounding MORECORE and MMAP that have times - proportional to the number of non-contiguous regions returned by - system allocation routines, which is often just 1. - - The implementation is not very modular and seriously overuses - macros. Perhaps someday all C compilers will do as good a job - inlining modular code as can now be done by brute-force expansion, - but now, enough of them seem not to. - - Some compilers issue a lot of warnings about code that is - dead/unreachable only on some platforms, and also about intentional - uses of negation on unsigned types. All known cases of each can be - ignored. - - For a longer but out of date high-level description, see - http://gee.cs.oswego.edu/dl/html/malloc.html - -* MSPACES - If MSPACES is defined, then in addition to malloc, free, etc., - this file also defines mspace_malloc, mspace_free, etc. These - are versions of malloc routines that take an "mspace" argument - obtained using create_mspace, to control all internal bookkeeping. - If ONLY_MSPACES is defined, only these versions are compiled. - So if you would like to use this allocator for only some allocations, - and your system malloc for others, you can compile with - ONLY_MSPACES and then do something like... - static mspace mymspace = create_mspace(0,0); // for example - #define mymalloc(bytes) mspace_malloc(mymspace, bytes) - - (Note: If you only need one instance of an mspace, you can instead - use "USE_DL_PREFIX" to relabel the global malloc.) - - You can similarly create thread-local allocators by storing - mspaces as thread-locals. For example: - static __thread mspace tlms = 0; - void* tlmalloc(size_t bytes) { - if (tlms == 0) tlms = create_mspace(0, 0); - return mspace_malloc(tlms, bytes); - } - void tlfree(void* mem) { mspace_free(tlms, mem); } - - Unless FOOTERS is defined, each mspace is completely independent. - You cannot allocate from one and free to another (although - conformance is only weakly checked, so usage errors are not always - caught). If FOOTERS is defined, then each chunk carries around a tag - indicating its originating mspace, and frees are directed to their - originating spaces. - - ------------------------- Compile-time options --------------------------- - -Be careful in setting #define values for numerical constants of type -size_t. On some systems, literal values are not automatically extended -to size_t precision unless they are explicitly casted. - -WIN32 default: defined if _WIN32 defined - Defining WIN32 sets up defaults for MS environment and compilers. - Otherwise defaults are for unix. - -MALLOC_ALIGNMENT default: (size_t)8 - Controls the minimum alignment for malloc'ed chunks. It must be a - power of two and at least 8, even on machines for which smaller - alignments would suffice. It may be defined as larger than this - though. Note however that code and data structures are optimized for - the case of 8-byte alignment. - -MSPACES default: 0 (false) - If true, compile in support for independent allocation spaces. - This is only supported if HAVE_MMAP is true. - -ONLY_MSPACES default: 0 (false) - If true, only compile in mspace versions, not regular versions. - -USE_LOCKS default: 0 (false) - Causes each call to each public routine to be surrounded with - pthread or WIN32 mutex lock/unlock. (If set true, this can be - overridden on a per-mspace basis for mspace versions.) - -FOOTERS default: 0 - If true, provide extra checking and dispatching by placing - information in the footers of allocated chunks. This adds - space and time overhead. - -INSECURE default: 0 - If true, omit checks for usage errors and heap space overwrites. - -USE_DL_PREFIX default: NOT defined - Causes compiler to prefix all public routines with the string 'dl'. - This can be useful when you only want to use this malloc in one part - of a program, using your regular system malloc elsewhere. - -ABORT default: defined as abort() - Defines how to abort on failed checks. On most systems, a failed - check cannot die with an "assert" or even print an informative - message, because the underlying print routines in turn call malloc, - which will fail again. Generally, the best policy is to simply call - abort(). It's not very useful to do more than this because many - errors due to overwriting will show up as address faults (null, odd - addresses etc) rather than malloc-triggered checks, so will also - abort. Also, most compilers know that abort() does not return, so - can better optimize code conditionally calling it. - -PROCEED_ON_ERROR default: defined as 0 (false) - Controls whether detected bad addresses cause them to bypassed - rather than aborting. If set, detected bad arguments to free and - realloc are ignored. And all bookkeeping information is zeroed out - upon a detected overwrite of freed heap space, thus losing the - ability to ever return it from malloc again, but enabling the - application to proceed. If PROCEED_ON_ERROR is defined, the - static variable malloc_corruption_error_count is compiled in - and can be examined to see if errors have occurred. This option - generates slower code than the default abort policy. - -DEBUG default: NOT defined - The DEBUG setting is mainly intended for people trying to modify - this code or diagnose problems when porting to new platforms. - However, it may also be able to better isolate user errors than just - using runtime checks. The assertions in the check routines spell - out in more detail the assumptions and invariants underlying the - algorithms. The checking is fairly extensive, and will slow down - execution noticeably. Calling malloc_stats or mallinfo with DEBUG - set will attempt to check every non-mmapped allocated and free chunk - in the course of computing the summaries. - -ABORT_ON_ASSERT_FAILURE default: defined as 1 (true) - Debugging assertion failures can be nearly impossible if your - version of the assert macro causes malloc to be called, which will - lead to a cascade of further failures, blowing the runtime stack. - ABORT_ON_ASSERT_FAILURE cause assertions failures to call abort(), - which will usually make debugging easier. - -MALLOC_FAILURE_ACTION default: sets errno to ENOMEM, or no-op on win32 - The action to take before "return 0" when malloc fails to be able to - return memory because there is none available. - -HAVE_MORECORE default: 1 (true) unless win32 or ONLY_MSPACES - True if this system supports sbrk or an emulation of it. - -MORECORE default: sbrk - The name of the sbrk-style system routine to call to obtain more - memory. See below for guidance on writing custom MORECORE - functions. The type of the argument to sbrk/MORECORE varies across - systems. It cannot be size_t, because it supports negative - arguments, so it is normally the signed type of the same width as - size_t (sometimes declared as "intptr_t"). It doesn't much matter - though. Internally, we only call it with arguments less than half - the max value of a size_t, which should work across all reasonable - possibilities, although sometimes generating compiler warnings. See - near the end of this file for guidelines for creating a custom - version of MORECORE. - -MORECORE_CONTIGUOUS default: 1 (true) - If true, take advantage of fact that consecutive calls to MORECORE - with positive arguments always return contiguous increasing - addresses. This is true of unix sbrk. It does not hurt too much to - set it true anyway, since malloc copes with non-contiguities. - Setting it false when definitely non-contiguous saves time - and possibly wasted space it would take to discover this though. - -MORECORE_CANNOT_TRIM default: NOT defined - True if MORECORE cannot release space back to the system when given - negative arguments. This is generally necessary only if you are - using a hand-crafted MORECORE function that cannot handle negative - arguments. - -HAVE_MMAP default: 1 (true) - True if this system supports mmap or an emulation of it. If so, and - HAVE_MORECORE is not true, MMAP is used for all system - allocation. If set and HAVE_MORECORE is true as well, MMAP is - primarily used to directly allocate very large blocks. It is also - used as a backup strategy in cases where MORECORE fails to provide - space from system. Note: A single call to MUNMAP is assumed to be - able to unmap memory that may have be allocated using multiple calls - to MMAP, so long as they are adjacent. - -HAVE_MREMAP default: 1 on linux, else 0 - If true realloc() uses mremap() to re-allocate large blocks and - extend or shrink allocation spaces. - -MMAP_CLEARS default: 1 on unix - True if mmap clears memory so calloc doesn't need to. This is true - for standard unix mmap using /dev/zero. - -USE_BUILTIN_FFS default: 0 (i.e., not used) - Causes malloc to use the builtin ffs() function to compute indices. - Some compilers may recognize and intrinsify ffs to be faster than the - supplied C version. Also, the case of x86 using gcc is special-cased - to an asm instruction, so is already as fast as it can be, and so - this setting has no effect. (On most x86s, the asm version is only - slightly faster than the C version.) - -malloc_getpagesize default: derive from system includes, or 4096. - The system page size. To the extent possible, this malloc manages - memory from the system in page-size units. This may be (and - usually is) a function rather than a constant. This is ignored - if WIN32, where page size is determined using getSystemInfo during - initialization. - -USE_DEV_RANDOM default: 0 (i.e., not used) - Causes malloc to use /dev/random to initialize secure magic seed for - stamping footers. Otherwise, the current time is used. - -NO_MALLINFO default: 0 - If defined, don't compile "mallinfo". This can be a simple way - of dealing with mismatches between system declarations and - those in this file. - -MALLINFO_FIELD_TYPE default: size_t - The type of the fields in the mallinfo struct. This was originally - defined as "int" in SVID etc, but is more usefully defined as - size_t. The value is used only if HAVE_USR_INCLUDE_MALLOC_H is not set - -REALLOC_ZERO_BYTES_FREES default: not defined - This should be set if a call to realloc with zero bytes should - be the same as a call to free. Some people think it should. Otherwise, - since this malloc returns a unique pointer for malloc(0), so does - realloc(p, 0). - -LACKS_UNISTD_H, LACKS_FCNTL_H, LACKS_SYS_PARAM_H, LACKS_SYS_MMAN_H -LACKS_STRINGS_H, LACKS_STRING_H, LACKS_SYS_TYPES_H, LACKS_ERRNO_H -LACKS_STDLIB_H default: NOT defined unless on WIN32 - Define these if your system does not have these header files. - You might need to manually insert some of the declarations they provide. - -DEFAULT_GRANULARITY default: page size if MORECORE_CONTIGUOUS, - system_info.dwAllocationGranularity in WIN32, - otherwise 64K. - Also settable using mallopt(M_GRANULARITY, x) - The unit for allocating and deallocating memory from the system. On - most systems with contiguous MORECORE, there is no reason to - make this more than a page. However, systems with MMAP tend to - either require or encourage larger granularities. You can increase - this value to prevent system allocation functions to be called so - often, especially if they are slow. The value must be at least one - page and must be a power of two. Setting to 0 causes initialization - to either page size or win32 region size. (Note: In previous - versions of malloc, the equivalent of this option was called - "TOP_PAD") - -DEFAULT_TRIM_THRESHOLD default: 2MB - Also settable using mallopt(M_TRIM_THRESHOLD, x) - The maximum amount of unused top-most memory to keep before - releasing via malloc_trim in free(). Automatic trimming is mainly - useful in long-lived programs using contiguous MORECORE. Because - trimming via sbrk can be slow on some systems, and can sometimes be - wasteful (in cases where programs immediately afterward allocate - more large chunks) the value should be high enough so that your - overall system performance would improve by releasing this much - memory. As a rough guide, you might set to a value close to the - average size of a process (program) running on your system. - Releasing this much memory would allow such a process to run in - memory. Generally, it is worth tuning trim thresholds when a - program undergoes phases where several large chunks are allocated - and released in ways that can reuse each other's storage, perhaps - mixed with phases where there are no such chunks at all. The trim - value must be greater than page size to have any useful effect. To - disable trimming completely, you can set to MAX_SIZE_T. Note that the trick - some people use of mallocing a huge space and then freeing it at - program startup, in an attempt to reserve system memory, doesn't - have the intended effect under automatic trimming, since that memory - will immediately be returned to the system. - -DEFAULT_MMAP_THRESHOLD default: 256K - Also settable using mallopt(M_MMAP_THRESHOLD, x) - The request size threshold for using MMAP to directly service a - request. Requests of at least this size that cannot be allocated - using already-existing space will be serviced via mmap. (If enough - normal freed space already exists it is used instead.) Using mmap - segregates relatively large chunks of memory so that they can be - individually obtained and released from the host system. A request - serviced through mmap is never reused by any other request (at least - not directly; the system may just so happen to remap successive - requests to the same locations). Segregating space in this way has - the benefits that: Mmapped space can always be individually released - back to the system, which helps keep the system level memory demands - of a long-lived program low. Also, mapped memory doesn't become - `locked' between other chunks, as can happen with normally allocated - chunks, which means that even trimming via malloc_trim would not - release them. However, it has the disadvantage that the space - cannot be reclaimed, consolidated, and then used to service later - requests, as happens with normal chunks. The advantages of mmap - nearly always outweigh disadvantages for "large" chunks, but the - value of "large" may vary across systems. The default is an - empirically derived value that works well in most systems. You can - disable mmap by setting to MAX_SIZE_T. - -*/ - -#ifndef WIN32 -#ifdef _WIN32 -#define WIN32 1 -#endif /* _WIN32 */ -#endif /* WIN32 */ -#ifdef WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#define HAVE_MMAP 1 -#define HAVE_MORECORE 0 -#define LACKS_UNISTD_H -#define LACKS_SYS_PARAM_H -#define LACKS_SYS_MMAN_H -#define LACKS_STRING_H -#define LACKS_STRINGS_H -#define LACKS_SYS_TYPES_H -#define LACKS_ERRNO_H -#define MALLOC_FAILURE_ACTION -#define MMAP_CLEARS 0 /* WINCE and some others apparently don't clear */ -#endif /* WIN32 */ - -#if defined(DARWIN) || defined(_DARWIN) -/* Mac OSX docs advise not to use sbrk; it seems better to use mmap */ -#ifndef HAVE_MORECORE -#define HAVE_MORECORE 0 -#define HAVE_MMAP 1 -#endif /* HAVE_MORECORE */ -#endif /* DARWIN */ - -#ifndef LACKS_SYS_TYPES_H -#include /* For size_t */ -#endif /* LACKS_SYS_TYPES_H */ - -/* The maximum possible size_t value has all bits set */ -#define MAX_SIZE_T (~(size_t)0) - -#ifndef ONLY_MSPACES -#define ONLY_MSPACES 0 -#endif /* ONLY_MSPACES */ -#ifndef MSPACES -#if ONLY_MSPACES -#define MSPACES 1 -#else /* ONLY_MSPACES */ -#define MSPACES 0 -#endif /* ONLY_MSPACES */ -#endif /* MSPACES */ -#ifndef MALLOC_ALIGNMENT -#define MALLOC_ALIGNMENT ((size_t)8U) -#endif /* MALLOC_ALIGNMENT */ -#ifndef FOOTERS -#define FOOTERS 0 -#endif /* FOOTERS */ -#ifndef ABORT -#define ABORT abort() -#endif /* ABORT */ -#ifndef ABORT_ON_ASSERT_FAILURE -#define ABORT_ON_ASSERT_FAILURE 1 -#endif /* ABORT_ON_ASSERT_FAILURE */ -#ifndef PROCEED_ON_ERROR -#define PROCEED_ON_ERROR 0 -#endif /* PROCEED_ON_ERROR */ -#ifndef USE_LOCKS -#define USE_LOCKS 0 -#endif /* USE_LOCKS */ -#ifndef INSECURE -#define INSECURE 0 -#endif /* INSECURE */ -#ifndef HAVE_MMAP -#define HAVE_MMAP 1 -#endif /* HAVE_MMAP */ -#ifndef MMAP_CLEARS -#define MMAP_CLEARS 1 -#endif /* MMAP_CLEARS */ -#ifndef HAVE_MREMAP -#ifdef linux -#define HAVE_MREMAP 1 -#else /* linux */ -#define HAVE_MREMAP 0 -#endif /* linux */ -#endif /* HAVE_MREMAP */ -#ifndef MALLOC_FAILURE_ACTION -#define MALLOC_FAILURE_ACTION errno = ENOMEM; -#endif /* MALLOC_FAILURE_ACTION */ -#ifndef HAVE_MORECORE -#if ONLY_MSPACES -#define HAVE_MORECORE 0 -#else /* ONLY_MSPACES */ -#define HAVE_MORECORE 1 -#endif /* ONLY_MSPACES */ -#endif /* HAVE_MORECORE */ -#if !HAVE_MORECORE -#define MORECORE_CONTIGUOUS 0 -#else /* !HAVE_MORECORE */ -#ifndef MORECORE -#define MORECORE sbrk -#endif /* MORECORE */ -#ifndef MORECORE_CONTIGUOUS -#define MORECORE_CONTIGUOUS 1 -#endif /* MORECORE_CONTIGUOUS */ -#endif /* HAVE_MORECORE */ -#ifndef DEFAULT_GRANULARITY -#if MORECORE_CONTIGUOUS -#define DEFAULT_GRANULARITY (0) /* 0 means to compute in init_mparams */ -#else /* MORECORE_CONTIGUOUS */ -#define DEFAULT_GRANULARITY ((size_t)64U * (size_t)1024U) -#endif /* MORECORE_CONTIGUOUS */ -#endif /* DEFAULT_GRANULARITY */ -#ifndef DEFAULT_TRIM_THRESHOLD -#ifndef MORECORE_CANNOT_TRIM -#define DEFAULT_TRIM_THRESHOLD ((size_t)2U * (size_t)1024U * (size_t)1024U) -#else /* MORECORE_CANNOT_TRIM */ -#define DEFAULT_TRIM_THRESHOLD MAX_SIZE_T -#endif /* MORECORE_CANNOT_TRIM */ -#endif /* DEFAULT_TRIM_THRESHOLD */ -#ifndef DEFAULT_MMAP_THRESHOLD -#if HAVE_MMAP -#define DEFAULT_MMAP_THRESHOLD ((size_t)256U * (size_t)1024U) -#else /* HAVE_MMAP */ -#define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T -#endif /* HAVE_MMAP */ -#endif /* DEFAULT_MMAP_THRESHOLD */ -#ifndef USE_BUILTIN_FFS -#define USE_BUILTIN_FFS 0 -#endif /* USE_BUILTIN_FFS */ -#ifndef USE_DEV_RANDOM -#define USE_DEV_RANDOM 0 -#endif /* USE_DEV_RANDOM */ -#ifndef NO_MALLINFO -#define NO_MALLINFO 0 -#endif /* NO_MALLINFO */ -#ifndef MALLINFO_FIELD_TYPE -#define MALLINFO_FIELD_TYPE size_t -#endif /* MALLINFO_FIELD_TYPE */ - -/* - mallopt tuning options. SVID/XPG defines four standard parameter - numbers for mallopt, normally defined in malloc.h. None of these - are used in this malloc, so setting them has no effect. But this - malloc does support the following options. -*/ - -#define M_TRIM_THRESHOLD (-1) -#define M_GRANULARITY (-2) -#define M_MMAP_THRESHOLD (-3) - -/* ------------------------ Mallinfo declarations ------------------------ */ - -#if !NO_MALLINFO -/* - This version of malloc supports the standard SVID/XPG mallinfo - routine that returns a struct containing usage properties and - statistics. It should work on any system that has a - /usr/include/malloc.h defining struct mallinfo. The main - declaration needed is the mallinfo struct that is returned (by-copy) - by mallinfo(). The malloinfo struct contains a bunch of fields that - are not even meaningful in this version of malloc. These fields are - are instead filled by mallinfo() with other numbers that might be of - interest. - - HAVE_USR_INCLUDE_MALLOC_H should be set if you have a - /usr/include/malloc.h file that includes a declaration of struct - mallinfo. If so, it is included; else a compliant version is - declared below. These must be precisely the same for mallinfo() to - work. The original SVID version of this struct, defined on most - systems with mallinfo, declares all fields as ints. But some others - define as unsigned long. If your system defines the fields using a - type of different width than listed here, you MUST #include your - system version and #define HAVE_USR_INCLUDE_MALLOC_H. -*/ - -/* #define HAVE_USR_INCLUDE_MALLOC_H */ - -#ifdef HAVE_USR_INCLUDE_MALLOC_H -#include "/usr/include/malloc.h" -#else /* HAVE_USR_INCLUDE_MALLOC_H */ - -struct mallinfo { - MALLINFO_FIELD_TYPE arena; /* non-mmapped space allocated from system */ - MALLINFO_FIELD_TYPE ordblks; /* number of free chunks */ - MALLINFO_FIELD_TYPE smblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblks; /* always 0 */ - MALLINFO_FIELD_TYPE hblkhd; /* space in mmapped regions */ - MALLINFO_FIELD_TYPE usmblks; /* maximum total allocated space */ - MALLINFO_FIELD_TYPE fsmblks; /* always 0 */ - MALLINFO_FIELD_TYPE uordblks; /* total allocated space */ - MALLINFO_FIELD_TYPE fordblks; /* total free space */ - MALLINFO_FIELD_TYPE keepcost; /* releasable (via malloc_trim) space */ -}; - -#endif /* HAVE_USR_INCLUDE_MALLOC_H */ -#endif /* NO_MALLINFO */ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#if !ONLY_MSPACES - -/* ------------------- Declarations of public routines ------------------- */ - -#ifndef USE_DL_PREFIX -#define dlcalloc calloc -#define dlfree free -#define dlmalloc malloc -#define dlmemalign memalign -#define dlrealloc realloc -#define dlvalloc valloc -#define dlpvalloc pvalloc -#define dlmallinfo mallinfo -#define dlmallopt mallopt -#define dlmalloc_trim malloc_trim -#define dlmalloc_stats malloc_stats -#define dlmalloc_usable_size malloc_usable_size -#define dlmalloc_footprint malloc_footprint -#define dlmalloc_max_footprint malloc_max_footprint -#define dlindependent_calloc independent_calloc -#define dlindependent_comalloc independent_comalloc -#endif /* USE_DL_PREFIX */ - - -/* - malloc(size_t n) - Returns a pointer to a newly allocated chunk of at least n bytes, or - null if no space is available, in which case errno is set to ENOMEM - on ANSI C systems. - - If n is zero, malloc returns a minimum-sized chunk. (The minimum - size is 16 bytes on most 32bit systems, and 32 bytes on 64bit - systems.) Note that size_t is an unsigned type, so calls with - arguments that would be negative if signed are interpreted as - requests for huge amounts of space, which will often fail. The - maximum supported value of n differs across systems, but is in all - cases less than the maximum representable value of a size_t. -*/ -void* dlmalloc(size_t); - -/* - free(void* p) - Releases the chunk of memory pointed to by p, that had been previously - allocated using malloc or a related routine such as realloc. - It has no effect if p is null. If p was not malloced or already - freed, free(p) will by default cause the current program to abort. -*/ -void dlfree(void*); - -/* - calloc(size_t n_elements, size_t element_size); - Returns a pointer to n_elements * element_size bytes, with all locations - set to zero. -*/ -void* dlcalloc(size_t, size_t); - -/* - realloc(void* p, size_t n) - Returns a pointer to a chunk of size n that contains the same data - as does chunk p up to the minimum of (n, p's size) bytes, or null - if no space is available. - - The returned pointer may or may not be the same as p. The algorithm - prefers extending p in most cases when possible, otherwise it - employs the equivalent of a malloc-copy-free sequence. - - If p is null, realloc is equivalent to malloc. - - If space is not available, realloc returns null, errno is set (if on - ANSI) and p is NOT freed. - - if n is for fewer bytes than already held by p, the newly unused - space is lopped off and freed if possible. realloc with a size - argument of zero (re)allocates a minimum-sized chunk. - - The old unix realloc convention of allowing the last-free'd chunk - to be used as an argument to realloc is not supported. -*/ - -void* dlrealloc(void*, size_t); - -/* - memalign(size_t alignment, size_t n); - Returns a pointer to a newly allocated chunk of n bytes, aligned - in accord with the alignment argument. - - The alignment argument should be a power of two. If the argument is - not a power of two, the nearest greater power is used. - 8-byte alignment is guaranteed by normal malloc calls, so don't - bother calling memalign with an argument of 8 or less. - - Overreliance on memalign is a sure way to fragment space. -*/ -void* dlmemalign(size_t, size_t); - -/* - valloc(size_t n); - Equivalent to memalign(pagesize, n), where pagesize is the page - size of the system. If the pagesize is unknown, 4096 is used. -*/ -void* dlvalloc(size_t); - -/* - mallopt(int parameter_number, int parameter_value) - Sets tunable parameters The format is to provide a - (parameter-number, parameter-value) pair. mallopt then sets the - corresponding parameter to the argument value if it can (i.e., so - long as the value is meaningful), and returns 1 if successful else - 0. SVID/XPG/ANSI defines four standard param numbers for mallopt, - normally defined in malloc.h. None of these are use in this malloc, - so setting them has no effect. But this malloc also supports other - options in mallopt. See below for details. Briefly, supported - parameters are as follows (listed defaults are for "typical" - configurations). - - Symbol param # default allowed param values - M_TRIM_THRESHOLD -1 2*1024*1024 any (MAX_SIZE_T disables) - M_GRANULARITY -2 page size any power of 2 >= page size - M_MMAP_THRESHOLD -3 256*1024 any (or 0 if no MMAP support) -*/ -int dlmallopt(int, int); - -/* - malloc_footprint(); - Returns the number of bytes obtained from the system. The total - number of bytes allocated by malloc, realloc etc., is less than this - value. Unlike mallinfo, this function returns only a precomputed - result, so can be called frequently to monitor memory consumption. - Even if locks are otherwise defined, this function does not use them, - so results might not be up to date. -*/ -size_t dlmalloc_footprint(void); - -/* - malloc_max_footprint(); - Returns the maximum number of bytes obtained from the system. This - value will be greater than current footprint if deallocated space - has been reclaimed by the system. The peak number of bytes allocated - by malloc, realloc etc., is less than this value. Unlike mallinfo, - this function returns only a precomputed result, so can be called - frequently to monitor memory consumption. Even if locks are - otherwise defined, this function does not use them, so results might - not be up to date. -*/ -size_t dlmalloc_max_footprint(void); - -#if !NO_MALLINFO -/* - mallinfo() - Returns (by copy) a struct containing various summary statistics: - - arena: current total non-mmapped bytes allocated from system - ordblks: the number of free chunks - smblks: always zero. - hblks: current number of mmapped regions - hblkhd: total bytes held in mmapped regions - usmblks: the maximum total allocated space. This will be greater - than current total if trimming has occurred. - fsmblks: always zero - uordblks: current total allocated space (normal or mmapped) - fordblks: total free space - keepcost: the maximum number of bytes that could ideally be released - back to system via malloc_trim. ("ideally" means that - it ignores page restrictions etc.) - - Because these fields are ints, but internal bookkeeping may - be kept as longs, the reported values may wrap around zero and - thus be inaccurate. -*/ -struct mallinfo dlmallinfo(void); -#endif /* NO_MALLINFO */ - -/* - independent_calloc(size_t n_elements, size_t element_size, void* chunks[]); - - independent_calloc is similar to calloc, but instead of returning a - single cleared space, it returns an array of pointers to n_elements - independent elements that can hold contents of size elem_size, each - of which starts out cleared, and can be independently freed, - realloc'ed etc. The elements are guaranteed to be adjacently - allocated (this is not guaranteed to occur with multiple callocs or - mallocs), which may also improve cache locality in some - applications. - - The "chunks" argument is optional (i.e., may be null, which is - probably the most typical usage). If it is null, the returned array - is itself dynamically allocated and should also be freed when it is - no longer needed. Otherwise, the chunks array must be of at least - n_elements in length. It is filled in with the pointers to the - chunks. - - In either case, independent_calloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and "chunks" - is null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use regular calloc and assign pointers into this - space to represent elements. (In this case though, you cannot - independently free elements.) - - independent_calloc simplifies and speeds up implementations of many - kinds of pools. It may also be useful when constructing large data - structures that initially have a fixed number of fixed-sized nodes, - but the number is not known at compile time, and some of the nodes - may later need to be freed. For example: - - struct Node { int item; struct Node* next; }; - - struct Node* build_list() { - struct Node** pool; - int n = read_number_of_nodes_needed(); - if (n <= 0) return 0; - pool = (struct Node**)(independent_calloc(n, sizeof(struct Node), 0); - if (pool == 0) die(); - // organize into a linked list... - struct Node* first = pool[0]; - for (i = 0; i < n-1; ++i) - pool[i]->next = pool[i+1]; - free(pool); // Can now free the array (or not, if it is needed later) - return first; - } -*/ -void** dlindependent_calloc(size_t, size_t, void**); - -/* - independent_comalloc(size_t n_elements, size_t sizes[], void* chunks[]); - - independent_comalloc allocates, all at once, a set of n_elements - chunks with sizes indicated in the "sizes" array. It returns - an array of pointers to these elements, each of which can be - independently freed, realloc'ed etc. The elements are guaranteed to - be adjacently allocated (this is not guaranteed to occur with - multiple callocs or mallocs), which may also improve cache locality - in some applications. - - The "chunks" argument is optional (i.e., may be null). If it is null - the returned array is itself dynamically allocated and should also - be freed when it is no longer needed. Otherwise, the chunks array - must be of at least n_elements in length. It is filled in with the - pointers to the chunks. - - In either case, independent_comalloc returns this pointer array, or - null if the allocation failed. If n_elements is zero and chunks is - null, it returns a chunk representing an array with zero elements - (which should be freed if not wanted). - - Each element must be individually freed when it is no longer - needed. If you'd like to instead be able to free all at once, you - should instead use a single regular malloc, and assign pointers at - particular offsets in the aggregate space. (In this case though, you - cannot independently free elements.) - - independent_comallac differs from independent_calloc in that each - element may have a different size, and also that it does not - automatically clear elements. - - independent_comalloc can be used to speed up allocation in cases - where several structs or objects must always be allocated at the - same time. For example: - - struct Head { ... } - struct Foot { ... } - - void send_message(char* msg) { - int msglen = strlen(msg); - size_t sizes[3] = { sizeof(struct Head), msglen, sizeof(struct Foot) }; - void* chunks[3]; - if (independent_comalloc(3, sizes, chunks) == 0) - die(); - struct Head* head = (struct Head*)(chunks[0]); - char* body = (char*)(chunks[1]); - struct Foot* foot = (struct Foot*)(chunks[2]); - // ... - } - - In general though, independent_comalloc is worth using only for - larger values of n_elements. For small values, you probably won't - detect enough difference from series of malloc calls to bother. - - Overuse of independent_comalloc can increase overall memory usage, - since it cannot reuse existing noncontiguous small chunks that - might be available for some of the elements. -*/ -void** dlindependent_comalloc(size_t, size_t*, void**); - - -/* - pvalloc(size_t n); - Equivalent to valloc(minimum-page-that-holds(n)), that is, - round up n to nearest pagesize. - */ -void* dlpvalloc(size_t); - -/* - malloc_trim(size_t pad); - - If possible, gives memory back to the system (via negative arguments - to sbrk) if there is unused memory at the `high' end of the malloc - pool or in unused MMAP segments. You can call this after freeing - large blocks of memory to potentially reduce the system-level memory - requirements of a program. However, it cannot guarantee to reduce - memory. Under some allocation patterns, some large free blocks of - memory will be locked between two used chunks, so they cannot be - given back to the system. - - The `pad' argument to malloc_trim represents the amount of free - trailing space to leave untrimmed. If this argument is zero, only - the minimum amount of memory to maintain internal data structures - will be left. Non-zero arguments can be supplied to maintain enough - trailing space to service future expected allocations without having - to re-obtain memory from the system. - - Malloc_trim returns 1 if it actually released any memory, else 0. -*/ -int dlmalloc_trim(size_t); - -/* - malloc_usable_size(void* p); - - Returns the number of bytes you can actually use in - an allocated chunk, which may be more than you requested (although - often not) due to alignment and minimum size constraints. - You can use this many bytes without worrying about - overwriting other allocated objects. This is not a particularly great - programming practice. malloc_usable_size can be more useful in - debugging and assertions, for example: - - p = malloc(n); - assert(malloc_usable_size(p) >= 256); -*/ -size_t dlmalloc_usable_size(void*); - -/* - malloc_stats(); - Prints on stderr the amount of space obtained from the system (both - via sbrk and mmap), the maximum amount (which may be more than - current if malloc_trim and/or munmap got called), and the current - number of bytes allocated via malloc (or realloc, etc) but not yet - freed. Note that this is the number of bytes allocated, not the - number requested. It will be larger than the number requested - because of alignment and bookkeeping overhead. Because it includes - alignment wastage as being in use, this figure may be greater than - zero even when no user-level chunks are allocated. - - The reported current and maximum system memory can be inaccurate if - a program makes other calls to system memory allocation functions - (normally sbrk) outside of malloc. - - malloc_stats prints only the most commonly interesting statistics. - More information can be obtained by calling mallinfo. -*/ -void dlmalloc_stats(void); - -#endif /* ONLY_MSPACES */ - -#if MSPACES - -/* - mspace is an opaque type representing an independent - region of space that supports mspace_malloc, etc. -*/ -typedef void* mspace; - -/* - create_mspace creates and returns a new independent space with the - given initial capacity, or, if 0, the default granularity size. It - returns null if there is no system memory available to create the - space. If argument locked is non-zero, the space uses a separate - lock to control access. The capacity of the space will grow - dynamically as needed to service mspace_malloc requests. You can - control the sizes of incremental increases of this space by - compiling with a different DEFAULT_GRANULARITY or dynamically - setting with mallopt(M_GRANULARITY, value). -*/ -mspace create_mspace(size_t capacity, int locked); - -/* - destroy_mspace destroys the given space, and attempts to return all - of its memory back to the system, returning the total number of - bytes freed. After destruction, the results of access to all memory - used by the space become undefined. -*/ -size_t destroy_mspace(mspace msp); - -/* - create_mspace_with_base uses the memory supplied as the initial base - of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this - space is used for bookkeeping, so the capacity must be at least this - large. (Otherwise 0 is returned.) When this initial space is - exhausted, additional memory will be obtained from the system. - Destroying this space will deallocate all additionally allocated - space (if possible) but not the initial base. -*/ -mspace create_mspace_with_base(void* base, size_t capacity, int locked); - -/* - mspace_malloc behaves as malloc, but operates within - the given space. -*/ -void* mspace_malloc(mspace msp, size_t bytes); - -/* - mspace_free behaves as free, but operates within - the given space. - - If compiled with FOOTERS==1, mspace_free is not actually needed. - free may be called instead of mspace_free because freed chunks from - any space are handled by their originating spaces. -*/ -void mspace_free(mspace msp, void* mem); - -/* - mspace_realloc behaves as realloc, but operates within - the given space. - - If compiled with FOOTERS==1, mspace_realloc is not actually - needed. realloc may be called instead of mspace_realloc because - realloced chunks from any space are handled by their originating - spaces. -*/ -void* mspace_realloc(mspace msp, void* mem, size_t newsize); - -/* - mspace_calloc behaves as calloc, but operates within - the given space. -*/ -void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size); - -/* - mspace_memalign behaves as memalign, but operates within - the given space. -*/ -void* mspace_memalign(mspace msp, size_t alignment, size_t bytes); - -/* - mspace_independent_calloc behaves as independent_calloc, but - operates within the given space. -*/ -void** mspace_independent_calloc(mspace msp, size_t n_elements, - size_t elem_size, void* chunks[]); - -/* - mspace_independent_comalloc behaves as independent_comalloc, but - operates within the given space. -*/ -void** mspace_independent_comalloc(mspace msp, size_t n_elements, - size_t sizes[], void* chunks[]); - -/* - mspace_footprint() returns the number of bytes obtained from the - system for this space. -*/ -size_t mspace_footprint(mspace msp); - -/* - mspace_max_footprint() returns the peak number of bytes obtained from the - system for this space. -*/ -size_t mspace_max_footprint(mspace msp); - - -#if !NO_MALLINFO -/* - mspace_mallinfo behaves as mallinfo, but reports properties of - the given space. -*/ -struct mallinfo mspace_mallinfo(mspace msp); -#endif /* NO_MALLINFO */ - -/* - mspace_malloc_stats behaves as malloc_stats, but reports - properties of the given space. -*/ -void mspace_malloc_stats(mspace msp); - -/* - mspace_trim behaves as malloc_trim, but - operates within the given space. -*/ -int mspace_trim(mspace msp, size_t pad); - -/* - An alias for mallopt. -*/ -int mspace_mallopt(int, int); - -#endif /* MSPACES */ - -#ifdef __cplusplus -}; /* end of extern "C" */ -#endif /* __cplusplus */ - -/* - ======================================================================== - To make a fully customizable malloc.h header file, cut everything - above this line, put into file malloc.h, edit to suit, and #include it - on the next line, as well as in programs that use this malloc. - ======================================================================== -*/ - -/* #include "malloc.h" */ - -/*------------------------------ internal #includes ---------------------- */ - -#ifdef WIN32 -#pragma warning( disable : 4146 ) /* no "unsigned" warnings */ -#endif /* WIN32 */ - -#include /* for printing in malloc_stats */ - -#ifndef LACKS_ERRNO_H -#include /* for MALLOC_FAILURE_ACTION */ -#endif /* LACKS_ERRNO_H */ -#if FOOTERS -#include /* for magic initialization */ -#endif /* FOOTERS */ -#ifndef LACKS_STDLIB_H -#include /* for abort() */ -#endif /* LACKS_STDLIB_H */ -#ifdef DEBUG -#if ABORT_ON_ASSERT_FAILURE -#define assert(x) if(!(x)) ABORT -#else /* ABORT_ON_ASSERT_FAILURE */ -#include -#endif /* ABORT_ON_ASSERT_FAILURE */ -#else /* DEBUG */ -#define assert(x) -#endif /* DEBUG */ -#ifndef LACKS_STRING_H -#include /* for memset etc */ -#endif /* LACKS_STRING_H */ -#if USE_BUILTIN_FFS -#ifndef LACKS_STRINGS_H -#include /* for ffs */ -#endif /* LACKS_STRINGS_H */ -#endif /* USE_BUILTIN_FFS */ -#if HAVE_MMAP -#ifndef LACKS_SYS_MMAN_H -#include /* for mmap */ -#endif /* LACKS_SYS_MMAN_H */ -#ifndef LACKS_FCNTL_H -#include -#endif /* LACKS_FCNTL_H */ -#endif /* HAVE_MMAP */ -#if HAVE_MORECORE -#ifndef LACKS_UNISTD_H -#include /* for sbrk */ -#else /* LACKS_UNISTD_H */ -#if !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) -extern void* sbrk(ptrdiff_t); -#endif /* FreeBSD etc */ -#endif /* LACKS_UNISTD_H */ -#endif /* HAVE_MMAP */ - -#ifndef WIN32 -#ifndef malloc_getpagesize -# ifdef _SC_PAGESIZE /* some SVR4 systems omit an underscore */ -# ifndef _SC_PAGE_SIZE -# define _SC_PAGE_SIZE _SC_PAGESIZE -# endif -# endif -# ifdef _SC_PAGE_SIZE -# define malloc_getpagesize sysconf(_SC_PAGE_SIZE) -# else -# if defined(BSD) || defined(DGUX) || defined(HAVE_GETPAGESIZE) - extern size_t getpagesize(); -# define malloc_getpagesize getpagesize() -# else -# ifdef WIN32 /* use supplied emulation of getpagesize */ -# define malloc_getpagesize getpagesize() -# else -# ifndef LACKS_SYS_PARAM_H -# include -# endif -# ifdef EXEC_PAGESIZE -# define malloc_getpagesize EXEC_PAGESIZE -# else -# ifdef NBPG -# ifndef CLSIZE -# define malloc_getpagesize NBPG -# else -# define malloc_getpagesize (NBPG * CLSIZE) -# endif -# else -# ifdef NBPC -# define malloc_getpagesize NBPC -# else -# ifdef PAGESIZE -# define malloc_getpagesize PAGESIZE -# else /* just guess */ -# define malloc_getpagesize ((size_t)4096U) -# endif -# endif -# endif -# endif -# endif -# endif -# endif -#endif -#endif - -/* ------------------- size_t and alignment properties -------------------- */ - -/* The byte and bit size of a size_t */ -#define SIZE_T_SIZE (sizeof(size_t)) -#define SIZE_T_BITSIZE (sizeof(size_t) << 3) - -/* Some constants coerced to size_t */ -/* Annoying but necessary to avoid errors on some plaftorms */ -#define SIZE_T_ZERO ((size_t)0) -#define SIZE_T_ONE ((size_t)1) -#define SIZE_T_TWO ((size_t)2) -#define TWO_SIZE_T_SIZES (SIZE_T_SIZE<<1) -#define FOUR_SIZE_T_SIZES (SIZE_T_SIZE<<2) -#define SIX_SIZE_T_SIZES (FOUR_SIZE_T_SIZES+TWO_SIZE_T_SIZES) -#define HALF_MAX_SIZE_T (MAX_SIZE_T / 2U) - -/* The bit mask value corresponding to MALLOC_ALIGNMENT */ -#define CHUNK_ALIGN_MASK (MALLOC_ALIGNMENT - SIZE_T_ONE) - -/* True if address a has acceptable alignment */ -#define is_aligned(A) (((size_t)((A)) & (CHUNK_ALIGN_MASK)) == 0) - -/* the number of bytes to offset an address to align it */ -#define align_offset(A)\ - ((((size_t)(A) & CHUNK_ALIGN_MASK) == 0)? 0 :\ - ((MALLOC_ALIGNMENT - ((size_t)(A) & CHUNK_ALIGN_MASK)) & CHUNK_ALIGN_MASK)) - -/* -------------------------- MMAP preliminaries ------------------------- */ - -/* - If HAVE_MORECORE or HAVE_MMAP are false, we just define calls and - checks to fail so compiler optimizer can delete code rather than - using so many "#if"s. -*/ - - -/* MORECORE and MMAP must return MFAIL on failure */ -#define MFAIL ((void*)(MAX_SIZE_T)) -#define CMFAIL ((char*)(MFAIL)) /* defined for convenience */ - -#if !HAVE_MMAP -#define IS_MMAPPED_BIT (SIZE_T_ZERO) -#define USE_MMAP_BIT (SIZE_T_ZERO) -#define CALL_MMAP(s) MFAIL -#define CALL_MUNMAP(a, s) (-1) -#define DIRECT_MMAP(s) MFAIL - -#else /* HAVE_MMAP */ -#define IS_MMAPPED_BIT (SIZE_T_ONE) -#define USE_MMAP_BIT (SIZE_T_ONE) - -#ifndef WIN32 -#define CALL_MUNMAP(a, s) munmap((a), (s)) -#define MMAP_PROT (PROT_READ|PROT_WRITE) -#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON) -#define MAP_ANONYMOUS MAP_ANON -#endif /* MAP_ANON */ -#ifdef MAP_ANONYMOUS -#define MMAP_FLAGS (MAP_PRIVATE|MAP_ANONYMOUS) -#define CALL_MMAP(s) mmap(0, (s), MMAP_PROT, MMAP_FLAGS, -1, 0) -#else /* MAP_ANONYMOUS */ -/* - Nearly all versions of mmap support MAP_ANONYMOUS, so the following - is unlikely to be needed, but is supplied just in case. -*/ -#define MMAP_FLAGS (MAP_PRIVATE) -static int dev_zero_fd = -1; /* Cached file descriptor for /dev/zero. */ -#define CALL_MMAP(s) ((dev_zero_fd < 0) ? \ - (dev_zero_fd = open("/dev/zero", O_RDWR), \ - mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) : \ - mmap(0, (s), MMAP_PROT, MMAP_FLAGS, dev_zero_fd, 0)) -#endif /* MAP_ANONYMOUS */ - -#define DIRECT_MMAP(s) CALL_MMAP(s) -#else /* WIN32 */ - -/* Win32 MMAP via VirtualAlloc */ -static void* win32mmap(size_t size) { - void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); - return (ptr != 0)? ptr: MFAIL; -} - -/* For direct MMAP, use MEM_TOP_DOWN to minimize interference */ -static void* win32direct_mmap(size_t size) { - void* ptr = VirtualAlloc(0, size, MEM_RESERVE|MEM_COMMIT|MEM_TOP_DOWN, - PAGE_READWRITE); - return (ptr != 0)? ptr: MFAIL; -} - -/* This function supports releasing coalesed segments */ -static int win32munmap(void* ptr, size_t size) { - MEMORY_BASIC_INFORMATION minfo; - char* cptr = ptr; - while (size) { - if (VirtualQuery(cptr, &minfo, sizeof(minfo)) == 0) - return -1; - if (minfo.BaseAddress != cptr || minfo.AllocationBase != cptr || - minfo.State != MEM_COMMIT || minfo.RegionSize > size) - return -1; - if (VirtualFree(cptr, 0, MEM_RELEASE) == 0) - return -1; - cptr += minfo.RegionSize; - size -= minfo.RegionSize; - } - return 0; -} - -#define CALL_MMAP(s) win32mmap(s) -#define CALL_MUNMAP(a, s) win32munmap((a), (s)) -#define DIRECT_MMAP(s) win32direct_mmap(s) -#endif /* WIN32 */ -#endif /* HAVE_MMAP */ - -#if HAVE_MMAP && HAVE_MREMAP -#define CALL_MREMAP(addr, osz, nsz, mv) mremap((addr), (osz), (nsz), (mv)) -#else /* HAVE_MMAP && HAVE_MREMAP */ -#define CALL_MREMAP(addr, osz, nsz, mv) MFAIL -#endif /* HAVE_MMAP && HAVE_MREMAP */ - -#if HAVE_MORECORE -#define CALL_MORECORE(S) MORECORE(S) -#else /* HAVE_MORECORE */ -#define CALL_MORECORE(S) MFAIL -#endif /* HAVE_MORECORE */ - -/* mstate bit set if continguous morecore disabled or failed */ -#define USE_NONCONTIGUOUS_BIT (4U) - -/* segment bit set in create_mspace_with_base */ -#define EXTERN_BIT (8U) - - -/* --------------------------- Lock preliminaries ------------------------ */ - -#if USE_LOCKS - -/* - When locks are defined, there are up to two global locks: - - * If HAVE_MORECORE, morecore_mutex protects sequences of calls to - MORECORE. In many cases sys_alloc requires two calls, that should - not be interleaved with calls by other threads. This does not - protect against direct calls to MORECORE by other threads not - using this lock, so there is still code to cope the best we can on - interference. - - * magic_init_mutex ensures that mparams.magic and other - unique mparams values are initialized only once. -*/ - -#ifndef WIN32 -/* By default use posix locks */ -#include -#define MLOCK_T pthread_mutex_t -#define INITIAL_LOCK(l) pthread_mutex_init(l, NULL) -#define ACQUIRE_LOCK(l) pthread_mutex_lock(l) -#define RELEASE_LOCK(l) pthread_mutex_unlock(l) - -#if HAVE_MORECORE -static MLOCK_T morecore_mutex = PTHREAD_MUTEX_INITIALIZER; -#endif /* HAVE_MORECORE */ - -static MLOCK_T magic_init_mutex = PTHREAD_MUTEX_INITIALIZER; - -#else /* WIN32 */ -/* - Because lock-protected regions have bounded times, and there - are no recursive lock calls, we can use simple spinlocks. -*/ - -#define MLOCK_T long -static int win32_acquire_lock (MLOCK_T *sl) { - for (;;) { -#ifdef InterlockedCompareExchangePointer - if (!InterlockedCompareExchange(sl, 1, 0)) - return 0; -#else /* Use older void* version */ - if (!InterlockedCompareExchange((void**)sl, (void*)1, (void*)0)) - return 0; -#endif /* InterlockedCompareExchangePointer */ - Sleep (0); - } -} - -static void win32_release_lock (MLOCK_T *sl) { - InterlockedExchange (sl, 0); -} - -#define INITIAL_LOCK(l) *(l)=0 -#define ACQUIRE_LOCK(l) win32_acquire_lock(l) -#define RELEASE_LOCK(l) win32_release_lock(l) -#if HAVE_MORECORE -static MLOCK_T morecore_mutex; -#endif /* HAVE_MORECORE */ -static MLOCK_T magic_init_mutex; -#endif /* WIN32 */ - -#define USE_LOCK_BIT (2U) -#else /* USE_LOCKS */ -#define USE_LOCK_BIT (0U) -#define INITIAL_LOCK(l) -#endif /* USE_LOCKS */ - -#if USE_LOCKS && HAVE_MORECORE -#define ACQUIRE_MORECORE_LOCK() ACQUIRE_LOCK(&morecore_mutex); -#define RELEASE_MORECORE_LOCK() RELEASE_LOCK(&morecore_mutex); -#else /* USE_LOCKS && HAVE_MORECORE */ -#define ACQUIRE_MORECORE_LOCK() -#define RELEASE_MORECORE_LOCK() -#endif /* USE_LOCKS && HAVE_MORECORE */ - -#if USE_LOCKS -#define ACQUIRE_MAGIC_INIT_LOCK() ACQUIRE_LOCK(&magic_init_mutex); -#define RELEASE_MAGIC_INIT_LOCK() RELEASE_LOCK(&magic_init_mutex); -#else /* USE_LOCKS */ -#define ACQUIRE_MAGIC_INIT_LOCK() -#define RELEASE_MAGIC_INIT_LOCK() -#endif /* USE_LOCKS */ - - -/* ----------------------- Chunk representations ------------------------ */ - -/* - (The following includes lightly edited explanations by Colin Plumb.) - - The malloc_chunk declaration below is misleading (but accurate and - necessary). It declares a "view" into memory allowing access to - necessary fields at known offsets from a given base. - - Chunks of memory are maintained using a `boundary tag' method as - originally described by Knuth. (See the paper by Paul Wilson - ftp://ftp.cs.utexas.edu/pub/garbage/allocsrv.ps for a survey of such - techniques.) Sizes of free chunks are stored both in the front of - each chunk and at the end. This makes consolidating fragmented - chunks into bigger chunks fast. The head fields also hold bits - representing whether chunks are free or in use. - - Here are some pictures to make it clearer. They are "exploded" to - show that the state of a chunk can be thought of as extending from - the high 31 bits of the head field of its header through the - prev_foot and PINUSE_BIT bit of the following chunk header. - - A chunk that's in use looks like: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk (if P = 1) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| - | Size of this chunk 1| +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | | - +- -+ - | | - +- -+ - | : - +- size - sizeof(size_t) available payload bytes -+ - : | - chunk-> +- -+ - | | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |1| - | Size of next chunk (may or may not be in use) | +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - And if it's free, it looks like this: - - chunk-> +- -+ - | User payload (must be in use, or we would have merged!) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |P| - | Size of this chunk 0| +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Next pointer | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Prev pointer | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | : - +- size - sizeof(struct chunk) unused bytes -+ - : | - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of this chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |0| - | Size of next chunk (must be in use, or we would have merged)| +-+ - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | : - +- User payload -+ - : | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - |0| - +-+ - Note that since we always merge adjacent free chunks, the chunks - adjacent to a free chunk must be in use. - - Given a pointer to a chunk (which can be derived trivially from the - payload pointer) we can, in O(1) time, find out whether the adjacent - chunks are free, and if so, unlink them from the lists that they - are on and merge them with the current chunk. - - Chunks always begin on even word boundaries, so the mem portion - (which is returned to the user) is also on an even word boundary, and - thus at least double-word aligned. - - The P (PINUSE_BIT) bit, stored in the unused low-order bit of the - chunk size (which is always a multiple of two words), is an in-use - bit for the *previous* chunk. If that bit is *clear*, then the - word before the current chunk size contains the previous chunk - size, and can be used to find the front of the previous chunk. - The very first chunk allocated always has this bit set, preventing - access to non-existent (or non-owned) memory. If pinuse is set for - any given chunk, then you CANNOT determine the size of the - previous chunk, and might even get a memory addressing fault when - trying to do so. - - The C (CINUSE_BIT) bit, stored in the unused second-lowest bit of - the chunk size redundantly records whether the current chunk is - inuse. This redundancy enables usage checks within free and realloc, - and reduces indirection when freeing and consolidating chunks. - - Each freshly allocated chunk must have both cinuse and pinuse set. - That is, each allocated chunk borders either a previously allocated - and still in-use chunk, or the base of its memory arena. This is - ensured by making all allocations from the the `lowest' part of any - found chunk. Further, no free chunk physically borders another one, - so each free chunk is known to be preceded and followed by either - inuse chunks or the ends of memory. - - Note that the `foot' of the current chunk is actually represented - as the prev_foot of the NEXT chunk. This makes it easier to - deal with alignments etc but can be very confusing when trying - to extend or adapt this code. - - The exceptions to all this are - - 1. The special chunk `top' is the top-most available chunk (i.e., - the one bordering the end of available memory). It is treated - specially. Top is never included in any bin, is used only if - no other chunk is available, and is released back to the - system if it is very large (see M_TRIM_THRESHOLD). In effect, - the top chunk is treated as larger (and thus less well - fitting) than any other available chunk. The top chunk - doesn't update its trailing size field since there is no next - contiguous chunk that would have to index off it. However, - space is still allocated for it (TOP_FOOT_SIZE) to enable - separation or merging when space is extended. - - 3. Chunks allocated via mmap, which have the lowest-order bit - (IS_MMAPPED_BIT) set in their prev_foot fields, and do not set - PINUSE_BIT in their head fields. Because they are allocated - one-by-one, each must carry its own prev_foot field, which is - also used to hold the offset this chunk has within its mmapped - region, which is needed to preserve alignment. Each mmapped - chunk is trailed by the first two fields of a fake next-chunk - for sake of usage checks. - -*/ - -struct malloc_chunk { - size_t prev_foot; /* Size of previous chunk (if free). */ - size_t head; /* Size and inuse bits. */ - struct malloc_chunk* fd; /* double links -- used only if free. */ - struct malloc_chunk* bk; -}; - -typedef struct malloc_chunk mchunk; -typedef struct malloc_chunk* mchunkptr; -typedef struct malloc_chunk* sbinptr; /* The type of bins of chunks */ -typedef unsigned int bindex_t; /* Described below */ -typedef unsigned int binmap_t; /* Described below */ -typedef unsigned int flag_t; /* The type of various bit flag sets */ - -/* ------------------- Chunks sizes and alignments ----------------------- */ - -#define MCHUNK_SIZE (sizeof(mchunk)) - -#if FOOTERS -#define CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) -#else /* FOOTERS */ -#define CHUNK_OVERHEAD (SIZE_T_SIZE) -#endif /* FOOTERS */ - -/* MMapped chunks need a second word of overhead ... */ -#define MMAP_CHUNK_OVERHEAD (TWO_SIZE_T_SIZES) -/* ... and additional padding for fake next-chunk at foot */ -#define MMAP_FOOT_PAD (FOUR_SIZE_T_SIZES) - -/* The smallest size we can malloc is an aligned minimal chunk */ -#define MIN_CHUNK_SIZE\ - ((MCHUNK_SIZE + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) - -/* conversion from malloc headers to user pointers, and back */ -#define chunk2mem(p) ((void*)((char*)(p) + TWO_SIZE_T_SIZES)) -#define mem2chunk(mem) ((mchunkptr)((char*)(mem) - TWO_SIZE_T_SIZES)) -/* chunk associated with aligned address A */ -#define align_as_chunk(A) (mchunkptr)((A) + align_offset(chunk2mem(A))) - -/* Bounds on request (not chunk) sizes. */ -#define MAX_REQUEST ((-MIN_CHUNK_SIZE) << 2) -#define MIN_REQUEST (MIN_CHUNK_SIZE - CHUNK_OVERHEAD - SIZE_T_ONE) - -/* pad request bytes into a usable size */ -#define pad_request(req) \ - (((req) + CHUNK_OVERHEAD + CHUNK_ALIGN_MASK) & ~CHUNK_ALIGN_MASK) - -/* pad request, checking for minimum (but not maximum) */ -#define request2size(req) \ - (((req) < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(req)) - - -/* ------------------ Operations on head and foot fields ----------------- */ - -/* - The head field of a chunk is or'ed with PINUSE_BIT when previous - adjacent chunk in use, and or'ed with CINUSE_BIT if this chunk is in - use. If the chunk was obtained with mmap, the prev_foot field has - IS_MMAPPED_BIT set, otherwise holding the offset of the base of the - mmapped region to the base of the chunk. -*/ - -#define PINUSE_BIT (SIZE_T_ONE) -#define CINUSE_BIT (SIZE_T_TWO) -#define INUSE_BITS (PINUSE_BIT|CINUSE_BIT) - -/* Head value for fenceposts */ -#define FENCEPOST_HEAD (INUSE_BITS|SIZE_T_SIZE) - -/* extraction of fields from head words */ -#define cinuse(p) ((p)->head & CINUSE_BIT) -#define pinuse(p) ((p)->head & PINUSE_BIT) -#define chunksize(p) ((p)->head & ~(INUSE_BITS)) - -#define clear_pinuse(p) ((p)->head &= ~PINUSE_BIT) -#define clear_cinuse(p) ((p)->head &= ~CINUSE_BIT) - -/* Treat space at ptr +/- offset as a chunk */ -#define chunk_plus_offset(p, s) ((mchunkptr)(((char*)(p)) + (s))) -#define chunk_minus_offset(p, s) ((mchunkptr)(((char*)(p)) - (s))) - -/* Ptr to next or previous physical malloc_chunk. */ -#define next_chunk(p) ((mchunkptr)( ((char*)(p)) + ((p)->head & ~INUSE_BITS))) -#define prev_chunk(p) ((mchunkptr)( ((char*)(p)) - ((p)->prev_foot) )) - -/* extract next chunk's pinuse bit */ -#define next_pinuse(p) ((next_chunk(p)->head) & PINUSE_BIT) - -/* Get/set size at footer */ -#define get_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot) -#define set_foot(p, s) (((mchunkptr)((char*)(p) + (s)))->prev_foot = (s)) - -/* Set size, pinuse bit, and foot */ -#define set_size_and_pinuse_of_free_chunk(p, s)\ - ((p)->head = (s|PINUSE_BIT), set_foot(p, s)) - -/* Set size, pinuse bit, foot, and clear next pinuse */ -#define set_free_with_pinuse(p, s, n)\ - (clear_pinuse(n), set_size_and_pinuse_of_free_chunk(p, s)) - -#define is_mmapped(p)\ - (!((p)->head & PINUSE_BIT) && ((p)->prev_foot & IS_MMAPPED_BIT)) - -/* Get the internal overhead associated with chunk p */ -#define overhead_for(p)\ - (is_mmapped(p)? MMAP_CHUNK_OVERHEAD : CHUNK_OVERHEAD) - -/* Return true if malloced space is not necessarily cleared */ -#if MMAP_CLEARS -#define calloc_must_clear(p) (!is_mmapped(p)) -#else /* MMAP_CLEARS */ -#define calloc_must_clear(p) (1) -#endif /* MMAP_CLEARS */ - -/* ---------------------- Overlaid data structures ----------------------- */ - -/* - When chunks are not in use, they are treated as nodes of either - lists or trees. - - "Small" chunks are stored in circular doubly-linked lists, and look - like this: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `head:' | Size of chunk, in bytes |P| - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Forward pointer to next chunk in list | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Back pointer to previous chunk in list | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Unused space (may be 0 bytes long) . - . . - . | -nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `foot:' | Size of chunk, in bytes | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Larger chunks are kept in a form of bitwise digital trees (aka - tries) keyed on chunksizes. Because malloc_tree_chunks are only for - free chunks greater than 256 bytes, their size doesn't impose any - constraints on user chunk sizes. Each node looks like: - - chunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Size of previous chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `head:' | Size of chunk, in bytes |P| - mem-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Forward pointer to next chunk of same size | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Back pointer to previous chunk of same size | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Pointer to left child (child[0]) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Pointer to right child (child[1]) | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Pointer to parent | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | bin index of this chunk | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Unused space . - . | -nextchunk-> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - `foot:' | Size of chunk, in bytes | - +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - - Each tree holding treenodes is a tree of unique chunk sizes. Chunks - of the same size are arranged in a circularly-linked list, with only - the oldest chunk (the next to be used, in our FIFO ordering) - actually in the tree. (Tree members are distinguished by a non-null - parent pointer.) If a chunk with the same size an an existing node - is inserted, it is linked off the existing node using pointers that - work in the same way as fd/bk pointers of small chunks. - - Each tree contains a power of 2 sized range of chunk sizes (the - smallest is 0x100 <= x < 0x180), which is is divided in half at each - tree level, with the chunks in the smaller half of the range (0x100 - <= x < 0x140 for the top nose) in the left subtree and the larger - half (0x140 <= x < 0x180) in the right subtree. This is, of course, - done by inspecting individual bits. - - Using these rules, each node's left subtree contains all smaller - sizes than its right subtree. However, the node at the root of each - subtree has no particular ordering relationship to either. (The - dividing line between the subtree sizes is based on trie relation.) - If we remove the last chunk of a given size from the interior of the - tree, we need to replace it with a leaf node. The tree ordering - rules permit a node to be replaced by any leaf below it. - - The smallest chunk in a tree (a common operation in a best-fit - allocator) can be found by walking a path to the leftmost leaf in - the tree. Unlike a usual binary tree, where we follow left child - pointers until we reach a null, here we follow the right child - pointer any time the left one is null, until we reach a leaf with - both child pointers null. The smallest chunk in the tree will be - somewhere along that path. - - The worst case number of steps to add, find, or remove a node is - bounded by the number of bits differentiating chunks within - bins. Under current bin calculations, this ranges from 6 up to 21 - (for 32 bit sizes) or up to 53 (for 64 bit sizes). The typical case - is of course much better. -*/ - -struct malloc_tree_chunk { - /* The first four fields must be compatible with malloc_chunk */ - size_t prev_foot; - size_t head; - struct malloc_tree_chunk* fd; - struct malloc_tree_chunk* bk; - - struct malloc_tree_chunk* child[2]; - struct malloc_tree_chunk* parent; - bindex_t index; -}; - -typedef struct malloc_tree_chunk tchunk; -typedef struct malloc_tree_chunk* tchunkptr; -typedef struct malloc_tree_chunk* tbinptr; /* The type of bins of trees */ - -/* A little helper macro for trees */ -#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0] : (t)->child[1]) - -/* ----------------------------- Segments -------------------------------- */ - -/* - Each malloc space may include non-contiguous segments, held in a - list headed by an embedded malloc_segment record representing the - top-most space. Segments also include flags holding properties of - the space. Large chunks that are directly allocated by mmap are not - included in this list. They are instead independently created and - destroyed without otherwise keeping track of them. - - Segment management mainly comes into play for spaces allocated by - MMAP. Any call to MMAP might or might not return memory that is - adjacent to an existing segment. MORECORE normally contiguously - extends the current space, so this space is almost always adjacent, - which is simpler and faster to deal with. (This is why MORECORE is - used preferentially to MMAP when both are available -- see - sys_alloc.) When allocating using MMAP, we don't use any of the - hinting mechanisms (inconsistently) supported in various - implementations of unix mmap, or distinguish reserving from - committing memory. Instead, we just ask for space, and exploit - contiguity when we get it. It is probably possible to do - better than this on some systems, but no general scheme seems - to be significantly better. - - Management entails a simpler variant of the consolidation scheme - used for chunks to reduce fragmentation -- new adjacent memory is - normally prepended or appended to an existing segment. However, - there are limitations compared to chunk consolidation that mostly - reflect the fact that segment processing is relatively infrequent - (occurring only when getting memory from system) and that we - don't expect to have huge numbers of segments: - - * Segments are not indexed, so traversal requires linear scans. (It - would be possible to index these, but is not worth the extra - overhead and complexity for most programs on most platforms.) - * New segments are only appended to old ones when holding top-most - memory; if they cannot be prepended to others, they are held in - different segments. - - Except for the top-most segment of an mstate, each segment record - is kept at the tail of its segment. Segments are added by pushing - segment records onto the list headed by &mstate.seg for the - containing mstate. - - Segment flags control allocation/merge/deallocation policies: - * If EXTERN_BIT set, then we did not allocate this segment, - and so should not try to deallocate or merge with others. - (This currently holds only for the initial segment passed - into create_mspace_with_base.) - * If IS_MMAPPED_BIT set, the segment may be merged with - other surrounding mmapped segments and trimmed/de-allocated - using munmap. - * If neither bit is set, then the segment was obtained using - MORECORE so can be merged with surrounding MORECORE'd segments - and deallocated/trimmed using MORECORE with negative arguments. -*/ - -struct malloc_segment { - char* base; /* base address */ - size_t size; /* allocated size */ - struct malloc_segment* next; /* ptr to next segment */ - flag_t sflags; /* mmap and extern flag */ -}; - -#define is_mmapped_segment(S) ((S)->sflags & IS_MMAPPED_BIT) -#define is_extern_segment(S) ((S)->sflags & EXTERN_BIT) - -typedef struct malloc_segment msegment; -typedef struct malloc_segment* msegmentptr; - -/* ---------------------------- malloc_state ----------------------------- */ - -/* - A malloc_state holds all of the bookkeeping for a space. - The main fields are: - - Top - The topmost chunk of the currently active segment. Its size is - cached in topsize. The actual size of topmost space is - topsize+TOP_FOOT_SIZE, which includes space reserved for adding - fenceposts and segment records if necessary when getting more - space from the system. The size at which to autotrim top is - cached from mparams in trim_check, except that it is disabled if - an autotrim fails. - - Designated victim (dv) - This is the preferred chunk for servicing small requests that - don't have exact fits. It is normally the chunk split off most - recently to service another small request. Its size is cached in - dvsize. The link fields of this chunk are not maintained since it - is not kept in a bin. - - SmallBins - An array of bin headers for free chunks. These bins hold chunks - with sizes less than MIN_LARGE_SIZE bytes. Each bin contains - chunks of all the same size, spaced 8 bytes apart. To simplify - use in double-linked lists, each bin header acts as a malloc_chunk - pointing to the real first node, if it exists (else pointing to - itself). This avoids special-casing for headers. But to avoid - waste, we allocate only the fd/bk pointers of bins, and then use - repositioning tricks to treat these as the fields of a chunk. - - TreeBins - Treebins are pointers to the roots of trees holding a range of - sizes. There are 2 equally spaced treebins for each power of two - from TREE_SHIFT to TREE_SHIFT+16. The last bin holds anything - larger. - - Bin maps - There is one bit map for small bins ("smallmap") and one for - treebins ("treemap). Each bin sets its bit when non-empty, and - clears the bit when empty. Bit operations are then used to avoid - bin-by-bin searching -- nearly all "search" is done without ever - looking at bins that won't be selected. The bit maps - conservatively use 32 bits per map word, even if on 64bit system. - For a good description of some of the bit-based techniques used - here, see Henry S. Warren Jr's book "Hacker's Delight" (and - supplement at http://hackersdelight.org/). Many of these are - intended to reduce the branchiness of paths through malloc etc, as - well as to reduce the number of memory locations read or written. - - Segments - A list of segments headed by an embedded malloc_segment record - representing the initial space. - - Address check support - The least_addr field is the least address ever obtained from - MORECORE or MMAP. Attempted frees and reallocs of any address less - than this are trapped (unless INSECURE is defined). - - Magic tag - A cross-check field that should always hold same value as mparams.magic. - - Flags - Bits recording whether to use MMAP, locks, or contiguous MORECORE - - Statistics - Each space keeps track of current and maximum system memory - obtained via MORECORE or MMAP. - - Locking - If USE_LOCKS is defined, the "mutex" lock is acquired and released - around every public call using this mspace. -*/ - -/* Bin types, widths and sizes */ -#define NSMALLBINS (32U) -#define NTREEBINS (32U) -#define SMALLBIN_SHIFT (3U) -#define SMALLBIN_WIDTH (SIZE_T_ONE << SMALLBIN_SHIFT) -#define TREEBIN_SHIFT (8U) -#define MIN_LARGE_SIZE (SIZE_T_ONE << TREEBIN_SHIFT) -#define MAX_SMALL_SIZE (MIN_LARGE_SIZE - SIZE_T_ONE) -#define MAX_SMALL_REQUEST (MAX_SMALL_SIZE - CHUNK_ALIGN_MASK - CHUNK_OVERHEAD) - -struct malloc_state { - binmap_t smallmap; - binmap_t treemap; - size_t dvsize; - size_t topsize; - char* least_addr; - mchunkptr dv; - mchunkptr top; - size_t trim_check; - size_t magic; - mchunkptr smallbins[(NSMALLBINS+1)*2]; - tbinptr treebins[NTREEBINS]; - size_t footprint; - size_t max_footprint; - flag_t mflags; -#if USE_LOCKS - MLOCK_T mutex; /* locate lock among fields that rarely change */ -#endif /* USE_LOCKS */ - msegment seg; -}; - -typedef struct malloc_state* mstate; - -/* ------------- Global malloc_state and malloc_params ------------------- */ - -/* - malloc_params holds global properties, including those that can be - dynamically set using mallopt. There is a single instance, mparams, - initialized in init_mparams. -*/ - -struct malloc_params { - size_t magic; - size_t page_size; - size_t granularity; - size_t mmap_threshold; - size_t trim_threshold; - flag_t default_mflags; -}; - -static struct malloc_params mparams; - -/* The global malloc_state used for all non-"mspace" calls */ -static struct malloc_state _gm_; -#define gm (&_gm_) -#define is_global(M) ((M) == &_gm_) -#define is_initialized(M) ((M)->top != 0) - -/* -------------------------- system alloc setup ------------------------- */ - -/* Operations on mflags */ - -#define use_lock(M) ((M)->mflags & USE_LOCK_BIT) -#define enable_lock(M) ((M)->mflags |= USE_LOCK_BIT) -#define disable_lock(M) ((M)->mflags &= ~USE_LOCK_BIT) - -#define use_mmap(M) ((M)->mflags & USE_MMAP_BIT) -#define enable_mmap(M) ((M)->mflags |= USE_MMAP_BIT) -#define disable_mmap(M) ((M)->mflags &= ~USE_MMAP_BIT) - -#define use_noncontiguous(M) ((M)->mflags & USE_NONCONTIGUOUS_BIT) -#define disable_contiguous(M) ((M)->mflags |= USE_NONCONTIGUOUS_BIT) - -#define set_lock(M,L)\ - ((M)->mflags = (L)?\ - ((M)->mflags | USE_LOCK_BIT) :\ - ((M)->mflags & ~USE_LOCK_BIT)) - -/* page-align a size */ -#define page_align(S)\ - (((S) + (mparams.page_size)) & ~(mparams.page_size - SIZE_T_ONE)) - -/* granularity-align a size */ -#define granularity_align(S)\ - (((S) + (mparams.granularity)) & ~(mparams.granularity - SIZE_T_ONE)) - -#define is_page_aligned(S)\ - (((size_t)(S) & (mparams.page_size - SIZE_T_ONE)) == 0) -#define is_granularity_aligned(S)\ - (((size_t)(S) & (mparams.granularity - SIZE_T_ONE)) == 0) - -/* True if segment S holds address A */ -#define segment_holds(S, A)\ - ((char*)(A) >= S->base && (char*)(A) < S->base + S->size) - -/* Return segment holding given address */ -static msegmentptr segment_holding(mstate m, char* addr) { - msegmentptr sp = &m->seg; - for (;;) { - if (addr >= sp->base && addr < sp->base + sp->size) - return sp; - if ((sp = sp->next) == 0) - return 0; - } -} - -/* Return true if segment contains a segment link */ -static int has_segment_link(mstate m, msegmentptr ss) { - msegmentptr sp = &m->seg; - for (;;) { - if ((char*)sp >= ss->base && (char*)sp < ss->base + ss->size) - return 1; - if ((sp = sp->next) == 0) - return 0; - } -} - -#ifndef MORECORE_CANNOT_TRIM -#define should_trim(M,s) ((s) > (M)->trim_check) -#else /* MORECORE_CANNOT_TRIM */ -#define should_trim(M,s) (0) -#endif /* MORECORE_CANNOT_TRIM */ - -/* - TOP_FOOT_SIZE is padding at the end of a segment, including space - that may be needed to place segment records and fenceposts when new - noncontiguous segments are added. -*/ -#define TOP_FOOT_SIZE\ - (align_offset(chunk2mem(0))+pad_request(sizeof(struct malloc_segment))+MIN_CHUNK_SIZE) - - -/* ------------------------------- Hooks -------------------------------- */ - -/* - PREACTION should be defined to return 0 on success, and nonzero on - failure. If you are not using locking, you can redefine these to do - anything you like. -*/ - -#if USE_LOCKS - -/* Ensure locks are initialized */ -#define GLOBALLY_INITIALIZE() (mparams.page_size == 0 && init_mparams()) - -#define PREACTION(M) ((GLOBALLY_INITIALIZE() || use_lock(M))? ACQUIRE_LOCK(&(M)->mutex) : 0) -#define POSTACTION(M) { if (use_lock(M)) RELEASE_LOCK(&(M)->mutex); } -#else /* USE_LOCKS */ - -#ifndef PREACTION -#define PREACTION(M) (0) -#endif /* PREACTION */ - -#ifndef POSTACTION -#define POSTACTION(M) -#endif /* POSTACTION */ - -#endif /* USE_LOCKS */ - -/* - CORRUPTION_ERROR_ACTION is triggered upon detected bad addresses. - USAGE_ERROR_ACTION is triggered on detected bad frees and - reallocs. The argument p is an address that might have triggered the - fault. It is ignored by the two predefined actions, but might be - useful in custom actions that try to help diagnose errors. -*/ - -#if PROCEED_ON_ERROR - -/* A count of the number of corruption errors causing resets */ -int malloc_corruption_error_count; - -/* default corruption action */ -static void reset_on_error(mstate m); - -#define CORRUPTION_ERROR_ACTION(m) reset_on_error(m) -#define USAGE_ERROR_ACTION(m, p) - -#else /* PROCEED_ON_ERROR */ - -#ifndef CORRUPTION_ERROR_ACTION -#define CORRUPTION_ERROR_ACTION(m) ABORT -#endif /* CORRUPTION_ERROR_ACTION */ - -#ifndef USAGE_ERROR_ACTION -#define USAGE_ERROR_ACTION(m,p) ABORT -#endif /* USAGE_ERROR_ACTION */ - -#endif /* PROCEED_ON_ERROR */ - -/* -------------------------- Debugging setup ---------------------------- */ - -#if ! DEBUG - -#define check_free_chunk(M,P) -#define check_inuse_chunk(M,P) -#define check_malloced_chunk(M,P,N) -#define check_mmapped_chunk(M,P) -#define check_malloc_state(M) -#define check_top_chunk(M,P) - -#else /* DEBUG */ -#define check_free_chunk(M,P) do_check_free_chunk(M,P) -#define check_inuse_chunk(M,P) do_check_inuse_chunk(M,P) -#define check_top_chunk(M,P) do_check_top_chunk(M,P) -#define check_malloced_chunk(M,P,N) do_check_malloced_chunk(M,P,N) -#define check_mmapped_chunk(M,P) do_check_mmapped_chunk(M,P) -#define check_malloc_state(M) do_check_malloc_state(M) - -static void do_check_any_chunk(mstate m, mchunkptr p); -static void do_check_top_chunk(mstate m, mchunkptr p); -static void do_check_mmapped_chunk(mstate m, mchunkptr p); -static void do_check_inuse_chunk(mstate m, mchunkptr p); -static void do_check_free_chunk(mstate m, mchunkptr p); -static void do_check_malloced_chunk(mstate m, void* mem, size_t s); -static void do_check_tree(mstate m, tchunkptr t); -static void do_check_treebin(mstate m, bindex_t i); -static void do_check_smallbin(mstate m, bindex_t i); -static void do_check_malloc_state(mstate m); -static int bin_find(mstate m, mchunkptr x); -static size_t traverse_and_check(mstate m); -#endif /* DEBUG */ - -/* ---------------------------- Indexing Bins ---------------------------- */ - -#define is_small(s) (((s) >> SMALLBIN_SHIFT) < NSMALLBINS) -#define small_index(s) ((s) >> SMALLBIN_SHIFT) -#define small_index2size(i) ((i) << SMALLBIN_SHIFT) -#define MIN_SMALL_INDEX (small_index(MIN_CHUNK_SIZE)) - -/* addressing by index. See above about smallbin repositioning */ -#define smallbin_at(M, i) ((sbinptr)((char*)&((M)->smallbins[(i)<<1]))) -#define treebin_at(M,i) (&((M)->treebins[i])) - -/* assign tree index for size S to variable I */ -#if defined(__GNUC__) && defined(i386) -#define compute_tree_index(S, I)\ -{\ - size_t X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int K;\ - __asm__("bsrl %1,%0\n\t" : "=r" (K) : "rm" (X));\ - I = (bindex_t)((K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1)));\ - }\ -} -#else /* GNUC */ -#define compute_tree_index(S, I)\ -{\ - size_t X = S >> TREEBIN_SHIFT;\ - if (X == 0)\ - I = 0;\ - else if (X > 0xFFFF)\ - I = NTREEBINS-1;\ - else {\ - unsigned int Y = (unsigned int)X;\ - unsigned int N = ((Y - 0x100) >> 16) & 8;\ - unsigned int K = (((Y <<= N) - 0x1000) >> 16) & 4;\ - N += K;\ - N += K = (((Y <<= K) - 0x4000) >> 16) & 2;\ - K = 14 - N + ((Y <<= K) >> 15);\ - I = (K << 1) + ((S >> (K + (TREEBIN_SHIFT-1)) & 1));\ - }\ -} -#endif /* GNUC */ - -/* Bit representing maximum resolved size in a treebin at i */ -#define bit_for_tree_index(i) \ - (i == NTREEBINS-1)? (SIZE_T_BITSIZE-1) : (((i) >> 1) + TREEBIN_SHIFT - 2) - -/* Shift placing maximum resolved bit in a treebin at i as sign bit */ -#define leftshift_for_tree_index(i) \ - ((i == NTREEBINS-1)? 0 : \ - ((SIZE_T_BITSIZE-SIZE_T_ONE) - (((i) >> 1) + TREEBIN_SHIFT - 2))) - -/* The size of the smallest chunk held in bin with index i */ -#define minsize_for_tree_index(i) \ - ((SIZE_T_ONE << (((i) >> 1) + TREEBIN_SHIFT)) | \ - (((size_t)((i) & SIZE_T_ONE)) << (((i) >> 1) + TREEBIN_SHIFT - 1))) - - -/* ------------------------ Operations on bin maps ----------------------- */ - -/* bit corresponding to given index */ -#define idx2bit(i) ((binmap_t)(1) << (i)) - -/* Mark/Clear bits with given index */ -#define mark_smallmap(M,i) ((M)->smallmap |= idx2bit(i)) -#define clear_smallmap(M,i) ((M)->smallmap &= ~idx2bit(i)) -#define smallmap_is_marked(M,i) ((M)->smallmap & idx2bit(i)) - -#define mark_treemap(M,i) ((M)->treemap |= idx2bit(i)) -#define clear_treemap(M,i) ((M)->treemap &= ~idx2bit(i)) -#define treemap_is_marked(M,i) ((M)->treemap & idx2bit(i)) - -/* index corresponding to given bit */ - -#if defined(__GNUC__) && defined(i386) -#define compute_bit2idx(X, I)\ -{\ - unsigned int J;\ - __asm__("bsfl %1,%0\n\t" : "=r" (J) : "rm" (X));\ - I = (bindex_t)J;\ -} - -#else /* GNUC */ -#if USE_BUILTIN_FFS -#define compute_bit2idx(X, I) I = ffs(X)-1 - -#else /* USE_BUILTIN_FFS */ -#define compute_bit2idx(X, I)\ -{\ - unsigned int Y = X - 1;\ - unsigned int K = Y >> (16-4) & 16;\ - unsigned int N = K; Y >>= K;\ - N += K = Y >> (8-3) & 8; Y >>= K;\ - N += K = Y >> (4-2) & 4; Y >>= K;\ - N += K = Y >> (2-1) & 2; Y >>= K;\ - N += K = Y >> (1-0) & 1; Y >>= K;\ - I = (bindex_t)(N + Y);\ -} -#endif /* USE_BUILTIN_FFS */ -#endif /* GNUC */ - -/* isolate the least set bit of a bitmap */ -#define least_bit(x) ((x) & -(x)) - -/* mask with all bits to left of least bit of x on */ -#define left_bits(x) ((x<<1) | -(x<<1)) - -/* mask with all bits to left of or equal to least bit of x on */ -#define same_or_left_bits(x) ((x) | -(x)) - - -/* ----------------------- Runtime Check Support ------------------------- */ - -/* - For security, the main invariant is that malloc/free/etc never - writes to a static address other than malloc_state, unless static - malloc_state itself has been corrupted, which cannot occur via - malloc (because of these checks). In essence this means that we - believe all pointers, sizes, maps etc held in malloc_state, but - check all of those linked or offsetted from other embedded data - structures. These checks are interspersed with main code in a way - that tends to minimize their run-time cost. - - When FOOTERS is defined, in addition to range checking, we also - verify footer fields of inuse chunks, which can be used guarantee - that the mstate controlling malloc/free is intact. This is a - streamlined version of the approach described by William Robertson - et al in "Run-time Detection of Heap-based Overflows" LISA'03 - http://www.usenix.org/events/lisa03/tech/robertson.html The footer - of an inuse chunk holds the xor of its mstate and a random seed, - that is checked upon calls to free() and realloc(). This is - (probablistically) unguessable from outside the program, but can be - computed by any code successfully malloc'ing any chunk, so does not - itself provide protection against code that has already broken - security through some other means. Unlike Robertson et al, we - always dynamically check addresses of all offset chunks (previous, - next, etc). This turns out to be cheaper than relying on hashes. -*/ - -#if !INSECURE -/* Check if address a is at least as high as any from MORECORE or MMAP */ -#define ok_address(M, a) ((char*)(a) >= (M)->least_addr) -/* Check if address of next chunk n is higher than base chunk p */ -#define ok_next(p, n) ((char*)(p) < (char*)(n)) -/* Check if p has its cinuse bit on */ -#define ok_cinuse(p) cinuse(p) -/* Check if p has its pinuse bit on */ -#define ok_pinuse(p) pinuse(p) - -#else /* !INSECURE */ -#define ok_address(M, a) (1) -#define ok_next(b, n) (1) -#define ok_cinuse(p) (1) -#define ok_pinuse(p) (1) -#endif /* !INSECURE */ - -#if (FOOTERS && !INSECURE) -/* Check if (alleged) mstate m has expected magic field */ -#define ok_magic(M) ((M)->magic == mparams.magic) -#else /* (FOOTERS && !INSECURE) */ -#define ok_magic(M) (1) -#endif /* (FOOTERS && !INSECURE) */ - - -/* In gcc, use __builtin_expect to minimize impact of checks */ -#if !INSECURE -#if defined(__GNUC__) && __GNUC__ >= 3 -#define RTCHECK(e) __builtin_expect(e, 1) -#else /* GNUC */ -#define RTCHECK(e) (e) -#endif /* GNUC */ -#else /* !INSECURE */ -#define RTCHECK(e) (1) -#endif /* !INSECURE */ - -/* macros to set up inuse chunks with or without footers */ - -#if !FOOTERS - -#define mark_inuse_foot(M,p,s) - -/* Set cinuse bit and pinuse bit of next chunk */ -#define set_inuse(M,p,s)\ - ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ - ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) - -/* Set cinuse and pinuse of this chunk and pinuse of next chunk */ -#define set_inuse_and_pinuse(M,p,s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - ((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT) - -/* Set size, cinuse and pinuse bit of this chunk */ -#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT)) - -#else /* FOOTERS */ - -/* Set foot of inuse chunk to be xor of mstate and seed */ -#define mark_inuse_foot(M,p,s)\ - (((mchunkptr)((char*)(p) + (s)))->prev_foot = ((size_t)(M) ^ mparams.magic)) - -#define get_mstate_for(p)\ - ((mstate)(((mchunkptr)((char*)(p) +\ - (chunksize(p))))->prev_foot ^ mparams.magic)) - -#define set_inuse(M,p,s)\ - ((p)->head = (((p)->head & PINUSE_BIT)|s|CINUSE_BIT),\ - (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT), \ - mark_inuse_foot(M,p,s)) - -#define set_inuse_and_pinuse(M,p,s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - (((mchunkptr)(((char*)(p)) + (s)))->head |= PINUSE_BIT),\ - mark_inuse_foot(M,p,s)) - -#define set_size_and_pinuse_of_inuse_chunk(M, p, s)\ - ((p)->head = (s|PINUSE_BIT|CINUSE_BIT),\ - mark_inuse_foot(M, p, s)) - -#endif /* !FOOTERS */ - -/* ---------------------------- setting mparams -------------------------- */ - -/* Initialize mparams */ -static int init_mparams(void) { - if (mparams.page_size == 0) { - size_t s; - - mparams.mmap_threshold = DEFAULT_MMAP_THRESHOLD; - mparams.trim_threshold = DEFAULT_TRIM_THRESHOLD; -#if MORECORE_CONTIGUOUS - mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT; -#else /* MORECORE_CONTIGUOUS */ - mparams.default_mflags = USE_LOCK_BIT|USE_MMAP_BIT|USE_NONCONTIGUOUS_BIT; -#endif /* MORECORE_CONTIGUOUS */ - -#if (FOOTERS && !INSECURE) - { -#if USE_DEV_RANDOM - int fd; - unsigned char buf[sizeof(size_t)]; - /* Try to use /dev/urandom, else fall back on using time */ - if ((fd = open("/dev/urandom", O_RDONLY)) >= 0 && - read(fd, buf, sizeof(buf)) == sizeof(buf)) { - s = *((size_t *) buf); - close(fd); - } - else -#endif /* USE_DEV_RANDOM */ - s = (size_t)(time(0) ^ (size_t)0x55555555U); - - s |= (size_t)8U; /* ensure nonzero */ - s &= ~(size_t)7U; /* improve chances of fault for bad values */ - - } -#else /* (FOOTERS && !INSECURE) */ - s = (size_t)0x58585858U; -#endif /* (FOOTERS && !INSECURE) */ - ACQUIRE_MAGIC_INIT_LOCK(); - if (mparams.magic == 0) { - mparams.magic = s; - /* Set up lock for main malloc area */ - INITIAL_LOCK(&gm->mutex); - gm->mflags = mparams.default_mflags; - } - RELEASE_MAGIC_INIT_LOCK(); - -#ifndef WIN32 - mparams.page_size = malloc_getpagesize; - mparams.granularity = ((DEFAULT_GRANULARITY != 0)? - DEFAULT_GRANULARITY : mparams.page_size); -#else /* WIN32 */ - { - SYSTEM_INFO system_info; - GetSystemInfo(&system_info); - mparams.page_size = system_info.dwPageSize; - mparams.granularity = system_info.dwAllocationGranularity; - } -#endif /* WIN32 */ - - /* Sanity-check configuration: - size_t must be unsigned and as wide as pointer type. - ints must be at least 4 bytes. - alignment must be at least 8. - Alignment, min chunk size, and page size must all be powers of 2. - */ - if ((sizeof(size_t) != sizeof(char*)) || - (MAX_SIZE_T < MIN_CHUNK_SIZE) || - (sizeof(int) < 4) || - (MALLOC_ALIGNMENT < (size_t)8U) || - ((MALLOC_ALIGNMENT & (MALLOC_ALIGNMENT-SIZE_T_ONE)) != 0) || - ((MCHUNK_SIZE & (MCHUNK_SIZE-SIZE_T_ONE)) != 0) || - ((mparams.granularity & (mparams.granularity-SIZE_T_ONE)) != 0) || - ((mparams.page_size & (mparams.page_size-SIZE_T_ONE)) != 0)) - ABORT; - } - return 0; -} - -/* support for mallopt */ -static int change_mparam(int param_number, int value) { - size_t val = (size_t)value; - init_mparams(); - switch(param_number) { - case M_TRIM_THRESHOLD: - mparams.trim_threshold = val; - return 1; - case M_GRANULARITY: - if (val >= mparams.page_size && ((val & (val-1)) == 0)) { - mparams.granularity = val; - return 1; - } - else - return 0; - case M_MMAP_THRESHOLD: - mparams.mmap_threshold = val; - return 1; - default: - return 0; - } -} - -#if DEBUG -/* ------------------------- Debugging Support --------------------------- */ - -/* Check properties of any chunk, whether free, inuse, mmapped etc */ -static void do_check_any_chunk(mstate m, mchunkptr p) { - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); - assert(ok_address(m, p)); -} - -/* Check properties of top chunk */ -static void do_check_top_chunk(mstate m, mchunkptr p) { - msegmentptr sp = segment_holding(m, (char*)p); - size_t sz = chunksize(p); - assert(sp != 0); - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); - assert(ok_address(m, p)); - assert(sz == m->topsize); - assert(sz > 0); - assert(sz == ((sp->base + sp->size) - (char*)p) - TOP_FOOT_SIZE); - assert(pinuse(p)); - assert(!next_pinuse(p)); -} - -/* Check properties of (inuse) mmapped chunks */ -static void do_check_mmapped_chunk(mstate m, mchunkptr p) { - size_t sz = chunksize(p); - size_t len = (sz + (p->prev_foot & ~IS_MMAPPED_BIT) + MMAP_FOOT_PAD); - assert(is_mmapped(p)); - assert(use_mmap(m)); - assert((is_aligned(chunk2mem(p))) || (p->head == FENCEPOST_HEAD)); - assert(ok_address(m, p)); - assert(!is_small(sz)); - assert((len & (mparams.page_size-SIZE_T_ONE)) == 0); - assert(chunk_plus_offset(p, sz)->head == FENCEPOST_HEAD); - assert(chunk_plus_offset(p, sz+SIZE_T_SIZE)->head == 0); -} - -/* Check properties of inuse chunks */ -static void do_check_inuse_chunk(mstate m, mchunkptr p) { - do_check_any_chunk(m, p); - assert(cinuse(p)); - assert(next_pinuse(p)); - /* If not pinuse and not mmapped, previous chunk has OK offset */ - assert(is_mmapped(p) || pinuse(p) || next_chunk(prev_chunk(p)) == p); - if (is_mmapped(p)) - do_check_mmapped_chunk(m, p); -} - -/* Check properties of free chunks */ -static void do_check_free_chunk(mstate m, mchunkptr p) { - size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT); - mchunkptr next = chunk_plus_offset(p, sz); - do_check_any_chunk(m, p); - assert(!cinuse(p)); - assert(!next_pinuse(p)); - assert (!is_mmapped(p)); - if (p != m->dv && p != m->top) { - if (sz >= MIN_CHUNK_SIZE) { - assert((sz & CHUNK_ALIGN_MASK) == 0); - assert(is_aligned(chunk2mem(p))); - assert(next->prev_foot == sz); - assert(pinuse(p)); - assert (next == m->top || cinuse(next)); - assert(p->fd->bk == p); - assert(p->bk->fd == p); - } - else /* markers are always of size SIZE_T_SIZE */ - assert(sz == SIZE_T_SIZE); - } -} - -/* Check properties of malloced chunks at the point they are malloced */ -static void do_check_malloced_chunk(mstate m, void* mem, size_t s) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - size_t sz = p->head & ~(PINUSE_BIT|CINUSE_BIT); - do_check_inuse_chunk(m, p); - assert((sz & CHUNK_ALIGN_MASK) == 0); - assert(sz >= MIN_CHUNK_SIZE); - assert(sz >= s); - /* unless mmapped, size is less than MIN_CHUNK_SIZE more than request */ - assert(is_mmapped(p) || sz < (s + MIN_CHUNK_SIZE)); - } -} - -/* Check a tree and its subtrees. */ -static void do_check_tree(mstate m, tchunkptr t) { - tchunkptr head = 0; - tchunkptr u = t; - bindex_t tindex = t->index; - size_t tsize = chunksize(t); - bindex_t idx; - compute_tree_index(tsize, idx); - assert(tindex == idx); - assert(tsize >= MIN_LARGE_SIZE); - assert(tsize >= minsize_for_tree_index(idx)); - assert((idx == NTREEBINS-1) || (tsize < minsize_for_tree_index((idx+1)))); - - do { /* traverse through chain of same-sized nodes */ - do_check_any_chunk(m, ((mchunkptr)u)); - assert(u->index == tindex); - assert(chunksize(u) == tsize); - assert(!cinuse(u)); - assert(!next_pinuse(u)); - assert(u->fd->bk == u); - assert(u->bk->fd == u); - if (u->parent == 0) { - assert(u->child[0] == 0); - assert(u->child[1] == 0); - } - else { - assert(head == 0); /* only one node on chain has parent */ - head = u; - assert(u->parent != u); - assert (u->parent->child[0] == u || - u->parent->child[1] == u || - *((tbinptr*)(u->parent)) == u); - if (u->child[0] != 0) { - assert(u->child[0]->parent == u); - assert(u->child[0] != u); - do_check_tree(m, u->child[0]); - } - if (u->child[1] != 0) { - assert(u->child[1]->parent == u); - assert(u->child[1] != u); - do_check_tree(m, u->child[1]); - } - if (u->child[0] != 0 && u->child[1] != 0) { - assert(chunksize(u->child[0]) < chunksize(u->child[1])); - } - } - u = u->fd; - } while (u != t); - assert(head != 0); -} - -/* Check all the chunks in a treebin. */ -static void do_check_treebin(mstate m, bindex_t i) { - tbinptr* tb = treebin_at(m, i); - tchunkptr t = *tb; - int empty = (m->treemap & (1U << i)) == 0; - if (t == 0) - assert(empty); - if (!empty) - do_check_tree(m, t); -} - -/* Check all the chunks in a smallbin. */ -static void do_check_smallbin(mstate m, bindex_t i) { - sbinptr b = smallbin_at(m, i); - mchunkptr p = b->bk; - unsigned int empty = (m->smallmap & (1U << i)) == 0; - if (p == b) - assert(empty); - if (!empty) { - for (; p != b; p = p->bk) { - size_t size = chunksize(p); - mchunkptr q; - /* each chunk claims to be free */ - do_check_free_chunk(m, p); - /* chunk belongs in bin */ - assert(small_index(size) == i); - assert(p->bk == b || chunksize(p->bk) == chunksize(p)); - /* chunk is followed by an inuse chunk */ - q = next_chunk(p); - if (q->head != FENCEPOST_HEAD) - do_check_inuse_chunk(m, q); - } - } -} - -/* Find x in a bin. Used in other check functions. */ -static int bin_find(mstate m, mchunkptr x) { - size_t size = chunksize(x); - if (is_small(size)) { - bindex_t sidx = small_index(size); - sbinptr b = smallbin_at(m, sidx); - if (smallmap_is_marked(m, sidx)) { - mchunkptr p = b; - do { - if (p == x) - return 1; - } while ((p = p->fd) != b); - } - } - else { - bindex_t tidx; - compute_tree_index(size, tidx); - if (treemap_is_marked(m, tidx)) { - tchunkptr t = *treebin_at(m, tidx); - size_t sizebits = size << leftshift_for_tree_index(tidx); - while (t != 0 && chunksize(t) != size) { - t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; - sizebits <<= 1; - } - if (t != 0) { - tchunkptr u = t; - do { - if (u == (tchunkptr)x) - return 1; - } while ((u = u->fd) != t); - } - } - } - return 0; -} - -/* Traverse each chunk and check it; return total */ -static size_t traverse_and_check(mstate m) { - size_t sum = 0; - if (is_initialized(m)) { - msegmentptr s = &m->seg; - sum += m->topsize + TOP_FOOT_SIZE; - while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - mchunkptr lastq = 0; - assert(pinuse(q)); - while (segment_holds(s, q) && - q != m->top && q->head != FENCEPOST_HEAD) { - sum += chunksize(q); - if (cinuse(q)) { - assert(!bin_find(m, q)); - do_check_inuse_chunk(m, q); - } - else { - assert(q == m->dv || bin_find(m, q)); - assert(lastq == 0 || cinuse(lastq)); /* Not 2 consecutive free */ - do_check_free_chunk(m, q); - } - lastq = q; - q = next_chunk(q); - } - s = s->next; - } - } - return sum; -} - -/* Check all properties of malloc_state. */ -static void do_check_malloc_state(mstate m) { - bindex_t i; - size_t total; - /* check bins */ - for (i = 0; i < NSMALLBINS; ++i) - do_check_smallbin(m, i); - for (i = 0; i < NTREEBINS; ++i) - do_check_treebin(m, i); - - if (m->dvsize != 0) { /* check dv chunk */ - do_check_any_chunk(m, m->dv); - assert(m->dvsize == chunksize(m->dv)); - assert(m->dvsize >= MIN_CHUNK_SIZE); - assert(bin_find(m, m->dv) == 0); - } - - if (m->top != 0) { /* check top chunk */ - do_check_top_chunk(m, m->top); - assert(m->topsize == chunksize(m->top)); - assert(m->topsize > 0); - assert(bin_find(m, m->top) == 0); - } - - total = traverse_and_check(m); - assert(total <= m->footprint); - assert(m->footprint <= m->max_footprint); -} -#endif /* DEBUG */ - -/* ----------------------------- statistics ------------------------------ */ - -#if !NO_MALLINFO -static struct mallinfo internal_mallinfo(mstate m) { - struct mallinfo nm = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - if (!PREACTION(m)) { - check_malloc_state(m); - if (is_initialized(m)) { - size_t nfree = SIZE_T_ONE; /* top always free */ - size_t mfree = m->topsize + TOP_FOOT_SIZE; - size_t sum = mfree; - msegmentptr s = &m->seg; - while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - while (segment_holds(s, q) && - q != m->top && q->head != FENCEPOST_HEAD) { - size_t sz = chunksize(q); - sum += sz; - if (!cinuse(q)) { - mfree += sz; - ++nfree; - } - q = next_chunk(q); - } - s = s->next; - } - - nm.arena = sum; - nm.ordblks = nfree; - nm.hblkhd = m->footprint - sum; - nm.usmblks = m->max_footprint; - nm.uordblks = m->footprint - mfree; - nm.fordblks = mfree; - nm.keepcost = m->topsize; - } - - POSTACTION(m); - } - return nm; -} -#endif /* !NO_MALLINFO */ - -static void internal_malloc_stats(mstate m) { - if (!PREACTION(m)) { - size_t maxfp = 0; - size_t fp = 0; - size_t used = 0; - check_malloc_state(m); - if (is_initialized(m)) { - msegmentptr s = &m->seg; - maxfp = m->max_footprint; - fp = m->footprint; - used = fp - (m->topsize + TOP_FOOT_SIZE); - - while (s != 0) { - mchunkptr q = align_as_chunk(s->base); - while (segment_holds(s, q) && - q != m->top && q->head != FENCEPOST_HEAD) { - if (!cinuse(q)) - used -= chunksize(q); - q = next_chunk(q); - } - s = s->next; - } - } - - fprintf(stderr, "max system bytes = %10lu\n", (unsigned long)(maxfp)); - fprintf(stderr, "system bytes = %10lu\n", (unsigned long)(fp)); - fprintf(stderr, "in use bytes = %10lu\n", (unsigned long)(used)); - - POSTACTION(m); - } -} - -/* ----------------------- Operations on smallbins ----------------------- */ - -/* - Various forms of linking and unlinking are defined as macros. Even - the ones for trees, which are very long but have very short typical - paths. This is ugly but reduces reliance on inlining support of - compilers. -*/ - -/* Link a free chunk into a smallbin */ -#define insert_small_chunk(M, P, S) {\ - bindex_t I = small_index(S);\ - mchunkptr B = smallbin_at(M, I);\ - mchunkptr F = B;\ - assert(S >= MIN_CHUNK_SIZE);\ - if (!smallmap_is_marked(M, I))\ - mark_smallmap(M, I);\ - else if (RTCHECK(ok_address(M, B->fd)))\ - F = B->fd;\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - B->fd = P;\ - F->bk = P;\ - P->fd = F;\ - P->bk = B;\ -} - -/* Unlink a chunk from a smallbin */ -#define unlink_small_chunk(M, P, S) {\ - mchunkptr F = P->fd;\ - mchunkptr B = P->bk;\ - bindex_t I = small_index(S);\ - assert(P != B);\ - assert(P != F);\ - assert(chunksize(P) == small_index2size(I));\ - if (F == B)\ - clear_smallmap(M, I);\ - else if (RTCHECK((F == smallbin_at(M,I) || ok_address(M, F)) &&\ - (B == smallbin_at(M,I) || ok_address(M, B)))) {\ - F->bk = B;\ - B->fd = F;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ -} - -/* Unlink the first chunk from a smallbin */ -#define unlink_first_small_chunk(M, B, P, I) {\ - mchunkptr F = P->fd;\ - assert(P != B);\ - assert(P != F);\ - assert(chunksize(P) == small_index2size(I));\ - if (B == F)\ - clear_smallmap(M, I);\ - else if (RTCHECK(ok_address(M, F))) {\ - B->fd = F;\ - F->bk = B;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ -} - -/* Replace dv node, binning the old one */ -/* Used only when dvsize known to be small */ -#define replace_dv(M, P, S) {\ - size_t DVS = M->dvsize;\ - if (DVS != 0) {\ - mchunkptr DV = M->dv;\ - assert(is_small(DVS));\ - insert_small_chunk(M, DV, DVS);\ - }\ - M->dvsize = S;\ - M->dv = P;\ -} - -/* ------------------------- Operations on trees ------------------------- */ - -/* Insert chunk into tree */ -#define insert_large_chunk(M, X, S) {\ - tbinptr* H;\ - bindex_t I;\ - compute_tree_index(S, I);\ - H = treebin_at(M, I);\ - X->index = I;\ - X->child[0] = X->child[1] = 0;\ - if (!treemap_is_marked(M, I)) {\ - mark_treemap(M, I);\ - *H = X;\ - X->parent = (tchunkptr)H;\ - X->fd = X->bk = X;\ - }\ - else {\ - tchunkptr T = *H;\ - size_t K = S << leftshift_for_tree_index(I);\ - for (;;) {\ - if (chunksize(T) != S) {\ - tchunkptr* C = &(T->child[(K >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]);\ - K <<= 1;\ - if (*C != 0)\ - T = *C;\ - else if (RTCHECK(ok_address(M, C))) {\ - *C = X;\ - X->parent = T;\ - X->fd = X->bk = X;\ - break;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - break;\ - }\ - }\ - else {\ - tchunkptr F = T->fd;\ - if (RTCHECK(ok_address(M, T) && ok_address(M, F))) {\ - T->fd = F->bk = X;\ - X->fd = F;\ - X->bk = T;\ - X->parent = 0;\ - break;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - break;\ - }\ - }\ - }\ - }\ -} - -/* - Unlink steps: - - 1. If x is a chained node, unlink it from its same-sized fd/bk links - and choose its bk node as its replacement. - 2. If x was the last node of its size, but not a leaf node, it must - be replaced with a leaf node (not merely one with an open left or - right), to make sure that lefts and rights of descendents - correspond properly to bit masks. We use the rightmost descendent - of x. We could use any other leaf, but this is easy to locate and - tends to counteract removal of leftmosts elsewhere, and so keeps - paths shorter than minimally guaranteed. This doesn't loop much - because on average a node in a tree is near the bottom. - 3. If x is the base of a chain (i.e., has parent links) relink - x's parent and children to x's replacement (or null if none). -*/ - -#define unlink_large_chunk(M, X) {\ - tchunkptr XP = X->parent;\ - tchunkptr R;\ - if (X->bk != X) {\ - tchunkptr F = X->fd;\ - R = X->bk;\ - if (RTCHECK(ok_address(M, F))) {\ - F->bk = R;\ - R->fd = F;\ - }\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - else {\ - tchunkptr* RP;\ - if (((R = *(RP = &(X->child[1]))) != 0) ||\ - ((R = *(RP = &(X->child[0]))) != 0)) {\ - tchunkptr* CP;\ - while ((*(CP = &(R->child[1])) != 0) ||\ - (*(CP = &(R->child[0])) != 0)) {\ - R = *(RP = CP);\ - }\ - if (RTCHECK(ok_address(M, RP)))\ - *RP = 0;\ - else {\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - }\ - if (XP != 0) {\ - tbinptr* H = treebin_at(M, X->index);\ - if (X == *H) {\ - if ((*H = R) == 0) \ - clear_treemap(M, X->index);\ - }\ - else if (RTCHECK(ok_address(M, XP))) {\ - if (XP->child[0] == X) \ - XP->child[0] = R;\ - else \ - XP->child[1] = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - if (R != 0) {\ - if (RTCHECK(ok_address(M, R))) {\ - tchunkptr C0, C1;\ - R->parent = XP;\ - if ((C0 = X->child[0]) != 0) {\ - if (RTCHECK(ok_address(M, C0))) {\ - R->child[0] = C0;\ - C0->parent = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - if ((C1 = X->child[1]) != 0) {\ - if (RTCHECK(ok_address(M, C1))) {\ - R->child[1] = C1;\ - C1->parent = R;\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ - else\ - CORRUPTION_ERROR_ACTION(M);\ - }\ - }\ -} - -/* Relays to large vs small bin operations */ - -#define insert_chunk(M, P, S)\ - if (is_small(S)) insert_small_chunk(M, P, S)\ - else { tchunkptr TP = (tchunkptr)(P); insert_large_chunk(M, TP, S); } - -#define unlink_chunk(M, P, S)\ - if (is_small(S)) unlink_small_chunk(M, P, S)\ - else { tchunkptr TP = (tchunkptr)(P); unlink_large_chunk(M, TP); } - - -/* Relays to internal calls to malloc/free from realloc, memalign etc */ - -#if ONLY_MSPACES -#define internal_malloc(m, b) mspace_malloc(m, b) -#define internal_free(m, mem) mspace_free(m,mem); -#else /* ONLY_MSPACES */ -#if MSPACES -#define internal_malloc(m, b)\ - (m == gm)? dlmalloc(b) : mspace_malloc(m, b) -#define internal_free(m, mem)\ - if (m == gm) dlfree(mem); else mspace_free(m,mem); -#else /* MSPACES */ -#define internal_malloc(m, b) dlmalloc(b) -#define internal_free(m, mem) dlfree(mem) -#endif /* MSPACES */ -#endif /* ONLY_MSPACES */ - -/* ----------------------- Direct-mmapping chunks ----------------------- */ - -/* - Directly mmapped chunks are set up with an offset to the start of - the mmapped region stored in the prev_foot field of the chunk. This - allows reconstruction of the required argument to MUNMAP when freed, - and also allows adjustment of the returned chunk to meet alignment - requirements (especially in memalign). There is also enough space - allocated to hold a fake next chunk of size SIZE_T_SIZE to maintain - the PINUSE bit so frees can be checked. -*/ - -/* Malloc using mmap */ -static void* mmap_alloc(mstate m, size_t nb) { - size_t mmsize = granularity_align(nb + SIX_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - if (mmsize > nb) { /* Check for wrap around 0 */ - char* mm = (char*)(DIRECT_MMAP(mmsize)); - if (mm != CMFAIL) { - size_t offset = align_offset(chunk2mem(mm)); - size_t psize = mmsize - offset - MMAP_FOOT_PAD; - mchunkptr p = (mchunkptr)(mm + offset); - p->prev_foot = offset | IS_MMAPPED_BIT; - (p)->head = (psize|CINUSE_BIT); - mark_inuse_foot(m, p, psize); - chunk_plus_offset(p, psize)->head = FENCEPOST_HEAD; - chunk_plus_offset(p, psize+SIZE_T_SIZE)->head = 0; - - if (mm < m->least_addr) - m->least_addr = mm; - if ((m->footprint += mmsize) > m->max_footprint) - m->max_footprint = m->footprint; - assert(is_aligned(chunk2mem(p))); - check_mmapped_chunk(m, p); - return chunk2mem(p); - } - } - return 0; -} - -/* Realloc using mmap */ -static mchunkptr mmap_resize(mstate m, mchunkptr oldp, size_t nb) { - size_t oldsize = chunksize(oldp); - if (is_small(nb)) /* Can't shrink mmap regions below small size */ - return 0; - /* Keep old chunk if big enough but not too big */ - if (oldsize >= nb + SIZE_T_SIZE && - (oldsize - nb) <= (mparams.granularity << 1)) - return oldp; - else { - size_t offset = oldp->prev_foot & ~IS_MMAPPED_BIT; - size_t oldmmsize = oldsize + offset + MMAP_FOOT_PAD; - size_t newmmsize = granularity_align(nb + SIX_SIZE_T_SIZES + - CHUNK_ALIGN_MASK); - char* cp = (char*)CALL_MREMAP((char*)oldp - offset, - oldmmsize, newmmsize, 1); - if (cp != CMFAIL) { - mchunkptr newp = (mchunkptr)(cp + offset); - size_t psize = newmmsize - offset - MMAP_FOOT_PAD; - newp->head = (psize|CINUSE_BIT); - mark_inuse_foot(m, newp, psize); - chunk_plus_offset(newp, psize)->head = FENCEPOST_HEAD; - chunk_plus_offset(newp, psize+SIZE_T_SIZE)->head = 0; - - if (cp < m->least_addr) - m->least_addr = cp; - if ((m->footprint += newmmsize - oldmmsize) > m->max_footprint) - m->max_footprint = m->footprint; - check_mmapped_chunk(m, newp); - return newp; - } - } - return 0; -} - -/* -------------------------- mspace management -------------------------- */ - -/* Initialize top chunk and its size */ -static void init_top(mstate m, mchunkptr p, size_t psize) { - /* Ensure alignment */ - size_t offset = align_offset(chunk2mem(p)); - p = (mchunkptr)((char*)p + offset); - psize -= offset; - - m->top = p; - m->topsize = psize; - p->head = psize | PINUSE_BIT; - /* set size of fake trailing chunk holding overhead space only once */ - chunk_plus_offset(p, psize)->head = TOP_FOOT_SIZE; - m->trim_check = mparams.trim_threshold; /* reset on each update */ -} - -/* Initialize bins for a new mstate that is otherwise zeroed out */ -static void init_bins(mstate m) { - /* Establish circular links for smallbins */ - bindex_t i; - for (i = 0; i < NSMALLBINS; ++i) { - sbinptr bin = smallbin_at(m,i); - bin->fd = bin->bk = bin; - } -} - -#if PROCEED_ON_ERROR - -/* default corruption action */ -static void reset_on_error(mstate m) { - int i; - ++malloc_corruption_error_count; - /* Reinitialize fields to forget about all memory */ - m->smallbins = m->treebins = 0; - m->dvsize = m->topsize = 0; - m->seg.base = 0; - m->seg.size = 0; - m->seg.next = 0; - m->top = m->dv = 0; - for (i = 0; i < NTREEBINS; ++i) - *treebin_at(m, i) = 0; - init_bins(m); -} -#endif /* PROCEED_ON_ERROR */ - -/* Allocate chunk and prepend remainder with chunk in successor base. */ -static void* prepend_alloc(mstate m, char* newbase, char* oldbase, - size_t nb) { - mchunkptr p = align_as_chunk(newbase); - mchunkptr oldfirst = align_as_chunk(oldbase); - size_t psize = (char*)oldfirst - (char*)p; - mchunkptr q = chunk_plus_offset(p, nb); - size_t qsize = psize - nb; - set_size_and_pinuse_of_inuse_chunk(m, p, nb); - - assert((char*)oldfirst > (char*)q); - assert(pinuse(oldfirst)); - assert(qsize >= MIN_CHUNK_SIZE); - - /* consolidate remainder with first chunk of old base */ - if (oldfirst == m->top) { - size_t tsize = m->topsize += qsize; - m->top = q; - q->head = tsize | PINUSE_BIT; - check_top_chunk(m, q); - } - else if (oldfirst == m->dv) { - size_t dsize = m->dvsize += qsize; - m->dv = q; - set_size_and_pinuse_of_free_chunk(q, dsize); - } - else { - if (!cinuse(oldfirst)) { - size_t nsize = chunksize(oldfirst); - unlink_chunk(m, oldfirst, nsize); - oldfirst = chunk_plus_offset(oldfirst, nsize); - qsize += nsize; - } - set_free_with_pinuse(q, qsize, oldfirst); - insert_chunk(m, q, qsize); - check_free_chunk(m, q); - } - - check_malloced_chunk(m, chunk2mem(p), nb); - return chunk2mem(p); -} - - -/* Add a segment to hold a new noncontiguous region */ -static void add_segment(mstate m, char* tbase, size_t tsize, flag_t mmapped) { - /* Determine locations and sizes of segment, fenceposts, old top */ - char* old_top = (char*)m->top; - msegmentptr oldsp = segment_holding(m, old_top); - char* old_end = oldsp->base + oldsp->size; - size_t ssize = pad_request(sizeof(struct malloc_segment)); - char* rawsp = old_end - (ssize + FOUR_SIZE_T_SIZES + CHUNK_ALIGN_MASK); - size_t offset = align_offset(chunk2mem(rawsp)); - char* asp = rawsp + offset; - char* csp = (asp < (old_top + MIN_CHUNK_SIZE))? old_top : asp; - mchunkptr sp = (mchunkptr)csp; - msegmentptr ss = (msegmentptr)(chunk2mem(sp)); - mchunkptr tnext = chunk_plus_offset(sp, ssize); - mchunkptr p = tnext; - int nfences = 0; - - /* reset top to new space */ - init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); - - /* Set up segment record */ - assert(is_aligned(ss)); - set_size_and_pinuse_of_inuse_chunk(m, sp, ssize); - *ss = m->seg; /* Push current record */ - m->seg.base = tbase; - m->seg.size = tsize; - m->seg.sflags = mmapped; - m->seg.next = ss; - - /* Insert trailing fenceposts */ - for (;;) { - mchunkptr nextp = chunk_plus_offset(p, SIZE_T_SIZE); - p->head = FENCEPOST_HEAD; - ++nfences; - if ((char*)(&(nextp->head)) < old_end) - p = nextp; - else - break; - } - assert(nfences >= 2); - - /* Insert the rest of old top into a bin as an ordinary free chunk */ - if (csp != old_top) { - mchunkptr q = (mchunkptr)old_top; - size_t psize = csp - old_top; - mchunkptr tn = chunk_plus_offset(q, psize); - set_free_with_pinuse(q, psize, tn); - insert_chunk(m, q, psize); - } - - check_top_chunk(m, m->top); -} - -/* -------------------------- System allocation -------------------------- */ - -/* Get memory from system using MORECORE or MMAP */ -static void* sys_alloc(mstate m, size_t nb) { - char* tbase = CMFAIL; - size_t tsize = 0; - flag_t mmap_flag = 0; - - init_mparams(); - - /* Directly map large chunks */ - if (use_mmap(m) && nb >= mparams.mmap_threshold) { - void* mem = mmap_alloc(m, nb); - if (mem != 0) - return mem; - } - - /* - Try getting memory in any of three ways (in most-preferred to - least-preferred order): - 1. A call to MORECORE that can normally contiguously extend memory. - (disabled if not MORECORE_CONTIGUOUS or not HAVE_MORECORE or - or main space is mmapped or a previous contiguous call failed) - 2. A call to MMAP new space (disabled if not HAVE_MMAP). - Note that under the default settings, if MORECORE is unable to - fulfill a request, and HAVE_MMAP is true, then mmap is - used as a noncontiguous system allocator. This is a useful backup - strategy for systems with holes in address spaces -- in this case - sbrk cannot contiguously expand the heap, but mmap may be able to - find space. - 3. A call to MORECORE that cannot usually contiguously extend memory. - (disabled if not HAVE_MORECORE) - */ - - if (MORECORE_CONTIGUOUS && !use_noncontiguous(m)) { - char* br = CMFAIL; - msegmentptr ss = (m->top == 0)? 0 : segment_holding(m, (char*)m->top); - size_t asize = 0; - ACQUIRE_MORECORE_LOCK(); - - if (ss == 0) { /* First time through or recovery */ - char* base = (char*)CALL_MORECORE(0); - if (base != CMFAIL) { - asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE); - /* Adjust to end on a page boundary */ - if (!is_page_aligned(base)) - asize += (page_align((size_t)base) - (size_t)base); - /* Can't call MORECORE if size is negative when treated as signed */ - if (asize < HALF_MAX_SIZE_T && - (br = (char*)(CALL_MORECORE(asize))) == base) { - tbase = base; - tsize = asize; - } - } - } - else { - /* Subtract out existing available top space from MORECORE request. */ - asize = granularity_align(nb - m->topsize + TOP_FOOT_SIZE + SIZE_T_ONE); - /* Use mem here only if it did continuously extend old space */ - if (asize < HALF_MAX_SIZE_T && - (br = (char*)(CALL_MORECORE(asize))) == ss->base+ss->size) { - tbase = br; - tsize = asize; - } - } - - if (tbase == CMFAIL) { /* Cope with partial failure */ - if (br != CMFAIL) { /* Try to use/extend the space we did get */ - if (asize < HALF_MAX_SIZE_T && - asize < nb + TOP_FOOT_SIZE + SIZE_T_ONE) { - size_t esize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE - asize); - if (esize < HALF_MAX_SIZE_T) { - char* end = (char*)CALL_MORECORE(esize); - if (end != CMFAIL) - asize += esize; - else { /* Can't use; try to release */ - CALL_MORECORE(-asize); - br = CMFAIL; - } - } - } - } - if (br != CMFAIL) { /* Use the space we did get */ - tbase = br; - tsize = asize; - } - else - disable_contiguous(m); /* Don't try contiguous path in the future */ - } - - RELEASE_MORECORE_LOCK(); - } - - if (HAVE_MMAP && tbase == CMFAIL) { /* Try MMAP */ - size_t req = nb + TOP_FOOT_SIZE + SIZE_T_ONE; - size_t rsize = granularity_align(req); - if (rsize > nb) { /* Fail if wraps around zero */ - char* mp = (char*)(CALL_MMAP(rsize)); - if (mp != CMFAIL) { - tbase = mp; - tsize = rsize; - mmap_flag = IS_MMAPPED_BIT; - } - } - } - - if (HAVE_MORECORE && tbase == CMFAIL) { /* Try noncontiguous MORECORE */ - size_t asize = granularity_align(nb + TOP_FOOT_SIZE + SIZE_T_ONE); - if (asize < HALF_MAX_SIZE_T) { - char* br = CMFAIL; - char* end = CMFAIL; - ACQUIRE_MORECORE_LOCK(); - br = (char*)(CALL_MORECORE(asize)); - end = (char*)(CALL_MORECORE(0)); - RELEASE_MORECORE_LOCK(); - if (br != CMFAIL && end != CMFAIL && br < end) { - size_t ssize = end - br; - if (ssize > nb + TOP_FOOT_SIZE) { - tbase = br; - tsize = ssize; - } - } - } - } - - if (tbase != CMFAIL) { - - if ((m->footprint += tsize) > m->max_footprint) - m->max_footprint = m->footprint; - - if (!is_initialized(m)) { /* first-time initialization */ - m->seg.base = m->least_addr = tbase; - m->seg.size = tsize; - m->seg.sflags = mmap_flag; - m->magic = mparams.magic; - init_bins(m); - if (is_global(m)) - init_top(m, (mchunkptr)tbase, tsize - TOP_FOOT_SIZE); - else { - /* Offset top by embedded malloc_state */ - mchunkptr mn = next_chunk(mem2chunk(m)); - init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) -TOP_FOOT_SIZE); - } - } - - else { - /* Try to merge with an existing segment */ - msegmentptr sp = &m->seg; - while (sp != 0 && tbase != sp->base + sp->size) - sp = sp->next; - if (sp != 0 && - !is_extern_segment(sp) && - (sp->sflags & IS_MMAPPED_BIT) == mmap_flag && - segment_holds(sp, m->top)) { /* append */ - sp->size += tsize; - init_top(m, m->top, m->topsize + tsize); - } - else { - if (tbase < m->least_addr) - m->least_addr = tbase; - sp = &m->seg; - while (sp != 0 && sp->base != tbase + tsize) - sp = sp->next; - if (sp != 0 && - !is_extern_segment(sp) && - (sp->sflags & IS_MMAPPED_BIT) == mmap_flag) { - char* oldbase = sp->base; - sp->base = tbase; - sp->size += tsize; - return prepend_alloc(m, tbase, oldbase, nb); - } - else - add_segment(m, tbase, tsize, mmap_flag); - } - } - - if (nb < m->topsize) { /* Allocate from new or extended top space */ - size_t rsize = m->topsize -= nb; - mchunkptr p = m->top; - mchunkptr r = m->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(m, p, nb); - check_top_chunk(m, m->top); - check_malloced_chunk(m, chunk2mem(p), nb); - return chunk2mem(p); - } - } - - MALLOC_FAILURE_ACTION; - return 0; -} - -/* ----------------------- system deallocation -------------------------- */ - -/* Unmap and unlink any mmapped segments that don't contain used chunks */ -static size_t release_unused_segments(mstate m) { - size_t released = 0; - msegmentptr pred = &m->seg; - msegmentptr sp = pred->next; - while (sp != 0) { - char* base = sp->base; - size_t size = sp->size; - msegmentptr next = sp->next; - if (is_mmapped_segment(sp) && !is_extern_segment(sp)) { - mchunkptr p = align_as_chunk(base); - size_t psize = chunksize(p); - /* Can unmap if first chunk holds entire segment and not pinned */ - if (!cinuse(p) && (char*)p + psize >= base + size - TOP_FOOT_SIZE) { - tchunkptr tp = (tchunkptr)p; - assert(segment_holds(sp, (char*)sp)); - if (p == m->dv) { - m->dv = 0; - m->dvsize = 0; - } - else { - unlink_large_chunk(m, tp); - } - if (CALL_MUNMAP(base, size) == 0) { - released += size; - m->footprint -= size; - /* unlink obsoleted record */ - sp = pred; - sp->next = next; - } - else { /* back out if cannot unmap */ - insert_large_chunk(m, tp, psize); - } - } - } - pred = sp; - sp = next; - } - return released; -} - -static int sys_trim(mstate m, size_t pad) { - size_t released = 0; - if (pad < MAX_REQUEST && is_initialized(m)) { - pad += TOP_FOOT_SIZE; /* ensure enough room for segment overhead */ - - if (m->topsize > pad) { - /* Shrink top space in granularity-size units, keeping at least one */ - size_t unit = mparams.granularity; - size_t extra = ((m->topsize - pad + (unit - SIZE_T_ONE)) / unit - - SIZE_T_ONE) * unit; - msegmentptr sp = segment_holding(m, (char*)m->top); - - if (!is_extern_segment(sp)) { - if (is_mmapped_segment(sp)) { - if (HAVE_MMAP && - sp->size >= extra && - !has_segment_link(m, sp)) { /* can't shrink if pinned */ - size_t newsize = sp->size - extra; - /* Prefer mremap, fall back to munmap */ - if ((CALL_MREMAP(sp->base, sp->size, newsize, 0) != MFAIL) || - (CALL_MUNMAP(sp->base + newsize, extra) == 0)) { - released = extra; - } - } - } - else if (HAVE_MORECORE) { - if (extra >= HALF_MAX_SIZE_T) /* Avoid wrapping negative */ - extra = (HALF_MAX_SIZE_T) + SIZE_T_ONE - unit; - ACQUIRE_MORECORE_LOCK(); - { - /* Make sure end of memory is where we last set it. */ - char* old_br = (char*)(CALL_MORECORE(0)); - if (old_br == sp->base + sp->size) { - char* rel_br = (char*)(CALL_MORECORE(-extra)); - char* new_br = (char*)(CALL_MORECORE(0)); - if (rel_br != CMFAIL && new_br < old_br) - released = old_br - new_br; - } - } - RELEASE_MORECORE_LOCK(); - } - } - - if (released != 0) { - sp->size -= released; - m->footprint -= released; - init_top(m, m->top, m->topsize - released); - check_top_chunk(m, m->top); - } - } - - /* Unmap any unused mmapped segments */ - if (HAVE_MMAP) - released += release_unused_segments(m); - - /* On failure, disable autotrim to avoid repeated failed future calls */ - if (released == 0) - m->trim_check = MAX_SIZE_T; - } - - return (released != 0)? 1 : 0; -} - -/* ---------------------------- malloc support --------------------------- */ - -/* allocate a large request from the best fitting chunk in a treebin */ -static void* tmalloc_large(mstate m, size_t nb) { - tchunkptr v = 0; - size_t rsize = -nb; /* Unsigned negation */ - tchunkptr t; - bindex_t idx; - compute_tree_index(nb, idx); - - if ((t = *treebin_at(m, idx)) != 0) { - /* Traverse tree for this bin looking for node with size == nb */ - size_t sizebits = nb << leftshift_for_tree_index(idx); - tchunkptr rst = 0; /* The deepest untaken right subtree */ - for (;;) { - tchunkptr rt; - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - v = t; - if ((rsize = trem) == 0) - break; - } - rt = t->child[1]; - t = t->child[(sizebits >> (SIZE_T_BITSIZE-SIZE_T_ONE)) & 1]; - if (rt != 0 && rt != t) - rst = rt; - if (t == 0) { - t = rst; /* set t to least subtree holding sizes > nb */ - break; - } - sizebits <<= 1; - } - } - - if (t == 0 && v == 0) { /* set t to root of next non-empty treebin */ - binmap_t leftbits = left_bits(idx2bit(idx)) & m->treemap; - if (leftbits != 0) { - bindex_t i; - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - t = *treebin_at(m, i); - } - } - - while (t != 0) { /* find smallest of tree or subtree */ - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - rsize = trem; - v = t; - } - t = leftmost_child(t); - } - - /* If dv is a better fit, return 0 so malloc will use it */ - if (v != 0 && rsize < (size_t)(m->dvsize - nb)) { - if (RTCHECK(ok_address(m, v))) { /* split */ - mchunkptr r = chunk_plus_offset(v, nb); - assert(chunksize(v) == rsize + nb); - if (RTCHECK(ok_next(v, r))) { - unlink_large_chunk(m, v); - if (rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(m, v, (rsize + nb)); - else { - set_size_and_pinuse_of_inuse_chunk(m, v, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - insert_chunk(m, r, rsize); - } - return chunk2mem(v); - } - } - CORRUPTION_ERROR_ACTION(m); - } - return 0; -} - -/* allocate a small request from the best fitting chunk in a treebin */ -static void* tmalloc_small(mstate m, size_t nb) { - tchunkptr t, v; - size_t rsize; - bindex_t i; - binmap_t leastbit = least_bit(m->treemap); - compute_bit2idx(leastbit, i); - - v = t = *treebin_at(m, i); - rsize = chunksize(t) - nb; - - while ((t = leftmost_child(t)) != 0) { - size_t trem = chunksize(t) - nb; - if (trem < rsize) { - rsize = trem; - v = t; - } - } - - if (RTCHECK(ok_address(m, v))) { - mchunkptr r = chunk_plus_offset(v, nb); - assert(chunksize(v) == rsize + nb); - if (RTCHECK(ok_next(v, r))) { - unlink_large_chunk(m, v); - if (rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(m, v, (rsize + nb)); - else { - set_size_and_pinuse_of_inuse_chunk(m, v, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(m, r, rsize); - } - return chunk2mem(v); - } - } - - CORRUPTION_ERROR_ACTION(m); - return 0; -} - -/* --------------------------- realloc support --------------------------- */ - -static void* internal_realloc(mstate m, void* oldmem, size_t bytes) { - if (bytes >= MAX_REQUEST) { - MALLOC_FAILURE_ACTION; - return 0; - } - if (!PREACTION(m)) { - mchunkptr oldp = mem2chunk(oldmem); - size_t oldsize = chunksize(oldp); - mchunkptr next = chunk_plus_offset(oldp, oldsize); - mchunkptr newp = 0; - void* extra = 0; - - /* Try to either shrink or extend into top. Else malloc-copy-free */ - - if (RTCHECK(ok_address(m, oldp) && ok_cinuse(oldp) && - ok_next(oldp, next) && ok_pinuse(next))) { - size_t nb = request2size(bytes); - if (is_mmapped(oldp)) - newp = mmap_resize(m, oldp, nb); - else if (oldsize >= nb) { /* already big enough */ - size_t rsize = oldsize - nb; - newp = oldp; - if (rsize >= MIN_CHUNK_SIZE) { - mchunkptr remainder = chunk_plus_offset(newp, nb); - set_inuse(m, newp, nb); - set_inuse(m, remainder, rsize); - extra = chunk2mem(remainder); - } - } - else if (next == m->top && oldsize + m->topsize > nb) { - /* Expand into top */ - size_t newsize = oldsize + m->topsize; - size_t newtopsize = newsize - nb; - mchunkptr newtop = chunk_plus_offset(oldp, nb); - set_inuse(m, oldp, nb); - newtop->head = newtopsize |PINUSE_BIT; - m->top = newtop; - m->topsize = newtopsize; - newp = oldp; - } - } - else { - USAGE_ERROR_ACTION(m, oldmem); - POSTACTION(m); - return 0; - } - - POSTACTION(m); - - if (newp != 0) { - if (extra != 0) { - internal_free(m, extra); - } - check_inuse_chunk(m, newp); - return chunk2mem(newp); - } - else { - void* newmem = internal_malloc(m, bytes); - if (newmem != 0) { - size_t oc = oldsize - overhead_for(oldp); - memcpy(newmem, oldmem, (oc < bytes)? oc : bytes); - internal_free(m, oldmem); - } - return newmem; - } - } - return 0; -} - -/* --------------------------- memalign support -------------------------- */ - -static void* internal_memalign(mstate m, size_t alignment, size_t bytes) { - if (alignment <= MALLOC_ALIGNMENT) /* Can just use malloc */ - return internal_malloc(m, bytes); - if (alignment < MIN_CHUNK_SIZE) /* must be at least a minimum chunk size */ - alignment = MIN_CHUNK_SIZE; - if ((alignment & (alignment-SIZE_T_ONE)) != 0) {/* Ensure a power of 2 */ - size_t a = MALLOC_ALIGNMENT << 1; - while (a < alignment) a <<= 1; - alignment = a; - } - - if (bytes >= MAX_REQUEST - alignment) { - if (m != 0) { /* Test isn't needed but avoids compiler warning */ - MALLOC_FAILURE_ACTION; - } - } - else { - size_t nb = request2size(bytes); - size_t req = nb + alignment + MIN_CHUNK_SIZE - CHUNK_OVERHEAD; - char* mem = (char*)internal_malloc(m, req); - if (mem != 0) { - void* leader = 0; - void* trailer = 0; - mchunkptr p = mem2chunk(mem); - - if (PREACTION(m)) return 0; - if ((((size_t)(mem)) % alignment) != 0) { /* misaligned */ - /* - Find an aligned spot inside chunk. Since we need to give - back leading space in a chunk of at least MIN_CHUNK_SIZE, if - the first calculation places us at a spot with less than - MIN_CHUNK_SIZE leader, we can move to the next aligned spot. - We've allocated enough total room so that this is always - possible. - */ - char* br = (char*)mem2chunk((size_t)(((size_t)(mem + - alignment - - SIZE_T_ONE)) & - -alignment)); - char* pos = ((size_t)(br - (char*)(p)) >= MIN_CHUNK_SIZE)? - br : br+alignment; - mchunkptr newp = (mchunkptr)pos; - size_t leadsize = pos - (char*)(p); - size_t newsize = chunksize(p) - leadsize; - - if (is_mmapped(p)) { /* For mmapped chunks, just adjust offset */ - newp->prev_foot = p->prev_foot + leadsize; - newp->head = (newsize|CINUSE_BIT); - } - else { /* Otherwise, give back leader, use the rest */ - set_inuse(m, newp, newsize); - set_inuse(m, p, leadsize); - leader = chunk2mem(p); - } - p = newp; - } - - /* Give back spare room at the end */ - if (!is_mmapped(p)) { - size_t size = chunksize(p); - if (size > nb + MIN_CHUNK_SIZE) { - size_t remainder_size = size - nb; - mchunkptr remainder = chunk_plus_offset(p, nb); - set_inuse(m, p, nb); - set_inuse(m, remainder, remainder_size); - trailer = chunk2mem(remainder); - } - } - - assert (chunksize(p) >= nb); - assert((((size_t)(chunk2mem(p))) % alignment) == 0); - check_inuse_chunk(m, p); - POSTACTION(m); - if (leader != 0) { - internal_free(m, leader); - } - if (trailer != 0) { - internal_free(m, trailer); - } - return chunk2mem(p); - } - } - return 0; -} - -/* ------------------------ comalloc/coalloc support --------------------- */ - -static void** ialloc(mstate m, - size_t n_elements, - size_t* sizes, - int opts, - void* chunks[]) { - /* - This provides common support for independent_X routines, handling - all of the combinations that can result. - - The opts arg has: - bit 0 set if all elements are same size (using sizes[0]) - bit 1 set if elements should be zeroed - */ - - size_t element_size; /* chunksize of each element, if all same */ - size_t contents_size; /* total size of elements */ - size_t array_size; /* request size of pointer array */ - void* mem; /* malloced aggregate space */ - mchunkptr p; /* corresponding chunk */ - size_t remainder_size; /* remaining bytes while splitting */ - void** marray; /* either "chunks" or malloced ptr array */ - mchunkptr array_chunk; /* chunk for malloced ptr array */ - flag_t was_enabled; /* to disable mmap */ - size_t size; - size_t i; - - /* compute array length, if needed */ - if (chunks != 0) { - if (n_elements == 0) - return chunks; /* nothing to do */ - marray = chunks; - array_size = 0; - } - else { - /* if empty req, must still return chunk representing empty array */ - if (n_elements == 0) - return (void**)internal_malloc(m, 0); - marray = 0; - array_size = request2size(n_elements * (sizeof(void*))); - } - - /* compute total element size */ - if (opts & 0x1) { /* all-same-size */ - element_size = request2size(*sizes); - contents_size = n_elements * element_size; - } - else { /* add up all the sizes */ - element_size = 0; - contents_size = 0; - for (i = 0; i != n_elements; ++i) - contents_size += request2size(sizes[i]); - } - - size = contents_size + array_size; - - /* - Allocate the aggregate chunk. First disable direct-mmapping so - malloc won't use it, since we would not be able to later - free/realloc space internal to a segregated mmap region. - */ - was_enabled = use_mmap(m); - disable_mmap(m); - mem = internal_malloc(m, size - CHUNK_OVERHEAD); - if (was_enabled) - enable_mmap(m); - if (mem == 0) - return 0; - - if (PREACTION(m)) return 0; - p = mem2chunk(mem); - remainder_size = chunksize(p); - - assert(!is_mmapped(p)); - - if (opts & 0x2) { /* optionally clear the elements */ - memset((size_t*)mem, 0, remainder_size - SIZE_T_SIZE - array_size); - } - - /* If not provided, allocate the pointer array as final part of chunk */ - if (marray == 0) { - size_t array_chunk_size; - array_chunk = chunk_plus_offset(p, contents_size); - array_chunk_size = remainder_size - contents_size; - marray = (void**) (chunk2mem(array_chunk)); - set_size_and_pinuse_of_inuse_chunk(m, array_chunk, array_chunk_size); - remainder_size = contents_size; - } - - /* split out elements */ - for (i = 0; ; ++i) { - marray[i] = chunk2mem(p); - if (i != n_elements-1) { - if (element_size != 0) - size = element_size; - else - size = request2size(sizes[i]); - remainder_size -= size; - set_size_and_pinuse_of_inuse_chunk(m, p, size); - p = chunk_plus_offset(p, size); - } - else { /* the final element absorbs any overallocation slop */ - set_size_and_pinuse_of_inuse_chunk(m, p, remainder_size); - break; - } - } - -#if DEBUG - if (marray != chunks) { - /* final element must have exactly exhausted chunk */ - if (element_size != 0) { - assert(remainder_size == element_size); - } - else { - assert(remainder_size == request2size(sizes[i])); - } - check_inuse_chunk(m, mem2chunk(marray)); - } - for (i = 0; i != n_elements; ++i) - check_inuse_chunk(m, mem2chunk(marray[i])); - -#endif /* DEBUG */ - - POSTACTION(m); - return marray; -} - - -/* -------------------------- public routines ---------------------------- */ - -#if !ONLY_MSPACES - -void* dlmalloc(size_t bytes) { - /* - Basic algorithm: - If a small request (< 256 bytes minus per-chunk overhead): - 1. If one exists, use a remainderless chunk in associated smallbin. - (Remainderless means that there are too few excess bytes to - represent as a chunk.) - 2. If it is big enough, use the dv chunk, which is normally the - chunk adjacent to the one used for the most recent small request. - 3. If one exists, split the smallest available chunk in a bin, - saving remainder in dv. - 4. If it is big enough, use the top chunk. - 5. If available, get memory from system and use it - Otherwise, for a large request: - 1. Find the smallest available binned chunk that fits, and use it - if it is better fitting than dv chunk, splitting if necessary. - 2. If better fitting than any binned chunk, use the dv chunk. - 3. If it is big enough, use the top chunk. - 4. If request size >= mmap threshold, try to directly mmap this chunk. - 5. If available, get memory from system and use it - - The ugly goto's here ensure that postaction occurs along all paths. - */ - - if (!PREACTION(gm)) { - void* mem; - size_t nb; - if (bytes <= MAX_SMALL_REQUEST) { - bindex_t idx; - binmap_t smallbits; - nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); - idx = small_index(nb); - smallbits = gm->smallmap >> idx; - - if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ - mchunkptr b, p; - idx += ~smallbits & 1; /* Uses next bin if idx empty */ - b = smallbin_at(gm, idx); - p = b->fd; - assert(chunksize(p) == small_index2size(idx)); - unlink_first_small_chunk(gm, b, p, idx); - set_inuse_and_pinuse(gm, p, small_index2size(idx)); - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - else if (nb > gm->dvsize) { - if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ - mchunkptr b, p, r; - size_t rsize; - bindex_t i; - binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - b = smallbin_at(gm, i); - p = b->fd; - assert(chunksize(p) == small_index2size(i)); - unlink_first_small_chunk(gm, b, p, i); - rsize = small_index2size(i) - nb; - /* Fit here cannot be remainderless if 4byte sizes */ - if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(gm, p, small_index2size(i)); - else { - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - r = chunk_plus_offset(p, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(gm, r, rsize); - } - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - else if (gm->treemap != 0 && (mem = tmalloc_small(gm, nb)) != 0) { - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - } - } - else if (bytes >= MAX_REQUEST) - nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ - else { - nb = pad_request(bytes); - if (gm->treemap != 0 && (mem = tmalloc_large(gm, nb)) != 0) { - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - } - - if (nb <= gm->dvsize) { - size_t rsize = gm->dvsize - nb; - mchunkptr p = gm->dv; - if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ - mchunkptr r = gm->dv = chunk_plus_offset(p, nb); - gm->dvsize = rsize; - set_size_and_pinuse_of_free_chunk(r, rsize); - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - } - else { /* exhaust dv */ - size_t dvs = gm->dvsize; - gm->dvsize = 0; - gm->dv = 0; - set_inuse_and_pinuse(gm, p, dvs); - } - mem = chunk2mem(p); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - else if (nb < gm->topsize) { /* Split top */ - size_t rsize = gm->topsize -= nb; - mchunkptr p = gm->top; - mchunkptr r = gm->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(gm, p, nb); - mem = chunk2mem(p); - check_top_chunk(gm, gm->top); - check_malloced_chunk(gm, mem, nb); - goto postaction; - } - - mem = sys_alloc(gm, nb); - - postaction: - POSTACTION(gm); - return mem; - } - - return 0; -} - -void dlfree(void* mem) { - /* - Consolidate freed chunks with preceeding or succeeding bordering - free chunks, if they exist, and then place in a bin. Intermixed - with special cases for top, dv, mmapped chunks, and usage errors. - */ - - if (mem != 0) { - mchunkptr p = mem2chunk(mem); -#if FOOTERS - mstate fm = get_mstate_for(p); - if (!ok_magic(fm)) { - USAGE_ERROR_ACTION(fm, p); - return; - } -#else /* FOOTERS */ -#define fm gm -#endif /* FOOTERS */ - if (!PREACTION(fm)) { - check_inuse_chunk(fm, p); - if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) { - size_t psize = chunksize(p); - mchunkptr next = chunk_plus_offset(p, psize); - if (!pinuse(p)) { - size_t prevsize = p->prev_foot; - if ((prevsize & IS_MMAPPED_BIT) != 0) { - prevsize &= ~IS_MMAPPED_BIT; - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) - fm->footprint -= psize; - goto postaction; - } - else { - mchunkptr prev = chunk_minus_offset(p, prevsize); - psize += prevsize; - p = prev; - if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ - if (p != fm->dv) { - unlink_chunk(fm, p, prevsize); - } - else if ((next->head & INUSE_BITS) == INUSE_BITS) { - fm->dvsize = psize; - set_free_with_pinuse(p, psize, next); - goto postaction; - } - } - else - goto erroraction; - } - } - - if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { - if (!cinuse(next)) { /* consolidate forward */ - if (next == fm->top) { - size_t tsize = fm->topsize += psize; - fm->top = p; - p->head = tsize | PINUSE_BIT; - if (p == fm->dv) { - fm->dv = 0; - fm->dvsize = 0; - } - if (should_trim(fm, tsize)) - sys_trim(fm, 0); - goto postaction; - } - else if (next == fm->dv) { - size_t dsize = fm->dvsize += psize; - fm->dv = p; - set_size_and_pinuse_of_free_chunk(p, dsize); - goto postaction; - } - else { - size_t nsize = chunksize(next); - psize += nsize; - unlink_chunk(fm, next, nsize); - set_size_and_pinuse_of_free_chunk(p, psize); - if (p == fm->dv) { - fm->dvsize = psize; - goto postaction; - } - } - } - else - set_free_with_pinuse(p, psize, next); - insert_chunk(fm, p, psize); - check_free_chunk(fm, p); - goto postaction; - } - } - erroraction: - USAGE_ERROR_ACTION(fm, p); - postaction: - POSTACTION(fm); - } - } -#if !FOOTERS -#undef fm -#endif /* FOOTERS */ -} - -void* dlcalloc(size_t n_elements, size_t elem_size) { - void* mem; - size_t req = 0; - if (n_elements != 0) { - req = n_elements * elem_size; - if (((n_elements | elem_size) & ~(size_t)0xffff) && - (req / n_elements != elem_size)) - req = MAX_SIZE_T; /* force downstream failure on overflow */ - } - mem = dlmalloc(req); - if (mem != 0 && calloc_must_clear(mem2chunk(mem))) - memset(mem, 0, req); - return mem; -} - -void* dlrealloc(void* oldmem, size_t bytes) { - if (oldmem == 0) - return dlmalloc(bytes); -#ifdef REALLOC_ZERO_BYTES_FREES - if (bytes == 0) { - dlfree(oldmem); - return 0; - } -#endif /* REALLOC_ZERO_BYTES_FREES */ - else { -#if ! FOOTERS - mstate m = gm; -#else /* FOOTERS */ - mstate m = get_mstate_for(mem2chunk(oldmem)); - if (!ok_magic(m)) { - USAGE_ERROR_ACTION(m, oldmem); - return 0; - } -#endif /* FOOTERS */ - return internal_realloc(m, oldmem, bytes); - } -} - -void* dlmemalign(size_t alignment, size_t bytes) { - return internal_memalign(gm, alignment, bytes); -} - -void** dlindependent_calloc(size_t n_elements, size_t elem_size, - void* chunks[]) { - size_t sz = elem_size; /* serves as 1-element array */ - return ialloc(gm, n_elements, &sz, 3, chunks); -} - -void** dlindependent_comalloc(size_t n_elements, size_t sizes[], - void* chunks[]) { - return ialloc(gm, n_elements, sizes, 0, chunks); -} - -void* dlvalloc(size_t bytes) { - size_t pagesz; - init_mparams(); - pagesz = mparams.page_size; - return dlmemalign(pagesz, bytes); -} - -void* dlpvalloc(size_t bytes) { - size_t pagesz; - init_mparams(); - pagesz = mparams.page_size; - return dlmemalign(pagesz, (bytes + pagesz - SIZE_T_ONE) & ~(pagesz - SIZE_T_ONE)); -} - -int dlmalloc_trim(size_t pad) { - int result = 0; - if (!PREACTION(gm)) { - result = sys_trim(gm, pad); - POSTACTION(gm); - } - return result; -} - -size_t dlmalloc_footprint(void) { - return gm->footprint; -} - -size_t dlmalloc_max_footprint(void) { - return gm->max_footprint; -} - -#if !NO_MALLINFO -struct mallinfo dlmallinfo(void) { - return internal_mallinfo(gm); -} -#endif /* NO_MALLINFO */ - -void dlmalloc_stats() { - internal_malloc_stats(gm); -} - -size_t dlmalloc_usable_size(void* mem) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); - if (cinuse(p)) - return chunksize(p) - overhead_for(p); - } - return 0; -} - -int dlmallopt(int param_number, int value) { - return change_mparam(param_number, value); -} - -#endif /* !ONLY_MSPACES */ - -/* ----------------------------- user mspaces ---------------------------- */ - -#if MSPACES - -static mstate init_user_mstate(char* tbase, size_t tsize) { - size_t msize = pad_request(sizeof(struct malloc_state)); - mchunkptr mn; - mchunkptr msp = align_as_chunk(tbase); - mstate m = (mstate)(chunk2mem(msp)); - memset(m, 0, msize); - INITIAL_LOCK(&m->mutex); - msp->head = (msize|PINUSE_BIT|CINUSE_BIT); - m->seg.base = m->least_addr = tbase; - m->seg.size = m->footprint = m->max_footprint = tsize; - m->magic = mparams.magic; - m->mflags = mparams.default_mflags; - disable_contiguous(m); - init_bins(m); - mn = next_chunk(mem2chunk(m)); - init_top(m, mn, (size_t)((tbase + tsize) - (char*)mn) - TOP_FOOT_SIZE); - check_top_chunk(m, m->top); - return m; -} - -mspace create_mspace(size_t capacity, int locked) { - mstate m = 0; - size_t msize = pad_request(sizeof(struct malloc_state)); - init_mparams(); /* Ensure pagesize etc initialized */ - - if (capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { - size_t rs = ((capacity == 0)? mparams.granularity : - (capacity + TOP_FOOT_SIZE + msize)); - size_t tsize = granularity_align(rs); - char* tbase = (char*)(CALL_MMAP(tsize)); - if (tbase != CMFAIL) { - m = init_user_mstate(tbase, tsize); - m->seg.sflags = IS_MMAPPED_BIT; - set_lock(m, locked); - } - } - return (mspace)m; -} - -mspace create_mspace_with_base(void* base, size_t capacity, int locked) { - mstate m = 0; - size_t msize = pad_request(sizeof(struct malloc_state)); - init_mparams(); /* Ensure pagesize etc initialized */ - - if (capacity > msize + TOP_FOOT_SIZE && - capacity < (size_t) -(msize + TOP_FOOT_SIZE + mparams.page_size)) { - m = init_user_mstate((char*)base, capacity); - m->seg.sflags = EXTERN_BIT; - set_lock(m, locked); - } - return (mspace)m; -} - -size_t destroy_mspace(mspace msp) { - size_t freed = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - msegmentptr sp = &ms->seg; - while (sp != 0) { - char* base = sp->base; - size_t size = sp->size; - flag_t flag = sp->sflags; - sp = sp->next; - if ((flag & IS_MMAPPED_BIT) && !(flag & EXTERN_BIT) && - CALL_MUNMAP(base, size) == 0) - freed += size; - } - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return freed; -} - -/* - mspace versions of routines are near-clones of the global - versions. This is not so nice but better than the alternatives. -*/ - - -void* mspace_malloc(mspace msp, size_t bytes) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - if (!PREACTION(ms)) { - void* mem; - size_t nb; - if (bytes <= MAX_SMALL_REQUEST) { - bindex_t idx; - binmap_t smallbits; - nb = (bytes < MIN_REQUEST)? MIN_CHUNK_SIZE : pad_request(bytes); - idx = small_index(nb); - smallbits = ms->smallmap >> idx; - - if ((smallbits & 0x3U) != 0) { /* Remainderless fit to a smallbin. */ - mchunkptr b, p; - idx += ~smallbits & 1; /* Uses next bin if idx empty */ - b = smallbin_at(ms, idx); - p = b->fd; - assert(chunksize(p) == small_index2size(idx)); - unlink_first_small_chunk(ms, b, p, idx); - set_inuse_and_pinuse(ms, p, small_index2size(idx)); - mem = chunk2mem(p); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - else if (nb > ms->dvsize) { - if (smallbits != 0) { /* Use chunk in next nonempty smallbin */ - mchunkptr b, p, r; - size_t rsize; - bindex_t i; - binmap_t leftbits = (smallbits << idx) & left_bits(idx2bit(idx)); - binmap_t leastbit = least_bit(leftbits); - compute_bit2idx(leastbit, i); - b = smallbin_at(ms, i); - p = b->fd; - assert(chunksize(p) == small_index2size(i)); - unlink_first_small_chunk(ms, b, p, i); - rsize = small_index2size(i) - nb; - /* Fit here cannot be remainderless if 4byte sizes */ - if (SIZE_T_SIZE != 4 && rsize < MIN_CHUNK_SIZE) - set_inuse_and_pinuse(ms, p, small_index2size(i)); - else { - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - r = chunk_plus_offset(p, nb); - set_size_and_pinuse_of_free_chunk(r, rsize); - replace_dv(ms, r, rsize); - } - mem = chunk2mem(p); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - else if (ms->treemap != 0 && (mem = tmalloc_small(ms, nb)) != 0) { - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - } - } - else if (bytes >= MAX_REQUEST) - nb = MAX_SIZE_T; /* Too big to allocate. Force failure (in sys alloc) */ - else { - nb = pad_request(bytes); - if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) { - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - } - - if (nb <= ms->dvsize) { - size_t rsize = ms->dvsize - nb; - mchunkptr p = ms->dv; - if (rsize >= MIN_CHUNK_SIZE) { /* split dv */ - mchunkptr r = ms->dv = chunk_plus_offset(p, nb); - ms->dvsize = rsize; - set_size_and_pinuse_of_free_chunk(r, rsize); - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - } - else { /* exhaust dv */ - size_t dvs = ms->dvsize; - ms->dvsize = 0; - ms->dv = 0; - set_inuse_and_pinuse(ms, p, dvs); - } - mem = chunk2mem(p); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - else if (nb < ms->topsize) { /* Split top */ - size_t rsize = ms->topsize -= nb; - mchunkptr p = ms->top; - mchunkptr r = ms->top = chunk_plus_offset(p, nb); - r->head = rsize | PINUSE_BIT; - set_size_and_pinuse_of_inuse_chunk(ms, p, nb); - mem = chunk2mem(p); - check_top_chunk(ms, ms->top); - check_malloced_chunk(ms, mem, nb); - goto postaction; - } - - mem = sys_alloc(ms, nb); - - postaction: - POSTACTION(ms); - return mem; - } - - return 0; -} - -void mspace_free(mspace msp, void* mem) { - if (mem != 0) { - mchunkptr p = mem2chunk(mem); -#if FOOTERS - mstate fm = get_mstate_for(p); -#else /* FOOTERS */ - mstate fm = (mstate)msp; -#endif /* FOOTERS */ - if (!ok_magic(fm)) { - USAGE_ERROR_ACTION(fm, p); - return; - } - if (!PREACTION(fm)) { - check_inuse_chunk(fm, p); - if (RTCHECK(ok_address(fm, p) && ok_cinuse(p))) { - size_t psize = chunksize(p); - mchunkptr next = chunk_plus_offset(p, psize); - if (!pinuse(p)) { - size_t prevsize = p->prev_foot; - if ((prevsize & IS_MMAPPED_BIT) != 0) { - prevsize &= ~IS_MMAPPED_BIT; - psize += prevsize + MMAP_FOOT_PAD; - if (CALL_MUNMAP((char*)p - prevsize, psize) == 0) - fm->footprint -= psize; - goto postaction; - } - else { - mchunkptr prev = chunk_minus_offset(p, prevsize); - psize += prevsize; - p = prev; - if (RTCHECK(ok_address(fm, prev))) { /* consolidate backward */ - if (p != fm->dv) { - unlink_chunk(fm, p, prevsize); - } - else if ((next->head & INUSE_BITS) == INUSE_BITS) { - fm->dvsize = psize; - set_free_with_pinuse(p, psize, next); - goto postaction; - } - } - else - goto erroraction; - } - } - - if (RTCHECK(ok_next(p, next) && ok_pinuse(next))) { - if (!cinuse(next)) { /* consolidate forward */ - if (next == fm->top) { - size_t tsize = fm->topsize += psize; - fm->top = p; - p->head = tsize | PINUSE_BIT; - if (p == fm->dv) { - fm->dv = 0; - fm->dvsize = 0; - } - if (should_trim(fm, tsize)) - sys_trim(fm, 0); - goto postaction; - } - else if (next == fm->dv) { - size_t dsize = fm->dvsize += psize; - fm->dv = p; - set_size_and_pinuse_of_free_chunk(p, dsize); - goto postaction; - } - else { - size_t nsize = chunksize(next); - psize += nsize; - unlink_chunk(fm, next, nsize); - set_size_and_pinuse_of_free_chunk(p, psize); - if (p == fm->dv) { - fm->dvsize = psize; - goto postaction; - } - } - } - else - set_free_with_pinuse(p, psize, next); - insert_chunk(fm, p, psize); - check_free_chunk(fm, p); - goto postaction; - } - } - erroraction: - USAGE_ERROR_ACTION(fm, p); - postaction: - POSTACTION(fm); - } - } -} - -void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size) { - void* mem; - size_t req = 0; - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - if (n_elements != 0) { - req = n_elements * elem_size; - if (((n_elements | elem_size) & ~(size_t)0xffff) && - (req / n_elements != elem_size)) - req = MAX_SIZE_T; /* force downstream failure on overflow */ - } - mem = internal_malloc(ms, req); - if (mem != 0 && calloc_must_clear(mem2chunk(mem))) - memset(mem, 0, req); - return mem; -} - -void* mspace_realloc(mspace msp, void* oldmem, size_t bytes) { - if (oldmem == 0) - return mspace_malloc(msp, bytes); -#ifdef REALLOC_ZERO_BYTES_FREES - if (bytes == 0) { - mspace_free(msp, oldmem); - return 0; - } -#endif /* REALLOC_ZERO_BYTES_FREES */ - else { -#if FOOTERS - mchunkptr p = mem2chunk(oldmem); - mstate ms = get_mstate_for(p); -#else /* FOOTERS */ - mstate ms = (mstate)msp; -#endif /* FOOTERS */ - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return internal_realloc(ms, oldmem, bytes); - } -} - -void* mspace_memalign(mspace msp, size_t alignment, size_t bytes) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return internal_memalign(ms, alignment, bytes); -} - -void** mspace_independent_calloc(mspace msp, size_t n_elements, - size_t elem_size, void* chunks[]) { - size_t sz = elem_size; /* serves as 1-element array */ - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return ialloc(ms, n_elements, &sz, 3, chunks); -} - -void** mspace_independent_comalloc(mspace msp, size_t n_elements, - size_t sizes[], void* chunks[]) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - return 0; - } - return ialloc(ms, n_elements, sizes, 0, chunks); -} - -int mspace_trim(mspace msp, size_t pad) { - int result = 0; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - if (!PREACTION(ms)) { - result = sys_trim(ms, pad); - POSTACTION(ms); - } - } - else { - USAGE_ERROR_ACTION(ms,ms); - } - return result; -} - -void mspace_malloc_stats(mspace msp) { - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - internal_malloc_stats(ms); - } - else { - USAGE_ERROR_ACTION(ms,ms); - } -} - -size_t mspace_footprint(mspace msp) { - size_t result; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - result = ms->footprint; - } - USAGE_ERROR_ACTION(ms,ms); - return result; -} - - -size_t mspace_max_footprint(mspace msp) { - size_t result; - mstate ms = (mstate)msp; - if (ok_magic(ms)) { - result = ms->max_footprint; - } - USAGE_ERROR_ACTION(ms,ms); - return result; -} - - -#if !NO_MALLINFO -struct mallinfo mspace_mallinfo(mspace msp) { - mstate ms = (mstate)msp; - if (!ok_magic(ms)) { - USAGE_ERROR_ACTION(ms,ms); - } - return internal_mallinfo(ms); -} -#endif /* NO_MALLINFO */ - -int mspace_mallopt(int param_number, int value) { - return change_mparam(param_number, value); -} - -#endif /* MSPACES */ - -/* -------------------- Alternative MORECORE functions ------------------- */ - -/* - Guidelines for creating a custom version of MORECORE: - - * For best performance, MORECORE should allocate in multiples of pagesize. - * MORECORE may allocate more memory than requested. (Or even less, - but this will usually result in a malloc failure.) - * MORECORE must not allocate memory when given argument zero, but - instead return one past the end address of memory from previous - nonzero call. - * For best performance, consecutive calls to MORECORE with positive - arguments should return increasing addresses, indicating that - space has been contiguously extended. - * Even though consecutive calls to MORECORE need not return contiguous - addresses, it must be OK for malloc'ed chunks to span multiple - regions in those cases where they do happen to be contiguous. - * MORECORE need not handle negative arguments -- it may instead - just return MFAIL when given negative arguments. - Negative arguments are always multiples of pagesize. MORECORE - must not misinterpret negative args as large positive unsigned - args. You can suppress all such calls from even occurring by defining - MORECORE_CANNOT_TRIM, - - As an example alternative MORECORE, here is a custom allocator - kindly contributed for pre-OSX macOS. It uses virtually but not - necessarily physically contiguous non-paged memory (locked in, - present and won't get swapped out). You can use it by uncommenting - this section, adding some #includes, and setting up the appropriate - defines above: - - #define MORECORE osMoreCore - - There is also a shutdown routine that should somehow be called for - cleanup upon program exit. - - #define MAX_POOL_ENTRIES 100 - #define MINIMUM_MORECORE_SIZE (64 * 1024U) - static int next_os_pool; - void *our_os_pools[MAX_POOL_ENTRIES]; - - void *osMoreCore(int size) - { - void *ptr = 0; - static void *sbrk_top = 0; - - if (size > 0) - { - if (size < MINIMUM_MORECORE_SIZE) - size = MINIMUM_MORECORE_SIZE; - if (CurrentExecutionLevel() == kTaskLevel) - ptr = PoolAllocateResident(size + RM_PAGE_SIZE, 0); - if (ptr == 0) - { - return (void *) MFAIL; - } - // save ptrs so they can be freed during cleanup - our_os_pools[next_os_pool] = ptr; - next_os_pool++; - ptr = (void *) ((((size_t) ptr) + RM_PAGE_MASK) & ~RM_PAGE_MASK); - sbrk_top = (char *) ptr + size; - return ptr; - } - else if (size < 0) - { - // we don't currently support shrink behavior - return (void *) MFAIL; - } - else - { - return sbrk_top; - } - } - - // cleanup any allocated memory pools - // called as last thing before shutting down driver - - void osCleanupMem(void) - { - void **ptr; - - for (ptr = our_os_pools; ptr < &our_os_pools[MAX_POOL_ENTRIES]; ptr++) - if (*ptr) - { - PoolDeallocate(*ptr); - *ptr = 0; - } - } - -*/ - - -/* ----------------------------------------------------------------------- -History: - V2.8.3 Thu Sep 22 11:16:32 2005 Doug Lea (dl at gee) - * Add max_footprint functions - * Ensure all appropriate literals are size_t - * Fix conditional compilation problem for some #define settings - * Avoid concatenating segments with the one provided - in create_mspace_with_base - * Rename some variables to avoid compiler shadowing warnings - * Use explicit lock initialization. - * Better handling of sbrk interference. - * Simplify and fix segment insertion, trimming and mspace_destroy - * Reinstate REALLOC_ZERO_BYTES_FREES option from 2.7.x - * Thanks especially to Dennis Flanagan for help on these. - - V2.8.2 Sun Jun 12 16:01:10 2005 Doug Lea (dl at gee) - * Fix memalign brace error. - - V2.8.1 Wed Jun 8 16:11:46 2005 Doug Lea (dl at gee) - * Fix improper #endif nesting in C++ - * Add explicit casts needed for C++ - - V2.8.0 Mon May 30 14:09:02 2005 Doug Lea (dl at gee) - * Use trees for large bins - * Support mspaces - * Use segments to unify sbrk-based and mmap-based system allocation, - removing need for emulation on most platforms without sbrk. - * Default safety checks - * Optional footer checks. Thanks to William Robertson for the idea. - * Internal code refactoring - * Incorporate suggestions and platform-specific changes. - Thanks to Dennis Flanagan, Colin Plumb, Niall Douglas, - Aaron Bachmann, Emery Berger, and others. - * Speed up non-fastbin processing enough to remove fastbins. - * Remove useless cfree() to avoid conflicts with other apps. - * Remove internal memcpy, memset. Compilers handle builtins better. - * Remove some options that no one ever used and rename others. - - V2.7.2 Sat Aug 17 09:07:30 2002 Doug Lea (dl at gee) - * Fix malloc_state bitmap array misdeclaration - - V2.7.1 Thu Jul 25 10:58:03 2002 Doug Lea (dl at gee) - * Allow tuning of FIRST_SORTED_BIN_SIZE - * Use PTR_UINT as type for all ptr->int casts. Thanks to John Belmonte. - * Better detection and support for non-contiguousness of MORECORE. - Thanks to Andreas Mueller, Conal Walsh, and Wolfram Gloger - * Bypass most of malloc if no frees. Thanks To Emery Berger. - * Fix freeing of old top non-contiguous chunk im sysmalloc. - * Raised default trim and map thresholds to 256K. - * Fix mmap-related #defines. Thanks to Lubos Lunak. - * Fix copy macros; added LACKS_FCNTL_H. Thanks to Neal Walfield. - * Branch-free bin calculation - * Default trim and mmap thresholds now 256K. - - V2.7.0 Sun Mar 11 14:14:06 2001 Doug Lea (dl at gee) - * Introduce independent_comalloc and independent_calloc. - Thanks to Michael Pachos for motivation and help. - * Make optional .h file available - * Allow > 2GB requests on 32bit systems. - * new WIN32 sbrk, mmap, munmap, lock code from . - Thanks also to Andreas Mueller , - and Anonymous. - * Allow override of MALLOC_ALIGNMENT (Thanks to Ruud Waij for - helping test this.) - * memalign: check alignment arg - * realloc: don't try to shift chunks backwards, since this - leads to more fragmentation in some programs and doesn't - seem to help in any others. - * Collect all cases in malloc requiring system memory into sysmalloc - * Use mmap as backup to sbrk - * Place all internal state in malloc_state - * Introduce fastbins (although similar to 2.5.1) - * Many minor tunings and cosmetic improvements - * Introduce USE_PUBLIC_MALLOC_WRAPPERS, USE_MALLOC_LOCK - * Introduce MALLOC_FAILURE_ACTION, MORECORE_CONTIGUOUS - Thanks to Tony E. Bennett and others. - * Include errno.h to support default failure action. - - V2.6.6 Sun Dec 5 07:42:19 1999 Doug Lea (dl at gee) - * return null for negative arguments - * Added Several WIN32 cleanups from Martin C. Fong - * Add 'LACKS_SYS_PARAM_H' for those systems without 'sys/param.h' - (e.g. WIN32 platforms) - * Cleanup header file inclusion for WIN32 platforms - * Cleanup code to avoid Microsoft Visual C++ compiler complaints - * Add 'USE_DL_PREFIX' to quickly allow co-existence with existing - memory allocation routines - * Set 'malloc_getpagesize' for WIN32 platforms (needs more work) - * Use 'assert' rather than 'ASSERT' in WIN32 code to conform to - usage of 'assert' in non-WIN32 code - * Improve WIN32 'sbrk()' emulation's 'findRegion()' routine to - avoid infinite loop - * Always call 'fREe()' rather than 'free()' - - V2.6.5 Wed Jun 17 15:57:31 1998 Doug Lea (dl at gee) - * Fixed ordering problem with boundary-stamping - - V2.6.3 Sun May 19 08:17:58 1996 Doug Lea (dl at gee) - * Added pvalloc, as recommended by H.J. Liu - * Added 64bit pointer support mainly from Wolfram Gloger - * Added anonymously donated WIN32 sbrk emulation - * Malloc, calloc, getpagesize: add optimizations from Raymond Nijssen - * malloc_extend_top: fix mask error that caused wastage after - foreign sbrks - * Add linux mremap support code from HJ Liu - - V2.6.2 Tue Dec 5 06:52:55 1995 Doug Lea (dl at gee) - * Integrated most documentation with the code. - * Add support for mmap, with help from - Wolfram Gloger (Gloger@lrz.uni-muenchen.de). - * Use last_remainder in more cases. - * Pack bins using idea from colin@nyx10.cs.du.edu - * Use ordered bins instead of best-fit threshhold - * Eliminate block-local decls to simplify tracing and debugging. - * Support another case of realloc via move into top - * Fix error occuring when initial sbrk_base not word-aligned. - * Rely on page size for units instead of SBRK_UNIT to - avoid surprises about sbrk alignment conventions. - * Add mallinfo, mallopt. Thanks to Raymond Nijssen - (raymond@es.ele.tue.nl) for the suggestion. - * Add `pad' argument to malloc_trim and top_pad mallopt parameter. - * More precautions for cases where other routines call sbrk, - courtesy of Wolfram Gloger (Gloger@lrz.uni-muenchen.de). - * Added macros etc., allowing use in linux libc from - H.J. Lu (hjl@gnu.ai.mit.edu) - * Inverted this history list - - V2.6.1 Sat Dec 2 14:10:57 1995 Doug Lea (dl at gee) - * Re-tuned and fixed to behave more nicely with V2.6.0 changes. - * Removed all preallocation code since under current scheme - the work required to undo bad preallocations exceeds - the work saved in good cases for most test programs. - * No longer use return list or unconsolidated bins since - no scheme using them consistently outperforms those that don't - given above changes. - * Use best fit for very large chunks to prevent some worst-cases. - * Added some support for debugging - - V2.6.0 Sat Nov 4 07:05:23 1995 Doug Lea (dl at gee) - * Removed footers when chunks are in use. Thanks to - Paul Wilson (wilson@cs.texas.edu) for the suggestion. - - V2.5.4 Wed Nov 1 07:54:51 1995 Doug Lea (dl at gee) - * Added malloc_trim, with help from Wolfram Gloger - (wmglo@Dent.MED.Uni-Muenchen.DE). - - V2.5.3 Tue Apr 26 10:16:01 1994 Doug Lea (dl at g) - - V2.5.2 Tue Apr 5 16:20:40 1994 Doug Lea (dl at g) - * realloc: try to expand in both directions - * malloc: swap order of clean-bin strategy; - * realloc: only conditionally expand backwards - * Try not to scavenge used bins - * Use bin counts as a guide to preallocation - * Occasionally bin return list chunks in first scan - * Add a few optimizations from colin@nyx10.cs.du.edu - - V2.5.1 Sat Aug 14 15:40:43 1993 Doug Lea (dl at g) - * faster bin computation & slightly different binning - * merged all consolidations to one part of malloc proper - (eliminating old malloc_find_space & malloc_clean_bin) - * Scan 2 returns chunks (not just 1) - * Propagate failure in realloc if malloc returns 0 - * Add stuff to allow compilation on non-ANSI compilers - from kpv@research.att.com - - V2.5 Sat Aug 7 07:41:59 1993 Doug Lea (dl at g.oswego.edu) - * removed potential for odd address access in prev_chunk - * removed dependency on getpagesize.h - * misc cosmetics and a bit more internal documentation - * anticosmetics: mangled names in macros to evade debugger strangeness - * tested on sparc, hp-700, dec-mips, rs6000 - with gcc & native cc (hp, dec only) allowing - Detlefs & Zorn comparison study (in SIGPLAN Notices.) - - Trial version Fri Aug 28 13:14:29 1992 Doug Lea (dl at g.oswego.edu) - * Based loosely on libg++-1.2X malloc. (It retains some of the overall - structure of old version, but most details differ.) - -*/ diff --git a/src/md5.c b/src/md5.c index 941c0d37e5..888993b9c4 100644 --- a/src/md5.c +++ b/src/md5.c @@ -21,7 +21,6 @@ ghost@aladdin.com */ -/* $Id: md5.c 80 2004-07-14 20:15:50Z jason $ */ /* Independent implementation of MD5 (RFC 1321). diff --git a/src/md5.h b/src/md5.h index 8cff20d0af..2806b5b9b5 100644 --- a/src/md5.h +++ b/src/md5.h @@ -21,7 +21,6 @@ ghost@aladdin.com */ -/* $Id: md5.h 80 2004-07-14 20:15:50Z jason $ */ /* Independent implementation of MD5 (RFC 1321). diff --git a/src/modp_numtoa.c b/src/modp_numtoa.c new file mode 100644 index 0000000000..6deb8a70ed --- /dev/null +++ b/src/modp_numtoa.c @@ -0,0 +1,291 @@ +/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ +/* vi: set expandtab shiftwidth=4 tabstop=4: */ + +#include "modp_numtoa.h" + +#include +#include +#include + +// other interesting references on num to string convesion +// http://www.jb.man.ac.uk/~slowe/cpp/itoa.html +// and http://www.ddj.com/dept/cpp/184401596?pgno=6 + +// Version 19-Nov-2007 +// Fixed round-to-even rules to match printf +// thanks to Johannes Otepka + +/** + * Powers of 10 + * 10^0 to 10^9 + */ +static const double _pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000, + 10000000, 100000000, 1000000000}; + +static void strreverse(char* begin, char* end) +{ + char aux; + while (end > begin) + aux = *end, *end-- = *begin, *begin++ = aux; +} + +void modp_itoa10(int32_t value, char* str) +{ + char* wstr=str; + // Take care of sign + unsigned int uvalue = (value < 0) ? -value : value; + // Conversion. Number is reversed. + do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10); + if (value < 0) *wstr++ = '-'; + *wstr='\0'; + + // Reverse string + strreverse(str,wstr-1); +} + +void modp_uitoa10(uint32_t value, char* str) +{ + char* wstr=str; + // Conversion. Number is reversed. + do *wstr++ = (char)(48 + (value % 10)); while (value /= 10); + *wstr='\0'; + // Reverse string + strreverse(str, wstr-1); +} + +void modp_litoa10(int64_t value, char* str) +{ + char* wstr=str; + unsigned long uvalue = (value < 0) ? -value : value; + + // Conversion. Number is reversed. + do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10); + if (value < 0) *wstr++ = '-'; + *wstr='\0'; + + // Reverse string + strreverse(str,wstr-1); +} + +void modp_ulitoa10(uint64_t value, char* str) +{ + char* wstr=str; + // Conversion. Number is reversed. + do *wstr++ = (char)(48 + (value % 10)); while (value /= 10); + *wstr='\0'; + // Reverse string + strreverse(str, wstr-1); +} + +void modp_dtoa(double value, char* str, int prec) +{ + /* Hacky test for NaN + * under -fast-math this won't work, but then you also won't + * have correct nan values anyways. The alternative is + * to link with libmath (bad) or hack IEEE double bits (bad) + */ + if (! (value == value)) { + str[0] = 'n'; str[1] = 'a'; str[2] = 'n'; str[3] = '\0'; + return; + } + /* if input is larger than thres_max, revert to exponential */ + const double thres_max = (double)(0x7FFFFFFF); + + double diff = 0.0; + char* wstr = str; + + if (prec < 0) { + prec = 0; + } else if (prec > 9) { + /* precision of >= 10 can lead to overflow errors */ + prec = 9; + } + + + /* we'll work in positive values and deal with the + negative sign issue later */ + int neg = 0; + if (value < 0) { + neg = 1; + value = -value; + } + + + int whole = (int) value; + double tmp = (value - whole) * _pow10[prec]; + uint32_t frac = (uint32_t)(tmp); + diff = tmp - frac; + + if (diff > 0.5) { + ++frac; + /* handle rollover, e.g. case 0.99 with prec 1 is 1.0 */ + if (frac >= _pow10[prec]) { + frac = 0; + ++whole; + } + } else if (diff == 0.5 && ((frac == 0) || (frac & 1))) { + /* if halfway, round up if odd, OR + if last digit is 0. That last part is strange */ + ++frac; + } + + /* for very large numbers switch back to native sprintf for exponentials. + anyone want to write code to replace this? */ + /* + normal printf behavior is to print EVERY whole number digit + which can be 100s of characters overflowing your buffers == bad + */ + if (value > thres_max) { + sprintf(str, "%e", neg ? -value : value); + return; + } + + if (prec == 0) { + diff = value - whole; + if (diff > 0.5) { + /* greater than 0.5, round up, e.g. 1.6 -> 2 */ + ++whole; + } else if (diff == 0.5 && (whole & 1)) { + /* exactly 0.5 and ODD, then round up */ + /* 1.5 -> 2, but 2.5 -> 2 */ + ++whole; + } + } else { + int count = prec; + // now do fractional part, as an unsigned number + do { + --count; + *wstr++ = (char)(48 + (frac % 10)); + } while (frac /= 10); + // add extra 0s + while (count-- > 0) *wstr++ = '0'; + // add decimal + *wstr++ = '.'; + } + + // do whole part + // Take care of sign + // Conversion. Number is reversed. + do *wstr++ = (char)(48 + (whole % 10)); while (whole /= 10); + if (neg) { + *wstr++ = '-'; + } + *wstr='\0'; + strreverse(str, wstr-1); +} + + +// This is near identical to modp_dtoa above +// The differnce is noted below +void modp_dtoa2(double value, char* str, int prec) +{ + /* Hacky test for NaN + * under -fast-math this won't work, but then you also won't + * have correct nan values anyways. The alternative is + * to link with libmath (bad) or hack IEEE double bits (bad) + */ + if (! (value == value)) { + str[0] = 'n'; str[1] = 'a'; str[2] = 'n'; str[3] = '\0'; + return; + } + + /* if input is larger than thres_max, revert to exponential */ + const double thres_max = (double)(0x7FFFFFFF); + + int count; + double diff = 0.0; + char* wstr = str; + + if (prec < 0) { + prec = 0; + } else if (prec > 9) { + /* precision of >= 10 can lead to overflow errors */ + prec = 9; + } + + + /* we'll work in positive values and deal with the + negative sign issue later */ + int neg = 0; + if (value < 0) { + neg = 1; + value = -value; + } + + + int whole = (int) value; + double tmp = (value - whole) * _pow10[prec]; + uint32_t frac = (uint32_t)(tmp); + diff = tmp - frac; + + if (diff > 0.5) { + ++frac; + /* handle rollover, e.g. case 0.99 with prec 1 is 1.0 */ + if (frac >= _pow10[prec]) { + frac = 0; + ++whole; + } + } else if (diff == 0.5 && ((frac == 0) || (frac & 1))) { + /* if halfway, round up if odd, OR + if last digit is 0. That last part is strange */ + ++frac; + } + + /* for very large numbers switch back to native sprintf for exponentials. + anyone want to write code to replace this? */ + /* + normal printf behavior is to print EVERY whole number digit + which can be 100s of characters overflowing your buffers == bad + */ + if (value > thres_max) { + sprintf(str, "%e", neg ? -value : value); + return; + } + + if (prec == 0) { + diff = value - whole; + if (diff > 0.5) { + /* greater than 0.5, round up, e.g. 1.6 -> 2 */ + ++whole; + } else if (diff == 0.5 && (whole & 1)) { + /* exactly 0.5 and ODD, then round up */ + /* 1.5 -> 2, but 2.5 -> 2 */ + ++whole; + } + + //vvvvvvvvvvvvvvvvvvv Diff from modp_dto2 + } else if (frac) { + count = prec; + // now do fractional part, as an unsigned number + // we know it is not 0 but we can have leading zeros, these + // should be removed + while (!(frac % 10)) { + --count; + frac /= 10; + } + //^^^^^^^^^^^^^^^^^^^ Diff from modp_dto2 + + // now do fractional part, as an unsigned number + do { + --count; + *wstr++ = (char)(48 + (frac % 10)); + } while (frac /= 10); + // add extra 0s + while (count-- > 0) *wstr++ = '0'; + // add decimal + *wstr++ = '.'; + } + + // do whole part + // Take care of sign + // Conversion. Number is reversed. + do *wstr++ = (char)(48 + (whole % 10)); while (whole /= 10); + if (neg) { + *wstr++ = '-'; + } + *wstr='\0'; + strreverse(str, wstr-1); +} + + + diff --git a/src/modp_numtoa.h b/src/modp_numtoa.h new file mode 100644 index 0000000000..b848163d1d --- /dev/null +++ b/src/modp_numtoa.h @@ -0,0 +1,102 @@ +/* -*- mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4 -*- */ +/* vi: set expandtab shiftwidth=4 tabstop=4: */ + +/** + * \file + * + *
    + * Copyright © 2007, Nick Galbreath -- nickg [at] modp [dot] com
    + * All rights reserved.
    + * http://code.google.com/p/stringencoders/
    + * Released under the bsd license.
    + * 
    + * + * This defines signed/unsigned integer, and 'double' to char buffer + * converters. The standard way of doing this is with "sprintf", however + * these functions are + * * guarenteed maximum size output + * * 5-20x faster! + * * core-dump safe + * + * + */ + +#ifndef COM_MODP_STRINGENCODERS_NUMTOA_H +#define COM_MODP_STRINGENCODERS_NUMTOA_H + +#ifdef __cplusplus +#define BEGIN_C extern "C" { +#define END_C } +#else +#define BEGIN_C +#define END_C +#endif + +BEGIN_C + +#include + +/** \brief convert an signed integer to char buffer + * + * \param[in] value + * \param[out] buf the output buffer. Should be 16 chars or more. + */ +void modp_itoa10(int32_t value, char* buf); + +/** \brief convert an unsigned integer to char buffer + * + * \param[in] value + * \param[out] buf The output buffer, should be 16 chars or more. + */ +void modp_uitoa10(uint32_t value, char* buf); + +/** \brief convert an signed long integer to char buffer + * + * \param[in] value + * \param[out] buf the output buffer. Should be 24 chars or more. + */ +void modp_litoa10(int64_t value, char* buf); + +/** \brief convert an unsigned long integer to char buffer + * + * \param[in] value + * \param[out] buf The output buffer, should be 24 chars or more. + */ +void modp_ulitoa10(uint64_t value, char* buf); + +/** \brief convert a floating point number to char buffer with + * fixed-precision format + * + * This is similar to "%.[0-9]f" in the printf style. It will include + * trailing zeros + * + * If the input value is greater than 1<<31, then the output format + * will be switched exponential format. + * + * \param[in] value + * \param[out] buf The allocated output buffer. Should be 32 chars or more. + * \param[in] precision Number of digits to the right of the decimal point. + * Can only be 0-9. + */ +void modp_dtoa(double value, char* buf, int precision); + +/** \brief convert a floating point number to char buffer with a + * variable-precision format, and no trailing zeros + * + * This is similar to "%.[0-9]f" in the printf style, except it will + * NOT include trailing zeros after the decimal point. This type + * of format oddly does not exists with printf. + * + * If the input value is greater than 1<<31, then the output format + * will be switched exponential format. + * + * \param[in] value + * \param[out] buf The allocated output buffer. Should be 32 chars or more. + * \param[in] precision Number of digits to the right of the decimal point. + * Can only be 0-9. + */ +void modp_dtoa2(double value, char* buf, int precision); + +END_C + +#endif diff --git a/src/nb_dns.c b/src/nb_dns.c index 225eb984cf..d3b3c5c4de 100644 --- a/src/nb_dns.c +++ b/src/nb_dns.c @@ -1,10 +1,6 @@ /* * See the file "COPYING" in the main distribution directory for copyright. */ -#ifndef lint -static const char rcsid[] = - "@(#) $Id: nb_dns.c 6219 2008-10-01 05:39:07Z vern $ (LBL)"; -#endif /* * nb_dns - non-blocking dns routines * @@ -190,7 +186,7 @@ _nb_dns_cmpsockaddr(register struct sockaddr *sa1, #endif static const char serr[] = "answer from wrong nameserver (%d)"; - if (sa1->sa_family != sa1->sa_family) { + if (sa1->sa_family != sa2->sa_family) { snprintf(errstr, NB_DNS_ERRSIZE, serr, 1); return (-1); } @@ -385,7 +381,7 @@ nb_dns_addr_request2(register struct nb_dns_info *nd, char *addrp, size -= i; cp += i; } - snprintf(cp, size, "ip6.int"); + snprintf(cp, size, "ip6.arpa"); break; #endif @@ -438,7 +434,7 @@ nb_dns_activity(struct nb_dns_info *nd, struct nb_dns_result *nr, char *errstr) register char **ap, **hap; register u_int16_t id; register const u_char *rdata; - register u_int32_t rttl; + register u_int32_t rttl = 0; // make compiler happy. register struct hostent *he; register size_t rdlen; ns_msg handle; diff --git a/src/nb_dns.h b/src/nb_dns.h index 5787a3fdb0..d458f61716 100644 --- a/src/nb_dns.h +++ b/src/nb_dns.h @@ -1,5 +1,4 @@ -/* @(#) $Id: nb_dns.h 6219 2008-10-01 05:39:07Z vern $ (LBL) - * +/* * See the file "COPYING" in the main distribution directory for copyright. */ diff --git a/src/ncp.pac b/src/ncp.pac index 8a3fcf1478..86b8bca5da 100644 --- a/src/ncp.pac +++ b/src/ncp.pac @@ -1,5 +1,3 @@ -# $Id: ncp.pac 4608 2007-07-05 18:23:58Z vern $ -# # Netware Core Protocol %include bro.pac diff --git a/src/net_util.cc b/src/net_util.cc index d7dc3f4add..d91cf02de9 100644 --- a/src/net_util.cc +++ b/src/net_util.cc @@ -1,20 +1,18 @@ -// $Id: net_util.cc 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" -#ifdef BROv6 #include #include #include #include -#endif #include "Reporter.h" #include "net_util.h" +#include "IPAddr.h" +#include "IP.h" // - adapted from tcpdump // Returns the ones-complement checksum of a chunk of b short-aligned bytes. @@ -34,80 +32,13 @@ int ones_complement_checksum(const void* p, int b, uint32 sum) return sum; } -int tcp_checksum(const struct ip* ip, const struct tcphdr* tp, int len) +int ones_complement_checksum(const IPAddr& a, uint32 sum) { - // ### Note, this is only correct for IPv4. This routine is only - // used by the connection compressor (which we turn off for IPv6 - // traffic). - - int tcp_len = tp->th_off * 4 + len; - uint32 sum; - - if ( len % 2 == 1 ) - // Add in pad byte. - sum = htons(((const u_char*) tp)[tcp_len - 1] << 8); - else - sum = 0; - - sum = ones_complement_checksum((void*) &ip->ip_src.s_addr, 4, sum); - sum = ones_complement_checksum((void*) &ip->ip_dst.s_addr, 4, sum); - - uint32 addl_pseudo = - (htons(IPPROTO_TCP) << 16) | htons((unsigned short) tcp_len); - - sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum); - sum = ones_complement_checksum((void*) tp, tcp_len, sum); - - return sum; + const uint32* bytes; + int len = a.GetBytes(&bytes); + return ones_complement_checksum(bytes, len*4, sum); } -int udp_checksum(const struct ip* ip, const struct udphdr* up, int len) - { - uint32 sum; - - if ( len % 2 == 1 ) - // Add in pad byte. - sum = htons(((const u_char*) up)[len - 1] << 8); - else - sum = 0; - - sum = ones_complement_checksum((void*) &ip->ip_src.s_addr, 4, sum); - sum = ones_complement_checksum((void*) &ip->ip_dst.s_addr, 4, sum); - - uint32 addl_pseudo = - (htons(IPPROTO_UDP) << 16) | htons((unsigned short) len); - - sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum); - sum = ones_complement_checksum((void*) up, len, sum); - - return sum; - } - -#ifdef BROv6 -int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len) - { - uint32 sum; - - if ( len % 2 == 1 ) - // Add in pad byte. - sum = htons(((const u_char*) up)[len - 1] << 8); - else - sum = 0; - - sum = ones_complement_checksum((void*) ip6->ip6_src.s6_addr, 16, sum); - sum = ones_complement_checksum((void*) ip6->ip6_dst.s6_addr, 16, sum); - - uint32 l = htonl(len); - sum = ones_complement_checksum((void*) &l, 4, sum); - - uint32 addl_pseudo = htons(IPPROTO_UDP); - sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum); - sum = ones_complement_checksum((void*) up, len, sum); - - return sum; - } -#endif - int icmp_checksum(const struct icmp* icmpp, int len) { uint32 sum; @@ -123,6 +54,58 @@ int icmp_checksum(const struct icmp* icmpp, int len) return sum; } +#ifdef ENABLE_MOBILE_IPV6 +int mobility_header_checksum(const IP_Hdr* ip) + { + const ip6_mobility* mh = ip->MobilityHeader(); + + if ( ! mh ) return 0; + + uint32 sum = 0; + uint8 mh_len = 8 + 8 * mh->ip6mob_len; + + if ( mh_len % 2 == 1 ) + reporter->Weird(ip->SrcAddr(), ip->DstAddr(), "odd_mobility_hdr_len"); + + sum = ones_complement_checksum(ip->SrcAddr(), sum); + sum = ones_complement_checksum(ip->DstAddr(), sum); + // Note, for IPv6, strictly speaking the protocol and length fields are + // 32 bits rather than 16 bits. But because the upper bits are all zero, + // we get the same checksum either way. + sum += htons(IPPROTO_MOBILITY); + sum += htons(mh_len); + sum = ones_complement_checksum(mh, mh_len, sum); + + return sum; + } +#endif + +int icmp6_checksum(const struct icmp* icmpp, const IP_Hdr* ip, int len) + { + // ICMP6 uses the same checksum function as ICMP4 but a different + // pseudo-header over which it is computed. + uint32 sum; + + if ( len % 2 == 1 ) + // Add in pad byte. + sum = htons(((const u_char*) icmpp)[len - 1] << 8); + else + sum = 0; + + // Pseudo-header as for UDP over IPv6 above. + sum = ones_complement_checksum(ip->SrcAddr(), sum); + sum = ones_complement_checksum(ip->DstAddr(), sum); + uint32 l = htonl(len); + sum = ones_complement_checksum((void*) &l, 4, sum); + + uint32 addl_pseudo = htons(IPPROTO_ICMPV6); + sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum); + + sum = ones_complement_checksum((void*) icmpp, len, sum); + + return sum; + } + #define CLASS_A 0x00000000 #define CLASS_B 0x80000000 @@ -145,223 +128,24 @@ char addr_to_class(uint32 addr) return 'A'; } -uint32 addr_to_net(uint32 addr) +const char* fmt_conn_id(const IPAddr& src_addr, uint32 src_port, + const IPAddr& dst_addr, uint32 dst_port) { - if ( CHECK_CLASS(addr, CLASS_D) ) - ; // class D's are left alone ### - else if ( CHECK_CLASS(addr, CLASS_C) ) - addr = addr & 0xffffff00; - else if ( CHECK_CLASS(addr, CLASS_B) ) - addr = addr & 0xffff0000; - else - addr = addr & 0xff000000; + static char buffer[512]; - return addr; - } + safe_snprintf(buffer, sizeof(buffer), "%s:%d > %s:%d", + string(src_addr).c_str(), src_port, + string(dst_addr).c_str(), dst_port); -const char* dotted_addr(uint32 addr, int alternative) - { - addr = ntohl(addr); - const char* fmt = alternative ? "%d,%d.%d.%d" : "%d.%d.%d.%d"; - - static char buf[32]; - snprintf(buf, sizeof(buf), fmt, - addr >> 24, (addr >> 16) & 0xff, - (addr >> 8) & 0xff, addr & 0xff); - - return buf; - } - -const char* dotted_addr(const uint32* addr, int alternative) - { -#ifdef BROv6 - if ( is_v4_addr(addr) ) - return dotted_addr(addr[3], alternative); - - static char buf[256]; - - if ( inet_ntop(AF_INET6, addr, buf, sizeof buf) == NULL ) - return ""; - - return buf; - -#else - return dotted_addr(to_v4_addr(addr), alternative); -#endif - } - -const char* dotted_net(uint32 addr) - { - addr = ntohl(addr); - - static char buf[32]; - - if ( CHECK_CLASS(addr, CLASS_D) ) - sprintf(buf, "%d.%d.%d.%d", - addr >> 24, (addr >> 16) & 0xff, - (addr >> 8) & 0xff, addr & 0xff); - - else if ( CHECK_CLASS(addr, CLASS_C) ) - sprintf(buf, "%d.%d.%d", - addr >> 24, (addr >> 16) & 0xff, (addr >> 8) & 0xff); - - else - // Same for class A's and B's. - sprintf(buf, "%d.%d", addr >> 24, (addr >> 16) & 0xff); - - return buf; - } - -#ifdef BROv6 -const char* dotted_net6(const uint32* addr) - { - if ( is_v4_addr(addr) ) - return dotted_net(to_v4_addr(addr)); - else - // ### this isn't right, but net's should go away eventually ... - return dotted_addr(addr); - } -#endif - -uint32 dotted_to_addr(const char* addr_text) - { - int addr[4]; - - if ( sscanf(addr_text, - "%d.%d.%d.%d", addr+0, addr+1, addr+2, addr+3) != 4 ) - { - reporter->Error("bad dotted address:", addr_text ); - return 0; - } - - if ( addr[0] < 0 || addr[1] < 0 || addr[2] < 0 || addr[3] < 0 || - addr[0] > 255 || addr[1] > 255 || addr[2] > 255 || addr[3] > 255 ) - { - reporter->Error("bad dotted address:", addr_text); - return 0; - } - - uint32 a = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3]; - - // ### perhaps do gethostbyaddr here? - - return uint32(htonl(a)); - } - -#ifdef BROv6 -uint32* dotted_to_addr6(const char* addr_text) - { - uint32* addr = new uint32[4]; - if ( inet_pton(AF_INET6, addr_text, addr) <= 0 ) - { - reporter->Error("bad IPv6 address:", addr_text ); - addr[0] = addr[1] = addr[2] = addr[3] = 0; - } - - return addr; - } - -#endif - -#ifdef BROv6 -int is_v4_addr(const uint32 addr[4]) - { - return addr[0] == 0 && addr[1] == 0 && addr[2] == 0; - } -#endif - -uint32 to_v4_addr(const uint32* addr) - { -#ifdef BROv6 - if ( ! is_v4_addr(addr) ) - reporter->InternalError("conversion of non-IPv4 address to IPv4 address"); - return addr[3]; -#else - return addr[0]; -#endif - } - -uint32 mask_addr(uint32 a, uint32 top_bits_to_keep) - { - if ( top_bits_to_keep > 32 ) - { - reporter->Error("bad address mask value", top_bits_to_keep); - return a; - } - - if ( top_bits_to_keep == 0 ) - // The shifts below don't have any effect with 0, i.e., - // 1 << 32 does not yield 0; either due to compiler - // misoptimization or language semantics. - return 0; - - uint32 addr = ntohl(a); - - int shift = 32 - top_bits_to_keep; - addr >>= shift; - addr <<= shift; - - return htonl(addr); - } - -const uint32* mask_addr(const uint32* a, uint32 top_bits_to_keep) - { -#ifdef BROv6 - static uint32 addr[4]; - - addr[0] = a[0]; - addr[1] = a[1]; - addr[2] = a[2]; - addr[3] = a[3]; - - // This is a bit dicey: if it's a v4 address, then we interpret - // the mask as being with respect to 32 bits total, even though - // strictly speaking, the v4 address comprises the least-significant - // bits out of 128, rather than the most significant. However, - // we only do this if the mask itself is consistent for a 32-bit - // address. - uint32 max_bits = (is_v4_addr(a) && top_bits_to_keep <= 32) ? 32 : 128; - - if ( top_bits_to_keep == 0 || top_bits_to_keep > max_bits ) - { - reporter->Error("bad address mask value", top_bits_to_keep); - return addr; - } - - int word = 3; // start zeroing out with word #3 - int bits_to_chop = max_bits - top_bits_to_keep; // bits to discard - while ( bits_to_chop >= 32 ) - { // there's an entire word to discard - addr[word] = 0; - --word; // move on to next, more significant word - bits_to_chop -= 32; // we just go rid of 32 bits - } - - // All that's left to work with now is the word pointed to by "word". - uint32 addr32 = ntohl(addr[word]); - addr32 >>= bits_to_chop; - addr32 <<= bits_to_chop; - addr[word] = htonl(addr32); - - return addr; -#else - return a; -#endif + return buffer; } const char* fmt_conn_id(const uint32* src_addr, uint32 src_port, const uint32* dst_addr, uint32 dst_port) { - char addr1[128], addr2[128]; - static char buffer[512]; - - strcpy(addr1, dotted_addr(src_addr)); - strcpy(addr2, dotted_addr(dst_addr)); - - safe_snprintf(buffer, sizeof(buffer), "%s:%d > %s:%d", - addr1, src_port, addr2, dst_port); - - return buffer; + IPAddr src(IPv6, src_addr, IPAddr::Network); + IPAddr dst(IPv6, dst_addr, IPAddr::Network); + return fmt_conn_id(src, src_port, dst, dst_port); } uint32 extract_uint32(const u_char* data) diff --git a/src/net_util.h b/src/net_util.h index 25b6b293fc..733d946564 100644 --- a/src/net_util.h +++ b/src/net_util.h @@ -1,5 +1,3 @@ -// $Id: net_util.h 6219 2008-10-01 05:39:07Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef netutil_h @@ -7,6 +5,13 @@ #include "config.h" +// Define first. +typedef enum { + TRANSPORT_UNKNOWN, TRANSPORT_TCP, TRANSPORT_UDP, TRANSPORT_ICMP, +} TransportProto; + +typedef enum { IPv4, IPv6 } IPFamily; + #include #include @@ -26,37 +31,82 @@ #ifdef HAVE_NETINET_IP6_H #include -#else -struct ip6_hdr { - uint16 ip6_plen; - uint8 ip6_nxt; - uint8 ip6_hlim; + +#ifndef HAVE_IP6_OPT +struct ip6_opt { + uint8 ip6o_type; + uint8 ip6o_len; }; -#endif +#endif // HAVE_IP6_OPT -#include "util.h" - -#ifdef BROv6 -typedef uint32* addr_type; // a pointer to 4 uint32's -typedef const uint32* const_addr_type; -#define NUM_ADDR_WORDS 4 - -typedef struct { - uint32 net[4]; - uint32 width; -} subnet_type; +#ifndef HAVE_IP6_EXT +struct ip6_ext { + uint8 ip6e_nxt; + uint8 ip6e_len; +}; +#endif // HAVE_IP6_EXT #else -typedef uint32 addr_type; -typedef const uint32 const_addr_type; -#define NUM_ADDR_WORDS 1 -typedef struct { - uint32 net; - uint32 width; -} subnet_type; +struct ip6_hdr { + union { + struct ip6_hdrctl { + uint32 ip6_un1_flow; /* 4 bits version, 8 bits TC, 20 bits + flow-ID */ + uint16 ip6_un1_plen; /* payload length */ + uint8 ip6_un1_nxt; /* next header */ + uint8 ip6_un1_hlim; /* hop limit */ + } ip6_un1; + uint8 ip6_un2_vfc; /* 4 bits version, top 4 bits tclass */ + } ip6_ctlun; + struct in6_addr ip6_src; /* source address */ + struct in6_addr ip6_dst; /* destination address */ +}; -#endif +#define ip6_vfc ip6_ctlun.ip6_un2_vfc +#define ip6_flow ip6_ctlun.ip6_un1.ip6_un1_flow +#define ip6_plen ip6_ctlun.ip6_un1.ip6_un1_plen +#define ip6_nxt ip6_ctlun.ip6_un1.ip6_un1_nxt +#define ip6_hlim ip6_ctlun.ip6_un1.ip6_un1_hlim +#define ip6_hops ip6_ctlun.ip6_un1.ip6_un1_hlim + +struct ip6_opt { + uint8 ip6o_type; + uint8 ip6o_len; +}; + +struct ip6_ext { + uint8 ip6e_nxt; + uint8 ip6e_len; +}; + +struct ip6_frag { + uint8 ip6f_nxt; /* next header */ + uint8 ip6f_reserved; /* reserved field */ + uint16 ip6f_offlg; /* offset, reserved, and flag */ + uint32 ip6f_ident; /* identification */ +}; + +struct ip6_hbh { + uint8 ip6h_nxt; /* next header */ + uint8 ip6h_len; /* length in units of 8 octets */ + /* followed by options */ +}; + +struct ip6_dest { + uint8 ip6d_nxt; /* next header */ + uint8 ip6d_len; /* length in units of 8 octets */ + /* followed by options */ +}; + +struct ip6_rthdr { + uint8 ip6r_nxt; /* next header */ + uint8 ip6r_len; /* length in units of 8 octets */ + uint8 ip6r_type; /* routing type */ + uint8 ip6r_segleft; /* segments left */ + /* followed by routing type specific data */ +}; +#endif // HAVE_NETINET_IP6_H // For Solaris. #if !defined(TCPOPT_WINDOW) && defined(TCPOPT_WSCALE) @@ -83,83 +133,29 @@ inline int seq_delta(uint32 a, uint32 b) return int(a-b); } +class IPAddr; +class IP_Hdr; + // Returns the ones-complement checksum of a chunk of b short-aligned bytes. extern int ones_complement_checksum(const void* p, int b, uint32 sum); -extern int tcp_checksum(const struct ip* ip, const struct tcphdr* tp, int len); -extern int udp_checksum(const struct ip* ip, const struct udphdr* up, int len); -#ifdef BROv6 -extern int udp6_checksum(const struct ip6_hdr* ip, const struct udphdr* up, - int len); -#endif +extern int ones_complement_checksum(const IPAddr& a, uint32 sum); + +extern int icmp6_checksum(const struct icmp* icmpp, const IP_Hdr* ip, int len); extern int icmp_checksum(const struct icmp* icmpp, int len); -// Given an address in host order, returns its "classical network prefix", -// also in host order. -extern uint32 addr_to_net(uint32 addr); +#ifdef ENABLE_MOBILE_IPV6 +extern int mobility_header_checksum(const IP_Hdr* ip); +#endif + // Returns 'A', 'B', 'C' or 'D' extern char addr_to_class(uint32 addr); -// Returns a pointer to static storage giving the ASCII dotted representation -// of the given address, which should be passed in network order. -extern const char* dotted_addr(uint32 addr, int alternative=0); -extern const char* dotted_addr(const uint32* addr, int alternative=0); - -// Same, but for the network prefix. -extern const char* dotted_net(uint32 addr); -extern const char* dotted_net6(const uint32* addr); - -// Given an ASCII dotted representation, returns the corresponding address -// in network order. -extern uint32 dotted_to_addr(const char* addr_text); -extern uint32* dotted_to_addr6(const char* addr_text); - -extern int is_v4_addr(const uint32 addr[4]); -extern uint32 to_v4_addr(const uint32* addr); - -extern uint32 mask_addr(uint32 a, uint32 top_bits_to_keep); -extern const uint32* mask_addr(const uint32* a, uint32 top_bits_to_keep); - +extern const char* fmt_conn_id(const IPAddr& src_addr, uint32 src_port, + const IPAddr& dst_addr, uint32 dst_port); extern const char* fmt_conn_id(const uint32* src_addr, uint32 src_port, const uint32* dst_addr, uint32 dst_port); -inline void copy_addr(const uint32* src_a, uint32* dst_a) - { -#ifdef BROv6 - dst_a[0] = src_a[0]; - dst_a[1] = src_a[1]; - dst_a[2] = src_a[2]; - dst_a[3] = src_a[3]; -#else - dst_a[0] = src_a[0]; -#endif - } - -inline int addr_eq(const uint32* a1, const uint32* a2) - { -#ifdef BROv6 - return a1[0] == a2[0] && - a1[1] == a2[1] && - a1[2] == a2[2] && - a1[3] == a2[3]; -#else - return a1[0] == a2[0]; -#endif - } - -inline int subnet_eq(const subnet_type* s1, const subnet_type* s2) - { -#ifdef BROv6 - return s1->net[0] == s2->net[0] && - s1->net[1] == s2->net[1] && - s1->net[2] == s2->net[2] && - s1->net[3] == s2->net[3] && - s1->width == s2->width; -#else - return s1->net == s2->net && s1->width == s2->width; -#endif - } - // Read 4 bytes from data and return in network order. extern uint32 extract_uint32(const u_char* data); @@ -172,6 +168,8 @@ extern uint32 extract_uint32(const u_char* data); inline double ntohd(double d) { return d; } inline double htond(double d) { return d; } +inline uint64 ntohll(uint64 i) { return i; } +inline uint64 htonll(uint64 i) { return i; } #else @@ -197,6 +195,24 @@ inline double ntohd(double d) inline double htond(double d) { return ntohd(d); } +inline uint64 ntohll(uint64 i) + { + u_char c; + union { + uint64 i; + u_char c[8]; + } x; + + x.i = i; + c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c; + c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c; + c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c; + c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c; + return x.i; + } + +inline uint64 htonll(uint64 i) { return ntohll(i); } + #endif #endif diff --git a/src/netflow-analyzer.pac b/src/netflow-analyzer.pac index 68de4d4a4e..e89a0181a2 100644 --- a/src/netflow-analyzer.pac +++ b/src/netflow-analyzer.pac @@ -1,4 +1,3 @@ -# $Id:$ # Code written by Bernhard Ager (2007). analyzer NetFlow withcontext { diff --git a/src/netflow-protocol.pac b/src/netflow-protocol.pac index 7d106aed34..6b97b7cee6 100644 --- a/src/netflow-protocol.pac +++ b/src/netflow-protocol.pac @@ -1,4 +1,3 @@ -# $Id:$ # Code written by Bernhard Ager (2007). type NetFlowPacket = record { diff --git a/src/netflow.pac b/src/netflow.pac index 8484d5fd11..91040aadeb 100644 --- a/src/netflow.pac +++ b/src/netflow.pac @@ -1,4 +1,3 @@ -# $Id:$ # Code written by Bernhard Ager (2007). %extern{ diff --git a/src/parse.y b/src/parse.y index 2eb84680b7..f78003f08b 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1,9 +1,8 @@ %{ -// $Id: parse.in 6688 2009-04-16 22:44:55Z vern $ // See the file "COPYING" in the main distribution directory for copyright. %} -%expect 88 +%expect 87 %token TOK_ADD TOK_ADD_TO TOK_ADDR TOK_ANY %token TOK_ATENDIF TOK_ATELSE TOK_ATIF TOK_ATIFDEF TOK_ATIFNDEF @@ -11,7 +10,7 @@ %token TOK_CONSTANT TOK_COPY TOK_COUNT TOK_COUNTER TOK_DEFAULT TOK_DELETE %token TOK_DOUBLE TOK_ELSE TOK_ENUM TOK_EVENT TOK_EXPORT TOK_FILE TOK_FOR %token TOK_FUNCTION TOK_GLOBAL TOK_ID TOK_IF TOK_INT -%token TOK_INTERVAL TOK_LIST TOK_LOCAL TOK_MODULE TOK_MATCH +%token TOK_INTERVAL TOK_LIST TOK_LOCAL TOK_MODULE %token TOK_NEXT TOK_OF TOK_PATTERN TOK_PATTERN_TEXT %token TOK_PORT TOK_PRINT TOK_RECORD TOK_REDEF %token TOK_REMOVE_FROM TOK_RETURN TOK_SCHEDULE TOK_SET @@ -30,9 +29,11 @@ %token TOK_DOC TOK_POST_DOC +%token TOK_NO_TEST + %left ',' '|' %right '=' TOK_ADD_TO TOK_REMOVE_FROM -%right '?' ':' TOK_USING +%right '?' ':' %left TOK_OR %left TOK_AND %nonassoc '<' '>' TOK_LE TOK_GE TOK_EQ TOK_NE @@ -43,6 +44,7 @@ %right '!' %left '$' '[' ']' '(' ')' TOK_HAS_FIELD TOK_HAS_ATTR +%type opt_no_test opt_no_test_block %type TOK_ID TOK_PATTERN_TEXT single_pattern TOK_DOC TOK_POST_DOC %type opt_doc_list opt_post_doc_list %type local_id global_id def_global_id event_id global_or_event_id resolve_id begin_func @@ -54,7 +56,7 @@ %type expr init anonymous_function %type event %type stmt stmt_list func_body for_head -%type type opt_type refined_type enum_body +%type type opt_type enum_body %type func_hdr func_params %type type_list %type type_decl formal_args_decl @@ -81,10 +83,12 @@ #include "Reporter.h" #include "BroDoc.h" #include "BroDocObj.h" +#include "Brofiler.h" #include #include +extern Brofiler brofiler; extern BroDoc* current_reST_doc; extern int generate_documentation; extern std::list* reST_doc_comments; @@ -166,7 +170,7 @@ static ID* create_dummy_id (ID* id, BroType* type) ID* fake_id = new ID(copy_string(id->Name()), (IDScope) id->Scope(), is_export); - fake_id->SetType(type); + fake_id->SetType(type->Ref()); if ( id->AsType() ) { @@ -195,6 +199,7 @@ static std::list* concat_opt_docs (std::list* pre, %} %union { + bool b; char* str; std::list* str_l; ID* id; @@ -499,12 +504,6 @@ expr: $$ = new VectorConstructorExpr($3); } - | TOK_MATCH expr TOK_USING expr - { - set_location(@1, @4); - $$ = new RecordMatchExpr($2, $4); - } - | expr '(' opt_expr_list ')' { set_location(@1, @4); @@ -1105,7 +1104,7 @@ decl: } } - | TOK_TYPE global_id ':' refined_type opt_attr ';' + | TOK_TYPE global_id ':' type opt_attr ';' { add_type($2, $4, $5, 0); @@ -1135,7 +1134,7 @@ decl: } } - | TOK_EVENT event_id ':' refined_type opt_attr ';' + | TOK_EVENT event_id ':' type_list opt_attr ';' { add_type($2, $4, $5, 1); @@ -1179,7 +1178,7 @@ func_hdr: FUNC_FLAVOR_EVENT, 0, $3); $$ = $3; if ( generate_documentation ) - current_reST_doc->AddEvent( + current_reST_doc->AddEventHandler( new BroDocObj($2, reST_doc_comments)); } | TOK_REDEF TOK_EVENT event_id func_params @@ -1221,13 +1220,6 @@ func_params: { $$ = new FuncType($2, base_type(TYPE_VOID), 0); } ; -refined_type: - type_list '{' type_decl_list '}' - { $$ = refine_type($1, $3); } - | type_list - { $$ = refine_type($1, 0); } - ; - opt_type: ':' type { $$ = $2; } @@ -1321,22 +1313,28 @@ attr: ; stmt: - '{' stmt_list '}' + '{' opt_no_test_block stmt_list '}' { - set_location(@1, @3); - $$ = $2; + set_location(@1, @4); + $$ = $3; + if ( $2 ) + brofiler.DecIgnoreDepth(); } - | TOK_PRINT expr_list ';' + | TOK_PRINT expr_list ';' opt_no_test { set_location(@1, @3); $$ = new PrintStmt($2); + if ( ! $4 ) + brofiler.AddStmt($$); } - | TOK_EVENT event ';' + | TOK_EVENT event ';' opt_no_test { set_location(@1, @3); $$ = new EventStmt($2); + if ( ! $4 ) + brofiler.AddStmt($$); } | TOK_IF '(' expr ')' stmt @@ -1358,54 +1356,72 @@ stmt: } | for_head stmt - { $1->AsForStmt()->AddBody($2); } + { + $1->AsForStmt()->AddBody($2); + } - | TOK_NEXT ';' + | TOK_NEXT ';' opt_no_test { set_location(@1, @2); $$ = new NextStmt; + if ( ! $3 ) + brofiler.AddStmt($$); } - | TOK_BREAK ';' + | TOK_BREAK ';' opt_no_test { set_location(@1, @2); $$ = new BreakStmt; + if ( ! $3 ) + brofiler.AddStmt($$); } - | TOK_RETURN ';' + | TOK_RETURN ';' opt_no_test { set_location(@1, @2); $$ = new ReturnStmt(0); + if ( ! $3 ) + brofiler.AddStmt($$); } - | TOK_RETURN expr ';' + | TOK_RETURN expr ';' opt_no_test { set_location(@1, @2); $$ = new ReturnStmt($2); + if ( ! $4 ) + brofiler.AddStmt($$); } - | TOK_ADD expr ';' + | TOK_ADD expr ';' opt_no_test { set_location(@1, @3); $$ = new AddStmt($2); + if ( ! $4 ) + brofiler.AddStmt($$); } - | TOK_DELETE expr ';' + | TOK_DELETE expr ';' opt_no_test { set_location(@1, @3); $$ = new DelStmt($2); + if ( ! $4 ) + brofiler.AddStmt($$); } - | TOK_LOCAL local_id opt_type init_class opt_init opt_attr ';' + | TOK_LOCAL local_id opt_type init_class opt_init opt_attr ';' opt_no_test { set_location(@1, @7); $$ = add_local($2, $3, $4, $5, $6, VAR_REGULAR); + if ( ! $8 ) + brofiler.AddStmt($$); } - | TOK_CONST local_id opt_type init_class opt_init opt_attr ';' + | TOK_CONST local_id opt_type init_class opt_init opt_attr ';' opt_no_test { set_location(@1, @6); $$ = add_local($2, $3, $4, $5, $6, VAR_CONST); + if ( ! $8 ) + brofiler.AddStmt($$); } | TOK_WHEN '(' expr ')' stmt @@ -1414,10 +1430,12 @@ stmt: $$ = new WhenStmt($3, $5, 0, 0, false); } - | TOK_WHEN '(' expr ')' stmt TOK_TIMEOUT expr '{' stmt_list '}' + | TOK_WHEN '(' expr ')' stmt TOK_TIMEOUT expr '{' opt_no_test_block stmt_list '}' { - set_location(@3, @8); - $$ = new WhenStmt($3, $5, $9, $7, false); + set_location(@3, @9); + $$ = new WhenStmt($3, $5, $10, $7, false); + if ( $9 ) + brofiler.DecIgnoreDepth(); } @@ -1427,16 +1445,20 @@ stmt: $$ = new WhenStmt($4, $6, 0, 0, true); } - | TOK_RETURN TOK_WHEN '(' expr ')' stmt TOK_TIMEOUT expr '{' stmt_list '}' + | TOK_RETURN TOK_WHEN '(' expr ')' stmt TOK_TIMEOUT expr '{' opt_no_test_block stmt_list '}' { - set_location(@4, @9); - $$ = new WhenStmt($4, $6, $10, $8, true); + set_location(@4, @10); + $$ = new WhenStmt($4, $6, $11, $8, true); + if ( $10 ) + brofiler.DecIgnoreDepth(); } - | expr ';' + | expr ';' opt_no_test { set_location(@1, @2); $$ = new ExprStmt($1); + if ( ! $3 ) + brofiler.AddStmt($$); } | ';' @@ -1594,7 +1616,7 @@ resolve_id: $$ = lookup_ID($1, current_module.c_str()); if ( ! $$ ) - reporter->Error("identifier not defined:", $1); + reporter->Error("identifier not defined: %s", $1); delete [] $1; } @@ -1634,6 +1656,18 @@ opt_doc_list: { $$ = 0; } ; +opt_no_test: + TOK_NO_TEST + { $$ = true; } + | + { $$ = false; } + +opt_no_test_block: + TOK_NO_TEST + { $$ = true; brofiler.IncIgnoreDepth(); } + | + { $$ = false; } + %% int yyerror(const char msg[]) @@ -1651,7 +1685,7 @@ int yyerror(const char msg[]) strcat(msgbuf, "\nDocumentation mode is enabled: " "remember to check syntax of ## style comments\n"); - reporter->Error(msgbuf); + reporter->Error("%s", msgbuf); return 0; } diff --git a/src/patricia.c b/src/patricia.c index 8e40cb5ef6..1dbc795ab7 100644 --- a/src/patricia.c +++ b/src/patricia.c @@ -1,5 +1,4 @@ /* - * $Id: patricia.c 80 2004-07-14 20:15:50Z jason $ * Dave Plonka * * This product includes software developed by the University of Michigan, @@ -116,16 +115,12 @@ local_inet_pton (int af, const char *src, void *dst) } } #ifdef NT -#ifdef HAVE_IPV6 else if (af == AF_INET6) { struct in6_addr Address; return (inet6_addr(src, &Address)); } -#endif /* HAVE_IPV6 */ -#endif /* NT */ -#ifndef NT +#else else { - errno = EAFNOSUPPORT; return -1; } @@ -161,10 +156,8 @@ my_inet_pton (int af, const char *src, void *dst) } memcpy (dst, xp, 4); return (1); -#ifdef HAVE_IPV6 } else if (af == AF_INET6) { return (local_inet_pton (af, src, dst)); -#endif /* HAVE_IPV6 */ } else { #ifndef NT errno = EAFNOSUPPORT; @@ -218,7 +211,6 @@ prefix_toa2x (prefix_t *prefix, char *buff, int with_len) } return (buff); } -#ifdef HAVE_IPV6 else if (prefix->family == AF_INET6) { char *r; r = (char *) inet_ntop (AF_INET6, &prefix->add.sin6, buff, 48 /* a guess value */ ); @@ -228,7 +220,6 @@ prefix_toa2x (prefix_t *prefix, char *buff, int with_len) } return (buff); } -#endif /* HAVE_IPV6 */ else return (NULL); } @@ -256,17 +247,15 @@ New_Prefix2 (int family, void *dest, int bitlen, prefix_t *prefix) int dynamic_allocated = 0; int default_bitlen = 32; -#ifdef HAVE_IPV6 if (family == AF_INET6) { default_bitlen = 128; if (prefix == NULL) { - prefix = calloc(1, sizeof (prefix6_t)); + prefix = calloc(1, sizeof (prefix_t)); dynamic_allocated++; } memcpy (&prefix->add.sin6, dest, 16); } else -#endif /* HAVE_IPV6 */ if (family == AF_INET) { if (prefix == NULL) { #ifndef NT @@ -309,9 +298,7 @@ ascii2prefix (int family, char *string) u_long bitlen, maxbitlen = 0; char *cp; struct in_addr sin; -#ifdef HAVE_IPV6 struct in6_addr sin6; -#endif /* HAVE_IPV6 */ int result; char save[MAXLINE]; @@ -321,19 +308,15 @@ ascii2prefix (int family, char *string) /* easy way to handle both families */ if (family == 0) { family = AF_INET; -#ifdef HAVE_IPV6 if (strchr (string, ':')) family = AF_INET6; -#endif /* HAVE_IPV6 */ } if (family == AF_INET) { maxbitlen = 32; } -#ifdef HAVE_IPV6 else if (family == AF_INET6) { maxbitlen = 128; } -#endif /* HAVE_IPV6 */ if ((cp = strchr (string, '/')) != NULL) { bitlen = atol (cp + 1); @@ -356,7 +339,6 @@ ascii2prefix (int family, char *string) return (New_Prefix (AF_INET, &sin, bitlen)); } -#ifdef HAVE_IPV6 else if (family == AF_INET6) { // Get rid of this with next IPv6 upgrade #if defined(NT) && !defined(HAVE_INET_NTOP) @@ -368,7 +350,6 @@ ascii2prefix (int family, char *string) #endif /* NT */ return (New_Prefix (AF_INET6, &sin6, bitlen)); } -#endif /* HAVE_IPV6 */ else return (NULL); } diff --git a/src/patricia.h b/src/patricia.h index 0118679331..dc67226362 100644 --- a/src/patricia.h +++ b/src/patricia.h @@ -1,5 +1,4 @@ /* - * $Id: patricia.h 967 2005-01-03 07:19:06Z vern $ * Dave Plonka * * This product includes software developed by the University of Michigan, @@ -53,13 +52,6 @@ #include - -#ifdef BROv6 -#ifndef HAVE_IPV6 -#define HAVE_IPV6 -#endif -#endif - /* typedef unsigned int u_int; */ typedef void (*void_fn_t)(); /* { from defs.h */ @@ -89,9 +81,7 @@ typedef struct _prefix_t { int ref_count; /* reference count */ union { struct in_addr sin; -#ifdef HAVE_IPV6 struct in6_addr sin6; -#endif /* IPV6 */ } add; } prefix_t; diff --git a/src/re-parse.y b/src/re-parse.y index 26c8ab6716..3847c06f29 100644 --- a/src/re-parse.y +++ b/src/re-parse.y @@ -1,8 +1,6 @@ // parse.y - parser for flex input %{ -// $Id: re-parse.y 5857 2008-06-26 23:00:03Z vern $ - #include #include "CCL.h" diff --git a/src/re-scan.l b/src/re-scan.l index fbd85899a4..0d737f08a6 100644 --- a/src/re-scan.l +++ b/src/re-scan.l @@ -5,8 +5,6 @@ */ %{ -// $Id: re-scan.l 6219 2008-10-01 05:39:07Z vern $ - #include "CCL.h" #include "NFA.h" #include "util.h" diff --git a/src/reporter.bif b/src/reporter.bif index 4a77c2fcda..c0f83205c3 100644 --- a/src/reporter.bif +++ b/src/reporter.bif @@ -1,3 +1,11 @@ +##! The reporter built-in functions allow for the scripting layer to +##! generate messages of varying severity. If no event handlers +##! exist for reporter messages, the messages are output to stderr. +##! If event handlers do exist, it's assumed they take care of determining +##! how/where to output the messages. +##! +##! See :doc:`/scripts/base/frameworks/reporter/main` for a convenient +##! reporter message logging framework. module Reporter; @@ -5,6 +13,13 @@ module Reporter; #include "NetVar.h" %%} +## Generates an informational message. +## +## msg: The informational message to report. +## +## Returns: Always true. +## +## .. bro:see:: reporter_info function Reporter::info%(msg: string%): bool %{ reporter->PushLocation(frame->GetCall()->GetLocationInfo()); @@ -13,6 +28,13 @@ function Reporter::info%(msg: string%): bool return new Val(1, TYPE_BOOL); %} +## Generates a message that warns of a potential problem. +## +## msg: The warning message to report. +## +## Returns: Always true. +## +## .. bro:see:: reporter_warning function Reporter::warning%(msg: string%): bool %{ reporter->PushLocation(frame->GetCall()->GetLocationInfo()); @@ -21,6 +43,14 @@ function Reporter::warning%(msg: string%): bool return new Val(1, TYPE_BOOL); %} +## Generates a non-fatal error indicative of a definite problem that should +## be addressed. Program execution does not terminate. +## +## msg: The error message to report. +## +## Returns: Always true. +## +## .. bro:see:: reporter_error function Reporter::error%(msg: string%): bool %{ reporter->PushLocation(frame->GetCall()->GetLocationInfo()); @@ -28,3 +58,16 @@ function Reporter::error%(msg: string%): bool reporter->PopLocation(); return new Val(1, TYPE_BOOL); %} + +## Generates a fatal error on stderr and terminates program execution. +## +## msg: The error message to report. +## +## Returns: Always true. +function Reporter::fatal%(msg: string%): bool + %{ + reporter->PushLocation(frame->GetCall()->GetLocationInfo()); + reporter->FatalError("%s", msg->CheckString()); + reporter->PopLocation(); + return new Val(1, TYPE_BOOL); + %} diff --git a/src/rule-parse.y b/src/rule-parse.y index 73c04a72ab..c8770c3e22 100644 --- a/src/rule-parse.y +++ b/src/rule-parse.y @@ -1,6 +1,4 @@ %{ -/* $Id: rule-parse.y 5988 2008-07-19 07:02:12Z vern $ */ - #include #include "RuleMatcher.h" #include "Reporter.h" diff --git a/src/rule-scan.l b/src/rule-scan.l index 0c444543b2..781c477ff2 100644 --- a/src/rule-scan.l +++ b/src/rule-scan.l @@ -1,5 +1,3 @@ -/* $Id: rule-scan.l 6914 2009-09-22 00:35:24Z vern $ */ - %{ typedef unsigned int uint32; @@ -20,7 +18,7 @@ WS [ \t]+ D [0-9]+ H [0-9a-fA-F]+ STRING \"([^\n\"]|\\\")*\" -ID [0-9a-zA-Z_-]+ +ID ([0-9a-zA-Z_-]+::)*[0-9a-zA-Z_-]+ RE \/(\\\/)?([^/]|[^\\]\\\/)*\/ META \.[^ \t]+{WS}[^\n]+ PID ([0-9a-zA-Z_-]|"::")+ diff --git a/src/scan.l b/src/scan.l index cdeedbf038..ca7a01574c 100644 --- a/src/scan.l +++ b/src/scan.l @@ -1,4 +1,3 @@ -/* $Id: scan.l 6510 2009-01-08 14:51:04Z vern $ */ %{ // See the file "COPYING" in the main distribution directory for copyright. @@ -51,7 +50,7 @@ char last_tok[128]; // a read fails. #define YY_INPUT(buf,result,max_size) \ if ( ((result = fread(buf, 1, max_size, yyin)) == 0) && ferror(yyin) ) \ - reporter->Error(fmt("read failed with \"%s\"", strerror(errno))); + reporter->Error("read failed with \"%s\"", strerror(errno)); // reST documents that we've created (or have at least opened so far). std::list docs_generated; @@ -80,6 +79,19 @@ static const char* canon_doc_comment(const char* comment) return ( comment[0] == ' ' ) ? comment + 1 : comment; } +static std::string canon_doc_func_param(const char* id_start) + { + std::string id_name(id_start, strcspn(id_start, ":")); + const char* comment = id_start + id_name.size() + 1; + std::string doc; + + if ( id_name == "Returns" ) + doc.append(":returns:").append(comment); + else + doc.append(":param ").append(id_name).append(":").append(comment); + return doc; + } + static ino_t get_inode_num(FILE* f, const char* filename) { struct stat b; @@ -155,6 +167,12 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) return TOK_POST_DOC; } +##{OWS}{ID}:{WS}.* { + const char* id_start = skip_whitespace(yytext + 2); + yylval.str = copy_string(canon_doc_func_param(id_start).c_str()); + return TOK_DOC; +} + ##.* { if ( yytext[2] != '#' ) { @@ -163,26 +181,12 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) } } -##{OWS}{ID}:.* { +##{OWS}{ID}:{WS}.* { if ( generate_documentation ) { // Comment is documenting either a function parameter or return type, // so appropriate reST markup substitutions are automatically made // in order to distinguish them from other comments. - const char* id_start = skip_whitespace(yytext + 2); - size_t id_len = strcspn(id_start, ":"); - char* id_name = new char[id_len + 1]; - strncpy(id_name, id_start, id_len); - id_name[id_len] = '\0'; - const char* comment = id_start + id_len + 1; - - std::string doc; - - if ( streq(id_name, "Returns") ) - doc.append(":returns:").append(comment); - else - doc.append(":param ").append(id_name).append(":").append(comment); - if ( ! reST_doc_comments ) reST_doc_comments = new std::list(); @@ -192,12 +196,16 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) // 2) has a blank line between it and non-field-list reST markup, // which is required for correct HTML rendering by Sphinx reST_doc_comments->push_back(""); - reST_doc_comments->push_back(doc); - - delete [] id_name; + const char* id_start = skip_whitespace(yytext + 2); + reST_doc_comments->push_back(canon_doc_func_param(id_start)); } } +##<.* { + if ( generate_documentation && BroDocObj::last ) + BroDocObj::last->AddDocString(canon_doc_comment(yytext + 3)); +} + ##.* { if ( generate_documentation && (yytext[2] != '#') ) { @@ -208,6 +216,8 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) } } +#{OWS}@no-test.* return TOK_NO_TEST; + #.* /* eat comments */ {WS} /* eat whitespace */ @@ -218,6 +228,24 @@ ESCSEQ (\\([^\n]|[0-7]+|x[[:xdigit:]]+)) ++yylloc.last_line; } + /* IPv6 literal constant patterns */ +"["({HEX}:){7}{HEX}"]" { + string s(yytext+1); + RET_CONST(new AddrVal(s.erase(s.size()-1))) +} +"["0x{HEX}({HEX}|:)*"::"({HEX}|:)*"]" { + string s(yytext+3); + RET_CONST(new AddrVal(s.erase(s.size()-1))) +} +"["({HEX}|:)*"::"({HEX}|:)*"]" { + string s(yytext+1); + RET_CONST(new AddrVal(s.erase(s.size()-1))) +} +"["({HEX}|:)*"::"({HEX}|:)*({D}"."){3}{D}"]" { + string s(yytext+1); + RET_CONST(new AddrVal(s.erase(s.size()-1))) +} + [!%*/+\-,:;<=>?()\[\]{}~$|] return yytext[0]; "--" return TOK_DECR; @@ -263,7 +291,6 @@ int return TOK_INT; interval return TOK_INTERVAL; list return TOK_LIST; local return TOK_LOCAL; -match return TOK_MATCH; module return TOK_MODULE; next return TOK_NEXT; of return TOK_OF; @@ -285,7 +312,6 @@ timeout return TOK_TIMEOUT; timer return TOK_TIMER; type return TOK_TYPE; union return TOK_UNION; -using return TOK_USING; vector return TOK_VECTOR; when return TOK_WHEN; @@ -405,7 +431,7 @@ F RET_CONST(new Val(false, TYPE_BOOL)) uint32 p = atoi(yytext); if ( p > 65535 ) { - reporter->Error("bad port number -", yytext); + reporter->Error("bad port number - %s", yytext); p = 0; } RET_CONST(new PortVal(p, TRANSPORT_TCP)) @@ -414,7 +440,7 @@ F RET_CONST(new Val(false, TYPE_BOOL)) uint32 p = atoi(yytext); if ( p > 65535 ) { - reporter->Error("bad port number -", yytext); + reporter->Error("bad port number - %s", yytext); p = 0; } RET_CONST(new PortVal(p, TRANSPORT_UDP)) @@ -423,7 +449,7 @@ F RET_CONST(new Val(false, TYPE_BOOL)) uint32 p = atoi(yytext); if ( p > 255 ) { - reporter->Error("bad port number -", yytext); + reporter->Error("bad port number - %s", yytext); p = 0; } RET_CONST(new PortVal(p, TRANSPORT_ICMP)) @@ -432,7 +458,7 @@ F RET_CONST(new Val(false, TYPE_BOOL)) uint32 p = atoi(yytext); if ( p > 255 ) { - reporter->Error("bad port number -", yytext); + reporter->Error("bad port number - %s", yytext); p = 0; } RET_CONST(new PortVal(p, TRANSPORT_UNKNOWN)) @@ -440,11 +466,6 @@ F RET_CONST(new Val(false, TYPE_BOOL)) ({D}"."){3}{D} RET_CONST(new AddrVal(yytext)) -({HEX}:){7}{HEX} RET_CONST(new AddrVal(yytext)) - -0x{HEX}({HEX}|:)*"::"({HEX}|:)* RET_CONST(new AddrVal(yytext+2)) -(({D}|:)({HEX}|:)*)?"::"({HEX}|:)* RET_CONST(new AddrVal(yytext)) - "0x"{HEX}+ RET_CONST(new Val(static_cast(strtol(yytext, 0, 16)), TYPE_COUNT)) {H}("."{H})+ RET_CONST(dns_mgr->LookupHost(yytext)) @@ -496,7 +517,7 @@ F RET_CONST(new Val(false, TYPE_BOOL)) [/\\\n] return yytext[0]; -<*>. reporter->Error("unrecognized character -", yytext); +<*>. reporter->Error("unrecognized character - %s", yytext); <> last_tok[0] = '\0'; return EOF; @@ -1027,7 +1048,7 @@ void clear_reST_doc_comments() if ( ! reST_doc_comments ) return; - fprintf(stderr, "Warning: %lu unconsumed reST comments:\n", + fprintf(stderr, "Warning: %zu unconsumed reST comments:\n", reST_doc_comments->size()); print_current_reST_doc_comments(); diff --git a/src/setsignal.c b/src/setsignal.c index f5263bb06d..b49f0784e9 100644 --- a/src/setsignal.c +++ b/src/setsignal.c @@ -2,11 +2,6 @@ * See the file "COPYING" in the main distribution directory for copyright. */ -#ifndef lint -static const char rcsid[] = - "@(#) $Id: setsignal.c 6219 2008-10-01 05:39:07Z vern $ (LBL)"; -#endif - #include "config.h" /* must appear before first ifdef */ #include diff --git a/src/setsignal.h b/src/setsignal.h index 8bacdca8db..b768ed031f 100644 --- a/src/setsignal.h +++ b/src/setsignal.h @@ -1,7 +1,6 @@ /* * See the file "COPYING" in the main distribution directory for copyright. * - * @(#) $Id: setsignal.h 6219 2008-10-01 05:39:07Z vern $ (LBL) */ #ifndef setsignal_h #define setsignal_h diff --git a/src/smb-protocol.pac b/src/smb-protocol.pac index b00613f16c..585edfacd6 100644 --- a/src/smb-protocol.pac +++ b/src/smb-protocol.pac @@ -1,5 +1,3 @@ -# $Id$ -# # CIFS/SMB # TODO: diff --git a/src/smb.pac b/src/smb.pac index 4bd2c34bc5..740ad47991 100644 --- a/src/smb.pac +++ b/src/smb.pac @@ -1,5 +1,3 @@ -# $Id: smb.pac 3929 2007-01-14 00:37:59Z vern $ - %include binpac.pac %include bro.pac diff --git a/src/ssl-analyzer.pac b/src/ssl-analyzer.pac index e543b4c351..f41fb8639b 100644 --- a/src/ssl-analyzer.pac +++ b/src/ssl-analyzer.pac @@ -22,11 +22,17 @@ } }; + string orig_label(bool is_orig); void free_X509(void *); X509* d2i_X509_binpac(X509** px, const uint8** in, int len); %} %code{ +string orig_label(bool is_orig) + { + return string(is_orig ? "originator" :"responder"); + } + void free_X509(void* cert) { X509_free((X509*) cert); @@ -75,17 +81,21 @@ function version_ok(vers : uint16) : bool refine connection SSL_Conn += { %member{ + int eof; %} %init{ + eof=0; %} %eof{ - if ( state_ != STATE_CONN_ESTABLISHED && + if ( ! eof && + state_ != STATE_CONN_ESTABLISHED && state_ != STATE_TRACK_LOST && state_ != STATE_INITIAL ) bro_analyzer()->ProtocolViolation(fmt("unexpected end of connection in state %s", state_label(state_).c_str())); + ++eof; %} %cleanup{ @@ -113,14 +123,14 @@ refine connection SSL_Conn += { function proc_alert(rec: SSLRecord, level : int, desc : int) : bool %{ BifEvent::generate_ssl_alert(bro_analyzer(), bro_analyzer()->Conn(), - level, desc); + ${rec.is_orig}, level, desc); return true; %} function proc_client_hello(rec: SSLRecord, version : uint16, ts : double, session_id : uint8[], - cipher_suites16 : uint16[], + cipher_suites16 : uint16[], cipher_suites24 : uint24[]) : bool %{ if ( state_ == STATE_TRACK_LOST ) @@ -134,7 +144,7 @@ refine connection SSL_Conn += { if ( ssl_client_hello ) { vector* cipher_suites = new vector(); - if ( cipher_suites16 ) + if ( cipher_suites16 ) std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*cipher_suites)); else std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*cipher_suites), to_int()); @@ -146,15 +156,15 @@ refine connection SSL_Conn += { cipher_set->Assign(ciph, 0); Unref(ciph); } - + BifEvent::generate_ssl_client_hello(bro_analyzer(), bro_analyzer()->Conn(), version, ts, to_string_val(session_id), cipher_set); - + delete cipher_suites; } - + return true; %} @@ -183,24 +193,36 @@ refine connection SSL_Conn += { std::copy(cipher_suites16->begin(), cipher_suites16->end(), std::back_inserter(*ciphers)); else std::transform(cipher_suites24->begin(), cipher_suites24->end(), std::back_inserter(*ciphers), to_int()); - + BifEvent::generate_ssl_server_hello(bro_analyzer(), bro_analyzer()->Conn(), version, ts, to_string_val(session_id), ciphers->size()==0 ? 0 : ciphers->at(0), comp_method); - + delete ciphers; } + + return true; + %} + function proc_session_ticket_handshake(rec: SessionTicketHandshake, is_orig: bool): bool + %{ + if ( ssl_session_ticket_handshake ) + { + BifEvent::generate_ssl_session_ticket_handshake(bro_analyzer(), + bro_analyzer()->Conn(), + ${rec.ticket_lifetime_hint}, + new StringVal(${rec.data}.length(), (const char*) ${rec.data}.data())); + } return true; %} - function proc_ssl_extension(type: int, data: bytestring) : bool + function proc_ssl_extension(rec: SSLRecord, type: int, data: bytestring) : bool %{ if ( ssl_extension ) BifEvent::generate_ssl_extension(bro_analyzer(), - bro_analyzer()->Conn(), type, + bro_analyzer()->Conn(), ${rec.is_orig}, type, new StringVal(data.length(), (const char*) data.data())); return true; %} @@ -218,7 +240,7 @@ refine connection SSL_Conn += { if ( x509_certificate ) { STACK_OF(X509)* untrusted_certs = 0; - + for ( unsigned int i = 0; i < certificates->size(); ++i ) { const bytestring& cert = (*certificates)[i]; @@ -227,7 +249,7 @@ refine connection SSL_Conn += { if ( ! pTemp ) { BifEvent::generate_x509_error(bro_analyzer(), bro_analyzer()->Conn(), - ERR_get_error()); + ${rec.is_orig}, ERR_get_error()); return false; } @@ -253,34 +275,35 @@ refine connection SSL_Conn += { StringVal* der_cert = new StringVal(cert.length(), (const char*) cert.data()); BifEvent::generate_x509_certificate(bro_analyzer(), bro_analyzer()->Conn(), + ${rec.is_orig}, pX509Cert, - ! ${rec.is_orig}, i, certificates->size(), der_cert); // Are there any X509 extensions? + //printf("Number of x509 extensions: %d\n", X509_get_ext_count(pTemp)); if ( x509_extension && X509_get_ext_count(pTemp) > 0 ) { int num_ext = X509_get_ext_count(pTemp); for ( int k = 0; k < num_ext; ++k ) { - char *pBuffer = 0; - int length = 0; + unsigned char *pBuffer = 0; + uint length = 0; X509_EXTENSION* ex = X509_get_ext(pTemp, k); if (ex) { ASN1_STRING *pString = X509_EXTENSION_get_data(ex); - length = ASN1_STRING_to_UTF8((unsigned char**)&pBuffer, pString); + length = ASN1_STRING_to_UTF8(&pBuffer, pString); //i2t_ASN1_OBJECT(&pBuffer, length, obj) - + // printf("extension length: %u\n", length); // -1 indicates an error. if ( length < 0 ) continue; - StringVal* value = new StringVal(length, pBuffer); + StringVal* value = new StringVal(length, (char*)pBuffer); BifEvent::generate_x509_extension(bro_analyzer(), - bro_analyzer()->Conn(), value); + bro_analyzer()->Conn(), ${rec.is_orig}, value); OPENSSL_free(pBuffer); } } @@ -432,6 +455,10 @@ refine typeattr Handshake += &let { proc : bool = $context.connection.proc_handshake(this, rec.is_orig); }; +refine typeattr SessionTicketHandshake += &let { + proc : bool = $context.connection.proc_session_ticket_handshake(this, rec.is_orig); +} + refine typeattr UnknownRecord += &let { proc : bool = $context.connection.proc_unknown_record(rec); }; @@ -441,5 +468,5 @@ refine typeattr CiphertextRecord += &let { } refine typeattr SSLExtension += &let { - proc : bool = $context.connection.proc_ssl_extension(type, data); + proc : bool = $context.connection.proc_ssl_extension(rec, type, data); }; diff --git a/src/ssl-defs.pac b/src/ssl-defs.pac index 6a4a91bb36..31d90338f5 100644 --- a/src/ssl-defs.pac +++ b/src/ssl-defs.pac @@ -1,5 +1,3 @@ -# $Id:$ - # Some common definitions for the SSL and SSL record-layer analyzers. %extern{ diff --git a/src/ssl-protocol.pac b/src/ssl-protocol.pac index 9e88186d39..627645e4da 100644 --- a/src/ssl-protocol.pac +++ b/src/ssl-protocol.pac @@ -22,7 +22,6 @@ type uint24 = record { }; string state_label(int state_nr); - string orig_label(bool is_orig); double get_time_from_asn1(const ASN1_TIME * atime); string handshake_type_label(int type); %} @@ -35,7 +34,7 @@ type SSLRecord(is_orig: bool) = record { head2 : uint8; head3 : uint8; head4 : uint8; - rec : RecordText(this, is_orig)[] &length=length, &requires(content_type); + rec : RecordText(this)[] &length=length, &requires(content_type); } &length = length+5, &byteorder=bigendian, &let { version : int = @@ -54,25 +53,18 @@ type SSLRecord(is_orig: bool) = record { }; }; -type RecordText(rec: SSLRecord, is_orig: bool) = case $context.connection.state() of { +type RecordText(rec: SSLRecord) = case $context.connection.state() of { STATE_ABBREV_SERVER_ENCRYPTED, STATE_CLIENT_ENCRYPTED, STATE_COMM_ENCRYPTED, STATE_CONN_ESTABLISHED - -> ciphertext : CiphertextRecord(rec, is_orig); + -> ciphertext : CiphertextRecord(rec); default - -> plaintext : PlaintextRecord(rec, is_orig); + -> plaintext : PlaintextRecord(rec); }; -type PossibleEncryptedHandshake(rec: SSLRecord, is_orig: bool) = case $context.connection.state() of { - # Deal with encrypted handshakes before the server cipher spec change. - STATE_CLIENT_FINISHED, STATE_CLIENT_ENCRYPTED - -> ct : CiphertextRecord(rec, is_orig); - default -> hs : Handshake(rec); -}; - -type PlaintextRecord(rec: SSLRecord, is_orig: bool) = case rec.content_type of { +type PlaintextRecord(rec: SSLRecord) = case rec.content_type of { CHANGE_CIPHER_SPEC -> ch_cipher : ChangeCipherSpec(rec); ALERT -> alert : Alert(rec); - HANDSHAKE -> handshake : PossibleEncryptedHandshake(rec, is_orig); + HANDSHAKE -> handshake : Handshake(rec); APPLICATION_DATA -> app_data : ApplicationData(rec); V2_ERROR -> v2_error : V2Error(rec); V2_CLIENT_HELLO -> v2_client_hello : V2ClientHello(rec); @@ -81,7 +73,7 @@ type PlaintextRecord(rec: SSLRecord, is_orig: bool) = case rec.content_type of { default -> unknown_record : UnknownRecord(rec); }; -type SSLExtension = record { +type SSLExtension(rec: SSLRecord) = record { type: uint16; data_len: uint16; data: bytestring &length=data_len; @@ -156,10 +148,6 @@ enum AnalyzerState { } } - string orig_label(bool is_orig) - { - return string(is_orig ? "originator" :"responder"); - } double get_time_from_asn1(const ASN1_TIME * atime) { @@ -265,18 +253,19 @@ enum AnalyzerState { ###################################################################### enum HandshakeType { - HELLO_REQUEST = 0, - CLIENT_HELLO = 1, - SERVER_HELLO = 2, - CERTIFICATE = 11, - SERVER_KEY_EXCHANGE = 12, - CERTIFICATE_REQUEST = 13, - SERVER_HELLO_DONE = 14, - CERTIFICATE_VERIFY = 15, - CLIENT_KEY_EXCHANGE = 16, - FINISHED = 20, - CERTIFICATE_URL = 21, # RFC 3546 - CERTIFICATE_STATUS = 22, # RFC 3546 + HELLO_REQUEST = 0, + CLIENT_HELLO = 1, + SERVER_HELLO = 2, + SESSION_TICKET = 4, # RFC 5077 + CERTIFICATE = 11, + SERVER_KEY_EXCHANGE = 12, + CERTIFICATE_REQUEST = 13, + SERVER_HELLO_DONE = 14, + CERTIFICATE_VERIFY = 15, + CLIENT_KEY_EXCHANGE = 16, + FINISHED = 20, + CERTIFICATE_URL = 21, # RFC 3546 + CERTIFICATE_STATUS = 22, # RFC 3546 }; %code{ @@ -286,6 +275,7 @@ enum HandshakeType { case HELLO_REQUEST: return string("HELLO_REQUEST"); case CLIENT_HELLO: return string("CLIENT_HELLO"); case SERVER_HELLO: return string("SERVER_HELLO"); + case SESSION_TICKET: return string("SESSION_TICKET"); case CERTIFICATE: return string("CERTIFICATE"); case SERVER_KEY_EXCHANGE: return string("SERVER_KEY_EXCHANGE"); case CERTIFICATE_REQUEST: return string("CERTIFICATE_REQUEST"); @@ -389,7 +379,7 @@ type ClientHello(rec: SSLRecord) = record { # This weirdness is to deal with the possible existence or absence # of the following fields. ext_len: uint16[] &until($element == 0 || $element != 0); - extensions : SSLExtension[] &until($input.length() == 0); + extensions : SSLExtension(rec)[] &until($input.length() == 0); } &let { state_changed : bool = $context.connection.transition(STATE_INITIAL, @@ -457,8 +447,7 @@ type V2ServerHello(rec: SSLRecord) = record { cert_data : bytestring &length = cert_len; ciphers : uint24[ciph_len/3]; conn_id_data : bytestring &length = conn_id_len; -} #&length = 8 + cert_len + ciph_len + conn_id_len, -&let { +} &let { state_changed : bool = (session_id_hit > 0 ? $context.connection.transition(STATE_CLIENT_HELLO_RCVD, @@ -608,7 +597,7 @@ type CertificateVerify(rec: SSLRecord) = record { ###################################################################### # The finished messages are always sent after encryption is in effect, -# so we will not be able to read those message. +# so we will not be able to read those messages. type Finished(rec: SSLRecord) = record { cont : bytestring &restofdata &transient; } &let { @@ -620,13 +609,17 @@ type Finished(rec: SSLRecord) = record { $context.connection.lost_track(); }; +type SessionTicketHandshake(rec: SSLRecord) = record { + ticket_lifetime_hint: uint32; + data: bytestring &restofdata; +}; ###################################################################### # V3 Handshake Protocol (7.) ###################################################################### type UnknownHandshake(hs: Handshake, is_orig: bool) = record { - cont : bytestring &restofdata &transient; + data : bytestring &restofdata &transient; } &let { state_changed : bool = $context.connection.lost_track(); }; @@ -636,19 +629,20 @@ type Handshake(rec: SSLRecord) = record { length : uint24; body : case msg_type of { - HELLO_REQUEST -> hello_request : HelloRequest(rec); - CLIENT_HELLO -> client_hello : ClientHello(rec); - SERVER_HELLO -> server_hello : ServerHello(rec); - CERTIFICATE -> certificate : Certificate(rec); - SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec); - CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec); - SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec); - CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec); - CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec); - FINISHED -> finished : Finished(rec); - CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient; - CERTIFICATE_STATUS -> certificate_status : bytestring &restofdata &transient; - default -> unknown_handshake : UnknownHandshake(this, rec.is_orig); + HELLO_REQUEST -> hello_request : HelloRequest(rec); + CLIENT_HELLO -> client_hello : ClientHello(rec); + SERVER_HELLO -> server_hello : ServerHello(rec); + SESSION_TICKET -> session_ticket : SessionTicketHandshake(rec); + CERTIFICATE -> certificate : Certificate(rec); + SERVER_KEY_EXCHANGE -> server_key_exchange : ServerKeyExchange(rec); + CERTIFICATE_REQUEST -> certificate_request : CertificateRequest(rec); + SERVER_HELLO_DONE -> server_hello_done : ServerHelloDone(rec); + CERTIFICATE_VERIFY -> certificate_verify : CertificateVerify(rec); + CLIENT_KEY_EXCHANGE -> client_key_exchange : ClientKeyExchange(rec); + FINISHED -> finished : Finished(rec); + CERTIFICATE_URL -> certificate_url : bytestring &restofdata &transient; + CERTIFICATE_STATUS -> certificate_status : bytestring &restofdata &transient; + default -> unknown_handshake : UnknownHandshake(this, rec.is_orig); } &length = to_int()(length); }; @@ -663,7 +657,7 @@ type UnknownRecord(rec: SSLRecord) = record { state_changed : bool = $context.connection.lost_track(); }; -type CiphertextRecord(rec: SSLRecord, is_orig: bool) = record { +type CiphertextRecord(rec: SSLRecord) = record { cont : bytestring &restofdata &transient; } &let { state_changed : bool = @@ -692,7 +686,7 @@ type CiphertextRecord(rec: SSLRecord, is_orig: bool) = record { ###################################################################### type SSLPDU(is_orig: bool) = record { - records : SSLRecord(is_orig)[] &until($element <= 0); + records : SSLRecord(is_orig)[] &transient &until($element <= 0); } &byteorder = bigendian; diff --git a/src/ssl.pac b/src/ssl.pac index 82dd0246c4..25aed7a66f 100644 --- a/src/ssl.pac +++ b/src/ssl.pac @@ -1,5 +1,3 @@ -# $Id:$ - # binpac file for SSL analyzer # split in three parts: diff --git a/src/strings.bif b/src/strings.bif index d13de8accb..ebe16529ea 100644 --- a/src/strings.bif +++ b/src/strings.bif @@ -1,6 +1,5 @@ -# $Id: strings.bif 6920 2009-10-03 20:47:25Z vern $ -# -# Definitions of Bro built-in functions related to strings. +##! Definitions of built-in functions related to string processing and +##! manipulation. %%{ // C segment @@ -12,6 +11,14 @@ using namespace std; %%} +## Concates all arguments into a single string. The function takes a variable +## number of arguments of type string and stiches them together. +## +## Returns: The concatenation of all (string) arguments. +## +## .. bro:see:: cat cat_sep cat_string_array cat_string_array_n +## fmt +## join_string_vec join_string_array function string_cat%(...%): string %{ int n = 0; @@ -75,18 +82,53 @@ BroString* cat_string_array_n(TableVal* tbl, int start, int end) } %%} +## Concatenates all elements in an array of strings. +## +## a: The :bro:type:`string_array` (``table[count] of string``). +## +## Returns: The concatenation of all elements in *a*. +## +## .. bro:see:: cat cat_sep string_cat cat_string_array_n +## fmt +## join_string_vec join_string_array function cat_string_array%(a: string_array%): string %{ TableVal* tbl = a->AsTableVal(); return new StringVal(cat_string_array_n(tbl, 1, a->AsTable()->Length())); %} +## Concatenates a specific range of elements in an array of strings. +## +## a: The :bro:type:`string_array` (``table[count] of string``). +## +## start: The array index of the first element of the range. +## +## end: The array index of the last element of the range. +## +## Returns: The concatenation of the range *[start, end]* in *a*. +## +## .. bro:see:: cat string_cat cat_string_array +## fmt +## join_string_vec join_string_array function cat_string_array_n%(a: string_array, start: count, end: count%): string %{ TableVal* tbl = a->AsTableVal(); return new StringVal(cat_string_array_n(tbl, start, end)); %} +## Joins all values in the given array of strings with a separator placed +## between each element. +## +## sep: The separator to place between each element. +## +## a: The :bro:type:`string_array` (``table[count] of string``). +## +## Returns: The concatenation of all elements in *a*, with *sep* placed +## between each element. +## +## .. bro:see:: cat cat_sep string_cat cat_string_array cat_string_array_n +## fmt +## join_string_vec function join_string_array%(sep: string, a: string_array%): string %{ vector vs; @@ -110,6 +152,45 @@ function join_string_array%(sep: string, a: string_array%): string return new StringVal(concatenate(vs)); %} +## Joins all values in the given vector of strings with a separator placed +## between each element. +## +## sep: The separator to place between each element. +## +## a: The :bro:type:`string_vec` (``vector of string``). +## +## Returns: The concatenation of all elements in *a*, with *sep* placed +## between each element. +## +## .. bro:see:: cat cat_sep string_cat cat_string_array cat_string_array_n +## fmt +## join_string_array +function join_string_vec%(vec: string_vec, sep: string%): string + %{ + ODesc d; + VectorVal *v = vec->AsVectorVal(); + + for ( unsigned i = 0; i < v->Size(); ++i ) + { + if ( i > 0 ) + d.Add(sep->CheckString(), 0); + + v->Lookup(i+1)->Describe(&d); + } + + BroString* s = new BroString(1, d.TakeBytes(), d.Len()); + s->SetUseFreeToDelete(true); + + return new StringVal(s); + %} + +## Sorts an array of strings. +## +## a: The :bro:type:`string_array` (``table[count] of string``). +## +## Returns: A sorted copy of *a*. +## +## .. bro:see:: sort function sort_string_array%(a: string_array%): string_array %{ TableVal* tbl = a->AsTableVal(); @@ -131,31 +212,29 @@ function sort_string_array%(a: string_array%): string_array } // sort(vs.begin(), vs.end(), Bstr_cmp); - TableVal* b = new TableVal(internal_type("string_array")->AsTableType()); + TableVal* b = new TableVal(string_array); vs_to_string_array(vs, b, 1, n); return b; %} - -function join_string_vec%(vec: string_vec, sep: string%): string - %{ - ODesc d; - VectorVal *v = vec->AsVectorVal(); - - for ( unsigned i = 0; i < v->Size(); ++i ) - { - if ( i > 0 ) - d.Add(sep->CheckString(), 0); - - v->Lookup(i+1)->Describe(&d); - } - - BroString* s = new BroString(1, d.TakeBytes(), d.Len()); - s->SetUseFreeToDelete(true); - - return new StringVal(s); - %} - +## Returns an edited version of a string that applies a special +## "backspace character" (usually ``\x08`` for backspace or ``\x7f`` for DEL). +## For ## example, ``edit("hello there", "e")`` returns ``"llo t"``. +## +## arg_s: The string to edit. +## +## arg_edit_char: A string of exactly one character that represents the +## "backspace character". If it is longer than one character Bro +## generates a run-time error and uses the first character in +## the string. +## +## Returns: An edited version of *arg_s* where *arg_edit_char* triggers the +## deletetion of the last character. +## +## .. bro:see:: clean +## to_string_literal +## escape_string +## strip function edit%(arg_s: string, arg_edit_char: string%): string %{ if ( arg_edit_char->Len() != 1 ) @@ -186,11 +265,28 @@ function edit%(arg_s: string, arg_edit_char: string%): string return new StringVal(new BroString(1, byte_vec(new_s), ind)); %} +## Returns the number of characters (bytes) in the given string. The +## length computation includes any embedded NULs, and also a trailing NUL, +## if any (which is why the function isn't called ``strlen``; to remind +## the user that Bro strings can include NULs). +## +## s: The string to compute the length for. +## +## Returns: The number of characters in *s*. function byte_len%(s: string%): count %{ return new Val(s->Len(), TYPE_COUNT); %} +## Get a substring of from a string, given a starting position length. +## +## s: The string to obtain a substring from. +## +## start: The starting position of the substring in *s* +## +## n: The number of characters to extract, beginning at *start*. +## +## Returns: A substring of *s* of length *n* from position *start*. function sub_bytes%(s: string, start: count, n: int%): string %{ if ( start > 0 ) @@ -218,7 +314,7 @@ static int match_prefix(int s_len, const char* s, int t_len, const char* t) Val* do_split(StringVal* str_val, RE_Matcher* re, TableVal* other_sep, int incl_sep, int max_num_sep) { - TableVal* a = new TableVal(internal_type("string_array")->AsTableType()); + TableVal* a = new TableVal(string_array); ListVal* other_strings = 0; if ( other_sep && other_sep->Size() > 0 ) @@ -370,42 +466,94 @@ Val* do_sub(StringVal* str_val, RE_Matcher* re, StringVal* repl, int do_all) } %%} -# Similar to split in awk. - +## Splits a string into an array of strings according to a pattern. +## +## str: The string to split. +## +## re: The pattern describing the element separator in *str*. +## +## Returns: An array of strings where each element corresponds to a substring +## in *str* separated by *re*. +## +## .. bro:see:: split1 split_all split_n str_split +## +## .. note:: The returned table starts at index 1. Note that conceptually the +## return value is meant to be a vector and this might change in the +## future. +## function split%(str: string, re: pattern%): string_array %{ return do_split(str, re, 0, 0, 0); %} -# split1(str, pattern, include_separator): table[count] of string -# -# Same as split, except that str is only split (if possible) at the -# earliest position and an array of two strings is returned. -# An array of one string is returned when str cannot be splitted. - +## Splits a string *once* into a a two-element array of strings according to a +## pattern. This function is the same as :bro:id:`split`, but * is only split +## once (if possible) at the earliest position and an array of two strings is +## returned. +## +## str: The string to split. +## +## re: The pattern describing the separator to split *str* in two pieces. +## +## Returns: An array of strings with two elements in which the first represents +## the substring in *str* up to the first occurence of *re*, and the +## second everything after *re*. An array of one string is returned +## when *s* cannot be split. +## +## .. bro:see:: split split_all split_n str_split function split1%(str: string, re: pattern%): string_array %{ return do_split(str, re, 0, 0, 1); %} -# Same as split, except that the array returned by split_all also -# includes parts of string that match the pattern in the array. - -# For example, split_all("a-b--cd", /(\-)+/) returns {"a", "-", "b", -# "--", "cd"}: odd-indexed elements do not match the pattern -# and even-indexed ones do. - +## Splits a string into an array of strings according to a pattern. This +## function is the same as :bro:id:`split`, except that the separators are +## returned as well. For example, ``split_all("a-b--cd", /(\-)+/)`` returns +## ``{"a", "-", "b", "--", "cd"}``: odd-indexed elements do not match the +## pattern and even-indexed ones do. +## +## str: The string to split. +## +## re: The pattern describing the element separator in *str*. +## +## Returns: An array of strings where each two successive elements correspond +## to a substring in *str* of the part not matching *re* (odd-indexed) +## and thei part that matches *re* (even-indexed). +## +## .. bro:see:: split split1 split_n str_split function split_all%(str: string, re: pattern%): string_array %{ return do_split(str, re, 0, 1, 0); %} +## Splits a string a given number of times into an array of strings according +## to a pattern. This function is similar to :bro:id:`split1` and +## :bro:id:`split_all`, but with customizable behavior with respect to +## including separators in the result and the number of times to split. +## +## str: The string to split. +## +## re: The pattern describing the element separator in *str*. +## +## incl_sep: A flag indicating whether to include the separator matches in the +## result (as in :bro:id:`split_all`). +## +## max_num_sep: The number of times to split *str*. +## +## Returns: An array of strings where, if *incl_sep* is true, each two +## successive elements correspond to a substring in *str* of the part +## not matching *re* (odd-indexed) and the part that matches *re* +## (even-indexed). +## +## .. bro:see:: split split1 split_all str_split function split_n%(str: string, re: pattern, incl_sep: bool, max_num_sep: count%): string_array %{ return do_split(str, re, 0, incl_sep, max_num_sep); %} +## Deprecated. Will be removed. +# Reason: the parameter ``other`` does nothing. function split_complete%(str: string, re: pattern, other: string_set, incl_sep: bool, max_num_sep: count%): string_array @@ -413,22 +561,65 @@ function split_complete%(str: string, return do_split(str, re, other->AsTableVal(), incl_sep, max_num_sep); %} +## Substitutes a given replacement string for the first occurrence of a pattern +## in a given string. +## +## str: The string to perform the substitution in. +## +## re: The pattern being replaced with *repl*. +## +## repl: The string that replacs *re*. +## +## Returns: A copy of *str* with the first occurence of *re* replaced with +## *repl*. +## +## .. bro:see:: gsub subst_string function sub%(str: string, re: pattern, repl: string%): string %{ return do_sub(str, re, repl, 0); %} +## Substitutes a given replacement string for the all occurrences of a pattern +## in a given string. +## +## str: The string to perform the substitution in. +## +## re: The pattern being replaced with *repl*. +## +## repl: The string that replacs *re*. +## +## Returns: A copy of *str* with all occurences of *re* replaced with *repl*. +## +## .. bro:see:: sub subst_string function gsub%(str: string, re: pattern, repl: string%): string %{ return do_sub(str, re, repl, 1); %} + +## Lexicographically compares two string. +## +## s1: The first string. +## +## s2: The second string. +## +## Returns: An integer greater than, equal to, or less than 0 according as +## *s1* is greater than, equal to, or less than *s2*. function strcmp%(s1: string, s2: string%): int %{ return new Val(Bstr_cmp(s1->AsString(), s2->AsString()), TYPE_INT); %} -# Returns 0 if $little is not found in $big. +## Locates the first occurrence of one string in another. +## +## big: The string to look in. +## +## little: The (smaller) string to find inside *big*. +## +## Returns: The location of *little* in *big* or 0 if *little* is not found in +## *big*. +## +## .. bro:see:: find_all find_last function strstr%(big: string, little: string%): count %{ return new Val( @@ -436,8 +627,17 @@ function strstr%(big: string, little: string%): count TYPE_COUNT); %} -# Substitute each (non-overlapping) appearance of $from in $s to $to, -# and return the resulting string. +## Substitutes each (non-overlapping) appearance of a string in another. +## +## s: The string in which to perform the substitution. +## +## from: The string to look for which is replaced with *to*. +## +## to: The string that replaces all occurrences of *from* in *s*. +## +## Returns: A copy of *s* where each occurrence of *from* is replaced with *to*. +## +## .. bro:see:: sub gsub function subst_string%(s: string, from: string, to: string%): string %{ const int little_len = from->Len(); @@ -480,12 +680,21 @@ function subst_string%(s: string, from: string, to: string%): string return new StringVal(concatenate(vs)); %} +## Replaces all uppercase letters in a string with their lowercase counterpart. +## +## str: The string to convert to lowercase letters. +## +## Returns: A copy of the given string with the uppercase letters (as indicated +## by ``isascii`` and \verb|isupper|``) folded to lowercase +## (via ``tolower``). +## +## .. bro:see:: to_upper is_ascii function to_lower%(str: string%): string %{ const u_char* s = str->Bytes(); int n = str->Len(); - char* lower_s = new char[n]; - char* ls = lower_s; + u_char* lower_s = new u_char[n + 1]; + u_char* ls = lower_s; for ( int i = 0; i < n; ++i) { @@ -495,15 +704,26 @@ function to_lower%(str: string%): string *ls++ = s[i]; } - return new StringVal(new BroString(1, byte_vec(lower_s), n)); + *ls++ = '\0'; + + return new StringVal(new BroString(1, lower_s, n)); %} +## Replaces all lowercase letters in a string with their uppercase counterpart. +## +## str: The string to convert to uppercase letters. +## +## Returns: A copy of the given string with the lowercase letters (as indicated +## by ``isascii`` and \verb|islower|``) folded to uppercase +## (via ``toupper``). +## +## .. bro:see:: to_lower is_ascii function to_upper%(str: string%): string %{ const u_char* s = str->Bytes(); int n = str->Len(); - char* upper_s = new char[n]; - char* us = upper_s; + u_char* upper_s = new u_char[n + 1]; + u_char* us = upper_s; for ( int i = 0; i < n; ++i) { @@ -513,21 +733,59 @@ function to_upper%(str: string%): string *us++ = s[i]; } - return new StringVal(new BroString(1, byte_vec(upper_s), n)); + *us++ = '\0'; + + return new StringVal(new BroString(1, upper_s, n)); %} +## Replaces non-printable characters in a string with escaped sequences. The +## mappings are: +## +## - ``NUL`` to ``\0`` +## - ``DEL`` to ``^?`` +## - values <= 26 to ``^[A-Z]`` +## - values not in *[32, 126]** to ``%XX`` +## +## If the string does not yet have a trailing NUL, one is added. +## +## str: The string to escape. +## +## Returns: The escaped string. +## +## .. bro:see:: to_string_literal escape_string function clean%(str: string%): string %{ char* s = str->AsString()->Render(); return new StringVal(new BroString(1, byte_vec(s), strlen(s))); %} +## Replaces non-printable characters in a string with escaped sequences. The +## mappings are: +## +## - ``NUL`` to ``\0`` +## - ``DEL`` to ``^?`` +## - values <= 26 to ``^[A-Z]`` +## - values not in *[32, 126]** to ``%XX`` +## +## str: The string to escape. +## +## Returns: The escaped string. +## +## .. bro:see:: clean escape_string function to_string_literal%(str: string%): string %{ char* s = str->AsString()->Render(BroString::BRO_STRING_LITERAL); return new StringVal(new BroString(1, byte_vec(s), strlen(s))); %} +## Determines whether a given string contains only ASCII characters. +## +## str: The string to examine. +## +## Returns: False if any byte value of *str* is greater than 127, and true +## otherwise. +## +## .. bro:see:: to_upper to_lower function is_ascii%(str: string%): bool %{ int n = str->Len(); @@ -540,7 +798,14 @@ function is_ascii%(str: string%): bool return new Val(1, TYPE_BOOL); %} -# Make printable version of string. +## Creates a printable version of a string. This function is the same as +## :bro:id:`clean` except that non-printable characters are removed. +## +## s: The string to escape. +## +## Returns: The escaped string. +## +## .. bro:see:: clean to_string_literal function escape_string%(s: string%): string %{ char* escstr = s->AsString()->Render(); @@ -549,7 +814,12 @@ function escape_string%(s: string%): string return val; %} -# Returns an ASCII hexadecimal representation of a string. +## Returns an ASCII hexadecimal representation of a string. +## +## s: The string to convert to hex. +## +## Returns: A copy of *s* where each byte is replaced with the corresponding +## hex nibble. function string_to_ascii_hex%(s: string%): string %{ char* x = new char[s->Len() * 2 + 1]; @@ -561,8 +831,15 @@ function string_to_ascii_hex%(s: string%): string return new StringVal(new BroString(1, (u_char*) x, s->Len() * 2)); %} -function str_smith_waterman%(s1: string, s2: string, params: sw_params%) -: sw_substring_vec +## Uses the Smith Waterman algorithm to find similar/overlapping substrings. +## See `Wikipedia `_. +## +## s1: The first string. +## +## s2: The second string. +## +## Returns: The result of the Smit Waterman algorithm calculation. +function str_smith_waterman%(s1: string, s2: string, params: sw_params%) : sw_substring_vec %{ SWParams sw_params(params->AsRecordVal()->Lookup(0)->AsCount(), SWVariant(params->AsRecordVal()->Lookup(1)->AsCount())); @@ -576,6 +853,16 @@ function str_smith_waterman%(s1: string, s2: string, params: sw_params%) return result; %} +## Splits a string into substrings with the help of an index vector of cutting +## points. +## +## s: The string to split. +## +## idx: The index vector (``vector of count``) with the cutting points. +## +## Returns: A vector of strings. +## +## .. bro:see:: split split1 split_all split_n function str_split%(s: string, idx: index_vec%): string_vec %{ vector* idx_v = idx->AsVector(); @@ -604,6 +891,13 @@ function str_split%(s: string, idx: index_vec%): string_vec return result_v; %} +## Strips whitespace at both ends of a string. +## +## str: The string to strip the whitespace from. +## +## Returns: A copy of *str* with leading and trailing whitespace removed. +## +## .. bro:see:: sub gsub function strip%(str: string%): string %{ const u_char* s = str->Bytes(); @@ -627,6 +921,14 @@ function strip%(str: string%): string return new StringVal(new BroString(sp, (e - sp + 1), 1)); %} +## Generates a string of a given size and fills it with repetitions of a source +## string. +## +## len: The length of the output string. +## +## source: The string to concatenate repeatedly until *len* has been reached. +## +## Returns: A string of length *len* filled with *source*. function string_fill%(len: int, source: string%): string %{ const u_char* src = source->Bytes(); @@ -641,10 +943,15 @@ function string_fill%(len: int, source: string%): string return new StringVal(new BroString(1, byte_vec(dst), len)); %} -# Takes a string and escapes characters that would allow execution of commands -# at the shell level. Must be used before including strings in system() or -# similar calls. -# +## Takes a string and escapes characters that would allow execution of +## commands at the shell level. Must be used before including strings in +## :bro:id:`system` or similar calls. +## +## source: The string to escape. +## +## Returns: A shell-escaped version of *source*. +## +## .. bro:see:: system function str_shell_escape%(source: string%): string %{ unsigned j = 0; @@ -673,11 +980,18 @@ function str_shell_escape%(source: string%): string return new StringVal(new BroString(1, dst, j)); %} -# Returns all occurrences of the given pattern in the given string (an empty -# empty set if none). +## Finds all occurrences of a pattern in a string. +## +## str: The string to inspect. +## +## re: The pattern to look for in *str*. +## +## Returns: The set of strings in *str* that match *re*, or the empty set. +## +## .. bro:see: find_last strstr function find_all%(str: string, re: pattern%) : string_set %{ - TableVal* a = new TableVal(internal_type("string_set")->AsTableType()); + TableVal* a = new TableVal(string_set); const u_char* s = str->Bytes(); const u_char* e = s + str->Len(); @@ -695,11 +1009,18 @@ function find_all%(str: string, re: pattern%) : string_set return a; %} -# Returns the last occurrence of the given pattern in the given string. -# If not found, returns an empty string. Note that this function returns -# the match that starts at the largest index in the string, which is -# not necessarily the longest match. For example, a pattern of /.*/ -# will return the final character in the string. +## Finds the last occurrence of a pattern in a string. This function returns +## the match that starts at the largest index in the string, which is not +## necessarily the longest match. For example, a pattern of ``/.*/`` will +## return the final character in the string. +## +## str: The string to inspect. +## +## re: The pattern to look for in *str*. +## +## Returns: The last string in *str* that matches *re*, or the empty string. +## +## .. bro:see: find_all strstr function find_last%(str: string, re: pattern%) : string %{ const u_char* s = str->Bytes(); @@ -715,10 +1036,16 @@ function find_last%(str: string, re: pattern%) : string return new StringVal(""); %} -# Returns a hex dump for given input data. The hex dump renders -# 16 bytes per line, with hex on the left and ASCII (where printable) -# on the right. Based on Netdude's hex editor code. -# +## Returns a hex dump for given input data. The hex dump renders 16 bytes per +## line, with hex on the left and ASCII (where printable) +## on the right. +## +## data_str: The string to dump in hex format. +## +## .. bro:see:: string_to_ascii_hex bytestring_to_hexstr +## +## .. note:: Based on Netdude's hex editor code. +## function hexdump%(data_str: string%) : string %{ diff --git a/src/threading/BasicThread.cc b/src/threading/BasicThread.cc new file mode 100644 index 0000000000..e590b13434 --- /dev/null +++ b/src/threading/BasicThread.cc @@ -0,0 +1,174 @@ + +#include +#include + +#include "config.h" +#include "BasicThread.h" +#include "Manager.h" + +#ifdef HAVE_LINUX +#include +#endif + +using namespace threading; + +uint64_t BasicThread::thread_counter = 0; + +BasicThread::BasicThread() + { + started = false; + terminating = false; + pthread = 0; + + buf_len = 2048; + buf = (char*) malloc(buf_len); + + name = Fmt("thread-%d", ++thread_counter); + + thread_mgr->AddThread(this); + } + +BasicThread::~BasicThread() + { + if ( buf ) + free(buf); + } + +void BasicThread::SetName(const string& arg_name) + { + // Slight race condition here with reader threads, but shouldn't matter. + name = arg_name; + } + +void BasicThread::SetOSName(const string& name) + { +#ifdef HAVE_LINUX + prctl(PR_SET_NAME, name.c_str(), 0, 0, 0); +#endif + +#ifdef __APPLE__ + pthread_setname_np(name.c_str()); +#endif + +#ifdef FREEBSD + pthread_set_name_np(pthread_self(), name, name.c_str()); +#endif + } + +const char* BasicThread::Fmt(const char* format, ...) + { + va_list al; + va_start(al, format); + int n = safe_vsnprintf(buf, buf_len, format, al); + va_end(al); + + if ( (unsigned int) n >= buf_len ) + { // Not enough room, grow the buffer. + int tmp_len = n + 32; + char* tmp = (char*) malloc(tmp_len); + + // Is it portable to restart? + va_start(al, format); + n = safe_vsnprintf(tmp, tmp_len, format, al); + va_end(al); + + free(tmp); + } + + return buf; + } + +void BasicThread::Start() + { + if ( started ) + return; + + if ( pthread_mutex_init(&terminate, 0) != 0 ) + reporter->FatalError("Cannot create terminate mutex for thread %s", name.c_str()); + + // We use this like a binary semaphore and acquire it immediately. + if ( pthread_mutex_lock(&terminate) != 0 ) + reporter->FatalError("Cannot aquire terminate mutex for thread %s", name.c_str()); + + if ( pthread_create(&pthread, 0, BasicThread::launcher, this) != 0 ) + reporter->FatalError("Cannot create thread %s", name.c_str()); + + DBG_LOG(DBG_THREADING, "Started thread %s", name.c_str()); + + started = true; + + OnStart(); + } + +void BasicThread::Stop() + { + if ( ! started ) + return; + + if ( terminating ) + return; + + DBG_LOG(DBG_THREADING, "Signaling thread %s to terminate ...", name.c_str()); + + // Signal that it's ok for the thread to exit now by unlocking the + // mutex. + if ( pthread_mutex_unlock(&terminate) != 0 ) + reporter->FatalError("Failure flagging terminate condition for thread %s", name.c_str()); + + terminating = true; + + OnStop(); + } + +void BasicThread::Join() + { + if ( ! started ) + return; + + if ( ! terminating ) + Stop(); + + DBG_LOG(DBG_THREADING, "Joining thread %s ...", name.c_str()); + + if ( pthread_join(pthread, 0) != 0 ) + reporter->FatalError("Failure joining thread %s", name.c_str()); + + pthread_mutex_destroy(&terminate); + + DBG_LOG(DBG_THREADING, "Done with thread %s", name.c_str()); + + pthread = 0; + } + +void BasicThread::Kill() + { + if ( ! (started && pthread) ) + return; + + // I believe this is safe to call from a signal handler ... Not error + // checking so that killing doesn't bail out if we have already + // terminated. + pthread_kill(pthread, SIGKILL); + } + +void* BasicThread::launcher(void *arg) + { + BasicThread* thread = (BasicThread *)arg; + + // Block signals in thread. We handle signals only in the main + // process. + sigset_t mask_set; + sigfillset(&mask_set); + int res = pthread_sigmask(SIG_BLOCK, &mask_set, 0); + assert(res == 0); // + + // Run thread's main function. + thread->Run(); + + // Wait until somebody actually wants us to terminate. + if ( pthread_mutex_lock(&thread->terminate) != 0 ) + reporter->FatalError("Failure acquiring terminate mutex at end of thread %s", thread->Name().c_str()); + + return 0; + } + diff --git a/src/threading/BasicThread.h b/src/threading/BasicThread.h new file mode 100644 index 0000000000..cc87ae03bc --- /dev/null +++ b/src/threading/BasicThread.h @@ -0,0 +1,170 @@ + +#ifndef THREADING_BASICTHREAD_H +#define THREADING_BASICTHREAD_H + +#include +#include + +#include "Queue.h" +#include "util.h" + +using namespace std; + +namespace threading { + +class Manager; + +/** + * Base class for all threads. + * + * This class encapsulates all the OS-level thread handling. All thread + * instances are automatically added to the threading::Manager for management. The + * manager also takes care of deleting them (which must not be done + * manually). + */ +class BasicThread +{ +public: + /** + * Creates a new thread object. Instantiating the object does however + * not yet start the actual OS thread, that requires calling Start(). + * + * Only Bro's main thread may create new thread instances. + * + * @param name A descriptive name for thread the thread. This may + * show up in messages to the user. + */ + BasicThread(); + + /** + * Returns a descriptive name for the thread. If not set via + * SetName(). If not set, a default name is choosen automatically. + * + * This method is safe to call from any thread. + */ + const string& Name() const { return name; } + + /** + * Sets a descriptive name for the thread. This should be a string + * that's useful in output presented to the user and uniquely + * identifies the thread. + * + * This method must be called only from the thread itself. + */ + void SetName(const string& name); + + /** + * Set the name shown by the OS as the thread's description. Not + * supported on all OSs. + */ + void SetOSName(const string& name); + + /** + * Starts the thread. Calling this methods will spawn a new OS thread + * executing Run(). Note that one can't restart a thread after a + * Stop(), doing so will be ignored. + * + * Only Bro's main thread must call this method. + */ + void Start(); + + /** + * Signals the thread to stop. The method lets Terminating() now + * return true. It does however not force the thread to terminate. + * It's up to the Run() method to to query Terminating() and exit + * eventually. + * + * Calling this method has no effect if Start() hasn't been executed + * yet. + * + * Only Bro's main thread must call this method. + */ + void Stop(); + + /** + * Returns true if Stop() has been called. + * + * This method is safe to call from any thread. + */ + bool Terminating() const { return terminating; } + + /** + * A version of fmt() that the thread can safely use. + * + * This is safe to call from Run() but must not be used from any + * other thread than the current one. + */ + const char* Fmt(const char* format, ...); + +protected: + friend class Manager; + + /** + * Entry point for the thread. This must be overridden by derived + * classes and will execute in a separate thread once Start() is + * called. The thread will not terminate before this method finishes. + * An implementation should regularly check Terminating() to see if + * exiting has been requested. + */ + virtual void Run() = 0; + + /** + * Executed with Start(). This is a hook into starting the thread. It + * will be called from Bro's main thread after the OS thread has been + * started. + */ + virtual void OnStart() {} + + /** + * Executed with Stop(). This is a hook into stopping the thread. It + * will be called from Bro's main thread after the thread has been + * signaled to stop. + */ + virtual void OnStop() {} + + /** + * Destructor. This will be called by the manager. + * + * Only Bro's main thread may delete thread instances. + * + */ + virtual ~BasicThread(); + + /** + * Waits until the thread's Run() method has finished and then joins + * it. This is called from the threading::Manager. + */ + void Join(); + + /** + * Kills the thread immediately. One still needs to call Join() + * afterwards. + * + * This is called from the threading::Manager and safe to execute + * during a signal handler. + */ + void Kill(); + +private: + // pthread entry function. + static void* launcher(void *arg); + + string name; + pthread_t pthread; + bool started; // Set to to true once running. + bool terminating; // Set to to true to signal termination. + + // Used as a semaphore to tell the pthread thread when it may + // terminate. + pthread_mutex_t terminate; + + // For implementing Fmt(). + char* buf; + unsigned int buf_len; + + static uint64_t thread_counter; +}; + +} + +#endif diff --git a/src/threading/Manager.cc b/src/threading/Manager.cc new file mode 100644 index 0000000000..abdbf849b5 --- /dev/null +++ b/src/threading/Manager.cc @@ -0,0 +1,147 @@ + +#include "Manager.h" + +using namespace threading; + +Manager::Manager() + { + DBG_LOG(DBG_THREADING, "Creating thread manager ..."); + + did_process = true; + next_beat = 0; + terminating = false; + idle = true; + } + +Manager::~Manager() + { + if ( all_threads.size() ) + Terminate(); + } + +void Manager::Terminate() + { + DBG_LOG(DBG_THREADING, "Terminating thread manager ..."); + + terminating = true; + + // First process remaining thread output for the message threads. + do Process(); while ( did_process ); + + // Signal all to stop. + for ( all_thread_list::iterator i = all_threads.begin(); i != all_threads.end(); i++ ) + (*i)->Stop(); + + // Then join them all. + for ( all_thread_list::iterator i = all_threads.begin(); i != all_threads.end(); i++ ) + { + (*i)->Join(); + delete *i; + } + + all_threads.clear(); + msg_threads.clear(); + + idle = true; + closed = true; + terminating = false; + } + +void Manager::KillThreads() + { + DBG_LOG(DBG_THREADING, "Killing threads ..."); + + for ( all_thread_list::iterator i = all_threads.begin(); i != all_threads.end(); i++ ) + (*i)->Kill(); + } + +void Manager::AddThread(BasicThread* thread) + { + DBG_LOG(DBG_THREADING, "Adding thread %s ...", thread->Name().c_str()); + all_threads.push_back(thread); + idle = false; + } + +void Manager::AddMsgThread(MsgThread* thread) + { + DBG_LOG(DBG_THREADING, "%s is a MsgThread ...", thread->Name().c_str()); + msg_threads.push_back(thread); + } + +void Manager::GetFds(int* read, int* write, int* except) + { + } + +double Manager::NextTimestamp(double* network_time) + { +// fprintf(stderr, "N %.6f %.6f did_process=%d next_next=%.6f\n", ::network_time, timer_mgr->Time(), (int)did_process, next_beat); + + if ( ::network_time && (did_process || ::network_time > next_beat || ! next_beat) ) + // If we had something to process last time (or out heartbeat + // is due or not set yet), we want to check for more asap. + return timer_mgr->Time(); + + return -1.0; + } + +void Manager::Process() + { + bool do_beat = false; + + if ( network_time && (network_time > next_beat || ! next_beat) ) + { + do_beat = true; + next_beat = ::network_time + HEART_BEAT_INTERVAL; + } + + did_process = false; + + for ( msg_thread_list::iterator i = msg_threads.begin(); i != msg_threads.end(); i++ ) + { + MsgThread* t = *i; + + if ( do_beat ) + t->Heartbeat(); + + while ( t->HasOut() ) + { + Message* msg = t->RetrieveOut(); + + if ( msg->Process() ) + { + if ( network_time ) + did_process = true; + } + + else + { + string s = msg->Name() + " failed, terminating thread"; + reporter->Error("%s", s.c_str()); + t->Stop(); + } + + delete msg; + } + } + +// fprintf(stderr, "P %.6f %.6f do_beat=%d did_process=%d next_next=%.6f\n", network_time, timer_mgr->Time(), do_beat, (int)did_process, next_beat); + } + +const threading::Manager::msg_stats_list& threading::Manager::GetMsgThreadStats() + { + stats.clear(); + + for ( msg_thread_list::iterator i = msg_threads.begin(); i != msg_threads.end(); i++ ) + { + MsgThread* t = *i; + + MsgThread::Stats s; + t->GetStats(&s); + + stats.push_back(std::make_pair(t->Name(),s)); + } + + return stats; + } + + diff --git a/src/threading/Manager.h b/src/threading/Manager.h new file mode 100644 index 0000000000..7d9ba766d4 --- /dev/null +++ b/src/threading/Manager.h @@ -0,0 +1,146 @@ + +#ifndef THREADING_MANAGER_H +#define THREADING_MANAGER_H + +#include + +#include "IOSource.h" + +#include "BasicThread.h" +#include "MsgThread.h" + +namespace threading { + +/** + * The thread manager coordinates all child threads. Once a BasicThread is + * instantitated, it gets addedd to the manager, which will delete it later + * once it has terminated. + * + * In addition to basic threads, the manager also provides additional + * functionality specific to MsgThread instances. In particular, it polls + * their outgoing message queue on a regular basis and feeds data sent into + * the rest of Bro. It also triggers the regular heartbeats. + */ +class Manager : public IOSource +{ +public: + /** + * Constructor. Only a single instance of the manager must be + * created. + */ + Manager(); + + /** + * Destructir. + */ + ~Manager(); + + /** + * Terminates the manager's processor. The method signals all threads + * to terminates and wait for them to do so. It then joins them and + * returns to the caller. Afterwards, no more thread instances may be + * created. + */ + void Terminate(); + + /** + * Returns True if we are currently in Terminate() waiting for + * threads to exit. + */ + bool Terminating() const { return terminating; } + + /** + * Immediately kills all child threads. It does however not yet join + * them, one still needs to call Terminate() for that. + * + * This method is safe to call from a signal handler, and can in fact + * be called while Terminate() is already in progress. + */ + void KillThreads(); + + typedef std::list > msg_stats_list; + + /** + * Returns statistics from all current MsgThread instances. + * + * @return A list of statistics, with one entry for each MsgThread. + * Each entry is a tuple of thread name and statistics. The list + * reference remains valid until the next call to this method (or + * termination of the manager). + */ + const msg_stats_list& GetMsgThreadStats(); + + /** + * Returns the number of currently active threads. This counts all + * threads that are not yet joined, includingt any potentially in + * Terminating() state. + */ + int NumThreads() const { return all_threads.size(); } + +protected: + friend class BasicThread; + friend class MsgThread; + + /** + * Registers a new basic thread with the manager. This is + * automatically called by the thread's constructor. + * + * @param thread The thread. + */ + void AddThread(BasicThread* thread); + + /** + * Registers a new message thread with the manager. This is + * automatically called by the thread's constructor. This must be + * called \a in \a addition to AddThread(BasicThread* thread). The + * MsgThread constructor makes sure to do so. + * + * @param thread The thread. + */ + void AddMsgThread(MsgThread* thread); + + /** + * Part of the IOSource interface. + */ + virtual void GetFds(int* read, int* write, int* except); + + /** + * Part of the IOSource interface. + */ + virtual double NextTimestamp(double* network_time); + + /** + * Part of the IOSource interface. + */ + virtual void Process(); + + /** + * Part of the IOSource interface. + */ + virtual const char* Tag() { return "threading::Manager"; } + +private: + static const int HEART_BEAT_INTERVAL = 1; + + typedef std::list all_thread_list; + all_thread_list all_threads; + + typedef std::list msg_thread_list; + msg_thread_list msg_threads; + + bool did_process; // True if the last Process() found some work to do. + double next_beat; // Timestamp when the next heartbeat will be sent. + bool terminating; // True if we are in Terminate(). + + msg_stats_list stats; +}; + +} + +/** + * A singleton instance of the thread manager. All methods must only be + * called from Bro's main thread. + */ +extern threading::Manager* thread_mgr; + +#endif diff --git a/src/threading/MsgThread.cc b/src/threading/MsgThread.cc new file mode 100644 index 0000000000..ddcd3df1dd --- /dev/null +++ b/src/threading/MsgThread.cc @@ -0,0 +1,289 @@ + +#include "DebugLogger.h" + +#include "MsgThread.h" +#include "Manager.h" + +using namespace threading; + +namespace threading { + +////// Messages. + +// Signals child thread to terminate. This is actually a no-op; its only +// purpose is unblock the current read operation so that the child's Run() +// methods can check the termination status. +class TerminateMessage : public InputMessage +{ +public: + TerminateMessage(MsgThread* thread) : InputMessage("Terminate", thread) { } + + virtual bool Process() { return true; } +}; + +/// Sends a heartbeat to the child thread. +class HeartbeatMessage : public InputMessage +{ +public: + HeartbeatMessage(MsgThread* thread, double arg_network_time, double arg_current_time) + : InputMessage("Heartbeat", thread) + { network_time = arg_network_time; current_time = arg_current_time; } + + virtual bool Process() { return Object()->DoHeartbeat(network_time, current_time); } + +private: + double network_time; + double current_time; +}; + +// A message from the child to be passed on to the Reporter. +class ReporterMessage : public OutputMessage +{ +public: + enum Type { + INFO, WARNING, ERROR, FATAL_ERROR, FATAL_ERROR_WITH_CORE, + INTERNAL_WARNING, INTERNAL_ERROR + }; + + ReporterMessage(Type arg_type, MsgThread* thread, const string& arg_msg) + : OutputMessage("ReporterMessage", thread) + { type = arg_type; msg = arg_msg; } + + virtual bool Process(); + +private: + string msg; + Type type; +}; + +#ifdef DEBUG +// A debug message from the child to be passed on to the DebugLogger. +class DebugMessage : public OutputMessage +{ +public: + DebugMessage(DebugStream arg_stream, MsgThread* thread, const string& arg_msg) + : OutputMessage("DebugMessage", thread) + { stream = arg_stream; msg = arg_msg; } + + virtual bool Process() + { + string s = Object()->Name() + ": " + msg; + debug_logger.Log(stream, "%s", s.c_str()); + return true; + } +private: + string msg; + DebugStream stream; +}; +#endif + +} + +////// Methods. + +Message::~Message() + { + } + +bool ReporterMessage::Process() + { + string s = Object()->Name() + ": " + msg; + const char* cmsg = s.c_str(); + + switch ( type ) { + + case INFO: + reporter->Info("%s", cmsg); + break; + + case WARNING: + reporter->Warning("%s", cmsg); + break; + + case ERROR: + reporter->Error("%s", cmsg); + break; + + case FATAL_ERROR: + reporter->FatalError("%s", cmsg); + break; + + case FATAL_ERROR_WITH_CORE: + reporter->FatalErrorWithCore("%s", cmsg); + break; + + case INTERNAL_WARNING: + reporter->InternalWarning("%s", cmsg); + break; + + case INTERNAL_ERROR : + reporter->InternalError("%s", cmsg); + break; + + default: + reporter->InternalError("unknown ReporterMessage type %d", type); + } + + return true; + } + +MsgThread::MsgThread() : BasicThread() + { + cnt_sent_in = cnt_sent_out = 0; + thread_mgr->AddMsgThread(this); + } + +void MsgThread::OnStop() + { + // This is to unblock the current queue read operation. + SendIn(new TerminateMessage(this), true); + } + +void MsgThread::Heartbeat() + { + SendIn(new HeartbeatMessage(this, network_time, current_time())); + } + +bool MsgThread::DoHeartbeat(double network_time, double current_time) + { + string n = Name(); + + n = Fmt("bro: %s (%" PRIu64 "/%" PRIu64 ")", n.c_str(), + cnt_sent_in - queue_in.Size(), + cnt_sent_out - queue_out.Size()); + + SetOSName(n.c_str()); + + return true; + } + +void MsgThread::Info(const char* msg) + { + SendOut(new ReporterMessage(ReporterMessage::INFO, this, msg)); + } + +void MsgThread::Warning(const char* msg) + { + SendOut(new ReporterMessage(ReporterMessage::WARNING, this, msg)); + } + +void MsgThread::Error(const char* msg) + { + SendOut(new ReporterMessage(ReporterMessage::ERROR, this, msg)); + } + +void MsgThread::FatalError(const char* msg) + { + SendOut(new ReporterMessage(ReporterMessage::FATAL_ERROR, this, msg)); + } + +void MsgThread::FatalErrorWithCore(const char* msg) + { + SendOut(new ReporterMessage(ReporterMessage::FATAL_ERROR_WITH_CORE, this, msg)); + } + +void MsgThread::InternalWarning(const char* msg) + { + SendOut(new ReporterMessage(ReporterMessage::INTERNAL_WARNING, this, msg)); + } + +void MsgThread::InternalError(const char* msg) + { + SendOut(new ReporterMessage(ReporterMessage::INTERNAL_ERROR, this, msg)); + } + +#ifdef DEBUG + +void MsgThread::Debug(DebugStream stream, const char* msg) + { + SendOut(new DebugMessage(stream, this, msg)); + } + +#endif + +void MsgThread::SendIn(BasicInputMessage* msg, bool force) + { + if ( Terminating() && ! force ) + { + delete msg; + return; + } + + DBG_LOG(DBG_THREADING, "Sending '%s' to %s ...", msg->Name().c_str(), Name().c_str()); + + queue_in.Put(msg); + ++cnt_sent_in; + } + + +void MsgThread::SendOut(BasicOutputMessage* msg, bool force) + { + if ( Terminating() && ! force ) + { + delete msg; + return; + } + + queue_out.Put(msg); + + ++cnt_sent_out; + } + +BasicOutputMessage* MsgThread::RetrieveOut() + { + BasicOutputMessage* msg = queue_out.Get(); + assert(msg); + + DBG_LOG(DBG_THREADING, "Retrieved '%s' from %s", msg->Name().c_str(), Name().c_str()); + + return msg; + } + +BasicInputMessage* MsgThread::RetrieveIn() + { + BasicInputMessage* msg = queue_in.Get(); + assert(msg); + +#ifdef DEBUG + string s = Fmt("Retrieved '%s' in %s", msg->Name().c_str(), Name().c_str()); + Debug(DBG_THREADING, s.c_str()); +#endif + + return msg; + } + +void MsgThread::Run() + { + while ( true ) + { + // When requested to terminate, we only do so when + // all input has been processed. + if ( Terminating() && ! queue_in.Ready() ) + break; + + BasicInputMessage* msg = RetrieveIn(); + + bool result = msg->Process(); + + if ( ! result ) + { + string s = msg->Name() + " failed, terminating thread"; + Error(s.c_str()); + Stop(); + break; + } + + delete msg; + } + } + +void MsgThread::GetStats(Stats* stats) + { + stats->sent_in = cnt_sent_in; + stats->sent_out = cnt_sent_out; + stats->pending_in = queue_in.Size(); + stats->pending_out = queue_out.Size(); + queue_in.GetStats(&stats->queue_in_stats); + queue_out.GetStats(&stats->queue_out_stats); + } + diff --git a/src/threading/MsgThread.h b/src/threading/MsgThread.h new file mode 100644 index 0000000000..5ac1c0f780 --- /dev/null +++ b/src/threading/MsgThread.h @@ -0,0 +1,402 @@ + +#ifndef THREADING_MSGTHREAD_H +#define THREADING_MSGTHREAD_H + +#include + +#include "DebugLogger.h" + +#include "BasicThread.h" +#include "Queue.h" + +namespace threading { + +class BasicInputMessage; +class BasicOutputMessage; +class HeartbeatMessage; + +/** + * A specialized thread that provides bi-directional message passing between + * Bro's main thread and the child thread. Messages are instances of + * BasicInputMessage and BasicOutputMessage for message sent \a to the child + * thread and received \a from the child thread, respectively. + * + * The thread's Run() method implements main loop that processes incoming + * messages until Terminating() indicates that execution should stop. Once + * that happens, the thread stops accepting any new messages, finishes + * processes all remaining ones still in the queue, and then exits. + */ +class MsgThread : public BasicThread +{ +public: + /** + * Constructor. It automatically registers the thread with the + * threading::Manager. + * + * Only Bro's main thread may instantiate a new thread. + */ + MsgThread(); + + /** + * Sends a message to the child thread. The message will be proceesed + * once the thread has retrieved it from its incoming queue. + * + * Only the main thread may call this method. + * + * @param msg The message. + */ + void SendIn(BasicInputMessage* msg) { return SendIn(msg, false); } + + /** + * Sends a message from the child thread to the main thread. + * + * Only the child thread may call this method. + * + * @param msg The mesasge. + */ + void SendOut(BasicOutputMessage* msg) { return SendOut(msg, false); } + + /** + * Reports an informational message from the child thread. The main + * thread will pass this to the Reporter once received. + * + * Only the child thread may call this method. + * + * @param msg The message. It will be prefixed with the thread's name. + */ + void Info(const char* msg); + + /** + * Reports a warning from the child thread that may indicate a + * problem. The main thread will pass this to the Reporter once + * received. + * + * Only the child thread may call this method. + * + * @param msg The message. It will be prefixed with the thread's name. + */ + void Warning(const char* msg); + + /** + * Reports a non-fatal error from the child thread. The main thread + * will pass this to the Reporter once received. Processing proceeds + * normally after the error has been reported. + * + * Only the child thread may call this method. + * + * @param msg The message. It will be prefixed with the thread's name. + */ + void Error(const char* msg); + + /** + * Reports a fatal error from the child thread. The main thread will + * pass this to the Reporter once received. Bro will terminate after + * the message has been reported. + * + * Only the child thread may call this method. + * + * @param msg The message. It will be prefixed with the thread's name. + */ + void FatalError(const char* msg); + + /** + * Reports a fatal error from the child thread. The main thread will + * pass this to the Reporter once received. Bro will terminate with a + * core dump after the message has been reported. + * + * Only the child thread may call this method. + * + * @param msg The message. It will be prefixed with the thread's name. + */ + void FatalErrorWithCore(const char* msg); + + /** + * Reports a potential internal problem from the child thread. The + * main thread will pass this to the Reporter once received. Bro will + * continue normally. + * + * Only the child thread may call this method. + * + * @param msg The message. It will be prefixed with the thread's name. + */ + void InternalWarning(const char* msg); + + /** + * Reports an internal program error from the child thread. The main + * thread will pass this to the Reporter once received. Bro will + * terminate with a core dump after the message has been reported. + * + * Only the child thread may call this method. + * + * @param msg The message. It will be prefixed with the thread's name. + */ + void InternalError(const char* msg); + +#ifdef DEBUG + /** + * Records a debug message for the given stream from the child + * thread. The main thread will pass this to the DebugLogger once + * received. + * + * Only the child thread may call this method. + * + * @param msg The message. It will be prefixed with the thread's name. + */ + void Debug(DebugStream stream, const char* msg); +#endif + + /** + * Statistics about inter-thread communication. + */ + struct Stats + { + uint64_t sent_in; //! Number of messages sent to the child thread. + uint64_t sent_out; //! Number of messages sent from the child thread to the main thread + uint64_t pending_in; //! Number of messages sent to the child but not yet processed. + uint64_t pending_out; //! Number of messages sent from the child but not yet processed by the main thread. + + /// Statistics from our queues. + Queue::Stats queue_in_stats; + Queue::Stats queue_out_stats; + }; + + /** + * Returns statistics about the inter-thread communication. + * + * @param stats A pointer to a structure that will be filled with + * current numbers. + */ + void GetStats(Stats* stats); + +protected: + friend class Manager; + friend class HeartbeatMessage; + + /** + * Pops a message sent by the child from the child-to-main queue. + * + * This is method is called regularly by the threading::Manager. + * + * @return The message, wth ownership passed to caller. Returns null + * if the queue is empty. + */ + BasicOutputMessage* RetrieveOut(); + + /** + * Triggers a heartbeat message being sent to the client thread. + * + * This is method is called regularly by the threading::Manager. + * + * Can be overriden in derived classed to hook into the heart beat, + * but must call the parent implementation. Note that this method is + * always called by the main thread and must not access data of the + * child thread directly. See DoHeartbeat() if you want to do + * something on the child-side. + */ + virtual void Heartbeat(); + + /** + * Overriden from BasicThread. + * + */ + virtual void Run(); + virtual void OnStop(); + + /** + * Regulatly triggered for execution in the child thread. + * + * When overriding, one must call the parent class' implementation. + * + * network_time: The network_time when the heartbeat was trigger by + * the main thread. + * + * current_time: Wall clock when the heartbeat was trigger by the + * main thread. + */ + virtual bool DoHeartbeat(double network_time, double current_time); + +private: + /** + * Pops a message sent by the main thread from the main-to-chold + * queue. + * + * Must only be called by the child thread. + * + * @return The message, wth ownership passed to caller. Returns null + * if the queue is empty. + */ + BasicInputMessage* RetrieveIn(); + + /** + * Queues a message for the child. + * + * Must only be called by the main thread. + * + * @param msg The message. + * + * @param force: If true, the message will be queued even when we're already + * Terminating(). Normally, the message would be discarded in that + * case. + */ + void SendIn(BasicInputMessage* msg, bool force); + + /** + * Queues a message for the main thread. + * + * Must only be called by the child thread. + * + * @param msg The message. + * + * @param force: If true, the message will be queued even when we're already + * Terminating(). Normally, the message would be discarded in that + * case. + */ + void SendOut(BasicOutputMessage* msg, bool force); + + /** + * Returns true if there's at least one message pending for the child + * thread. + */ + bool HasIn() { return queue_in.Ready(); } + + /** + * Returns true if there's at least one message pending for the main + * thread. + */ + bool HasOut() { return queue_out.Ready(); } + + Queue queue_in; + Queue queue_out; + + uint64_t cnt_sent_in; // Counts message sent to child. + uint64_t cnt_sent_out; // Counts message sent by child. +}; + +/** + * Base class for all message between Bro's main process and a MsgThread. + */ +class Message +{ +public: + /** + * Destructor. + */ + virtual ~Message(); + + /** + * Returns a descriptive name for the message's general type. This is + * what's passed into the constructor and used mainly for debugging + * purposes. + */ + const string& Name() const { return name; } + + /** + * Callback that must be overriden for processing a message. + */ + virtual bool Process() = 0; // Thread will be terminated if returngin false. + +protected: + /** + * Constructor. + * + * @param arg_name A descriptive name for the type of message. Used + * mainly for debugging purposes. + */ + Message(const string& arg_name) { name = arg_name; } + +private: + string name; +}; + +/** + * Base class for messages sent from Bro's main thread to a child MsgThread. + */ +class BasicInputMessage : public Message +{ +protected: + /** + * Constructor. + * + * @param name A descriptive name for the type of message. Used + * mainly for debugging purposes. + */ + BasicInputMessage(const string& name) : Message(name) {} +}; + +/** + * Base class for messages sent from a child MsgThread to Bro's main thread. + */ +class BasicOutputMessage : public Message +{ +protected: + /** + * Constructor. + * + * @param name A descriptive name for the type of message. Used + * mainly for debugging purposes. + */ + BasicOutputMessage(const string& name) : Message(name) {} +}; + +/** + * A paremeterized InputMessage that stores a pointer to an argument object. + * Normally, the objects will be used from the Process() callback. + */ +template +class InputMessage : public BasicInputMessage +{ +public: + /** + * Returns the objects passed to the constructor. + */ + O* Object() const { return object; } + +protected: + /** + * Constructor. + * + * @param name: A descriptive name for the type of message. Used + * mainly for debugging purposes. + * + * @param arg_object: An object to store with the message. + */ + InputMessage(const string& name, O* arg_object) : BasicInputMessage(name) + { object = arg_object; } + +private: + O* object; +}; + +/** + * A paremeterized OututMessage that stores a pointer to an argument object. + * Normally, the objects will be used from the Process() callback. + */ +template +class OutputMessage : public BasicOutputMessage +{ +public: + /** + * Returns the objects passed to the constructor. + */ + O* Object() const { return object; } + +protected: + /** + * Constructor. + * + * @param name A descriptive name for the type of message. Used + * mainly for debugging purposes. + * + * @param arg_object An object to store with the message. + */ + OutputMessage(const string& name, O* arg_object) : BasicOutputMessage(name) + { object = arg_object; } + +private: + O* object; +}; + +} + + +#endif diff --git a/src/threading/Queue.h b/src/threading/Queue.h new file mode 100644 index 0000000000..985ba31714 --- /dev/null +++ b/src/threading/Queue.h @@ -0,0 +1,222 @@ + +#ifndef THREADING_QUEUE_H +#define THREADING_QUEUE_H + +#include +#include +#include +#include + +#include "Reporter.h" + +#undef Queue // Defined elsewhere unfortunately. + +namespace threading { + +/** + * A thread-safe single-reader single-writer queue. + * + * The implementation uses multiple queues and reads/writes in rotary fashion + * in an attempt to limit contention. + * + * All Queue instances must be instantiated by Bro's main thread. + * + * TODO: Unclear how critical performance is for this qeueue. We could like;y + * optimize it further if helpful. + */ +template +class Queue +{ +public: + /** + * Constructor. + */ + Queue(); + + /** + * Destructor. + */ + ~Queue(); + + /** + * Retrieves one elment. + */ + T Get(); + + /** + * Queues one element. + */ + void Put(T data); + + /** + * Returns true if the next Get() operation will succeed. + */ + bool Ready(); + + /** + * Returns the number of queued items not yet retrieved. + */ + uint64_t Size(); + + /** + * Statistics about inter-thread communication. + */ + struct Stats + { + uint64_t num_reads; //! Number of messages read from the queue. + uint64_t num_writes; //! Number of messages written to the queue. + }; + + /** + * Returns statistics about the queue's usage. + * + * @param stats A pointer to a structure that will be filled with + * current numbers. */ + void GetStats(Stats* stats); + +private: + static const int NUM_QUEUES = 8; + + pthread_mutex_t mutex[NUM_QUEUES]; // Mutex protected shared accesses. + pthread_cond_t has_data[NUM_QUEUES]; // Signals when data becomes available + std::queue messages[NUM_QUEUES]; // Actually holds the queued messages + + int read_ptr; // Where the next operation will read from + int write_ptr; // Where the next operation will write to + + // Statistics. + uint64_t num_reads; + uint64_t num_writes; +}; + +inline static void safe_lock(pthread_mutex_t* mutex) + { + if ( pthread_mutex_lock(mutex) != 0 ) + reporter->FatalErrorWithCore("cannot lock mutex"); + } + +inline static void safe_unlock(pthread_mutex_t* mutex) + { + if ( pthread_mutex_unlock(mutex) != 0 ) + reporter->FatalErrorWithCore("cannot unlock mutex"); + } + +template +inline Queue::Queue() + { + read_ptr = 0; + write_ptr = 0; + num_reads = num_writes = 0; + + for( int i = 0; i < NUM_QUEUES; ++i ) + { + if ( pthread_cond_init(&has_data[i], NULL) != 0 ) + reporter->FatalError("cannot init queue condition variable"); + + if ( pthread_mutex_init(&mutex[i], NULL) != 0 ) + reporter->FatalError("cannot init queue mutex"); + } + } + +template +inline Queue::~Queue() + { + for( int i = 0; i < NUM_QUEUES; ++i ) + { + pthread_cond_destroy(&has_data[i]); + pthread_mutex_destroy(&mutex[i]); + } + } + +template +inline T Queue::Get() + { + safe_lock(&mutex[read_ptr]); + + int old_read_ptr = read_ptr; + + if ( messages[read_ptr].empty() ) + pthread_cond_wait(&has_data[read_ptr], &mutex[read_ptr]); + + T data = messages[read_ptr].front(); + messages[read_ptr].pop(); + + read_ptr = (read_ptr + 1) % NUM_QUEUES; + ++num_reads; + + safe_unlock(&mutex[old_read_ptr]); + + return data; + } + +template +inline void Queue::Put(T data) + { + safe_lock(&mutex[write_ptr]); + + int old_write_ptr = write_ptr; + + bool need_signal = messages[write_ptr].empty(); + + messages[write_ptr].push(data); + + if ( need_signal ) + pthread_cond_signal(&has_data[write_ptr]); + + write_ptr = (write_ptr + 1) % NUM_QUEUES; + ++num_writes; + + safe_unlock(&mutex[old_write_ptr]); + } + + +template +inline bool Queue::Ready() + { + safe_lock(&mutex[read_ptr]); + + bool ret = (messages[read_ptr].size()); + + safe_unlock(&mutex[read_ptr]); + + return ret; + } + +template +inline uint64_t Queue::Size() + { + // Need to lock all queues. + for ( int i = 0; i < NUM_QUEUES; i++ ) + safe_lock(&mutex[i]); + + uint64_t size = 0; + + for ( int i = 0; i < NUM_QUEUES; i++ ) + size += messages[i].size(); + + for ( int i = 0; i < NUM_QUEUES; i++ ) + safe_unlock(&mutex[i]); + + return size; + } + +template +inline void Queue::GetStats(Stats* stats) + { + // To be safe, we look all queues. That's probably unneccessary, but + // doesn't really hurt. + for ( int i = 0; i < NUM_QUEUES; i++ ) + safe_lock(&mutex[i]); + + stats->num_reads = num_reads; + stats->num_writes = num_writes; + + for ( int i = 0; i < NUM_QUEUES; i++ ) + safe_unlock(&mutex[i]); + } + +} + + +#endif + diff --git a/src/threading/SerialTypes.cc b/src/threading/SerialTypes.cc new file mode 100644 index 0000000000..a5692b2ffd --- /dev/null +++ b/src/threading/SerialTypes.cc @@ -0,0 +1,355 @@ +// See the file "COPYING" in the main distribution directory for copyright. + + +#include "SerialTypes.h" +#include "../RemoteSerializer.h" + + +using namespace threading; + +bool Field::Read(SerializationFormat* fmt) + { + int t; + int st; + + bool success = (fmt->Read(&name, "name") && fmt->Read(&t, "type") && fmt->Read(&st, "subtype") ); + type = (TypeTag) t; + subtype = (TypeTag) st; + + return success; + } + +bool Field::Write(SerializationFormat* fmt) const + { + return (fmt->Write(name, "name") && fmt->Write((int)type, "type") && fmt->Write((int)subtype, "subtype")); + } + +Value::~Value() + { + if ( (type == TYPE_ENUM || type == TYPE_STRING || type == TYPE_FILE || type == TYPE_FUNC) + && present ) + delete val.string_val; + + if ( type == TYPE_TABLE && present ) + { + for ( int i = 0; i < val.set_val.size; i++ ) + delete val.set_val.vals[i]; + + delete [] val.set_val.vals; + } + + if ( type == TYPE_VECTOR && present ) + { + for ( int i = 0; i < val.vector_val.size; i++ ) + delete val.vector_val.vals[i]; + + delete [] val.vector_val.vals; + } + } + +bool Value::IsCompatibleType(BroType* t, bool atomic_only) + { + if ( ! t ) + return false; + + switch ( t->Tag() ) { + case TYPE_BOOL: + case TYPE_INT: + case TYPE_COUNT: + case TYPE_COUNTER: + case TYPE_PORT: + case TYPE_SUBNET: + case TYPE_ADDR: + case TYPE_DOUBLE: + case TYPE_TIME: + case TYPE_INTERVAL: + case TYPE_ENUM: + case TYPE_STRING: + case TYPE_FILE: + case TYPE_FUNC: + return true; + + case TYPE_RECORD: + return ! atomic_only; + + case TYPE_TABLE: + { + if ( atomic_only ) + return false; + + if ( ! t->IsSet() ) + return false; + + return IsCompatibleType(t->AsSetType()->Indices()->PureType(), true); + } + + case TYPE_VECTOR: + { + if ( atomic_only ) + return false; + + return IsCompatibleType(t->AsVectorType()->YieldType(), true); + } + + default: + return false; + } + + return false; + } + +bool Value::Read(SerializationFormat* fmt) + { + int ty; + + if ( ! (fmt->Read(&ty, "type") && fmt->Read(&present, "present")) ) + return false; + + type = (TypeTag)(ty); + + if ( ! present ) + return true; + + switch ( type ) { + case TYPE_BOOL: + case TYPE_INT: + return fmt->Read(&val.int_val, "int"); + + case TYPE_COUNT: + case TYPE_COUNTER: + return fmt->Read(&val.uint_val, "uint"); + + case TYPE_PORT: { + int proto; + if ( ! (fmt->Read(&val.port_val.port, "port") && fmt->Read(&proto, "proto") ) ) { + return false; + } + + switch ( proto ) { + case 0: + val.port_val.proto = TRANSPORT_UNKNOWN; + break; + case 1: + val.port_val.proto = TRANSPORT_TCP; + break; + case 2: + val.port_val.proto = TRANSPORT_UDP; + break; + case 3: + val.port_val.proto = TRANSPORT_ICMP; + break; + default: + return false; + } + + return true; + } + + case TYPE_ADDR: + { + char family; + + if ( ! fmt->Read(&family, "addr-family") ) + return false; + + switch ( family ) { + case 4: + val.addr_val.family = IPv4; + return fmt->Read(&val.addr_val.in.in4, "addr-in4"); + + case 6: + val.addr_val.family = IPv6; + return fmt->Read(&val.addr_val.in.in6, "addr-in6"); + + } + + // Can't be reached. + abort(); + } + + case TYPE_SUBNET: + { + char length; + char family; + + if ( ! (fmt->Read(&length, "subnet-len") && fmt->Read(&family, "subnet-family")) ) + return false; + + switch ( family ) { + case 4: + val.subnet_val.length = (uint8_t)length; + val.subnet_val.prefix.family = IPv4; + return fmt->Read(&val.subnet_val.prefix.in.in4, "subnet-in4"); + + case 6: + val.subnet_val.length = (uint8_t)length; + val.subnet_val.prefix.family = IPv6; + return fmt->Read(&val.subnet_val.prefix.in.in6, "subnet-in6"); + + } + + // Can't be reached. + abort(); + } + + case TYPE_DOUBLE: + case TYPE_TIME: + case TYPE_INTERVAL: + return fmt->Read(&val.double_val, "double"); + + case TYPE_ENUM: + case TYPE_STRING: + case TYPE_FILE: + case TYPE_FUNC: + { + val.string_val = new string; + return fmt->Read(val.string_val, "string"); + } + + case TYPE_TABLE: + { + if ( ! fmt->Read(&val.set_val.size, "set_size") ) + return false; + + val.set_val.vals = new Value* [val.set_val.size]; + + for ( int i = 0; i < val.set_val.size; ++i ) + { + val.set_val.vals[i] = new Value; + + if ( ! val.set_val.vals[i]->Read(fmt) ) + return false; + } + + return true; + } + + case TYPE_VECTOR: + { + if ( ! fmt->Read(&val.vector_val.size, "vector_size") ) + return false; + + val.vector_val.vals = new Value* [val.vector_val.size]; + + for ( int i = 0; i < val.vector_val.size; ++i ) + { + val.vector_val.vals[i] = new Value; + + if ( ! val.vector_val.vals[i]->Read(fmt) ) + return false; + } + + return true; + } + + default: + reporter->InternalError("unsupported type %s in Value::Write", type_name(type)); + } + + return false; + } + +bool Value::Write(SerializationFormat* fmt) const + { + if ( ! (fmt->Write((int)type, "type") && + fmt->Write(present, "present")) ) + return false; + + if ( ! present ) + return true; + + switch ( type ) { + case TYPE_BOOL: + case TYPE_INT: + return fmt->Write(val.int_val, "int"); + + case TYPE_COUNT: + case TYPE_COUNTER: + return fmt->Write(val.uint_val, "uint"); + + case TYPE_PORT: + return fmt->Write(val.port_val.port, "port") && fmt->Write(val.port_val.proto, "proto"); + + case TYPE_ADDR: + { + switch ( val.addr_val.family ) { + case IPv4: + return fmt->Write((char)4, "addr-family") + && fmt->Write(val.addr_val.in.in4, "addr-in4"); + + case IPv6: + return fmt->Write((char)6, "addr-family") + && fmt->Write(val.addr_val.in.in6, "addr-in6"); + break; + } + + // Can't be reached. + abort(); + } + + case TYPE_SUBNET: + { + if ( ! fmt->Write((char)val.subnet_val.length, "subnet-length") ) + return false; + + switch ( val.subnet_val.prefix.family ) { + case IPv4: + return fmt->Write((char)4, "subnet-family") + && fmt->Write(val.subnet_val.prefix.in.in4, "subnet-in4"); + + case IPv6: + return fmt->Write((char)6, "subnet-family") + && fmt->Write(val.subnet_val.prefix.in.in6, "subnet-in6"); + break; + } + + // Can't be reached. + abort(); + } + + case TYPE_DOUBLE: + case TYPE_TIME: + case TYPE_INTERVAL: + return fmt->Write(val.double_val, "double"); + + case TYPE_ENUM: + case TYPE_STRING: + case TYPE_FILE: + case TYPE_FUNC: + return fmt->Write(*val.string_val, "string"); + + case TYPE_TABLE: + { + if ( ! fmt->Write(val.set_val.size, "set_size") ) + return false; + + for ( int i = 0; i < val.set_val.size; ++i ) + { + if ( ! val.set_val.vals[i]->Write(fmt) ) + return false; + } + + return true; + } + + case TYPE_VECTOR: + { + if ( ! fmt->Write(val.vector_val.size, "vector_size") ) + return false; + + for ( int i = 0; i < val.vector_val.size; ++i ) + { + if ( ! val.vector_val.vals[i]->Write(fmt) ) + return false; + } + + return true; + } + + default: + reporter->InternalError("unsupported type %s in Value::REad", type_name(type)); + } + + return false; + } + diff --git a/src/threading/SerialTypes.h b/src/threading/SerialTypes.h new file mode 100644 index 0000000000..db7dc837bd --- /dev/null +++ b/src/threading/SerialTypes.h @@ -0,0 +1,146 @@ + +#ifndef THREADING_SERIALIZATIONTYPES_H +#define THREADING_SERIALIZATIONTYPES_H + +using namespace std; + +#include +#include +#include + +#include "Type.h" +#include "net_util.h" + +class SerializationFormat; + +namespace threading { + +/** + * Definition of a log file, i.e., one column of a log stream. + */ +struct Field { + string name; //! Name of the field. + TypeTag type; //! Type of the field. + TypeTag subtype; //! Inner type for sets. + + /** + * Constructor. + */ + Field() { subtype = TYPE_VOID; } + + /** + * Copy constructor. + */ + Field(const Field& other) + : name(other.name), type(other.type), subtype(other.subtype) { } + + /** + * Unserializes a field. + * + * @param fmt The serialization format to use. The format handles + * low-level I/O. + * + * @return False if an error occured. + */ + bool Read(SerializationFormat* fmt); + + /** + * Serializes a field. + * + * @param fmt The serialization format to use. The format handles + * low-level I/O. + * + * @return False if an error occured. + */ + bool Write(SerializationFormat* fmt) const; +}; + +/** + * Definition of a log value, i.e., a entry logged by a stream. + * + * This struct essentialy represents a serialization of a Val instance (for + * those Vals supported). + */ +struct Value { + TypeTag type; //! The type of the value. + bool present; //! False for optional record fields that are not set. + + struct set_t { bro_int_t size; Value** vals; }; + typedef set_t vec_t; + struct port_t { bro_uint_t port; TransportProto proto; }; + + struct addr_t { + IPFamily family; + union { + struct in_addr in4; + struct in6_addr in6; + } in; + }; + + struct subnet_t { addr_t prefix; uint8_t length; }; + + /** + * This union is a subset of BroValUnion, including only the types we + * can log directly. See IsCompatibleType(). + */ + union _val { + bro_int_t int_val; + bro_uint_t uint_val; + port_t port_val; + double double_val; + set_t set_val; + vec_t vector_val; + addr_t addr_val; + subnet_t subnet_val; + string* string_val; + } val; + + /** + * Constructor. + * + * arg_type: The type of the value. + * + * arg_present: False if the value represents an optional record field + * that is not set. + */ + Value(TypeTag arg_type = TYPE_ERROR, bool arg_present = true) + : type(arg_type), present(arg_present) {} + + /** + * Destructor. + */ + ~Value(); + + /** + * Unserializes a value. + * + * @param fmt The serialization format to use. The format handles low-level I/O. + * + * @return False if an error occured. + */ + bool Read(SerializationFormat* fmt); + + /** + * Serializes a value. + * + * @param fmt The serialization format to use. The format handles + * low-level I/O. + * + * @return False if an error occured. + */ + bool Write(SerializationFormat* fmt) const; + + /** + * Returns true if the type can be represented by a Value. If + * `atomic_only` is true, will not permit composite types. + */ + static bool IsCompatibleType(BroType* t, bool atomic_only=false); + +private: +friend class ::IPAddr; + Value(const Value& other) { } // Disabled. +}; + +} + +#endif /* THREADING_SERIALIZATIONTZPES_H */ diff --git a/src/types.bif b/src/types.bif index 5f1c4b850b..0017c4b6ff 100644 --- a/src/types.bif +++ b/src/types.bif @@ -1,3 +1,4 @@ +##! Declaration of various types that the Bro core uses internally. enum dce_rpc_ptype %{ DCE_RPC_REQUEST, @@ -134,8 +135,8 @@ enum createmode_t %{ EXCLUSIVE = 2, %} -# Decleare record types that we want to access from the even engine. These are -# defined in bro.init. +# Declare record types that we want to access from the event engine. These are +# defined in init-bare.bro. type info_t: record; type fattr_t: record; type diropargs_t: record; @@ -159,6 +160,7 @@ module Log; enum Writer %{ WRITER_DEFAULT, + WRITER_NONE, WRITER_ASCII, %} diff --git a/src/util.cc b/src/util.cc index 90eac56cca..856e90d156 100644 --- a/src/util.cc +++ b/src/util.cc @@ -1,5 +1,3 @@ -// $Id: util.cc 6916 2009-09-24 20:48:36Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #include "config.h" @@ -43,6 +41,37 @@ #include "Net.h" #include "Reporter.h" +/** + * Takes a string, escapes characters into equivalent hex codes (\x##), and + * returns a string containing all escaped values. + * + * @param str string to escape + * @param escape_all If true, all characters are escaped. If false, only + * characters are escaped that are either whitespace or not printable in + * ASCII. + * @return A std::string containing a list of escaped hex values of the form + * \x## */ +std::string get_escaped_string(const std::string& str, bool escape_all) +{ + char tbuf[16]; + string esc = ""; + + for ( size_t i = 0; i < str.length(); ++i ) + { + char c = str[i]; + + if ( escape_all || isspace(c) || ! isascii(c) || ! isprint(c) ) + { + snprintf(tbuf, sizeof(tbuf), "\\x%02x", str[i]); + esc += tbuf; + } + else + esc += c; + } + + return esc; +} + char* copy_string(const char* s) { char* c = new char[strlen(s)+1]; @@ -87,7 +116,7 @@ int expand_escape(const char*& s) int result; if ( sscanf(start, "%3o", &result) != 1 ) { - reporter->Warning("bad octal escape: ", start); + reporter->Warning("bad octal escape: %s ", start); result = 0; } @@ -106,7 +135,7 @@ int expand_escape(const char*& s) int result; if ( sscanf(start, "%2x", &result) != 1 ) { - reporter->Warning("bad hexadecimal escape: ", start); + reporter->Warning("bad hexadecimal escape: %s", start); result = 0; } @@ -347,6 +376,7 @@ template int atoi_n(int len, const char* s, const char** end, int base, // Instantiate the ones we need. template int atoi_n(int len, const char* s, const char** end, int base, int& result); template int atoi_n(int len, const char* s, const char** end, int base, int64_t& result); +template int atoi_n(int len, const char* s, const char** end, int base, uint64_t& result); char* uitoa_n(uint64 value, char* str, int n, int base, const char* prefix) { @@ -359,7 +389,7 @@ char* uitoa_n(uint64 value, char* str, int n, int base, const char* prefix) char* p, *q; char c; - if ( prefix ) + if ( prefix ) { strncpy(str, prefix, n); str[n-1] = '\0'; @@ -480,22 +510,22 @@ bool ensure_dir(const char *dirname) { if ( errno != ENOENT ) { - reporter->Warning(fmt("can't stat directory %s: %s", - dirname, strerror(errno))); + reporter->Warning("can't stat directory %s: %s", + dirname, strerror(errno)); return false; } if ( mkdir(dirname, 0700) < 0 ) { - reporter->Warning(fmt("can't create directory %s: %s", - dirname, strerror(errno))); + reporter->Warning("can't create directory %s: %s", + dirname, strerror(errno)); return false; } } else if ( ! S_ISDIR(st.st_mode) ) { - reporter->Warning(fmt("%s exists but is not a directory", dirname)); + reporter->Warning("%s exists but is not a directory", dirname); return false; } @@ -508,7 +538,7 @@ bool is_dir(const char* path) if ( stat(path, &st) < 0 ) { if ( errno != ENOENT ) - reporter->Warning(fmt("can't stat %s: %s", path, strerror(errno))); + reporter->Warning("can't stat %s: %s", path, strerror(errno)); return false; } @@ -558,15 +588,15 @@ static bool read_random_seeds(const char* read_file, uint32* seed, if ( stat(read_file, &st) < 0 ) { - reporter->Warning(fmt("Seed file '%s' does not exist: %s", - read_file, strerror(errno))); + reporter->Warning("Seed file '%s' does not exist: %s", + read_file, strerror(errno)); return false; } if ( ! (f = fopen(read_file, "r")) ) { - reporter->Warning(fmt("Could not open seed file '%s': %s", - read_file, strerror(errno))); + reporter->Warning("Could not open seed file '%s': %s", + read_file, strerror(errno)); return false; } @@ -601,8 +631,8 @@ static bool write_random_seeds(const char* write_file, uint32 seed, if ( ! (f = fopen(write_file, "w+")) ) { - reporter->Warning(fmt("Could not create seed file '%s': %s", - write_file, strerror(errno))); + reporter->Warning("Could not create seed file '%s': %s", + write_file, strerror(errno)); return false; } @@ -839,7 +869,7 @@ string dot_canon(string path, string file, string prefix) } delete [] tmp; size_t n; - while ( (n = dottedform.find("/")) != string::npos ) + while ( (n = dottedform.find("/")) != string::npos ) dottedform.replace(n, 1, "."); return dottedform; } @@ -891,7 +921,7 @@ const char* normalize_path(const char* path) return copy_string(new_path.c_str()); } -// Returns the subpath of the root Bro script install/source directory in +// Returns the subpath of the root Bro script install/source/build directory in // which the loaded file is located. If it's not under a subpath of that // directory (e.g. cwd or custom path) then the full path is returned. void get_script_subpath(const std::string& full_filename, const char** subpath) @@ -909,11 +939,15 @@ void get_script_subpath(const std::string& full_filename, const char** subpath) // first check if this is some subpath of the installed scripts root path, // if not check if it's a subpath of the script source root path, - // if neither, will just use the given directory - if ( (p=my_subpath.find(BRO_SCRIPT_INSTALL_PATH)) != std::string::npos ) + // then check if it's a subpath of the build directory (where BIF scripts + // will get generated). + // If none of those, will just use the given directory. + if ( (p = my_subpath.find(BRO_SCRIPT_INSTALL_PATH)) != std::string::npos ) my_subpath.erase(0, strlen(BRO_SCRIPT_INSTALL_PATH)); - else if ( (p=my_subpath.find(BRO_SCRIPT_SOURCE_PATH)) != std::string::npos ) + else if ( (p = my_subpath.find(BRO_SCRIPT_SOURCE_PATH)) != std::string::npos ) my_subpath.erase(0, strlen(BRO_SCRIPT_SOURCE_PATH)); + else if ( (p = my_subpath.find(BRO_BUILD_PATH)) != std::string::npos ) + my_subpath.erase(0, strlen(BRO_BUILD_PATH)); // if root path found, remove path separators until next path component if ( p != std::string::npos ) @@ -1022,7 +1056,7 @@ FILE* rotate_file(const char* name, RecordVal* rotate_info) FILE* newf = fopen(tmpname, "w"); if ( ! newf ) { - reporter->Error(fmt("rotate_file: can't open %s: %s", tmpname, strerror(errno))); + reporter->Error("rotate_file: can't open %s: %s", tmpname, strerror(errno)); return 0; } @@ -1031,7 +1065,7 @@ FILE* rotate_file(const char* name, RecordVal* rotate_info) struct stat dummy; if ( link(name, newname) < 0 || stat(newname, &dummy) < 0 ) { - reporter->Error(fmt("rotate_file: can't move %s to %s: %s", name, newname, strerror(errno))); + reporter->Error("rotate_file: can't move %s to %s: %s", name, newname, strerror(errno)); fclose(newf); unlink(newname); unlink(tmpname); @@ -1041,7 +1075,7 @@ FILE* rotate_file(const char* name, RecordVal* rotate_info) // Close current file, and move the tmp to its place. if ( unlink(name) < 0 || link(tmpname, name) < 0 || unlink(tmpname) < 0 ) { - reporter->Error(fmt("rotate_file: can't move %s to %s: %s", tmpname, name, strerror(errno))); + reporter->Error("rotate_file: can't move %s to %s: %s", tmpname, name, strerror(errno)); exit(1); // hard to fix, but shouldn't happen anyway... } @@ -1182,15 +1216,44 @@ int time_compare(struct timeval* tv_a, struct timeval* tv_b) return tv_a->tv_sec - tv_b->tv_sec; } -static uint64 uid_counter; // Counter for unique IDs. -static uint64 uid_instance; // Instance ID, computed once. +struct UIDEntry { + UIDEntry() : key(0, 0), needs_init(true) { } + UIDEntry(const uint64 i) : key(i, 0), needs_init(false) { } + + struct UIDKey { + UIDKey(uint64 i, uint64 c) : instance(i), counter(c) { } + uint64 instance; + uint64 counter; + } key; + + bool needs_init; +}; + +static std::vector uid_pool; uint64 calculate_unique_id() { - if ( uid_instance == 0 ) - { - // This is the first time we need a UID. + return calculate_unique_id(UID_POOL_DEFAULT_INTERNAL); + } +uint64 calculate_unique_id(size_t pool) + { + uint64 uid_instance = 0; + + if( pool >= uid_pool.size() ) + { + if ( pool < 10000 ) + uid_pool.resize(pool + 1); + else + { + reporter->Warning("pool passed to calculate_unique_id() too large, using default"); + pool = UID_POOL_DEFAULT_INTERNAL; + } + } + + if ( uid_pool[pool].needs_init ) + { + // This is the first time we need a UID for this pool. if ( ! have_random_seed() ) { // If we don't need deterministic output (as @@ -1198,39 +1261,37 @@ uint64 calculate_unique_id() // instance ID by hashing something likely to be // globally unique. struct { - char hostname[128]; + char hostname[120]; + uint64 pool; struct timeval time; pid_t pid; int rnd; } unique; memset(&unique, 0, sizeof(unique)); // Make valgrind happy. - gethostname(unique.hostname, 128); + gethostname(unique.hostname, 120); unique.hostname[sizeof(unique.hostname)-1] = '\0'; gettimeofday(&unique.time, 0); + unique.pool = (uint64) pool; unique.pid = getpid(); unique.rnd = bro_random(); uid_instance = HashKey::HashBytes(&unique, sizeof(unique)); ++uid_instance; // Now it's larger than zero. } - else - // Generate determistic UIDs. - uid_instance = 1; + // Generate determistic UIDs for each individual pool. + uid_instance = pool; + + // Our instance is unique. Huzzah. + uid_pool[pool] = UIDEntry(uid_instance); } - // Now calculate the unique ID. - struct { - uint64 counter; - hash_t instance; - } key; + assert(!uid_pool[pool].needs_init); + assert(uid_pool[pool].key.instance != 0); - key.counter = ++uid_counter; - key.instance = uid_instance; - - uint64_t h = HashKey::HashBytes(&key, sizeof(key)); - return h; + ++uid_pool[pool].key.counter; + return HashKey::HashBytes(&(uid_pool[pool].key), sizeof(uid_pool[pool].key)); } void out_of_memory(const char* where) diff --git a/src/util.h b/src/util.h index 392b2ca76a..a4e3aa71b8 100644 --- a/src/util.h +++ b/src/util.h @@ -1,5 +1,3 @@ -// $Id: util.h 6782 2009-06-28 02:19:03Z vern $ -// // See the file "COPYING" in the main distribution directory for copyright. #ifndef util_h @@ -39,7 +37,7 @@ #endif -#ifdef USE_PERFTOOLS +#ifdef USE_PERFTOOLS_DEBUG #include #include extern HeapLeakChecker* heap_checker; @@ -78,6 +76,11 @@ typedef int32 ptr_compat_int; # error "Unusual pointer size. Please report to bro@bro-ids.org." #endif +extern "C" + { + #include "modp_numtoa.h" + } + template void delete_each(T* t) { @@ -86,6 +89,8 @@ void delete_each(T* t) delete *it; } +std::string get_escaped_string(const std::string& str, bool escape_all); + extern char* copy_string(const char* s); extern int streq(const char* s1, const char* s2); @@ -225,8 +230,14 @@ extern struct timeval double_to_timeval(double t); extern int time_compare(struct timeval* tv_a, struct timeval* tv_b); // Returns an integer that's very likely to be unique, even across Bro -// instances. +// instances. The integer can be drawn from different pools, which is helpful +// when the randon number generator is seeded to be deterministic. In that +// case, the same sequence of integers is generated per pool. +#define UID_POOL_DEFAULT_INTERNAL 1 +#define UID_POOL_DEFAULT_SCRIPT 2 +#define UID_POOL_CUSTOM_SCRIPT 10 // First available custom script level pool. extern uint64 calculate_unique_id(); +extern uint64 calculate_unique_id(const size_t pool); // For now, don't use hash_maps - they're not fully portable. #if 0 diff --git a/testing/.gitignore b/testing/.gitignore new file mode 100644 index 0000000000..a664c1d684 --- /dev/null +++ b/testing/.gitignore @@ -0,0 +1 @@ +coverage.log diff --git a/testing/Makefile b/testing/Makefile index 7f03a55f49..1c82580ec4 100644 --- a/testing/Makefile +++ b/testing/Makefile @@ -1,8 +1,21 @@ DIRS=btest external -all: +all: make-verbose coverage + +brief: make-brief coverage + +make-verbose: @for repo in $(DIRS); do (cd $$repo && make ); done -brief: +make-brief: @for repo in $(DIRS); do (cd $$repo && make brief ); done + +coverage: + @for repo in $(DIRS); do (cd $$repo && echo "Coverage for '$$repo' dir:" && make coverage); done + @test -f btest/coverage.log && cp btest/coverage.log `mktemp brocov.tmp.XXX` || true + @for f in external/*/coverage.log; do test -f $$f && cp $$f `mktemp brocov.tmp.XXX` || true; done + @echo "Complete test suite code coverage:" + @./scripts/coverage-calc "brocov.tmp.*" coverage.log `pwd`/../scripts + @rm -f brocov.tmp.* + diff --git a/testing/btest/.gitignore b/testing/btest/.gitignore index 0c143f664e..b4c1b7a858 100644 --- a/testing/btest/.gitignore +++ b/testing/btest/.gitignore @@ -1,2 +1,4 @@ .tmp +.btest.failed.dat diag.log +coverage.log diff --git a/testing/btest/Baseline/bifs.addr_count_conversion/output b/testing/btest/Baseline/bifs.addr_count_conversion/output new file mode 100644 index 0000000000..08a74512d3 --- /dev/null +++ b/testing/btest/Baseline/bifs.addr_count_conversion/output @@ -0,0 +1,4 @@ +[536939960, 2242052096, 35374, 57701172] +2001:db8:85a3::8a2e:370:7334 +[16909060] +1.2.3.4 diff --git a/testing/btest/Baseline/bifs.addr_to_ptr_name/output b/testing/btest/Baseline/bifs.addr_to_ptr_name/output new file mode 100644 index 0000000000..8de05d1d8e --- /dev/null +++ b/testing/btest/Baseline/bifs.addr_to_ptr_name/output @@ -0,0 +1,2 @@ +2.1.0.1.0.0.0.0.0.0.0.0.0.0.0.0.2.0.8.0.9.0.0.4.0.b.8.f.7.0.6.2.ip6.arpa +52.225.125.74.in-addr.arpa diff --git a/testing/btest/Baseline/bifs.addr_version/out b/testing/btest/Baseline/bifs.addr_version/out new file mode 100644 index 0000000000..328bff6687 --- /dev/null +++ b/testing/btest/Baseline/bifs.addr_version/out @@ -0,0 +1,4 @@ +T +F +F +T diff --git a/testing/btest/Baseline/bifs.decode_base64/out b/testing/btest/Baseline/bifs.decode_base64/out new file mode 100644 index 0000000000..af0d32fbb8 --- /dev/null +++ b/testing/btest/Baseline/bifs.decode_base64/out @@ -0,0 +1,6 @@ +bro +bro +bro +bro +bro +bro diff --git a/testing/btest/Baseline/bifs.install_src_addr_filter/output b/testing/btest/Baseline/bifs.install_src_addr_filter/output new file mode 100644 index 0000000000..bf99083391 --- /dev/null +++ b/testing/btest/Baseline/bifs.install_src_addr_filter/output @@ -0,0 +1,8 @@ +[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp] diff --git a/testing/btest/Baseline/bifs.net_stats_trace/output b/testing/btest/Baseline/bifs.net_stats_trace/output index a2e25e03a7..55d6693db5 100644 --- a/testing/btest/Baseline/bifs.net_stats_trace/output +++ b/testing/btest/Baseline/bifs.net_stats_trace/output @@ -1 +1 @@ -[pkts_recvd=131, pkts_dropped=0, pkts_link=0] +[pkts_recvd=136, pkts_dropped=0, pkts_link=0] diff --git a/testing/btest/Baseline/bifs.ptr_name_to_addr/output b/testing/btest/Baseline/bifs.ptr_name_to_addr/output new file mode 100644 index 0000000000..7c290027aa --- /dev/null +++ b/testing/btest/Baseline/bifs.ptr_name_to_addr/output @@ -0,0 +1,2 @@ +2607:f8b0:4009:802::1012 +74.125.225.52 diff --git a/testing/btest/Baseline/bifs.records_fields/out b/testing/btest/Baseline/bifs.records_fields/out index b221230fc0..0d52e64255 100644 --- a/testing/btest/Baseline/bifs.records_fields/out +++ b/testing/btest/Baseline/bifs.records_fields/out @@ -1,6 +1,6 @@ -[a=42, b=, c=, d=Bar] +[a=42, b=Foo, c=, d=Bar] { -[b] = [type_name=record, log=F, value=, default_val=Foo], +[b] = [type_name=record, log=F, value=Foo, default_val=Foo], [d] = [type_name=record, log=T, value=Bar, default_val=], [c] = [type_name=record, log=F, value=, default_val=], [a] = [type_name=record, log=F, value=42, default_val=] diff --git a/testing/btest/Baseline/bifs.remask_addr/output b/testing/btest/Baseline/bifs.remask_addr/output new file mode 100644 index 0000000000..1d276abd4f --- /dev/null +++ b/testing/btest/Baseline/bifs.remask_addr/output @@ -0,0 +1,32 @@ +1: 127.255.0.0 +2: 63.255.0.0 +3: 31.255.0.0 +4: 15.255.0.0 +5: 7.255.0.0 +6: 3.255.0.0 +7: 1.255.0.0 +8: 0.255.0.0 +9: 0.127.0.0 +10: 0.63.0.0 +11: 0.31.0.0 +12: 0.15.0.0 +13: 0.7.0.0 +14: 0.3.0.0 +15: 0.1.0.0 +16: 0.0.0.0 +17: 0.0.128.0 +18: 0.0.192.0 +19: 0.0.224.0 +20: 0.0.240.0 +21: 0.0.248.0 +22: 0.0.252.0 +23: 0.0.254.0 +24: 0.0.255.0 +25: 0.0.255.128 +26: 0.0.255.192 +27: 0.0.255.224 +28: 0.0.255.240 +29: 0.0.255.248 +30: 0.0.255.252 +31: 0.0.255.254 +32: 0.0.255.255 diff --git a/testing/btest/Baseline/bifs.routing0_data_to_addrs/output b/testing/btest/Baseline/bifs.routing0_data_to_addrs/output new file mode 100644 index 0000000000..c79aef89d0 --- /dev/null +++ b/testing/btest/Baseline/bifs.routing0_data_to_addrs/output @@ -0,0 +1 @@ +[2001:78:1:32::1, 2001:78:1:32::2] diff --git a/testing/btest/Baseline/bifs.to_addr/error b/testing/btest/Baseline/bifs.to_addr/error new file mode 100644 index 0000000000..b8ba985f7a --- /dev/null +++ b/testing/btest/Baseline/bifs.to_addr/error @@ -0,0 +1 @@ +error: Bad IP address: not an IP diff --git a/testing/btest/Baseline/bifs.to_addr/output b/testing/btest/Baseline/bifs.to_addr/output new file mode 100644 index 0000000000..ff277498f8 --- /dev/null +++ b/testing/btest/Baseline/bifs.to_addr/output @@ -0,0 +1,9 @@ +to_addr(0.0.0.0) = 0.0.0.0 (SUCCESS) +to_addr(1.2.3.4) = 1.2.3.4 (SUCCESS) +to_addr(01.02.03.04) = 1.2.3.4 (SUCCESS) +to_addr(001.002.003.004) = 1.2.3.4 (SUCCESS) +to_addr(10.20.30.40) = 10.20.30.40 (SUCCESS) +to_addr(100.200.30.40) = 100.200.30.40 (SUCCESS) +to_addr(10.0.0.0) = 10.0.0.0 (SUCCESS) +to_addr(10.00.00.000) = 10.0.0.0 (SUCCESS) +to_addr(not an IP) = :: (SUCCESS) diff --git a/testing/btest/Baseline/bifs.to_subnet/error b/testing/btest/Baseline/bifs.to_subnet/error new file mode 100644 index 0000000000..ee0062cd83 --- /dev/null +++ b/testing/btest/Baseline/bifs.to_subnet/error @@ -0,0 +1 @@ +error: Bad string in SubNetVal ctor: 10.0.0.0 diff --git a/testing/btest/Baseline/bifs.to_subnet/output b/testing/btest/Baseline/bifs.to_subnet/output new file mode 100644 index 0000000000..0775063f89 --- /dev/null +++ b/testing/btest/Baseline/bifs.to_subnet/output @@ -0,0 +1,3 @@ +10.0.0.0/8, T +2607:f8b0::/32, T +::/0, T diff --git a/testing/btest/Baseline/bifs.unique_id-rnd/count b/testing/btest/Baseline/bifs.unique_id-rnd/count index 1e8b314962..48082f72f0 100644 --- a/testing/btest/Baseline/bifs.unique_id-rnd/count +++ b/testing/btest/Baseline/bifs.unique_id-rnd/count @@ -1 +1 @@ -6 +12 diff --git a/testing/btest/Baseline/bifs.unique_id/out b/testing/btest/Baseline/bifs.unique_id/out index f1275a52d4..a538697057 100644 --- a/testing/btest/Baseline/bifs.unique_id/out +++ b/testing/btest/Baseline/bifs.unique_id/out @@ -1,3 +1,6 @@ -A-UWkUyAuUGXf -B-56gKBmhBBB6 -C-50da4BEzauh +A-56gKBmhBBB6 +B-PjbroujOxH4 +C-N4zgPFAv3J +D-R8BqVlcp23e +E-duYdXg7bTa3 +F-FSX5JvMaA88 diff --git a/testing/btest/Baseline/core.check-unused-event-handlers/.stderr b/testing/btest/Baseline/core.check-unused-event-handlers/.stderr new file mode 100644 index 0000000000..8d8bf1a85b --- /dev/null +++ b/testing/btest/Baseline/core.check-unused-event-handlers/.stderr @@ -0,0 +1 @@ +warning in , line 1: event handler never invoked: this_is_never_used diff --git a/testing/btest/Baseline/core.checksums/bad.out b/testing/btest/Baseline/core.checksums/bad.out new file mode 100644 index 0000000000..57089a72a6 --- /dev/null +++ b/testing/btest/Baseline/core.checksums/bad.out @@ -0,0 +1,13 @@ +1332784981.078396 weird: bad_IP_checksum +1332784885.686428 weird: bad_TCP_checksum +1332784933.501023 weird: bad_UDP_checksum +1334075363.536871 weird: bad_ICMP_checksum +1332785210.013051 weird: routing0_hdr +1332785210.013051 weird: bad_TCP_checksum +1332782580.798420 weird: routing0_hdr +1332782580.798420 weird: bad_UDP_checksum +1334075111.800086 weird: routing0_hdr +1334075111.800086 weird: bad_ICMP_checksum +1332785250.469132 weird: bad_TCP_checksum +1332781342.923813 weird: bad_UDP_checksum +1334074939.467194 weird: bad_ICMP_checksum diff --git a/testing/btest/Baseline/core.checksums/good.out b/testing/btest/Baseline/core.checksums/good.out new file mode 100644 index 0000000000..4330967d8d --- /dev/null +++ b/testing/btest/Baseline/core.checksums/good.out @@ -0,0 +1,3 @@ +1332785125.596793 weird: routing0_hdr +1332782508.592037 weird: routing0_hdr +1334075027.053380 weird: routing0_hdr diff --git a/testing/btest/Baseline/core.conn-uid/counts b/testing/btest/Baseline/core.conn-uid/counts index a8fa06e1be..38b10c1b2b 100644 --- a/testing/btest/Baseline/core.conn-uid/counts +++ b/testing/btest/Baseline/core.conn-uid/counts @@ -1 +1 @@ -62 +68 diff --git a/testing/btest/Baseline/core.conn-uid/output b/testing/btest/Baseline/core.conn-uid/output index ff6514e133..c77eda4f04 100644 --- a/testing/btest/Baseline/core.conn-uid/output +++ b/testing/btest/Baseline/core.conn-uid/output @@ -1,39 +1,43 @@ [orig_h=141.142.220.202, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], UWkUyAuUGXf -[orig_h=141.142.220.50, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], 56gKBmhBBB6 -[orig_h=141.142.220.118, orig_p=35634/tcp, resp_h=208.80.152.2, resp_p=80/tcp], 50da4BEzauh -[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp], WUjEZFOdSS -[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp], WUjEZFOdSS -[orig_h=141.142.220.118, orig_p=43927/udp, resp_h=141.142.2.2, resp_p=53/udp], ecqdozAET6c -[orig_h=141.142.220.118, orig_p=37676/udp, resp_h=141.142.2.2, resp_p=53/udp], tdkrEYpj5ja -[orig_h=141.142.220.118, orig_p=40526/udp, resp_h=141.142.2.2, resp_p=53/udp], F5XgctwO3Vl -[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp], svqqNKN9CFj -[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp], UZkBBvjF0r8 -[orig_h=141.142.220.118, orig_p=32902/udp, resp_h=141.142.2.2, resp_p=53/udp], nSEQzFk1LZc -[orig_h=141.142.220.118, orig_p=59816/udp, resp_h=141.142.2.2, resp_p=53/udp], rmXOq6wncn1 -[orig_h=141.142.220.118, orig_p=59714/udp, resp_h=141.142.2.2, resp_p=53/udp], 4YYJTjETe1i -[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp], OldlyspNIr7 -[orig_h=141.142.220.118, orig_p=58206/udp, resp_h=141.142.2.2, resp_p=53/udp], R8BqVlcp23e -[orig_h=141.142.220.118, orig_p=38911/udp, resp_h=141.142.2.2, resp_p=53/udp], duYdXg7bTa3 -[orig_h=141.142.220.118, orig_p=59746/udp, resp_h=141.142.2.2, resp_p=53/udp], yzqaQTU9DXe -[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp], OPM7xFSDNw3 -[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp], j5w2LueK8Ti -[orig_h=141.142.220.118, orig_p=45000/udp, resp_h=141.142.2.2, resp_p=53/udp], N6rbUGwigQ7 -[orig_h=141.142.220.118, orig_p=48479/udp, resp_h=141.142.2.2, resp_p=53/udp], 8b9q7qPtzhd -[orig_h=141.142.220.118, orig_p=48128/udp, resp_h=141.142.2.2, resp_p=53/udp], KOdlL7sC9z2 -[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp], hvOo97vj60k -[orig_h=141.142.220.118, orig_p=56056/udp, resp_h=141.142.2.2, resp_p=53/udp], FHu81uYujA9 -[orig_h=141.142.220.118, orig_p=55092/udp, resp_h=141.142.2.2, resp_p=53/udp], 2M1wDTa0C7a -[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp], OKiJdtzKWPk -[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp], UZkBBvjF0r8 -[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp], svqqNKN9CFj -[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp], OldlyspNIr7 -[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp], j5w2LueK8Ti -[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp], OPM7xFSDNw3 -[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp], hvOo97vj60k -[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp], OKiJdtzKWPk -[orig_h=173.192.163.128, orig_p=80/tcp, resp_h=141.142.220.235, resp_p=6705/tcp], tpUWfNdSLE -[orig_h=141.142.220.44, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], ra1C6ZLut4b -[orig_h=141.142.220.226, orig_p=137/udp, resp_h=141.142.220.255, resp_p=137/udp], UElDH5b9qA5 -[orig_h=141.142.220.226, orig_p=55131/udp, resp_h=224.0.0.252, resp_p=5355/udp], sO3mBXBav1h -[orig_h=141.142.220.226, orig_p=55671/udp, resp_h=224.0.0.252, resp_p=5355/udp], xAQqZE8Wdp4 -[orig_h=141.142.220.238, orig_p=56641/udp, resp_h=141.142.220.255, resp_p=137/udp], zVecVnfOlsf +[orig_h=fe80::217:f2ff:fed7:cf65, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp], arKYeMETxOg +[orig_h=141.142.220.50, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], k6kgXLOoSKl +[orig_h=141.142.220.118, orig_p=35634/tcp, resp_h=208.80.152.2, resp_p=80/tcp], nQcgTWjvg4c +[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp], j4u32Pc5bif +[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp], j4u32Pc5bif +[orig_h=141.142.220.118, orig_p=43927/udp, resp_h=141.142.2.2, resp_p=53/udp], TEfuqmmG4bh +[orig_h=141.142.220.118, orig_p=37676/udp, resp_h=141.142.2.2, resp_p=53/udp], FrJExwHcSal +[orig_h=141.142.220.118, orig_p=40526/udp, resp_h=141.142.2.2, resp_p=53/udp], 5OKnoww6xl4 +[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp], 3PKsZ2Uye21 +[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp], VW0XPVINV8a +[orig_h=141.142.220.118, orig_p=32902/udp, resp_h=141.142.2.2, resp_p=53/udp], fRFu0wcOle6 +[orig_h=141.142.220.118, orig_p=59816/udp, resp_h=141.142.2.2, resp_p=53/udp], qSsw6ESzHV4 +[orig_h=141.142.220.118, orig_p=59714/udp, resp_h=141.142.2.2, resp_p=53/udp], iE6yhOq3SF +[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp], GSxOnSLghOa +[orig_h=141.142.220.118, orig_p=58206/udp, resp_h=141.142.2.2, resp_p=53/udp], qCaWGmzFtM5 +[orig_h=141.142.220.118, orig_p=38911/udp, resp_h=141.142.2.2, resp_p=53/udp], 70MGiRM1Qf4 +[orig_h=141.142.220.118, orig_p=59746/udp, resp_h=141.142.2.2, resp_p=53/udp], h5DsfNtYzi1 +[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp], P654jzLoe3a +[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp], Tw8jXtpTGu6 +[orig_h=141.142.220.118, orig_p=45000/udp, resp_h=141.142.2.2, resp_p=53/udp], c4Zw9TmAE05 +[orig_h=141.142.220.118, orig_p=48479/udp, resp_h=141.142.2.2, resp_p=53/udp], EAr0uf4mhq +[orig_h=141.142.220.118, orig_p=48128/udp, resp_h=141.142.2.2, resp_p=53/udp], GvmoxJFXdTa +[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp], 0Q4FH8sESw5 +[orig_h=141.142.220.118, orig_p=56056/udp, resp_h=141.142.2.2, resp_p=53/udp], slFea8xwSmb +[orig_h=141.142.220.118, orig_p=55092/udp, resp_h=141.142.2.2, resp_p=53/udp], UfGkYA2HI2g +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp], i2rO3KD1Syg +[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp], VW0XPVINV8a +[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp], 3PKsZ2Uye21 +[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp], GSxOnSLghOa +[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp], Tw8jXtpTGu6 +[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp], P654jzLoe3a +[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp], 0Q4FH8sESw5 +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp], i2rO3KD1Syg +[orig_h=141.142.220.235, orig_p=6705/tcp, resp_h=173.192.163.128, resp_p=80/tcp], 2cx26uAvUPl +[orig_h=141.142.220.235, orig_p=6705/tcp, resp_h=173.192.163.128, resp_p=80/tcp], 2cx26uAvUPl +[orig_h=141.142.220.44, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], BWaU4aSuwkc +[orig_h=141.142.220.226, orig_p=137/udp, resp_h=141.142.220.255, resp_p=137/udp], 10XodEwRycf +[orig_h=fe80::3074:17d5:2052:c324, orig_p=65373/udp, resp_h=ff02::1:3, resp_p=5355/udp], zno26fFZkrh +[orig_h=141.142.220.226, orig_p=55131/udp, resp_h=224.0.0.252, resp_p=5355/udp], v5rgkJBig5l +[orig_h=fe80::3074:17d5:2052:c324, orig_p=54213/udp, resp_h=ff02::1:3, resp_p=5355/udp], eWZCH7OONC1 +[orig_h=141.142.220.226, orig_p=55671/udp, resp_h=224.0.0.252, resp_p=5355/udp], 0Pwk3ntf8O3 +[orig_h=141.142.220.238, orig_p=56641/udp, resp_h=141.142.220.255, resp_p=137/udp], 0HKorjr8Zp7 diff --git a/testing/btest/Baseline/core.conn-uid/output.cc b/testing/btest/Baseline/core.conn-uid/output.cc deleted file mode 100644 index ff6514e133..0000000000 --- a/testing/btest/Baseline/core.conn-uid/output.cc +++ /dev/null @@ -1,39 +0,0 @@ -[orig_h=141.142.220.202, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], UWkUyAuUGXf -[orig_h=141.142.220.50, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], 56gKBmhBBB6 -[orig_h=141.142.220.118, orig_p=35634/tcp, resp_h=208.80.152.2, resp_p=80/tcp], 50da4BEzauh -[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp], WUjEZFOdSS -[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp], WUjEZFOdSS -[orig_h=141.142.220.118, orig_p=43927/udp, resp_h=141.142.2.2, resp_p=53/udp], ecqdozAET6c -[orig_h=141.142.220.118, orig_p=37676/udp, resp_h=141.142.2.2, resp_p=53/udp], tdkrEYpj5ja -[orig_h=141.142.220.118, orig_p=40526/udp, resp_h=141.142.2.2, resp_p=53/udp], F5XgctwO3Vl -[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp], svqqNKN9CFj -[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp], UZkBBvjF0r8 -[orig_h=141.142.220.118, orig_p=32902/udp, resp_h=141.142.2.2, resp_p=53/udp], nSEQzFk1LZc -[orig_h=141.142.220.118, orig_p=59816/udp, resp_h=141.142.2.2, resp_p=53/udp], rmXOq6wncn1 -[orig_h=141.142.220.118, orig_p=59714/udp, resp_h=141.142.2.2, resp_p=53/udp], 4YYJTjETe1i -[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp], OldlyspNIr7 -[orig_h=141.142.220.118, orig_p=58206/udp, resp_h=141.142.2.2, resp_p=53/udp], R8BqVlcp23e -[orig_h=141.142.220.118, orig_p=38911/udp, resp_h=141.142.2.2, resp_p=53/udp], duYdXg7bTa3 -[orig_h=141.142.220.118, orig_p=59746/udp, resp_h=141.142.2.2, resp_p=53/udp], yzqaQTU9DXe -[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp], OPM7xFSDNw3 -[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp], j5w2LueK8Ti -[orig_h=141.142.220.118, orig_p=45000/udp, resp_h=141.142.2.2, resp_p=53/udp], N6rbUGwigQ7 -[orig_h=141.142.220.118, orig_p=48479/udp, resp_h=141.142.2.2, resp_p=53/udp], 8b9q7qPtzhd -[orig_h=141.142.220.118, orig_p=48128/udp, resp_h=141.142.2.2, resp_p=53/udp], KOdlL7sC9z2 -[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp], hvOo97vj60k -[orig_h=141.142.220.118, orig_p=56056/udp, resp_h=141.142.2.2, resp_p=53/udp], FHu81uYujA9 -[orig_h=141.142.220.118, orig_p=55092/udp, resp_h=141.142.2.2, resp_p=53/udp], 2M1wDTa0C7a -[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp], OKiJdtzKWPk -[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp], UZkBBvjF0r8 -[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp], svqqNKN9CFj -[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp], OldlyspNIr7 -[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp], j5w2LueK8Ti -[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp], OPM7xFSDNw3 -[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp], hvOo97vj60k -[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp], OKiJdtzKWPk -[orig_h=173.192.163.128, orig_p=80/tcp, resp_h=141.142.220.235, resp_p=6705/tcp], tpUWfNdSLE -[orig_h=141.142.220.44, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], ra1C6ZLut4b -[orig_h=141.142.220.226, orig_p=137/udp, resp_h=141.142.220.255, resp_p=137/udp], UElDH5b9qA5 -[orig_h=141.142.220.226, orig_p=55131/udp, resp_h=224.0.0.252, resp_p=5355/udp], sO3mBXBav1h -[orig_h=141.142.220.226, orig_p=55671/udp, resp_h=224.0.0.252, resp_p=5355/udp], xAQqZE8Wdp4 -[orig_h=141.142.220.238, orig_p=56641/udp, resp_h=141.142.220.255, resp_p=137/udp], zVecVnfOlsf diff --git a/testing/btest/Baseline/core.conn-uid/output.cc2 b/testing/btest/Baseline/core.conn-uid/output.cc2 deleted file mode 100644 index ff6514e133..0000000000 --- a/testing/btest/Baseline/core.conn-uid/output.cc2 +++ /dev/null @@ -1,39 +0,0 @@ -[orig_h=141.142.220.202, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], UWkUyAuUGXf -[orig_h=141.142.220.50, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], 56gKBmhBBB6 -[orig_h=141.142.220.118, orig_p=35634/tcp, resp_h=208.80.152.2, resp_p=80/tcp], 50da4BEzauh -[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp], WUjEZFOdSS -[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp], WUjEZFOdSS -[orig_h=141.142.220.118, orig_p=43927/udp, resp_h=141.142.2.2, resp_p=53/udp], ecqdozAET6c -[orig_h=141.142.220.118, orig_p=37676/udp, resp_h=141.142.2.2, resp_p=53/udp], tdkrEYpj5ja -[orig_h=141.142.220.118, orig_p=40526/udp, resp_h=141.142.2.2, resp_p=53/udp], F5XgctwO3Vl -[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp], svqqNKN9CFj -[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp], UZkBBvjF0r8 -[orig_h=141.142.220.118, orig_p=32902/udp, resp_h=141.142.2.2, resp_p=53/udp], nSEQzFk1LZc -[orig_h=141.142.220.118, orig_p=59816/udp, resp_h=141.142.2.2, resp_p=53/udp], rmXOq6wncn1 -[orig_h=141.142.220.118, orig_p=59714/udp, resp_h=141.142.2.2, resp_p=53/udp], 4YYJTjETe1i -[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp], OldlyspNIr7 -[orig_h=141.142.220.118, orig_p=58206/udp, resp_h=141.142.2.2, resp_p=53/udp], R8BqVlcp23e -[orig_h=141.142.220.118, orig_p=38911/udp, resp_h=141.142.2.2, resp_p=53/udp], duYdXg7bTa3 -[orig_h=141.142.220.118, orig_p=59746/udp, resp_h=141.142.2.2, resp_p=53/udp], yzqaQTU9DXe -[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp], OPM7xFSDNw3 -[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp], j5w2LueK8Ti -[orig_h=141.142.220.118, orig_p=45000/udp, resp_h=141.142.2.2, resp_p=53/udp], N6rbUGwigQ7 -[orig_h=141.142.220.118, orig_p=48479/udp, resp_h=141.142.2.2, resp_p=53/udp], 8b9q7qPtzhd -[orig_h=141.142.220.118, orig_p=48128/udp, resp_h=141.142.2.2, resp_p=53/udp], KOdlL7sC9z2 -[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp], hvOo97vj60k -[orig_h=141.142.220.118, orig_p=56056/udp, resp_h=141.142.2.2, resp_p=53/udp], FHu81uYujA9 -[orig_h=141.142.220.118, orig_p=55092/udp, resp_h=141.142.2.2, resp_p=53/udp], 2M1wDTa0C7a -[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp], OKiJdtzKWPk -[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp], UZkBBvjF0r8 -[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp], svqqNKN9CFj -[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp], OldlyspNIr7 -[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp], j5w2LueK8Ti -[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp], OPM7xFSDNw3 -[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp], hvOo97vj60k -[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp], OKiJdtzKWPk -[orig_h=173.192.163.128, orig_p=80/tcp, resp_h=141.142.220.235, resp_p=6705/tcp], tpUWfNdSLE -[orig_h=141.142.220.44, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], ra1C6ZLut4b -[orig_h=141.142.220.226, orig_p=137/udp, resp_h=141.142.220.255, resp_p=137/udp], UElDH5b9qA5 -[orig_h=141.142.220.226, orig_p=55131/udp, resp_h=224.0.0.252, resp_p=5355/udp], sO3mBXBav1h -[orig_h=141.142.220.226, orig_p=55671/udp, resp_h=224.0.0.252, resp_p=5355/udp], xAQqZE8Wdp4 -[orig_h=141.142.220.238, orig_p=56641/udp, resp_h=141.142.220.255, resp_p=137/udp], zVecVnfOlsf diff --git a/testing/btest/Baseline/core.disable-mobile-ipv6/output b/testing/btest/Baseline/core.disable-mobile-ipv6/output new file mode 100644 index 0000000000..b156353f74 --- /dev/null +++ b/testing/btest/Baseline/core.disable-mobile-ipv6/output @@ -0,0 +1 @@ +1333663011.602839 weird: unknown_protocol_135 diff --git a/testing/btest/Baseline/core.discarder/output b/testing/btest/Baseline/core.discarder/output new file mode 100644 index 0000000000..82b4b3e622 --- /dev/null +++ b/testing/btest/Baseline/core.discarder/output @@ -0,0 +1,24 @@ +################ IP Discarder ################ +[orig_h=141.142.220.118, orig_p=35634/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35634/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +################ TCP Discarder ################ +[orig_h=141.142.220.118, orig_p=48649/tcp, resp_h=208.80.152.118, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49996/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49997/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49998/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=49999/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=50000/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=50001/tcp, resp_h=208.80.152.3, resp_p=80/tcp] +[orig_h=141.142.220.118, orig_p=35642/tcp, resp_h=208.80.152.2, resp_p=80/tcp] +################ UDP Discarder ################ +[orig_h=fe80::217:f2ff:fed7:cf65, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp] +[orig_h=fe80::3074:17d5:2052:c324, orig_p=65373/udp, resp_h=ff02::1:3, resp_p=5355/udp] +[orig_h=fe80::3074:17d5:2052:c324, orig_p=65373/udp, resp_h=ff02::1:3, resp_p=5355/udp] +[orig_h=fe80::3074:17d5:2052:c324, orig_p=54213/udp, resp_h=ff02::1:3, resp_p=5355/udp] +[orig_h=fe80::3074:17d5:2052:c324, orig_p=54213/udp, resp_h=ff02::1:3, resp_p=5355/udp] +################ ICMP Discarder ################ +Discard icmp packet: [icmp_type=3] diff --git a/testing/btest/Baseline/core.dns-init/output b/testing/btest/Baseline/core.dns-init/output new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/Baseline/core.expr-exception/reporter.log b/testing/btest/Baseline/core.expr-exception/reporter.log new file mode 100644 index 0000000000..3767de37d8 --- /dev/null +++ b/testing/btest/Baseline/core.expr-exception/reporter.log @@ -0,0 +1,16 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path reporter +#fields ts level message location +#types time enum string string +1300475168.783842 Reporter::ERROR field value missing [c$ftp] /Users/robin/bro/master/testing/btest/.tmp/core.expr-exception/expr-exception.bro, line 8 +1300475168.915940 Reporter::ERROR field value missing [c$ftp] /Users/robin/bro/master/testing/btest/.tmp/core.expr-exception/expr-exception.bro, line 8 +1300475168.916118 Reporter::ERROR field value missing [c$ftp] /Users/robin/bro/master/testing/btest/.tmp/core.expr-exception/expr-exception.bro, line 8 +1300475168.918295 Reporter::ERROR field value missing [c$ftp] /Users/robin/bro/master/testing/btest/.tmp/core.expr-exception/expr-exception.bro, line 8 +1300475168.952193 Reporter::ERROR field value missing [c$ftp] /Users/robin/bro/master/testing/btest/.tmp/core.expr-exception/expr-exception.bro, line 8 +1300475168.952228 Reporter::ERROR field value missing [c$ftp] /Users/robin/bro/master/testing/btest/.tmp/core.expr-exception/expr-exception.bro, line 8 +1300475168.954761 Reporter::ERROR field value missing [c$ftp] /Users/robin/bro/master/testing/btest/.tmp/core.expr-exception/expr-exception.bro, line 8 +1300475168.962628 Reporter::ERROR field value missing [c$ftp] /Users/robin/bro/master/testing/btest/.tmp/core.expr-exception/expr-exception.bro, line 8 +1300475169.780331 Reporter::ERROR field value missing [c$ftp] /Users/robin/bro/master/testing/btest/.tmp/core.expr-exception/expr-exception.bro, line 8 diff --git a/testing/btest/Baseline/core.icmp.icmp-context/output b/testing/btest/Baseline/core.icmp.icmp-context/output new file mode 100644 index 0000000000..9e252d8c38 --- /dev/null +++ b/testing/btest/Baseline/core.icmp.icmp-context/output @@ -0,0 +1,12 @@ +icmp_unreachable (code=0) + conn_id: [orig_h=10.0.0.1, orig_p=3/icmp, resp_h=10.0.0.2, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=10.0.0.2, itype=3, icode=0, len=0, v6=F] + icmp_context: [id=[orig_h=::, orig_p=0/unknown, resp_h=::, resp_p=0/unknown], len=0, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F] +icmp_unreachable (code=0) + conn_id: [orig_h=10.0.0.1, orig_p=3/icmp, resp_h=10.0.0.2, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=10.0.0.2, itype=3, icode=0, len=20, v6=F] + icmp_context: [id=[orig_h=10.0.0.2, orig_p=0/unknown, resp_h=10.0.0.1, resp_p=0/unknown], len=20, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F] +icmp_unreachable (code=3) + conn_id: [orig_h=192.168.1.102, orig_p=3/icmp, resp_h=192.168.1.1, resp_p=3/icmp] + icmp_conn: [orig_h=192.168.1.102, resp_h=192.168.1.1, itype=3, icode=3, len=148, v6=F] + icmp_context: [id=[orig_h=192.168.1.1, orig_p=53/udp, resp_h=192.168.1.102, resp_p=59207/udp], len=163, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] diff --git a/testing/btest/Baseline/core.icmp.icmp-events/output b/testing/btest/Baseline/core.icmp.icmp-events/output new file mode 100644 index 0000000000..9d8f484921 --- /dev/null +++ b/testing/btest/Baseline/core.icmp.icmp-events/output @@ -0,0 +1,20 @@ +icmp_unreachable (code=3) + conn_id: [orig_h=192.168.1.102, orig_p=3/icmp, resp_h=192.168.1.1, resp_p=3/icmp] + icmp_conn: [orig_h=192.168.1.102, resp_h=192.168.1.1, itype=3, icode=3, len=148, v6=F] + icmp_context: [id=[orig_h=192.168.1.1, orig_p=53/udp, resp_h=192.168.1.102, resp_p=59207/udp], len=163, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_time_exceeded (code=0) + conn_id: [orig_h=10.0.0.1, orig_p=11/icmp, resp_h=10.0.0.2, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=10.0.0.2, itype=11, icode=0, len=32, v6=F] + icmp_context: [id=[orig_h=10.0.0.2, orig_p=30000/udp, resp_h=10.0.0.1, resp_p=13000/udp], len=32, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_echo_request (id=34844, seq=0, payload=O\x85\xe0C\0^N\xeb\xff^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./01234567) + conn_id: [orig_h=10.0.0.1, orig_p=8/icmp, resp_h=74.125.225.99, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=74.125.225.99, itype=8, icode=0, len=56, v6=F] +icmp_echo_reply (id=34844, seq=0, payload=O\x85\xe0C\0^N\xeb\xff^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./01234567) + conn_id: [orig_h=10.0.0.1, orig_p=8/icmp, resp_h=74.125.225.99, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=74.125.225.99, itype=8, icode=0, len=56, v6=F] +icmp_echo_request (id=34844, seq=1, payload=O\x85\xe0D\0^N\xf0}^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./01234567) + conn_id: [orig_h=10.0.0.1, orig_p=8/icmp, resp_h=74.125.225.99, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=74.125.225.99, itype=8, icode=0, len=56, v6=F] +icmp_echo_reply (id=34844, seq=1, payload=O\x85\xe0D\0^N\xf0}^H^I^J^K^L^M^N^O^P^Q^R^S^T^U^V^W^X^Y^Z\x1b\x1c\x1d\x1e\x1f !"#$%&'()*+,-./01234567) + conn_id: [orig_h=10.0.0.1, orig_p=8/icmp, resp_h=74.125.225.99, resp_p=0/icmp] + icmp_conn: [orig_h=10.0.0.1, resp_h=74.125.225.99, itype=8, icode=0, len=56, v6=F] diff --git a/testing/btest/Baseline/core.icmp.icmp6-context/output b/testing/btest/Baseline/core.icmp.icmp6-context/output new file mode 100644 index 0000000000..4b75210a18 --- /dev/null +++ b/testing/btest/Baseline/core.icmp.icmp6-context/output @@ -0,0 +1,16 @@ +icmp_unreachable (code=0) + conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=0, v6=T] + icmp_context: [id=[orig_h=::, orig_p=0/unknown, resp_h=::, resp_p=0/unknown], len=0, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F] +icmp_unreachable (code=0) + conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=40, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=0/unknown, resp_h=fe80::dead, resp_p=0/unknown], len=48, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F] +icmp_unreachable (code=0) + conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=60, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=60, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_unreachable (code=0) + conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=48, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=0/unknown, resp_h=fe80::dead, resp_p=0/unknown], len=48, proto=0, frag_offset=0, bad_hdr_len=T, bad_checksum=F, MF=F, DF=F] diff --git a/testing/btest/Baseline/core.icmp.icmp6-events/output b/testing/btest/Baseline/core.icmp.icmp6-events/output new file mode 100644 index 0000000000..1ff26ff889 --- /dev/null +++ b/testing/btest/Baseline/core.icmp.icmp6-events/output @@ -0,0 +1,55 @@ +icmp_unreachable (code=0) + conn_id: [orig_h=fe80::dead, orig_p=1/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=1, icode=0, len=60, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=60, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_packet_too_big (code=0) + conn_id: [orig_h=fe80::dead, orig_p=2/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=2, icode=0, len=52, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=52, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_time_exceeded (code=0) + conn_id: [orig_h=fe80::dead, orig_p=3/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=3, icode=0, len=52, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=52, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_parameter_problem (code=0) + conn_id: [orig_h=fe80::dead, orig_p=4/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=4, icode=0, len=52, v6=T] + icmp_context: [id=[orig_h=fe80::beef, orig_p=30000/udp, resp_h=fe80::dead, resp_p=13000/udp], len=52, proto=2, frag_offset=0, bad_hdr_len=F, bad_checksum=F, MF=F, DF=F] +icmp_echo_request (id=1, seq=3, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_reply (id=1, seq=3, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_request (id=1, seq=4, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_reply (id=1, seq=4, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_request (id=1, seq=5, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_reply (id=1, seq=5, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_request (id=1, seq=6, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_echo_reply (id=1, seq=6, payload=abcdefghijklmnopqrstuvwabcdefghi) + conn_id: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, orig_p=128/icmp, resp_h=2001:4860:8006::63, resp_p=129/icmp] + icmp_conn: [orig_h=2620:0:e00:400e:d1d:db37:beb:5aac, resp_h=2001:4860:8006::63, itype=128, icode=0, len=32, v6=T] +icmp_redirect (tgt=fe80::cafe, dest=fe80::babe) + conn_id: [orig_h=fe80::dead, orig_p=137/icmp, resp_h=fe80::beef, resp_p=0/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=137, icode=0, len=32, v6=T] +icmp_router_advertisement (hop_limit=0, managed=F, rlifetime=1800, reachable=0.000000, retrans=0.000000) + conn_id: [orig_h=fe80::dead, orig_p=134/icmp, resp_h=fe80::beef, resp_p=133/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=134, icode=0, len=8, v6=T] +icmp_neighbor_advertisement (tgt=fe80::babe) + conn_id: [orig_h=fe80::dead, orig_p=136/icmp, resp_h=fe80::beef, resp_p=135/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=136, icode=0, len=16, v6=T] +icmp_router_solicitation + conn_id: [orig_h=fe80::dead, orig_p=133/icmp, resp_h=fe80::beef, resp_p=134/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=133, icode=0, len=0, v6=T] +icmp_neighbor_solicitation (tgt=fe80::babe) + conn_id: [orig_h=fe80::dead, orig_p=135/icmp, resp_h=fe80::beef, resp_p=136/icmp] + icmp_conn: [orig_h=fe80::dead, resp_h=fe80::beef, itype=135, icode=0, len=16, v6=T] diff --git a/testing/btest/Baseline/core.ipv6-atomic-frag/output b/testing/btest/Baseline/core.ipv6-atomic-frag/output new file mode 100644 index 0000000000..4a628a4bdc --- /dev/null +++ b/testing/btest/Baseline/core.ipv6-atomic-frag/output @@ -0,0 +1,4 @@ +[orig_h=2001:db8:1::2, orig_p=36951/tcp, resp_h=2001:db8:1::1, resp_p=80/tcp] +[orig_h=2001:db8:1::2, orig_p=59694/tcp, resp_h=2001:db8:1::1, resp_p=80/tcp] +[orig_h=2001:db8:1::2, orig_p=27393/tcp, resp_h=2001:db8:1::1, resp_p=80/tcp] +[orig_h=2001:db8:1::2, orig_p=45805/tcp, resp_h=2001:db8:1::1, resp_p=80/tcp] diff --git a/testing/btest/Baseline/core.ipv6-frag/dns.log b/testing/btest/Baseline/core.ipv6-frag/dns.log new file mode 100644 index 0000000000..251f35d789 --- /dev/null +++ b/testing/btest/Baseline/core.ipv6-frag/dns.log @@ -0,0 +1,9 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dns +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs +#types time string addr port addr port enum count string count string count string count string bool bool bool bool count vector[string] vector[interval] +1331084278.438444 UWkUyAuUGXf 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51850 2607:f740:b::f93 53 udp 3903 txtpadding_323.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT 0 NOERROR T F T F 0 This TXT record should be ignored 1.000000 +1331084293.592245 arKYeMETxOg 2001:470:1f11:81f:d138:5f55:6d4:1fe2 51851 2607:f740:b::f93 53 udp 40849 txtpadding_3230.n1.netalyzr.icsi.berkeley.edu 1 C_INTERNET 16 TXT 0 NOERROR T F T F 0 This TXT record should be ignored 1.000000 diff --git a/testing/btest/Baseline/core.ipv6-frag/output b/testing/btest/Baseline/core.ipv6-frag/output new file mode 100644 index 0000000000..12dfc3a841 --- /dev/null +++ b/testing/btest/Baseline/core.ipv6-frag/output @@ -0,0 +1,5 @@ +ip6=[class=0, flow=0, len=81, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93, exts=[]], udp = [sport=51850/udp, dport=53/udp, ulen=81] +ip6=[class=0, flow=0, len=331, nxt=17, hlim=53, src=2607:f740:b::f93, dst=2001:470:1f11:81f:d138:5f55:6d4:1fe2, exts=[]], udp = [sport=53/udp, dport=51850/udp, ulen=331] +ip6=[class=0, flow=0, len=82, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93, exts=[]], udp = [sport=51851/udp, dport=53/udp, ulen=82] +ip6=[class=0, flow=0, len=82, nxt=17, hlim=64, src=2001:470:1f11:81f:d138:5f55:6d4:1fe2, dst=2607:f740:b::f93, exts=[]], udp = [sport=51851/udp, dport=53/udp, ulen=82] +ip6=[class=0, flow=0, len=3238, nxt=17, hlim=53, src=2607:f740:b::f93, dst=2001:470:1f11:81f:d138:5f55:6d4:1fe2, exts=[]], udp = [sport=53/udp, dport=51851/udp, ulen=3238] diff --git a/testing/btest/Baseline/core.ipv6_esp/output b/testing/btest/Baseline/core.ipv6_esp/output new file mode 100644 index 0000000000..02fb7e154f --- /dev/null +++ b/testing/btest/Baseline/core.ipv6_esp/output @@ -0,0 +1,120 @@ +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=1], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=2], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=3], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=4], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=5], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=6], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=7], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=8], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=9], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::2, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=10], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=1], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=2], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=3], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=4], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=5], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=6], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=7], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=8], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=9], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::3, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=10], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=1], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=2], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=3], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=4], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=5], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=6], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=7], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=8], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=9], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::4, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=10], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=1], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=2], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=3], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=4], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=5], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=6], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=7], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=8], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=9], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::5, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=10], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=1], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=2], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=3], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=4], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=5], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=6], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=7], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=8], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=9], mobility=]]] +[class=0, flow=0, len=116, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::12, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=10, seq=10], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=1], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=2], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=3], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=4], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=5], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=6], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=7], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=8], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=9], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::13, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=11, seq=10], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=1], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=2], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=3], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=4], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=5], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=6], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=7], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=8], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=9], mobility=]]] +[class=0, flow=0, len=100, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::14, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=12, seq=10], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=1], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=2], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=3], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=4], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=5], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=6], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=7], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=8], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=9], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::15, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=13, seq=10], mobility=]]] +[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=1], mobility=]]] +[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=2], mobility=]]] +[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=3], mobility=]]] +[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=4], mobility=]]] +[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=5], mobility=]]] +[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=6], mobility=]]] +[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=7], mobility=]]] +[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=8], mobility=]]] +[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=9], mobility=]]] +[class=0, flow=0, len=104, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::22, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=20, seq=10], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=1], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=2], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=3], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=4], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=5], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=6], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=7], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=8], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=9], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::23, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=21, seq=10], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=1], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=2], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=3], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=4], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=5], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=6], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=7], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=8], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=9], mobility=]]] +[class=0, flow=0, len=88, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::24, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=22, seq=10], mobility=]]] +[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=1], mobility=]]] +[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=2], mobility=]]] +[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=3], mobility=]]] +[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=4], mobility=]]] +[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=5], mobility=]]] +[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=6], mobility=]]] +[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=7], mobility=]]] +[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=8], mobility=]]] +[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=9], mobility=]]] +[class=0, flow=0, len=76, nxt=50, hlim=64, src=3ffe::1, dst=3ffe::25, exts=[[id=50, hopopts=, dstopts=, routing=, fragment=, ah=, esp=[spi=23, seq=10], mobility=]]] diff --git a/testing/btest/Baseline/core.ipv6_ext_headers/output b/testing/btest/Baseline/core.ipv6_ext_headers/output new file mode 100644 index 0000000000..b4cd249371 --- /dev/null +++ b/testing/btest/Baseline/core.ipv6_ext_headers/output @@ -0,0 +1,3 @@ +weird routing0_hdr from 2001:4f8:4:7:2e0:81ff:fe52:ffff to 2001:78:1:32::2 +[orig_h=2001:4f8:4:7:2e0:81ff:fe52:ffff, orig_p=53/udp, resp_h=2001:78:1:32::2, resp_p=53/udp] +[ip=, ip6=[class=0, flow=0, len=59, nxt=0, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=0, hopopts=[nxt=43, len=0, options=[[otype=1, len=4, data=\0\0\0\0]]], dstopts=, routing=, fragment=, ah=, esp=, mobility=], [id=43, hopopts=, dstopts=, routing=[nxt=17, len=4, rtype=0, segleft=2, data=\0\0\0\0 ^A\0x\0^A\02\0\0\0\0\0\0\0^A ^A\0x\0^A\02\0\0\0\0\0\0\0^B], fragment=, ah=, esp=, mobility=]]], tcp=, udp=[sport=53/udp, dport=53/udp, ulen=11], icmp=] diff --git a/testing/btest/Baseline/core.leaks.basic-cluster/manager-1.metrics.log b/testing/btest/Baseline/core.leaks.basic-cluster/manager-1.metrics.log new file mode 100644 index 0000000000..42fcd6a526 --- /dev/null +++ b/testing/btest/Baseline/core.leaks.basic-cluster/manager-1.metrics.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path metrics +#fields ts metric_id filter_name index.host index.str index.network value +#types time enum string addr string subnet count +1331256494.591966 TEST_METRIC foo-bar 6.5.4.3 - - 4 +1331256494.591966 TEST_METRIC foo-bar 7.2.1.5 - - 2 +1331256494.591966 TEST_METRIC foo-bar 1.2.3.4 - - 6 diff --git a/testing/btest/Baseline/core.leaks.remote/sender.test.failure.log b/testing/btest/Baseline/core.leaks.remote/sender.test.failure.log new file mode 100644 index 0000000000..5a26f322f4 --- /dev/null +++ b/testing/btest/Baseline/core.leaks.remote/sender.test.failure.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test.failure +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1331256472.375609 1.2.3.4 1234 2.3.4.5 80 failure US +1331256472.375609 1.2.3.4 1234 2.3.4.5 80 failure UK +1331256472.375609 1.2.3.4 1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/core.leaks.remote/sender.test.log b/testing/btest/Baseline/core.leaks.remote/sender.test.log new file mode 100644 index 0000000000..9d2ba26f48 --- /dev/null +++ b/testing/btest/Baseline/core.leaks.remote/sender.test.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1331256472.375609 1.2.3.4 1234 2.3.4.5 80 success unknown +1331256472.375609 1.2.3.4 1234 2.3.4.5 80 failure US +1331256472.375609 1.2.3.4 1234 2.3.4.5 80 failure UK +1331256472.375609 1.2.3.4 1234 2.3.4.5 80 success BR +1331256472.375609 1.2.3.4 1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/core.leaks.remote/sender.test.success.log b/testing/btest/Baseline/core.leaks.remote/sender.test.success.log new file mode 100644 index 0000000000..1b2ed452a0 --- /dev/null +++ b/testing/btest/Baseline/core.leaks.remote/sender.test.success.log @@ -0,0 +1,9 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test.success +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1331256472.375609 1.2.3.4 1234 2.3.4.5 80 success unknown +1331256472.375609 1.2.3.4 1234 2.3.4.5 80 success BR diff --git a/testing/btest/Baseline/core.mobile-ipv6-home-addr/output b/testing/btest/Baseline/core.mobile-ipv6-home-addr/output new file mode 100644 index 0000000000..88cbe0cb16 --- /dev/null +++ b/testing/btest/Baseline/core.mobile-ipv6-home-addr/output @@ -0,0 +1,2 @@ +[orig_h=2001:78:1:32::1, orig_p=30000/udp, resp_h=2001:4f8:4:7:2e0:81ff:fe52:9a6b, resp_p=13000/udp] +[ip=, ip6=[class=0, flow=0, len=36, nxt=60, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=60, hopopts=, dstopts=[nxt=17, len=2, options=[[otype=1, len=2, data=\0\0], [otype=201, len=16, data= ^A\0x\0^A\02\0\0\0\0\0\0\0^A]]], routing=, fragment=, ah=, esp=, mobility=]]], tcp=, udp=[sport=30000/udp, dport=13000/udp, ulen=12], icmp=] diff --git a/testing/btest/Baseline/core.mobile-ipv6-routing/output b/testing/btest/Baseline/core.mobile-ipv6-routing/output new file mode 100644 index 0000000000..04292caaa7 --- /dev/null +++ b/testing/btest/Baseline/core.mobile-ipv6-routing/output @@ -0,0 +1,2 @@ +[orig_h=2001:4f8:4:7:2e0:81ff:fe52:ffff, orig_p=30000/udp, resp_h=2001:78:1:32::1, resp_p=13000/udp] +[ip=, ip6=[class=0, flow=0, len=36, nxt=43, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=43, hopopts=, dstopts=, routing=[nxt=17, len=2, rtype=2, segleft=1, data=\0\0\0\0 ^A\0x\0^A\02\0\0\0\0\0\0\0^A], fragment=, ah=, esp=, mobility=]]], tcp=, udp=[sport=30000/udp, dport=13000/udp, ulen=12], icmp=] diff --git a/testing/btest/Baseline/core.mobility-checksums/bad.out b/testing/btest/Baseline/core.mobility-checksums/bad.out new file mode 100644 index 0000000000..6ea9955402 --- /dev/null +++ b/testing/btest/Baseline/core.mobility-checksums/bad.out @@ -0,0 +1,3 @@ +1333988844.893456 weird: bad_MH_checksum +1333995733.276730 weird: bad_TCP_checksum +1333995701.656496 weird: bad_UDP_checksum diff --git a/testing/btest/Baseline/core.mobility-checksums/good.out b/testing/btest/Baseline/core.mobility-checksums/good.out new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/Baseline/core.mobility_msg/output b/testing/btest/Baseline/core.mobility_msg/output new file mode 100644 index 0000000000..6f8d6a1699 --- /dev/null +++ b/testing/btest/Baseline/core.mobility_msg/output @@ -0,0 +1,16 @@ +Binding ACK: +[class=0, flow=0, len=16, nxt=135, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=135, hopopts=, dstopts=, routing=, fragment=, ah=, esp=, mobility=[nxt=59, len=1, mh_type=6, rsv=0, chksum=53722, msg=[id=6, brr=, hoti=, coti=, hot=, cot=, bu=, back=[status=0, k=T, seq=42, life=8, options=[[otype=1, len=2, data=\0\0]]], be=]]]]] +Binding Error: +[class=0, flow=0, len=24, nxt=135, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=135, hopopts=, dstopts=, routing=, fragment=, ah=, esp=, mobility=[nxt=59, len=2, mh_type=7, rsv=0, chksum=45272, msg=[id=7, brr=, hoti=, coti=, hot=, cot=, bu=, back=, be=[status=1, hoa=2001:78:1:32::1, options=[]]]]]]] +Binding Refresh Request: +[class=0, flow=0, len=8, nxt=135, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=135, hopopts=, dstopts=, routing=, fragment=, ah=, esp=, mobility=[nxt=59, len=0, mh_type=0, rsv=0, chksum=55703, msg=[id=0, brr=[rsv=0, options=[]], hoti=, coti=, hot=, cot=, bu=, back=, be=]]]]] +Binding Update: +[class=0, flow=0, len=16, nxt=135, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=135, hopopts=, dstopts=, routing=, fragment=, ah=, esp=, mobility=[nxt=59, len=1, mh_type=5, rsv=0, chksum=868, msg=[id=5, brr=, hoti=, coti=, hot=, cot=, bu=[seq=37, a=T, h=T, l=F, k=T, life=3, options=[[otype=1, len=2, data=\0\0]]], back=, be=]]]]] +Care-of Test: +[class=0, flow=0, len=24, nxt=135, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=135, hopopts=, dstopts=, routing=, fragment=, ah=, esp=, mobility=[nxt=59, len=2, mh_type=4, rsv=0, chksum=54378, msg=[id=4, brr=, hoti=, coti=, hot=, cot=[nonce_idx=13, cookie=15, token=255, options=[]], bu=, back=, be=]]]]] +Care-of Test Init: +[class=0, flow=0, len=16, nxt=135, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=135, hopopts=, dstopts=, routing=, fragment=, ah=, esp=, mobility=[nxt=59, len=1, mh_type=2, rsv=0, chksum=55181, msg=[id=2, brr=, hoti=, coti=[rsv=0, cookie=1, options=[]], hot=, cot=, bu=, back=, be=]]]]] +Home Test: +[class=0, flow=0, len=24, nxt=135, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=135, hopopts=, dstopts=, routing=, fragment=, ah=, esp=, mobility=[nxt=59, len=2, mh_type=3, rsv=0, chksum=54634, msg=[id=3, brr=, hoti=, coti=, hot=[nonce_idx=13, cookie=15, token=255, options=[]], cot=, bu=, back=, be=]]]]] +Home Test Init: +[class=0, flow=0, len=16, nxt=135, hlim=64, src=2001:4f8:4:7:2e0:81ff:fe52:ffff, dst=2001:4f8:4:7:2e0:81ff:fe52:9a6b, exts=[[id=135, hopopts=, dstopts=, routing=, fragment=, ah=, esp=, mobility=[nxt=59, len=1, mh_type=1, rsv=0, chksum=55437, msg=[id=1, brr=, hoti=[rsv=0, cookie=1, options=[]], coti=, hot=, cot=, bu=, back=, be=]]]]] diff --git a/testing/btest/Baseline/core.print-bpf-filters-ipv4/conn.log b/testing/btest/Baseline/core.print-bpf-filters-ipv4/conn.log deleted file mode 100644 index a744346519..0000000000 --- a/testing/btest/Baseline/core.print-bpf-filters-ipv4/conn.log +++ /dev/null @@ -1,2 +0,0 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history -1128727435.450898 UWkUyAuUGXf 141.42.64.125 56730 125.190.109.199 80 tcp http 1.73330307006836 98 9417 SF - 0 ShADdFaf diff --git a/testing/btest/Baseline/core.print-bpf-filters-ipv4/output b/testing/btest/Baseline/core.print-bpf-filters-ipv4/output deleted file mode 100644 index 494e1946e7..0000000000 --- a/testing/btest/Baseline/core.print-bpf-filters-ipv4/output +++ /dev/null @@ -1,8 +0,0 @@ -# ts node filter init success -1312570784.336354 - not ip6 F T -# ts node filter init success -1312570784.550594 - (((((((((((((((((((((((port 53) or (tcp port 989)) or (tcp port 443)) or (udp and port 5353)) or (udp and port 5355)) or (tcp port 22)) or (tcp port 995)) or (port 21)) or (tcp port smtp or tcp port 587)) or (port 6667)) or (tcp port 614)) or (tcp port 990)) or (udp port 137)) or (tcp port 993)) or (tcp port 5223)) or (port 514)) or (tcp port 585)) or (tcp port 992)) or (tcp port 563)) or (tcp port 994)) or (tcp port 636)) or (tcp and port (80 or 81 or 631 or 1080 or 3138 or 8000 or 8080 or 8888))) or (port 6666)) and (not ip6) F T -# ts node filter init success -1312570784.765990 - port 42 F T -# ts node filter init success -1312570784.992999 - port 56730 T T diff --git a/testing/btest/Baseline/core.print-bpf-filters-ipv6/conn.log b/testing/btest/Baseline/core.print-bpf-filters-ipv6/conn.log deleted file mode 100644 index e71eff9d57..0000000000 --- a/testing/btest/Baseline/core.print-bpf-filters-ipv6/conn.log +++ /dev/null @@ -1,2 +0,0 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history notice_tags -1128727435.4509 UWkUyAuUGXf 141.42.64.125 56730 125.190.109.199 80 tcp - 1.73330307006836 98 9417 SF - 0 ShADdFaf - diff --git a/testing/btest/Baseline/core.print-bpf-filters-ipv6/output b/testing/btest/Baseline/core.print-bpf-filters-ipv6/output deleted file mode 100644 index 0065fabfd3..0000000000 --- a/testing/btest/Baseline/core.print-bpf-filters-ipv6/output +++ /dev/null @@ -1,8 +0,0 @@ -# ts node filter init success -1308603220.46822 - ip or not ip F T -# ts node filter init success -1308603220.51607 - tcp port 22 F T -# ts node filter init success -1308603220.55432 - port 42 F T -# ts node filter init success -1308603220.59452 - port 56730 T T diff --git a/testing/btest/Baseline/core.print-bpf-filters/conn.log b/testing/btest/Baseline/core.print-bpf-filters/conn.log new file mode 100644 index 0000000000..5ce968d5e6 --- /dev/null +++ b/testing/btest/Baseline/core.print-bpf-filters/conn.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes +#types time string addr port addr port enum string interval count count string bool count string count count count count +1128727435.450898 UWkUyAuUGXf 141.42.64.125 56730 125.190.109.199 80 tcp http 1.733303 98 9417 SF - 0 ShADdFaf 12 730 10 9945 diff --git a/testing/btest/Baseline/core.print-bpf-filters/output b/testing/btest/Baseline/core.print-bpf-filters/output new file mode 100644 index 0000000000..a2bf430fb4 --- /dev/null +++ b/testing/btest/Baseline/core.print-bpf-filters/output @@ -0,0 +1,32 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path packet_filter +#fields ts node filter init success +#types time string string bool bool +1328294052.330721 - ip or not ip T T +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path packet_filter +#fields ts node filter init success +#types time string string bool bool +1328294052.542418 - ((((((((((((((((((((((((port 53) or (tcp port 989)) or (tcp port 443)) or (port 6669)) or (udp and port 5353)) or (port 6668)) or (udp and port 5355)) or (tcp port 22)) or (tcp port 995)) or (port 21)) or (tcp port 25 or tcp port 587)) or (port 6667)) or (tcp port 614)) or (tcp port 990)) or (udp port 137)) or (tcp port 993)) or (tcp port 5223)) or (port 514)) or (tcp port 585)) or (tcp port 992)) or (tcp port 563)) or (tcp port 994)) or (tcp port 636)) or (tcp and port (80 or 81 or 631 or 1080 or 3138 or 8000 or 8080 or 8888))) or (port 6666) T T +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path packet_filter +#fields ts node filter init success +#types time string string bool bool +1328294052.748480 - port 42 T T +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path packet_filter +#fields ts node filter init success +#types time string string bool bool +1328294052.952845 - port 56730 T T diff --git a/testing/btest/Baseline/core.reporter-error-in-handler/output b/testing/btest/Baseline/core.reporter-error-in-handler/output index bfb2880ed4..3d8aa6ff54 100644 --- a/testing/btest/Baseline/core.reporter-error-in-handler/output +++ b/testing/btest/Baseline/core.reporter-error-in-handler/output @@ -1,2 +1,2 @@ -error in /da/home/robin/bro/seth/testing/btest/.tmp/core.reporter-error-in-handler/reporter-error-in-handler.bro, line 22: no such index (a[2]) +error in /Users/robin/bro/master/testing/btest/.tmp/core.reporter-error-in-handler/reporter-error-in-handler.bro, line 22: no such index (a[2]) 1st error printed on script level diff --git a/testing/btest/Baseline/core.reporter-fmt-strings/output b/testing/btest/Baseline/core.reporter-fmt-strings/output index 10a883cb5d..4842dd9fc5 100644 --- a/testing/btest/Baseline/core.reporter-fmt-strings/output +++ b/testing/btest/Baseline/core.reporter-fmt-strings/output @@ -1 +1 @@ -error in /Users/jsiwek/tmp/bro/testing/btest/.tmp/core.reporter-fmt-strings/reporter-fmt-strings.bro, line 9: not an event (dont_interpret_this(%s)) +error in /Users/robin/bro/master/testing/btest/.tmp/core.reporter-fmt-strings/reporter-fmt-strings.bro, line 9: not an event (dont_interpret_this(%s)) diff --git a/testing/btest/Baseline/core.reporter-parse-error/output b/testing/btest/Baseline/core.reporter-parse-error/output index ca0bc9304b..7606fe5667 100644 --- a/testing/btest/Baseline/core.reporter-parse-error/output +++ b/testing/btest/Baseline/core.reporter-parse-error/output @@ -1 +1 @@ -error in /da/home/robin/bro/seth/testing/btest/.tmp/core.reporter-parse-error/reporter-parse-error.bro, line 7: unknown identifier TESTFAILURE, at or near "TESTFAILURE" +error in /Users/robin/bro/master/testing/btest/.tmp/core.reporter-parse-error/reporter-parse-error.bro, line 7: unknown identifier TESTFAILURE, at or near "TESTFAILURE" diff --git a/testing/btest/Baseline/core.reporter-runtime-error/output b/testing/btest/Baseline/core.reporter-runtime-error/output index 5c0feedf42..3a96954101 100644 --- a/testing/btest/Baseline/core.reporter-runtime-error/output +++ b/testing/btest/Baseline/core.reporter-runtime-error/output @@ -1 +1 @@ -error in /Users/seth/bro.git9/testing/btest/.tmp/core.reporter-runtime-error/reporter-runtime-error.bro, line 12: no such index (a[1]) +error in /Users/robin/bro/master/testing/btest/.tmp/core.reporter-runtime-error/reporter-runtime-error.bro, line 12: no such index (a[1]) diff --git a/testing/btest/Baseline/core.reporter-type-mismatch/output b/testing/btest/Baseline/core.reporter-type-mismatch/output index 6211752225..4c038ea8c5 100644 --- a/testing/btest/Baseline/core.reporter-type-mismatch/output +++ b/testing/btest/Baseline/core.reporter-type-mismatch/output @@ -1,3 +1,3 @@ -error in string and /da/home/robin/bro/seth/testing/btest/.tmp/core.reporter-type-mismatch/reporter-type-mismatch.bro, line 11: arithmetic mixed with non-arithmetic (string and 42) -error in /da/home/robin/bro/seth/testing/btest/.tmp/core.reporter-type-mismatch/reporter-type-mismatch.bro, line 11 and string: type mismatch (42 and string) -error in /da/home/robin/bro/seth/testing/btest/.tmp/core.reporter-type-mismatch/reporter-type-mismatch.bro, line 11: argument type mismatch in event invocation (foo(42)) +error in string and /Users/robin/bro/master/testing/btest/.tmp/core.reporter-type-mismatch/reporter-type-mismatch.bro, line 11: arithmetic mixed with non-arithmetic (string and 42) +error in /Users/robin/bro/master/testing/btest/.tmp/core.reporter-type-mismatch/reporter-type-mismatch.bro, line 11 and string: type mismatch (42 and string) +error in /Users/robin/bro/master/testing/btest/.tmp/core.reporter-type-mismatch/reporter-type-mismatch.bro, line 11: argument type mismatch in event invocation (foo(42)) diff --git a/testing/btest/Baseline/core.reporter/logger-test.log b/testing/btest/Baseline/core.reporter/logger-test.log index 6f7ba1d8c7..bc2abd142a 100644 --- a/testing/btest/Baseline/core.reporter/logger-test.log +++ b/testing/btest/Baseline/core.reporter/logger-test.log @@ -1,6 +1,6 @@ -reporter_info|init test-info|/da/home/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 8|0.000000 -reporter_warning|init test-warning|/da/home/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 9|0.000000 -reporter_error|init test-error|/da/home/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 10|0.000000 -reporter_info|done test-info|/da/home/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 15|0.000000 -reporter_warning|done test-warning|/da/home/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 16|0.000000 -reporter_error|done test-error|/da/home/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 17|0.000000 +reporter_info|init test-info|/Users/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 8|0.000000 +reporter_warning|init test-warning|/Users/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 9|0.000000 +reporter_error|init test-error|/Users/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 10|0.000000 +reporter_info|done test-info|/Users/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 15|0.000000 +reporter_warning|done test-warning|/Users/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 16|0.000000 +reporter_error|done test-error|/Users/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 17|0.000000 diff --git a/testing/btest/Baseline/core.reporter/output b/testing/btest/Baseline/core.reporter/output index 2735adc931..185cabb1eb 100644 --- a/testing/btest/Baseline/core.reporter/output +++ b/testing/btest/Baseline/core.reporter/output @@ -1,3 +1,3 @@ -/da/home/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 52: pre test-info -warning in /da/home/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 53: pre test-warning -error in /da/home/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 54: pre test-error +/Users/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 52: pre test-info +warning in /Users/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 53: pre test-warning +error in /Users/robin/bro/master/testing/btest/.tmp/core.reporter/reporter.bro, line 54: pre test-error diff --git a/testing/btest/Baseline/core.truncation/output b/testing/btest/Baseline/core.truncation/output new file mode 100644 index 0000000000..ba8d3eedee --- /dev/null +++ b/testing/btest/Baseline/core.truncation/output @@ -0,0 +1,3 @@ +1334160095.895421 weird: truncated_IP +1334156241.519125 weird: truncated_IP +1334094648.590126 weird: truncated_IP diff --git a/testing/btest/Baseline/core.vlan-mpls/conn.log b/testing/btest/Baseline/core.vlan-mpls/conn.log index 1d46bd7ab1..f3c958ea99 100644 --- a/testing/btest/Baseline/core.vlan-mpls/conn.log +++ b/testing/btest/Baseline/core.vlan-mpls/conn.log @@ -1,4 +1,10 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history -952109346.874907 UWkUyAuUGXf 10.1.2.1 11001 10.34.0.1 23 tcp - 2.10255992412567 25 0 SH - 0 - -1128727435.450898 56gKBmhBBB6 141.42.64.125 56730 125.190.109.199 80 tcp http 1.73330307006836 98 9417 SF - 0 ShADdFaf -1278600802.069419 50da4BEzauh 10.20.80.1 50343 10.0.0.15 80 tcp - 0.00415205955505371 9 3429 SF - 0 ShADadfF +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes +#types time string addr port addr port enum string interval count count string bool count string count count count count +952109346.874907 UWkUyAuUGXf 10.1.2.1 11001 10.34.0.1 23 tcp - 2.102560 26 0 SH - 0 SADF 11 470 0 0 +1128727435.450898 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 tcp http 1.733303 98 9417 SF - 0 ShADdFaf 12 730 10 9945 +1278600802.069419 k6kgXLOoSKl 10.20.80.1 50343 10.0.0.15 80 tcp - 0.004152 9 3429 SF - 0 ShADadfF 7 381 7 3801 diff --git a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log new file mode 100644 index 0000000000..d43367f300 --- /dev/null +++ b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log @@ -0,0 +1,22 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path loaded_scripts +#fields name +#types string +scripts/base/init-bare.bro + build/src/base/const.bif.bro + build/src/base/types.bif.bro + build/src/base/strings.bif.bro + build/src/base/bro.bif.bro + build/src/base/reporter.bif.bro + build/src/base/event.bif.bro + scripts/base/frameworks/logging/__load__.bro + scripts/base/frameworks/logging/./main.bro + build/src/base/logging.bif.bro + scripts/base/frameworks/logging/./postprocessors/__load__.bro + scripts/base/frameworks/logging/./postprocessors/./scp.bro + scripts/base/frameworks/logging/./postprocessors/./sftp.bro + scripts/base/frameworks/logging/./writers/ascii.bro +scripts/policy/misc/loaded-scripts.bro diff --git a/testing/btest/Baseline/coverage.bare-mode-errors/unique_errors b/testing/btest/Baseline/coverage.bare-mode-errors/unique_errors new file mode 100644 index 0000000000..e69de29bb2 diff --git a/testing/btest/Baseline/coverage.coverage-blacklist/output b/testing/btest/Baseline/coverage.coverage-blacklist/output new file mode 100644 index 0000000000..6d3d243220 --- /dev/null +++ b/testing/btest/Baseline/coverage.coverage-blacklist/output @@ -0,0 +1,5 @@ +1 /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/coverage.coverage-blacklist/coverage-blacklist.bro, line 13 print cover me; +1 /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/coverage.coverage-blacklist/coverage-blacklist.bro, line 17 print always executed; +0 /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/coverage.coverage-blacklist/coverage-blacklist.bro, line 26 print also impossible, but included in code coverage analysis; +1 /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/coverage.coverage-blacklist/coverage-blacklist.bro, line 29 print success; +1 /Users/jsiwek/Projects/bro/bro/testing/btest/.tmp/coverage.coverage-blacklist/coverage-blacklist.bro, line 5 print first; diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log new file mode 100644 index 0000000000..92deb62edb --- /dev/null +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -0,0 +1,97 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path loaded_scripts +#fields name +#types string +scripts/base/init-bare.bro + build/src/base/const.bif.bro + build/src/base/types.bif.bro + build/src/base/strings.bif.bro + build/src/base/bro.bif.bro + build/src/base/reporter.bif.bro + build/src/base/event.bif.bro + scripts/base/frameworks/logging/__load__.bro + scripts/base/frameworks/logging/./main.bro + build/src/base/logging.bif.bro + scripts/base/frameworks/logging/./postprocessors/__load__.bro + scripts/base/frameworks/logging/./postprocessors/./scp.bro + scripts/base/frameworks/logging/./postprocessors/./sftp.bro + scripts/base/frameworks/logging/./writers/ascii.bro +scripts/base/init-default.bro + scripts/base/utils/site.bro + scripts/base/utils/./patterns.bro + scripts/base/utils/addrs.bro + scripts/base/utils/conn-ids.bro + scripts/base/utils/directions-and-hosts.bro + scripts/base/utils/files.bro + scripts/base/utils/numbers.bro + scripts/base/utils/paths.bro + scripts/base/utils/strings.bro + scripts/base/utils/thresholds.bro + scripts/base/frameworks/notice/__load__.bro + scripts/base/frameworks/notice/./main.bro + scripts/base/frameworks/notice/./weird.bro + scripts/base/frameworks/notice/./actions/drop.bro + scripts/base/frameworks/notice/./actions/email_admin.bro + scripts/base/frameworks/notice/./actions/page.bro + scripts/base/frameworks/notice/./actions/add-geodata.bro + scripts/base/frameworks/notice/./extend-email/hostnames.bro + scripts/base/frameworks/cluster/__load__.bro + scripts/base/frameworks/cluster/./main.bro + scripts/base/frameworks/control/__load__.bro + scripts/base/frameworks/control/./main.bro + scripts/base/frameworks/notice/./actions/pp-alarms.bro + scripts/base/frameworks/dpd/__load__.bro + scripts/base/frameworks/dpd/./main.bro + scripts/base/frameworks/signatures/__load__.bro + scripts/base/frameworks/signatures/./main.bro + scripts/base/frameworks/packet-filter/__load__.bro + scripts/base/frameworks/packet-filter/./main.bro + scripts/base/frameworks/packet-filter/./netstats.bro + scripts/base/frameworks/software/__load__.bro + scripts/base/frameworks/software/./main.bro + scripts/base/frameworks/communication/__load__.bro + scripts/base/frameworks/communication/./main.bro + scripts/base/frameworks/metrics/__load__.bro + scripts/base/frameworks/metrics/./main.bro + scripts/base/frameworks/metrics/./non-cluster.bro + scripts/base/frameworks/intel/__load__.bro + scripts/base/frameworks/intel/./main.bro + scripts/base/frameworks/reporter/__load__.bro + scripts/base/frameworks/reporter/./main.bro + scripts/base/protocols/conn/__load__.bro + scripts/base/protocols/conn/./main.bro + scripts/base/protocols/conn/./contents.bro + scripts/base/protocols/conn/./inactivity.bro + scripts/base/protocols/dns/__load__.bro + scripts/base/protocols/dns/./consts.bro + scripts/base/protocols/dns/./main.bro + scripts/base/protocols/ftp/__load__.bro + scripts/base/protocols/ftp/./utils-commands.bro + scripts/base/protocols/ftp/./main.bro + scripts/base/protocols/ftp/./file-extract.bro + scripts/base/protocols/http/__load__.bro + scripts/base/protocols/http/./main.bro + scripts/base/protocols/http/./utils.bro + scripts/base/protocols/http/./file-ident.bro + scripts/base/protocols/http/./file-hash.bro + scripts/base/protocols/http/./file-extract.bro + scripts/base/protocols/irc/__load__.bro + scripts/base/protocols/irc/./main.bro + scripts/base/protocols/irc/./dcc-send.bro + scripts/base/protocols/smtp/__load__.bro + scripts/base/protocols/smtp/./main.bro + scripts/base/protocols/smtp/./entities.bro + scripts/base/protocols/smtp/./entities-excerpt.bro + scripts/base/protocols/ssh/__load__.bro + scripts/base/protocols/ssh/./main.bro + scripts/base/protocols/ssl/__load__.bro + scripts/base/protocols/ssl/./consts.bro + scripts/base/protocols/ssl/./main.bro + scripts/base/protocols/ssl/./mozilla-ca-list.bro + scripts/base/protocols/syslog/__load__.bro + scripts/base/protocols/syslog/./consts.bro + scripts/base/protocols/syslog/./main.bro +scripts/policy/misc/loaded-scripts.bro diff --git a/testing/btest/Baseline/coverage.init-default/missing_loads b/testing/btest/Baseline/coverage.init-default/missing_loads new file mode 100644 index 0000000000..4497bbd185 --- /dev/null +++ b/testing/btest/Baseline/coverage.init-default/missing_loads @@ -0,0 +1,6 @@ +-./frameworks/cluster/nodes/manager.bro +-./frameworks/cluster/nodes/proxy.bro +-./frameworks/cluster/nodes/worker.bro +-./frameworks/cluster/setup-connections.bro +-./frameworks/metrics/cluster.bro +-./frameworks/notice/cluster.bro diff --git a/testing/btest/Baseline/doc.autogen-reST-enums/autogen-reST-enums.rst b/testing/btest/Baseline/doc.autogen-reST-enums/autogen-reST-enums.rst index 519ed708d5..8bd6286c24 100644 --- a/testing/btest/Baseline/doc.autogen-reST-enums/autogen-reST-enums.rst +++ b/testing/btest/Baseline/doc.autogen-reST-enums/autogen-reST-enums.rst @@ -1,14 +1,15 @@ .. Automatically generated. Do not edit. +:tocdepth: 3 + autogen-reST-enums.bro ====================== -:download:`Original Source File ` -Overview --------- +:Source File: :download:`autogen-reST-enums.bro` + Summary ~~~~~~~ Types @@ -27,10 +28,10 @@ Redefinitions :bro:type:`TestEnum1`: :bro:type:`enum` now with a comma ======================================= ======================= -Public Interface ----------------- +Detailed Interface +~~~~~~~~~~~~~~~~~~ Types -~~~~~ +##### .. bro:type:: TestEnum1 :Type: :bro:type:`enum` @@ -74,7 +75,7 @@ Types The final comma is optional Redefinitions -~~~~~~~~~~~~~ +############# :bro:type:`TestEnum1` :Type: :bro:type:`enum` diff --git a/testing/btest/Baseline/doc.autogen-reST-example/example.rst b/testing/btest/Baseline/doc.autogen-reST-example/example.rst index ec48477d61..bee8658e14 100644 --- a/testing/btest/Baseline/doc.autogen-reST-example/example.rst +++ b/testing/btest/Baseline/doc.autogen-reST-example/example.rst @@ -1,35 +1,32 @@ .. Automatically generated. Do not edit. +:tocdepth: 3 + example.bro =========== +.. bro:namespace:: Example -:download:`Original Source File ` - -Overview --------- -This is an example script that demonstrates how to document. Comments -of the form ``##!`` are for the script summary. The contents of +This is an example script that demonstrates documentation features. +Comments of the form ``##!`` are for the script summary. The contents of these comments are transferred directly into the auto-generated `reStructuredText `_ (reST) document's summary section. .. tip:: You can embed directives and roles within ``##``-stylized comments. -A script's logging information has to be documented manually as minimally -shown below. Note that references may not always be possible (e.g. -anonymous filter functions) and a script may not need to document -each of "columns", "event", "filter" depending on exactly what it's doing. +There's also a custom role to reference any identifier node in +the Bro Sphinx domain that's good for "see alsos", e.g. -**Logging Stream ID:** :bro:enum:`Example::EXAMPLE` - :Columns: :bro:type:`Example::Info` - :Event: :bro:id:`Example::log_example` - :Filter: ``example-filter`` - uses :bro:id:`Example::filter_func` to determine whether to - exclude the ``ts`` field +See also: :bro:see:`Example::a_var`, :bro:see:`Example::ONE`, +:bro:see:`SSH::Info` -:Author: Jon Siwek +And a custom directive does the equivalent references: +.. bro:see:: Example::a_var Example::ONE SSH::Info + +:Namespace: ``Example`` :Imports: :doc:`policy/frameworks/software/vulnerable
    ` +:Source File: :download:`example.bro` Summary ~~~~~~~ @@ -38,7 +35,7 @@ Options ============================================================================ ====================================== :bro:id:`Example::an_option`: :bro:type:`set` :bro:attr:`&redef` add documentation for "an_option" here -:bro:id:`Example::option_with_init`: :bro:type:`interval` :bro:attr:`&redef` +:bro:id:`Example::option_with_init`: :bro:type:`interval` :bro:attr:`&redef` More docs can be added here. ============================================================================ ====================================== State Variables @@ -72,8 +69,6 @@ Events :bro:id:`Example::log_example`: :bro:type:`event` This is a declaration of an example event that can be used in logging streams and is raised once for each log entry. - -:bro:id:`bro_init`: :bro:type:`event` ================================================= ============================================================= Functions @@ -92,12 +87,8 @@ Redefinitions :bro:type:`Example::SimpleRecord`: :bro:type:`record` document the record extension redef here ===================================================== ======================================== -Namespaces -~~~~~~~~~~ -.. bro:namespace:: Example - Notices -~~~~~~~ +####### :bro:type:`Notice::Type` :Type: :bro:type:`enum` @@ -116,10 +107,32 @@ Notices .. bro:enum:: Example::Notice_Four Notice::Type -Public Interface ----------------- +Configuration Changes +##################### +Port Analysis +^^^^^^^^^^^^^ +Loading this script makes the following changes to :bro:see:`dpd_config`. + +SSL:: + + [ports={ + 443/tcp, + 562/tcp + }] + +Packet Filter +^^^^^^^^^^^^^ +Loading this script makes the following changes to :bro:see:`capture_filters`. + +Filters added:: + + [ssl] = tcp port 443, + [nntps] = tcp port 562 + +Detailed Interface +~~~~~~~~~~~~~~~~~~ Options -~~~~~~~ +####### .. bro:id:: Example::an_option :Type: :bro:type:`set` [:bro:type:`addr`, :bro:type:`addr`, :bro:type:`string`] @@ -134,8 +147,10 @@ Options :Attributes: :bro:attr:`&redef` :Default: ``10.0 msecs`` + More docs can be added here. + State Variables -~~~~~~~~~~~~~~~ +############### .. bro:id:: Example::a_var :Type: :bro:type:`bool` @@ -153,7 +168,7 @@ State Variables :Default: ``"this works"`` Types -~~~~~ +##### .. bro:type:: Example::SimpleEnum :Type: :bro:type:`enum` @@ -216,13 +231,14 @@ Types An example record to be used with a logging stream. Events -~~~~~~ +###### .. bro:id:: Example::an_event :Type: :bro:type:`event` (name: :bro:type:`string`) Summarize "an_event" here. Give more details about "an_event" here. + Example::an_event should not be confused as a parameter. :param name: describe the argument here @@ -233,12 +249,8 @@ Events This is a declaration of an example event that can be used in logging streams and is raised once for each log entry. -.. bro:id:: bro_init - - :Type: :bro:type:`event` () - Functions -~~~~~~~~~ +######### .. bro:id:: Example::a_function :Type: :bro:type:`function` (tag: :bro:type:`string`, msg: :bro:type:`string`) : :bro:type:`string` @@ -258,12 +270,12 @@ Functions :returns: describe the return type here Redefinitions -~~~~~~~~~~~~~ +############# :bro:type:`Log::ID` :Type: :bro:type:`enum` - .. bro:enum:: Example::EXAMPLE Log::ID + .. bro:enum:: Example::LOG Log::ID :bro:type:`Example::SimpleEnum` @@ -289,60 +301,3 @@ Redefinitions document the record extension redef here -Port Analysis -------------- -:ref:`More Information ` - -SSL:: - - [ports={ - 443/tcp, - 562/tcp - }] - -Packet Filter -------------- -:ref:`More Information ` - -Filters added:: - - [ssl] = tcp port 443, - [nntps] = tcp port 562 - -Private Interface ------------------ -State Variables -~~~~~~~~~~~~~~~ -.. bro:id:: Example::example_ports - - :Type: :bro:type:`set` [:bro:type:`port`] - :Attributes: :bro:attr:`&redef` - :Default: - - :: - - { - 443/tcp, - 562/tcp - } - -Types -~~~~~ -.. bro:type:: Example::PrivateRecord - - :Type: :bro:type:`record` - - field1: :bro:type:`bool` - - field2: :bro:type:`count` - -Functions -~~~~~~~~~ -.. bro:id:: Example::filter_func - - :Type: :bro:type:`function` (rec: :bro:type:`Example::Info`) : :bro:type:`bool` - -.. bro:id:: Example::function_without_proto - - :Type: :bro:type:`function` (tag: :bro:type:`string`) : :bro:type:`string` - diff --git a/testing/btest/Baseline/doc.autogen-reST-func-params/autogen-reST-func-params.rst b/testing/btest/Baseline/doc.autogen-reST-func-params/autogen-reST-func-params.rst new file mode 100644 index 0000000000..15526f12c7 --- /dev/null +++ b/testing/btest/Baseline/doc.autogen-reST-func-params/autogen-reST-func-params.rst @@ -0,0 +1,58 @@ +.. Automatically generated. Do not edit. + +:tocdepth: 3 + +autogen-reST-func-params.bro +============================ + + + + +:Source File: :download:`autogen-reST-func-params.bro` + +Summary +~~~~~~~ +Types +##### +======================================== = +:bro:type:`test_rec`: :bro:type:`record` +======================================== = + +Functions +######### +===================================== ====================================== +:bro:id:`test_func`: :bro:type:`func` This is a global function declaration. +===================================== ====================================== + +Detailed Interface +~~~~~~~~~~~~~~~~~~ +Types +##### +.. bro:type:: test_rec + + :Type: :bro:type:`record` + + field_func: :bro:type:`function` (i: :bro:type:`int`, j: :bro:type:`int`) : :bro:type:`string` + This is a record field function. + + :param i: First param. + :param j: Second param. + + :returns: A string. + +Functions +######### +.. bro:id:: test_func + + :Type: :bro:type:`function` (i: :bro:type:`int`, j: :bro:type:`int`) : :bro:type:`string` + + This is a global function declaration. + + + :param i: First param. + + :param j: Second param. + + + :returns: A string. + diff --git a/testing/btest/Baseline/doc.autogen-reST-records/autogen-reST-records.rst b/testing/btest/Baseline/doc.autogen-reST-records/autogen-reST-records.rst index f43232f5ea..0344fa265c 100644 --- a/testing/btest/Baseline/doc.autogen-reST-records/autogen-reST-records.rst +++ b/testing/btest/Baseline/doc.autogen-reST-records/autogen-reST-records.rst @@ -1,14 +1,15 @@ .. Automatically generated. Do not edit. +:tocdepth: 3 + autogen-reST-records.bro ======================== -:download:`Original Source File ` -Overview --------- +:Source File: :download:`autogen-reST-records.bro` + Summary ~~~~~~~ Types @@ -19,10 +20,10 @@ Types :bro:type:`TestRecord`: :bro:type:`record` Here's the ways records and record fields can be documented. ============================================ ============================================================ -Public Interface ----------------- +Detailed Interface +~~~~~~~~~~~~~~~~~~ Types -~~~~~ +##### .. bro:type:: SimpleRecord :Type: :bro:type:`record` diff --git a/testing/btest/Baseline/doc.autogen-reST-type-aliases/autogen-reST-type-aliases.rst b/testing/btest/Baseline/doc.autogen-reST-type-aliases/autogen-reST-type-aliases.rst index b24d7a01ab..96a3b9377d 100644 --- a/testing/btest/Baseline/doc.autogen-reST-type-aliases/autogen-reST-type-aliases.rst +++ b/testing/btest/Baseline/doc.autogen-reST-type-aliases/autogen-reST-type-aliases.rst @@ -1,14 +1,15 @@ .. Automatically generated. Do not edit. +:tocdepth: 3 + autogen-reST-type-aliases.bro ============================= -:download:`Original Source File ` -Overview --------- +:Source File: :download:`autogen-reST-type-aliases.bro` + Summary ~~~~~~~ State Variables @@ -28,10 +29,10 @@ Types so this type just creates a cross reference to ``bool``. ============================================ ========================================================================== -Public Interface ----------------- +Detailed Interface +~~~~~~~~~~~~~~~~~~ State Variables -~~~~~~~~~~~~~~~ +############### .. bro:id:: a :Type: :bro:type:`TypeAlias` @@ -45,7 +46,7 @@ State Variables And this should reference a type of ``OtherTypeAlias``. Types -~~~~~ +##### .. bro:type:: TypeAlias :Type: :bro:type:`bool` diff --git a/testing/btest/Baseline/istate.broccoli-ipv6/bro..stdout b/testing/btest/Baseline/istate.broccoli-ipv6/bro..stdout new file mode 100644 index 0000000000..0a7bac52c5 --- /dev/null +++ b/testing/btest/Baseline/istate.broccoli-ipv6/bro..stdout @@ -0,0 +1,9 @@ +handshake done with peer +bro_addr(1.2.3.4) +bro_subnet(10.0.0.0/16) +bro_addr(2607:f8b0:4009:802::1014) +bro_subnet(2607:f8b0::/32) +broccoli_addr(1.2.3.4) +broccoli_subnet(10.0.0.0/16) +broccoli_addr(2607:f8b0:4009:802::1014) +broccoli_subnet(2607:f8b0::/32) diff --git a/testing/btest/Baseline/istate.broccoli-ipv6/broccoli..stdout b/testing/btest/Baseline/istate.broccoli-ipv6/broccoli..stdout new file mode 100644 index 0000000000..481778c98a --- /dev/null +++ b/testing/btest/Baseline/istate.broccoli-ipv6/broccoli..stdout @@ -0,0 +1,6 @@ +Connected to Bro instance at: localhost:47757 +Received bro_addr(1.2.3.4) +Received bro_subnet(10.0.0.0/16) +Received bro_addr(2607:f8b0:4009:802::1014) +Received bro_subnet(2607:f8b0::/32) +Terminating diff --git a/testing/btest/Baseline/istate.broccoli/bro.log b/testing/btest/Baseline/istate.broccoli/bro.log index eeebe944ef..4fbbfc81ae 100644 --- a/testing/btest/Baseline/istate.broccoli/bro.log +++ b/testing/btest/Baseline/istate.broccoli/bro.log @@ -1,3 +1,3 @@ -ping received, seq 0, 1303093042.542125 at src, 1303093042.583423 at dest, -ping received, seq 1, 1303093043.543167 at src, 1303093043.544026 at dest, -ping received, seq 2, 1303093044.544115 at src, 1303093044.545008 at dest, +ping received, seq 0, 1324314397.698781 at src, 1324314397.699240 at dest, +ping received, seq 1, 1324314398.698905 at src, 1324314398.699094 at dest, +ping received, seq 2, 1324314399.699012 at src, 1324314399.699231 at dest, diff --git a/testing/btest/Baseline/istate.events-ssl/receiver.http.log b/testing/btest/Baseline/istate.events-ssl/receiver.http.log index 2e56522dae..1601f8ad3c 100644 --- a/testing/btest/Baseline/istate.events-ssl/receiver.http.log +++ b/testing/btest/Baseline/istate.events-ssl/receiver.http.log @@ -1,2 +1,8 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p method host uri referrer user_agent request_content_length response_content_length status_code status_msg filename tags username password proxied mime_type md5 extraction_file -1310750785.32134 56gKBmhBBB6 141.42.64.125 56730 125.190.109.199 80 GET www.icir.org / - Wget/1.10 - 9130 200 OK - - - - - text/html - - +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1324314406.995958 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - text/html - - diff --git a/testing/btest/Baseline/istate.events-ssl/sender.http.log b/testing/btest/Baseline/istate.events-ssl/sender.http.log index 2e56522dae..1601f8ad3c 100644 --- a/testing/btest/Baseline/istate.events-ssl/sender.http.log +++ b/testing/btest/Baseline/istate.events-ssl/sender.http.log @@ -1,2 +1,8 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p method host uri referrer user_agent request_content_length response_content_length status_code status_msg filename tags username password proxied mime_type md5 extraction_file -1310750785.32134 56gKBmhBBB6 141.42.64.125 56730 125.190.109.199 80 GET www.icir.org / - Wget/1.10 - 9130 200 OK - - - - - text/html - - +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1324314406.995958 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - text/html - - diff --git a/testing/btest/Baseline/istate.events/receiver.http.log b/testing/btest/Baseline/istate.events/receiver.http.log index 38ba563dc7..25a7f289c0 100644 --- a/testing/btest/Baseline/istate.events/receiver.http.log +++ b/testing/btest/Baseline/istate.events/receiver.http.log @@ -1,2 +1,8 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p method host uri referrer user_agent request_content_length response_content_length status_code status_msg filename tags username password proxied mime_type md5 extraction_file -1310750770.8185 56gKBmhBBB6 141.42.64.125 56730 125.190.109.199 80 GET www.icir.org / - Wget/1.10 - 9130 200 OK - - - - - text/html - - +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1324314415.616486 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - text/html - - diff --git a/testing/btest/Baseline/istate.events/sender.http.log b/testing/btest/Baseline/istate.events/sender.http.log index 38ba563dc7..25a7f289c0 100644 --- a/testing/btest/Baseline/istate.events/sender.http.log +++ b/testing/btest/Baseline/istate.events/sender.http.log @@ -1,2 +1,8 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p method host uri referrer user_agent request_content_length response_content_length status_code status_msg filename tags username password proxied mime_type md5 extraction_file -1310750770.8185 56gKBmhBBB6 141.42.64.125 56730 125.190.109.199 80 GET www.icir.org / - Wget/1.10 - 9130 200 OK - - - - - text/html - - +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1324314415.616486 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - text/html - - diff --git a/testing/btest/Baseline/istate.pybroccoli/bro..stdout b/testing/btest/Baseline/istate.pybroccoli/bro..stdout index 1e70711932..70ca69dd98 100644 --- a/testing/btest/Baseline/istate.pybroccoli/bro..stdout +++ b/testing/btest/Baseline/istate.pybroccoli/bro..stdout @@ -1,14 +1,16 @@ ==== atomic -10 2 -1313624487.48817 +1330035434.516896 2.0 mins F 1.5 Servus 5555/tcp 6.7.6.5 +2001:db8:85a3::8a2e:370:7334 192.168.0.0/16 +2001:db8:85a3::/48 ==== record [a=42, b=6.6.7.7] 42, 6.6.7.7 diff --git a/testing/btest/Baseline/istate.pybroccoli/python..stdout.filtered b/testing/btest/Baseline/istate.pybroccoli/python..stdout.filtered index 864a4eb627..5d98e2d759 100644 --- a/testing/btest/Baseline/istate.pybroccoli/python..stdout.filtered +++ b/testing/btest/Baseline/istate.pybroccoli/python..stdout.filtered @@ -1,7 +1,7 @@ ==== atomic a 1 ==== -4L -4 42 42 -1313624487.4889 +1330035434.5180 60.0 True True 3.14 @@ -9,10 +9,12 @@ True True '12345/udp' 12345/udp '1.2.3.4' 1.2.3.4 '22.33.44.0/24' 22.33.44.0/24 +'2607:f8b0:4009:802::1014' 2607:f8b0:4009:802::1014 +'2607:f8b0::/32' 2607:f8b0::/32 ==== atomic a 2 ==== -10L -10 2 2 -1313624487.4882 +1330035434.5169 120.0 False False 1.5 @@ -20,10 +22,12 @@ False False '5555/tcp' 5555/tcp '6.7.6.5' 6.7.6.5 '192.168.0.0/16' 192.168.0.0/16 +'2001:db8:85a3::8a2e:370:7334' 2001:db8:85a3::8a2e:370:7334 +'2001:db8:85a3::/48' 2001:db8:85a3::/48 ==== atomic b 2 ==== -10L -10 2 - 1313624487.4882 + 1330035434.5169 120.0 False False 1.5 @@ -31,6 +35,8 @@ False False 5555/tcp 6.7.6.5 192.168.0.0/16 + 2001:db8:85a3::8a2e:370:7334 + 2001:db8:85a3::/48 ==== record 1 ==== 42L 42 diff --git a/testing/btest/Baseline/language.cross-product-init/output b/testing/btest/Baseline/language.cross-product-init/output index 95794f9179..fcb5e43e67 100644 --- a/testing/btest/Baseline/language.cross-product-init/output +++ b/testing/btest/Baseline/language.cross-product-init/output @@ -1,6 +1,6 @@ { -[bar, 1.2.0.0/19] , -[foo, 5.6.0.0/21] , +[foo, 1.2.0.0/19] , [bar, 5.6.0.0/21] , -[foo, 1.2.0.0/19] +[foo, 5.6.0.0/21] , +[bar, 1.2.0.0/19] } diff --git a/testing/btest/Baseline/language.enum-desc/output b/testing/btest/Baseline/language.enum-desc/output new file mode 100644 index 0000000000..f46cc71693 --- /dev/null +++ b/testing/btest/Baseline/language.enum-desc/output @@ -0,0 +1,4 @@ +ONE +ONE +TEST::TWO +TEST::TWO diff --git a/testing/btest/Baseline/language.enum-scope/output b/testing/btest/Baseline/language.enum-scope/output index f2ad6c76f0..84705950d9 100644 --- a/testing/btest/Baseline/language.enum-scope/output +++ b/testing/btest/Baseline/language.enum-scope/output @@ -1 +1 @@ -c +test::c diff --git a/testing/btest/Baseline/language.expire_func/output b/testing/btest/Baseline/language.expire_func/output new file mode 100644 index 0000000000..91cd2bad16 --- /dev/null +++ b/testing/btest/Baseline/language.expire_func/output @@ -0,0 +1,378 @@ +{ +[orig_h=172.16.238.1, orig_p=49656/tcp, resp_h=172.16.238.131, resp_p=22/tcp], +i, +here, +am +} +{ +[orig_h=172.16.238.1, orig_p=49656/tcp, resp_h=172.16.238.131, resp_p=22/tcp], +i, +[orig_h=172.16.238.131, orig_p=37975/udp, resp_h=172.16.238.2, resp_p=53/udp], +here, +am +} +{ +[orig_h=172.16.238.1, orig_p=49656/tcp, resp_h=172.16.238.131, resp_p=22/tcp], +i, +[orig_h=172.16.238.131, orig_p=37975/udp, resp_h=172.16.238.2, resp_p=53/udp], +here, +[orig_h=fe80::20c:29ff:febd:6f01, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp], +am +} +{ +[orig_h=172.16.238.131, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], +[orig_h=172.16.238.1, orig_p=49656/tcp, resp_h=172.16.238.131, resp_p=22/tcp], +i, +[orig_h=172.16.238.131, orig_p=37975/udp, resp_h=172.16.238.2, resp_p=53/udp], +here, +[orig_h=fe80::20c:29ff:febd:6f01, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp], +am +} +{ +[orig_h=172.16.238.131, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], +[orig_h=172.16.238.1, orig_p=49656/tcp, resp_h=172.16.238.131, resp_p=22/tcp], +i, +[orig_h=172.16.238.131, orig_p=37975/udp, resp_h=172.16.238.2, resp_p=53/udp], +here, +[orig_h=fe80::20c:29ff:febd:6f01, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp], +[orig_h=172.16.238.1, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], +am +} +{ +[orig_h=172.16.238.131, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], +[orig_h=172.16.238.1, orig_p=49656/tcp, resp_h=172.16.238.131, resp_p=22/tcp], +i, +[orig_h=172.16.238.131, orig_p=37975/udp, resp_h=172.16.238.2, resp_p=53/udp], +here, +[orig_h=172.16.238.1, orig_p=49657/tcp, resp_h=172.16.238.131, resp_p=80/tcp], +[orig_h=fe80::20c:29ff:febd:6f01, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp], +[orig_h=172.16.238.1, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], +am +} +{ +[orig_h=172.16.238.131, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], +[orig_h=172.16.238.1, orig_p=49656/tcp, resp_h=172.16.238.131, resp_p=22/tcp], +i, +[orig_h=172.16.238.131, orig_p=37975/udp, resp_h=172.16.238.2, resp_p=53/udp], +here, +[orig_h=172.16.238.1, orig_p=49657/tcp, resp_h=172.16.238.131, resp_p=80/tcp], +[orig_h=172.16.238.1, orig_p=49658/tcp, resp_h=172.16.238.131, resp_p=80/tcp], +[orig_h=fe80::20c:29ff:febd:6f01, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp], +[orig_h=172.16.238.1, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], +am +} +{ +[orig_h=172.16.238.131, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], +[orig_h=172.16.238.1, orig_p=17500/udp, resp_h=172.16.238.255, resp_p=17500/udp], +[orig_h=172.16.238.1, orig_p=49656/tcp, resp_h=172.16.238.131, resp_p=22/tcp], +i, +[orig_h=172.16.238.131, orig_p=37975/udp, resp_h=172.16.238.2, resp_p=53/udp], +here, +[orig_h=172.16.238.1, orig_p=49657/tcp, resp_h=172.16.238.131, resp_p=80/tcp], +[orig_h=172.16.238.1, orig_p=49658/tcp, resp_h=172.16.238.131, resp_p=80/tcp], +[orig_h=fe80::20c:29ff:febd:6f01, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp], +[orig_h=172.16.238.1, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp], +am +} +expired [orig_h=172.16.238.131, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp] +expired [orig_h=172.16.238.1, orig_p=17500/udp, resp_h=172.16.238.255, resp_p=17500/udp] +expired [orig_h=172.16.238.1, orig_p=49656/tcp, resp_h=172.16.238.131, resp_p=22/tcp] +expired i +expired [orig_h=172.16.238.131, orig_p=37975/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired here +expired [orig_h=172.16.238.1, orig_p=49657/tcp, resp_h=172.16.238.131, resp_p=80/tcp] +expired [orig_h=172.16.238.1, orig_p=49658/tcp, resp_h=172.16.238.131, resp_p=80/tcp] +expired [orig_h=fe80::20c:29ff:febd:6f01, orig_p=5353/udp, resp_h=ff02::fb, resp_p=5353/udp] +expired [orig_h=172.16.238.1, orig_p=5353/udp, resp_h=224.0.0.251, resp_p=5353/udp] +expired am +{ +[orig_h=172.16.238.1, orig_p=49659/tcp, resp_h=172.16.238.131, resp_p=21/tcp] +} +{ +[orig_h=172.16.238.1, orig_p=49659/tcp, resp_h=172.16.238.131, resp_p=21/tcp], +[orig_h=172.16.238.131, orig_p=45126/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +expired [orig_h=172.16.238.1, orig_p=49659/tcp, resp_h=172.16.238.131, resp_p=21/tcp] +expired [orig_h=172.16.238.131, orig_p=45126/udp, resp_h=172.16.238.2, resp_p=53/udp] +{ +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=57272/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=57272/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33818/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=57272/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33818/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45140/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=57272/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55368/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33818/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45140/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=57272/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55368/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33818/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45140/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=53102/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=57272/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55368/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=59573/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33818/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45140/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=53102/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=57272/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55368/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=59573/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33818/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=52952/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45140/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=53102/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=48621/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=57272/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp], +[orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=55368/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=59573/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33818/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=52952/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45140/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=53102/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +expired [orig_h=172.16.238.131, orig_p=48621/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=37846/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=57272/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=55515/tcp, resp_h=74.125.225.81, resp_p=80/tcp] +expired [orig_h=172.16.238.131, orig_p=44555/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=55368/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=50205/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=59573/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=33818/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=33109/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=52952/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=45140/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=53102/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=51970/udp, resp_h=172.16.238.2, resp_p=53/udp] +expired [orig_h=172.16.238.131, orig_p=54304/udp, resp_h=172.16.238.2, resp_p=53/udp] +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45908/tcp, resp_h=141.142.192.39, resp_p=22/tcp] +} +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56214/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45908/tcp, resp_h=141.142.192.39, resp_p=22/tcp] +} +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56214/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=38118/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45908/tcp, resp_h=141.142.192.39, resp_p=22/tcp] +} +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56214/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=38118/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=37934/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45908/tcp, resp_h=141.142.192.39, resp_p=22/tcp] +} +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56214/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=38118/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=37934/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45908/tcp, resp_h=141.142.192.39, resp_p=22/tcp], +[orig_h=172.16.238.131, orig_p=36682/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56214/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=38118/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=46552/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=37934/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45908/tcp, resp_h=141.142.192.39, resp_p=22/tcp], +[orig_h=172.16.238.131, orig_p=36682/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=58367/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56214/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=38118/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=46552/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=37934/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45908/tcp, resp_h=141.142.192.39, resp_p=22/tcp], +[orig_h=172.16.238.131, orig_p=36682/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=58367/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56214/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=38118/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=46552/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=42269/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=37934/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45908/tcp, resp_h=141.142.192.39, resp_p=22/tcp], +[orig_h=172.16.238.131, orig_p=36682/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=58367/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56214/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=38118/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56485/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=46552/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=42269/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=37934/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45908/tcp, resp_h=141.142.192.39, resp_p=22/tcp], +[orig_h=172.16.238.131, orig_p=36682/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=58367/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56214/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=38118/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56485/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=46552/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=42269/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=37934/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=39723/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45908/tcp, resp_h=141.142.192.39, resp_p=22/tcp], +[orig_h=172.16.238.131, orig_p=36682/udp, resp_h=172.16.238.2, resp_p=53/udp] +} +{ +[orig_h=172.16.238.131, orig_p=54935/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=58367/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56214/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=123/udp, resp_h=69.50.219.51, resp_p=123/udp], +[orig_h=172.16.238.131, orig_p=38118/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=56485/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=46552/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=42269/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=33624/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=37934/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=39723/udp, resp_h=172.16.238.2, resp_p=53/udp], +[orig_h=172.16.238.131, orig_p=45908/tcp, resp_h=141.142.192.39, resp_p=22/tcp], +[orig_h=172.16.238.131, orig_p=36682/udp, resp_h=172.16.238.2, resp_p=53/udp] +} diff --git a/testing/btest/Baseline/language.ipv6-literals/output b/testing/btest/Baseline/language.ipv6-literals/output new file mode 100644 index 0000000000..8542af7f91 --- /dev/null +++ b/testing/btest/Baseline/language.ipv6-literals/output @@ -0,0 +1,24 @@ +::1 +::ffff +::255.255.255.255 +::10.10.255.255 +1::1 +1::a +1::1:1 +1::1:a +a::a +a::1 +a::a:a +a::a:1 +a:a::a +aaaa::ffff +192.168.1.100 +ffff::c0a8:164 +::192.168.1.100 +::ffff:0:192.168.1.100 +805b:2d9d:dc28::fc57:d4c8:1fff +aaaa::bbbb +aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222 +aaaa:bbbb:cccc:dddd:eeee:ffff:1:2222 +aaaa:bbbb:cccc:dddd:eeee:ffff:0:2222 +aaaa:bbbb:cccc:dddd:eeee::2222 diff --git a/testing/btest/Baseline/language.match-test/output b/testing/btest/Baseline/language.match-test/output deleted file mode 100644 index 5ee7ba029d..0000000000 --- a/testing/btest/Baseline/language.match-test/output +++ /dev/null @@ -1,3 +0,0 @@ -default -it's big -it's really big diff --git a/testing/btest/Baseline/language.match-test2/output b/testing/btest/Baseline/language.match-test2/output deleted file mode 100644 index 0cfbf08886..0000000000 --- a/testing/btest/Baseline/language.match-test2/output +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/testing/btest/Baseline/language.record-default-coercion/out b/testing/btest/Baseline/language.record-default-coercion/out new file mode 100644 index 0000000000..2f0e6cd17d --- /dev/null +++ b/testing/btest/Baseline/language.record-default-coercion/out @@ -0,0 +1,4 @@ +[a=13, c=13, v=[]] +0 +[a=13, c=13, v=[test]] +1 diff --git a/testing/btest/Baseline/language.record-index-complex-fields/output b/testing/btest/Baseline/language.record-index-complex-fields/output new file mode 100644 index 0000000000..21591bc210 --- /dev/null +++ b/testing/btest/Baseline/language.record-index-complex-fields/output @@ -0,0 +1,27 @@ +{ +[1.2.3.4] = { +[a=4, tags_v=[0, 1], tags_t={ +[two] = 2, +[one] = 1 +}, tags_s={ +b, +a +}] +} +} +{ +[a=13, tags_v=[, , 2, 3], tags_t={ +[four] = 4, +[five] = 5 +}, tags_s={ +d, +c +}], +[a=4, tags_v=[0, 1], tags_t={ +[two] = 2, +[one] = 1 +}, tags_s={ +b, +a +}] +} diff --git a/testing/btest/Baseline/language.record-recursive-coercion/output b/testing/btest/Baseline/language.record-recursive-coercion/output index 37c916713f..5c4dea621c 100644 --- a/testing/btest/Baseline/language.record-recursive-coercion/output +++ b/testing/btest/Baseline/language.record-recursive-coercion/output @@ -1 +1,2 @@ [major=4, minor=4, minor2=, addl=] +[c=1, f=[i=2.0 hrs, s=]] diff --git a/testing/btest/Baseline/language.set-opt-record-index/output b/testing/btest/Baseline/language.set-opt-record-index/output new file mode 100644 index 0000000000..fdc6f9d723 --- /dev/null +++ b/testing/btest/Baseline/language.set-opt-record-index/output @@ -0,0 +1,16 @@ +{ +[a=1, b=], +[a=4, b=5], +[a=3, b=] +} + +[a=1, b=] +[a=4, b=5] +[a=3, b=] + +T +F + +T +F +T diff --git a/testing/btest/Baseline/language.sizeof/output b/testing/btest/Baseline/language.sizeof/output index 737a999292..43cb73f763 100644 --- a/testing/btest/Baseline/language.sizeof/output +++ b/testing/btest/Baseline/language.sizeof/output @@ -1,4 +1,5 @@ -Address 1.2.3.4: 16909060 +IPv4 Address 1.2.3.4: 32 +IPv6 Address ::1: 128 Boolean T: 1 Count 10: 10 Double -1.23: 1.230000 diff --git a/testing/btest/Baseline/language.table-init/output b/testing/btest/Baseline/language.table-init/output new file mode 100644 index 0000000000..0272e12319 --- /dev/null +++ b/testing/btest/Baseline/language.table-init/output @@ -0,0 +1,10 @@ +{ +[2] = two, +[1] = one +} +global table default +{ +[4] = four, +[3] = three +} +local table default diff --git a/testing/btest/Baseline/language.wrong-delete-field/output b/testing/btest/Baseline/language.wrong-delete-field/output index f8271e43c2..c2aae8aae3 100644 --- a/testing/btest/Baseline/language.wrong-delete-field/output +++ b/testing/btest/Baseline/language.wrong-delete-field/output @@ -1 +1 @@ -error in /da/home/robin/bro/seth/testing/btest/.tmp/language.wrong-delete-field/wrong-delete-field.bro, line 10: illegal delete statement (delete x$a) +error in /Users/robin/bro/master/testing/btest/.tmp/language.wrong-delete-field/wrong-delete-field.bro, line 10: illegal delete statement (delete x$a) diff --git a/testing/btest/Baseline/policy.frameworks.logging.adapt-filter/ssh-new-default.log b/testing/btest/Baseline/policy.frameworks.logging.adapt-filter/ssh-new-default.log deleted file mode 100644 index ee274bb0fa..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.adapt-filter/ssh-new-default.log +++ /dev/null @@ -1,3 +0,0 @@ -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1313212563.234939 1.2.3.4 1234 2.3.4.5 80 success unknown -1313212563.234939 1.2.3.4 1234 2.3.4.5 80 failure US diff --git a/testing/btest/Baseline/policy.frameworks.logging.ascii-binary/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.ascii-binary/ssh.log deleted file mode 100644 index 84a2cc609e..0000000000 Binary files a/testing/btest/Baseline/policy.frameworks.logging.ascii-binary/ssh.log and /dev/null differ diff --git a/testing/btest/Baseline/policy.frameworks.logging.ascii-empty/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.ascii-empty/ssh.log deleted file mode 100644 index d377ca15d7..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.ascii-empty/ssh.log +++ /dev/null @@ -1,6 +0,0 @@ -PREFIX<>t|id.orig_h|id.orig_p|id.resp_h|id.resp_p|status|country|b -1299718506.56593|1.2.3.4|1234|2.3.4.5|80|success|unknown|NOT-SET -1299718506.56593|1.2.3.4|1234|2.3.4.5|80|NOT-SET|US|NOT-SET -1299718506.56593|1.2.3.4|1234|2.3.4.5|80|failure|UK|NOT-SET -1299718506.56593|1.2.3.4|1234|2.3.4.5|80|NOT-SET|BR|NOT-SET -1299718506.56593|1.2.3.4|1234|2.3.4.5|80|failure|EMPTY|T diff --git a/testing/btest/Baseline/policy.frameworks.logging.ascii-escape/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.ascii-escape/ssh.log deleted file mode 100644 index aa08625281..0000000000 Binary files a/testing/btest/Baseline/policy.frameworks.logging.ascii-escape/ssh.log and /dev/null differ diff --git a/testing/btest/Baseline/policy.frameworks.logging.ascii-options/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.ascii-options/ssh.log deleted file mode 100644 index 33a922cc2b..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.ascii-options/ssh.log +++ /dev/null @@ -1,5 +0,0 @@ -1299718506.38074|1.2.3.4|1234|2.3.4.5|80|success|unknown -1299718506.38074|1.2.3.4|1234|2.3.4.5|80|failure|US -1299718506.38074|1.2.3.4|1234|2.3.4.5|80|failure|UK -1299718506.38074|1.2.3.4|1234|2.3.4.5|80|success|BR -1299718506.38074|1.2.3.4|1234|2.3.4.5|80|failure|MX diff --git a/testing/btest/Baseline/policy.frameworks.logging.attr-extend/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.attr-extend/ssh.log deleted file mode 100644 index d543af3a43..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.attr-extend/ssh.log +++ /dev/null @@ -1,2 +0,0 @@ -# status country a1 b1 b2 -success unknown 1 3 4 diff --git a/testing/btest/Baseline/policy.frameworks.logging.attr/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.attr/ssh.log deleted file mode 100644 index c4355d2fd5..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.attr/ssh.log +++ /dev/null @@ -1,6 +0,0 @@ -# status country -success unknown -failure US -failure UK -success BR -failure MX diff --git a/testing/btest/Baseline/policy.frameworks.logging.empty-event/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.empty-event/ssh.log deleted file mode 100644 index 7f21430ea7..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.empty-event/ssh.log +++ /dev/null @@ -1,6 +0,0 @@ -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1299809561.67372 1.2.3.4 1234 2.3.4.5 80 success unknown -1299809561.67372 1.2.3.4 1234 2.3.4.5 80 failure US -1299809561.67372 1.2.3.4 1234 2.3.4.5 80 failure UK -1299809561.67372 1.2.3.4 1234 2.3.4.5 80 success BR -1299809561.67372 1.2.3.4 1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/policy.frameworks.logging.events/output b/testing/btest/Baseline/policy.frameworks.logging.events/output deleted file mode 100644 index c3dbf607a6..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.events/output +++ /dev/null @@ -1,2 +0,0 @@ -[t=1299718502.96511, id=[orig_h=1.2.3.4, orig_p=1234/tcp, resp_h=2.3.4.5, resp_p=80/tcp], status=success, country=] -[t=1299718502.96511, id=[orig_h=1.2.3.4, orig_p=1234/tcp, resp_h=2.3.4.5, resp_p=80/tcp], status=failure, country=US] diff --git a/testing/btest/Baseline/policy.frameworks.logging.exclude/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.exclude/ssh.log deleted file mode 100644 index 4defa5ced1..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.exclude/ssh.log +++ /dev/null @@ -1,6 +0,0 @@ -# id.orig_p id.resp_h id.resp_p status country -1234 2.3.4.5 80 success unknown -1234 2.3.4.5 80 failure US -1234 2.3.4.5 80 failure UK -1234 2.3.4.5 80 success BR -1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/policy.frameworks.logging.file/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.file/ssh.log deleted file mode 100644 index 49115ab1df..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.file/ssh.log +++ /dev/null @@ -1,2 +0,0 @@ -# t f -1303098703.62603 Foo.log diff --git a/testing/btest/Baseline/policy.frameworks.logging.include/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.include/ssh.log deleted file mode 100644 index 881704257e..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.include/ssh.log +++ /dev/null @@ -1,6 +0,0 @@ -# t id.orig_h -1303064007.48299 1.2.3.4 -1303064007.48299 1.2.3.4 -1303064007.48299 1.2.3.4 -1303064007.48299 1.2.3.4 -1303064007.48299 1.2.3.4 diff --git a/testing/btest/Baseline/policy.frameworks.logging.path-func/output b/testing/btest/Baseline/policy.frameworks.logging.path-func/output deleted file mode 100644 index 7e8acf5106..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.path-func/output +++ /dev/null @@ -1,21 +0,0 @@ -static-prefix-0-BR.log -static-prefix-0-MX3.log -static-prefix-0-unknown.log -static-prefix-1-MX.log -static-prefix-1-US.log -static-prefix-2-MX2.log -static-prefix-2-UK.log -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1313212701.542245 1.2.3.4 1234 2.3.4.5 80 success BR -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1313212701.542245 1.2.3.4 1234 2.3.4.5 80 failure MX3 -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1313212701.542245 1.2.3.4 1234 2.3.4.5 80 success unknown -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1313212701.542245 1.2.3.4 1234 2.3.4.5 80 failure MX -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1313212701.542245 1.2.3.4 1234 2.3.4.5 80 failure US -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1313212701.542245 1.2.3.4 1234 2.3.4.5 80 failure MX2 -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1313212701.542245 1.2.3.4 1234 2.3.4.5 80 failure UK diff --git a/testing/btest/Baseline/policy.frameworks.logging.pred/ssh.failure.log b/testing/btest/Baseline/policy.frameworks.logging.pred/ssh.failure.log deleted file mode 100644 index c46990dc65..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.pred/ssh.failure.log +++ /dev/null @@ -1,2 +0,0 @@ -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1299718503.16177 1.2.3.4 1234 2.3.4.5 80 failure US diff --git a/testing/btest/Baseline/policy.frameworks.logging.pred/ssh.success.log b/testing/btest/Baseline/policy.frameworks.logging.pred/ssh.success.log deleted file mode 100644 index c6adcd86aa..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.pred/ssh.success.log +++ /dev/null @@ -1,2 +0,0 @@ -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1299718503.16177 1.2.3.4 1234 2.3.4.5 80 success - diff --git a/testing/btest/Baseline/policy.frameworks.logging.remote-types/receiver.test.log b/testing/btest/Baseline/policy.frameworks.logging.remote-types/receiver.test.log deleted file mode 100644 index eee707f89f..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.remote-types/receiver.test.log +++ /dev/null @@ -1,2 +0,0 @@ -# b i e c p sn a d t iv s sc ss se vc ve -T -42 Test::TEST 21 123 10.0.0.0/24 1.2.3.4 3.14 1313623666.027768 100.0 hurz 2,4,1,3 CC,AA,BB EMPTY 10,20,30 EMPTY diff --git a/testing/btest/Baseline/policy.frameworks.logging.remote/sender.test.failure.log b/testing/btest/Baseline/policy.frameworks.logging.remote/sender.test.failure.log deleted file mode 100644 index 87f5fb3bcb..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.remote/sender.test.failure.log +++ /dev/null @@ -1,4 +0,0 @@ -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1312565744.470171 1.2.3.4 1234 2.3.4.5 80 failure US -1312565744.470171 1.2.3.4 1234 2.3.4.5 80 failure UK -1312565744.470171 1.2.3.4 1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/policy.frameworks.logging.remote/sender.test.log b/testing/btest/Baseline/policy.frameworks.logging.remote/sender.test.log deleted file mode 100644 index 8d0fedd1b5..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.remote/sender.test.log +++ /dev/null @@ -1,6 +0,0 @@ -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1312565744.470171 1.2.3.4 1234 2.3.4.5 80 success - -1312565744.470171 1.2.3.4 1234 2.3.4.5 80 failure US -1312565744.470171 1.2.3.4 1234 2.3.4.5 80 failure UK -1312565744.470171 1.2.3.4 1234 2.3.4.5 80 success BR -1312565744.470171 1.2.3.4 1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/policy.frameworks.logging.remote/sender.test.success.log b/testing/btest/Baseline/policy.frameworks.logging.remote/sender.test.success.log deleted file mode 100644 index 4b8f54e7ce..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.remote/sender.test.success.log +++ /dev/null @@ -1,3 +0,0 @@ -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1312565744.470171 1.2.3.4 1234 2.3.4.5 80 success - -1312565744.470171 1.2.3.4 1234 2.3.4.5 80 success BR diff --git a/testing/btest/Baseline/policy.frameworks.logging.remove/ssh.failure.log b/testing/btest/Baseline/policy.frameworks.logging.remove/ssh.failure.log deleted file mode 100644 index ddbacda28e..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.remove/ssh.failure.log +++ /dev/null @@ -1,3 +0,0 @@ -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1299718503.28253 1.2.3.4 1234 2.3.4.5 80 failure US -1299718503.28253 1.2.3.4 1234 2.3.4.5 80 failure UK diff --git a/testing/btest/Baseline/policy.frameworks.logging.remove/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.remove/ssh.log deleted file mode 100644 index 123e8e3a87..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.remove/ssh.log +++ /dev/null @@ -1,4 +0,0 @@ -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1299718503.28253 1.2.3.4 1234 2.3.4.5 80 failure US -1299718503.28253 1.2.3.4 1234 2.3.4.5 80 failure UK -1299718503.28253 1.2.3.4 1234 2.3.4.5 80 failure BR diff --git a/testing/btest/Baseline/policy.frameworks.logging.rotate-custom/out b/testing/btest/Baseline/policy.frameworks.logging.rotate-custom/out deleted file mode 100644 index 18bd12d88f..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.rotate-custom/out +++ /dev/null @@ -1,83 +0,0 @@ -1st test.2011-03-07-03-00-05.log test 11-03-07_03.00.05 11-03-07_04.00.05 0 -1st test.2011-03-07-04-00-05.log test 11-03-07_04.00.05 11-03-07_05.00.05 0 -1st test.2011-03-07-05-00-05.log test 11-03-07_05.00.05 11-03-07_06.00.05 0 -1st test.2011-03-07-06-00-05.log test 11-03-07_06.00.05 11-03-07_07.00.05 0 -1st test.2011-03-07-07-00-05.log test 11-03-07_07.00.05 11-03-07_08.00.05 0 -1st test.2011-03-07-08-00-05.log test 11-03-07_08.00.05 11-03-07_09.00.05 0 -1st test.2011-03-07-09-00-05.log test 11-03-07_09.00.05 11-03-07_10.00.05 0 -1st test.2011-03-07-10-00-05.log test 11-03-07_10.00.05 11-03-07_11.00.05 0 -1st test.2011-03-07-11-00-05.log test 11-03-07_11.00.05 11-03-07_12.00.05 0 -1st test.2011-03-07-12-00-05.log test 11-03-07_12.00.05 11-03-07_12.59.55 1 -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_03.00.05.log, path=test2, open=1299466805.0, close=1299470395.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_03.59.55.log, path=test2, open=1299470395.0, close=1299470405.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_04.00.05.log, path=test2, open=1299470405.0, close=1299473995.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_04.59.55.log, path=test2, open=1299473995.0, close=1299474005.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_05.00.05.log, path=test2, open=1299474005.0, close=1299477595.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_05.59.55.log, path=test2, open=1299477595.0, close=1299477605.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_06.00.05.log, path=test2, open=1299477605.0, close=1299481195.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_06.59.55.log, path=test2, open=1299481195.0, close=1299481205.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_07.00.05.log, path=test2, open=1299481205.0, close=1299484795.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_07.59.55.log, path=test2, open=1299484795.0, close=1299484805.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_08.00.05.log, path=test2, open=1299484805.0, close=1299488395.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_08.59.55.log, path=test2, open=1299488395.0, close=1299488405.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_09.00.05.log, path=test2, open=1299488405.0, close=1299491995.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_09.59.55.log, path=test2, open=1299491995.0, close=1299492005.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_10.00.05.log, path=test2, open=1299492005.0, close=1299495595.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_10.59.55.log, path=test2, open=1299495595.0, close=1299495605.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_11.00.05.log, path=test2, open=1299495605.0, close=1299499195.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_11.59.55.log, path=test2, open=1299499195.0, close=1299499205.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_12.00.05.log, path=test2, open=1299499205.0, close=1299502795.0, terminating=F] -custom rotate, [writer=WRITER_ASCII, fname=test2-11-03-07_12.59.55.log, path=test2, open=1299502795.0, close=1299502795.0, terminating=T] -# t id.orig_h id.orig_p id.resp_h id.resp_p -1299466805.000000 10.0.0.1 20 10.0.0.2 1024 -1299470395.000000 10.0.0.2 20 10.0.0.3 0 -1299470405.000000 10.0.0.1 20 10.0.0.2 1025 -1299473995.000000 10.0.0.2 20 10.0.0.3 1 -1299474005.000000 10.0.0.1 20 10.0.0.2 1026 -1299477595.000000 10.0.0.2 20 10.0.0.3 2 -1299477605.000000 10.0.0.1 20 10.0.0.2 1027 -1299481195.000000 10.0.0.2 20 10.0.0.3 3 -1299481205.000000 10.0.0.1 20 10.0.0.2 1028 -1299484795.000000 10.0.0.2 20 10.0.0.3 4 -1299484805.000000 10.0.0.1 20 10.0.0.2 1029 -1299488395.000000 10.0.0.2 20 10.0.0.3 5 -1299488405.000000 10.0.0.1 20 10.0.0.2 1030 -1299491995.000000 10.0.0.2 20 10.0.0.3 6 -1299492005.000000 10.0.0.1 20 10.0.0.2 1031 -1299495595.000000 10.0.0.2 20 10.0.0.3 7 -1299495605.000000 10.0.0.1 20 10.0.0.2 1032 -1299499195.000000 10.0.0.2 20 10.0.0.3 8 -1299499205.000000 10.0.0.1 20 10.0.0.2 1033 -1299502795.000000 10.0.0.2 20 10.0.0.3 9 -> test.2011-03-07-03-00-05.log -> test.2011-03-07-04-00-05.log -> test.2011-03-07-05-00-05.log -> test.2011-03-07-06-00-05.log -> test.2011-03-07-07-00-05.log -> test.2011-03-07-08-00-05.log -> test.2011-03-07-09-00-05.log -> test.2011-03-07-10-00-05.log -> test.2011-03-07-11-00-05.log -> test.2011-03-07-12-00-05.log -> test.log -> test2-11-03-07_03.00.05.log -> test2-11-03-07_03.59.55.log -> test2-11-03-07_04.00.05.log -> test2-11-03-07_04.59.55.log -> test2-11-03-07_05.00.05.log -> test2-11-03-07_05.59.55.log -> test2-11-03-07_06.00.05.log -> test2-11-03-07_06.59.55.log -> test2-11-03-07_07.00.05.log -> test2-11-03-07_07.59.55.log -> test2-11-03-07_08.00.05.log -> test2-11-03-07_08.59.55.log -> test2-11-03-07_09.00.05.log -> test2-11-03-07_09.59.55.log -> test2-11-03-07_10.00.05.log -> test2-11-03-07_10.59.55.log -> test2-11-03-07_11.00.05.log -> test2-11-03-07_11.59.55.log -> test2-11-03-07_12.00.05.log -> test2-11-03-07_12.59.55.log -> test2.log diff --git a/testing/btest/Baseline/policy.frameworks.logging.stdout/output b/testing/btest/Baseline/policy.frameworks.logging.stdout/output deleted file mode 100644 index 4c73aed8e4..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.stdout/output +++ /dev/null @@ -1,6 +0,0 @@ -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1299718506.28824 1.2.3.4 1234 2.3.4.5 80 success unknown -1299718506.28824 1.2.3.4 1234 2.3.4.5 80 failure US -1299718506.28824 1.2.3.4 1234 2.3.4.5 80 failure UK -1299718506.28824 1.2.3.4 1234 2.3.4.5 80 success BR -1299718506.28824 1.2.3.4 1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/policy.frameworks.logging.test-logging/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.test-logging/ssh.log deleted file mode 100644 index 82523b7c13..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.test-logging/ssh.log +++ /dev/null @@ -1,6 +0,0 @@ -# t id.orig_h id.orig_p id.resp_h id.resp_p status country -1299718506.1313 1.2.3.4 1234 2.3.4.5 80 success unknown -1299718506.1313 1.2.3.4 1234 2.3.4.5 80 failure US -1299718506.1313 1.2.3.4 1234 2.3.4.5 80 failure UK -1299718506.1313 1.2.3.4 1234 2.3.4.5 80 success BR -1299718506.1313 1.2.3.4 1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/policy.frameworks.logging.types/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.types/ssh.log deleted file mode 100644 index e5633026b2..0000000000 Binary files a/testing/btest/Baseline/policy.frameworks.logging.types/ssh.log and /dev/null differ diff --git a/testing/btest/Baseline/policy.frameworks.logging.unset-record/testing.log b/testing/btest/Baseline/policy.frameworks.logging.unset-record/testing.log deleted file mode 100644 index 34f20a588b..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.unset-record/testing.log +++ /dev/null @@ -1,3 +0,0 @@ -# a.val1 a.val2 b -- - 6 -1 2 3 diff --git a/testing/btest/Baseline/policy.frameworks.logging.vec/ssh.log b/testing/btest/Baseline/policy.frameworks.logging.vec/ssh.log deleted file mode 100644 index 1602f7d1c0..0000000000 --- a/testing/btest/Baseline/policy.frameworks.logging.vec/ssh.log +++ /dev/null @@ -1,2 +0,0 @@ -# vec --,2,-,-,5 diff --git a/testing/btest/Baseline/policy.frameworks.metrics.basic-cluster/manager-1.metrics.log b/testing/btest/Baseline/policy.frameworks.metrics.basic-cluster/manager-1.metrics.log deleted file mode 100644 index ff692027b2..0000000000 --- a/testing/btest/Baseline/policy.frameworks.metrics.basic-cluster/manager-1.metrics.log +++ /dev/null @@ -1,4 +0,0 @@ -# ts metric_id filter_name index.host index.str index.network value -1313429477.091485 TEST_METRIC foo-bar 6.5.4.3 - - 4 -1313429477.091485 TEST_METRIC foo-bar 1.2.3.4 - - 6 -1313429477.091485 TEST_METRIC foo-bar 7.2.1.5 - - 2 diff --git a/testing/btest/Baseline/policy.frameworks.metrics.basic/metrics.log b/testing/btest/Baseline/policy.frameworks.metrics.basic/metrics.log deleted file mode 100644 index fb4a2c4528..0000000000 --- a/testing/btest/Baseline/policy.frameworks.metrics.basic/metrics.log +++ /dev/null @@ -1,4 +0,0 @@ -# ts metric_id filter_name index.host index.str index.network value -1313430544.678529 TEST_METRIC foo-bar 6.5.4.3 - - 2 -1313430544.678529 TEST_METRIC foo-bar 1.2.3.4 - - 3 -1313430544.678529 TEST_METRIC foo-bar 7.2.1.5 - - 1 diff --git a/testing/btest/Baseline/policy.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log b/testing/btest/Baseline/policy.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log deleted file mode 100644 index 48c74fe7c4..0000000000 --- a/testing/btest/Baseline/policy.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log +++ /dev/null @@ -1,2 +0,0 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network -1313897486.017657 - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 100/100 - 1.2.3.4 - - 100 manager-1 Notice::ACTION_LOG 4 - - - - - - 1.2.3.4 - - diff --git a/testing/btest/Baseline/policy.frameworks.metrics.notice/notice.log b/testing/btest/Baseline/policy.frameworks.metrics.notice/notice.log deleted file mode 100644 index 1e0e6a572b..0000000000 --- a/testing/btest/Baseline/policy.frameworks.metrics.notice/notice.log +++ /dev/null @@ -1,3 +0,0 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p note msg sub src dst p n peer_descr actions policy_items dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network -1313685819.326521 - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 3/2 - 1.2.3.4 - - 3 bro Notice::ACTION_LOG 4 - - - - - - 1.2.3.4 - - -1313685819.326521 - - - - - Test_Notice Threshold crossed by metric_index(host=6.5.4.3) 2/2 - 6.5.4.3 - - 2 bro Notice::ACTION_LOG 4 - - - - - - 6.5.4.3 - - diff --git a/testing/btest/Baseline/policy.misc.bare-loaded-scripts/canonified_loaded_scripts.log b/testing/btest/Baseline/policy.misc.bare-loaded-scripts/canonified_loaded_scripts.log deleted file mode 100644 index 7d40d728da..0000000000 --- a/testing/btest/Baseline/policy.misc.bare-loaded-scripts/canonified_loaded_scripts.log +++ /dev/null @@ -1,13 +0,0 @@ -# depth name -0 scripts/base/init-bare.bro -1 build/src/const.bif.bro -1 build/src/types.bif.bro -1 build/src/strings.bif.bro -1 build/src/bro.bif.bro -1 build/src/reporter.bif.bro -1 build/src/event.bif.bro -1 scripts/base/frameworks/logging/__load__.bro -2 scripts/base/frameworks/logging/./main.bro -3 build/src/logging.bif.bro -2 scripts/base/frameworks/logging/./writers/ascii.bro -0 scripts/policy/misc/loaded-scripts.bro diff --git a/testing/btest/Baseline/policy.misc.default-loaded-scripts/canonified_loaded_scripts.log b/testing/btest/Baseline/policy.misc.default-loaded-scripts/canonified_loaded_scripts.log deleted file mode 100644 index 825be4fbb5..0000000000 --- a/testing/btest/Baseline/policy.misc.default-loaded-scripts/canonified_loaded_scripts.log +++ /dev/null @@ -1,86 +0,0 @@ -# depth name -0 scripts/base/init-bare.bro -1 build/src/const.bif.bro -1 build/src/types.bif.bro -1 build/src/strings.bif.bro -1 build/src/bro.bif.bro -1 build/src/reporter.bif.bro -1 build/src/event.bif.bro -1 scripts/base/frameworks/logging/__load__.bro -2 scripts/base/frameworks/logging/./main.bro -3 build/src/logging.bif.bro -2 scripts/base/frameworks/logging/./writers/ascii.bro -0 scripts/base/init-default.bro -1 scripts/base/utils/site.bro -2 scripts/base/utils/./patterns.bro -1 scripts/base/utils/addrs.bro -1 scripts/base/utils/conn-ids.bro -1 scripts/base/utils/directions-and-hosts.bro -1 scripts/base/utils/files.bro -1 scripts/base/utils/numbers.bro -1 scripts/base/utils/paths.bro -1 scripts/base/utils/strings.bro -1 scripts/base/utils/thresholds.bro -1 scripts/base/frameworks/notice/__load__.bro -2 scripts/base/frameworks/notice/./main.bro -2 scripts/base/frameworks/notice/./weird.bro -2 scripts/base/frameworks/notice/./actions/drop.bro -2 scripts/base/frameworks/notice/./actions/email_admin.bro -2 scripts/base/frameworks/notice/./actions/page.bro -2 scripts/base/frameworks/notice/./actions/add-geodata.bro -2 scripts/base/frameworks/notice/./extend-email/hostnames.bro -1 scripts/base/frameworks/dpd/__load__.bro -2 scripts/base/frameworks/dpd/./main.bro -1 scripts/base/frameworks/signatures/__load__.bro -2 scripts/base/frameworks/signatures/./main.bro -1 scripts/base/frameworks/packet-filter/__load__.bro -2 scripts/base/frameworks/packet-filter/./main.bro -2 scripts/base/frameworks/packet-filter/./netstats.bro -1 scripts/base/frameworks/software/__load__.bro -2 scripts/base/frameworks/software/./main.bro -1 scripts/base/frameworks/intel/__load__.bro -2 scripts/base/frameworks/intel/./main.bro -1 scripts/base/frameworks/metrics/__load__.bro -2 scripts/base/frameworks/metrics/./main.bro -1 scripts/base/frameworks/communication/__load__.bro -2 scripts/base/frameworks/communication/./main.bro -1 scripts/base/frameworks/control/__load__.bro -2 scripts/base/frameworks/control/./main.bro -1 scripts/base/frameworks/cluster/__load__.bro -2 scripts/base/frameworks/cluster/./main.bro -1 scripts/base/frameworks/reporter/__load__.bro -2 scripts/base/frameworks/reporter/./main.bro -1 scripts/base/protocols/conn/__load__.bro -2 scripts/base/protocols/conn/./main.bro -2 scripts/base/protocols/conn/./contents.bro -2 scripts/base/protocols/conn/./inactivity.bro -1 scripts/base/protocols/dns/__load__.bro -2 scripts/base/protocols/dns/./consts.bro -2 scripts/base/protocols/dns/./main.bro -1 scripts/base/protocols/ftp/__load__.bro -2 scripts/base/protocols/ftp/./utils-commands.bro -2 scripts/base/protocols/ftp/./main.bro -2 scripts/base/protocols/ftp/./file-extract.bro -1 scripts/base/protocols/http/__load__.bro -2 scripts/base/protocols/http/./main.bro -2 scripts/base/protocols/http/./utils.bro -2 scripts/base/protocols/http/./file-ident.bro -2 scripts/base/protocols/http/./file-hash.bro -2 scripts/base/protocols/http/./file-extract.bro -1 scripts/base/protocols/irc/__load__.bro -2 scripts/base/protocols/irc/./main.bro -2 scripts/base/protocols/irc/./dcc-send.bro -1 scripts/base/protocols/smtp/__load__.bro -2 scripts/base/protocols/smtp/./main.bro -2 scripts/base/protocols/smtp/./entities.bro -2 scripts/base/protocols/smtp/./entities-excerpt.bro -1 scripts/base/protocols/ssh/__load__.bro -2 scripts/base/protocols/ssh/./main.bro -1 scripts/base/protocols/ssl/__load__.bro -2 scripts/base/protocols/ssl/./consts.bro -2 scripts/base/protocols/ssl/./main.bro -2 scripts/base/protocols/ssl/./mozilla-ca-list.bro -1 scripts/base/protocols/syslog/__load__.bro -2 scripts/base/protocols/syslog/./consts.bro -2 scripts/base/protocols/syslog/./main.bro -0 scripts/policy/misc/loaded-scripts.bro diff --git a/testing/btest/Baseline/policy.protocols.conn.known-hosts/knownhosts-all.log b/testing/btest/Baseline/policy.protocols.conn.known-hosts/knownhosts-all.log deleted file mode 100644 index 8eae4b3163..0000000000 --- a/testing/btest/Baseline/policy.protocols.conn.known-hosts/knownhosts-all.log +++ /dev/null @@ -1,5 +0,0 @@ -# ts host -1300475168.78384 141.142.220.118 -1300475168.78384 208.80.152.118 -1300475168.91594 208.80.152.3 -1300475168.96263 208.80.152.2 diff --git a/testing/btest/Baseline/policy.protocols.conn.known-hosts/knownhosts-local.log b/testing/btest/Baseline/policy.protocols.conn.known-hosts/knownhosts-local.log deleted file mode 100644 index 91e952dc96..0000000000 --- a/testing/btest/Baseline/policy.protocols.conn.known-hosts/knownhosts-local.log +++ /dev/null @@ -1,2 +0,0 @@ -# ts host -1300475168.78384 141.142.220.118 diff --git a/testing/btest/Baseline/policy.protocols.conn.known-hosts/knownhosts-remote.log b/testing/btest/Baseline/policy.protocols.conn.known-hosts/knownhosts-remote.log deleted file mode 100644 index 7224058b56..0000000000 --- a/testing/btest/Baseline/policy.protocols.conn.known-hosts/knownhosts-remote.log +++ /dev/null @@ -1,4 +0,0 @@ -# ts host -1300475168.78384 208.80.152.118 -1300475168.91594 208.80.152.3 -1300475168.96263 208.80.152.2 diff --git a/testing/btest/Baseline/policy.protocols.conn.known-services/knownservices-all.log b/testing/btest/Baseline/policy.protocols.conn.known-services/knownservices-all.log deleted file mode 100644 index 9e427cbffe..0000000000 --- a/testing/btest/Baseline/policy.protocols.conn.known-services/knownservices-all.log +++ /dev/null @@ -1,6 +0,0 @@ -# ts host port_num port_proto service -1308930691.03504 172.16.238.131 22 tcp SSH -1308930694.54896 172.16.238.131 80 tcp HTTP -1308930716.45795 74.125.225.81 80 tcp HTTP -1308930703.06815 172.16.238.131 21 tcp FTP -1308930726.86415 141.142.192.39 22 tcp SSH diff --git a/testing/btest/Baseline/policy.protocols.conn.known-services/knownservices-local.log b/testing/btest/Baseline/policy.protocols.conn.known-services/knownservices-local.log deleted file mode 100644 index 9ff7eb3198..0000000000 --- a/testing/btest/Baseline/policy.protocols.conn.known-services/knownservices-local.log +++ /dev/null @@ -1,4 +0,0 @@ -# ts host port_num port_proto service -1308930691.03504 172.16.238.131 22 tcp SSH -1308930694.54896 172.16.238.131 80 tcp HTTP -1308930703.06815 172.16.238.131 21 tcp FTP diff --git a/testing/btest/Baseline/policy.protocols.conn.known-services/knownservices-remote.log b/testing/btest/Baseline/policy.protocols.conn.known-services/knownservices-remote.log deleted file mode 100644 index 1adb50ed94..0000000000 --- a/testing/btest/Baseline/policy.protocols.conn.known-services/knownservices-remote.log +++ /dev/null @@ -1,3 +0,0 @@ -# ts host port_num port_proto service -1308930716.45795 74.125.225.81 80 tcp HTTP -1308930726.86415 141.142.192.39 22 tcp SSH diff --git a/testing/btest/Baseline/policy.protocols.dns.event-priority/dns.log b/testing/btest/Baseline/policy.protocols.dns.event-priority/dns.log deleted file mode 100644 index 6a5b6c6044..0000000000 --- a/testing/btest/Baseline/policy.protocols.dns.event-priority/dns.log +++ /dev/null @@ -1,2 +0,0 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name QR AA TC RD RA Z TTL answers auth addl -930613226.529070 UWkUyAuUGXf 212.180.42.100 25000 131.243.64.3 53 tcp 34798 - - - - - 0 NOERROR F F F F T 0 31337.0 4.3.2.1 - - diff --git a/testing/btest/Baseline/policy.protocols.http.http-mime-and-md5/http.log b/testing/btest/Baseline/policy.protocols.http.http-mime-and-md5/http.log deleted file mode 100644 index ee07722d92..0000000000 --- a/testing/btest/Baseline/policy.protocols.http.http-mime-and-md5/http.log +++ /dev/null @@ -1,6 +0,0 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p method host uri referrer user_agent request_content_length response_content_length status_code status_msg filename tags username password proxied mime_type md5 extraction_file -1258577884.844956 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 GET www.mozilla.org /style/enhanced.css http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 - 946 200 OK - - - - - FAKE_MIME - - -1258577884.960135 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 GET www.mozilla.org /script/urchin.js http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 - 6716 200 OK - - - - - FAKE_MIME - - -1258577885.317160 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 GET www.mozilla.org /images/template/screen/bullet_utility.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 - 94 200 OK - - - - - FAKE_MIME - - -1258577885.349639 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 GET www.mozilla.org /images/template/screen/key-point-top.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 - 2349 200 OK - - - - - image/png e0029eea80812e9a8e57b8d05d52938a - -1258577885.394612 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 GET www.mozilla.org /projects/calendar/images/header-sunbird.png http://www.mozilla.org/projects/calendar/calendar.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 - 27579 200 OK - - - - - image/png 30aa926344f58019d047e85ba049ca1e - diff --git a/testing/btest/Baseline/policy.protocols.http.http-pipelining/http.log b/testing/btest/Baseline/policy.protocols.http.http-pipelining/http.log deleted file mode 100644 index 1c9e7eb7d6..0000000000 --- a/testing/btest/Baseline/policy.protocols.http.http-pipelining/http.log +++ /dev/null @@ -1,6 +0,0 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p method host uri referrer user_agent request_content_length response_content_length status_code status_msg filename tags username password proxied md5 extraction_file -1258577884.844956 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 GET www.mozilla.org /style/enhanced.css http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 - 946 200 OK - - - - - - - -1258577884.960135 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 GET www.mozilla.org /script/urchin.js http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 - 6716 200 OK - - - - - - - -1258577885.317160 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 GET www.mozilla.org /images/template/screen/bullet_utility.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 - 94 200 OK - - - - - - - -1258577885.349639 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 GET www.mozilla.org /images/template/screen/key-point-top.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 - 2349 200 OK - - - - - - - -1258577885.394612 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 GET www.mozilla.org /projects/calendar/images/header-sunbird.png http://www.mozilla.org/projects/calendar/calendar.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 - 27579 200 OK - - - - - - - diff --git a/testing/btest/Baseline/policy.protocols.irc.basic/irc.log b/testing/btest/Baseline/policy.protocols.irc.basic/irc.log deleted file mode 100644 index bea67dcf5b..0000000000 --- a/testing/btest/Baseline/policy.protocols.irc.basic/irc.log +++ /dev/null @@ -1,5 +0,0 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p nick user channels command value addl tags dcc_file_name dcc_file_size extraction_file -1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 - - - NICK bloed - - - - - -1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed - - USER sdkfje sdkfje Montreal.QC.CA.Undernet.org dkdkrwq - - - - -1311189174.474127 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje - JOIN #easymovies - - - - - -1311189316.326025 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje - DCC #easymovies - - ladyvampress-default(2011-07-07)-OS.zip 42208 - diff --git a/testing/btest/Baseline/policy.protocols.irc.dcc-extract/irc.log b/testing/btest/Baseline/policy.protocols.irc.dcc-extract/irc.log deleted file mode 100644 index fcb002698e..0000000000 --- a/testing/btest/Baseline/policy.protocols.irc.dcc-extract/irc.log +++ /dev/null @@ -1,5 +0,0 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p nick user channels command value addl tags dcc_file_name dcc_file_size dcc_mime_type extraction_file -1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 - - - NICK bloed - - - - - - -1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed - - USER sdkfje sdkfje Montreal.QC.CA.Undernet.org dkdkrwq - - - - - -1311189174.474127 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje - JOIN #easymovies - - - - - - -1311189316.326025 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje - DCC #easymovies - IRC::EXTRACTED_FILE ladyvampress-default(2011-07-07)-OS.zip 42208 FAKE_MIME irc-dcc-item_192.168.1.77:57655-209.197.168.151:1024_1.dat diff --git a/testing/btest/Baseline/policy.protocols.smtp.basic/smtp.log b/testing/btest/Baseline/policy.protocols.smtp.basic/smtp.log deleted file mode 100644 index ea638d1892..0000000000 --- a/testing/btest/Baseline/policy.protocols.smtp.basic/smtp.log +++ /dev/null @@ -1,2 +0,0 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p mid helo mailfrom rcptto date from to reply_to msg_id in_reply_to subject x_originating_ip first_received second_received last_reply path user_agent -1254722768.219663 56gKBmhBBB6 10.10.1.4 1470 74.53.140.153 25 @50da4BEzauh GP Mon, 5 Oct 2009 11:36:07 +0530 "Gurpartap Singh" - <000301ca4581$ef9e57f0$cedb07d0$@in> - SMTP - - - 250 OK id=1Mugho-0003Dg-Un 74.53.140.153,10.10.1.4 Microsoft Office Outlook 12.0 diff --git a/testing/btest/Baseline/policy.protocols.smtp.mime-extract/smtp_entities.log b/testing/btest/Baseline/policy.protocols.smtp.mime-extract/smtp_entities.log deleted file mode 100644 index 9496887d65..0000000000 --- a/testing/btest/Baseline/policy.protocols.smtp.mime-extract/smtp_entities.log +++ /dev/null @@ -1,4 +0,0 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p mid filename content_len mime_type md5 extraction_file excerpt -1254722770.692743 56gKBmhBBB6 10.10.1.4 1470 74.53.140.153 25 @50da4BEzauh - 79 FAKE_MIME - smtp-entity_10.10.1.4:1470-74.53.140.153:25_1.dat - -1254722770.692743 56gKBmhBBB6 10.10.1.4 1470 74.53.140.153 25 @50da4BEzauh - 1918 FAKE_MIME - - - -1254722770.692804 56gKBmhBBB6 10.10.1.4 1470 74.53.140.153 25 @50da4BEzauh NEWS.txt 10823 FAKE_MIME - smtp-entity_10.10.1.4:1470-74.53.140.153:25_2.dat - diff --git a/testing/btest/Baseline/policy.protocols.smtp.mime/smtp_entities.log b/testing/btest/Baseline/policy.protocols.smtp.mime/smtp_entities.log deleted file mode 100644 index 2b143eacda..0000000000 --- a/testing/btest/Baseline/policy.protocols.smtp.mime/smtp_entities.log +++ /dev/null @@ -1,4 +0,0 @@ -# ts uid id.orig_h id.orig_p id.resp_h id.resp_p mid filename content_len mime_type md5 extraction_file excerpt -1254722770.692743 56gKBmhBBB6 10.10.1.4 1470 74.53.140.153 25 @50da4BEzauh - 79 FAKE_MIME 92bca2e6cdcde73647125da7dccbdd07 - - -1254722770.692743 56gKBmhBBB6 10.10.1.4 1470 74.53.140.153 25 @50da4BEzauh - 1918 FAKE_MIME - - - -1254722770.692804 56gKBmhBBB6 10.10.1.4 1470 74.53.140.153 25 @50da4BEzauh NEWS.txt 10823 FAKE_MIME a968bb0f9f9d95835b2e74c845877e87 - - diff --git a/testing/btest/Baseline/policy.frameworks.cluster.start-it-up/manager-1..stdout b/testing/btest/Baseline/scripts.base.frameworks.cluster.start-it-up/manager-1..stdout similarity index 100% rename from testing/btest/Baseline/policy.frameworks.cluster.start-it-up/manager-1..stdout rename to testing/btest/Baseline/scripts.base.frameworks.cluster.start-it-up/manager-1..stdout diff --git a/testing/btest/Baseline/policy.frameworks.cluster.start-it-up/proxy-1..stdout b/testing/btest/Baseline/scripts.base.frameworks.cluster.start-it-up/proxy-1..stdout similarity index 100% rename from testing/btest/Baseline/policy.frameworks.cluster.start-it-up/proxy-1..stdout rename to testing/btest/Baseline/scripts.base.frameworks.cluster.start-it-up/proxy-1..stdout diff --git a/testing/btest/Baseline/policy.frameworks.cluster.start-it-up/proxy-2..stdout b/testing/btest/Baseline/scripts.base.frameworks.cluster.start-it-up/proxy-2..stdout similarity index 100% rename from testing/btest/Baseline/policy.frameworks.cluster.start-it-up/proxy-2..stdout rename to testing/btest/Baseline/scripts.base.frameworks.cluster.start-it-up/proxy-2..stdout diff --git a/testing/btest/Baseline/policy.frameworks.cluster.start-it-up/worker-1..stdout b/testing/btest/Baseline/scripts.base.frameworks.cluster.start-it-up/worker-1..stdout similarity index 100% rename from testing/btest/Baseline/policy.frameworks.cluster.start-it-up/worker-1..stdout rename to testing/btest/Baseline/scripts.base.frameworks.cluster.start-it-up/worker-1..stdout diff --git a/testing/btest/Baseline/policy.frameworks.cluster.start-it-up/worker-2..stdout b/testing/btest/Baseline/scripts.base.frameworks.cluster.start-it-up/worker-2..stdout similarity index 100% rename from testing/btest/Baseline/policy.frameworks.cluster.start-it-up/worker-2..stdout rename to testing/btest/Baseline/scripts.base.frameworks.cluster.start-it-up/worker-2..stdout diff --git a/testing/btest/Baseline/scripts.base.frameworks.communication.communication_log_baseline/send.log b/testing/btest/Baseline/scripts.base.frameworks.communication.communication_log_baseline/send.log new file mode 100644 index 0000000000..d3c14c8603 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.communication.communication_log_baseline/send.log @@ -0,0 +1,21 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path communication +#fields ts peer src_name connected_peer_desc connected_peer_addr connected_peer_port level message +#types time string string string addr port string string +1326492291.485390 bro parent - - - info [#1/127.0.0.1:47757] added peer +1326492291.491731 bro child - - - info [#1/127.0.0.1:47757] connected +1326492291.492024 bro parent - - - info [#1/127.0.0.1:47757] peer connected +1326492291.492024 bro parent - - - info [#1/127.0.0.1:47757] phase: version +1326492291.492740 bro script - - - info connection established +1326492291.492740 bro script - - - info requesting events matching /^?(NOTHING)$?/ +1326492291.492740 bro script - - - info accepting state +1326492291.493800 bro parent - - - info [#1/127.0.0.1:47757] phase: handshake +1326492291.493800 bro parent - - - info warning: no events to request +1326492291.494161 bro parent - - - info [#1/127.0.0.1:47757] peer_description is bro +1326492291.494404 bro parent - - - info [#1/127.0.0.1:47757] peer supports keep-in-cache; using that +1326492291.494404 bro parent - - - info [#1/127.0.0.1:47757] phase: running +1326492291.494404 bro parent - - - info terminating... +1326492291.494404 bro parent - - - info [#1/127.0.0.1:47757] closing connection diff --git a/testing/btest/Baseline/policy.frameworks.control.configuration_update/controllee..stdout b/testing/btest/Baseline/scripts.base.frameworks.control.configuration_update/controllee..stdout similarity index 100% rename from testing/btest/Baseline/policy.frameworks.control.configuration_update/controllee..stdout rename to testing/btest/Baseline/scripts.base.frameworks.control.configuration_update/controllee..stdout diff --git a/testing/btest/Baseline/policy.frameworks.control.id_value/controller..stdout b/testing/btest/Baseline/scripts.base.frameworks.control.id_value/controller..stdout similarity index 100% rename from testing/btest/Baseline/policy.frameworks.control.id_value/controller..stdout rename to testing/btest/Baseline/scripts.base.frameworks.control.id_value/controller..stdout diff --git a/testing/btest/Baseline/policy.frameworks.intel.insert-and-matcher/out b/testing/btest/Baseline/scripts.base.frameworks.intel.insert-and-matcher/out similarity index 100% rename from testing/btest/Baseline/policy.frameworks.intel.insert-and-matcher/out rename to testing/btest/Baseline/scripts.base.frameworks.intel.insert-and-matcher/out diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.adapt-filter/ssh-new-default.log b/testing/btest/Baseline/scripts.base.frameworks.logging.adapt-filter/ssh-new-default.log new file mode 100644 index 0000000000..485bfe3eba --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.adapt-filter/ssh-new-default.log @@ -0,0 +1,9 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssh-new-default +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314313.140603 1.2.3.4 1234 2.3.4.5 80 success unknown +1324314313.140603 1.2.3.4 1234 2.3.4.5 80 failure US diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-binary/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-binary/ssh.log new file mode 100644 index 0000000000..144a7a6426 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-binary/ssh.log @@ -0,0 +1,10 @@ +#separator | +#set_separator|, +#empty_field|(empty) +#unset_field|- +#path|ssh +#fields|data|data2 +#types|string|string +abc\x0a\xffdef|DATA2 +abc\x7c\xffdef|DATA2 +abc\xff\x7cdef|DATA2 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-empty/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-empty/ssh.log new file mode 100644 index 0000000000..10275205a5 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-empty/ssh.log @@ -0,0 +1,12 @@ +PREFIX<>separator | +PREFIX<>set_separator|, +PREFIX<>empty_field|EMPTY +PREFIX<>unset_field|NOT-SET +PREFIX<>path|ssh +PREFIX<>fields|t|id.orig_h|id.orig_p|id.resp_h|id.resp_p|status|country|b +PREFIX<>types|time|addr|port|addr|port|string|string|bool +1324314313.345323|1.2.3.4|1234|2.3.4.5|80|success|unknown|NOT-SET +1324314313.345323|1.2.3.4|1234|2.3.4.5|80|NOT-SET|US|NOT-SET +1324314313.345323|1.2.3.4|1234|2.3.4.5|80|failure|UK|NOT-SET +1324314313.345323|1.2.3.4|1234|2.3.4.5|80|NOT-SET|BR|NOT-SET +1324314313.345323|1.2.3.4|1234|2.3.4.5|80|failure|EMPTY|T diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-notset-str/test.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-notset-str/test.log new file mode 100644 index 0000000000..c9e69994fc --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-notset-str/test.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields x y z +#types string string string +\x2d - (empty) diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-odd-url/http.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-odd-url/http.log new file mode 100644 index 0000000000..97744b7df8 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-odd-url/http.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1315799856.264750 UWkUyAuUGXf 10.0.1.104 64216 193.40.5.162 80 1 GET lepo.it.da.ut.ee /~cect/teoreetilised seminarid_2010/arheoloogia_uurimisr\xfchma_seminar/Joyce et al - The Languages of Archaeology ~ Dialogue, Narrative and Writing.pdf - Wget/1.12 (darwin10.8.0) 0 346 404 Not Found - - - (empty) - - - text/html - - diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-set-separator/test.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-set-separator/test.log new file mode 100644 index 0000000000..b88627c806 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape-set-separator/test.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields ss +#types table[string] +CC,AA,\x2c,\x2c\x2c diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape/ssh.log new file mode 100644 index 0000000000..0ef81128d3 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-escape/ssh.log @@ -0,0 +1,12 @@ +#separator || +#set_separator||, +#empty_field||(empty) +#unset_field||- +#path||ssh +#fields||t||id.orig_h||id.orig_p||id.resp_h||id.resp_p||status||country +#types||time||addr||port||addr||port||string||string +1324314313.899736||1.2.3.4||1234||2.3.4.5||80||success||unknown +1324314313.899736||1.2.3.4||1234||2.3.4.5||80||failure||US +1324314313.899736||1.2.3.4||1234||2.3.4.5||80||fa\x7c\x7cure||UK +1324314313.899736||1.2.3.4||1234||2.3.4.5||80||su\x7c\x7cess||BR +1324314313.899736||1.2.3.4||1234||2.3.4.5||80||failure||MX diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-options/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-options/ssh.log new file mode 100644 index 0000000000..f66dec7160 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-options/ssh.log @@ -0,0 +1,5 @@ +1324314313.990741|1.2.3.4|1234|2.3.4.5|80|success|unknown +1324314313.990741|1.2.3.4|1234|2.3.4.5|80|failure|US +1324314313.990741|1.2.3.4|1234|2.3.4.5|80|failure|UK +1324314313.990741|1.2.3.4|1234|2.3.4.5|80|success|BR +1324314313.990741|1.2.3.4|1234|2.3.4.5|80|failure|MX diff --git a/testing/btest/Baseline/policy.frameworks.logging.ascii-timestamps/test.log b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-timestamps/test.log similarity index 57% rename from testing/btest/Baseline/policy.frameworks.logging.ascii-timestamps/test.log rename to testing/btest/Baseline/scripts.base.frameworks.logging.ascii-timestamps/test.log index fb7ae6d486..00ab6c8ca0 100644 --- a/testing/btest/Baseline/policy.frameworks.logging.ascii-timestamps/test.log +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.ascii-timestamps/test.log @@ -1,4 +1,10 @@ -# data +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields data +#types time 1234567890.000000 1234567890.000000 1234567890.010000 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.attr-extend/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.attr-extend/ssh.log new file mode 100644 index 0000000000..5acaa7b2fc --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.attr-extend/ssh.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssh +#fields status country a1 b1 b2 +#types string string count count count +success unknown 1 3 4 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.attr/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.attr/ssh.log new file mode 100644 index 0000000000..086a4836fe --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.attr/ssh.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssh +#fields status country +#types string string +success unknown +failure US +failure UK +success BR +failure MX diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.empty-event/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.empty-event/ssh.log new file mode 100644 index 0000000000..16ba17c62c --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.empty-event/ssh.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssh +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314314.443785 1.2.3.4 1234 2.3.4.5 80 success unknown +1324314314.443785 1.2.3.4 1234 2.3.4.5 80 failure US +1324314314.443785 1.2.3.4 1234 2.3.4.5 80 failure UK +1324314314.443785 1.2.3.4 1234 2.3.4.5 80 success BR +1324314314.443785 1.2.3.4 1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.events/output b/testing/btest/Baseline/scripts.base.frameworks.logging.events/output new file mode 100644 index 0000000000..5da27764a5 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.events/output @@ -0,0 +1,2 @@ +[t=1324314314.738385, id=[orig_h=1.2.3.4, orig_p=1234/tcp, resp_h=2.3.4.5, resp_p=80/tcp], status=success, country=unknown] +[t=1324314314.738385, id=[orig_h=1.2.3.4, orig_p=1234/tcp, resp_h=2.3.4.5, resp_p=80/tcp], status=failure, country=US] diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.exclude/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.exclude/ssh.log new file mode 100644 index 0000000000..4ccf4c836a --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.exclude/ssh.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssh +#fields id.orig_p id.resp_h id.resp_p status country +#types port addr port string string +1234 2.3.4.5 80 success unknown +1234 2.3.4.5 80 failure US +1234 2.3.4.5 80 failure UK +1234 2.3.4.5 80 success BR +1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.file/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.file/ssh.log new file mode 100644 index 0000000000..4aa3d8f0a7 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.file/ssh.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssh +#fields t f +#types time file +1324314314.940195 Foo.log diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.include/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.include/ssh.log new file mode 100644 index 0000000000..00242d65c1 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.include/ssh.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssh +#fields t id.orig_h +#types time addr +1324314315.040480 1.2.3.4 +1324314315.040480 1.2.3.4 +1324314315.040480 1.2.3.4 +1324314315.040480 1.2.3.4 +1324314315.040480 1.2.3.4 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.path-func-column-demote/local.log b/testing/btest/Baseline/scripts.base.frameworks.logging.path-func-column-demote/local.log new file mode 100644 index 0000000000..291909b80a --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.path-func-column-demote/local.log @@ -0,0 +1,37 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path local +#fields ts id.orig_h +#types time addr +1300475168.855330 141.142.220.118 +1300475168.652003 141.142.220.118 +1300475168.895267 141.142.220.118 +1300475168.855305 141.142.220.118 +1300475168.859163 141.142.220.118 +1300475168.892913 141.142.220.118 +1300475168.724007 141.142.220.118 +1300475168.892936 141.142.220.118 +1300475168.902635 141.142.220.118 +1300475168.891644 141.142.220.118 +1300475170.862384 141.142.220.226 +1300475168.853899 141.142.220.118 +1300475168.854378 141.142.220.118 +1300475168.857956 141.142.220.118 +1300475173.117362 141.142.220.226 +1300475168.858713 141.142.220.118 +1300475167.096535 141.142.220.202 +1300475167.099816 141.142.220.50 +1300475168.892037 141.142.220.118 +1300475168.893988 141.142.220.118 +1300475168.854837 141.142.220.118 +1300475169.899438 141.142.220.44 +1300475168.858306 141.142.220.118 +1300475168.894422 141.142.220.118 +1300475173.153679 141.142.220.238 +1300475168.892414 141.142.220.118 +1300475171.677081 141.142.220.226 +1300475168.902195 141.142.220.118 +1300475168.894787 141.142.220.118 +1300475168.901749 141.142.220.118 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.path-func-column-demote/remote.log b/testing/btest/Baseline/scripts.base.frameworks.logging.path-func-column-demote/remote.log new file mode 100644 index 0000000000..b396c3fc2d --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.path-func-column-demote/remote.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path remote +#fields ts id.orig_h +#types time addr +1300475169.780331 173.192.163.128 +1300475167.097012 fe80::217:f2ff:fed7:cf65 +1300475171.675372 fe80::3074:17d5:2052:c324 +1300475173.116749 fe80::3074:17d5:2052:c324 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.path-func/output b/testing/btest/Baseline/scripts.base.frameworks.logging.path-func/output new file mode 100644 index 0000000000..a6b8a4e090 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.path-func/output @@ -0,0 +1,63 @@ +static-prefix-0-BR.log +static-prefix-0-MX3.log +static-prefix-0-unknown.log +static-prefix-1-MX.log +static-prefix-1-US.log +static-prefix-2-MX2.log +static-prefix-2-UK.log +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path static-prefix-0-BR +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314315.385189 1.2.3.4 1234 2.3.4.5 80 success BR +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path static-prefix-0-MX3 +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314315.385189 1.2.3.4 1234 2.3.4.5 80 failure MX3 +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path static-prefix-0-unknown +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314315.385189 1.2.3.4 1234 2.3.4.5 80 success unknown +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path static-prefix-1-MX +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314315.385189 1.2.3.4 1234 2.3.4.5 80 failure MX +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path static-prefix-1-US +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314315.385189 1.2.3.4 1234 2.3.4.5 80 failure US +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path static-prefix-2-MX2 +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314315.385189 1.2.3.4 1234 2.3.4.5 80 failure MX2 +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path static-prefix-2-UK +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314315.385189 1.2.3.4 1234 2.3.4.5 80 failure UK diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.pred/test.failure.log b/testing/btest/Baseline/scripts.base.frameworks.logging.pred/test.failure.log new file mode 100644 index 0000000000..733bb02847 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.pred/test.failure.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test.failure +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314315.498365 1.2.3.4 1234 2.3.4.5 80 failure US diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.pred/test.success.log b/testing/btest/Baseline/scripts.base.frameworks.logging.pred/test.success.log new file mode 100644 index 0000000000..0261caeb06 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.pred/test.success.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test.success +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314315.498365 1.2.3.4 1234 2.3.4.5 80 success unknown diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.remote-types/receiver.test.log b/testing/btest/Baseline/scripts.base.frameworks.logging.remote-types/receiver.test.log new file mode 100644 index 0000000000..d9bd34309a --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.remote-types/receiver.test.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field EMPTY +#unset_field - +#path test +#fields b i e c p sn a d t iv s sc ss se vc ve +#types bool int enum count port subnet addr double time interval string table[count] table[string] table[string] vector[count] vector[string] +T -42 Test::LOG 21 123 10.0.0.0/24 1.2.3.4 3.14 1324314315.880694 100.000000 hurz 2,4,1,3 CC,AA,BB EMPTY 10,20,30 EMPTY diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.remote/sender.test.failure.log b/testing/btest/Baseline/scripts.base.frameworks.logging.remote/sender.test.failure.log new file mode 100644 index 0000000000..6cb58bf4ac --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.remote/sender.test.failure.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test.failure +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314321.061516 1.2.3.4 1234 2.3.4.5 80 failure US +1324314321.061516 1.2.3.4 1234 2.3.4.5 80 failure UK +1324314321.061516 1.2.3.4 1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.remote/sender.test.log b/testing/btest/Baseline/scripts.base.frameworks.logging.remote/sender.test.log new file mode 100644 index 0000000000..f5b79ee2c4 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.remote/sender.test.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314321.061516 1.2.3.4 1234 2.3.4.5 80 success unknown +1324314321.061516 1.2.3.4 1234 2.3.4.5 80 failure US +1324314321.061516 1.2.3.4 1234 2.3.4.5 80 failure UK +1324314321.061516 1.2.3.4 1234 2.3.4.5 80 success BR +1324314321.061516 1.2.3.4 1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.remote/sender.test.success.log b/testing/btest/Baseline/scripts.base.frameworks.logging.remote/sender.test.success.log new file mode 100644 index 0000000000..c40e56af93 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.remote/sender.test.success.log @@ -0,0 +1,9 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test.success +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314321.061516 1.2.3.4 1234 2.3.4.5 80 success unknown +1324314321.061516 1.2.3.4 1234 2.3.4.5 80 success BR diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.remove/ssh.failure.log b/testing/btest/Baseline/scripts.base.frameworks.logging.remove/ssh.failure.log new file mode 100644 index 0000000000..cb3d4aafb8 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.remove/ssh.failure.log @@ -0,0 +1,9 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssh.failure +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314328.196443 1.2.3.4 1234 2.3.4.5 80 failure US +1324314328.196443 1.2.3.4 1234 2.3.4.5 80 failure UK diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.remove/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.remove/ssh.log new file mode 100644 index 0000000000..38a5bb660c --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.remove/ssh.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssh +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314328.196443 1.2.3.4 1234 2.3.4.5 80 failure US +1324314328.196443 1.2.3.4 1234 2.3.4.5 80 failure UK +1324314328.196443 1.2.3.4 1234 2.3.4.5 80 failure BR diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.rotate-custom/.stderr b/testing/btest/Baseline/scripts.base.frameworks.logging.rotate-custom/.stderr new file mode 100644 index 0000000000..0954137b7e --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.rotate-custom/.stderr @@ -0,0 +1,10 @@ +1st test.2011-03-07-03-00-05.log test 11-03-07_03.00.05 11-03-07_04.00.05 0 +1st test.2011-03-07-04-00-05.log test 11-03-07_04.00.05 11-03-07_05.00.05 0 +1st test.2011-03-07-05-00-05.log test 11-03-07_05.00.05 11-03-07_06.00.05 0 +1st test.2011-03-07-06-00-05.log test 11-03-07_06.00.05 11-03-07_07.00.05 0 +1st test.2011-03-07-07-00-05.log test 11-03-07_07.00.05 11-03-07_08.00.05 0 +1st test.2011-03-07-08-00-05.log test 11-03-07_08.00.05 11-03-07_09.00.05 0 +1st test.2011-03-07-09-00-05.log test 11-03-07_09.00.05 11-03-07_10.00.05 0 +1st test.2011-03-07-10-00-05.log test 11-03-07_10.00.05 11-03-07_11.00.05 0 +1st test.2011-03-07-11-00-05.log test 11-03-07_11.00.05 11-03-07_12.00.05 0 +1st test.2011-03-07-12-00-05.log test 11-03-07_12.00.05 11-03-07_12.59.55 1 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.rotate-custom/out b/testing/btest/Baseline/scripts.base.frameworks.logging.rotate-custom/out new file mode 100644 index 0000000000..915915f43e --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.rotate-custom/out @@ -0,0 +1,78 @@ +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_03.00.05.log, path=test2, open=1299466805.0, close=1299470395.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_03.59.55.log, path=test2, open=1299470395.0, close=1299470405.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_04.00.05.log, path=test2, open=1299470405.0, close=1299473995.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_04.59.55.log, path=test2, open=1299473995.0, close=1299474005.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_05.00.05.log, path=test2, open=1299474005.0, close=1299477595.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_05.59.55.log, path=test2, open=1299477595.0, close=1299477605.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_06.00.05.log, path=test2, open=1299477605.0, close=1299481195.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_06.59.55.log, path=test2, open=1299481195.0, close=1299481205.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_07.00.05.log, path=test2, open=1299481205.0, close=1299484795.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_07.59.55.log, path=test2, open=1299484795.0, close=1299484805.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_08.00.05.log, path=test2, open=1299484805.0, close=1299488395.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_08.59.55.log, path=test2, open=1299488395.0, close=1299488405.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_09.00.05.log, path=test2, open=1299488405.0, close=1299491995.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_09.59.55.log, path=test2, open=1299491995.0, close=1299492005.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_10.00.05.log, path=test2, open=1299492005.0, close=1299495595.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_10.59.55.log, path=test2, open=1299495595.0, close=1299495605.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_11.00.05.log, path=test2, open=1299495605.0, close=1299499195.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_11.59.55.log, path=test2, open=1299499195.0, close=1299499205.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_12.00.05.log, path=test2, open=1299499205.0, close=1299502795.0, terminating=F] +custom rotate, [writer=Log::WRITER_ASCII, fname=test2-11-03-07_12.59.55.log, path=test2, open=1299502795.0, close=1299502795.0, terminating=T] +#empty_field (empty) +#fields t id.orig_h id.orig_p id.resp_h id.resp_p +#path test +#path test2 +#separator \x09 +#set_separator , +#types time addr port addr port +#unset_field - +1299466805.000000 10.0.0.1 20 10.0.0.2 1024 +1299470395.000000 10.0.0.2 20 10.0.0.3 0 +1299470405.000000 10.0.0.1 20 10.0.0.2 1025 +1299473995.000000 10.0.0.2 20 10.0.0.3 1 +1299474005.000000 10.0.0.1 20 10.0.0.2 1026 +1299477595.000000 10.0.0.2 20 10.0.0.3 2 +1299477605.000000 10.0.0.1 20 10.0.0.2 1027 +1299481195.000000 10.0.0.2 20 10.0.0.3 3 +1299481205.000000 10.0.0.1 20 10.0.0.2 1028 +1299484795.000000 10.0.0.2 20 10.0.0.3 4 +1299484805.000000 10.0.0.1 20 10.0.0.2 1029 +1299488395.000000 10.0.0.2 20 10.0.0.3 5 +1299488405.000000 10.0.0.1 20 10.0.0.2 1030 +1299491995.000000 10.0.0.2 20 10.0.0.3 6 +1299492005.000000 10.0.0.1 20 10.0.0.2 1031 +1299495595.000000 10.0.0.2 20 10.0.0.3 7 +1299495605.000000 10.0.0.1 20 10.0.0.2 1032 +1299499195.000000 10.0.0.2 20 10.0.0.3 8 +1299499205.000000 10.0.0.1 20 10.0.0.2 1033 +1299502795.000000 10.0.0.2 20 10.0.0.3 9 +> test.2011-03-07-03-00-05.log +> test.2011-03-07-04-00-05.log +> test.2011-03-07-05-00-05.log +> test.2011-03-07-06-00-05.log +> test.2011-03-07-07-00-05.log +> test.2011-03-07-08-00-05.log +> test.2011-03-07-09-00-05.log +> test.2011-03-07-10-00-05.log +> test.2011-03-07-11-00-05.log +> test.2011-03-07-12-00-05.log +> test2-11-03-07_03.00.05.log +> test2-11-03-07_03.59.55.log +> test2-11-03-07_04.00.05.log +> test2-11-03-07_04.59.55.log +> test2-11-03-07_05.00.05.log +> test2-11-03-07_05.59.55.log +> test2-11-03-07_06.00.05.log +> test2-11-03-07_06.59.55.log +> test2-11-03-07_07.00.05.log +> test2-11-03-07_07.59.55.log +> test2-11-03-07_08.00.05.log +> test2-11-03-07_08.59.55.log +> test2-11-03-07_09.00.05.log +> test2-11-03-07_09.59.55.log +> test2-11-03-07_10.00.05.log +> test2-11-03-07_10.59.55.log +> test2-11-03-07_11.00.05.log +> test2-11-03-07_11.59.55.log +> test2-11-03-07_12.00.05.log +> test2-11-03-07_12.59.55.log diff --git a/testing/btest/Baseline/policy.frameworks.logging.rotate/out b/testing/btest/Baseline/scripts.base.frameworks.logging.rotate/out similarity index 53% rename from testing/btest/Baseline/policy.frameworks.logging.rotate/out rename to testing/btest/Baseline/scripts.base.frameworks.logging.rotate/out index b153c5b7fa..d31783edc4 100644 --- a/testing/btest/Baseline/policy.frameworks.logging.rotate/out +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.rotate/out @@ -9,42 +9,102 @@ test.2011-03-07-10-00-05.log test 11-03-07_10.00.05 11-03-07_11.00.05 0 test.2011-03-07-11-00-05.log test 11-03-07_11.00.05 11-03-07_12.00.05 0 test.2011-03-07-12-00-05.log test 11-03-07_12.00.05 11-03-07_12.59.55 1 > test.2011-03-07-03-00-05.log -# t id.orig_h id.orig_p id.resp_h id.resp_p +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields t id.orig_h id.orig_p id.resp_h id.resp_p +#types time addr port addr port 1299466805.000000 10.0.0.1 20 10.0.0.2 1024 1299470395.000000 10.0.0.2 20 10.0.0.3 0 > test.2011-03-07-04-00-05.log -# t id.orig_h id.orig_p id.resp_h id.resp_p +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields t id.orig_h id.orig_p id.resp_h id.resp_p +#types time addr port addr port 1299470405.000000 10.0.0.1 20 10.0.0.2 1025 1299473995.000000 10.0.0.2 20 10.0.0.3 1 > test.2011-03-07-05-00-05.log -# t id.orig_h id.orig_p id.resp_h id.resp_p +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields t id.orig_h id.orig_p id.resp_h id.resp_p +#types time addr port addr port 1299474005.000000 10.0.0.1 20 10.0.0.2 1026 1299477595.000000 10.0.0.2 20 10.0.0.3 2 > test.2011-03-07-06-00-05.log -# t id.orig_h id.orig_p id.resp_h id.resp_p +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields t id.orig_h id.orig_p id.resp_h id.resp_p +#types time addr port addr port 1299477605.000000 10.0.0.1 20 10.0.0.2 1027 1299481195.000000 10.0.0.2 20 10.0.0.3 3 > test.2011-03-07-07-00-05.log -# t id.orig_h id.orig_p id.resp_h id.resp_p +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields t id.orig_h id.orig_p id.resp_h id.resp_p +#types time addr port addr port 1299481205.000000 10.0.0.1 20 10.0.0.2 1028 1299484795.000000 10.0.0.2 20 10.0.0.3 4 > test.2011-03-07-08-00-05.log -# t id.orig_h id.orig_p id.resp_h id.resp_p +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields t id.orig_h id.orig_p id.resp_h id.resp_p +#types time addr port addr port 1299484805.000000 10.0.0.1 20 10.0.0.2 1029 1299488395.000000 10.0.0.2 20 10.0.0.3 5 > test.2011-03-07-09-00-05.log -# t id.orig_h id.orig_p id.resp_h id.resp_p +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields t id.orig_h id.orig_p id.resp_h id.resp_p +#types time addr port addr port 1299488405.000000 10.0.0.1 20 10.0.0.2 1030 1299491995.000000 10.0.0.2 20 10.0.0.3 6 > test.2011-03-07-10-00-05.log -# t id.orig_h id.orig_p id.resp_h id.resp_p +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields t id.orig_h id.orig_p id.resp_h id.resp_p +#types time addr port addr port 1299492005.000000 10.0.0.1 20 10.0.0.2 1031 1299495595.000000 10.0.0.2 20 10.0.0.3 7 > test.2011-03-07-11-00-05.log -# t id.orig_h id.orig_p id.resp_h id.resp_p +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields t id.orig_h id.orig_p id.resp_h id.resp_p +#types time addr port addr port 1299495605.000000 10.0.0.1 20 10.0.0.2 1032 1299499195.000000 10.0.0.2 20 10.0.0.3 8 > test.2011-03-07-12-00-05.log -# t id.orig_h id.orig_p id.resp_h id.resp_p +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path test +#fields t id.orig_h id.orig_p id.resp_h id.resp_p +#types time addr port addr port 1299499205.000000 10.0.0.1 20 10.0.0.2 1033 1299502795.000000 10.0.0.2 20 10.0.0.3 9 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.stdout/output b/testing/btest/Baseline/scripts.base.frameworks.logging.stdout/output new file mode 100644 index 0000000000..09afe2031c --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.stdout/output @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path /dev/stdout +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314328.844271 1.2.3.4 1234 2.3.4.5 80 success unknown +1324314328.844271 1.2.3.4 1234 2.3.4.5 80 failure US +1324314328.844271 1.2.3.4 1234 2.3.4.5 80 failure UK +1324314328.844271 1.2.3.4 1234 2.3.4.5 80 success BR +1324314328.844271 1.2.3.4 1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.test-logging/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.test-logging/ssh.log new file mode 100644 index 0000000000..53292324af --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.test-logging/ssh.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssh +#fields t id.orig_h id.orig_p id.resp_h id.resp_p status country +#types time addr port addr port string string +1324314328.950525 1.2.3.4 1234 2.3.4.5 80 success unknown +1324314328.950525 1.2.3.4 1234 2.3.4.5 80 failure US +1324314328.950525 1.2.3.4 1234 2.3.4.5 80 failure UK +1324314328.950525 1.2.3.4 1234 2.3.4.5 80 success BR +1324314328.950525 1.2.3.4 1234 2.3.4.5 80 failure MX diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.types/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.types/ssh.log new file mode 100644 index 0000000000..74aa0312a1 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.types/ssh.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field EMPTY +#unset_field - +#path ssh +#fields b i e c p sn a d t iv s sc ss se vc ve f +#types bool int enum count port subnet addr double time interval string table[count] table[string] table[string] vector[count] vector[string] func +T -42 SSH::LOG 21 123 10.0.0.0/24 1.2.3.4 3.14 1324314329.051618 100.000000 hurz 2,4,1,3 CC,AA,BB EMPTY 10,20,30 EMPTY SSH::foo\x0a{ \x0aif (0 < SSH::i) \x0a\x09return (Foo);\x0aelse\x0a\x09return (Bar);\x0a\x0a} diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.unset-record/testing.log b/testing/btest/Baseline/scripts.base.frameworks.logging.unset-record/testing.log new file mode 100644 index 0000000000..7956ad11a0 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.unset-record/testing.log @@ -0,0 +1,9 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path testing +#fields a.val1 a.val2 b +#types count count count +- - 6 +1 2 3 diff --git a/testing/btest/Baseline/scripts.base.frameworks.logging.vec/ssh.log b/testing/btest/Baseline/scripts.base.frameworks.logging.vec/ssh.log new file mode 100644 index 0000000000..65ab5592bf --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.logging.vec/ssh.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ssh +#fields vec +#types vector[string] +-,2,-,-,5 diff --git a/testing/btest/Baseline/scripts.base.frameworks.metrics.basic-cluster/manager-1.metrics.log b/testing/btest/Baseline/scripts.base.frameworks.metrics.basic-cluster/manager-1.metrics.log new file mode 100644 index 0000000000..a22deb26e4 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.metrics.basic-cluster/manager-1.metrics.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path metrics +#fields ts metric_id filter_name index.host index.str index.network value +#types time enum string addr string subnet count +1328303679.867377 TEST_METRIC foo-bar 6.5.4.3 - - 4 +1328303679.867377 TEST_METRIC foo-bar 7.2.1.5 - - 2 +1328303679.867377 TEST_METRIC foo-bar 1.2.3.4 - - 6 diff --git a/testing/btest/Baseline/scripts.base.frameworks.metrics.basic/metrics.log b/testing/btest/Baseline/scripts.base.frameworks.metrics.basic/metrics.log new file mode 100644 index 0000000000..4bfb6964ea --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.metrics.basic/metrics.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path metrics +#fields ts metric_id filter_name index.host index.str index.network value +#types time enum string addr string subnet count +1328303763.333948 TEST_METRIC foo-bar 6.5.4.3 - - 2 +1328303763.333948 TEST_METRIC foo-bar 7.2.1.5 - - 1 +1328303763.333948 TEST_METRIC foo-bar 1.2.3.4 - - 3 diff --git a/testing/btest/Baseline/scripts.base.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log b/testing/btest/Baseline/scripts.base.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log new file mode 100644 index 0000000000..59d70896fb --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.metrics.cluster-intermediate-update/manager-1.notice.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path notice +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network +#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet +1325633225.777902 - - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 100/100 - 1.2.3.4 - - 100 manager-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - - diff --git a/testing/btest/Baseline/scripts.base.frameworks.metrics.notice/notice.log b/testing/btest/Baseline/scripts.base.frameworks.metrics.notice/notice.log new file mode 100644 index 0000000000..58346b79e6 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.metrics.notice/notice.log @@ -0,0 +1,9 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path notice +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network +#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet +1325633274.875473 - - - - - - Test_Notice Threshold crossed by metric_index(host=1.2.3.4) 3/2 - 1.2.3.4 - - 3 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 1.2.3.4 - - +1325633274.875473 - - - - - - Test_Notice Threshold crossed by metric_index(host=6.5.4.3) 2/2 - 6.5.4.3 - - 2 bro Notice::ACTION_LOG 6 3600.000000 F - - - - - 6.5.4.3 - - diff --git a/testing/btest/Baseline/scripts.base.frameworks.notice.cluster/manager-1.notice.log b/testing/btest/Baseline/scripts.base.frameworks.notice.cluster/manager-1.notice.log new file mode 100644 index 0000000000..10888b21ec --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.notice.cluster/manager-1.notice.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path notice +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network +#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet +1325633122.490990 - - - - - - Test_Notice test notice! - - - - - worker-1 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - - diff --git a/testing/btest/Baseline/scripts.base.frameworks.notice.mail-alarms/alarm-mail.txt b/testing/btest/Baseline/scripts.base.frameworks.notice.mail-alarms/alarm-mail.txt new file mode 100644 index 0000000000..e2cd51edd1 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.notice.mail-alarms/alarm-mail.txt @@ -0,0 +1,4 @@ +> 2005-10-07-23:23:55 Test_Notice 141.42.64.125:56730/tcp -> 125.190.109.199:80/tcp (uid arKYeMETxOg) + test + # 141.42.64.125 = 125.190.109.199 = + diff --git a/testing/btest/Baseline/scripts.base.frameworks.notice.suppression-cluster/manager-1.notice.log b/testing/btest/Baseline/scripts.base.frameworks.notice.suppression-cluster/manager-1.notice.log new file mode 100644 index 0000000000..5deac88071 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.notice.suppression-cluster/manager-1.notice.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path notice +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude metric_index.host metric_index.str metric_index.network +#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double addr string subnet +1325633150.723248 - - - - - - Test_Notice test notice! - - - - - worker-2 Notice::ACTION_LOG 6 3600.000000 F - - - - - - - - diff --git a/testing/btest/Baseline/scripts.base.frameworks.notice.suppression/notice.log b/testing/btest/Baseline/scripts.base.frameworks.notice.suppression/notice.log new file mode 100644 index 0000000000..1d168d7613 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.frameworks.notice.suppression/notice.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path notice +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto note msg sub src dst p n peer_descr actions policy_items suppress_for dropped remote_location.country_code remote_location.region remote_location.city remote_location.latitude remote_location.longitude +#types time string addr port addr port enum enum string string addr addr port count string table[enum] table[count] interval bool string string string double double +1325633207.922993 - - - - - - Test_Notice test - - - - - bro Notice::ACTION_LOG 6 3600.000000 F - - - - - diff --git a/testing/btest/Baseline/policy.frameworks.software.version-parsing/output b/testing/btest/Baseline/scripts.base.frameworks.software.version-parsing/output similarity index 75% rename from testing/btest/Baseline/policy.frameworks.software.version-parsing/output rename to testing/btest/Baseline/scripts.base.frameworks.software.version-parsing/output index 77fc25c72d..f172268aa6 100644 --- a/testing/btest/Baseline/policy.frameworks.software.version-parsing/output +++ b/testing/btest/Baseline/scripts.base.frameworks.software.version-parsing/output @@ -1,6 +1,7 @@ success on: Apache/1.3.19 (Unix) success on: Python-urllib/3.1 success on: Apache +success on: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3; Creative AutoUpdate v1.40.02) success on: Java/1.6.0_13 success on: Wget/1.11.4 (Red Hat modified) success on: curl/7.15.1 (i486-pc-linux-gnu) libcurl/7.15.1 OpenSSL/0.9.8a zlib/1.2.3 libidn/0.5.18 @@ -14,9 +15,13 @@ success on: Apple Mail (2.1084) success on: libwww-perl/5.820 success on: Apache/2.0.46 (Win32) mod_ssl/2.0.46 OpenSSL/0.9.7b mod_jk2/2.0.4 success on: iTunes/9.0 (Macintosh; Intel Mac OS X 10.5.8) AppleWebKit/531.9 +success on: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-us) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27 success on: Wget/1.9+cvs-stable (Red Hat modified) +success on: Mozilla/5.0 (iPod; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7 +success on: Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0) success on: The Bat! (v2.00.9) Personal success on: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.205 Safari/534.16 +success on: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) success on: ProFTPD 1.2.5rc1 Server (Debian) success on: Java1.2.2-JDeveloper success on: Total Commander @@ -32,6 +37,7 @@ success on: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; GTB5; SLCC1; .NET success on: Mozilla/5.0 (Linux; U; Android 2.3.3; zh-tw; HTC Pyramid Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 success on: wu-2.6.2(1) success on: Opera/9.80 (J2ME/MIDP; Opera Mini/5.0.18741/18.794; U; en) Presto/2.4.15 +success on: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0; InfoPath.2; InfoPath.3) success on: Flash/10,2,153,1 success on: CacheFlyServe v26b success on: Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.11) Gecko/20101013 Lightning/1.0b2 Thunderbird/3.1.5 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/conn.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/conn.log new file mode 100644 index 0000000000..bcb05ef415 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/conn.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes +#types time string addr port addr port enum string interval count count string bool count string count count count count +1329843175.736107 arKYeMETxOg 141.142.220.235 37604 199.233.217.249 56666 tcp ftp-data 0.112432 0 342 SF - 0 ShAdfFa 4 216 4 562 +1329843179.871641 k6kgXLOoSKl 141.142.220.235 59378 199.233.217.249 56667 tcp ftp-data 0.111218 0 77 SF - 0 ShAdfFa 4 216 4 297 +1329843194.151526 nQcgTWjvg4c 199.233.217.249 61920 141.142.220.235 33582 tcp ftp-data 0.056211 342 0 SF - 0 ShADaFf 5 614 3 164 +1329843197.783443 j4u32Pc5bif 199.233.217.249 61918 141.142.220.235 37835 tcp ftp-data 0.056005 77 0 SF - 0 ShADaFf 5 349 3 164 +1329843161.968492 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 tcp ftp 38.055625 180 3146 SF - 0 ShAdDfFa 38 2164 25 4458 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log new file mode 100644 index 0000000000..debc093771 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv4/ftp.log @@ -0,0 +1,9 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ftp +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type mime_desc file_size reply_code reply_msg tags extraction_file +#types time string addr port addr port string string string string string string count count string table[string] file +1329843179.926563 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain ASCII text 77 226 Transfer complete. - - +1329843197.727769 UWkUyAuUGXf 141.142.220.235 50003 199.233.217.249 21 anonymous test RETR ftp://199.233.217.249/./robots.txt text/plain ASCII text, with CRLF line terminators 77 226 Transfer complete. - - diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/conn.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/conn.log new file mode 100644 index 0000000000..c4a515710d --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/conn.log @@ -0,0 +1,13 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path conn +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto service duration orig_bytes resp_bytes conn_state local_orig missed_bytes history orig_pkts orig_ip_bytes resp_pkts resp_ip_bytes +#types time string addr port addr port enum string interval count count string bool count string count count count count +1329327783.316897 arKYeMETxOg 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49186 2001:470:4867:99::21 57086 tcp ftp-data 0.219721 0 342 SF - 0 ShAdfFa 5 372 4 642 +1329327786.524332 k6kgXLOoSKl 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49187 2001:470:4867:99::21 57087 tcp ftp-data 0.217501 0 43 SF - 0 ShAdfFa 5 372 4 343 +1329327787.289095 nQcgTWjvg4c 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49188 2001:470:4867:99::21 57088 tcp ftp-data 0.217941 0 77 SF - 0 ShAdfFa 5 372 4 377 +1329327795.571921 j4u32Pc5bif 2001:470:4867:99::21 55785 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49189 tcp ftp-data 0.109813 77 0 SF - 0 ShADFaf 5 449 4 300 +1329327777.822004 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 tcp ftp 26.658219 310 3448 SF - 0 ShAdDfFa 57 4426 34 5908 +1329327800.017649 TEfuqmmG4bh 2001:470:4867:99::21 55647 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49190 tcp ftp-data 0.109181 342 0 SF - 0 ShADFaf 5 714 4 300 diff --git a/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log new file mode 100644 index 0000000000..8bc2ef2cb7 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.ftp.ftp-ipv6/ftp.log @@ -0,0 +1,9 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path ftp +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p user password command arg mime_type mime_desc file_size reply_code reply_msg tags extraction_file +#types time string addr port addr port string string string string string string count count string table[string] file +1329327787.396984 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR ftp://[2001:470:4867:99::21]/robots.txt - - 77 226 Transfer complete. - - +1329327795.463946 UWkUyAuUGXf 2001:470:1f11:81f:c999:d94:aa7c:2e3e 49185 2001:470:4867:99::21 21 anonymous test RETR ftp://[2001:470:4867:99::21]/robots.txt - - 77 226 Transfer complete. - - diff --git a/testing/btest/Baseline/scripts.base.protocols.http.100-continue/http.log b/testing/btest/Baseline/scripts.base.protocols.http.100-continue/http.log new file mode 100644 index 0000000000..ddcea2e9c7 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.http.100-continue/http.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1237440095.634312 UWkUyAuUGXf 192.168.3.103 54102 128.146.216.51 80 1 POST www.osu.edu / - curl/7.17.1 (i386-apple-darwin8.11.1) libcurl/7.17.1 zlib/1.2.3 2001 60731 200 OK 100 Continue - (empty) - - - text/html - - diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http-item_141.42.64.125:56730-125.190.109.199:80_resp_1.dat b/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http-item_141.42.64.125:56730-125.190.109.199:80_resp_1.dat new file mode 100644 index 0000000000..73c369dd14 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http-item_141.42.64.125:56730-125.190.109.199:80_resp_1.dat @@ -0,0 +1,304 @@ + +ICIR + +ICIR
    +

    +ICIR (The ICSI Center for Internet Research) +is a +non-profit +research institute at +ICSI +in +Berkeley, +California.
    +For the three years from 1999 to 2001 we were named +ACIRI, the AT&T Center for Internet Research at ICSI, +and were funded by AT&T.
    + +The goals of ICIR are to: +

      +
    • Pursue research on the Internet architecture and related networking issues, +
    • +Participate actively in the research (SIGCOMM and IRTF) and +standards (IETF) communities, +
    • Bridge the gap between the Internet research community and commercial +interests by providing a neutral forum where topics of mutual technical +interest can be addressed. +
    +

    + +


    + +
    + + + + + + + + + + +
    + +

    +People +

    + + +
    + +

    +Publications +

    + + +

    +Projects +

    + + + +
    + +

    Research

    +   Transport and Congestion + + +   Traffic and Topology +
      +
    • +IDMaps +(Internet Distance Mapping). +
    • The +Internet Traffic Archive. +
    • +MINC +(Multicast-based Inference of Network-internal Characteristics). +
    • +NIMI +(National Internet Measurement Infrastructure). +
    + +

    + +Collaborators +

    + + + +
    +
    + +
    +

    Information for visitors and local users.

    +
    +Last modified: June 2004. Copyright notice. + +Older versions of this web page, in its ACIRI incarnation.. +
    +For more information about this server, mail www@aciri.org. +
    +To report unusual activity by any of our hosts, mail abuse@aciri.org. + diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http.log new file mode 100644 index 0000000000..cec098a50b --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-extract-files/http.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1128727435.634189 arKYeMETxOg 141.42.64.125 56730 125.190.109.199 80 1 GET www.icir.org / - Wget/1.10 0 9130 200 OK - - - (empty) - - - text/html - http-item_141.42.64.125:56730-125.190.109.199:80_resp_1.dat diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-mime-and-md5/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-mime-and-md5/http.log new file mode 100644 index 0000000000..d4e5679da1 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-mime-and-md5/http.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied mime_type md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string string file +1258577884.844956 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 1 GET www.mozilla.org /style/enhanced.css http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2675 200 OK - - - (empty) - - - FAKE_MIME - - +1258577884.960135 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 2 GET www.mozilla.org /script/urchin.js http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 21421 200 OK - - - (empty) - - - FAKE_MIME - - +1258577885.317160 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 3 GET www.mozilla.org /images/template/screen/bullet_utility.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 94 200 OK - - - (empty) - - - FAKE_MIME - - +1258577885.349639 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 4 GET www.mozilla.org /images/template/screen/key-point-top.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2349 200 OK - - - (empty) - - - image/png e0029eea80812e9a8e57b8d05d52938a - +1258577885.394612 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 5 GET www.mozilla.org /projects/calendar/images/header-sunbird.png http://www.mozilla.org/projects/calendar/calendar.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 27579 200 OK - - - (empty) - - - image/png 30aa926344f58019d047e85ba049ca1e - diff --git a/testing/btest/Baseline/scripts.base.protocols.http.http-pipelining/http.log b/testing/btest/Baseline/scripts.base.protocols.http.http-pipelining/http.log new file mode 100644 index 0000000000..dfaf34acbf --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.http.http-pipelining/http.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path http +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth method host uri referrer user_agent request_body_len response_body_len status_code status_msg info_code info_msg filename tags username password proxied md5 extraction_file +#types time string addr port addr port count string string string string string count count count string count string string table[enum] string string table[string] string file +1258577884.844956 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 1 GET www.mozilla.org /style/enhanced.css http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2675 200 OK - - - (empty) - - - - - +1258577884.960135 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 2 GET www.mozilla.org /script/urchin.js http://www.mozilla.org/projects/calendar/ Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 21421 200 OK - - - (empty) - - - - - +1258577885.317160 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 3 GET www.mozilla.org /images/template/screen/bullet_utility.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 94 200 OK - - - (empty) - - - - - +1258577885.349639 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 4 GET www.mozilla.org /images/template/screen/key-point-top.png http://www.mozilla.org/style/screen.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 2349 200 OK - - - (empty) - - - - - +1258577885.394612 UWkUyAuUGXf 192.168.1.104 1673 63.245.209.11 80 5 GET www.mozilla.org /projects/calendar/images/header-sunbird.png http://www.mozilla.org/projects/calendar/calendar.css Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.5) Gecko/20091102 Firefox/3.5.5 0 27579 200 OK - - - (empty) - - - - - diff --git a/testing/btest/Baseline/scripts.base.protocols.irc.basic/irc.log b/testing/btest/Baseline/scripts.base.protocols.irc.basic/irc.log new file mode 100644 index 0000000000..b5c137bcf8 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.irc.basic/irc.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path irc +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p nick user command value addl dcc_file_name dcc_file_size extraction_file +#types time string addr port addr port string string string string string string count file +1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 - - NICK bloed - - - - +1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed - USER sdkfje sdkfje Montreal.QC.CA.Undernet.org dkdkrwq - - - +1311189174.474127 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje JOIN #easymovies (empty) - - - +1311189316.326025 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje DCC #easymovies (empty) ladyvampress-default(2011-07-07)-OS.zip 42208 - diff --git a/testing/btest/Baseline/policy.protocols.irc.dcc-extract/irc-dcc-item_192.168.1.77:57655-209.197.168.151:1024_1.dat b/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc-dcc-item_192.168.1.77:57655-209.197.168.151:1024_1.dat similarity index 100% rename from testing/btest/Baseline/policy.protocols.irc.dcc-extract/irc-dcc-item_192.168.1.77:57655-209.197.168.151:1024_1.dat rename to testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc-dcc-item_192.168.1.77:57655-209.197.168.151:1024_1.dat diff --git a/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc.log b/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc.log new file mode 100644 index 0000000000..7513bfb9b8 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.irc.dcc-extract/irc.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path irc +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p nick user command value addl dcc_file_name dcc_file_size dcc_mime_type extraction_file +#types time string addr port addr port string string string string string string count string file +1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 - - NICK bloed - - - - - +1311189164.119437 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed - USER sdkfje sdkfje Montreal.QC.CA.Undernet.org dkdkrwq - - - - +1311189174.474127 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje JOIN #easymovies (empty) - - - - +1311189316.326025 UWkUyAuUGXf 192.168.1.77 57640 66.198.80.67 6667 bloed sdkfje DCC #easymovies (empty) ladyvampress-default(2011-07-07)-OS.zip 42208 FAKE_MIME irc-dcc-item_192.168.1.77:57655-209.197.168.151:1024_1.dat diff --git a/testing/btest/Baseline/scripts.base.protocols.smtp.basic/smtp.log b/testing/btest/Baseline/scripts.base.protocols.smtp.basic/smtp.log new file mode 100644 index 0000000000..2c1380cb44 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.smtp.basic/smtp.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path smtp +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth helo mailfrom rcptto date from to reply_to msg_id in_reply_to subject x_originating_ip first_received second_received last_reply path user_agent +#types time string addr port addr port count string string table[string] string string table[string] string string string string addr string string string vector[addr] string +1254722768.219663 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 GP Mon, 5 Oct 2009 11:36:07 +0530 "Gurpartap Singh" - <000301ca4581$ef9e57f0$cedb07d0$@in> - SMTP - - - 250 OK id=1Mugho-0003Dg-Un 74.53.140.153,10.10.1.4 Microsoft Office Outlook 12.0 diff --git a/testing/btest/Baseline/policy.protocols.smtp.mime-extract/smtp-entity_10.10.1.4:1470-74.53.140.153:25_1.dat b/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp-entity_10.10.1.4:1470-74.53.140.153:25_1.dat similarity index 100% rename from testing/btest/Baseline/policy.protocols.smtp.mime-extract/smtp-entity_10.10.1.4:1470-74.53.140.153:25_1.dat rename to testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp-entity_10.10.1.4:1470-74.53.140.153:25_1.dat diff --git a/testing/btest/Baseline/policy.protocols.smtp.mime-extract/smtp-entity_10.10.1.4:1470-74.53.140.153:25_2.dat b/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp-entity_10.10.1.4:1470-74.53.140.153:25_2.dat similarity index 100% rename from testing/btest/Baseline/policy.protocols.smtp.mime-extract/smtp-entity_10.10.1.4:1470-74.53.140.153:25_2.dat rename to testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp-entity_10.10.1.4:1470-74.53.140.153:25_2.dat diff --git a/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp_entities.log b/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp_entities.log new file mode 100644 index 0000000000..453b55932e --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.smtp.mime-extract/smtp_entities.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path smtp_entities +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth filename content_len mime_type md5 extraction_file excerpt +#types time string addr port addr port count string count string string file string +1254722770.692743 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 - 79 FAKE_MIME - smtp-entity_10.10.1.4:1470-74.53.140.153:25_1.dat (empty) +1254722770.692743 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 - 1918 FAKE_MIME - - (empty) +1254722770.692804 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 NEWS.txt 10823 FAKE_MIME - smtp-entity_10.10.1.4:1470-74.53.140.153:25_2.dat (empty) diff --git a/testing/btest/Baseline/scripts.base.protocols.smtp.mime/smtp_entities.log b/testing/btest/Baseline/scripts.base.protocols.smtp.mime/smtp_entities.log new file mode 100644 index 0000000000..2b471782d5 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.smtp.mime/smtp_entities.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path smtp_entities +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p trans_depth filename content_len mime_type md5 extraction_file excerpt +#types time string addr port addr port count string count string string file string +1254722770.692743 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 - 79 FAKE_MIME 92bca2e6cdcde73647125da7dccbdd07 - (empty) +1254722770.692743 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 - 1918 FAKE_MIME - - (empty) +1254722770.692804 arKYeMETxOg 10.10.1.4 1470 74.53.140.153 25 1 NEWS.txt 10823 FAKE_MIME a968bb0f9f9d95835b2e74c845877e87 - (empty) diff --git a/testing/btest/Baseline/policy.utils.addrs/output b/testing/btest/Baseline/scripts.base.utils.addrs/output similarity index 100% rename from testing/btest/Baseline/policy.utils.addrs/output rename to testing/btest/Baseline/scripts.base.utils.addrs/output diff --git a/testing/btest/Baseline/policy.utils.conn-ids/output b/testing/btest/Baseline/scripts.base.utils.conn-ids/output similarity index 100% rename from testing/btest/Baseline/policy.utils.conn-ids/output rename to testing/btest/Baseline/scripts.base.utils.conn-ids/output diff --git a/testing/btest/Baseline/policy.utils.directions-and-hosts/output b/testing/btest/Baseline/scripts.base.utils.directions-and-hosts/output similarity index 100% rename from testing/btest/Baseline/policy.utils.directions-and-hosts/output rename to testing/btest/Baseline/scripts.base.utils.directions-and-hosts/output diff --git a/testing/btest/Baseline/policy.utils.files/output b/testing/btest/Baseline/scripts.base.utils.files/output similarity index 88% rename from testing/btest/Baseline/policy.utils.files/output rename to testing/btest/Baseline/scripts.base.utils.files/output index 99691c7efb..ab92c3a624 100644 --- a/testing/btest/Baseline/policy.utils.files/output +++ b/testing/btest/Baseline/scripts.base.utils.files/output @@ -30,3 +30,7 @@ test-prefix_141.142.220.118:35642-208.80.152.2:80_test-suffix test-prefix_141.142.220.118:35642-208.80.152.2:80 141.142.220.118:35642-208.80.152.2:80_test-suffix 141.142.220.118:35642-208.80.152.2:80 +test-prefix_141.142.220.235:6705-173.192.163.128:80_test-suffix +test-prefix_141.142.220.235:6705-173.192.163.128:80 +141.142.220.235:6705-173.192.163.128:80_test-suffix +141.142.220.235:6705-173.192.163.128:80 diff --git a/testing/btest/Baseline/policy.utils.numbers/output b/testing/btest/Baseline/scripts.base.utils.numbers/output similarity index 100% rename from testing/btest/Baseline/policy.utils.numbers/output rename to testing/btest/Baseline/scripts.base.utils.numbers/output diff --git a/testing/btest/Baseline/policy.utils.paths/output b/testing/btest/Baseline/scripts.base.utils.paths/output similarity index 100% rename from testing/btest/Baseline/policy.utils.paths/output rename to testing/btest/Baseline/scripts.base.utils.paths/output diff --git a/testing/btest/Baseline/policy.utils.pattern/output b/testing/btest/Baseline/scripts.base.utils.pattern/output similarity index 100% rename from testing/btest/Baseline/policy.utils.pattern/output rename to testing/btest/Baseline/scripts.base.utils.pattern/output diff --git a/testing/btest/Baseline/policy.utils.site/output b/testing/btest/Baseline/scripts.base.utils.site/output similarity index 100% rename from testing/btest/Baseline/policy.utils.site/output rename to testing/btest/Baseline/scripts.base.utils.site/output diff --git a/testing/btest/Baseline/policy.utils.strings/output b/testing/btest/Baseline/scripts.base.utils.strings/output similarity index 100% rename from testing/btest/Baseline/policy.utils.strings/output rename to testing/btest/Baseline/scripts.base.utils.strings/output diff --git a/testing/btest/Baseline/policy.utils.thresholds/output b/testing/btest/Baseline/scripts.base.utils.thresholds/output similarity index 100% rename from testing/btest/Baseline/policy.utils.thresholds/output rename to testing/btest/Baseline/scripts.base.utils.thresholds/output diff --git a/testing/btest/Baseline/policy.misc.check-test-all-policy/output b/testing/btest/Baseline/scripts.check-test-all-policy/output similarity index 100% rename from testing/btest/Baseline/policy.misc.check-test-all-policy/output rename to testing/btest/Baseline/scripts.check-test-all-policy/output diff --git a/testing/btest/Baseline/scripts.policy.protocols.conn.known-hosts/knownhosts-all.log b/testing/btest/Baseline/scripts.policy.protocols.conn.known-hosts/knownhosts-all.log new file mode 100644 index 0000000000..0799292857 --- /dev/null +++ b/testing/btest/Baseline/scripts.policy.protocols.conn.known-hosts/knownhosts-all.log @@ -0,0 +1,11 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path known_hosts +#fields ts host +#types time addr +1300475168.783842 141.142.220.118 +1300475168.783842 208.80.152.118 +1300475168.915940 208.80.152.3 +1300475168.962628 208.80.152.2 diff --git a/testing/btest/Baseline/scripts.policy.protocols.conn.known-hosts/knownhosts-local.log b/testing/btest/Baseline/scripts.policy.protocols.conn.known-hosts/knownhosts-local.log new file mode 100644 index 0000000000..6fdba24d39 --- /dev/null +++ b/testing/btest/Baseline/scripts.policy.protocols.conn.known-hosts/knownhosts-local.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path known_hosts +#fields ts host +#types time addr +1300475168.783842 141.142.220.118 diff --git a/testing/btest/Baseline/scripts.policy.protocols.conn.known-hosts/knownhosts-remote.log b/testing/btest/Baseline/scripts.policy.protocols.conn.known-hosts/knownhosts-remote.log new file mode 100644 index 0000000000..9ef6ee47b7 --- /dev/null +++ b/testing/btest/Baseline/scripts.policy.protocols.conn.known-hosts/knownhosts-remote.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path known_hosts +#fields ts host +#types time addr +1300475168.783842 208.80.152.118 +1300475168.915940 208.80.152.3 +1300475168.962628 208.80.152.2 diff --git a/testing/btest/Baseline/scripts.policy.protocols.conn.known-services/knownservices-all.log b/testing/btest/Baseline/scripts.policy.protocols.conn.known-services/knownservices-all.log new file mode 100644 index 0000000000..d53da6f693 --- /dev/null +++ b/testing/btest/Baseline/scripts.policy.protocols.conn.known-services/knownservices-all.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path known_services +#fields ts host port_num port_proto service +#types time addr port enum table[string] +1308930691.049431 172.16.238.131 22 tcp SSH +1308930694.550308 172.16.238.131 80 tcp HTTP +1308930716.462556 74.125.225.81 80 tcp HTTP +1308930718.361665 172.16.238.131 21 tcp FTP +1308930726.872485 141.142.192.39 22 tcp SSH diff --git a/testing/btest/Baseline/scripts.policy.protocols.conn.known-services/knownservices-local.log b/testing/btest/Baseline/scripts.policy.protocols.conn.known-services/knownservices-local.log new file mode 100644 index 0000000000..ef1722d6a1 --- /dev/null +++ b/testing/btest/Baseline/scripts.policy.protocols.conn.known-services/knownservices-local.log @@ -0,0 +1,10 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path known_services +#fields ts host port_num port_proto service +#types time addr port enum table[string] +1308930691.049431 172.16.238.131 22 tcp SSH +1308930694.550308 172.16.238.131 80 tcp HTTP +1308930718.361665 172.16.238.131 21 tcp FTP diff --git a/testing/btest/Baseline/scripts.policy.protocols.conn.known-services/knownservices-remote.log b/testing/btest/Baseline/scripts.policy.protocols.conn.known-services/knownservices-remote.log new file mode 100644 index 0000000000..3fc68cdb91 --- /dev/null +++ b/testing/btest/Baseline/scripts.policy.protocols.conn.known-services/knownservices-remote.log @@ -0,0 +1,9 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path known_services +#fields ts host port_num port_proto service +#types time addr port enum table[string] +1308930716.462556 74.125.225.81 80 tcp HTTP +1308930726.872485 141.142.192.39 22 tcp SSH diff --git a/testing/btest/Baseline/scripts.policy.protocols.dns.event-priority/dns.log b/testing/btest/Baseline/scripts.policy.protocols.dns.event-priority/dns.log new file mode 100644 index 0000000000..f636093677 --- /dev/null +++ b/testing/btest/Baseline/scripts.policy.protocols.dns.event-priority/dns.log @@ -0,0 +1,8 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path dns +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs auth addl +#types time string addr port addr port enum count string count string count string count string bool bool bool bool count vector[string] vector[interval] table[string] table[string] +930613226.529070 UWkUyAuUGXf 212.180.42.100 25000 131.243.64.3 53 tcp 34798 - - - - - 0 NOERROR F F F T 0 4.3.2.1 31337.000000 - - diff --git a/testing/btest/Baseline/policy.protocols.http.test-sql-injection-regex/output b/testing/btest/Baseline/scripts.policy.protocols.http.test-sql-injection-regex/output similarity index 100% rename from testing/btest/Baseline/policy.protocols.http.test-sql-injection-regex/output rename to testing/btest/Baseline/scripts.policy.protocols.http.test-sql-injection-regex/output diff --git a/testing/btest/Makefile b/testing/btest/Makefile index 7489d761fb..257146daa0 100644 --- a/testing/btest/Makefile +++ b/testing/btest/Makefile @@ -2,12 +2,23 @@ DIAG=diag.log BTEST=../../aux/btest/btest -all: - # Showing all tests. - @rm -f $(DIAG) - @$(BTEST) -f $(DIAG) +all: cleanup btest-verbose coverage -brief: - # Brief output showing only failed tests. +# Showing all tests. +btest-verbose: + @$(BTEST) -j 5 -f $(DIAG) + +brief: cleanup btest-brief coverage + +# Brief output showing only failed tests. +btest-brief: + @$(BTEST) -j 5 -b -f $(DIAG) + +coverage: + @../scripts/coverage-calc ".tmp/script-coverage*" coverage.log `pwd`/../../scripts + +cleanup: @rm -f $(DIAG) - @$(BTEST) -b -f $(DIAG) + @rm -f .tmp/script-coverage* + +.PHONY: all btest-verbose brief btest-brief coverage cleanup diff --git a/testing/btest/README b/testing/btest/README index 82b6463ad9..6e8abd24ed 100644 --- a/testing/btest/README +++ b/testing/btest/README @@ -1,97 +1,85 @@ -BTest is simple framework for writing unit tests. Each test consists of a set -of command lines that will be executed, and success is determined based on -their exit codes. In addition, output can optionally be compared against a -previously established baseline. +This a test suite of small "unit tests" that verify individual pieces of Bro +functionality. They all utilize BTest, a simple framework/driver for +writing unit tests. More information about BTest can be found at +http://www.bro-ids.org/development/btest.html -More information about BTest can be found at http://www.icir.org/robin/btest/ +The test suite's BTest configuration is handled through the +``btest.cfg`` file. Of particular interest is the "TestDirs" settings, +which specifies which directories BTest will recursively search for +test files. +Significant Subdirectories +========================== -This README contains the following sections: - * Contents of the testing/btest/ directory - * Running tests - * Adding tests +* Baseline/ + Validated baselines for comparison against the output of each + test on future runs. If the new output differs from the Baseline + output, then the test fails. - -Contents of the testing/btest/ directory: - -Baseline/*/ - The validated baselines for comparison against the output of each test on - future runs. If the new output differs from the Baseline output, then the - test fails. - -Scripts/ - Shell scripts invoked by BTest to support testing. - -Traces/ +* Traces/ Packet captures utilized by the various BTest tests. -logging/ - Tests to validate the logging framework. +* scripts/ + This hierarchy of tests emulates the hierarchy of the Bro scripts/ + directory. -policy/ - Tests of the functionality of Bro's bundled policy scripts. +* coverage/ + This collection of tests relates to checking whether we're covering + everything we want to in terms of tests, documentation, and which + scripts get loaded in different Bro configurations. These tests are + more prone to fail as new Bro scripts are developed and added to the + distribution -- checking the individual test's comments is the best + place to check for more details on what exactly the test is checking + and hints on how to fix it when it fails. -software/ - Tests to validate Bro software not tested elsewhere. +Running Tests +============= -btest.cfg - Configuration file that specifies run-time settings for BTest. Of particular - interest is the "TestDirs" settings, which specifies which directories BTest - will recursively search for test files. +Either use the ``make all`` or ``make brief`` ``Makefile`` targets, or +run ``btest`` directly with desired options/arguments. Examples: + +* btest + If you simply execute btest in this directory with no arguments, + then all directories listed as "TestDirs" in btest.cfg will be + searched recursively for test files. -Running tests: - -btest - If you simply execute btest in this directory with no arguments, then all - directories listed as "TestDirs" in btest.cfg will be searched recursively - for test files. This is how the NMI automated build & test environment - invokes BTest to run all tests. +* btest test_directory + You can specify a directory on the command line to run just the + tests contained in that directory. This is useful if you wish to + run all of a given type of test, without running all the tests + there are. For example, "btest scripts" will run all of the Bro + script unit tests. -btest test_directory - You can specify a directory on the command line to run just the tests - contained in that directory. This is useful if you wish to run all of a - given type of test, without running all the tests there are. For example, - "btest policy" will run all of the tests for Bro's bundled policy scripts. - - -btest test_directory/test_file - You can specify a single test file to run just that test. This is useful - when testing a single aspect of Bro functionality, and also when developing +* btest test_directory/test_file + You can specify a single test file to run just that test. This + is useful when testing a single failing test or when developing a new test. +Adding Tests +============= +See either the `BTest documentation +`_ or the existing unit +tests for examples of what they actually look like. The essential +components of a new test include: -Adding tests: +* A test file in one of the subdirectories listed in the ``TestDirs`` + of the ``btest.cfg`` file. -See the documentation at http://www.icir.org/robin/btest/ for information on -what BTests actually look like. +* If the unit test requires a known-good baseline output against which + future tests will be compared (via ``btest-diff``), then that baseline + output will need to live in the ``Baseline`` directory. Manually + adding that is possible, but it's easier to just use the ``-u`` or + ``-U`` options of ``btest`` to do it for you (using ``btest -d`` on a + test for which no baseline exists will show you the output so it can + be verified first before adding/updating the baseline output). -The essential components of a new test include: -* A test file in a subdirectory of /testing/btest. This can be a sub-sub- - directory, as the search for test files is recursive from the directories - listed as "TestDirs" in btest.cfg -* A baseline for the output of your test. Although the baseline will be stored - in testing/btest/Baseline/ you should allow btest to copy the correct files - to that location, rather than copying them manually (see below). +If you create a new top-level testing directory for collecting related +tests, then you'll need to add it to the list of ``TestDirs`` in +``btest.cfg``. Do this only if your test really doesn't fit logically in +any of the extant directories. -If you create a new subdirectory from testing/btest you'll need to add it to the -list of "TestDirs" in btest.cfg. Do this only if your test really doesn't fit -logically in any of the extant directories. - -While developing your test, you can specify the "-t" command-line option to make -BTest preserve the testing/btest/.tmp directory. This directory holds the output -from your test run; you can inspect it in place to ensure it is correct and as -expected. - -Once you are satisfied with the results in testing/btest/.tmp you can make BTest -store this output as the Baseline for the test by specifying the "-U" command- -line option. - -When you are ready to commit your test to git, be sure the testing/btest/.tmp -directory is deleted, and use "git status" to ensure you correctly identify all -of the files that should be committed to the repository. - -Note that any new test you add this way will automatically be included in the -testing done in the NMI automated build & test environment. +Note that any new test you add this way will automatically be included +in the testing done in the NMI automated build & test environment. diff --git a/testing/btest/Traces/chksums/ip4-bad-chksum.pcap b/testing/btest/Traces/chksums/ip4-bad-chksum.pcap new file mode 100644 index 0000000000..6d8b9dd27d Binary files /dev/null and b/testing/btest/Traces/chksums/ip4-bad-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip4-icmp-bad-chksum.pcap b/testing/btest/Traces/chksums/ip4-icmp-bad-chksum.pcap new file mode 100644 index 0000000000..cc60d879c4 Binary files /dev/null and b/testing/btest/Traces/chksums/ip4-icmp-bad-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip4-icmp-good-chksum.pcap b/testing/btest/Traces/chksums/ip4-icmp-good-chksum.pcap new file mode 100644 index 0000000000..2b07326eab Binary files /dev/null and b/testing/btest/Traces/chksums/ip4-icmp-good-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip4-tcp-bad-chksum.pcap b/testing/btest/Traces/chksums/ip4-tcp-bad-chksum.pcap new file mode 100644 index 0000000000..b9ccd9e6b2 Binary files /dev/null and b/testing/btest/Traces/chksums/ip4-tcp-bad-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip4-tcp-good-chksum.pcap b/testing/btest/Traces/chksums/ip4-tcp-good-chksum.pcap new file mode 100644 index 0000000000..ff3f011884 Binary files /dev/null and b/testing/btest/Traces/chksums/ip4-tcp-good-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip4-udp-bad-chksum.pcap b/testing/btest/Traces/chksums/ip4-udp-bad-chksum.pcap new file mode 100644 index 0000000000..f3998c7e1c Binary files /dev/null and b/testing/btest/Traces/chksums/ip4-udp-bad-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip4-udp-good-chksum.pcap b/testing/btest/Traces/chksums/ip4-udp-good-chksum.pcap new file mode 100644 index 0000000000..3aec507329 Binary files /dev/null and b/testing/btest/Traces/chksums/ip4-udp-good-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-hoa-tcp-bad-chksum.pcap b/testing/btest/Traces/chksums/ip6-hoa-tcp-bad-chksum.pcap new file mode 100644 index 0000000000..3aa4bd21fa Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-hoa-tcp-bad-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-hoa-tcp-good-chksum.pcap b/testing/btest/Traces/chksums/ip6-hoa-tcp-good-chksum.pcap new file mode 100644 index 0000000000..a6fc9cb017 Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-hoa-tcp-good-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-hoa-udp-bad-chksum.pcap b/testing/btest/Traces/chksums/ip6-hoa-udp-bad-chksum.pcap new file mode 100644 index 0000000000..d2434dea80 Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-hoa-udp-bad-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-hoa-udp-good-chksum.pcap b/testing/btest/Traces/chksums/ip6-hoa-udp-good-chksum.pcap new file mode 100644 index 0000000000..f3e9d632c3 Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-hoa-udp-good-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-icmp6-bad-chksum.pcap b/testing/btest/Traces/chksums/ip6-icmp6-bad-chksum.pcap new file mode 100644 index 0000000000..ce1dfa547a Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-icmp6-bad-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-icmp6-good-chksum.pcap b/testing/btest/Traces/chksums/ip6-icmp6-good-chksum.pcap new file mode 100644 index 0000000000..4051fa5bc5 Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-icmp6-good-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-route0-icmp6-bad-chksum.pcap b/testing/btest/Traces/chksums/ip6-route0-icmp6-bad-chksum.pcap new file mode 100644 index 0000000000..15e11ed326 Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-route0-icmp6-bad-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-route0-icmp6-good-chksum.pcap b/testing/btest/Traces/chksums/ip6-route0-icmp6-good-chksum.pcap new file mode 100644 index 0000000000..b7924cab6f Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-route0-icmp6-good-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-route0-tcp-bad-chksum.pcap b/testing/btest/Traces/chksums/ip6-route0-tcp-bad-chksum.pcap new file mode 100644 index 0000000000..0f5711fe2e Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-route0-tcp-bad-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-route0-tcp-good-chksum.pcap b/testing/btest/Traces/chksums/ip6-route0-tcp-good-chksum.pcap new file mode 100644 index 0000000000..18f9a366c6 Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-route0-tcp-good-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-route0-udp-bad-chksum.pcap b/testing/btest/Traces/chksums/ip6-route0-udp-bad-chksum.pcap new file mode 100644 index 0000000000..b4eecae7a2 Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-route0-udp-bad-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-route0-udp-good-chksum.pcap b/testing/btest/Traces/chksums/ip6-route0-udp-good-chksum.pcap new file mode 100644 index 0000000000..deb1310107 Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-route0-udp-good-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-tcp-bad-chksum.pcap b/testing/btest/Traces/chksums/ip6-tcp-bad-chksum.pcap new file mode 100644 index 0000000000..38d8abf18f Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-tcp-bad-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-tcp-good-chksum.pcap b/testing/btest/Traces/chksums/ip6-tcp-good-chksum.pcap new file mode 100644 index 0000000000..9ab19b0ad8 Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-tcp-good-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-udp-bad-chksum.pcap b/testing/btest/Traces/chksums/ip6-udp-bad-chksum.pcap new file mode 100644 index 0000000000..25aa3fc2c3 Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-udp-bad-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/ip6-udp-good-chksum.pcap b/testing/btest/Traces/chksums/ip6-udp-good-chksum.pcap new file mode 100644 index 0000000000..b72b86678e Binary files /dev/null and b/testing/btest/Traces/chksums/ip6-udp-good-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/mip6-bad-mh-chksum.pcap b/testing/btest/Traces/chksums/mip6-bad-mh-chksum.pcap new file mode 100644 index 0000000000..9a2437baef Binary files /dev/null and b/testing/btest/Traces/chksums/mip6-bad-mh-chksum.pcap differ diff --git a/testing/btest/Traces/chksums/mip6-good-mh-chksum.pcap b/testing/btest/Traces/chksums/mip6-good-mh-chksum.pcap new file mode 100644 index 0000000000..6183fd9cb1 Binary files /dev/null and b/testing/btest/Traces/chksums/mip6-good-mh-chksum.pcap differ diff --git a/testing/btest/Traces/ftp-ipv4.trace b/testing/btest/Traces/ftp-ipv4.trace new file mode 100644 index 0000000000..02cac6f464 Binary files /dev/null and b/testing/btest/Traces/ftp-ipv4.trace differ diff --git a/testing/btest/Traces/http-100-continue.trace b/testing/btest/Traces/http-100-continue.trace new file mode 100644 index 0000000000..3ff38fa5c5 Binary files /dev/null and b/testing/btest/Traces/http-100-continue.trace differ diff --git a/testing/btest/Traces/icmp/icmp-destunreach-ip.pcap b/testing/btest/Traces/icmp/icmp-destunreach-ip.pcap new file mode 100644 index 0000000000..982f2e4734 Binary files /dev/null and b/testing/btest/Traces/icmp/icmp-destunreach-ip.pcap differ diff --git a/testing/btest/Traces/icmp/icmp-destunreach-no-context.pcap b/testing/btest/Traces/icmp/icmp-destunreach-no-context.pcap new file mode 100644 index 0000000000..1f904e3d91 Binary files /dev/null and b/testing/btest/Traces/icmp/icmp-destunreach-no-context.pcap differ diff --git a/testing/btest/Traces/icmp/icmp-destunreach-udp.pcap b/testing/btest/Traces/icmp/icmp-destunreach-udp.pcap new file mode 100644 index 0000000000..60137bb6fe Binary files /dev/null and b/testing/btest/Traces/icmp/icmp-destunreach-udp.pcap differ diff --git a/testing/btest/Traces/icmp/icmp-ping.pcap b/testing/btest/Traces/icmp/icmp-ping.pcap new file mode 100644 index 0000000000..499769b280 Binary files /dev/null and b/testing/btest/Traces/icmp/icmp-ping.pcap differ diff --git a/testing/btest/Traces/icmp/icmp-timeexceeded.pcap b/testing/btest/Traces/icmp/icmp-timeexceeded.pcap new file mode 100644 index 0000000000..27804b5559 Binary files /dev/null and b/testing/btest/Traces/icmp/icmp-timeexceeded.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext-trunc.pcap b/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext-trunc.pcap new file mode 100644 index 0000000000..bd0e0ccd42 Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext-trunc.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext-udp.pcap b/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext-udp.pcap new file mode 100644 index 0000000000..5aca9af1b5 Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext-udp.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext.pcap b/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext.pcap new file mode 100644 index 0000000000..996048e5ab Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-destunreach-ip6ext.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-destunreach-no-context.pcap b/testing/btest/Traces/icmp/icmp6-destunreach-no-context.pcap new file mode 100644 index 0000000000..cf15a7cf65 Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-destunreach-no-context.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-neighbor-advert.pcap b/testing/btest/Traces/icmp/icmp6-neighbor-advert.pcap new file mode 100644 index 0000000000..0a06329fb5 Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-neighbor-advert.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-neighbor-solicit.pcap b/testing/btest/Traces/icmp/icmp6-neighbor-solicit.pcap new file mode 100644 index 0000000000..248bbae4ea Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-neighbor-solicit.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-paramprob.pcap b/testing/btest/Traces/icmp/icmp6-paramprob.pcap new file mode 100644 index 0000000000..ab2d41cd3a Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-paramprob.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-ping.pcap b/testing/btest/Traces/icmp/icmp6-ping.pcap new file mode 100644 index 0000000000..1638ca0822 Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-ping.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-redirect.pcap b/testing/btest/Traces/icmp/icmp6-redirect.pcap new file mode 100644 index 0000000000..f8ae7ed96b Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-redirect.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-router-advert.pcap b/testing/btest/Traces/icmp/icmp6-router-advert.pcap new file mode 100644 index 0000000000..9c3e557a9d Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-router-advert.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-router-solicit.pcap b/testing/btest/Traces/icmp/icmp6-router-solicit.pcap new file mode 100644 index 0000000000..b33495aa8d Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-router-solicit.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-timeexceeded.pcap b/testing/btest/Traces/icmp/icmp6-timeexceeded.pcap new file mode 100644 index 0000000000..b32fc4ab68 Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-timeexceeded.pcap differ diff --git a/testing/btest/Traces/icmp/icmp6-toobig.pcap b/testing/btest/Traces/icmp/icmp6-toobig.pcap new file mode 100644 index 0000000000..92bf50f240 Binary files /dev/null and b/testing/btest/Traces/icmp/icmp6-toobig.pcap differ diff --git a/testing/btest/Traces/ip6_esp.trace b/testing/btest/Traces/ip6_esp.trace new file mode 100644 index 0000000000..8b3b19a99a Binary files /dev/null and b/testing/btest/Traces/ip6_esp.trace differ diff --git a/testing/btest/Traces/ipv6-fragmented-dns.trace b/testing/btest/Traces/ipv6-fragmented-dns.trace new file mode 100755 index 0000000000..9dda47a8a9 Binary files /dev/null and b/testing/btest/Traces/ipv6-fragmented-dns.trace differ diff --git a/testing/btest/Traces/ipv6-ftp.trace b/testing/btest/Traces/ipv6-ftp.trace new file mode 100644 index 0000000000..81313fac11 Binary files /dev/null and b/testing/btest/Traces/ipv6-ftp.trace differ diff --git a/testing/btest/Traces/ipv6-hbh-routing0.trace b/testing/btest/Traces/ipv6-hbh-routing0.trace new file mode 100644 index 0000000000..2a294ed58e Binary files /dev/null and b/testing/btest/Traces/ipv6-hbh-routing0.trace differ diff --git a/testing/btest/Traces/ipv6-http-atomic-frag.trace b/testing/btest/Traces/ipv6-http-atomic-frag.trace new file mode 100644 index 0000000000..d5d9db276c Binary files /dev/null and b/testing/btest/Traces/ipv6-http-atomic-frag.trace differ diff --git a/testing/btest/Traces/mobile-ipv6/ipv6-mobile-hoa.trace b/testing/btest/Traces/mobile-ipv6/ipv6-mobile-hoa.trace new file mode 100644 index 0000000000..f3e9d632c3 Binary files /dev/null and b/testing/btest/Traces/mobile-ipv6/ipv6-mobile-hoa.trace differ diff --git a/testing/btest/Traces/mobile-ipv6/ipv6-mobile-routing.trace b/testing/btest/Traces/mobile-ipv6/ipv6-mobile-routing.trace new file mode 100644 index 0000000000..6289f268e3 Binary files /dev/null and b/testing/btest/Traces/mobile-ipv6/ipv6-mobile-routing.trace differ diff --git a/testing/btest/Traces/mobile-ipv6/mip6_back.trace b/testing/btest/Traces/mobile-ipv6/mip6_back.trace new file mode 100644 index 0000000000..9b97186979 Binary files /dev/null and b/testing/btest/Traces/mobile-ipv6/mip6_back.trace differ diff --git a/testing/btest/Traces/mobile-ipv6/mip6_be.trace b/testing/btest/Traces/mobile-ipv6/mip6_be.trace new file mode 100644 index 0000000000..19862ee4be Binary files /dev/null and b/testing/btest/Traces/mobile-ipv6/mip6_be.trace differ diff --git a/testing/btest/Traces/mobile-ipv6/mip6_brr.trace b/testing/btest/Traces/mobile-ipv6/mip6_brr.trace new file mode 100644 index 0000000000..4020ae8b14 Binary files /dev/null and b/testing/btest/Traces/mobile-ipv6/mip6_brr.trace differ diff --git a/testing/btest/Traces/mobile-ipv6/mip6_bu.trace b/testing/btest/Traces/mobile-ipv6/mip6_bu.trace new file mode 100644 index 0000000000..1c8c61e09d Binary files /dev/null and b/testing/btest/Traces/mobile-ipv6/mip6_bu.trace differ diff --git a/testing/btest/Traces/mobile-ipv6/mip6_cot.trace b/testing/btest/Traces/mobile-ipv6/mip6_cot.trace new file mode 100644 index 0000000000..2d8d215a41 Binary files /dev/null and b/testing/btest/Traces/mobile-ipv6/mip6_cot.trace differ diff --git a/testing/btest/Traces/mobile-ipv6/mip6_coti.trace b/testing/btest/Traces/mobile-ipv6/mip6_coti.trace new file mode 100644 index 0000000000..2a5790cc7c Binary files /dev/null and b/testing/btest/Traces/mobile-ipv6/mip6_coti.trace differ diff --git a/testing/btest/Traces/mobile-ipv6/mip6_hot.trace b/testing/btest/Traces/mobile-ipv6/mip6_hot.trace new file mode 100644 index 0000000000..0b54c9797d Binary files /dev/null and b/testing/btest/Traces/mobile-ipv6/mip6_hot.trace differ diff --git a/testing/btest/Traces/mobile-ipv6/mip6_hoti.trace b/testing/btest/Traces/mobile-ipv6/mip6_hoti.trace new file mode 100644 index 0000000000..3daaeb2905 Binary files /dev/null and b/testing/btest/Traces/mobile-ipv6/mip6_hoti.trace differ diff --git a/testing/btest/Traces/trunc/ip4-trunc.pcap b/testing/btest/Traces/trunc/ip4-trunc.pcap new file mode 100644 index 0000000000..30df0ea94d Binary files /dev/null and b/testing/btest/Traces/trunc/ip4-trunc.pcap differ diff --git a/testing/btest/Traces/trunc/ip6-ext-trunc.pcap b/testing/btest/Traces/trunc/ip6-ext-trunc.pcap new file mode 100644 index 0000000000..1de659084e Binary files /dev/null and b/testing/btest/Traces/trunc/ip6-ext-trunc.pcap differ diff --git a/testing/btest/Traces/trunc/ip6-trunc.pcap b/testing/btest/Traces/trunc/ip6-trunc.pcap new file mode 100644 index 0000000000..0111caed0f Binary files /dev/null and b/testing/btest/Traces/trunc/ip6-trunc.pcap differ diff --git a/testing/btest/Traces/www-odd-url.trace b/testing/btest/Traces/www-odd-url.trace new file mode 100644 index 0000000000..2fd86c50c2 Binary files /dev/null and b/testing/btest/Traces/www-odd-url.trace differ diff --git a/testing/btest/analyzers/conn-size.bro b/testing/btest/analyzers/conn-size.bro index 0e413cc554..0ba7977cf5 100644 --- a/testing/btest/analyzers/conn-size.bro +++ b/testing/btest/analyzers/conn-size.bro @@ -1,2 +1,2 @@ -# @TEST-EXEC: bro -C -r ${TRACES}/conn-size.trace tcp udp icmp report_conn_size_analyzer=T use_connection_compressor=F +# @TEST-EXEC: bro -C -r ${TRACES}/conn-size.trace tcp udp icmp report_conn_size_analyzer=T # @TEST-EXEC: btest-diff conn.log diff --git a/testing/btest/bifs/addr_count_conversion.bro b/testing/btest/bifs/addr_count_conversion.bro new file mode 100644 index 0000000000..360994a8e5 --- /dev/null +++ b/testing/btest/bifs/addr_count_conversion.bro @@ -0,0 +1,11 @@ +# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: btest-diff output + +global v: index_vec; + +v = addr_to_counts([2001:0db8:85a3:0000:0000:8a2e:0370:7334]); +print v; +print counts_to_addr(v); +v = addr_to_counts(1.2.3.4); +print v; +print counts_to_addr(v); diff --git a/testing/btest/bifs/addr_to_ptr_name.bro b/testing/btest/bifs/addr_to_ptr_name.bro new file mode 100644 index 0000000000..b9c831d061 --- /dev/null +++ b/testing/btest/bifs/addr_to_ptr_name.bro @@ -0,0 +1,6 @@ +# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: btest-diff output + +print addr_to_ptr_name([2607:f8b0:4009:802::1012]); +print addr_to_ptr_name(74.125.225.52); + diff --git a/testing/btest/bifs/addr_version.bro b/testing/btest/bifs/addr_version.bro new file mode 100644 index 0000000000..3e0123ef42 --- /dev/null +++ b/testing/btest/bifs/addr_version.bro @@ -0,0 +1,7 @@ +# @TEST-EXEC: bro %INPUT >out +# @TEST-EXEC: btest-diff out + +print is_v4_addr(1.2.3.4); +print is_v4_addr([::1]); +print is_v6_addr(1.2.3.4); +print is_v6_addr([::1]); diff --git a/testing/btest/bifs/decode_base64.bro b/testing/btest/bifs/decode_base64.bro new file mode 100644 index 0000000000..d4cbd2f37d --- /dev/null +++ b/testing/btest/bifs/decode_base64.bro @@ -0,0 +1,14 @@ +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out + +global default_alphabet: string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +global my_alphabet: string = "!#$%&/(),-.:;<>@[]^ `_{|}~abcdefghijklmnopqrstuvwxyz0123456789+?"; + +print decode_base64("YnJv"); +print decode_base64_custom("YnJv", default_alphabet); +print decode_base64_custom("}n-v", my_alphabet); + +print decode_base64("YnJv"); +print decode_base64_custom("YnJv", default_alphabet); +print decode_base64_custom("}n-v", my_alphabet); diff --git a/testing/btest/bifs/install_src_addr_filter.test b/testing/btest/bifs/install_src_addr_filter.test new file mode 100644 index 0000000000..5b387832de --- /dev/null +++ b/testing/btest/bifs/install_src_addr_filter.test @@ -0,0 +1,13 @@ +# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +event bro_init() + { + install_src_addr_filter(141.142.220.118, TH_SYN, 100.0); + } + +event new_packet(c: connection, p: pkt_hdr) + { + if ( p?$tcp && p$ip$src == 141.142.220.118 ) + print c$id; + } diff --git a/testing/btest/bifs/ptr_name_to_addr.bro b/testing/btest/bifs/ptr_name_to_addr.bro new file mode 100644 index 0000000000..89679ba57a --- /dev/null +++ b/testing/btest/bifs/ptr_name_to_addr.bro @@ -0,0 +1,8 @@ +# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: btest-diff output + +global v6 = ptr_name_to_addr("2.1.0.1.0.0.0.0.0.0.0.0.0.0.0.0.2.0.8.0.9.0.0.4.0.b.8.f.7.0.6.2.ip6.arpa"); +global v4 = ptr_name_to_addr("52.225.125.74.in-addr.arpa"); + +print v6; +print v4; \ No newline at end of file diff --git a/testing/btest/bifs/remask_addr.bro b/testing/btest/bifs/remask_addr.bro new file mode 100644 index 0000000000..d387667b6a --- /dev/null +++ b/testing/btest/bifs/remask_addr.bro @@ -0,0 +1,10 @@ +# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: btest-diff output + +const one_to_32: vector of count = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32}; + +for ( i in one_to_32 ) + { + print fmt("%s: %s", one_to_32[i], + remask_addr(0.0.255.255, 255.255.0.0, 96+one_to_32[i])); + } diff --git a/testing/btest/bifs/routing0_data_to_addrs.test b/testing/btest/bifs/routing0_data_to_addrs.test new file mode 100644 index 0000000000..a20bb3bf59 --- /dev/null +++ b/testing/btest/bifs/routing0_data_to_addrs.test @@ -0,0 +1,10 @@ +# @TEST-EXEC: bro -b -r $TRACES/ipv6-hbh-routing0.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +event ipv6_ext_headers(c: connection, p: pkt_hdr) + { + for ( h in p$ip6$exts ) + if ( p$ip6$exts[h]$id == IPPROTO_ROUTING ) + if ( p$ip6$exts[h]$routing$rtype == 0 ) + print routing0_data_to_addrs(p$ip6$exts[h]$routing$data); + } diff --git a/testing/btest/bifs/to_addr.bro b/testing/btest/bifs/to_addr.bro new file mode 100644 index 0000000000..3a43438bb7 --- /dev/null +++ b/testing/btest/bifs/to_addr.bro @@ -0,0 +1,20 @@ +# @TEST-EXEC: bro -b %INPUT >output 2>error +# @TEST-EXEC: btest-diff output +# @TEST-EXEC: btest-diff error + +function test_to_addr(ip: string, expect: addr) + { + local result = to_addr(ip); + print fmt("to_addr(%s) = %s (%s)", ip, result, + result == expect ? "SUCCESS" : "FAILURE"); + } + +test_to_addr("0.0.0.0", 0.0.0.0); +test_to_addr("1.2.3.4", 1.2.3.4); +test_to_addr("01.02.03.04", 1.2.3.4); +test_to_addr("001.002.003.004", 1.2.3.4); +test_to_addr("10.20.30.40", 10.20.30.40); +test_to_addr("100.200.30.40", 100.200.30.40); +test_to_addr("10.0.0.0", 10.0.0.0); +test_to_addr("10.00.00.000", 10.0.0.0); +test_to_addr("not an IP", [::]); diff --git a/testing/btest/bifs/to_subnet.bro b/testing/btest/bifs/to_subnet.bro new file mode 100644 index 0000000000..59064893e1 --- /dev/null +++ b/testing/btest/bifs/to_subnet.bro @@ -0,0 +1,11 @@ +# @TEST-EXEC: bro -b %INPUT >output 2>error +# @TEST-EXEC: btest-diff output +# @TEST-EXEC: btest-diff error + +global sn: subnet; +sn = to_subnet("10.0.0.0/8"); +print sn, sn == 10.0.0.0/8; +sn = to_subnet("2607:f8b0::/32"); +print sn, sn == [2607:f8b0::]/32; +sn = to_subnet("10.0.0.0"); +print sn, sn == [::]/0; diff --git a/testing/btest/bifs/unique_id-pools.bro b/testing/btest/bifs/unique_id-pools.bro new file mode 100644 index 0000000000..abdc4b22ba --- /dev/null +++ b/testing/btest/bifs/unique_id-pools.bro @@ -0,0 +1,27 @@ +# +# @TEST-EXEC: bro order_rand | sort >out.1 +# @TEST-EXEC: bro order_base | sort >out.2 +# @TEST-EXEC: cmp out.1 out.2 + +@TEST-START-FILE order_rand.bro + +print unique_id("A-"); +print unique_id_from(5, "E-"); +print unique_id("B-"); +print unique_id_from(4, "D-"); +print unique_id("C-"); +print unique_id_from(5, "F-"); + +@TEST-END-FILE + +@TEST-START-FILE order_base.bro + +print unique_id("A-"); +print unique_id("B-"); +print unique_id("C-"); +print unique_id_from(4, "D-"); +print unique_id_from(5, "E-"); +print unique_id_from(5, "F-"); + +@TEST-END-FILE + diff --git a/testing/btest/bifs/unique_id-rnd.bro b/testing/btest/bifs/unique_id-rnd.bro index d3b3b85849..4188725373 100644 --- a/testing/btest/bifs/unique_id-rnd.bro +++ b/testing/btest/bifs/unique_id-rnd.bro @@ -7,3 +7,6 @@ print unique_id("A-"); print unique_id("B-"); print unique_id("C-"); +print unique_id_from(4, "D-"); +print unique_id_from(5, "E-"); +print unique_id_from(5, "F-"); diff --git a/testing/btest/bifs/unique_id.bro b/testing/btest/bifs/unique_id.bro index d421803aa0..097f5d490d 100644 --- a/testing/btest/bifs/unique_id.bro +++ b/testing/btest/bifs/unique_id.bro @@ -5,3 +5,6 @@ print unique_id("A-"); print unique_id("B-"); print unique_id("C-"); +print unique_id_from(4, "D-"); +print unique_id_from(5, "E-"); +print unique_id_from(5, "F-"); diff --git a/testing/btest/btest.cfg b/testing/btest/btest.cfg index 1aa7b28f25..6afbde1ddb 100644 --- a/testing/btest/btest.cfg +++ b/testing/btest/btest.cfg @@ -1,5 +1,5 @@ [btest] -TestDirs = doc bifs language core policy istate +TestDirs = doc bifs language core scripts istate coverage TmpDir = %(testbase)s/.tmp BaselineDir = %(testbase)s/Baseline IgnoreDirs = .svn CVS .tmp @@ -10,9 +10,12 @@ BROPATH=`bash -c %(testbase)s/../../build/bro-path-dev` BRO_SEED_FILE=%(testbase)s/random.seed TZ=UTC LC_ALL=C -PATH=%(testbase)s/../../build/src:%(testbase)s/../../aux/btest:%(default_path)s +BTEST_PATH=%(testbase)s/../../aux/btest +PATH=%(testbase)s/../../build/src:%(testbase)s/../scripts:%(testbase)s/../../aux/btest:%(default_path)s TRACES=%(testbase)s/Traces SCRIPTS=%(testbase)s/../scripts DIST=%(testbase)s/../.. BUILD=%(testbase)s/../../build TEST_DIFF_CANONIFIER=$SCRIPTS/diff-canonifier +TMPDIR=%(testbase)s/.tmp +BRO_PROFILER_FILE=%(testbase)s/.tmp/script-coverage.XXXXXX diff --git a/testing/btest/core/check-unused-event-handlers.test b/testing/btest/core/check-unused-event-handlers.test new file mode 100644 index 0000000000..f9ad105ff6 --- /dev/null +++ b/testing/btest/core/check-unused-event-handlers.test @@ -0,0 +1,8 @@ +# This test should print a warning that the event handler is never invoked. +# @TEST-EXEC: bro -b %INPUT check_for_unused_event_handlers=T +# @TEST-EXEC: btest-diff .stderr + +event this_is_never_used() + { + print "not even once"; + } diff --git a/testing/btest/core/checksums.test b/testing/btest/core/checksums.test new file mode 100644 index 0000000000..f5b3230686 --- /dev/null +++ b/testing/btest/core/checksums.test @@ -0,0 +1,23 @@ +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-tcp-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-udp-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-icmp-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-route0-tcp-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-route0-udp-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-route0-icmp6-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-tcp-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-udp-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-icmp6-bad-chksum.pcap >>bad.out 2>&1 + + +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-tcp-good-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-udp-good-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip4-icmp-good-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-route0-tcp-good-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-route0-udp-good-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-route0-icmp6-good-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-tcp-good-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-udp-good-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-icmp6-good-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: btest-diff bad.out +# @TEST-EXEC: btest-diff good.out diff --git a/testing/btest/core/conn-uid.bro b/testing/btest/core/conn-uid.bro index b2078bc9f5..52ff8fc4d3 100644 --- a/testing/btest/core/conn-uid.bro +++ b/testing/btest/core/conn-uid.bro @@ -9,17 +9,6 @@ # @TEST-EXEC: unset BRO_SEED_FILE && bro -C -r $TRACES/wikipedia.trace %INPUT >output2 # @TEST-EXEC: cat output output2 | sort | uniq -c | wc -l | sed 's/ //g' >counts # @TEST-EXEC: btest-diff counts -# -# Make sure it works without the connection compressor as well. -# -# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace %INPUT use_connection_compressor=F >output.cc -# @TEST-EXEC: btest-diff output.cc -# -# Make sure it works with the full connection compressor as well. -# -# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace %INPUT cc_handle_only_syns=F >output.cc2 -# @TEST-EXEC: btest-diff output.cc2 - event new_connection(c: connection) { diff --git a/testing/btest/core/disable-mobile-ipv6.test b/testing/btest/core/disable-mobile-ipv6.test new file mode 100644 index 0000000000..84dc43dae8 --- /dev/null +++ b/testing/btest/core/disable-mobile-ipv6.test @@ -0,0 +1,12 @@ +# @TEST-REQUIRES: grep -q "#undef ENABLE_MOBILE_IPV6" $BUILD/config.h +# @TEST-EXEC: bro -b -r $TRACES/mobile-ipv6/mip6_back.trace %INPUT >output 2>&1 +# @TEST-EXEC: btest-diff output + +event mobile_ipv6_message(p: pkt_hdr) + { + if ( ! p?$ip6 ) return; + + for ( i in p$ip6$exts ) + if ( p$ip6$exts[i]$id == IPPROTO_MOBILITY ) + print p$ip6; + } diff --git a/testing/btest/core/discarder.bro b/testing/btest/core/discarder.bro new file mode 100644 index 0000000000..0c87eece18 --- /dev/null +++ b/testing/btest/core/discarder.bro @@ -0,0 +1,92 @@ +# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-ip.bro >output +# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-tcp.bro >>output +# @TEST-EXEC: bro -C -r $TRACES/wikipedia.trace discarder-udp.bro >>output +# @TEST-EXEC: bro -C -r $TRACES/icmp/icmp-destunreach-udp.pcap discarder-icmp.bro >>output +# @TEST-EXEC: btest-diff output + +@TEST-START-FILE discarder-ip.bro + +event bro_init() + { + print "################ IP Discarder ################"; + } + +function discarder_check_ip(p: pkt_hdr): bool + { + if ( p?$ip && p$ip$src == 141.142.220.118 && p$ip$dst == 208.80.152.2 ) + return F; + return T; + } + + +event new_packet(c: connection, p: pkt_hdr) + { + print c$id; + } + +@TEST-END-FILE + +@TEST-START-FILE discarder-tcp.bro + +event bro_init() + { + print "################ TCP Discarder ################"; + } + +function discarder_check_tcp(p: pkt_hdr, d: string): bool + { + if ( p$tcp$flags == TH_SYN ) + return F; + return T; + } + +event new_packet(c: connection, p: pkt_hdr) + { + if ( p?$tcp ) + print c$id; + } + +@TEST-END-FILE + +@TEST-START-FILE discarder-udp.bro + +event bro_init() + { + print "################ UDP Discarder ################"; + } + +function discarder_check_udp(p: pkt_hdr, d: string): bool + { + if ( p?$ip6 ) + return F; + return T; + } + +event new_packet(c: connection, p: pkt_hdr) + { + if ( p?$udp ) + print c$id; + } + +@TEST-END-FILE + +@TEST-START-FILE discarder-icmp.bro + +event bro_init() + { + print "################ ICMP Discarder ################"; + } + +function discarder_check_icmp(p: pkt_hdr): bool + { + print fmt("Discard icmp packet: %s", p$icmp); + return T; + } + +event new_packet(c: connection, p: pkt_hdr) + { + if ( p?$icmp ) + print c$id; + } + +@TEST-END-FILE diff --git a/testing/btest/core/dns-init.bro b/testing/btest/core/dns-init.bro new file mode 100644 index 0000000000..5a7efff6fb --- /dev/null +++ b/testing/btest/core/dns-init.bro @@ -0,0 +1,9 @@ +# We once had a bug where DNS lookups at init time lead to an immediate crash. +# +# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: btest-diff output + +const foo: set[addr] = { + google.com +}; + diff --git a/testing/btest/core/expr-exception.bro b/testing/btest/core/expr-exception.bro new file mode 100644 index 0000000000..5225f092ba --- /dev/null +++ b/testing/btest/core/expr-exception.bro @@ -0,0 +1,9 @@ +# Bro shouldn't crash when doing nothing, nor outputting anything. +# +# @TEST-EXEC: cat /dev/null | bro -r $TRACES/wikipedia.trace %INPUT +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff reporter.log + +event connection_established(c: connection) + { + print c$ftp; + } diff --git a/testing/btest/core/icmp/icmp-context.test b/testing/btest/core/icmp/icmp-context.test new file mode 100644 index 0000000000..ca7a34c5aa --- /dev/null +++ b/testing/btest/core/icmp/icmp-context.test @@ -0,0 +1,14 @@ +# These tests all check that IPv6 context packet construction for ICMP6 works. + +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-destunreach-no-context.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-destunreach-ip.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-destunreach-udp.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: btest-diff output + +event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_unreachable (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } diff --git a/testing/btest/core/icmp/icmp-events.test b/testing/btest/core/icmp/icmp-events.test new file mode 100644 index 0000000000..1a54f05fba --- /dev/null +++ b/testing/btest/core/icmp/icmp-events.test @@ -0,0 +1,44 @@ +# These tests all check that ICMP6 events get raised with correct arguments. + +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-destunreach-udp.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-timeexceeded.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp-ping.pcap %INPUT >>output 2>&1 + +# @TEST-EXEC: btest-diff output + +event icmp_sent(c: connection, icmp: icmp_conn) + { + print "icmp_sent"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) + { + print "icmp_echo_request (id=" + fmt("%d", id) + ", seq=" + fmt("%d", seq) + ", payload=" + payload + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) + { + print "icmp_echo_reply (id=" + fmt("%d", id) + ", seq=" + fmt("%d", seq) + ", payload=" + payload + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_unreachable (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } + +event icmp_time_exceeded(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_time_exceeded (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } diff --git a/testing/btest/core/icmp/icmp6-context.test b/testing/btest/core/icmp/icmp6-context.test new file mode 100644 index 0000000000..dfa8271cbc --- /dev/null +++ b/testing/btest/core/icmp/icmp6-context.test @@ -0,0 +1,15 @@ +# These tests all check that IPv6 context packet construction for ICMP6 works. + +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-no-context.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-ip6ext-trunc.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-ip6ext-udp.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-ip6ext.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: btest-diff output + +event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_unreachable (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } diff --git a/testing/btest/core/icmp/icmp6-events.test b/testing/btest/core/icmp/icmp6-events.test new file mode 100644 index 0000000000..64c14920ff --- /dev/null +++ b/testing/btest/core/icmp/icmp6-events.test @@ -0,0 +1,110 @@ +# These tests all check that ICMP6 events get raised with correct arguments. + +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-destunreach-ip6ext-udp.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-toobig.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-timeexceeded.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-paramprob.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-ping.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-redirect.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-router-advert.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-neighbor-advert.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-router-solicit.pcap %INPUT >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/icmp/icmp6-neighbor-solicit.pcap %INPUT >>output 2>&1 + +# @TEST-EXEC: btest-diff output + +event icmp_sent(c: connection, icmp: icmp_conn) + { + print "icmp_sent"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_echo_request(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) + { + print "icmp_echo_request (id=" + fmt("%d", id) + ", seq=" + fmt("%d", seq) + ", payload=" + payload + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_echo_reply(c: connection, icmp: icmp_conn, id: count, seq: count, payload: string) + { + print "icmp_echo_reply (id=" + fmt("%d", id) + ", seq=" + fmt("%d", seq) + ", payload=" + payload + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_unreachable(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_unreachable (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } + +event icmp_packet_too_big(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_packet_too_big (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } + +event icmp_time_exceeded(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_time_exceeded (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } + +event icmp_parameter_problem(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_parameter_problem (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } + +event icmp_redirect(c: connection, icmp: icmp_conn, tgt: addr, dest: addr) + { + print "icmp_redirect (tgt=" + fmt("%s", tgt) + ", dest=" + fmt("%s", dest) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_error_message(c: connection, icmp: icmp_conn, code: count, context: icmp_context) + { + print "icmp_error_message (code=" + fmt("%d", code) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + print " icmp_context: " + fmt("%s", context); + } + +event icmp_neighbor_solicitation(c: connection, icmp: icmp_conn, tgt: addr) + { + print "icmp_neighbor_solicitation (tgt=" + fmt("%s", tgt) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_neighbor_advertisement(c: connection, icmp: icmp_conn, tgt:addr) + { + print "icmp_neighbor_advertisement (tgt=" + fmt("%s", tgt) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_router_solicitation(c: connection, icmp: icmp_conn) + { + print "icmp_router_solicitation"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } + +event icmp_router_advertisement(c: connection, icmp: icmp_conn, hop_limit: count, managed: bool, router_lifetime: count, reachable_time: interval, retrans_timer: interval) + { + print "icmp_router_advertisement (hop_limit=" + fmt("%d", hop_limit) + ", managed=" + fmt("%s", managed) + ", rlifetime=" + fmt("%d", router_lifetime) + ", reachable=" + fmt("%f", reachable_time) + ", retrans=" + fmt("%f", retrans_timer) + ")"; + print " conn_id: " + fmt("%s", c$id); + print " icmp_conn: " + fmt("%s", icmp); + } diff --git a/testing/btest/core/ipv6-atomic-frag.test b/testing/btest/core/ipv6-atomic-frag.test new file mode 100644 index 0000000000..8c8fe6ca64 --- /dev/null +++ b/testing/btest/core/ipv6-atomic-frag.test @@ -0,0 +1,8 @@ +# @TEST-EXEC: bro -r $TRACES/ipv6-http-atomic-frag.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +event new_connection(c: connection) + { + if ( c$id$resp_p == 80/tcp ) + print c$id; + } diff --git a/testing/btest/core/ipv6-frag.test b/testing/btest/core/ipv6-frag.test new file mode 100644 index 0000000000..32c7c0a8c1 --- /dev/null +++ b/testing/btest/core/ipv6-frag.test @@ -0,0 +1,9 @@ +# @TEST-EXEC: bro -r $TRACES/ipv6-fragmented-dns.trace %INPUT >output +# @TEST-EXEC: btest-diff output +# @TEST-EXEC: btest-diff dns.log + +event new_packet(c: connection, p: pkt_hdr) + { + if ( p?$ip6 && p?$ udp ) + print fmt("ip6=%s, udp = %s", p$ip6, p$udp); + } diff --git a/testing/btest/core/ipv6_esp.test b/testing/btest/core/ipv6_esp.test new file mode 100644 index 0000000000..8744df0036 --- /dev/null +++ b/testing/btest/core/ipv6_esp.test @@ -0,0 +1,11 @@ +# @TEST-EXEC: bro -r $TRACES/ip6_esp.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +# Just check that the event is raised correctly for a packet containing +# ESP extension headers. + +event esp_packet(p: pkt_hdr) + { + if ( p?$ip6 ) + print p$ip6; + } diff --git a/testing/btest/core/ipv6_ext_headers.test b/testing/btest/core/ipv6_ext_headers.test new file mode 100644 index 0000000000..32a0f5d558 --- /dev/null +++ b/testing/btest/core/ipv6_ext_headers.test @@ -0,0 +1,22 @@ +# @TEST-EXEC: bro -b -r $TRACES/ipv6-hbh-routing0.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +# Just check that the event is raised correctly for a packet containing +# extension headers. +event ipv6_ext_headers(c: connection, p: pkt_hdr) + { + print p; + } + +# Also check the weird for routing type 0 extensions headers +event flow_weird(name: string, src: addr, dst: addr) + { + print fmt("weird %s from %s to %s", name, src, dst); + } + +# And the connection for routing type 0 packets with non-zero segments left +# should use the last address in that extension header. +event new_connection(c: connection) + { + print c$id; + } diff --git a/testing/btest/core/leaks/basic-cluster.bro b/testing/btest/core/leaks/basic-cluster.bro new file mode 100644 index 0000000000..f5b40c1104 --- /dev/null +++ b/testing/btest/core/leaks/basic-cluster.bro @@ -0,0 +1,42 @@ +# Needs perftools support. +# +# @TEST-GROUP: leaks + +# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks + +# @TEST-EXEC: btest-bg-run manager-1 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=manager-1 bro -m %INPUT +# @TEST-EXEC: btest-bg-run proxy-1 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro -m %INPUT +# @TEST-EXEC: sleep 1 +# @TEST-EXEC: btest-bg-run worker-1 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro -m -r $TRACES/web.trace --pseudo-realtime %INPUT +# @TEST-EXEC: btest-bg-run worker-2 HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro -m -r $TRACES/web.trace --pseudo-realtime %INPUT +# @TEST-EXEC: btest-bg-wait -k 30 +# @TEST-EXEC: btest-diff manager-1/metrics.log + +@TEST-START-FILE cluster-layout.bro +redef Cluster::nodes = { + ["manager-1"] = [$node_type=Cluster::MANAGER, $ip=127.0.0.1, $p=37757/tcp, $workers=set("worker-1")], + ["proxy-1"] = [$node_type=Cluster::PROXY, $ip=127.0.0.1, $p=37758/tcp, $manager="manager-1", $workers=set("worker-1")], + ["worker-1"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37760/tcp, $manager="manager-1", $proxy="proxy-1", $interface="eth0"], + ["worker-2"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=37761/tcp, $manager="manager-1", $proxy="proxy-1", $interface="eth1"], +}; +@TEST-END-FILE + +redef Log::default_rotation_interval = 0secs; + +redef enum Metrics::ID += { + TEST_METRIC, +}; + +event bro_init() &priority=5 + { + Metrics::add_filter(TEST_METRIC, + [$name="foo-bar", + $break_interval=3secs]); + + if ( Cluster::local_node_type() == Cluster::WORKER ) + { + Metrics::add_data(TEST_METRIC, [$host=1.2.3.4], 3); + Metrics::add_data(TEST_METRIC, [$host=6.5.4.3], 2); + Metrics::add_data(TEST_METRIC, [$host=7.2.1.5], 1); + } + } diff --git a/testing/btest/core/leaks/dns.bro b/testing/btest/core/leaks/dns.bro new file mode 100644 index 0000000000..2816750758 --- /dev/null +++ b/testing/btest/core/leaks/dns.bro @@ -0,0 +1,54 @@ +# Needs perftools support. +# +# @TEST-GROUP: leaks +# +# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks +# +# @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local bro -m -r $TRACES/wikipedia.trace %INPUT + +const foo: set[addr] = { + google.com +}; + +# Add the state tracking information variable to the connection record + +event connection_established(c: connection) + { + when ( local addrs = lookup_hostname("localhost") ) + { + print "1a", c$id$resp_h, addrs; + } + timeout 100secs + { + print "1b", c$id$resp_h; + } + + when ( local addrs2 = lookup_hostname("qq.ww.ee.rrrrr") ) + { + print "2a", c$id$resp_h, addrs2; + } + timeout 100secs + { + print "2b", c$id$resp_h; + } + + when ( local a = lookup_addr(c$id$resp_h) ) + { + print "3a", c$id$resp_h, a; + } + timeout 100secs + { + print "3b", c$id$resp_h; + } + + when ( local a2 = lookup_addr(1.2.3.4) ) + { + print "4a", c$id$resp_h, a2; + } + timeout 100secs + { + print "4b", c$id$resp_h; + } + + } + diff --git a/testing/btest/core/leaks/remote.bro b/testing/btest/core/leaks/remote.bro new file mode 100644 index 0000000000..f888d8f6ee --- /dev/null +++ b/testing/btest/core/leaks/remote.bro @@ -0,0 +1,81 @@ +# Needs perftools support. +# +# @TEST-GROUP: leaks +# +# @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks +# +# @TEST-EXEC: btest-bg-run sender HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local bro -m --pseudo-realtime %INPUT ../sender.bro +# @TEST-EXEC: sleep 1 +# @TEST-EXEC: btest-bg-run receiver HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local bro -m --pseudo-realtime %INPUT ../receiver.bro +# @TEST-EXEC: sleep 1 +# @TEST-EXEC: btest-bg-wait -k 10 +# @TEST-EXEC: btest-diff sender/test.log +# @TEST-EXEC: btest-diff sender/test.failure.log +# @TEST-EXEC: btest-diff sender/test.success.log +# @TEST-EXEC: cmp receiver/test.log sender/test.log +# @TEST-EXEC: cmp receiver/test.failure.log sender/test.failure.log +# @TEST-EXEC: cmp receiver/test.success.log sender/test.success.log + +# This is the common part loaded by both sender and receiver. +module Test; + +export { + # Create a new ID for our log stream + redef enum Log::ID += { LOG }; + + # Define a record with all the columns the log file can have. + # (I'm using a subset of fields from ssh-ext for demonstration.) + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +event bro_init() +{ + Log::create_stream(Test::LOG, [$columns=Log]); + Log::add_filter(Test::LOG, [$name="f1", $path="test.success", $pred=function(rec: Log): bool { return rec$status == "success"; }]); +} + +##### + +@TEST-START-FILE sender.bro + +module Test; + +@load frameworks/communication/listen + +function fail(rec: Log): bool + { + return rec$status != "success"; + } + +event remote_connection_handshake_done(p: event_peer) + { + Log::add_filter(Test::LOG, [$name="f2", $path="test.failure", $pred=fail]); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + local r: Log = [$t=network_time(), $id=cid, $status="success"]; + + # Log something. + Log::write(Test::LOG, r); + Log::write(Test::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(Test::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(Test::LOG, [$t=network_time(), $id=cid, $status="success", $country="BR"]); + Log::write(Test::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + disconnect(p); + } +@TEST-END-FILE + +@TEST-START-FILE receiver.bro + +##### + +redef Communication::nodes += { + ["foo"] = [$host = 127.0.0.1, $connect=T, $request_logs=T] +}; + +@TEST-END-FILE diff --git a/testing/btest/core/leaks.bro b/testing/btest/core/leaks/test-all.bro similarity index 89% rename from testing/btest/core/leaks.bro rename to testing/btest/core/leaks/test-all.bro index 6e605372c9..f217cc229c 100644 --- a/testing/btest/core/leaks.bro +++ b/testing/btest/core/leaks/test-all.bro @@ -1,5 +1,7 @@ # Needs perftools support. # +# @TEST-GROUP: leaks +# # @TEST-REQUIRES: bro --help 2>&1 | grep -q mem-leaks # # @TEST-EXEC: HEAP_CHECK_DUMP_DIRECTORY=. HEAPCHECK=local bro -m -r $TRACES/wikipedia.trace test-all-policy diff --git a/testing/btest/core/mobile-ipv6-home-addr.test b/testing/btest/core/mobile-ipv6-home-addr.test new file mode 100644 index 0000000000..536d381f9b --- /dev/null +++ b/testing/btest/core/mobile-ipv6-home-addr.test @@ -0,0 +1,11 @@ +# @TEST-REQUIRES: grep -q "#define ENABLE_MOBILE_IPV6" $BUILD/config.h +# @TEST-EXEC: bro -b -r $TRACES/mobile-ipv6/ipv6-mobile-hoa.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +# Just check that the orig of the connection is the Home Address, but the +# source in the header is the actual source address. +event new_packet(c: connection, p: pkt_hdr) + { + print c$id; + print p; + } diff --git a/testing/btest/core/mobile-ipv6-routing.test b/testing/btest/core/mobile-ipv6-routing.test new file mode 100644 index 0000000000..6ad5be002d --- /dev/null +++ b/testing/btest/core/mobile-ipv6-routing.test @@ -0,0 +1,11 @@ +# @TEST-REQUIRES: grep -q "#define ENABLE_MOBILE_IPV6" $BUILD/config.h +# @TEST-EXEC: bro -b -r $TRACES/mobile-ipv6/ipv6-mobile-routing.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +# Just check that the responder of the connection is the final routing +# address, but the destination in the header is the actual destination address. +event new_packet(c: connection, p: pkt_hdr) + { + print c$id; + print p; + } diff --git a/testing/btest/core/mobility-checksums.test b/testing/btest/core/mobility-checksums.test new file mode 100644 index 0000000000..1d41daf543 --- /dev/null +++ b/testing/btest/core/mobility-checksums.test @@ -0,0 +1,9 @@ +# @TEST-REQUIRES: grep -q "#define ENABLE_MOBILE_IPV6" $BUILD/config.h +# @TEST-EXEC: bro -b -r $TRACES/chksums/mip6-bad-mh-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-hoa-tcp-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-hoa-udp-bad-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/mip6-good-mh-chksum.pcap >>good.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-hoa-tcp-good-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/chksums/ip6-hoa-udp-good-chksum.pcap >>bad.out 2>&1 +# @TEST-EXEC: btest-diff bad.out +# @TEST-EXEC: btest-diff good.out diff --git a/testing/btest/core/mobility_msg.test b/testing/btest/core/mobility_msg.test new file mode 100644 index 0000000000..73461e7944 --- /dev/null +++ b/testing/btest/core/mobility_msg.test @@ -0,0 +1,44 @@ +# @TEST-REQUIRES: grep -q "#define ENABLE_MOBILE_IPV6" $BUILD/config.h +# @TEST-EXEC: bro -b -r $TRACES/mobile-ipv6/mip6_back.trace %INPUT >output +# @TEST-EXEC: bro -b -r $TRACES/mobile-ipv6/mip6_be.trace %INPUT >>output +# @TEST-EXEC: bro -b -r $TRACES/mobile-ipv6/mip6_brr.trace %INPUT >>output +# @TEST-EXEC: bro -b -r $TRACES/mobile-ipv6/mip6_bu.trace %INPUT >>output +# @TEST-EXEC: bro -b -r $TRACES/mobile-ipv6/mip6_cot.trace %INPUT >>output +# @TEST-EXEC: bro -b -r $TRACES/mobile-ipv6/mip6_coti.trace %INPUT >>output +# @TEST-EXEC: bro -b -r $TRACES/mobile-ipv6/mip6_hot.trace %INPUT >>output +# @TEST-EXEC: bro -b -r $TRACES/mobile-ipv6/mip6_hoti.trace %INPUT >>output +# @TEST-EXEC: btest-diff output + +event mobile_ipv6_message(p: pkt_hdr) + { + if ( ! p?$ip6 ) return; + + for ( i in p$ip6$exts ) + { + if ( p$ip6$exts[i]$id == IPPROTO_MOBILITY ) + { + if ( ! p$ip6$exts[i]?$mobility ) + print "ERROR: Mobility extension header uninitialized"; + + if ( p$ip6$exts[i]$mobility$mh_type == 0 ) + print "Binding Refresh Request:"; + else if ( p$ip6$exts[i]$mobility$mh_type == 1 ) + print "Home Test Init:"; + else if ( p$ip6$exts[i]$mobility$mh_type == 2 ) + print "Care-of Test Init:"; + else if ( p$ip6$exts[i]$mobility$mh_type == 3 ) + print "Home Test:"; + else if ( p$ip6$exts[i]$mobility$mh_type == 4 ) + print "Care-of Test:"; + else if ( p$ip6$exts[i]$mobility$mh_type == 5 ) + print "Binding Update:"; + else if ( p$ip6$exts[i]$mobility$mh_type == 6 ) + print "Binding ACK:"; + else if ( p$ip6$exts[i]$mobility$mh_type == 7 ) + print "Binding Error:"; + else + print "Unknown Mobility Header:"; + print p$ip6; + } + } + } diff --git a/testing/btest/core/print-bpf-filters-ipv4.bro b/testing/btest/core/print-bpf-filters-ipv4.bro deleted file mode 100644 index e1aeb3f95f..0000000000 --- a/testing/btest/core/print-bpf-filters-ipv4.bro +++ /dev/null @@ -1,12 +0,0 @@ -# @TEST-REQUIRES: bro -e 'print bro_has_ipv6()' | grep -q F -# -# @TEST-EXEC: bro -e '' >output -# @TEST-EXEC: cat packet_filter.log >>output -# @TEST-EXEC: bro PacketFilter::all_packets=F >>output -# @TEST-EXEC: cat packet_filter.log >>output -# @TEST-EXEC: bro -f "port 42" -e '' >>output -# @TEST-EXEC: cat packet_filter.log >>output -# @TEST-EXEC: bro -C -f "port 56730" -r $TRACES/mixed-vlan-mpls.trace >>output -# @TEST-EXEC: cat packet_filter.log >>output -# @TEST-EXEC: btest-diff output -# @TEST-EXEC: btest-diff conn.log diff --git a/testing/btest/core/print-bpf-filters-ipv6.bro b/testing/btest/core/print-bpf-filters-ipv6.bro deleted file mode 100644 index c4378f8ec6..0000000000 --- a/testing/btest/core/print-bpf-filters-ipv6.bro +++ /dev/null @@ -1,12 +0,0 @@ -# @TEST-REQUIRES: bro -e 'print bro_has_ipv6()' | grep -q T -# -# @TEST-EXEC: bro -e '' >output -# @TEST-EXEC: cat packet_filter.log >>output -# @TEST-EXEC: bro PacketFilter::all_packets=F ssh >>output -# @TEST-EXEC: cat packet_filter.log >>output -# @TEST-EXEC: bro -f "port 42" -e '' >>output -# @TEST-EXEC: cat packet_filter.log >>output -# @TEST-EXEC: bro -C -f "port 56730" -r $TRACES/mixed-vlan-mpls.trace conn >>output -# @TEST-EXEC: cat packet_filter.log >>output -# @TEST-EXEC: btest-diff output -# @TEST-EXEC: btest-diff conn.log diff --git a/testing/btest/core/print-bpf-filters.bro b/testing/btest/core/print-bpf-filters.bro new file mode 100644 index 0000000000..6d9cef0220 --- /dev/null +++ b/testing/btest/core/print-bpf-filters.bro @@ -0,0 +1,10 @@ +# @TEST-EXEC: bro -r $TRACES/empty.trace -e '' >output +# @TEST-EXEC: cat packet_filter.log >>output +# @TEST-EXEC: bro -r $TRACES/empty.trace PacketFilter::all_packets=F >>output +# @TEST-EXEC: cat packet_filter.log >>output +# @TEST-EXEC: bro -r $TRACES/empty.trace -f "port 42" -e '' >>output +# @TEST-EXEC: cat packet_filter.log >>output +# @TEST-EXEC: bro -r $TRACES/empty.trace -C -f "port 56730" -r $TRACES/mixed-vlan-mpls.trace >>output +# @TEST-EXEC: cat packet_filter.log >>output +# @TEST-EXEC: btest-diff output +# @TEST-EXEC: btest-diff conn.log diff --git a/testing/btest/core/truncation.test b/testing/btest/core/truncation.test new file mode 100644 index 0000000000..16a60fe6db --- /dev/null +++ b/testing/btest/core/truncation.test @@ -0,0 +1,6 @@ +# Truncated IP packet's should not be analyzed, and generate truncated_IP weird + +# @TEST-EXEC: bro -b -r $TRACES/trunc/ip4-trunc.pcap >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/trunc/ip6-trunc.pcap >>output 2>&1 +# @TEST-EXEC: bro -b -r $TRACES/trunc/ip6-ext-trunc.pcap >>output 2>&1 +# @TEST-EXEC: btest-diff output diff --git a/testing/btest/policy/misc/bare-loaded-scripts.test b/testing/btest/coverage/bare-load-baseline.test similarity index 59% rename from testing/btest/policy/misc/bare-loaded-scripts.test rename to testing/btest/coverage/bare-load-baseline.test index fb7074f2c2..52393afb7c 100644 --- a/testing/btest/policy/misc/bare-loaded-scripts.test +++ b/testing/btest/coverage/bare-load-baseline.test @@ -1,5 +1,7 @@ # This test is meant to cover whether the set of scripts that get loaded by -# default in bare mode matches a baseline of known defaults. +# default in bare mode matches a baseline of known defaults. The baseline +# should only need updating if something new is @load'd from init-bare.bro +# (or from an @load'd descendent of it). # # As the output has absolute paths in it, we need to remove the common # prefix to make the test work everywhere. That's what the sed magic @@ -7,6 +9,6 @@ # @TEST-EXEC: bro -b misc/loaded-scripts # @TEST-EXEC: test -e loaded_scripts.log -# @TEST-EXEC: cat loaded_scripts.log | awk 'NR>1{print $2}' | sed -e ':a' -e '$!N' -e 's/^\(.*\).*\n\1.*/\1/' -e 'ta' >prefix +# @TEST-EXEC: cat loaded_scripts.log | egrep -v '#' | awk 'NR>0{print $1}' | sed -e ':a' -e '$!N' -e 's/^\(.*\).*\n\1.*/\1/' -e 'ta' >prefix # @TEST-EXEC: cat loaded_scripts.log | sed "s#`cat prefix`##g" >canonified_loaded_scripts.log # @TEST-EXEC: btest-diff canonified_loaded_scripts.log diff --git a/testing/btest/coverage/bare-mode-errors.test b/testing/btest/coverage/bare-mode-errors.test new file mode 100644 index 0000000000..9fd18308ce --- /dev/null +++ b/testing/btest/coverage/bare-mode-errors.test @@ -0,0 +1,11 @@ +# Makes sure any given bro script in the scripts/ tree can be loaded in +# bare mode without error. btest-bg-run/btest-bg-wait are used to kill off +# scripts that block after loading, e.g. start listening on a socket. +# +# Commonly, this test may fail if one forgets to @load some base/ scripts +# when writing a new bro scripts. +# +# @TEST-EXEC: test -d $DIST/scripts +# @TEST-EXEC: for script in `find $DIST/scripts -name \*\.bro -not -path '*/site/*'`; do echo $script; if echo "$script" | egrep -q 'communication/listen|controllee'; then rm -rf load_attempt .bgprocs; btest-bg-run load_attempt bro -b $script; btest-bg-wait -k 2; cat load_attempt/.stderr >>allerrors; else bro -b $script 2>>allerrors; fi done || exit 0 +# @TEST-EXEC: cat allerrors | grep -v "received termination signal" | sort | uniq > unique_errors +# @TEST-EXEC: btest-diff unique_errors diff --git a/testing/btest/coverage/coverage-blacklist.bro b/testing/btest/coverage/coverage-blacklist.bro new file mode 100644 index 0000000000..30a5f86efa --- /dev/null +++ b/testing/btest/coverage/coverage-blacklist.bro @@ -0,0 +1,29 @@ +# @TEST-EXEC: BRO_PROFILER_FILE=coverage bro -b %INPUT +# @TEST-EXEC: grep %INPUT coverage | sort -k2 >output +# @TEST-EXEC: TEST_DIFF_CANONIFIER=$SCRIPTS/diff-remove-abspath btest-diff output + +print "first"; + +if ( F ) + { # @no-test + print "hello"; + print "world"; + } + +print "cover me"; + +if ( T ) + { + print "always executed"; + } + +print "don't cover me"; # @no-test + +if ( 0 + 0 == 1 ) print "impossible"; # @no-test + +if ( 1 == 0 ) + { + print "also impossible, but included in code coverage analysis"; + } + +print "success"; diff --git a/testing/btest/policy/misc/default-loaded-scripts.test b/testing/btest/coverage/default-load-baseline.test similarity index 61% rename from testing/btest/policy/misc/default-loaded-scripts.test rename to testing/btest/coverage/default-load-baseline.test index c7f0d12a23..669b465083 100644 --- a/testing/btest/policy/misc/default-loaded-scripts.test +++ b/testing/btest/coverage/default-load-baseline.test @@ -1,5 +1,7 @@ # This test is meant to cover whether the set of scripts that get loaded by -# default matches a baseline of known defaults. +# default matches a baseline of known defaults. When new scripts are +# added to the scripts/base/ directory, the baseline will usually just need +# to be updated. # # As the output has absolute paths in it, we need to remove the common # prefix to make the test work everywhere. That's what the sed magic @@ -7,6 +9,6 @@ # @TEST-EXEC: bro misc/loaded-scripts # @TEST-EXEC: test -e loaded_scripts.log -# @TEST-EXEC: cat loaded_scripts.log | awk 'NR>1{print $2}' | sed -e ':a' -e '$!N' -e 's/^\(.*\).*\n\1.*/\1/' -e 'ta' >prefix +# @TEST-EXEC: cat loaded_scripts.log | egrep -v '#' | sed 's/ //g' | sed -e ':a' -e '$!N' -e 's/^\(.*\).*\n\1.*/\1/' -e 'ta' >prefix # @TEST-EXEC: cat loaded_scripts.log | sed "s#`cat prefix`##g" >canonified_loaded_scripts.log # @TEST-EXEC: btest-diff canonified_loaded_scripts.log diff --git a/testing/btest/doc/coverage.test b/testing/btest/coverage/doc.test similarity index 63% rename from testing/btest/doc/coverage.test rename to testing/btest/coverage/doc.test index 6b31845704..18ed13e6fa 100644 --- a/testing/btest/doc/coverage.test +++ b/testing/btest/coverage/doc.test @@ -1,5 +1,5 @@ -# This tests that we're generating policy script documentation for all the -# available policy scripts. If this fails, then the genDocSources.sh needs +# This tests that we're generating bro script documentation for all the +# available bro scripts. If this fails, then the genDocSources.sh needs # to be run to produce a new DocSourcesList.cmake or genDocSources.sh needs # to be updated to blacklist undesired scripts. # diff --git a/testing/btest/coverage/init-default.test b/testing/btest/coverage/init-default.test new file mode 100644 index 0000000000..6877159c62 --- /dev/null +++ b/testing/btest/coverage/init-default.test @@ -0,0 +1,18 @@ +# Makes sure that all base/* scripts are loaded by default via init-default.bro; +# and that all scripts loaded there in there actually exist. +# +# This test will fail if a new bro script is added under the scripts/base/ +# directory and it is not also added as an @load in base/init-default.bro. +# In some cases, a script in base is loaded based on the bro configuration +# (e.g. cluster operation), and in such cases, the missing_loads baseline +# can be adjusted to tolerate that. + +#@TEST-EXEC: test -d $DIST/scripts/base +#@TEST-EXEC: test -e $DIST/scripts/base/init-default.bro +#@TEST-EXEC: ( cd $DIST/scripts/base && find . -name '*.bro' ) | sort >"all scripts found" +#@TEST-EXEC: bro misc/loaded-scripts +#@TEST-EXEC: cat loaded_scripts.log | egrep -v '/build/|/loaded-scripts.bro|#' | sed 's#/./#/#g' >loaded_scripts.log.tmp +#@TEST-EXEC: cat loaded_scripts.log.tmp | sed 's/ //g' | sed -e ':a' -e '$!N' -e 's/^\(.*\).*\n\1.*/\1/' -e 'ta' >prefix +#@TEST-EXEC: cat loaded_scripts.log.tmp | sed 's/ //g' | sed "s#`cat prefix`#./#g" | sort >init-default.bro +#@TEST-EXEC: diff -u "all scripts found" init-default.bro | egrep "^-[^-]" > missing_loads +#@TEST-EXEC: btest-diff missing_loads diff --git a/testing/btest/policy/misc/test-all-default-coverage.bro b/testing/btest/coverage/test-all-policy.test similarity index 54% rename from testing/btest/policy/misc/test-all-default-coverage.bro rename to testing/btest/coverage/test-all-policy.test index 89cbcb55fe..3a545a02af 100644 --- a/testing/btest/policy/misc/test-all-default-coverage.bro +++ b/testing/btest/coverage/test-all-policy.test @@ -1,5 +1,9 @@ -# Makes sure that all policy/* scripts are loaded in test-all-policy.bro; and that -# all scripts loaded there actually exist. +# Makes sure that all policy/* scripts are loaded in +# scripts/test-all-policy.bro and that all scripts loaded there actually exist. +# +# This test will fail if new bro scripts are added to the scripts/policy/ +# directory. Correcting that just involves updating scripts/test-all-policy.bro +# to @load the new bro scripts. @TEST-EXEC: test -e $DIST/scripts/test-all-policy.bro @TEST-EXEC: test -d $DIST/scripts diff --git a/testing/btest/doc/autogen-reST-func-params.bro b/testing/btest/doc/autogen-reST-func-params.bro new file mode 100644 index 0000000000..89cf90ef5a --- /dev/null +++ b/testing/btest/doc/autogen-reST-func-params.bro @@ -0,0 +1,20 @@ +# @TEST-EXEC: bro --doc-scripts %INPUT +# @TEST-EXEC: btest-diff autogen-reST-func-params.rst + +## This is a global function declaration. +## +## i: First param. +## j: Second param. +## +## Returns: A string. +global test_func: function(i: int, j: int): string; + +type test_rec: record { + ## This is a record field function. + ## + ## i: First param. + ## j: Second param. + ## + ## Returns: A string. + field_func: function(i: int, j: int): string; +}; diff --git a/testing/btest/doc/blacklist-reminder.test b/testing/btest/doc/blacklist-reminder.test deleted file mode 100644 index 8b79d8a28f..0000000000 --- a/testing/btest/doc/blacklist-reminder.test +++ /dev/null @@ -1,8 +0,0 @@ -# This test will fail if there are Bro scripts that have been temporarily -# blacklisted from the documentation generation process for some reason -# (e.g. they're a work-in-progress or otherwise fail to parse). It's meant -# to serve as a reminder that some future action may be needed to generate -# documentation for the blacklisted scripts. -# -# @TEST-EXEC: $DIST/doc/scripts/genDocSourcesList.sh -# @TEST-EXEC: btest-diff .stderr diff --git a/testing/btest/istate/broccoli-ipv6.bro b/testing/btest/istate/broccoli-ipv6.bro new file mode 100644 index 0000000000..b7ab5bdb05 --- /dev/null +++ b/testing/btest/istate/broccoli-ipv6.bro @@ -0,0 +1,15 @@ +# @TEST-GROUP: comm +# +# @TEST-REQUIRES: test -e $BUILD/aux/broccoli/src/libbroccoli.so || test -e $BUILD/aux/broccoli/src/libbroccoli.dylib +# +# @TEST-EXEC: btest-bg-run bro bro %INPUT $DIST/aux/broccoli/test/broccoli-v6addrs.bro +# @TEST-EXEC: btest-bg-run broccoli $BUILD/aux/broccoli/test/broccoli-v6addrs +# @TEST-EXEC: btest-bg-wait -k 20 +# @TEST-EXEC: btest-diff bro/.stdout +# @TEST-EXEC: btest-diff broccoli/.stdout + +event remote_connection_closed(p: event_peer) + { + terminate(); + } + diff --git a/testing/btest/istate/broccoli.bro b/testing/btest/istate/broccoli.bro index 7f97f40585..235ff9119c 100644 --- a/testing/btest/istate/broccoli.bro +++ b/testing/btest/istate/broccoli.bro @@ -1,4 +1,5 @@ -# @TEST-REQUIRES: grep -vq '#define BROv6' $BUILD/config.h +# @TEST-GROUP: comm +# # @TEST-REQUIRES: test -e $BUILD/aux/broccoli/src/libbroccoli.so || test -e $BUILD/aux/broccoli/src/libbroccoli.dylib # # @TEST-EXEC: btest-bg-run bro bro %INPUT $DIST/aux/broccoli/test/broping-record.bro diff --git a/testing/btest/istate/events-ssl.bro b/testing/btest/istate/events-ssl.bro index cfacae9da8..25aa2dc8fb 100644 --- a/testing/btest/istate/events-ssl.bro +++ b/testing/btest/istate/events-ssl.bro @@ -1,4 +1,5 @@ -# +# @TEST-GROUP: comm +# # @TEST-EXEC: btest-bg-run sender bro -C -r $TRACES/web.trace --pseudo-realtime ../sender.bro # @TEST-EXEC: btest-bg-run receiver bro ../receiver.bro # @TEST-EXEC: btest-bg-wait -k 20 @@ -16,7 +17,8 @@ @TEST-START-FILE sender.bro -@load frameworks/communication/listen-ssl +@load frameworks/communication/listen +redef Communication::listen_ssl=T; event bro_init() { diff --git a/testing/btest/istate/events.bro b/testing/btest/istate/events.bro index ecf2f2e2ad..81a1d765db 100644 --- a/testing/btest/istate/events.bro +++ b/testing/btest/istate/events.bro @@ -1,4 +1,5 @@ -# +# @TEST-GROUP: comm +# # @TEST-EXEC: btest-bg-run sender bro -C -r $TRACES/web.trace --pseudo-realtime ../sender.bro # @TEST-EXEC: btest-bg-run receiver bro ../receiver.bro # @TEST-EXEC: btest-bg-wait -k 20 @@ -16,7 +17,7 @@ @TEST-START-FILE sender.bro -@load frameworks/communication/listen-clear +@load frameworks/communication/listen event bro_init() { diff --git a/testing/btest/istate/pybroccoli.py b/testing/btest/istate/pybroccoli.py index b7fb53a955..1a5830b41a 100644 --- a/testing/btest/istate/pybroccoli.py +++ b/testing/btest/istate/pybroccoli.py @@ -1,4 +1,5 @@ -# @TEST-REQUIRES: grep -vq '#define BROv6' $BUILD/config.h +# @TEST-GROUP: comm +# # @TEST-REQUIRES: test -e $BUILD/aux/broccoli/src/libbroccoli.so || test -e $BUILD/aux/broccoli/src/libbroccoli.dylib # @TEST-REQUIRES: test -e $BUILD/aux/broccoli/bindings/broccoli-python/_broccoli_intern.so # diff --git a/testing/btest/istate/sync.bro b/testing/btest/istate/sync.bro index 567bbf2af1..db5ea0bbb4 100644 --- a/testing/btest/istate/sync.bro +++ b/testing/btest/istate/sync.bro @@ -1,3 +1,4 @@ +# @TEST-GROUP: comm # # @TEST-EXEC: btest-bg-run sender bro %INPUT ../sender.bro # @TEST-EXEC: btest-bg-run receiver bro %INPUT ../receiver.bro @@ -129,7 +130,7 @@ function modify() foo2 = 1234567; } -@load frameworks/communication/listen-clear +@load frameworks/communication/listen event remote_connection_handshake_done(p: event_peer) { diff --git a/testing/btest/language/enum-desc.bro b/testing/btest/language/enum-desc.bro new file mode 100644 index 0000000000..86466e2fc2 --- /dev/null +++ b/testing/btest/language/enum-desc.bro @@ -0,0 +1,15 @@ +# @TEST-EXEC: bro -b %INPUT >output +# @TEST-EXEC: btest-diff output + +type test_enum1: enum { ONE }; + +module TEST; + +type test_enum2: enum { TWO }; + +print ONE; +print fmt("%s", ONE); + + +print TWO; +print fmt("%s", TWO); diff --git a/testing/btest/language/expire_func.test b/testing/btest/language/expire_func.test new file mode 100644 index 0000000000..653a4d9a86 --- /dev/null +++ b/testing/btest/language/expire_func.test @@ -0,0 +1,23 @@ +# @TEST-EXEC: bro -C -r $TRACES/var-services-std-ports.trace %INPUT >output +# @TEST-EXEC: btest-diff output + +function inform_me(s: set[string], idx: string): interval + { + print fmt("expired %s", idx); + return 0secs; + } + +global s: set[string] &create_expire=1secs &expire_func=inform_me; + +event bro_init() + { + add s["i"]; + add s["am"]; + add s["here"]; + } + +event new_connection(c: connection) + { + add s[fmt("%s", c$id)]; + print s; + } diff --git a/testing/btest/language/ipv6-literals.bro b/testing/btest/language/ipv6-literals.bro new file mode 100644 index 0000000000..004d104c6e --- /dev/null +++ b/testing/btest/language/ipv6-literals.bro @@ -0,0 +1,32 @@ +# @TEST-EXEC: bro -b %INPUT >output +# @TEST-EXEC: btest-diff output + +local v: vector of addr = vector(); + +v[|v|] = [::1]; +v[|v|] = [::ffff]; +v[|v|] = [::ffff:ffff]; +v[|v|] = [::0a0a:ffff]; +v[|v|] = [1::1]; +v[|v|] = [1::a]; +v[|v|] = [1::1:1]; +v[|v|] = [1::1:a]; +v[|v|] = [a::a]; +v[|v|] = [a::1]; +v[|v|] = [a::a:a]; +v[|v|] = [a::a:1]; +v[|v|] = [a:a::a]; +v[|v|] = [aaaa:0::ffff]; +v[|v|] = [::ffff:192.168.1.100]; +v[|v|] = [ffff::192.168.1.100]; +v[|v|] = [::192.168.1.100]; +v[|v|] = [::ffff:0:192.168.1.100]; +v[|v|] = [805B:2D9D:DC28::FC57:212.200.31.255]; +v[|v|] = [0xaaaa::bbbb]; +v[|v|] = [aaaa:bbbb:cccc:dddd:eeee:ffff:1111:2222]; +v[|v|] = [aaaa:bbbb:cccc:dddd:eeee:ffff:1:2222]; +v[|v|] = [aaaa:bbbb:cccc:dddd:eeee:ffff:0:2222]; +v[|v|] = [aaaa:bbbb:cccc:dddd:eeee:0:0:2222]; + +for (i in v) + print v[i]; diff --git a/testing/btest/language/match-test.bro b/testing/btest/language/match-test.bro deleted file mode 100644 index 9352d0f39f..0000000000 --- a/testing/btest/language/match-test.bro +++ /dev/null @@ -1,20 +0,0 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 -# @TEST-EXEC: btest-diff output - -global match_stuff = { - [$pred(a: count) = { return a > 5; }, - $result = "it's big", - $priority = 2], - - [$pred(a: count) = { return a > 15; }, - $result = "it's really big", - $priority = 3], - - [$pred(a: count) = { return T; }, - $result = "default", - $priority = 0], -}; - -print match 0 using match_stuff; -print match 10 using match_stuff; -print match 20 using match_stuff; diff --git a/testing/btest/language/match-test2.bro b/testing/btest/language/match-test2.bro deleted file mode 100644 index f1c120adf2..0000000000 --- a/testing/btest/language/match-test2.bro +++ /dev/null @@ -1,51 +0,0 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 -# @TEST-EXEC: btest-diff output - -type fakealert : record { - alert: string; -}; - - -type match_rec : record { - result : count; - pred : function(rec : fakealert) : bool; - priority: count; -}; - - -#global test_set : set[int] = -#{ -#1, 2, 3 -#}; - -global match_set : set[match_rec] = -{ - [$result = 1, $pred(a: fakealert) = { return T; }, $priority = 8 ], - [$result = 2, $pred(a: fakealert) = { return T; }, $priority = 9 ] -}; - -global al : fakealert; - -#global testset : set[fakealert] = -#{ -# [$alert="hithere"] -#}; - - -type nonalert: record { - alert : string; - pred : function(a : int) : int; -}; - -#global na : nonalert; -#na$alert = "5"; - -#al$alert = "hithere2"; -#if (al in testset) -# print 1; -#else -# print 0; - - -al$alert = "hi"; -print (match al using match_set); diff --git a/testing/btest/language/record-default-coercion.bro b/testing/btest/language/record-default-coercion.bro new file mode 100644 index 0000000000..7e717c39e2 --- /dev/null +++ b/testing/btest/language/record-default-coercion.bro @@ -0,0 +1,18 @@ +# @TEST-EXEC: bro -b %INPUT >out +# @TEST-EXEC: btest-diff out + +type MyRecord: record { + a: count &default=13; + c: count; + v: vector of string &default=vector(); +}; + +event bro_init() + { + local r: MyRecord = [$c=13]; + print r; + print |r$v|; + r$v[|r$v|] = "test"; + print r; + print |r$v|; + } diff --git a/testing/btest/language/record-index-complex-fields.bro b/testing/btest/language/record-index-complex-fields.bro new file mode 100644 index 0000000000..ae45648728 --- /dev/null +++ b/testing/btest/language/record-index-complex-fields.bro @@ -0,0 +1,38 @@ +# @TEST-EXEC: bro -b %INPUT >output +# @TEST-EXEC: btest-diff output + +# This test checks whether records with complex fields (tables, sets, vectors) +# can be used as table/set indices. + +type MetaData: record { + a: count; + tags_v: vector of count; + tags_t: table[string] of count; + tags_s: set[string]; +}; + +global ip_data: table[addr] of set[MetaData] = table(); + +global t1_t: table[string] of count = { ["one"] = 1, ["two"] = 2 }; +global t2_t: table[string] of count = { ["four"] = 4, ["five"] = 5 }; + +global t1_v: vector of count = vector(); +global t2_v: vector of count = vector(); +t1_v[0] = 0; +t1_v[1] = 1; +t2_v[2] = 2; +t2_v[3] = 3; + +local m: MetaData = [$a=4, $tags_v=t1_v, $tags_t=t1_t, $tags_s=set("a", "b")]; +local n: MetaData = [$a=13, $tags_v=t2_v, $tags_t=t2_t, $tags_s=set("c", "d")]; + +if ( 1.2.3.4 !in ip_data ) + ip_data[1.2.3.4] = set(m); +else + add ip_data[1.2.3.4][m]; + +print ip_data; + +add ip_data[1.2.3.4][n]; + +print ip_data[1.2.3.4]; diff --git a/testing/btest/language/record-recursive-coercion.bro b/testing/btest/language/record-recursive-coercion.bro index eda80e3d11..ad9e41bd3a 100644 --- a/testing/btest/language/record-recursive-coercion.bro +++ b/testing/btest/language/record-recursive-coercion.bro @@ -1,4 +1,4 @@ -# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: bro %INPUT >output # @TEST-EXEC: btest-diff output type Version: record { @@ -17,8 +17,24 @@ global matched_software: table[string] of Info = { ["OpenSSH_4.4"] = [$name="OpenSSH", $version=[$major=4,$minor=4]], }; +type Foo: record { + i: interval &default=1hr; + s: string &optional; +}; + +type FooContainer: record { + c: count; + f: Foo &optional; +}; + +function foo_func(fc: FooContainer) + { + print fc; + } + event bro_init() { for ( sw in matched_software ) print matched_software[sw]$version; + foo_func([$c=1, $f=[$i=2hrs]]); } diff --git a/testing/btest/language/set-opt-record-index.bro b/testing/btest/language/set-opt-record-index.bro new file mode 100644 index 0000000000..18ec963809 --- /dev/null +++ b/testing/btest/language/set-opt-record-index.bro @@ -0,0 +1,55 @@ +# @TEST-EXEC: bro %INPUT >output 2>&1 +# @TEST-EXEC: btest-diff output + +# Make sure a set can be indexed with a record that has optional fields + +type FOO: record { + a: count; + b: count &optional; +}; + +event bro_init() + { + local set_of_foo: set[FOO] = set(); + + local f: FOO; + f$a = 1; + + add set_of_foo[f]; + add set_of_foo[[$a=3]]; + + local f3: FOO; # = [$a=4, $b=5]; + f3$a = 4; + f3$b = 5; + + add set_of_foo[f3]; + + add set_of_foo[[$a=4, $b=5]]; + + print set_of_foo; + + print ""; + + for ( i in set_of_foo ) + print i; + + print ""; + + local f2: FOO; + f2$a = 2; + + print f in set_of_foo; + print f2 in set_of_foo; + + print ""; + + f3$a = 4; + print f3 in set_of_foo; + + f3$b = 4; + print f3 in set_of_foo; + + f3$b = 5; + print f3 in set_of_foo; + + } diff --git a/testing/btest/language/sizeof.bro b/testing/btest/language/sizeof.bro index 3457f895c9..99d7b51ce8 100644 --- a/testing/btest/language/sizeof.bro +++ b/testing/btest/language/sizeof.bro @@ -20,6 +20,7 @@ type example_record: record { }; global a: addr = 1.2.3.4; +global a6: addr = [::1]; global b: bool = T; global c: count = 10; global d: double = -1.23; @@ -52,8 +53,10 @@ v[4] = "World"; # Print out the sizes of the various vals: #----------------------------------------- -# Size of addr: returns integer representation for IPv4, 0 for IPv6. -print fmt("Address %s: %d", a, |a|); +# Size of addr: returns number of bits required to represent the address +# which is 32 for IPv4 or 128 for IPv6 +print fmt("IPv4 Address %s: %d", a, |a|); +print fmt("IPv6 Address %s: %d", a6, |a6|); # Size of boolean: returns 1 or 0. print fmt("Boolean %s: %d", b, |b|); diff --git a/testing/btest/language/table-init.bro b/testing/btest/language/table-init.bro new file mode 100644 index 0000000000..5df682c5d2 --- /dev/null +++ b/testing/btest/language/table-init.bro @@ -0,0 +1,20 @@ +# @TEST-EXEC: bro %INPUT >output +# @TEST-EXEC: btest-diff output + +global global_table: table[count] of string = { + [1] = "one", + [2] = "two" +} &default = "global table default"; + +event bro_init() + { + local local_table: table[count] of string = { + [3] = "three", + [4] = "four" + } &default = "local table default"; + + print global_table; + print global_table[0]; + print local_table; + print local_table[0]; + } diff --git a/testing/btest/policy/frameworks/logging/ascii-binary.bro b/testing/btest/policy/frameworks/logging/ascii-binary.bro deleted file mode 100644 index 36ad5a5a1b..0000000000 --- a/testing/btest/policy/frameworks/logging/ascii-binary.bro +++ /dev/null @@ -1,25 +0,0 @@ -# -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff ssh.log - -module SSH; - -export { - redef enum Log::ID += { SSH }; - - type Info: record { - data: string; - data2: string; - } &log; -} - -redef LogAscii::separator = "|"; - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Info]); - Log::write(SSH, [$data="abc\n\xffdef", $data2="DATA2"]); - Log::write(SSH, [$data="abc|\xffdef", $data2="DATA2"]); - Log::write(SSH, [$data="abc\xff|def", $data2="DATA2"]); -} - diff --git a/testing/btest/policy/frameworks/logging/ascii-escape.bro b/testing/btest/policy/frameworks/logging/ascii-escape.bro deleted file mode 100644 index 11b9d608b3..0000000000 --- a/testing/btest/policy/frameworks/logging/ascii-escape.bro +++ /dev/null @@ -1,32 +0,0 @@ -# -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff ssh.log - -redef LogAscii::separator = "||"; - -module SSH; - -export { - redef enum Log::ID += { SSH }; - - type Log: record { - t: time; - id: conn_id; # Will be rolled out into individual columns. - status: string &optional; - country: string &default="unknown"; - } &log; -} - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log]); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="fa||ure", $country="UK"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="su||ess", $country="BR"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); -} - diff --git a/testing/btest/policy/frameworks/logging/ascii-options.bro b/testing/btest/policy/frameworks/logging/ascii-options.bro deleted file mode 100644 index 2914c95795..0000000000 --- a/testing/btest/policy/frameworks/logging/ascii-options.bro +++ /dev/null @@ -1,35 +0,0 @@ -# -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff ssh.log - -redef LogAscii::output_to_stdout = F; -redef LogAscii::separator = "|"; -redef LogAscii::include_header = F; - -module SSH; - -export { - redef enum Log::ID += { SSH }; - - type Log: record { - t: time; - id: conn_id; # Will be rolled out into individual columns. - status: string &optional; - country: string &default="unknown"; - } &log; -} - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log]); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="success", $country="BR"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); - -} - diff --git a/testing/btest/policy/frameworks/logging/ascii-timestamps.bro b/testing/btest/policy/frameworks/logging/ascii-timestamps.bro deleted file mode 100644 index 9b134d650f..0000000000 --- a/testing/btest/policy/frameworks/logging/ascii-timestamps.bro +++ /dev/null @@ -1,27 +0,0 @@ -# -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff test.log - -module Test; - -export { - redef enum Log::ID += { TEST }; - - type Info: record { - data: time &log; - }; -} - -event bro_init() -{ - Log::create_stream(TEST, [$columns=Info]); - Log::write(TEST, [$data=double_to_time(1234567890)]); - Log::write(TEST, [$data=double_to_time(1234567890.0)]); - Log::write(TEST, [$data=double_to_time(1234567890.01)]); - Log::write(TEST, [$data=double_to_time(1234567890.001)]); - Log::write(TEST, [$data=double_to_time(1234567890.0001)]); - Log::write(TEST, [$data=double_to_time(1234567890.00001)]); - Log::write(TEST, [$data=double_to_time(1234567890.000001)]); - Log::write(TEST, [$data=double_to_time(1234567890.0000001)]); -} - diff --git a/testing/btest/policy/frameworks/logging/attr.bro b/testing/btest/policy/frameworks/logging/attr.bro deleted file mode 100644 index 247dbce2a2..0000000000 --- a/testing/btest/policy/frameworks/logging/attr.bro +++ /dev/null @@ -1,31 +0,0 @@ -# -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff ssh.log - -module SSH; - -export { - redef enum Log::ID += { SSH }; - - type Log: record { - t: time; - id: conn_id; - status: string &optional &log; - country: string &default="unknown" &log; - }; -} - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log]); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="success", $country="BR"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); - -} - diff --git a/testing/btest/policy/frameworks/logging/disable-stream.bro b/testing/btest/policy/frameworks/logging/disable-stream.bro deleted file mode 100644 index 2bd18ae991..0000000000 --- a/testing/btest/policy/frameworks/logging/disable-stream.bro +++ /dev/null @@ -1,33 +0,0 @@ -# -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: test '!' -e ssh.log - -module SSH; - -export { - redef enum Log::ID += { SSH }; - - type Log: record { - t: time; - id: conn_id; # Will be rolled out into individual columns. - status: string &optional; - country: string &default="unknown"; - } &log; -} - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log]); - - Log::disable_stream(SSH); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="success", $country="BR"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); - -} - diff --git a/testing/btest/policy/frameworks/logging/empty-event.bro b/testing/btest/policy/frameworks/logging/empty-event.bro deleted file mode 100644 index 0f0a811117..0000000000 --- a/testing/btest/policy/frameworks/logging/empty-event.bro +++ /dev/null @@ -1,33 +0,0 @@ -# -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff ssh.log - -module SSH; - -export { - redef enum Log::ID += { SSH }; - - type Log: record { - t: time; - id: conn_id; # Will be rolled out into individual columns. - status: string &optional; - country: string &default="unknown"; - } &log; -} - -global log_ssh: event(rec: Log); - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log, $ev=log_ssh]); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="success", $country="BR"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); - -} - diff --git a/testing/btest/policy/frameworks/logging/exclude.bro b/testing/btest/policy/frameworks/logging/exclude.bro deleted file mode 100644 index 04767cec40..0000000000 --- a/testing/btest/policy/frameworks/logging/exclude.bro +++ /dev/null @@ -1,34 +0,0 @@ -# -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff ssh.log - -module SSH; - -export { - redef enum Log::ID += { SSH }; - - type Log: record { - t: time; - id: conn_id; # Will be rolled out into individual columns. - status: string &optional; - country: string &default="unknown"; - } &log; -} - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log]); - - Log::remove_default_filter(SSH); - Log::add_filter(SSH, [$name="f1", $exclude=set("t", "id.orig_h")]); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="success", $country="BR"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); - -} - diff --git a/testing/btest/policy/frameworks/logging/include.bro b/testing/btest/policy/frameworks/logging/include.bro deleted file mode 100644 index 414d0c8ab4..0000000000 --- a/testing/btest/policy/frameworks/logging/include.bro +++ /dev/null @@ -1,34 +0,0 @@ -# -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff ssh.log - -module SSH; - -export { - redef enum Log::ID += { SSH }; - - type Log: record { - t: time; - id: conn_id; # Will be rolled out into individual columns. - status: string &optional; - country: string &default="unknown"; - } &log; -} - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log]); - - Log::remove_default_filter(SSH); - Log::add_filter(SSH, [$name="default", $include=set("t", "id.orig_h")]); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="success", $country="BR"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); - -} - diff --git a/testing/btest/policy/frameworks/logging/no-local.bro b/testing/btest/policy/frameworks/logging/no-local.bro deleted file mode 100644 index 699f21d942..0000000000 --- a/testing/btest/policy/frameworks/logging/no-local.bro +++ /dev/null @@ -1,33 +0,0 @@ -# -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: test '!' -e ssh.log - -module SSH; - -export { - redef enum Log::ID += { SSH }; - - type Log: record { - t: time; - id: conn_id; # Will be rolled out into individual columns. - status: string &optional; - country: string &default="unknown"; - } &log; -} - -redef Log::enable_local_logging = F; - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log]); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="success", $country="BR"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); - -} - diff --git a/testing/btest/policy/frameworks/logging/path-func.bro b/testing/btest/policy/frameworks/logging/path-func.bro deleted file mode 100644 index ade6aedbc9..0000000000 --- a/testing/btest/policy/frameworks/logging/path-func.bro +++ /dev/null @@ -1,48 +0,0 @@ - -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: ( ls static-*; cat static-* ) >output -# @TEST-EXEC: btest-diff output - -module SSH; - -export { - # Create a new ID for our log stream - redef enum Log::ID += { SSH }; - - # Define a record with all the columns the log file can have. - # (I'm using a subset of fields from ssh-ext for demonstration.) - type Log: record { - t: time; - id: conn_id; # Will be rolled out into individual columns. - status: string &optional; - country: string &default="unknown"; - } &log; -} - -global c = -1; - -function path_func(id: Log::ID, path: string, rec: Log) : string - { - c = (c + 1) % 3; - - return fmt("%s-%d-%s", path, c, rec$country); - } - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log]); - Log::remove_default_filter(SSH); - - Log::add_filter(SSH, [$name="dyn", $path="static-prefix", $path_func=path_func]); - - Log::set_buf(SSH, F); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="success", $country="BR"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX2"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX3"]); -} diff --git a/testing/btest/policy/frameworks/logging/pred.bro b/testing/btest/policy/frameworks/logging/pred.bro deleted file mode 100644 index 3270c5f62d..0000000000 --- a/testing/btest/policy/frameworks/logging/pred.bro +++ /dev/null @@ -1,39 +0,0 @@ - -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff ssh.success.log -# @TEST-EXEC: btest-diff ssh.failure.log - -module SSH; - -export { - # Create a new ID for our log stream - redef enum Log::ID += { SSH }; - - # Define a record with all the columns the log file can have. - # (I'm using a subset of fields from ssh-ext for demonstration.) - type Log: record { - t: time; - id: conn_id; # Will be rolled out into individual columns. - status: string &optional; - country: string &default="unknown"; - } &log; -} - -function fail(rec: Log): bool - { - return rec$status != "success"; - } - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log]); - Log::remove_default_filter(SSH); - Log::add_filter(SSH, [$name="f1", $path="ssh.success", $pred=function(rec: Log): bool { return rec$status == "success"; }]); - Log::add_filter(SSH, [$name="f2", $path="ssh.failure", $pred=fail]); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - local r: Log = [$t=network_time(), $id=cid, $status="success"]; - Log::write(SSH, r); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - -} diff --git a/testing/btest/policy/frameworks/logging/remove.bro b/testing/btest/policy/frameworks/logging/remove.bro deleted file mode 100644 index 21b32c2b3e..0000000000 --- a/testing/btest/policy/frameworks/logging/remove.bro +++ /dev/null @@ -1,41 +0,0 @@ -# -# @TEST-EXEC: bro -b -B logging %INPUT -# @TEST-EXEC: btest-diff ssh.log -# @TEST-EXEC: btest-diff ssh.failure.log - -module SSH; - -export { - # Create a new ID for our log stream - redef enum Log::ID += { SSH }; - - # Define a record with all the columns the log file can have. - # (I'm using a subset of fields from ssh-ext for demonstration.) - type Log: record { - t: time; - id: conn_id; # Will be rolled out into individual columns. - status: string &optional; - country: string &default="unknown"; - } &log; -} - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log]); - Log::add_filter(SSH, [$name="f1", $path="ssh.failure", $pred=function(rec: Log): bool { return rec$status == "failure"; }]); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - - # Log something. - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - - Log::remove_filter(SSH, "f1"); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="BR"]); - - Log::remove_filter(SSH, "default"); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); - - Log::remove_filter(SSH, "doesn-not-exist"); -} - diff --git a/testing/btest/policy/frameworks/logging/stdout.bro b/testing/btest/policy/frameworks/logging/stdout.bro deleted file mode 100644 index 930a450d34..0000000000 --- a/testing/btest/policy/frameworks/logging/stdout.bro +++ /dev/null @@ -1,36 +0,0 @@ -# -# @TEST-EXEC: bro -b %INPUT >output -# @TEST-EXEC: btest-diff output -# @TEST-EXEC: test '!' -e ssh.log - -module SSH; - -export { - redef enum Log::ID += { SSH }; - - type Log: record { - t: time; - id: conn_id; # Will be rolled out into individual columns. - status: string &optional; - country: string &default="unknown"; - } &log; -} - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log]); - - local filter = Log::get_filter(SSH, "default"); - filter$path= "/dev/stdout"; - Log::add_filter(SSH, filter); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="success", $country="BR"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); - -} - diff --git a/testing/btest/policy/frameworks/logging/test-logging.bro b/testing/btest/policy/frameworks/logging/test-logging.bro deleted file mode 100644 index c4fed50093..0000000000 --- a/testing/btest/policy/frameworks/logging/test-logging.bro +++ /dev/null @@ -1,31 +0,0 @@ -# -# @TEST-EXEC: bro -b %INPUT -# @TEST-EXEC: btest-diff ssh.log - -module SSH; - -export { - redef enum Log::ID += { SSH }; - - type Log: record { - t: time; - id: conn_id; # Will be rolled out into individual columns. - status: string &optional; - country: string &default="unknown"; - } &log; -} - -event bro_init() -{ - Log::create_stream(SSH, [$columns=Log]); - - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="success", $country="BR"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); - -} - diff --git a/testing/btest/policy/misc/check-bare-test-all-policy.bro b/testing/btest/policy/misc/check-bare-test-all-policy.bro deleted file mode 100644 index a3474942e3..0000000000 --- a/testing/btest/policy/misc/check-bare-test-all-policy.bro +++ /dev/null @@ -1,7 +0,0 @@ -# Makes sures test-all-policy.bro (which loads *all* other policy scripts) -# compiles correctly even in bare mode. -# -# @TEST-EXEC: bro -b %INPUT >output -# @TEST-EXEC: btest-diff output - -@load test-all-policy diff --git a/testing/btest/policy/misc/init-default-coverage.bro b/testing/btest/policy/misc/init-default-coverage.bro deleted file mode 100644 index c2b2bb737d..0000000000 --- a/testing/btest/policy/misc/init-default-coverage.bro +++ /dev/null @@ -1,11 +0,0 @@ -# Makes sure that all base/* scripts are loaded by default via init-default.bro; -# and that all scripts loaded there in there actually exist. - -@TEST-EXEC: test -d $DIST/scripts/base -@TEST-EXEC: test -e $DIST/scripts/base/init-default.bro -@TEST-EXEC: ( cd $DIST/scripts/base && find . -name '*.bro' ) | sort >"all scripts found" -@TEST-EXEC: bro misc/loaded-scripts -@TEST-EXEC: cat loaded_scripts.log | egrep -v '/build/|/loaded-scripts.bro' | awk 'NR>1{print $2}' | sed 's#/./#/#g' >loaded_scripts.log.tmp -@TEST-EXEC: cat loaded_scripts.log.tmp | sed -e ':a' -e '$!N' -e 's/^\(.*\).*\n\1.*/\1/' -e 'ta' >prefix -@TEST-EXEC: cat loaded_scripts.log.tmp | sed "s#`cat prefix`#./#g" | sort >init-default.bro -@TEST-EXEC: diff -u "all scripts found" init-default.bro 1>&2 diff --git a/testing/btest/policy/frameworks/cluster/start-it-up.bro b/testing/btest/scripts/base/frameworks/cluster/start-it-up.bro similarity index 96% rename from testing/btest/policy/frameworks/cluster/start-it-up.bro rename to testing/btest/scripts/base/frameworks/cluster/start-it-up.bro index d1eb94d5e1..d7b552d962 100644 --- a/testing/btest/policy/frameworks/cluster/start-it-up.bro +++ b/testing/btest/scripts/base/frameworks/cluster/start-it-up.bro @@ -1,9 +1,11 @@ +# @TEST-GROUP: comm +# # @TEST-EXEC: btest-bg-run manager-1 BROPATH=$BROPATH:.. CLUSTER_NODE=manager-1 bro %INPUT # @TEST-EXEC: btest-bg-run proxy-1 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro %INPUT # @TEST-EXEC: btest-bg-run proxy-2 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-2 bro %INPUT # @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT # @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT -# @TEST-EXEC: btest-bg-wait -k 2 +# @TEST-EXEC: btest-bg-wait -k 10 # @TEST-EXEC: btest-diff manager-1/.stdout # @TEST-EXEC: btest-diff proxy-1/.stdout # @TEST-EXEC: btest-diff proxy-2/.stdout @@ -23,4 +25,4 @@ redef Cluster::nodes = { event remote_connection_handshake_done(p: event_peer) { print "Connected to a peer"; - } \ No newline at end of file + } diff --git a/testing/btest/scripts/base/frameworks/communication/communication_log_baseline.bro b/testing/btest/scripts/base/frameworks/communication/communication_log_baseline.bro new file mode 100644 index 0000000000..85b23dbdc0 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/communication/communication_log_baseline.bro @@ -0,0 +1,39 @@ +# @TEST-GROUP: comm +# +# @TEST-EXEC: btest-bg-run receiver bro -b ../receiver.bro +# @TEST-EXEC: btest-bg-run sender bro -b ../sender.bro +# @TEST-EXEC: btest-bg-wait -k 10 +# +# Don't diff the receiver log just because port is always going to change +# @TEST-EXEC: egrep -v 'pid|socket buffer size' sender/communication.log >send.log +# @TEST-EXEC: btest-diff send.log + +@TEST-START-FILE sender.bro + +@load base/frameworks/communication/main + +redef Communication::nodes += { + ["foo"] = [$host = 127.0.0.1, $events = /NOTHING/, $connect=T] +}; + +event remote_connection_handshake_done(p: event_peer) + { + terminate_communication(); + terminate(); + } + +@TEST-END-FILE + +############# + +@TEST-START-FILE receiver.bro + +@load frameworks/communication/listen + +event remote_connection_handshake_done(p: event_peer) + { + terminate_communication(); + terminate(); + } + +@TEST-END-FILE diff --git a/testing/btest/policy/frameworks/control/configuration_update.bro b/testing/btest/scripts/base/frameworks/control/configuration_update.bro similarity index 87% rename from testing/btest/policy/frameworks/control/configuration_update.bro rename to testing/btest/scripts/base/frameworks/control/configuration_update.bro index 23b4998a1b..d09105ca7a 100644 --- a/testing/btest/policy/frameworks/control/configuration_update.bro +++ b/testing/btest/scripts/base/frameworks/control/configuration_update.bro @@ -1,7 +1,9 @@ -# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port_clear=65531/tcp +# @TEST-GROUP: comm +# +# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port=65531/tcp # @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT test-redef frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65531/tcp Control::cmd=configuration_update # @TEST-EXEC: btest-bg-run controller2 BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65531/tcp Control::cmd=shutdown -# @TEST-EXEC: btest-bg-wait 1 +# @TEST-EXEC: btest-bg-wait 10 # @TEST-EXEC: btest-diff controllee/.stdout redef Communication::nodes = { @@ -23,4 +25,4 @@ event bro_init() event bro_done() { print test_var; - } \ No newline at end of file + } diff --git a/testing/btest/policy/frameworks/control/id_value.bro b/testing/btest/scripts/base/frameworks/control/id_value.bro similarity index 92% rename from testing/btest/policy/frameworks/control/id_value.bro rename to testing/btest/scripts/base/frameworks/control/id_value.bro index 9f0cb76861..7235521034 100644 --- a/testing/btest/policy/frameworks/control/id_value.bro +++ b/testing/btest/scripts/base/frameworks/control/id_value.bro @@ -1,6 +1,8 @@ -# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT only-for-controllee frameworks/control/controllee Communication::listen_port_clear=65532/tcp +# @TEST-GROUP: comm +# +# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT only-for-controllee frameworks/control/controllee Communication::listen_port=65532/tcp # @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65532/tcp Control::cmd=id_value Control::arg=test_var -# @TEST-EXEC: btest-bg-wait -k 1 +# @TEST-EXEC: btest-bg-wait -k 10 # @TEST-EXEC: btest-diff controller/.stdout redef Communication::nodes = { diff --git a/testing/btest/policy/frameworks/control/shutdown.bro b/testing/btest/scripts/base/frameworks/control/shutdown.bro similarity index 77% rename from testing/btest/policy/frameworks/control/shutdown.bro rename to testing/btest/scripts/base/frameworks/control/shutdown.bro index 55af973faa..ec1ca6da16 100644 --- a/testing/btest/policy/frameworks/control/shutdown.bro +++ b/testing/btest/scripts/base/frameworks/control/shutdown.bro @@ -1,6 +1,8 @@ -# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port_clear=65530/tcp +# @TEST-GROUP: comm +# +# @TEST-EXEC: btest-bg-run controllee BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controllee Communication::listen_port=65530/tcp # @TEST-EXEC: btest-bg-run controller BROPATH=$BROPATH:.. bro %INPUT frameworks/control/controller Control::host=127.0.0.1 Control::host_port=65530/tcp Control::cmd=shutdown -# @TEST-EXEC: btest-bg-wait 1 +# @TEST-EXEC: btest-bg-wait 10 redef Communication::nodes = { # We're waiting for connections from this host for control. diff --git a/testing/btest/policy/frameworks/intel/insert-and-matcher.bro b/testing/btest/scripts/base/frameworks/intel/insert-and-matcher.bro similarity index 100% rename from testing/btest/policy/frameworks/intel/insert-and-matcher.bro rename to testing/btest/scripts/base/frameworks/intel/insert-and-matcher.bro diff --git a/testing/btest/policy/frameworks/logging/adapt-filter.bro b/testing/btest/scripts/base/frameworks/logging/adapt-filter.bro similarity index 65% rename from testing/btest/policy/frameworks/logging/adapt-filter.bro rename to testing/btest/scripts/base/frameworks/logging/adapt-filter.bro index 2fc00dffb0..53cfdd1655 100644 --- a/testing/btest/policy/frameworks/logging/adapt-filter.bro +++ b/testing/btest/scripts/base/frameworks/logging/adapt-filter.bro @@ -7,7 +7,7 @@ module SSH; export { # Create a new ID for our log stream - redef enum Log::ID += { SSH }; + redef enum Log::ID += { LOG }; # Define a record with all the columns the log file can have. # (I'm using a subset of fields from ssh-ext for demonstration.) @@ -21,13 +21,13 @@ export { event bro_init() { - Log::create_stream(SSH, [$columns=Info]); + Log::create_stream(SSH::LOG, [$columns=Info]); - local filter = Log::get_filter(SSH, "default"); + local filter = Log::get_filter(SSH::LOG, "default"); filter$path= "ssh-new-default"; - Log::add_filter(SSH, filter); + Log::add_filter(SSH::LOG, filter); local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); } diff --git a/testing/btest/scripts/base/frameworks/logging/ascii-binary.bro b/testing/btest/scripts/base/frameworks/logging/ascii-binary.bro new file mode 100644 index 0000000000..fcbac3be58 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/ascii-binary.bro @@ -0,0 +1,25 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff ssh.log + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Info: record { + data: string; + data2: string; + } &log; +} + +redef LogAscii::separator = "|"; + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Info]); + Log::write(SSH::LOG, [$data="abc\n\xffdef", $data2="DATA2"]); + Log::write(SSH::LOG, [$data="abc|\xffdef", $data2="DATA2"]); + Log::write(SSH::LOG, [$data="abc\xff|def", $data2="DATA2"]); +} + diff --git a/testing/btest/policy/frameworks/logging/ascii-empty.bro b/testing/btest/scripts/base/frameworks/logging/ascii-empty.bro similarity index 55% rename from testing/btest/policy/frameworks/logging/ascii-empty.bro rename to testing/btest/scripts/base/frameworks/logging/ascii-empty.bro index 90f0b37a11..9dace5d52a 100644 --- a/testing/btest/policy/frameworks/logging/ascii-empty.bro +++ b/testing/btest/scripts/base/frameworks/logging/ascii-empty.bro @@ -11,7 +11,7 @@ redef LogAscii::header_prefix = "PREFIX<>"; module SSH; export { - redef enum Log::ID += { SSH }; + redef enum Log::ID += { LOG }; type Log: record { t: time; @@ -24,15 +24,15 @@ export { event bro_init() { - Log::create_stream(SSH, [$columns=Log]); + Log::create_stream(SSH::LOG, [$columns=Log]); local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - Log::write(SSH, [$t=network_time(), $id=cid, $status="success"]); - Log::write(SSH, [$t=network_time(), $id=cid, $country="US"]); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - Log::write(SSH, [$t=network_time(), $id=cid, $country="BR"]); - Log::write(SSH, [$t=network_time(), $id=cid, $b=T, $status="failure", $country=""]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $b=T, $status="failure", $country=""]); } diff --git a/testing/btest/scripts/base/frameworks/logging/ascii-escape-notset-str.bro b/testing/btest/scripts/base/frameworks/logging/ascii-escape-notset-str.bro new file mode 100644 index 0000000000..8c1401b179 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/ascii-escape-notset-str.bro @@ -0,0 +1,23 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff test.log + +module Test; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + x: string &optional; + y: string &optional; + z: string &optional; + } &log; +} + +event bro_init() +{ + Log::create_stream(Test::LOG, [$columns=Log]); + Log::write(Test::LOG, [$x=LogAscii::unset_field, $z=""]); +} + + diff --git a/testing/btest/scripts/base/frameworks/logging/ascii-escape-odd-url.bro b/testing/btest/scripts/base/frameworks/logging/ascii-escape-odd-url.bro new file mode 100644 index 0000000000..9df48edbb6 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/ascii-escape-odd-url.bro @@ -0,0 +1,4 @@ +# +# @TEST-EXEC: bro -C -r $TRACES/www-odd-url.trace +# @TEST-EXEC: btest-diff http.log + diff --git a/testing/btest/scripts/base/frameworks/logging/ascii-escape-set-separator.bro b/testing/btest/scripts/base/frameworks/logging/ascii-escape-set-separator.bro new file mode 100644 index 0000000000..f5fb7a6259 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/ascii-escape-set-separator.bro @@ -0,0 +1,21 @@ +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff test.log + +module Test; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + ss: set[string]; + } &log; +} + +event bro_init() +{ + Log::create_stream(Test::LOG, [$columns=Log]); + + + Log::write(Test::LOG, [$ss=set("AA", ",", ",,", "CC")]); +} + diff --git a/testing/btest/scripts/base/frameworks/logging/ascii-escape.bro b/testing/btest/scripts/base/frameworks/logging/ascii-escape.bro new file mode 100644 index 0000000000..f2c370a27a --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/ascii-escape.bro @@ -0,0 +1,32 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff ssh.log + +redef LogAscii::separator = "||"; + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="fa||ure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="su||ess", $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); +} + diff --git a/testing/btest/scripts/base/frameworks/logging/ascii-options.bro b/testing/btest/scripts/base/frameworks/logging/ascii-options.bro new file mode 100644 index 0000000000..8c228c1384 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/ascii-options.bro @@ -0,0 +1,35 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff ssh.log + +redef LogAscii::output_to_stdout = F; +redef LogAscii::separator = "|"; +redef LogAscii::include_header = F; + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success", $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + +} + diff --git a/testing/btest/scripts/base/frameworks/logging/ascii-timestamps.bro b/testing/btest/scripts/base/frameworks/logging/ascii-timestamps.bro new file mode 100644 index 0000000000..e63e30f6c6 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/ascii-timestamps.bro @@ -0,0 +1,27 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff test.log + +module Test; + +export { + redef enum Log::ID += { LOG }; + + type Info: record { + data: time &log; + }; +} + +event bro_init() +{ + Log::create_stream(Test::LOG, [$columns=Info]); + Log::write(Test::LOG, [$data=double_to_time(1234567890)]); + Log::write(Test::LOG, [$data=double_to_time(1234567890.0)]); + Log::write(Test::LOG, [$data=double_to_time(1234567890.01)]); + Log::write(Test::LOG, [$data=double_to_time(1234567890.001)]); + Log::write(Test::LOG, [$data=double_to_time(1234567890.0001)]); + Log::write(Test::LOG, [$data=double_to_time(1234567890.00001)]); + Log::write(Test::LOG, [$data=double_to_time(1234567890.000001)]); + Log::write(Test::LOG, [$data=double_to_time(1234567890.0000001)]); +} + diff --git a/testing/btest/policy/frameworks/logging/attr-extend.bro b/testing/btest/scripts/base/frameworks/logging/attr-extend.bro similarity index 72% rename from testing/btest/policy/frameworks/logging/attr-extend.bro rename to testing/btest/scripts/base/frameworks/logging/attr-extend.bro index 03f0996cef..7f58f3f8c1 100644 --- a/testing/btest/policy/frameworks/logging/attr-extend.bro +++ b/testing/btest/scripts/base/frameworks/logging/attr-extend.bro @@ -5,7 +5,7 @@ module SSH; export { - redef enum Log::ID += { SSH }; + redef enum Log::ID += { LOG }; type Log: record { t: time; @@ -28,10 +28,10 @@ redef record Log += { event bro_init() { - Log::create_stream(SSH, [$columns=Log]); + Log::create_stream(SSH::LOG, [$columns=Log]); local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; - Log::write(SSH, [$t=network_time(), $id=cid, $status="success", $a1=1, $a2=2, $b1=3, $b2=4]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success", $a1=1, $a2=2, $b1=3, $b2=4]); } diff --git a/testing/btest/scripts/base/frameworks/logging/attr.bro b/testing/btest/scripts/base/frameworks/logging/attr.bro new file mode 100644 index 0000000000..8ec3d1c385 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/attr.bro @@ -0,0 +1,31 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff ssh.log + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + t: time; + id: conn_id; + status: string &optional &log; + country: string &default="unknown" &log; + }; +} + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success", $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + +} + diff --git a/testing/btest/scripts/base/frameworks/logging/disable-stream.bro b/testing/btest/scripts/base/frameworks/logging/disable-stream.bro new file mode 100644 index 0000000000..6799f7ca2f --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/disable-stream.bro @@ -0,0 +1,33 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: test '!' -e ssh.log + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + + Log::disable_stream(SSH::LOG); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success", $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + +} + diff --git a/testing/btest/scripts/base/frameworks/logging/empty-event.bro b/testing/btest/scripts/base/frameworks/logging/empty-event.bro new file mode 100644 index 0000000000..6aa867220f --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/empty-event.bro @@ -0,0 +1,33 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff ssh.log + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +global log_ssh: event(rec: Log); + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log, $ev=log_ssh]); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success", $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + +} + diff --git a/testing/btest/scripts/base/frameworks/logging/env-ext.test b/testing/btest/scripts/base/frameworks/logging/env-ext.test new file mode 100644 index 0000000000..e9f690caa4 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/env-ext.test @@ -0,0 +1,2 @@ +# @TEST-EXEC: BRO_LOG_SUFFIX=txt bro -r $TRACES/wikipedia.trace +# @TEST-EXEC: test -f conn.txt diff --git a/testing/btest/policy/frameworks/logging/events.bro b/testing/btest/scripts/base/frameworks/logging/events.bro similarity index 76% rename from testing/btest/policy/frameworks/logging/events.bro rename to testing/btest/scripts/base/frameworks/logging/events.bro index 6013938569..bf156e6d60 100644 --- a/testing/btest/policy/frameworks/logging/events.bro +++ b/testing/btest/scripts/base/frameworks/logging/events.bro @@ -6,7 +6,7 @@ module SSH; export { # Create a new ID for our log stream - redef enum Log::ID += { SSH }; + redef enum Log::ID += { LOG }; # Define a record with all the columns the log file can have. # (I'm using a subset of fields from ssh-ext for demonstration.) @@ -22,12 +22,12 @@ global ssh_log: event(rec: Log); event bro_init() { - Log::create_stream(SSH, [$columns=Log, $ev=ssh_log]); + Log::create_stream(SSH::LOG, [$columns=Log, $ev=ssh_log]); local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; local r: Log = [$t=network_time(), $id=cid, $status="success"]; - Log::write(SSH, r); - Log::write(SSH, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, r); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); } diff --git a/testing/btest/scripts/base/frameworks/logging/exclude.bro b/testing/btest/scripts/base/frameworks/logging/exclude.bro new file mode 100644 index 0000000000..7b245541ab --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/exclude.bro @@ -0,0 +1,34 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff ssh.log + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + + Log::remove_default_filter(SSH::LOG); + Log::add_filter(SSH::LOG, [$name="f1", $exclude=set("t", "id.orig_h")]); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success", $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + +} + diff --git a/testing/btest/policy/frameworks/logging/file.bro b/testing/btest/scripts/base/frameworks/logging/file.bro similarity index 60% rename from testing/btest/policy/frameworks/logging/file.bro rename to testing/btest/scripts/base/frameworks/logging/file.bro index e910c7c516..94bdad6b1b 100644 --- a/testing/btest/policy/frameworks/logging/file.bro +++ b/testing/btest/scripts/base/frameworks/logging/file.bro @@ -5,7 +5,7 @@ module SSH; export { - redef enum Log::ID += { SSH }; + redef enum Log::ID += { LOG }; type Log: record { t: time; @@ -17,7 +17,7 @@ const foo_log = open_log_file("Foo") &redef; event bro_init() { - Log::create_stream(SSH, [$columns=Log]); - Log::write(SSH, [$t=network_time(), $f=foo_log]); + Log::create_stream(SSH::LOG, [$columns=Log]); + Log::write(SSH::LOG, [$t=network_time(), $f=foo_log]); } diff --git a/testing/btest/scripts/base/frameworks/logging/include.bro b/testing/btest/scripts/base/frameworks/logging/include.bro new file mode 100644 index 0000000000..d0fea93c99 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/include.bro @@ -0,0 +1,34 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff ssh.log + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + + Log::remove_default_filter(SSH::LOG); + Log::add_filter(SSH::LOG, [$name="default", $include=set("t", "id.orig_h")]); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success", $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + +} + diff --git a/testing/btest/scripts/base/frameworks/logging/no-local.bro b/testing/btest/scripts/base/frameworks/logging/no-local.bro new file mode 100644 index 0000000000..9ae7d32d61 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/no-local.bro @@ -0,0 +1,33 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: test '!' -e ssh.log + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +redef Log::enable_local_logging = F; + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success", $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + +} + diff --git a/testing/btest/scripts/base/frameworks/logging/path-func-column-demote.bro b/testing/btest/scripts/base/frameworks/logging/path-func-column-demote.bro new file mode 100644 index 0000000000..aff886c2f4 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/path-func-column-demote.bro @@ -0,0 +1,26 @@ +# @TEST-EXEC: bro -b -r $TRACES/wikipedia.trace %INPUT +# @TEST-EXEC: btest-diff local.log +# @TEST-EXEC: btest-diff remote.log +# +# The record value passed into the path_func should be allowed to contain a +# subset of the fields in the stream's columns. + +@load base/utils/site +@load base/protocols/conn +@load base/frameworks/notice + +redef Site::local_nets = {141.142.0.0/16}; + +function split_log(id: Log::ID, path: string, rec: record {id:conn_id;}): string +{ + return Site::is_local_addr(rec$id$orig_h) ? "local" : "remote"; +} + +event bro_init() +{ + # Add a new filter to the Conn::LOG stream that logs only + # timestamp and originator address. + local filter: Log::Filter = [$name="dst-only", $path_func=split_log, + $include=set("ts", "id.orig_h")]; + Log::add_filter(Conn::LOG, filter); +} diff --git a/testing/btest/scripts/base/frameworks/logging/path-func.bro b/testing/btest/scripts/base/frameworks/logging/path-func.bro new file mode 100644 index 0000000000..684aa03ed6 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/path-func.bro @@ -0,0 +1,48 @@ + +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: ( ls static-*; cat static-* ) >output +# @TEST-EXEC: btest-diff output + +module SSH; + +export { + # Create a new ID for our log stream + redef enum Log::ID += { LOG }; + + # Define a record with all the columns the log file can have. + # (I'm using a subset of fields from ssh-ext for demonstration.) + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +global c = -1; + +function path_func(id: Log::ID, path: string, rec: Log) : string + { + c = (c + 1) % 3; + + return fmt("%s-%d-%s", path, c, rec$country); + } + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + Log::remove_default_filter(SSH::LOG); + + Log::add_filter(SSH::LOG, [$name="dyn", $path="static-prefix", $path_func=path_func]); + + Log::set_buf(SSH::LOG, F); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success", $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX2"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX3"]); +} diff --git a/testing/btest/scripts/base/frameworks/logging/pred.bro b/testing/btest/scripts/base/frameworks/logging/pred.bro new file mode 100644 index 0000000000..e13c726656 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/pred.bro @@ -0,0 +1,39 @@ + +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff test.success.log +# @TEST-EXEC: btest-diff test.failure.log + +module Test; + +export { + # Create a new ID for our log stream + redef enum Log::ID += { LOG }; + + # Define a record with all the columns the log file can have. + # (I'm using a subset of fields from ssh for demonstration.) + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +function fail(rec: Log): bool + { + return rec$status != "success"; + } + +event bro_init() +{ + Log::create_stream(Test::LOG, [$columns=Log]); + Log::remove_default_filter(Test::LOG); + Log::add_filter(Test::LOG, [$name="f1", $path="test.success", $pred=function(rec: Log): bool { return rec$status == "success"; }]); + Log::add_filter(Test::LOG, [$name="f2", $path="test.failure", $pred=fail]); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + local r: Log = [$t=network_time(), $id=cid, $status="success"]; + Log::write(Test::LOG, r); + Log::write(Test::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + +} diff --git a/testing/btest/policy/frameworks/logging/remote-types.bro b/testing/btest/scripts/base/frameworks/logging/remote-types.bro similarity index 85% rename from testing/btest/policy/frameworks/logging/remote-types.bro rename to testing/btest/scripts/base/frameworks/logging/remote-types.bro index 08960eba86..ce93495bc8 100644 --- a/testing/btest/policy/frameworks/logging/remote-types.bro +++ b/testing/btest/scripts/base/frameworks/logging/remote-types.bro @@ -1,7 +1,8 @@ +# @TEST-GROUP: comm # # @TEST-EXEC: btest-bg-run sender bro --pseudo-realtime %INPUT ../sender.bro # @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro -# @TEST-EXEC: btest-bg-wait -k 1 +# @TEST-EXEC: btest-bg-wait -k 10 # @TEST-EXEC: btest-diff receiver/test.log # @TEST-EXEC: cmp receiver/test.log sender/test.log @@ -15,7 +16,7 @@ module Test; export { # Create a new ID for our log stream - redef enum Log::ID += { TEST }; + redef enum Log::ID += { LOG }; type Log: record { b: bool; @@ -39,7 +40,7 @@ export { event bro_init() { - Log::create_stream(TEST, [$columns=Log]); + Log::create_stream(Test::LOG, [$columns=Log]); } ##### @@ -48,17 +49,17 @@ event bro_init() module Test; -@load frameworks/communication/listen-clear +@load frameworks/communication/listen event remote_connection_handshake_done(p: event_peer) { local empty_set: set[string]; local empty_vector: vector of string; - Log::write(TEST, [ + Log::write(Test::LOG, [ $b=T, $i=-42, - $e=TEST, + $e=Test::LOG, $c=21, $p=123/tcp, $sn=10.0.0.1/24, @@ -73,6 +74,7 @@ event remote_connection_handshake_done(p: event_peer) $vc=vector(10, 20, 30), $ve=empty_vector ]); + disconnect(p); } @TEST-END-FILE diff --git a/testing/btest/policy/frameworks/logging/remote.bro b/testing/btest/scripts/base/frameworks/logging/remote.bro similarity index 62% rename from testing/btest/policy/frameworks/logging/remote.bro rename to testing/btest/scripts/base/frameworks/logging/remote.bro index 00d7d69463..bb1e5b8ce3 100644 --- a/testing/btest/policy/frameworks/logging/remote.bro +++ b/testing/btest/scripts/base/frameworks/logging/remote.bro @@ -1,9 +1,10 @@ +# @TEST-GROUP: comm # # @TEST-EXEC: btest-bg-run sender bro --pseudo-realtime %INPUT ../sender.bro # @TEST-EXEC: sleep 1 # @TEST-EXEC: btest-bg-run receiver bro --pseudo-realtime %INPUT ../receiver.bro # @TEST-EXEC: sleep 1 -# @TEST-EXEC: btest-bg-wait -k 1 +# @TEST-EXEC: btest-bg-wait -k 10 # @TEST-EXEC: btest-diff sender/test.log # @TEST-EXEC: btest-diff sender/test.failure.log # @TEST-EXEC: btest-diff sender/test.success.log @@ -16,7 +17,7 @@ module Test; export { # Create a new ID for our log stream - redef enum Log::ID += { TEST }; + redef enum Log::ID += { LOG }; # Define a record with all the columns the log file can have. # (I'm using a subset of fields from ssh-ext for demonstration.) @@ -30,8 +31,8 @@ export { event bro_init() { - Log::create_stream(TEST, [$columns=Log]); - Log::add_filter(TEST, [$name="f1", $path="test.success", $pred=function(rec: Log): bool { return rec$status == "success"; }]); + Log::create_stream(Test::LOG, [$columns=Log]); + Log::add_filter(Test::LOG, [$name="f1", $path="test.success", $pred=function(rec: Log): bool { return rec$status == "success"; }]); } ##### @@ -40,7 +41,7 @@ event bro_init() module Test; -@load frameworks/communication/listen-clear +@load frameworks/communication/listen function fail(rec: Log): bool { @@ -49,18 +50,19 @@ function fail(rec: Log): bool event remote_connection_handshake_done(p: event_peer) { - Log::add_filter(TEST, [$name="f2", $path="test.failure", $pred=fail]); + Log::add_filter(Test::LOG, [$name="f2", $path="test.failure", $pred=fail]); - local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; local r: Log = [$t=network_time(), $id=cid, $status="success"]; # Log something. - Log::write(TEST, r); - Log::write(TEST, [$t=network_time(), $id=cid, $status="failure", $country="US"]); - Log::write(TEST, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); - Log::write(TEST, [$t=network_time(), $id=cid, $status="success", $country="BR"]); - Log::write(TEST, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + Log::write(Test::LOG, r); + Log::write(Test::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(Test::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(Test::LOG, [$t=network_time(), $id=cid, $status="success", $country="BR"]); + Log::write(Test::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + disconnect(p); } @TEST-END-FILE diff --git a/testing/btest/scripts/base/frameworks/logging/remove.bro b/testing/btest/scripts/base/frameworks/logging/remove.bro new file mode 100644 index 0000000000..bb7c302942 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/remove.bro @@ -0,0 +1,41 @@ +# +# @TEST-EXEC: bro -b -B logging %INPUT +# @TEST-EXEC: btest-diff ssh.log +# @TEST-EXEC: btest-diff ssh.failure.log + +module SSH; + +export { + # Create a new ID for our log stream + redef enum Log::ID += { LOG }; + + # Define a record with all the columns the log file can have. + # (I'm using a subset of fields from ssh-ext for demonstration.) + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + Log::add_filter(SSH::LOG, [$name="f1", $path="ssh.failure", $pred=function(rec: Log): bool { return rec$status == "failure"; }]); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + # Log something. + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + + Log::remove_filter(SSH::LOG, "f1"); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="BR"]); + + Log::remove_filter(SSH::LOG, "default"); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + + Log::remove_filter(SSH::LOG, "doesn-not-exist"); +} + diff --git a/testing/btest/policy/frameworks/logging/rotate-custom.bro b/testing/btest/scripts/base/frameworks/logging/rotate-custom.bro similarity index 64% rename from testing/btest/policy/frameworks/logging/rotate-custom.bro rename to testing/btest/scripts/base/frameworks/logging/rotate-custom.bro index 788fa090e9..7c06ff9248 100644 --- a/testing/btest/policy/frameworks/logging/rotate-custom.bro +++ b/testing/btest/scripts/base/frameworks/logging/rotate-custom.bro @@ -1,13 +1,14 @@ # -# @TEST-EXEC: bro -b -r %DIR/rotation.trace %INPUT 2>&1 | egrep "test|test2" | sort >out +# @TEST-EXEC: bro -b -r %DIR/rotation.trace %INPUT | egrep "test|test2" | sort >out # @TEST-EXEC: for i in `ls test*.log | sort`; do printf '> %s\n' $i; cat $i; done | sort | uniq >>out # @TEST-EXEC: btest-diff out +# @TEST-EXEC: btest-diff .stderr module Test; export { # Create a new ID for our log stream - redef enum Log::ID += { Test }; + redef enum Log::ID += { LOG }; # Define a record with all the columns the log file can have. # (I'm using a subset of fields from ssh-ext for demonstration.) @@ -26,18 +27,13 @@ function custom_rotate(info: Log::RotationInfo) : bool return T; } -redef Log::rotation_control += { - [Log::WRITER_ASCII, "test2"] = [$interv=30mins, $postprocessor=custom_rotate] -}; - event bro_init() { - Log::create_stream(Test, [$columns=Log]); - Log::add_filter(Test, [$name="2nd", $path="test2"]); - + Log::create_stream(Test::LOG, [$columns=Log]); + Log::add_filter(Test::LOG, [$name="2nd", $path="test2", $interv=30mins, $postprocessor=custom_rotate]); } event new_connection(c: connection) { - Log::write(Test, [$t=network_time(), $id=c$id]); + Log::write(Test::LOG, [$t=network_time(), $id=c$id]); } diff --git a/testing/btest/policy/frameworks/logging/rotate.bro b/testing/btest/scripts/base/frameworks/logging/rotate.bro similarity index 73% rename from testing/btest/policy/frameworks/logging/rotate.bro rename to testing/btest/scripts/base/frameworks/logging/rotate.bro index d53b92f169..14123c56c6 100644 --- a/testing/btest/policy/frameworks/logging/rotate.bro +++ b/testing/btest/scripts/base/frameworks/logging/rotate.bro @@ -1,5 +1,5 @@ # -# @TEST-EXEC: bro -r %DIR/rotation.trace %INPUT 2>&1 | grep "test" >out +# @TEST-EXEC: bro -b -r %DIR/rotation.trace %INPUT 2>&1 | grep "test" >out # @TEST-EXEC: for i in test.*.log; do printf '> %s\n' $i; cat $i; done >>out # @TEST-EXEC: btest-diff out @@ -7,7 +7,7 @@ module Test; export { # Create a new ID for our log stream - redef enum Log::ID += { Test }; + redef enum Log::ID += { LOG }; # Define a record with all the columns the log file can have. # (I'm using a subset of fields from ssh-ext for demonstration.) @@ -22,10 +22,10 @@ redef Log::default_rotation_postprocessor_cmd = "echo"; event bro_init() { - Log::create_stream(Test, [$columns=Log]); + Log::create_stream(Test::LOG, [$columns=Log]); } event new_connection(c: connection) { - Log::write(Test, [$t=network_time(), $id=c$id]); + Log::write(Test::LOG, [$t=network_time(), $id=c$id]); } diff --git a/testing/btest/policy/frameworks/logging/rotation.trace b/testing/btest/scripts/base/frameworks/logging/rotation.trace similarity index 100% rename from testing/btest/policy/frameworks/logging/rotation.trace rename to testing/btest/scripts/base/frameworks/logging/rotation.trace diff --git a/testing/btest/scripts/base/frameworks/logging/stdout.bro b/testing/btest/scripts/base/frameworks/logging/stdout.bro new file mode 100644 index 0000000000..f431a5b6c9 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/stdout.bro @@ -0,0 +1,36 @@ +# +# @TEST-EXEC: bro -b %INPUT >output +# @TEST-EXEC: btest-diff output +# @TEST-EXEC: test '!' -e ssh.log + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + + local filter = Log::get_filter(SSH::LOG, "default"); + filter$path= "/dev/stdout"; + Log::add_filter(SSH::LOG, filter); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success", $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + +} + diff --git a/testing/btest/scripts/base/frameworks/logging/test-logging.bro b/testing/btest/scripts/base/frameworks/logging/test-logging.bro new file mode 100644 index 0000000000..9f90d515fb --- /dev/null +++ b/testing/btest/scripts/base/frameworks/logging/test-logging.bro @@ -0,0 +1,31 @@ +# +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff ssh.log + +module SSH; + +export { + redef enum Log::ID += { LOG }; + + type Log: record { + t: time; + id: conn_id; # Will be rolled out into individual columns. + status: string &optional; + country: string &default="unknown"; + } &log; +} + +event bro_init() +{ + Log::create_stream(SSH::LOG, [$columns=Log]); + + local cid = [$orig_h=1.2.3.4, $orig_p=1234/tcp, $resp_h=2.3.4.5, $resp_p=80/tcp]; + + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="US"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="UK"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="success", $country="BR"]); + Log::write(SSH::LOG, [$t=network_time(), $id=cid, $status="failure", $country="MX"]); + +} + diff --git a/testing/btest/policy/frameworks/logging/types.bro b/testing/btest/scripts/base/frameworks/logging/types.bro similarity index 88% rename from testing/btest/policy/frameworks/logging/types.bro rename to testing/btest/scripts/base/frameworks/logging/types.bro index 9e299c643a..d79c667e50 100644 --- a/testing/btest/policy/frameworks/logging/types.bro +++ b/testing/btest/scripts/base/frameworks/logging/types.bro @@ -9,7 +9,7 @@ redef LogAscii::empty_field = "EMPTY"; module SSH; export { - redef enum Log::ID += { SSH }; + redef enum Log::ID += { LOG }; type Log: record { b: bool; @@ -42,15 +42,15 @@ function foo(i : count) : string event bro_init() { - Log::create_stream(SSH, [$columns=Log]); + Log::create_stream(SSH::LOG, [$columns=Log]); local empty_set: set[string]; local empty_vector: vector of string; - Log::write(SSH, [ + Log::write(SSH::LOG, [ $b=T, $i=-42, - $e=SSH, + $e=SSH::LOG, $c=21, $p=123/tcp, $sn=10.0.0.1/24, diff --git a/testing/btest/policy/frameworks/logging/unset-record.bro b/testing/btest/scripts/base/frameworks/logging/unset-record.bro similarity index 100% rename from testing/btest/policy/frameworks/logging/unset-record.bro rename to testing/btest/scripts/base/frameworks/logging/unset-record.bro diff --git a/testing/btest/policy/frameworks/logging/vec.bro b/testing/btest/scripts/base/frameworks/logging/vec.bro similarity index 67% rename from testing/btest/policy/frameworks/logging/vec.bro rename to testing/btest/scripts/base/frameworks/logging/vec.bro index 2a2bc779f3..00c5ff5117 100644 --- a/testing/btest/policy/frameworks/logging/vec.bro +++ b/testing/btest/scripts/base/frameworks/logging/vec.bro @@ -5,7 +5,7 @@ module SSH; export { - redef enum Log::ID += { SSH }; + redef enum Log::ID += { LOG }; type Log: record { vec: vector of string &log; @@ -14,14 +14,14 @@ export { event bro_init() { - Log::create_stream(SSH, [$columns=Log]); + Log::create_stream(SSH::LOG, [$columns=Log]); local v: vector of string; v[1] = "2"; v[4] = "5"; - Log::write(SSH, [$vec=v]); + Log::write(SSH::LOG, [$vec=v]); } diff --git a/testing/btest/policy/frameworks/metrics/basic-cluster.bro b/testing/btest/scripts/base/frameworks/metrics/basic-cluster.bro similarity index 93% rename from testing/btest/policy/frameworks/metrics/basic-cluster.bro rename to testing/btest/scripts/base/frameworks/metrics/basic-cluster.bro index 75dd7b762d..b801074b33 100644 --- a/testing/btest/policy/frameworks/metrics/basic-cluster.bro +++ b/testing/btest/scripts/base/frameworks/metrics/basic-cluster.bro @@ -1,9 +1,11 @@ +# @TEST-GROUP: comm +# # @TEST-EXEC: btest-bg-run manager-1 BROPATH=$BROPATH:.. CLUSTER_NODE=manager-1 bro %INPUT # @TEST-EXEC: btest-bg-run proxy-1 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro %INPUT # @TEST-EXEC: sleep 1 # @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT # @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT -# @TEST-EXEC: btest-bg-wait -k 6 +# @TEST-EXEC: btest-bg-wait -k 10 # @TEST-EXEC: btest-diff manager-1/metrics.log @TEST-START-FILE cluster-layout.bro @@ -15,6 +17,8 @@ redef Cluster::nodes = { }; @TEST-END-FILE +redef Log::default_rotation_interval = 0secs; + redef enum Metrics::ID += { TEST_METRIC, }; diff --git a/testing/btest/policy/frameworks/metrics/basic.bro b/testing/btest/scripts/base/frameworks/metrics/basic.bro similarity index 100% rename from testing/btest/policy/frameworks/metrics/basic.bro rename to testing/btest/scripts/base/frameworks/metrics/basic.bro diff --git a/testing/btest/policy/frameworks/metrics/cluster-intermediate-update.bro b/testing/btest/scripts/base/frameworks/metrics/cluster-intermediate-update.bro similarity index 94% rename from testing/btest/policy/frameworks/metrics/cluster-intermediate-update.bro rename to testing/btest/scripts/base/frameworks/metrics/cluster-intermediate-update.bro index 519de35805..701d2ea378 100644 --- a/testing/btest/policy/frameworks/metrics/cluster-intermediate-update.bro +++ b/testing/btest/scripts/base/frameworks/metrics/cluster-intermediate-update.bro @@ -1,9 +1,11 @@ +# @TEST-GROUP: comm +# # @TEST-EXEC: btest-bg-run manager-1 BROPATH=$BROPATH:.. CLUSTER_NODE=manager-1 bro %INPUT # @TEST-EXEC: btest-bg-run proxy-1 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro %INPUT # @TEST-EXEC: sleep 1 # @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT # @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT -# @TEST-EXEC: btest-bg-wait -k 5 +# @TEST-EXEC: btest-bg-wait -k 10 # @TEST-EXEC: btest-diff manager-1/notice.log @TEST-START-FILE cluster-layout.bro @@ -15,6 +17,8 @@ redef Cluster::nodes = { }; @TEST-END-FILE +redef Log::default_rotation_interval = 0secs; + redef enum Notice::Type += { Test_Notice, }; @@ -51,4 +55,4 @@ event bro_init() event do_metrics(1); } -@endif \ No newline at end of file +@endif diff --git a/testing/btest/policy/frameworks/metrics/notice.bro b/testing/btest/scripts/base/frameworks/metrics/notice.bro similarity index 100% rename from testing/btest/policy/frameworks/metrics/notice.bro rename to testing/btest/scripts/base/frameworks/metrics/notice.bro diff --git a/testing/btest/scripts/base/frameworks/notice/cluster.bro b/testing/btest/scripts/base/frameworks/notice/cluster.bro new file mode 100644 index 0000000000..97470eaa7f --- /dev/null +++ b/testing/btest/scripts/base/frameworks/notice/cluster.bro @@ -0,0 +1,33 @@ +# @TEST-GROUP: comm +# +# @TEST-EXEC: btest-bg-run manager-1 BROPATH=$BROPATH:.. CLUSTER_NODE=manager-1 bro %INPUT +# @TEST-EXEC: btest-bg-run proxy-1 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro %INPUT +# @TEST-EXEC: sleep 1 +# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT +# @TEST-EXEC: btest-bg-wait -k 10 +# @TEST-EXEC: btest-diff manager-1/notice.log + +@TEST-START-FILE cluster-layout.bro +redef Cluster::nodes = { + ["manager-1"] = [$node_type=Cluster::MANAGER, $ip=127.0.0.1, $p=27757/tcp, $workers=set("worker-1")], + ["proxy-1"] = [$node_type=Cluster::PROXY, $ip=127.0.0.1, $p=27758/tcp, $manager="manager-1", $workers=set("worker-1")], + ["worker-1"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=27760/tcp, $manager="manager-1", $proxy="proxy-1", $interface="eth0"], +}; +@TEST-END-FILE + +redef Log::default_rotation_interval = 0secs; + +redef enum Notice::Type += { + Test_Notice, +}; + +event delayed_notice() + { + if ( Cluster::node == "worker-1" ) + NOTICE([$note=Test_Notice, $msg="test notice!"]); + } + +event bro_init() + { + schedule 1secs { delayed_notice() }; + } diff --git a/testing/btest/scripts/base/frameworks/notice/default-policy-order.test b/testing/btest/scripts/base/frameworks/notice/default-policy-order.test new file mode 100644 index 0000000000..6e53bd3b54 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/notice/default-policy-order.test @@ -0,0 +1,10 @@ +# This test checks that the default notice policy ordering does not +# change from run to run. +# @TEST-EXEC: bro -e '' +# @TEST-EXEC: mv notice_policy.log notice_policy.log.1 +# @TEST-EXEC: bro -e '' +# @TEST-EXEC: mv notice_policy.log notice_policy.log.2 +# @TEST-EXEC: bro -e '' +# @TEST-EXEC: mv notice_policy.log notice_policy.log.3 +# @TEST-EXEC: diff notice_policy.log.1 notice_policy.log.2 +# @TEST-EXEC: diff notice_policy.log.1 notice_policy.log.3 diff --git a/testing/btest/scripts/base/frameworks/notice/mail-alarms.bro b/testing/btest/scripts/base/frameworks/notice/mail-alarms.bro new file mode 100644 index 0000000000..3116b1025a --- /dev/null +++ b/testing/btest/scripts/base/frameworks/notice/mail-alarms.bro @@ -0,0 +1,17 @@ +# @TEST-EXEC: bro -C -r $TRACES/web.trace %INPUT +# @TEST-EXEC: btest-diff alarm-mail.txt + +redef Notice::policy += { [$action = Notice::ACTION_ALARM, $priority = 1 ] }; +redef Notice::force_email_summaries = T; + +redef enum Notice::Type += { + Test_Notice, +}; + +event connection_established(c: connection) + { + NOTICE([$note=Test_Notice, $conn=c, $msg="test", $identifier="static"]); + } + + + diff --git a/testing/btest/scripts/base/frameworks/notice/suppression-cluster.bro b/testing/btest/scripts/base/frameworks/notice/suppression-cluster.bro new file mode 100644 index 0000000000..d56d940e8e --- /dev/null +++ b/testing/btest/scripts/base/frameworks/notice/suppression-cluster.bro @@ -0,0 +1,39 @@ +# @TEST-GROUP: comm +# +# @TEST-EXEC: btest-bg-run manager-1 BROPATH=$BROPATH:.. CLUSTER_NODE=manager-1 bro %INPUT +# @TEST-EXEC: btest-bg-run proxy-1 BROPATH=$BROPATH:.. CLUSTER_NODE=proxy-1 bro %INPUT +# @TEST-EXEC: sleep 1 +# @TEST-EXEC: btest-bg-run worker-1 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-1 bro %INPUT +# @TEST-EXEC: btest-bg-run worker-2 BROPATH=$BROPATH:.. CLUSTER_NODE=worker-2 bro %INPUT +# @TEST-EXEC: btest-bg-wait -k 10 +# @TEST-EXEC: btest-diff manager-1/notice.log + +@TEST-START-FILE cluster-layout.bro +redef Cluster::nodes = { + ["manager-1"] = [$node_type=Cluster::MANAGER, $ip=127.0.0.1, $p=27757/tcp, $workers=set("worker-1", "worker-2")], + ["proxy-1"] = [$node_type=Cluster::PROXY, $ip=127.0.0.1, $p=27758/tcp, $manager="manager-1", $workers=set("worker-1", "worker-2")], + ["worker-1"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=27760/tcp, $manager="manager-1", $proxy="proxy-1"], + ["worker-2"] = [$node_type=Cluster::WORKER, $ip=127.0.0.1, $p=27761/tcp, $manager="manager-1", $proxy="proxy-1"], +}; +@TEST-END-FILE + +redef Log::default_rotation_interval = 0secs; + +redef enum Notice::Type += { + Test_Notice, +}; + +event delayed_notice() + { + NOTICE([$note=Test_Notice, + $msg="test notice!", + $identifier="this identifier is static"]); + } + +event bro_init() &priority=5 + { + if ( Cluster::node == "worker-1" ) + schedule 4secs { delayed_notice() }; + if ( Cluster::node == "worker-2" ) + schedule 1secs { delayed_notice() }; + } diff --git a/testing/btest/scripts/base/frameworks/notice/suppression-disable.bro b/testing/btest/scripts/base/frameworks/notice/suppression-disable.bro new file mode 100644 index 0000000000..96b932caf8 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/notice/suppression-disable.bro @@ -0,0 +1,25 @@ +# @TEST-EXEC: bro -b %INPUT +# The "Test_Notice" should be logged twice +# @TEST-EXEC: test `grep Test_Notice notice.log | wc -l` -eq 2 + +@load base/frameworks/notice + +redef enum Notice::Type += { + Test_Notice, +}; + +redef Notice::not_suppressed_types += { Test_Notice }; + +# The second notice needs to be scheduled due to how the notice framework +# uses the event queue. + +event second_notice() + { + NOTICE([$note=Test_Notice, $msg="another test", $identifier="static"]); + } + +event bro_init() + { + NOTICE([$note=Test_Notice, $msg="test", $identifier="static"]); + schedule 1msec { second_notice() }; + } diff --git a/testing/btest/scripts/base/frameworks/notice/suppression.bro b/testing/btest/scripts/base/frameworks/notice/suppression.bro new file mode 100644 index 0000000000..87ce3672b6 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/notice/suppression.bro @@ -0,0 +1,23 @@ +# @TEST-EXEC: bro -b %INPUT +# @TEST-EXEC: btest-diff notice.log + +@load base/frameworks/notice + +redef enum Notice::Type += { + Test_Notice, +}; + +# The second notice needs to be scheduled due to how the notice framework +# uses the event queue. + +event second_notice() + { + NOTICE([$note=Test_Notice, $msg="another test", $identifier="static"]); + } + +event bro_init() + { + NOTICE([$note=Test_Notice, $msg="test", $identifier="static"]); + schedule 1msec { second_notice() }; + } + diff --git a/testing/btest/scripts/base/frameworks/packet-filter/bad-filter.test b/testing/btest/scripts/base/frameworks/packet-filter/bad-filter.test new file mode 100644 index 0000000000..a3e2a54c57 --- /dev/null +++ b/testing/btest/scripts/base/frameworks/packet-filter/bad-filter.test @@ -0,0 +1,2 @@ +# @TEST-EXEC-FAIL: bro -r $TRACES/web.trace -f "bad filter" +# @TEST-EXEC: test -s .stderr diff --git a/testing/btest/policy/frameworks/software/version-parsing.bro b/testing/btest/scripts/base/frameworks/software/version-parsing.bro similarity index 57% rename from testing/btest/policy/frameworks/software/version-parsing.bro rename to testing/btest/scripts/base/frameworks/software/version-parsing.bro index 5e57a6c3a4..03327a25cd 100644 --- a/testing/btest/policy/frameworks/software/version-parsing.bro +++ b/testing/btest/scripts/base/frameworks/software/version-parsing.bro @@ -1,104 +1,116 @@ # @TEST-EXEC: bro %INPUT > output # @TEST-EXEC: btest-diff output -global ts = network_time(); -global host = 0.0.0.0; +module Software; -global matched_software: table[string] of Software::Info = { +global matched_software: table[string] of Software::Description = { ["OpenSSH_4.4"] = - [$name="OpenSSH", $version=[$major=4,$minor=4], $host=host, $ts=ts], + [$name="OpenSSH", $version=[$major=4,$minor=4], $unparsed_version=""], ["OpenSSH_5.2"] = - [$name="OpenSSH", $version=[$major=5,$minor=2], $host=host, $ts=ts], + [$name="OpenSSH", $version=[$major=5,$minor=2], $unparsed_version=""], ["Apache/2.0.63 (Unix) mod_auth_kerb/5.3 mod_ssl/2.0.63 OpenSSL/0.9.7a mod_fastcgi/2.4.2"] = - [$name="Apache", $version=[$major=2,$minor=0,$minor2=63,$addl="Unix"], $host=host, $ts=ts], + [$name="Apache", $version=[$major=2,$minor=0,$minor2=63,$addl="Unix"], $unparsed_version=""], ["Apache/1.3.19 (Unix)"] = - [$name="Apache", $version=[$major=1,$minor=3,$minor2=19,$addl="Unix"], $host=host, $ts=ts], + [$name="Apache", $version=[$major=1,$minor=3,$minor2=19,$addl="Unix"], $unparsed_version=""], ["ProFTPD 1.2.5rc1 Server (Debian)"] = - [$name="ProFTPD", $version=[$major=1,$minor=2,$minor2=5,$addl="rc1"], $host=host, $ts=ts], + [$name="ProFTPD", $version=[$major=1,$minor=2,$minor2=5,$addl="rc1"], $unparsed_version=""], ["wu-2.4.2-academ[BETA-18-VR14](1)"] = - [$name="wu", $version=[$major=2,$minor=4,$minor2=2,$addl="academ"], $host=host, $ts=ts], + [$name="wu", $version=[$major=2,$minor=4,$minor2=2,$addl="academ"], $unparsed_version=""], ["wu-2.6.2(1)"] = - [$name="wu", $version=[$major=2,$minor=6,$minor2=2,$addl="1"], $host=host, $ts=ts], + [$name="wu", $version=[$major=2,$minor=6,$minor2=2,$addl="1"], $unparsed_version=""], ["Java1.2.2-JDeveloper"] = - [$name="Java", $version=[$major=1,$minor=2,$minor2=2,$addl="JDeveloper"], $host=host, $ts=ts], + [$name="Java", $version=[$major=1,$minor=2,$minor2=2,$addl="JDeveloper"], $unparsed_version=""], ["Java/1.6.0_13"] = - [$name="Java", $version=[$major=1,$minor=6,$minor2=0,$addl="13"], $host=host, $ts=ts], + [$name="Java", $version=[$major=1,$minor=6,$minor2=0,$addl="13"], $unparsed_version=""], ["Python-urllib/3.1"] = - [$name="Python-urllib", $version=[$major=3,$minor=1], $host=host, $ts=ts], + [$name="Python-urllib", $version=[$major=3,$minor=1], $unparsed_version=""], ["libwww-perl/5.820"] = - [$name="libwww-perl", $version=[$major=5,$minor=820], $host=host, $ts=ts], + [$name="libwww-perl", $version=[$major=5,$minor=820], $unparsed_version=""], ["Wget/1.9+cvs-stable (Red Hat modified)"] = - [$name="Wget", $version=[$major=1,$minor=9,$addl="+cvs"], $host=host, $ts=ts], + [$name="Wget", $version=[$major=1,$minor=9,$addl="+cvs"], $unparsed_version=""], ["Wget/1.11.4 (Red Hat modified)"] = - [$name="Wget", $version=[$major=1,$minor=11,$minor2=4,$addl="Red Hat modified"], $host=host, $ts=ts], + [$name="Wget", $version=[$major=1,$minor=11,$minor2=4,$addl="Red Hat modified"], $unparsed_version=""], ["curl/7.15.1 (i486-pc-linux-gnu) libcurl/7.15.1 OpenSSL/0.9.8a zlib/1.2.3 libidn/0.5.18"] = - [$name="curl", $version=[$major=7,$minor=15,$minor2=1,$addl="i486-pc-linux-gnu"], $host=host, $ts=ts], + [$name="curl", $version=[$major=7,$minor=15,$minor2=1,$addl="i486-pc-linux-gnu"], $unparsed_version=""], ["Apache"] = - [$name="Apache", $host=host, $ts=ts], + [$name="Apache", $unparsed_version=""], ["Zope/(Zope 2.7.8-final, python 2.3.5, darwin) ZServer/1.1 Plone/Unknown"] = - [$name="Zope/(Zope", $version=[$major=2,$minor=7,$minor2=8,$addl="final"], $host=host, $ts=ts], + [$name="Zope/(Zope", $version=[$major=2,$minor=7,$minor2=8,$addl="final"], $unparsed_version=""], ["The Bat! (v2.00.9) Personal"] = - [$name="The Bat!", $version=[$major=2,$minor=0,$minor2=9,$addl="Personal"], $host=host, $ts=ts], + [$name="The Bat!", $version=[$major=2,$minor=0,$minor2=9,$addl="Personal"], $unparsed_version=""], ["Flash/10,2,153,1"] = - [$name="Flash", $version=[$major=10,$minor=2,$minor2=153,$addl="1"], $host=host, $ts=ts], + [$name="Flash", $version=[$major=10,$minor=2,$minor2=153,$addl="1"], $unparsed_version=""], ["mt2/1.2.3.967 Oct 13 2010-13:40:24 ord-pixel-x2 pid 0x35a3 13731"] = - [$name="mt2", $version=[$major=1,$minor=2,$minor2=3,$addl="967"], $host=host, $ts=ts], + [$name="mt2", $version=[$major=1,$minor=2,$minor2=3,$addl="967"], $unparsed_version=""], ["CacheFlyServe v26b"] = - [$name="CacheFlyServe", $version=[$major=26,$addl="b"], $host=host, $ts=ts], + [$name="CacheFlyServe", $version=[$major=26,$addl="b"], $unparsed_version=""], ["Apache/2.0.46 (Win32) mod_ssl/2.0.46 OpenSSL/0.9.7b mod_jk2/2.0.4"] = - [$name="Apache", $version=[$major=2,$minor=0,$minor2=46,$addl="Win32"], $host=host, $ts=ts], + [$name="Apache", $version=[$major=2,$minor=0,$minor2=46,$addl="Win32"], $unparsed_version=""], # I have no clue how I'd support this without a special case. #["Apache mod_fcgid/2.3.6 mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635"] = - # [$name="Apache", $version=[], $host=host, $ts=ts], + # [$name="Apache", $version=[], $unparsed_version=""], ["Apple iPhone v4.3.1 Weather v1.0.0.8G4"] = - [$name="Apple iPhone", $version=[$major=4,$minor=3,$minor2=1,$addl="Weather"], $host=host, $ts=ts], + [$name="Apple iPhone", $version=[$major=4,$minor=3,$minor2=1,$addl="Weather"], $unparsed_version=""], ["Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5"] = - [$name="Safari", $version=[$major=5,$minor=0,$minor2=2,$addl="Mobile"], $host=host, $ts=ts], + [$name="Safari", $version=[$major=5,$minor=0,$minor2=2,$addl="Mobile"], $unparsed_version=""], ["Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_7; en-US) AppleWebKit/534.16 (KHTML, like Gecko) Chrome/10.0.648.205 Safari/534.16"] = - [$name="Chrome", $version=[$major=10,$minor=0,$minor2=648,$addl="205"], $host=host, $ts=ts], + [$name="Chrome", $version=[$major=10,$minor=0,$minor2=648,$addl="205"], $unparsed_version=""], ["Opera/9.80 (Windows NT 6.1; U; sv) Presto/2.7.62 Version/11.01"] = - [$name="Opera", $version=[$major=11,$minor=1], $host=host, $ts=ts], + [$name="Opera", $version=[$major=11,$minor=1], $unparsed_version=""], ["Mozilla/5.0 (Windows; U; Windows NT 5.1; de; rv:1.9.2.11) Gecko/20101013 Lightning/1.0b2 Thunderbird/3.1.5"] = - [$name="Thunderbird", $version=[$major=3,$minor=1,$minor2=5], $host=host, $ts=ts], + [$name="Thunderbird", $version=[$major=3,$minor=1,$minor2=5], $unparsed_version=""], ["iTunes/9.0 (Macintosh; Intel Mac OS X 10.5.8) AppleWebKit/531.9"] = - [$name="iTunes", $version=[$major=9,$minor=0,$addl="Macintosh"], $host=host, $ts=ts], + [$name="iTunes", $version=[$major=9,$minor=0,$addl="Macintosh"], $unparsed_version=""], ["Java1.3.1_04"] = - [$name="Java", $version=[$major=1,$minor=3,$minor2=1,$addl="04"], $host=host, $ts=ts], + [$name="Java", $version=[$major=1,$minor=3,$minor2=1,$addl="04"], $unparsed_version=""], ["Mozilla/5.0 (Linux; U; Android 2.3.3; zh-tw; HTC Pyramid Build/GRI40) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"] = - [$name="Safari", $version=[$major=4,$minor=0,$addl="Mobile"], $host=host, $ts=ts], + [$name="Safari", $version=[$major=4,$minor=0,$addl="Mobile"], $unparsed_version=""], + ["Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_6; en-us) AppleWebKit/533.20.25 (KHTML, like Gecko) Version/5.0.4 Safari/533.20.27"] = + [$name="Safari", $version=[$major=5,$minor=0,$minor2=4], $unparsed_version=""], + ["Mozilla/5.0 (iPod; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7"] = + [$name="Safari", $version=[$major=4,$minor=0,$minor2=5,$addl="Mobile"], $unparsed_version=""], ["Opera/9.80 (J2ME/MIDP; Opera Mini/9.80 (S60; SymbOS; Opera Mobi/23.348; U; en) Presto/2.5.25 Version/10.54"] = - [$name="Opera Mini", $version=[$major=10,$minor=54], $host=host, $ts=ts], + [$name="Opera Mini", $version=[$major=10,$minor=54], $unparsed_version=""], ["Opera/9.80 (J2ME/MIDP; Opera Mini/5.0.18741/18.794; U; en) Presto/2.4.15"] = - [$name="Opera Mini", $version=[$major=5,$minor=0,$minor2=18741], $host=host, $ts=ts], + [$name="Opera Mini", $version=[$major=5,$minor=0,$minor2=18741], $unparsed_version=""], ["Opera/9.80 (Windows NT 5.1; Opera Mobi/49; U; en) Presto/2.4.18 Version/10.00"] = - [$name="Opera Mobi", $version=[$major=10,$minor=0], $host=host, $ts=ts], + [$name="Opera Mobi", $version=[$major=10,$minor=0], $unparsed_version=""], ["Mozilla/4.0 (compatible; MSIE 8.0; Android 2.2.2; Linux; Opera Mobi/ADR-1103311355; en) Opera 11.00"] = - [$name="Opera", $version=[$major=11,$minor=0], $host=host, $ts=ts], - ["Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; GTB5; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; InfoPath.2)"] = - [$name="MSIE", $version=[$major=7,$minor=0], $host=host, $ts=ts], - ["Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1; Media Center PC 3.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)"] = - [$name="MSIE", $version=[$major=7,$minor=0,$addl="b"], $host=host, $ts=ts], + [$name="Opera", $version=[$major=11,$minor=0], $unparsed_version=""], ["Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.2) Gecko/20040804 Netscape/7.2 (ax)"] = - [$name="Netscape", $version=[$major=7,$minor=2], $host=host, $ts=ts], + [$name="Netscape", $version=[$major=7,$minor=2], $unparsed_version=""], + ["Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; GTB5; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506; InfoPath.2)"] = + [$name="MSIE", $version=[$major=7,$minor=0], $unparsed_version=""], + ["Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.1; Media Center PC 3.0; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.1)"] = + [$name="MSIE", $version=[$major=7,$minor=0,$addl="b"], $unparsed_version=""], + ["Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; Tablet PC 2.0; InfoPath.2; InfoPath.3)"] = + [$name="MSIE", $version=[$major=8,$minor=0], $unparsed_version=""], + ["Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"] = + [$name="MSIE", $version=[$major=9,$minor=0], $unparsed_version=""], + ["Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; InfoPath.3; Creative AutoUpdate v1.40.02)"] = + [$name="MSIE", $version=[$major=9,$minor=0], $unparsed_version=""], + ["Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)"] = + [$name="MSIE", $version=[$major=10,$minor=0], $unparsed_version=""], ["The Bat! (3.0.1 RC3) Professional"] = - [$name="The Bat!", $version=[$major=3,$minor=0,$minor2=1,$addl="RC3"], $host=host, $ts=ts], + [$name="The Bat!", $version=[$major=3,$minor=0,$minor2=1,$addl="RC3"], $unparsed_version=""], # This is an FTP client (found with CLNT command) ["Total Commander"] = - [$name="Total Commander", $version=[], $host=host, $ts=ts], + [$name="Total Commander", $version=[], $unparsed_version=""], ["(vsFTPd 2.0.5)"] = - [$name="vsFTPd", $version=[$major=2,$minor=0,$minor2=5], $host=host, $ts=ts], + [$name="vsFTPd", $version=[$major=2,$minor=0,$minor2=5], $unparsed_version=""], ["Apple Mail (2.1084)"] = - [$name="Apple Mail", $version=[$major=2,$minor=1084], $host=host, $ts=ts], + [$name="Apple Mail", $version=[$major=2,$minor=1084], $unparsed_version=""], }; event bro_init() { for ( sw in matched_software ) { - local output = Software::parse(sw, host, Software::UNKNOWN); - local baseline: Software::Info; - baseline = matched_software[sw]; + local output = Software::parse(sw); + local baseline = matched_software[sw]; + if ( baseline$name == output$name && + sw == output$unparsed_version && Software::cmp_versions(baseline$version,output$version) == 0 ) print fmt("success on: %s", sw); else diff --git a/testing/btest/scripts/base/protocols/ftp/ftp-ipv4.bro b/testing/btest/scripts/base/protocols/ftp/ftp-ipv4.bro new file mode 100644 index 0000000000..5cb8b808d5 --- /dev/null +++ b/testing/btest/scripts/base/protocols/ftp/ftp-ipv4.bro @@ -0,0 +1,6 @@ +# This tests both active and passive FTP over IPv4. +# +# @TEST-EXEC: bro -r $TRACES/ftp-ipv4.trace +# @TEST-EXEC: btest-diff conn.log +# @TEST-EXEC: btest-diff ftp.log + diff --git a/testing/btest/scripts/base/protocols/ftp/ftp-ipv6.bro b/testing/btest/scripts/base/protocols/ftp/ftp-ipv6.bro new file mode 100644 index 0000000000..7ce31808c9 --- /dev/null +++ b/testing/btest/scripts/base/protocols/ftp/ftp-ipv6.bro @@ -0,0 +1,6 @@ +# This tests both active and passive FTP over IPv6. +# +# @TEST-EXEC: bro -r $TRACES/ipv6-ftp.trace +# @TEST-EXEC: btest-diff conn.log +# @TEST-EXEC: btest-diff ftp.log + diff --git a/testing/btest/scripts/base/protocols/http/100-continue.bro b/testing/btest/scripts/base/protocols/http/100-continue.bro new file mode 100644 index 0000000000..d1d34c1abe --- /dev/null +++ b/testing/btest/scripts/base/protocols/http/100-continue.bro @@ -0,0 +1,12 @@ +# This tests that the HTTP analyzer does not generate an unmatched_HTTP_reply +# weird as a result of seeing both a 1xx response and the real response to +# a given request. The http scripts should also be able log such replies +# in a way that correlates the final response with the request. +# +# @TEST-EXEC: bro -r $TRACES/http-100-continue.trace %INPUT +# @TEST-EXEC: test ! -f weird.log +# @TEST-EXEC: btest-diff http.log + +# The base analysis scripts are loaded by default. +#@load base/protocols/http + diff --git a/testing/btest/scripts/base/protocols/http/http-extract-files.bro b/testing/btest/scripts/base/protocols/http/http-extract-files.bro new file mode 100644 index 0000000000..4338cddb47 --- /dev/null +++ b/testing/btest/scripts/base/protocols/http/http-extract-files.bro @@ -0,0 +1,5 @@ +# @TEST-EXEC: bro -C -r $TRACES/web.trace %INPUT +# @TEST-EXEC: btest-diff http.log +# @TEST-EXEC: btest-diff http-item_141.42.64.125:56730-125.190.109.199:80_resp_1.dat + +redef HTTP::extract_file_types += /text\/html/; \ No newline at end of file diff --git a/testing/btest/policy/protocols/http/http-header-crlf.bro b/testing/btest/scripts/base/protocols/http/http-header-crlf.bro similarity index 54% rename from testing/btest/policy/protocols/http/http-header-crlf.bro rename to testing/btest/scripts/base/protocols/http/http-header-crlf.bro index 4e55141a7d..06081d94e5 100644 --- a/testing/btest/policy/protocols/http/http-header-crlf.bro +++ b/testing/btest/scripts/base/protocols/http/http-header-crlf.bro @@ -1,9 +1,9 @@ # This tests for what looks like a problem in the HTTP parser: -# it gets confused whether it's in a header or not; it should -# not report that weird. +# it gets confused whether it's in a header or not; it shouldn't report +# the http_no_crlf_in_header_list wierd. # # @TEST-EXEC: bro -r $TRACES/http-byteranges.trace %INPUT -# @TEST-EXEC: grep -q http_no_crlf_in_header_list weird.log && exit 1 || exit 0 +# @TEST-EXEC: test ! -f weird.log # The base analysis scripts are loaded by default. #@load base/protocols/http diff --git a/testing/btest/policy/protocols/http/http-mime-and-md5.bro b/testing/btest/scripts/base/protocols/http/http-mime-and-md5.bro similarity index 76% rename from testing/btest/policy/protocols/http/http-mime-and-md5.bro rename to testing/btest/scripts/base/protocols/http/http-mime-and-md5.bro index 4e202c75ed..dd01e62413 100644 --- a/testing/btest/policy/protocols/http/http-mime-and-md5.bro +++ b/testing/btest/scripts/base/protocols/http/http-mime-and-md5.bro @@ -2,7 +2,6 @@ # will normalize mime types other than the target type to prevent sensitivity # to varying versions of libmagic. -# @TEST-REQUIRES: grep -q '#define HAVE_LIBMAGIC' $BUILD/config.h # @TEST-EXEC: bro -r $TRACES/http-pipelined-requests.trace %INPUT > output # @TEST-EXEC: btest-diff http.log @@ -10,8 +9,8 @@ redef HTTP::generate_md5 += /image\/png/; event bro_init() { - Log::remove_default_filter(HTTP::HTTP); - Log::add_filter(HTTP::HTTP, [$name="normalized-mime-types", + Log::remove_default_filter(HTTP::LOG); + Log::add_filter(HTTP::LOG, [$name="normalized-mime-types", $pred=function(rec: HTTP::Info): bool { if ( rec?$mime_type && HTTP::generate_md5 != rec$mime_type ) diff --git a/testing/btest/policy/protocols/http/http-pipelining.bro b/testing/btest/scripts/base/protocols/http/http-pipelining.bro similarity index 60% rename from testing/btest/policy/protocols/http/http-pipelining.bro rename to testing/btest/scripts/base/protocols/http/http-pipelining.bro index 52ef81fbbf..9875683269 100644 --- a/testing/btest/policy/protocols/http/http-pipelining.bro +++ b/testing/btest/scripts/base/protocols/http/http-pipelining.bro @@ -4,6 +4,6 @@ # mime type is irrelevant to this test, so filter it out event bro_init() { - Log::remove_default_filter(HTTP::HTTP); - Log::add_filter(HTTP::HTTP, [$name="less-mime-types", $exclude=set("mime_type")]); + Log::remove_default_filter(HTTP::LOG); + Log::add_filter(HTTP::LOG, [$name="less-mime-types", $exclude=set("mime_type")]); } diff --git a/testing/btest/policy/protocols/irc/basic.test b/testing/btest/scripts/base/protocols/irc/basic.test similarity index 73% rename from testing/btest/policy/protocols/irc/basic.test rename to testing/btest/scripts/base/protocols/irc/basic.test index a462e828de..32358d12a4 100644 --- a/testing/btest/policy/protocols/irc/basic.test +++ b/testing/btest/scripts/base/protocols/irc/basic.test @@ -7,6 +7,6 @@ # dcc mime types are irrelevant to this test, so filter it out event bro_init() { - Log::remove_default_filter(IRC::IRC); - Log::add_filter(IRC::IRC, [$name="remove-mime", $exclude=set("dcc_mime_type")]); + Log::remove_default_filter(IRC::LOG); + Log::add_filter(IRC::LOG, [$name="remove-mime", $exclude=set("dcc_mime_type")]); } diff --git a/testing/btest/policy/protocols/irc/dcc-extract.test b/testing/btest/scripts/base/protocols/irc/dcc-extract.test similarity index 82% rename from testing/btest/policy/protocols/irc/dcc-extract.test rename to testing/btest/scripts/base/protocols/irc/dcc-extract.test index b6be26ddd4..b6bf43ac50 100644 --- a/testing/btest/policy/protocols/irc/dcc-extract.test +++ b/testing/btest/scripts/base/protocols/irc/dcc-extract.test @@ -2,7 +2,6 @@ # correctly extracted. The mime type of the file transferred is normalized # to prevent sensitivity to libmagic version being used. -# @TEST-REQUIRES: grep -q '#define HAVE_LIBMAGIC' $BUILD/config.h # @TEST-EXEC: bro -r $TRACES/irc-dcc-send.trace %INPUT # @TEST-EXEC: btest-diff irc.log # @TEST-EXEC: btest-diff irc-dcc-item_192.168.1.77:57655-209.197.168.151:1024_1.dat @@ -13,8 +12,8 @@ redef IRC::extract_file_types=/.*/; event bro_init() { - Log::remove_default_filter(IRC::IRC); - Log::add_filter(IRC::IRC, [$name="normalized-mime-types", + Log::remove_default_filter(IRC::LOG); + Log::add_filter(IRC::LOG, [$name="normalized-mime-types", $pred=function(rec: IRC::Info): bool { if ( rec?$dcc_mime_type ) diff --git a/testing/btest/policy/protocols/smtp/basic.test b/testing/btest/scripts/base/protocols/smtp/basic.test similarity index 100% rename from testing/btest/policy/protocols/smtp/basic.test rename to testing/btest/scripts/base/protocols/smtp/basic.test diff --git a/testing/btest/policy/protocols/smtp/mime-extract.test b/testing/btest/scripts/base/protocols/smtp/mime-extract.test similarity index 78% rename from testing/btest/policy/protocols/smtp/mime-extract.test rename to testing/btest/scripts/base/protocols/smtp/mime-extract.test index 09e6d3b242..8dc8bc9e31 100644 --- a/testing/btest/policy/protocols/smtp/mime-extract.test +++ b/testing/btest/scripts/base/protocols/smtp/mime-extract.test @@ -1,4 +1,3 @@ -# @TEST-REQUIRES: grep -q '#define HAVE_LIBMAGIC' $BUILD/config.h # @TEST-EXEC: bro -r $TRACES/smtp.trace %INPUT # @TEST-EXEC: btest-diff smtp_entities.log # @TEST-EXEC: btest-diff smtp-entity_10.10.1.4:1470-74.53.140.153:25_1.dat @@ -13,8 +12,8 @@ redef SMTP::extract_file_types=/text\/plain/; event bro_init() { - Log::remove_default_filter(SMTP::SMTP_ENTITIES); - Log::add_filter(SMTP::SMTP_ENTITIES, [$name="normalized-mime-types", + Log::remove_default_filter(SMTP::ENTITIES_LOG); + Log::add_filter(SMTP::ENTITIES_LOG, [$name="normalized-mime-types", $pred=function(rec: SMTP::EntityInfo): bool { if ( rec?$mime_type ) diff --git a/testing/btest/policy/protocols/smtp/mime.test b/testing/btest/scripts/base/protocols/smtp/mime.test similarity index 70% rename from testing/btest/policy/protocols/smtp/mime.test rename to testing/btest/scripts/base/protocols/smtp/mime.test index 37bbc6b14d..2b80e148ff 100644 --- a/testing/btest/policy/protocols/smtp/mime.test +++ b/testing/btest/scripts/base/protocols/smtp/mime.test @@ -1,7 +1,6 @@ # Checks logging of mime types and md5 calculation. Mime type in the log # is normalized to prevent sensitivity to libmagic version. -# @TEST-REQUIRES: grep -q '#define HAVE_LIBMAGIC' $BUILD/config.h # @TEST-EXEC: bro -r $TRACES/smtp.trace %INPUT # @TEST-EXEC: btest-diff smtp_entities.log @@ -11,8 +10,8 @@ redef SMTP::generate_md5=/text\/plain/; event bro_init() { - Log::remove_default_filter(SMTP::SMTP_ENTITIES); - Log::add_filter(SMTP::SMTP_ENTITIES, [$name="normalized-mime-types", + Log::remove_default_filter(SMTP::ENTITIES_LOG); + Log::add_filter(SMTP::ENTITIES_LOG, [$name="normalized-mime-types", $pred=function(rec: SMTP::EntityInfo): bool { if ( rec?$mime_type ) diff --git a/testing/btest/policy/utils/addrs.test b/testing/btest/scripts/base/utils/addrs.test similarity index 100% rename from testing/btest/policy/utils/addrs.test rename to testing/btest/scripts/base/utils/addrs.test diff --git a/testing/btest/policy/utils/conn-ids.test b/testing/btest/scripts/base/utils/conn-ids.test similarity index 100% rename from testing/btest/policy/utils/conn-ids.test rename to testing/btest/scripts/base/utils/conn-ids.test diff --git a/testing/btest/policy/utils/directions-and-hosts.test b/testing/btest/scripts/base/utils/directions-and-hosts.test similarity index 100% rename from testing/btest/policy/utils/directions-and-hosts.test rename to testing/btest/scripts/base/utils/directions-and-hosts.test diff --git a/testing/btest/policy/utils/files.test b/testing/btest/scripts/base/utils/files.test similarity index 100% rename from testing/btest/policy/utils/files.test rename to testing/btest/scripts/base/utils/files.test diff --git a/testing/btest/policy/utils/numbers.test b/testing/btest/scripts/base/utils/numbers.test similarity index 100% rename from testing/btest/policy/utils/numbers.test rename to testing/btest/scripts/base/utils/numbers.test diff --git a/testing/btest/policy/utils/paths.test b/testing/btest/scripts/base/utils/paths.test similarity index 100% rename from testing/btest/policy/utils/paths.test rename to testing/btest/scripts/base/utils/paths.test diff --git a/testing/btest/policy/utils/pattern.test b/testing/btest/scripts/base/utils/pattern.test similarity index 100% rename from testing/btest/policy/utils/pattern.test rename to testing/btest/scripts/base/utils/pattern.test diff --git a/testing/btest/policy/utils/site.test b/testing/btest/scripts/base/utils/site.test similarity index 100% rename from testing/btest/policy/utils/site.test rename to testing/btest/scripts/base/utils/site.test diff --git a/testing/btest/policy/utils/strings.test b/testing/btest/scripts/base/utils/strings.test similarity index 100% rename from testing/btest/policy/utils/strings.test rename to testing/btest/scripts/base/utils/strings.test diff --git a/testing/btest/policy/utils/thresholds.test b/testing/btest/scripts/base/utils/thresholds.test similarity index 100% rename from testing/btest/policy/utils/thresholds.test rename to testing/btest/scripts/base/utils/thresholds.test diff --git a/testing/btest/policy/misc/check-test-all-policy.bro b/testing/btest/scripts/check-test-all-policy.bro similarity index 100% rename from testing/btest/policy/misc/check-test-all-policy.bro rename to testing/btest/scripts/check-test-all-policy.bro diff --git a/testing/btest/policy/protocols/conn/known-hosts.bro b/testing/btest/scripts/policy/protocols/conn/known-hosts.bro similarity index 58% rename from testing/btest/policy/protocols/conn/known-hosts.bro rename to testing/btest/scripts/policy/protocols/conn/known-hosts.bro index 83c536925a..677cfa9f3d 100644 --- a/testing/btest/policy/protocols/conn/known-hosts.bro +++ b/testing/btest/scripts/policy/protocols/conn/known-hosts.bro @@ -1,18 +1,18 @@ # A basic test of the known-hosts script's logging and asset_tracking options -# @TEST-EXEC: bro -r $TRACES/wikipedia.trace %INPUT KnownHosts::asset_tracking=LOCAL_HOSTS +# @TEST-EXEC: bro -r $TRACES/wikipedia.trace %INPUT Known::host_tracking=LOCAL_HOSTS # @TEST-EXEC: mv known_hosts.log knownhosts-local.log # @TEST-EXEC: btest-diff knownhosts-local.log -# @TEST-EXEC: bro -r $TRACES/wikipedia.trace %INPUT KnownHosts::asset_tracking=REMOTE_HOSTS +# @TEST-EXEC: bro -r $TRACES/wikipedia.trace %INPUT Known::host_tracking=REMOTE_HOSTS # @TEST-EXEC: mv known_hosts.log knownhosts-remote.log # @TEST-EXEC: btest-diff knownhosts-remote.log -# @TEST-EXEC: bro -r $TRACES/wikipedia.trace %INPUT KnownHosts::asset_tracking=ALL_HOSTS +# @TEST-EXEC: bro -r $TRACES/wikipedia.trace %INPUT Known::host_tracking=ALL_HOSTS # @TEST-EXEC: mv known_hosts.log knownhosts-all.log # @TEST-EXEC: btest-diff knownhosts-all.log -# @TEST-EXEC: bro -r $TRACES/wikipedia.trace %INPUT KnownHosts::asset_tracking=NO_HOSTS +# @TEST-EXEC: bro -r $TRACES/wikipedia.trace %INPUT Known::host_tracking=NO_HOSTS # @TEST-EXEC: test '!' -e known_hosts.log @load protocols/conn/known-hosts diff --git a/testing/btest/policy/protocols/conn/known-services.bro b/testing/btest/scripts/policy/protocols/conn/known-services.bro similarity index 82% rename from testing/btest/policy/protocols/conn/known-services.bro rename to testing/btest/scripts/policy/protocols/conn/known-services.bro index 7adc7cb037..ab787b6bd4 100644 --- a/testing/btest/policy/protocols/conn/known-services.bro +++ b/testing/btest/scripts/policy/protocols/conn/known-services.bro @@ -1,18 +1,18 @@ # A basic test of the known-services script's logging and asset_tracking options -# @TEST-EXEC: bro -r $TRACES/var-services-std-ports.trace %INPUT KnownServices::asset_tracking=LOCAL_HOSTS +# @TEST-EXEC: bro -r $TRACES/var-services-std-ports.trace %INPUT Known::service_tracking=LOCAL_HOSTS # @TEST-EXEC: mv known_services.log knownservices-local.log # @TEST-EXEC: btest-diff knownservices-local.log -# @TEST-EXEC: bro -r $TRACES/var-services-std-ports.trace %INPUT KnownServices::asset_tracking=REMOTE_HOSTS +# @TEST-EXEC: bro -r $TRACES/var-services-std-ports.trace %INPUT Known::service_tracking=REMOTE_HOSTS # @TEST-EXEC: mv known_services.log knownservices-remote.log # @TEST-EXEC: btest-diff knownservices-remote.log -# @TEST-EXEC: bro -r $TRACES/var-services-std-ports.trace %INPUT KnownServices::asset_tracking=ALL_HOSTS +# @TEST-EXEC: bro -r $TRACES/var-services-std-ports.trace %INPUT Known::service_tracking=ALL_HOSTS # @TEST-EXEC: mv known_services.log knownservices-all.log # @TEST-EXEC: btest-diff knownservices-all.log -# @TEST-EXEC: bro -r $TRACES/var-services-std-ports.trace %INPUT KnownServices::asset_tracking=NO_HOSTS +# @TEST-EXEC: bro -r $TRACES/var-services-std-ports.trace %INPUT Known::service_tracking=NO_HOSTS # @TEST-EXEC: test '!' -e known_services.log @load protocols/conn/known-services diff --git a/testing/btest/policy/protocols/dns/event-priority.bro b/testing/btest/scripts/policy/protocols/dns/event-priority.bro similarity index 100% rename from testing/btest/policy/protocols/dns/event-priority.bro rename to testing/btest/scripts/policy/protocols/dns/event-priority.bro diff --git a/testing/btest/policy/protocols/http/test-sql-injection-regex.bro b/testing/btest/scripts/policy/protocols/http/test-sql-injection-regex.bro similarity index 92% rename from testing/btest/policy/protocols/http/test-sql-injection-regex.bro rename to testing/btest/scripts/policy/protocols/http/test-sql-injection-regex.bro index bf8be22210..2e82eb9dfb 100644 --- a/testing/btest/policy/protocols/http/test-sql-injection-regex.bro +++ b/testing/btest/scripts/policy/protocols/http/test-sql-injection-regex.bro @@ -42,6 +42,8 @@ event bro_init () #add positive_matches["/index.asp?ARF_ID=(1/(1-(asc(mid(now(),18,1))\(2^7) mod 2)))"]; #add positive_matches["/index.php' and 1=convert(int,(select top 1 table_name from information_schema.tables))--sp_password"]; #add positive_matches["/index.php?id=873 and user=0--"]; + #add positive_matches["?id=1;+if+(1=1)+waitfor+delay+'00:00:01'--9"]; + #add positive_matches["?id=1+and+if(1=1,BENCHMARK(728000,MD5(0x41)),0)9"]; # The positive_matches below are from the mod_security evasion challenge. # All supported attacks are uncommented. @@ -95,14 +97,6 @@ event bro_init () #add negative_matches["/index/hmm.gif?utmdt=Record > Create a Graph"]; #add negative_matches["/index.php?test='||\x0aTO_CHAR(foo_bar.Foo_Bar_ID)||"]; - local regex = - /[\?&][^[:blank:]\x00-\x37\|]+?=[\-[:alnum:]%]+([[:blank:]\x00-\x37]|\/\*.*?\*\/)*['"]?([[:blank:]\x00-\x37]|\/\*.*?\*\/|\)?;)+.*?([hH][aA][vV][iI][nN][gG]|[uU][nN][iI][oO][nN]|[eE][xX][eE][cC]|[sS][eE][lL][eE][cC][tT]|[dD][eE][lL][eE][tT][eE]|[dD][rR][oO][pP]|[dD][eE][cC][lL][aA][rR][eE]|[cC][rR][eE][aA][tT][eE]|[iI][nN][sS][eE][rR][tT])([[:blank:]\x00-\x37]|\/\*.*?\*\/)+/ - | /[\?&][^[:blank:]\x00-\x37\|]+?=[\-0-9%]+([[:blank:]\x00-\x37]|\/\*.*?\*\/)*['"]?([[:blank:]\x00-\x37]|\/\*.*?\*\/|\)?;)+([xX]?[oO][rR]|[nN]?[aA][nN][dD])([[:blank:]\x00-\x37]|\/\*.*?\*\/)+['"]?(([^a-zA-Z&]+)?=|[eE][xX][iI][sS][tT][sS])/ - | /[\?&][^[:blank:]\x00-\x37]+?=[\-0-9%]*([[:blank:]\x00-\x37]|\/\*.*?\*\/)*['"]([[:blank:]\x00-\x37]|\/\*.*?\*\/)*(-|=|\+|\|\|)([[:blank:]\x00-\x37]|\/\*.*?\*\/)*([0-9]|\(?[cC][oO][nN][vV][eE][rR][tT]|[cC][aA][sS][tT])/ - | /[\?&][^[:blank:]\x00-\x37\|]+?=([[:blank:]\x00-\x37]|\/\*.*?\*\/)*['"]([[:blank:]\x00-\x37]|\/\*.*?\*\/|;)*([xX]?[oO][rR]|[nN]?[aA][nN][dD]|[hH][aA][vV][iI][nN][gG]|[uU][nN][iI][oO][nN]|[eE][xX][eE][cC]|[sS][eE][lL][eE][cC][tT]|[dD][eE][lL][eE][tT][eE]|[dD][rR][oO][pP]|[dD][eE][cC][lL][aA][rR][eE]|[cC][rR][eE][aA][tT][eE]|[rR][eE][gG][eE][xX][pP]|[iI][nN][sS][eE][rR][tT])([[:blank:]\x00-\x37]|\/\*.*?\*\/|[\[(])+[a-zA-Z&]{2,}/ - | /[\?&][^[:blank:]\x00-\x37]+?=[^\.]*?([cC][hH][aA][rR]|[aA][sS][cC][iI][iI]|[sS][uU][bB][sS][tT][rR][iI][nN][gG]|[tT][rR][uU][nN][cC][aA][tT][eE]|[vV][eE][rR][sS][iI][oO][nN]|[lL][eE][nN][gG][tT][hH])\(/ - | /\/\*![[:digit:]]{5}.*?\*\//; - print "If anything besides this line prints out, there is a problem."; for ( test in positive_matches ) { diff --git a/testing/btest/policy/site/testing-local.bro b/testing/btest/scripts/site/local.test similarity index 100% rename from testing/btest/policy/site/testing-local.bro rename to testing/btest/scripts/site/local.test diff --git a/testing/external/.gitignore b/testing/external/.gitignore index 2077736b5b..9b7a29b755 100644 --- a/testing/external/.gitignore +++ b/testing/external/.gitignore @@ -1,3 +1,4 @@ *.git diag.log -bro-testing +bro-testing* +.proxy diff --git a/testing/external/Makefile b/testing/external/Makefile index 994d8962c0..b705734003 100644 --- a/testing/external/Makefile +++ b/testing/external/Makefile @@ -24,3 +24,7 @@ push: status: @for repo in $(REPOS); do ( cd $$repo && echo '>>' $$repo && git status -bs && echo ); done +coverage: + @for repo in $(REPOS); do (cd $$repo && echo "Coverage for '$$repo' repo:" && make coverage); done + +.PHONY: all brief init pull push status coverage diff --git a/testing/external/README b/testing/external/README index 2cec89df4a..345c7a81ae 100644 --- a/testing/external/README +++ b/testing/external/README @@ -12,20 +12,28 @@ private traces. Initialization -------------- -Before the test-suite can be run, one needs to download the traces and -the corresponding test and baseline files. They are kept in a separate -git repository and a ``Makefile`` is provided to clone a copy: +Before the test-suite can be run, one needs to download the necessary +files. Test and baselines are kept in git repositories, while any +traces are download directly. A ``Makefile`` is provided to get +everything that's needed initially: .. console: > make init +If you need a proxy to download the traces, enter it into a file +``.proxy`` either in the top-level directory or inside one of the +repositories. + To later update to upstream changes: .. console: > make pull +This updates the tests and the traces as necessary. + + Running Tests ------------- @@ -53,7 +61,7 @@ To update a test's baseline, first run ``btest`` in update mode: .. console: > cd bro-testing - > btest -U tests/test-you-want-to-update + > btest -u tests/test-you-want-to-update Then use ``git`` to commit the changes and push the changes upstream as usual. @@ -63,20 +71,29 @@ Adding a Local Repository One can add local non-public set of tests (potentially using private traces) by creating a git repository of a similar structure as the -public one. A helper script is provided to set up such a repository: +public one. + +If you already have such a private test repository that you want to +include into the test suite, clone it directly into ````. + +If you want to create a new private repository, there's a helper +script to set that up: .. console: > ./scripts/create-new-repo The first argument is the local name of the repository (it will be -cloned into ````); and then second is the path to the git +cloned into ````); and the second is the URL of the git repository. The repository will be initialized with a few standard -directories as well as a skeleton test in ``/tests``. You -can then edit files as needed (and in particular add traces to -``/traces``). +directories as well as a skeleton test in ``/tests``. You can +then edit files as needed. You add trace files by editing +``Traces/traces.cfg``; see the comments in there. For each trace, you +also need to calculate a checksum with ``md5sum`` and put it into +``.md5sum``. The scripts use this to decide if they need to +redownload the trace. Accordingly, if you update a trace, make sure to +also recalculate its checksum. Note that the traces will be downloaded +to ``Traces/`` but must not be added to the git repostiory; there's a +``.gitignore`` installed to prevent that. -If you already have such a private test repository that you want to -include into the test suite, clone it directly into -````. diff --git a/testing/external/scripts/create-new-repo b/testing/external/scripts/create-new-repo index c9cc68d6a6..8d64d73ca3 100755 --- a/testing/external/scripts/create-new-repo +++ b/testing/external/scripts/create-new-repo @@ -27,7 +27,7 @@ git clone $repo $name cd $name -for dir in Traces tests Baseline; do +for dir in tests Baseline; do mkdir $dir touch $dir/.gitignore done @@ -35,6 +35,7 @@ done ln -s ../subdir-btest.cfg ./btest.cfg cp $cwd/`dirname $0`/skel/test.skeleton tests +cp $cwd/`dirname $0`/skel/traces.cfg . cp $cwd/`dirname $0`/skel/Makefile . cp $cwd/`dirname $0`/skel/.gitignore . diff --git a/testing/external/scripts/diff-all b/testing/external/scripts/diff-all new file mode 100755 index 0000000000..e84416c088 --- /dev/null +++ b/testing/external/scripts/diff-all @@ -0,0 +1,45 @@ +#! /usr/bin/env bash +# +# Runs btest-diff on $@ and fails if any fails. If $@ contains globs, we expand +# them relative to *both* the current directory and the test's baseline +# directory so that we spot missing files. Note that you will need to quote +# the globals in the TEST-EXEC line as otherwise they will have been expanded relative +# to the current directory already when this scripts runs. + +diag=$TEST_DIAGNOSTICS + +export TEST_DIAGNOSTICS=$diag.tmp + +if [ "$diag" = "" ]; then + diag=/dev/stdout +else + rm -f $diag +fi + +rc=0; + +files_cwd=`ls $@` +files_baseline=`cd $TEST_BASELINE && ls $@` + +for i in `echo $files_cwd $files_baseline | sort | uniq`; do + if [[ "$i" != "loaded_scripts.log" && "$i" != "prof.log" && "$i" != "debug.log" && "$i" != "stats.log" ]]; then + + if [[ "$i" == "reporter.log" ]]; then + # Do not diff the reporter.log if it only complains about missing + # GeoIP support. + if ! egrep -v "^#|Bro was not configured for GeoIP support" $i; then + continue + fi + fi + + if ! btest-diff $i; then + echo "" >>$diag + echo "#### btest-diff $i" >>$diag + echo "" >>$diag + cat $diag.tmp >>$diag + rc=1 + fi + fi +done + +exit $rc diff --git a/testing/external/scripts/perftools-adapt-paths b/testing/external/scripts/perftools-adapt-paths new file mode 100755 index 0000000000..cfecd39993 --- /dev/null +++ b/testing/external/scripts/perftools-adapt-paths @@ -0,0 +1,10 @@ +#! /usr/bin/env bash +# +# Adapts relative paths in perftools stderr output to work +# directly from the top-level test directory. +# +# Returns an exit code > 0 if there's a leak. + +cat $1 | sed "s#bro *\"\./#../../../build/src/bro \".tmp/$TEST_NAME/#g" | sed 's/ *--gv//g' >$1.tmp && mv $1.tmp $1 + +grep -qv "detected leaks of" $1 diff --git a/testing/external/scripts/skel/.gitignore b/testing/external/scripts/skel/.gitignore index d49f35423e..91bbaf9ec2 100644 --- a/testing/external/scripts/skel/.gitignore +++ b/testing/external/scripts/skel/.gitignore @@ -1 +1,3 @@ +Traces diag.log +.proxy diff --git a/testing/external/scripts/skel/Makefile b/testing/external/scripts/skel/Makefile index c535827937..7926c51532 100644 --- a/testing/external/scripts/skel/Makefile +++ b/testing/external/scripts/skel/Makefile @@ -2,10 +2,13 @@ DIAG=diag.log BTEST=../../../aux/btest/btest -all: +all: update-traces @rm -f $(DIAG) @$(BTEST) -f $(DIAG) -brief: +brief: update-traces @rm -f $(DIAG) @$(BTEST) -b -f $(DIAG) + +update-traces: + ../scripts/update-traces Traces diff --git a/testing/external/scripts/skel/test.skeleton b/testing/external/scripts/skel/test.skeleton index 46a8f7a48d..a76f3d4d09 100644 --- a/testing/external/scripts/skel/test.skeleton +++ b/testing/external/scripts/skel/test.skeleton @@ -1,2 +1,6 @@ -@TEST-EXEC: bro -r $TRACES/test.trace test-all -@TEST-EXEC: for i in *.log; do btest-diff $i; done +# @TEST-EXEC: zcat $TRACES/trace.gz | bro -r - %INPUT +# @TEST-EXEC: $SCRIPTS/diff-all '*.log' + +@load testing-setup +@load test-all-policy + diff --git a/testing/external/scripts/skel/traces.cfg b/testing/external/scripts/skel/traces.cfg new file mode 100644 index 0000000000..705207c151 --- /dev/null +++ b/testing/external/scripts/skel/traces.cfg @@ -0,0 +1,4 @@ +# +# Format: +# +# [[:]] diff --git a/testing/external/scripts/testing-setup.bro b/testing/external/scripts/testing-setup.bro new file mode 100644 index 0000000000..fa5664a877 --- /dev/null +++ b/testing/external/scripts/testing-setup.bro @@ -0,0 +1,6 @@ +# Sets some testing specific options. + +@ifdef ( SMTP::never_calc_md5 ) + # MDD5s can depend on libmagic output. + redef SMTP::never_calc_md5 = T; +@endif diff --git a/testing/external/scripts/update-traces b/testing/external/scripts/update-traces new file mode 100755 index 0000000000..8c27fb055e --- /dev/null +++ b/testing/external/scripts/update-traces @@ -0,0 +1,80 @@ +#! /usr/bin/env bash +# +# Downloads all traces as specified in /traces.cfg to directory $1. +# +# traces.cfg must consist of lines of the form " " + +if [ "$1" == "" ]; then + echo "usage: `basename $0` " + exit 1 +fi + +if [ ! -e $cfg ]; then + echo "No $cfg found." + exit 1 +fi + +cfg=traces.cfg + +for p in .proxy ../.proxy; do + if [ -e $p ]; then + proxy=`cat $p | head -1 | awk '{print $1}'` + echo Using proxy $proxy ... + proxy="ALL_PROXY=$proxy" + break + fi +done + +mkdir -p $1 + +cat $cfg | while read line; do + + if echo $line | grep -q '^[ \t]*$'; then + continue + fi + + if echo $line | grep -q '^[ \t]*#'; then + continue + fi + + url=`echo $line | awk '{print $1}'` + auth=`echo $line | awk '{print $2}'` + + file=$1/`echo $url | sed 's#^.*/##g'` + fp=$file.md5sum + + if [ "$auth" != "" ]; then + auth="-u $auth" + fi + + # Get the fingerprint file. + if ! eval "$proxy curl $auth -fsS --anyauth $url.md5sum -o $fp.tmp"; then + echo "Error: Could not get $url.md5sum, skipping download." + continue + fi + + download=0 + + if [ -e $fp ]; then + if ! cmp -s $fp $fp.tmp; then + download=1 + fi + else + download=1 + fi + + if [ "$download" = "1" ]; then + echo Getting $url ... + echo + eval "$proxy curl $auth -f --anyauth $url -o $file" + echo + mv $fp.tmp $fp + else + echo "`basename $file` already available." + fi + + rm -f $fp.tmp + +done + + diff --git a/testing/external/subdir-btest.cfg b/testing/external/subdir-btest.cfg index 18938ec985..c4e74f99fa 100644 --- a/testing/external/subdir-btest.cfg +++ b/testing/external/subdir-btest.cfg @@ -6,13 +6,15 @@ IgnoreDirs = .svn CVS .tmp IgnoreFiles = *.tmp *.swp #* *.trace .gitignore *.skeleton [environment] -BROPATH=`bash -c %(testbase)s/../../../build/bro-path-dev` +BROPATH=`bash -c %(testbase)s/../../../build/bro-path-dev`:%(testbase)s/../scripts BRO_SEED_FILE=%(testbase)s/../random.seed TZ=UTC LC_ALL=C PATH=%(testbase)s/../../../build/src:%(testbase)s/../../../aux/btest:%(default_path)s -TEST_DIFF_CANONIFIER=%(testbase)s/../../btest/Scripts/diff-canonifier-external +TEST_DIFF_CANONIFIER=%(testbase)s/../../scripts/diff-canonifier-external +TEST_DIFF_BRIEF=1 TRACES=%(testbase)s/Traces SCRIPTS=%(testbase)s/../scripts DIST=%(testbase)s/../../.. BUILD=%(testbase)s/../../../build +BRO_PROFILER_FILE=%(testbase)s/.tmp/script-coverage.XXXXXX diff --git a/testing/scripts/coverage-calc b/testing/scripts/coverage-calc new file mode 100755 index 0000000000..cc5253c75c --- /dev/null +++ b/testing/scripts/coverage-calc @@ -0,0 +1,59 @@ +#! /usr/bin/env python + +# This script aggregates many files containing Bro script coverage information +# into a single file and reports the overall coverage information. Usage: +# +# coverage-calc