Merge branch 'master' into topic/jsiwek/ipv6-output-format

This commit is contained in:
Jon Siwek 2012-05-07 11:19:15 -05:00
commit af4be0bbe6
50 changed files with 737 additions and 667 deletions

56
CHANGES
View file

@ -1,4 +1,60 @@
2.0-323 | 2012-05-04 21:04:34 -0700
* Add SHA1 and SHA256 hashing BIFs. Addresses #542.
* Refactor all internal MD5 stuff to use OpenSSL's. (Jon Siwek)
* Changes to open-file caching limits and uncached file unserialization. (Jon Siwek)
- Unserializing files that were previously kicked out of the open-file
cache would cause them to be fopen'd with the original access
permissions which is usually 'w' and causes truncation. They
are now opened in 'a' mode. (addresses #780)
- Add 'max_files_in_cache' script option to manually set the maximum
amount of opened files to keep cached. Mainly this just helped
to create a simple test case for the above change.
- Remove unused NO_HAVE_SETRLIMIT preprocessor switch.
- On systems that don't enforce a limit on number of files opened for
the process, raise default max size of open-file cache from
32 to 512.
2.0-319 | 2012-05-03 13:24:44 -0700
* SSL bugfixes and cleanup. (Seth Hall)
- SSL related files and classes renamed to remove the "binpac" term.
- A small fix for DPD scripts to make the DPD log more helpful if
there are multiple continued failures.
- Fixed the SSL analyzer to make it stop doing repeated violation
messages for some handshake failures.
- Added a $issuer_subject to the SSL log.
- Created a basic test for SSL.
- Fixed parsing of TLS server extensions. (Seth Hall)
2.0-315 | 2012-05-03 11:44:17 -0700
* Add two more TLS extension values that we see in live traffic.
(Bernhard Amann)
* Fixed IPv6 link local unicast CIDR and added IPv6 loopback to
private address space. (Seth Hall)
* Fixed a problem where cluster workers were still processing
notices in some cases. (Seth Hall)
* Added a configure option to specify the 'etc' directory. Addresses
#801. (Daniel Thayer)
2.0-306 | 2012-04-24 14:37:00 -0700 2.0-306 | 2012-04-24 14:37:00 -0700
* Add further TLS extension values "extended_random" and * Add further TLS extension values "extended_random" and

View file

@ -1 +1 @@
2.0-306 2.0-323

@ -1 +1 @@
Subproject commit 55f368b0ad283b2e7d68ef72922b5d9683e2a880 Subproject commit 157c18427cb9bb52564e65d8224b95f70dc79e66

@ -1 +1 @@
Subproject commit ff35c3c144885902c898bf8b47e351c7b8d55e10 Subproject commit 76e6bd4b182e9ff43456890e08aeaf451f9e4615

@ -1 +1 @@
Subproject commit 045a02749b20b3c5896497959e6fda02d060508f Subproject commit c0bbe9b8676f4655e7a984ac5eb8dfba3cd061b2

View file

@ -105,5 +105,8 @@ event protocol_violation(c: connection, atype: count, aid: count,
reason: string) &priority=-5 reason: string) &priority=-5
{ {
if ( c?$dpd ) if ( c?$dpd )
{
Log::write(DPD::LOG, c$dpd); Log::write(DPD::LOG, c$dpd);
delete c$dpd;
}
} }

View file

@ -23,7 +23,10 @@ redef Cluster::worker2manager_events += /Notice::cluster_notice/;
@if ( Cluster::local_node_type() != Cluster::MANAGER ) @if ( Cluster::local_node_type() != Cluster::MANAGER )
# The notice policy is completely handled by the manager and shouldn't be # The notice policy is completely handled by the manager and shouldn't be
# done by workers or proxies to save time for packet processing. # done by workers or proxies to save time for packet processing.
redef policy = {}; event bro_init() &priority=-11
{
Notice::policy = table();
}
event Notice::begin_suppression(n: Notice::Info) event Notice::begin_suppression(n: Notice::Info)
{ {

View file

@ -2329,6 +2329,11 @@ type bt_tracker_headers: table[string] of string;
## BPF filter the user has set via the -f command line options. Empty if none. ## BPF filter the user has set via the -f command line options. Empty if none.
const cmd_line_bpf_filter = "" &redef; const cmd_line_bpf_filter = "" &redef;
## The maximum number of open files to keep cached at a given time.
## If set to zero, this is automatically determined by inspecting
## the current/maximum limit on open files for the process.
const max_files_in_cache = 0 &redef;
## Deprecated. ## Deprecated.
const log_rotate_interval = 0 sec &redef; const log_rotate_interval = 0 sec &redef;

View file

@ -81,6 +81,8 @@ export {
[35] = "SessionTicket TLS", [35] = "SessionTicket TLS",
[40] = "extended_random", [40] = "extended_random",
[13172] = "next_protocol_negotiation", [13172] = "next_protocol_negotiation",
[13175] = "origin_bound_certificates",
[13180] = "encrypted_client_certificates",
[65281] = "renegotiation_info" [65281] = "renegotiation_info"
} &default=function(i: count):string { return fmt("unknown-%d", i); }; } &default=function(i: count):string { return fmt("unknown-%d", i); };

View file

@ -24,6 +24,8 @@ export {
session_id: string &log &optional; session_id: string &log &optional;
## Subject of the X.509 certificate offered by the server. ## Subject of the X.509 certificate offered by the server.
subject: string &log &optional; subject: string &log &optional;
## Subject of the signer of the X.509 certificate offered by the server.
issuer_subject: string &log &optional;
## NotValidBefore field value from the server certificate. ## NotValidBefore field value from the server certificate.
not_valid_before: time &log &optional; not_valid_before: time &log &optional;
## NotValidAfter field value from the serve certificate. ## NotValidAfter field value from the serve certificate.
@ -146,6 +148,7 @@ event x509_certificate(c: connection, is_orig: bool, cert: X509, chain_idx: coun
# Also save other certificate information about the primary cert. # Also save other certificate information about the primary cert.
c$ssl$subject = cert$subject; c$ssl$subject = cert$subject;
c$ssl$issuer_subject = cert$issuer;
c$ssl$not_valid_before = cert$not_valid_before; c$ssl$not_valid_before = cert$not_valid_before;
c$ssl$not_valid_after = cert$not_valid_after; c$ssl$not_valid_after = cert$not_valid_after;
} }

View file

@ -10,15 +10,19 @@ export {
const private_address_space: set[subnet] = { const private_address_space: set[subnet] = {
10.0.0.0/8, 10.0.0.0/8,
192.168.0.0/16, 192.168.0.0/16,
172.16.0.0/12,
100.64.0.0/10, # RFC6598 Carrier Grade NAT
127.0.0.0/8, 127.0.0.0/8,
172.16.0.0/12 [fe80::]/10,
[::1]/128,
} &redef; } &redef;
## Networks that are considered "local". ## Networks that are considered "local".
const local_nets: set[subnet] &redef; const local_nets: set[subnet] &redef;
## This is used for retrieving the subnet when you multiple ## This is used for retrieving the subnet when using multiple entries in
## :bro:id:`Site::local_nets`. A membership query can be done with an ## :bro:id:`Site::local_nets`. It's populated automatically from there.
## A membership query can be done with an
## :bro:type:`addr` and the table will yield the subnet it was found ## :bro:type:`addr` and the table will yield the subnet it was found
## within. ## within.
global local_nets_table: table[subnet] of subnet = {}; global local_nets_table: table[subnet] of subnet = {};
@ -40,27 +44,33 @@ export {
## Function that returns true if an address corresponds to one of ## Function that returns true if an address corresponds to one of
## the local networks, false if not. ## the local networks, false if not.
## The function inspects :bro:id:`Site::local_nets`.
global is_local_addr: function(a: addr): bool; global is_local_addr: function(a: addr): bool;
## Function that returns true if an address corresponds to one of ## Function that returns true if an address corresponds to one of
## the neighbor networks, false if not. ## the neighbor networks, false if not.
## The function inspects :bro:id:`Site::neighbor_nets`.
global is_neighbor_addr: function(a: addr): bool; global is_neighbor_addr: function(a: addr): bool;
## Function that returns true if an address corresponds to one of ## Function that returns true if an address corresponds to one of
## the private/unrouted networks, false if not. ## the private/unrouted networks, false if not.
## The function inspects :bro:id:`Site::private_address_space`.
global is_private_addr: function(a: addr): bool; global is_private_addr: function(a: addr): bool;
## Function that returns true if a host name is within a local ## Function that returns true if a host name is within a local
## DNS zone. ## DNS zone.
## The function inspects :bro:id:`Site::local_zones`.
global is_local_name: function(name: string): bool; global is_local_name: function(name: string): bool;
## Function that returns true if a host name is within a neighbor ## Function that returns true if a host name is within a neighbor
## DNS zone. ## DNS zone.
## The function inspects :bro:id:`Site::neighbor_zones`.
global is_neighbor_name: function(name: string): bool; global is_neighbor_name: function(name: string): bool;
## Function that returns a common separated list of email addresses ## Function that returns a common separated list of email addresses
## that are considered administrators for the IP address provided as ## that are considered administrators for the IP address provided as
## an argument. ## an argument.
## The function inspects :bro:id:`Site::local_admins`.
global get_emails: function(a: addr): string; global get_emails: function(a: addr): string;
} }

View file

@ -34,7 +34,7 @@
#include "Portmap.h" #include "Portmap.h"
#include "POP3.h" #include "POP3.h"
#include "SSH.h" #include "SSH.h"
#include "SSL-binpac.h" #include "SSL.h"
#include "Syslog-binpac.h" #include "Syslog-binpac.h"
#include "ConnSizeAnalyzer.h" #include "ConnSizeAnalyzer.h"
@ -121,8 +121,8 @@ const Analyzer::Config Analyzer::analyzer_configs[] = {
HTTP_Analyzer_binpac::InstantiateAnalyzer, HTTP_Analyzer_binpac::InstantiateAnalyzer,
HTTP_Analyzer_binpac::Available, 0, false }, HTTP_Analyzer_binpac::Available, 0, false },
{ AnalyzerTag::SSL, "SSL", { AnalyzerTag::SSL, "SSL",
SSL_Analyzer_binpac::InstantiateAnalyzer, SSL_Analyzer::InstantiateAnalyzer,
SSL_Analyzer_binpac::Available, 0, false }, SSL_Analyzer::Available, 0, false },
{ AnalyzerTag::SYSLOG_BINPAC, "SYSLOG_BINPAC", { AnalyzerTag::SYSLOG_BINPAC, "SYSLOG_BINPAC",
Syslog_Analyzer_binpac::InstantiateAnalyzer, Syslog_Analyzer_binpac::InstantiateAnalyzer,
Syslog_Analyzer_binpac::Available, 0, false }, Syslog_Analyzer_binpac::Available, 0, false },

View file

@ -5,7 +5,6 @@
#include "util.h" #include "util.h"
#include "net_util.h" #include "net_util.h"
#include "md5.h"
#include "Anon.h" #include "Anon.h"
#include "Val.h" #include "Val.h"
#include "NetVar.h" #include "NetVar.h"

View file

@ -247,7 +247,6 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/DebugCmdConstants.h
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
) )
set(dns_SRCS nb_dns.c)
set_source_files_properties(nb_dns.c PROPERTIES COMPILE_FLAGS set_source_files_properties(nb_dns.c PROPERTIES COMPILE_FLAGS
-fno-strict-aliasing) -fno-strict-aliasing)
@ -376,7 +375,7 @@ set(bro_SRCS
SMB.cc SMB.cc
SMTP.cc SMTP.cc
SSH.cc SSH.cc
SSL-binpac.cc SSL.cc
Scope.cc Scope.cc
SerializationFormat.cc SerializationFormat.cc
SerialObj.cc SerialObj.cc
@ -403,7 +402,6 @@ set(bro_SRCS
bsd-getopt-long.c bsd-getopt-long.c
bro_inet_ntop.c bro_inet_ntop.c
cq.c cq.c
md5.c
patricia.c patricia.c
setsignal.c setsignal.c
PacketDumper.cc PacketDumper.cc
@ -421,8 +419,8 @@ set(bro_SRCS
logging/writers/Ascii.cc logging/writers/Ascii.cc
logging/writers/None.cc logging/writers/None.cc
${dns_SRCS} nb_dns.c
${openssl_SRCS} digest.h
) )
collect_headers(bro_HEADERS ${bro_SRCS}) collect_headers(bro_HEADERS ${bro_SRCS})

View file

@ -2,9 +2,10 @@
#include "config.h" #include "config.h"
#include <openssl/md5.h>
#include "EquivClass.h" #include "EquivClass.h"
#include "DFA.h" #include "DFA.h"
#include "md5.h"
int dfa_state_cache_size = 10000; int dfa_state_cache_size = 10000;
@ -312,8 +313,8 @@ DFA_State* DFA_State_Cache::Lookup(const NFA_state_list& nfas,
{ {
// We assume that state ID's don't exceed 10 digits, plus // We assume that state ID's don't exceed 10 digits, plus
// we allow one more character for the delimiter. // we allow one more character for the delimiter.
md5_byte_t id_tag[nfas.length() * 11 + 1]; u_char id_tag[nfas.length() * 11 + 1];
md5_byte_t* p = id_tag; u_char* p = id_tag;
for ( int i = 0; i < nfas.length(); ++i ) for ( int i = 0; i < nfas.length(); ++i )
{ {
@ -335,12 +336,8 @@ DFA_State* DFA_State_Cache::Lookup(const NFA_state_list& nfas,
// We use the short MD5 instead of the full string for the // We use the short MD5 instead of the full string for the
// HashKey because the data is copied into the key. // HashKey because the data is copied into the key.
md5_state_t state; u_char digest[16];
md5_byte_t digest[16]; MD5(id_tag, p - id_tag, digest);
md5_init(&state);
md5_append(&state, id_tag, p - id_tag);
md5_finish(&state, digest);
*hash = new HashKey(&digest, sizeof(digest)); *hash = new HashKey(&digest, sizeof(digest));
CacheEntry* e = states.Lookup(*hash); CacheEntry* e = states.Lookup(*hash);

View file

@ -74,9 +74,8 @@ void RotateTimer::Dispatch(double t, int is_expire)
// The following could in principle be part of a "file manager" object. // The following could in principle be part of a "file manager" object.
#define MAX_FILE_CACHE_SIZE 32 #define MAX_FILE_CACHE_SIZE 512
static int num_files_in_cache = 0; static int num_files_in_cache = 0;
static int max_files_in_cache = 0;
static BroFile* head = 0; static BroFile* head = 0;
static BroFile* tail = 0; static BroFile* tail = 0;
@ -87,12 +86,9 @@ double BroFile::default_rotation_size = 0;
// that we should use for the cache. // that we should use for the cache.
static int maximize_num_fds() static int maximize_num_fds()
{ {
#ifdef NO_HAVE_SETRLIMIT
return MAX_FILE_CACHE_SIZE;
#else
struct rlimit rl; struct rlimit rl;
if ( getrlimit(RLIMIT_NOFILE, &rl) < 0 ) if ( getrlimit(RLIMIT_NOFILE, &rl) < 0 )
reporter->InternalError("maximize_num_fds(): getrlimit failed"); reporter->FatalError("maximize_num_fds(): getrlimit failed");
if ( rl.rlim_max == RLIM_INFINITY ) if ( rl.rlim_max == RLIM_INFINITY )
{ {
@ -108,10 +104,9 @@ static int maximize_num_fds()
rl.rlim_cur = rl.rlim_max; rl.rlim_cur = rl.rlim_max;
if ( setrlimit(RLIMIT_NOFILE, &rl) < 0 ) if ( setrlimit(RLIMIT_NOFILE, &rl) < 0 )
reporter->InternalError("maximize_num_fds(): setrlimit failed"); reporter->FatalError("maximize_num_fds(): setrlimit failed");
return rl.rlim_cur / 2; return rl.rlim_cur / 2;
#endif
} }
@ -172,7 +167,7 @@ const char* BroFile::Name() const
return 0; return 0;
} }
bool BroFile::Open(FILE* file) bool BroFile::Open(FILE* file, const char* mode)
{ {
open_time = network_time ? network_time : current_time(); open_time = network_time ? network_time : current_time();
@ -196,7 +191,12 @@ bool BroFile::Open(FILE* file)
InstallRotateTimer(); InstallRotateTimer();
if ( ! f ) if ( ! f )
{
if ( ! mode )
f = fopen(name, access); f = fopen(name, access);
else
f = fopen(name, mode);
}
SetBuf(buffered); SetBuf(buffered);
@ -846,8 +846,8 @@ BroFile* BroFile::Unserialize(UnserialInfo* info)
} }
} }
// Otherwise, open. // Otherwise, open, but don't clobber.
if ( ! file->Open() ) if ( ! file->Open(0, "a") )
{ {
info->s->Error(fmt("cannot open %s: %s", info->s->Error(fmt("cannot open %s: %s",
file->name, strerror(errno))); file->name, strerror(errno)));

View file

@ -87,7 +87,13 @@ protected:
BroFile() { Init(); } BroFile() { Init(); }
void Init(); void Init();
bool Open(FILE* f = 0); // if file is given, it's an open file to use
/**
* If file is given, it's an open file to use already.
* If file is not given and mode is, the filename will be opened with that
* access mode.
*/
bool Open(FILE* f = 0, const char* mode = 0);
BroFile* Prev() { return prev; } BroFile* Prev() { return prev; }
BroFile* Next() { return next; } BroFile* Next() { return next; }

View file

@ -29,7 +29,6 @@
#include <algorithm> #include <algorithm>
#include "md5.h"
#include "Base64.h" #include "Base64.h"
#include "Stmt.h" #include "Stmt.h"
#include "Scope.h" #include "Scope.h"

View file

@ -4,6 +4,7 @@
#include "MIME.h" #include "MIME.h"
#include "Event.h" #include "Event.h"
#include "Reporter.h" #include "Reporter.h"
#include "digest.h"
// Here are a few things to do: // Here are a few things to do:
// //
@ -1008,7 +1009,7 @@ void MIME_Mail::Done()
if ( compute_content_hash && mime_content_hash ) if ( compute_content_hash && mime_content_hash )
{ {
u_char* digest = new u_char[16]; u_char* digest = new u_char[16];
md5_finish(&md5_hash, digest); md5_final(&md5_hash, digest);
val_list* vl = new val_list; val_list* vl = new val_list;
vl->append(analyzer->BuildConnVal()); vl->append(analyzer->BuildConnVal());
@ -1096,7 +1097,7 @@ void MIME_Mail::SubmitData(int len, const char* buf)
if ( compute_content_hash ) if ( compute_content_hash )
{ {
content_hash_length += len; content_hash_length += len;
md5_append(&md5_hash, (const u_char*) buf, len); md5_update(&md5_hash, (const u_char*) buf, len);
} }
if ( mime_entity_data || mime_all_data ) if ( mime_entity_data || mime_all_data )

View file

@ -2,13 +2,12 @@
#define mime_h #define mime_h
#include <assert.h> #include <assert.h>
#include <openssl/md5.h>
#include <stdio.h> #include <stdio.h>
#include <vector> #include <vector>
#include <queue> #include <queue>
using namespace std; using namespace std;
#include "md5.h"
#include "Base64.h" #include "Base64.h"
#include "BroString.h" #include "BroString.h"
#include "Analyzer.h" #include "Analyzer.h"
@ -248,7 +247,7 @@ protected:
int buffer_offset; int buffer_offset;
int compute_content_hash; int compute_content_hash;
int content_hash_length; int content_hash_length;
md5_state_t md5_hash; MD5_CTX md5_hash;
vector<const BroString*> entity_content; vector<const BroString*> entity_content;
vector<const BroString*> all_content; vector<const BroString*> all_content;

View file

@ -167,6 +167,7 @@ TableVal* preserve_orig_addr;
TableVal* preserve_resp_addr; TableVal* preserve_resp_addr;
TableVal* preserve_other_addr; TableVal* preserve_other_addr;
int max_files_in_cache;
double log_rotate_interval; double log_rotate_interval;
double log_max_size; double log_max_size;
RecordType* rotate_info; RecordType* rotate_info;
@ -257,6 +258,7 @@ void init_general_global_var()
state_dir = internal_val("state_dir")->AsStringVal(); state_dir = internal_val("state_dir")->AsStringVal();
state_write_delay = opt_internal_double("state_write_delay"); state_write_delay = opt_internal_double("state_write_delay");
max_files_in_cache = opt_internal_int("max_files_in_cache");
log_rotate_interval = opt_internal_double("log_rotate_interval"); log_rotate_interval = opt_internal_double("log_rotate_interval");
log_max_size = opt_internal_double("log_max_size"); log_max_size = opt_internal_double("log_max_size");
rotate_info = internal_type("rotate_info")->AsRecordType(); rotate_info = internal_type("rotate_info")->AsRecordType();

View file

@ -170,6 +170,7 @@ extern double connection_status_update_interval;
extern StringVal* state_dir; extern StringVal* state_dir;
extern double state_write_delay; extern double state_write_delay;
extern int max_files_in_cache;
extern double log_rotate_interval; extern double log_rotate_interval;
extern double log_max_size; extern double log_max_size;
extern RecordType* rotate_info; extern RecordType* rotate_info;

View file

@ -1,21 +1,21 @@
#include "SSL-binpac.h" #include "SSL.h"
#include "TCP_Reassembler.h" #include "TCP_Reassembler.h"
#include "Reporter.h" #include "Reporter.h"
#include "util.h" #include "util.h"
SSL_Analyzer_binpac::SSL_Analyzer_binpac(Connection* c) SSL_Analyzer::SSL_Analyzer(Connection* c)
: TCP_ApplicationAnalyzer(AnalyzerTag::SSL, c) : TCP_ApplicationAnalyzer(AnalyzerTag::SSL, c)
{ {
interp = new binpac::SSL::SSL_Conn(this); interp = new binpac::SSL::SSL_Conn(this);
had_gap = false; had_gap = false;
} }
SSL_Analyzer_binpac::~SSL_Analyzer_binpac() SSL_Analyzer::~SSL_Analyzer()
{ {
delete interp; delete interp;
} }
void SSL_Analyzer_binpac::Done() void SSL_Analyzer::Done()
{ {
TCP_ApplicationAnalyzer::Done(); TCP_ApplicationAnalyzer::Done();
@ -23,23 +23,22 @@ void SSL_Analyzer_binpac::Done()
interp->FlowEOF(false); interp->FlowEOF(false);
} }
void SSL_Analyzer_binpac::EndpointEOF(TCP_Reassembler* endp) void SSL_Analyzer::EndpointEOF(TCP_Reassembler* endp)
{ {
TCP_ApplicationAnalyzer::EndpointEOF(endp); TCP_ApplicationAnalyzer::EndpointEOF(endp);
interp->FlowEOF(endp->IsOrig()); interp->FlowEOF(endp->IsOrig());
} }
void SSL_Analyzer_binpac::DeliverStream(int len, const u_char* data, bool orig) void SSL_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
{ {
TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
assert(TCP()); assert(TCP());
if ( TCP()->IsPartial() ) if ( TCP()->IsPartial() )
return; return;
if ( had_gap ) if ( had_gap )
// XXX: If only one side had a content gap, we could still try to // 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. // deliver data to the other side if the script layer can handle this.
return; return;
@ -53,7 +52,7 @@ void SSL_Analyzer_binpac::DeliverStream(int len, const u_char* data, bool orig)
} }
} }
void SSL_Analyzer_binpac::Undelivered(int seq, int len, bool orig) void SSL_Analyzer::Undelivered(int seq, int len, bool orig)
{ {
TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
had_gap = true; had_gap = true;

View file

@ -1,14 +1,13 @@
#ifndef ssl_binpac_h #ifndef ssl_h
#define ssl_binpac_h #define ssl_h
#include "TCP.h" #include "TCP.h"
#include "ssl_pac.h" #include "ssl_pac.h"
class SSL_Analyzer_binpac : public TCP_ApplicationAnalyzer { class SSL_Analyzer : public TCP_ApplicationAnalyzer {
public: public:
SSL_Analyzer_binpac(Connection* conn); SSL_Analyzer(Connection* conn);
virtual ~SSL_Analyzer_binpac(); virtual ~SSL_Analyzer();
// Overriden from Analyzer. // Overriden from Analyzer.
virtual void Done(); virtual void Done();
@ -19,7 +18,7 @@ public:
virtual void EndpointEOF(TCP_Reassembler* endp); virtual void EndpointEOF(TCP_Reassembler* endp);
static Analyzer* InstantiateAnalyzer(Connection* conn) static Analyzer* InstantiateAnalyzer(Connection* conn)
{ return new SSL_Analyzer_binpac(conn); } { return new SSL_Analyzer(conn); }
static bool Available() static bool Available()
{ {

View file

@ -6,13 +6,13 @@
%%{ // C segment %%{ // C segment
#include <math.h> #include <math.h>
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
#include <sys/stat.h> #include <sys/stat.h>
#include <cstdio> #include <cstdio>
#include "digest.h"
#include "Reporter.h" #include "Reporter.h"
#include "IPAddr.h" #include "IPAddr.h"
@ -530,7 +530,7 @@ function piped_exec%(program: string, to_write: string%): bool
%%{ %%{
static void hash_md5_val(val_list& vlist, unsigned char digest[16]) static void hash_md5_val(val_list& vlist, unsigned char digest[16])
{ {
md5_state_s h; MD5_CTX h;
md5_init(&h); md5_init(&h);
loop_over_list(vlist, i) loop_over_list(vlist, i)
@ -539,16 +539,16 @@ static void hash_md5_val(val_list& vlist, unsigned char digest[16])
if ( v->Type()->Tag() == TYPE_STRING ) if ( v->Type()->Tag() == TYPE_STRING )
{ {
const BroString* str = v->AsString(); const BroString* str = v->AsString();
md5_append(&h, str->Bytes(), str->Len()); md5_update(&h, str->Bytes(), str->Len());
} }
else else
{ {
ODesc d(DESC_BINARY); ODesc d(DESC_BINARY);
v->Describe(&d); v->Describe(&d);
md5_append(&h, (const md5_byte_t *) d.Bytes(), d.Len()); md5_update(&h, (const u_char *) d.Bytes(), d.Len());
} }
} }
md5_finish(&h, digest); md5_final(&h, digest);
} }
static void hmac_md5_val(val_list& vlist, unsigned char digest[16]) static void hmac_md5_val(val_list& vlist, unsigned char digest[16])
@ -556,7 +556,53 @@ static void hmac_md5_val(val_list& vlist, unsigned char digest[16])
hash_md5_val(vlist, digest); hash_md5_val(vlist, digest);
for ( int i = 0; i < 16; ++i ) for ( int i = 0; i < 16; ++i )
digest[i] = digest[i] ^ shared_hmac_md5_key[i]; digest[i] = digest[i] ^ shared_hmac_md5_key[i];
hash_md5(16, digest, digest); MD5(digest, 16, digest);
}
static void hash_sha1_val(val_list& vlist, unsigned char digest[20])
{
SHA_CTX h;
sha1_init(&h);
loop_over_list(vlist, i)
{
Val* v = vlist[i];
if ( v->Type()->Tag() == TYPE_STRING )
{
const BroString* str = v->AsString();
sha1_update(&h, str->Bytes(), str->Len());
}
else
{
ODesc d(DESC_BINARY);
v->Describe(&d);
sha1_update(&h, (const u_char *) d.Bytes(), d.Len());
}
}
sha1_final(&h, digest);
}
static void hash_sha256_val(val_list& vlist, unsigned char digest[32])
{
SHA256_CTX h;
sha256_init(&h);
loop_over_list(vlist, i)
{
Val* v = vlist[i];
if ( v->Type()->Tag() == TYPE_STRING )
{
const BroString* str = v->AsString();
sha256_update(&h, str->Bytes(), str->Len());
}
else
{
ODesc d(DESC_BINARY);
v->Describe(&d);
sha256_update(&h, (const u_char *) d.Bytes(), d.Len());
}
}
sha256_final(&h, digest);
} }
%%} %%}
@ -565,6 +611,8 @@ static void hmac_md5_val(val_list& vlist, unsigned char digest[16])
## Returns: The MD5 hash value of the concatenated arguments. ## Returns: The MD5 hash value of the concatenated arguments.
## ##
## .. bro:see:: md5_hmac md5_hash_init md5_hash_update md5_hash_finish ## .. bro:see:: md5_hmac md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
## ##
## .. note:: ## .. note::
## ##
@ -578,6 +626,46 @@ function md5_hash%(...%): string
return new StringVal(md5_digest_print(digest)); return new StringVal(md5_digest_print(digest));
%} %}
## Computes the SHA1 hash value of the provided list of arguments.
##
## Returns: The SHA1 hash value of the concatenated arguments.
##
## .. bro:see:: md5_hash md5_hmac md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
##
## .. note::
##
## This function performs a one-shot computation of its arguments.
## For incremental hash computation, see :bro:id:`sha1_hash_init` and
## friends.
function sha1_hash%(...%): string
%{
unsigned char digest[20];
hash_sha1_val(@ARG@, digest);
return new StringVal(sha1_digest_print(digest));
%}
## Computes the SHA256 hash value of the provided list of arguments.
##
## Returns: The SHA256 hash value of the concatenated arguments.
##
## .. bro:see:: md5_hash md5_hmac md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash_init sha256_hash_update sha256_hash_finish
##
## .. note::
##
## This function performs a one-shot computation of its arguments.
## For incremental hash computation, see :bro:id:`sha256_hash_init` and
## friends.
function sha256_hash%(...%): string
%{
unsigned char digest[32];
hash_sha256_val(@ARG@, digest);
return new StringVal(sha256_digest_print(digest));
%}
## Computes an HMAC-MD5 hash value of the provided list of arguments. The HMAC ## 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 ## secret key is generated from available entropy when Bro starts up, or it can
## be specified for repeatability using the ``-K`` command line flag. ## be specified for repeatability using the ``-K`` command line flag.
@ -585,6 +673,8 @@ function md5_hash%(...%): string
## Returns: The HMAC-MD5 hash value of the concatenated arguments. ## Returns: The HMAC-MD5 hash value of the concatenated arguments.
## ##
## .. bro:see:: md5_hash md5_hash_init md5_hash_update md5_hash_finish ## .. bro:see:: md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function md5_hmac%(...%): string function md5_hmac%(...%): string
%{ %{
unsigned char digest[16]; unsigned char digest[16];
@ -593,7 +683,9 @@ function md5_hmac%(...%): string
%} %}
%%{ %%{
static map<BroString, md5_state_s> md5_states; static map<BroString, MD5_CTX> md5_states;
static map<BroString, SHA_CTX> sha1_states;
static map<BroString, SHA256_CTX> sha256_states;
BroString* convert_index_to_string(Val* index) BroString* convert_index_to_string(Val* index)
{ {
@ -618,7 +710,9 @@ BroString* convert_index_to_string(Val* index)
## ##
## index: The unique identifier to associate with this hash computation. ## index: The unique identifier to associate with this hash computation.
## ##
## .. bro:see:: md5_hash md5_hmac md5_hash_update md5_hash_finish ## .. bro:see:: md5_hmac md5_hash md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function md5_hash_init%(index: any%): bool function md5_hash_init%(index: any%): bool
%{ %{
BroString* s = convert_index_to_string(index); BroString* s = convert_index_to_string(index);
@ -626,7 +720,7 @@ function md5_hash_init%(index: any%): bool
if ( md5_states.count(*s) < 1 ) if ( md5_states.count(*s) < 1 )
{ {
md5_state_s h; MD5_CTX h;
md5_init(&h); md5_init(&h);
md5_states[*s] = h; md5_states[*s] = h;
status = 1; status = 1;
@ -636,6 +730,75 @@ function md5_hash_init%(index: any%): bool
return new Val(status, TYPE_BOOL); return new Val(status, TYPE_BOOL);
%} %}
## Initializes SHA1 state to enable incremental hash computation. After
## initializing the SHA1 state with this function, you can feed data to
## :bro:id:`sha1_hash_update` and finally need to call
## :bro:id:`sha1_hash_finish` to finish the computation and get the final hash
## value.
##
## For example, when computing incremental SHA1 values of transferred files in
## multiple concurrent HTTP connections, one would call ``sha1_hash_init(c$id)``
## once before invoking ``sha1_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:`sha1_hash_finish` returns the final hash value.
##
## index: The unique identifier to associate with this hash computation.
##
## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function sha1_hash_init%(index: any%): bool
%{
BroString* s = convert_index_to_string(index);
int status = 0;
if ( sha1_states.count(*s) < 1 )
{
SHA_CTX h;
sha1_init(&h);
sha1_states[*s] = h;
status = 1;
}
delete s;
return new Val(status, TYPE_BOOL);
%}
## Initializes SHA256 state to enable incremental hash computation. After
## initializing the SHA256 state with this function, you can feed data to
## :bro:id:`sha256_hash_update` and finally need to call
## :bro:id:`sha256_hash_finish` to finish the computation and get the final hash
## value.
##
## For example, when computing incremental SHA256 values of transferred files in
## multiple concurrent HTTP connections, one would call
## ``sha256_hash_init(c$id)`` once before invoking
## ``sha256_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:`sha256_hash_finish` returns the final hash value.
##
## index: The unique identifier to associate with this hash computation.
##
## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_update sha256_hash_finish
function sha256_hash_init%(index: any%): bool
%{
BroString* s = convert_index_to_string(index);
int status = 0;
if ( sha256_states.count(*s) < 1 )
{
SHA256_CTX h;
sha256_init(&h);
sha256_states[*s] = h;
status = 1;
}
delete s;
return new Val(status, TYPE_BOOL);
%}
## Update the MD5 value associated with a given index. It is required to ## Update the MD5 value associated with a given index. It is required to
## call :bro:id:`md5_hash_init` once before calling this ## call :bro:id:`md5_hash_init` once before calling this
## function. ## function.
@ -644,7 +807,9 @@ function md5_hash_init%(index: any%): bool
## ##
## data: The data to add to the hash computation. ## data: The data to add to the hash computation.
## ##
## .. bro:see:: md5_hash md5_hmac md5_hash_init md5_hash_finish ## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function md5_hash_update%(index: any, data: string%): bool function md5_hash_update%(index: any, data: string%): bool
%{ %{
BroString* s = convert_index_to_string(index); BroString* s = convert_index_to_string(index);
@ -652,7 +817,59 @@ function md5_hash_update%(index: any, data: string%): bool
if ( md5_states.count(*s) > 0 ) if ( md5_states.count(*s) > 0 )
{ {
md5_append(&md5_states[*s], data->Bytes(), data->Len()); md5_update(&md5_states[*s], data->Bytes(), data->Len());
status = 1;
}
delete s;
return new Val(status, TYPE_BOOL);
%}
## Update the SHA1 value associated with a given index. It is required to
## call :bro:id:`sha1_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_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function sha1_hash_update%(index: any, data: string%): bool
%{
BroString* s = convert_index_to_string(index);
int status = 0;
if ( sha1_states.count(*s) > 0 )
{
sha1_update(&sha1_states[*s], data->Bytes(), data->Len());
status = 1;
}
delete s;
return new Val(status, TYPE_BOOL);
%}
## Update the SHA256 value associated with a given index. It is required to
## call :bro:id:`sha256_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_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_finish
function sha256_hash_update%(index: any, data: string%): bool
%{
BroString* s = convert_index_to_string(index);
int status = 0;
if ( sha256_states.count(*s) > 0 )
{
sha256_update(&sha256_states[*s], data->Bytes(), data->Len());
status = 1; status = 1;
} }
@ -666,7 +883,9 @@ function md5_hash_update%(index: any, data: string%): bool
## ##
## Returns: The hash value associated with the computation at *index*. ## Returns: The hash value associated with the computation at *index*.
## ##
## .. bro:see:: md5_hash md5_hmac md5_hash_init md5_hash_update ## .. bro:see:: md5_hmac md5_hash md5_hash_init md5_hash_update
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function md5_hash_finish%(index: any%): string function md5_hash_finish%(index: any%): string
%{ %{
BroString* s = convert_index_to_string(index); BroString* s = convert_index_to_string(index);
@ -675,7 +894,7 @@ function md5_hash_finish%(index: any%): string
if ( md5_states.count(*s) > 0 ) if ( md5_states.count(*s) > 0 )
{ {
unsigned char digest[16]; unsigned char digest[16];
md5_finish(&md5_states[*s], digest); md5_final(&md5_states[*s], digest);
md5_states.erase(*s); md5_states.erase(*s);
printable_digest = new StringVal(md5_digest_print(digest)); printable_digest = new StringVal(md5_digest_print(digest));
} }
@ -686,6 +905,62 @@ function md5_hash_finish%(index: any%): string
return printable_digest; return printable_digest;
%} %}
## Returns the final SHA1 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_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update
## sha256_hash sha256_hash_init sha256_hash_update sha256_hash_finish
function sha1_hash_finish%(index: any%): string
%{
BroString* s = convert_index_to_string(index);
StringVal* printable_digest;
if ( sha1_states.count(*s) > 0 )
{
unsigned char digest[20];
sha1_final(&sha1_states[*s], digest);
sha1_states.erase(*s);
printable_digest = new StringVal(sha1_digest_print(digest));
}
else
printable_digest = new StringVal("");
delete s;
return printable_digest;
%}
## Returns the final SHA256 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_hmac md5_hash md5_hash_init md5_hash_update md5_hash_finish
## sha1_hash sha1_hash_init sha1_hash_update sha1_hash_finish
## sha256_hash sha256_hash_init sha256_hash_update
function sha256_hash_finish%(index: any%): string
%{
BroString* s = convert_index_to_string(index);
StringVal* printable_digest;
if ( sha256_states.count(*s) > 0 )
{
unsigned char digest[32];
sha256_final(&sha256_states[*s], digest);
sha256_states.erase(*s);
printable_digest = new StringVal(sha256_digest_print(digest));
}
else
printable_digest = new StringVal("");
delete s;
return printable_digest;
%}
## Generates a random number. ## Generates a random number.
## ##
## max: The maximum value the random number. ## max: The maximum value the random number.

92
src/digest.h Normal file
View file

@ -0,0 +1,92 @@
// See the file "COPYING" in the main distribution directory for copyright.
/**
* Wrapper and helper functions for MD5/SHA digest algorithms.
*/
#ifndef bro_digest_h
#define bro_digest_h
#include <openssl/md5.h>
#include <openssl/sha.h>
#include "Reporter.h"
static inline const char* digest_print(const u_char* digest, size_t n)
{
static char buf[256]; // big enough for any of md5/sha1/sha256
for ( size_t i = 0; i < n; ++i )
snprintf(buf + i * 2, 3, "%02x", digest[i]);
return buf;
}
inline const char* md5_digest_print(const u_char digest[MD5_DIGEST_LENGTH])
{
return digest_print(digest, MD5_DIGEST_LENGTH);
}
inline const char* sha1_digest_print(const u_char digest[SHA_DIGEST_LENGTH])
{
return digest_print(digest, SHA_DIGEST_LENGTH);
}
inline const char* sha256_digest_print(const u_char digest[SHA256_DIGEST_LENGTH])
{
return digest_print(digest, SHA256_DIGEST_LENGTH);
}
inline void md5_init(MD5_CTX* c)
{
if ( ! MD5_Init(c) )
reporter->InternalError("MD5_Init failed");
}
inline void md5_update(MD5_CTX* c, const void* data, unsigned long len)
{
if ( ! MD5_Update(c, data, len) )
reporter->InternalError("MD5_Update failed");
}
inline void md5_final(MD5_CTX* c, u_char md[MD5_DIGEST_LENGTH])
{
if ( ! MD5_Final(md, c) )
reporter->InternalError("MD5_Final failed");
}
inline void sha1_init(SHA_CTX* c)
{
if ( ! SHA1_Init(c) )
reporter->InternalError("SHA_Init failed");
}
inline void sha1_update(SHA_CTX* c, const void* data, unsigned long len)
{
if ( ! SHA1_Update(c, data, len) )
reporter->InternalError("SHA_Update failed");
}
inline void sha1_final(SHA_CTX* c, u_char md[SHA_DIGEST_LENGTH])
{
if ( ! SHA1_Final(md, c) )
reporter->InternalError("SHA_Final failed");
}
inline void sha256_init(SHA256_CTX* c)
{
if ( ! SHA256_Init(c) )
reporter->InternalError("SHA256_Init failed");
}
inline void sha256_update(SHA256_CTX* c, const void* data, unsigned long len)
{
if ( ! SHA256_Update(c, data, len) )
reporter->InternalError("SHA256_Update failed");
}
inline void sha256_final(SHA256_CTX* c, u_char md[SHA256_DIGEST_LENGTH])
{
if ( ! SHA256_Final(md, c) )
reporter->InternalError("SHA256_Final failed");
}
#endif //bro_digest_h

View file

@ -18,6 +18,8 @@ extern "C" {
} }
#endif #endif
#include <openssl/md5.h>
extern "C" void OPENSSL_add_all_algorithms_conf(void); extern "C" void OPENSSL_add_all_algorithms_conf(void);
#include "bsd-getopt-long.h" #include "bsd-getopt-long.h"
@ -570,8 +572,7 @@ int main(int argc, char** argv)
break; break;
case 'K': case 'K':
hash_md5(strlen(optarg), (const u_char*) optarg, MD5((const u_char*) optarg, strlen(optarg), shared_hmac_md5_key);
shared_hmac_md5_key);
hmac_key_set = 1; hmac_key_set = 1;
break; break;

380
src/md5.c
View file

@ -1,380 +0,0 @@
/*
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.c is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
either statically or dynamically; added missing #include <string.h>
in library.
2002-03-11 lpd Corrected argument list for main(), and added int return
type, in test program and T value program.
2002-02-21 lpd Added missing #include <stdio.h> in test program.
2000-07-03 lpd Patched to eliminate warnings about "constant is
unsigned in ANSI C, signed in traditional"; made test program
self-checking.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
1999-05-03 lpd Original version.
*/
#include "md5.h"
#include <string.h>
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#ifdef ARCH_IS_BIG_ENDIAN
# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
#else
# define BYTE_ORDER 0
#endif
#define T_MASK ((md5_word_t)~0)
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
#define T3 0x242070db
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
#define T6 0x4787c62a
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
#define T9 0x698098d8
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
#define T13 0x6b901122
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
#define T16 0x49b40821
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
#define T19 0x265e5a51
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
#define T22 0x02441453
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
#define T25 0x21e1cde6
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
#define T28 0x455a14ed
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
#define T31 0x676f02d9
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
#define T35 0x6d9d6122
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
#define T38 0x4bdecfa9
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
#define T41 0x289b7ec6
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
#define T44 0x04881d05
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
#define T47 0x1fa27cf8
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
#define T50 0x432aff97
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
#define T53 0x655b59c3
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
#define T57 0x6fa87e4f
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
#define T60 0x4e0811a1
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
#define T63 0x2ad7d2bb
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
static void
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
{
md5_word_t
a = pms->abcd[0], b = pms->abcd[1],
c = pms->abcd[2], d = pms->abcd[3];
md5_word_t t;
#if BYTE_ORDER > 0
/* Define storage only for big-endian CPUs. */
md5_word_t X[16];
#else
/* Define storage for little-endian or both types of CPUs. */
md5_word_t xbuf[16];
const md5_word_t *X;
#endif
{
#if BYTE_ORDER == 0
/*
* Determine dynamically whether this is a big-endian or
* little-endian machine, since we can use a more efficient
* algorithm on the latter.
*/
static const int w = 1;
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
#endif
#if BYTE_ORDER <= 0 /* little-endian */
{
/*
* On little-endian machines, we can process properly aligned
* data without copying it.
*/
if (!((data - (const md5_byte_t *)0) & 3)) {
/* data are properly aligned */
X = (const md5_word_t *)data;
} else {
/* not aligned */
memcpy(xbuf, data, 64);
X = xbuf;
}
}
#endif
#if BYTE_ORDER == 0
else /* dynamic big-endian */
#endif
#if BYTE_ORDER >= 0 /* big-endian */
{
/*
* On big-endian machines, we must arrange the bytes in the
* right order.
*/
const md5_byte_t *xp = data;
int i;
# if BYTE_ORDER == 0
X = xbuf; /* (dynamic only) */
# else
# define xbuf X /* (static only) */
# endif
for (i = 0; i < 16; ++i, xp += 4)
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
}
#endif
}
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
/* Round 1. */
/* Let [abcd k s i] denote the operation
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + F(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 7, T1);
SET(d, a, b, c, 1, 12, T2);
SET(c, d, a, b, 2, 17, T3);
SET(b, c, d, a, 3, 22, T4);
SET(a, b, c, d, 4, 7, T5);
SET(d, a, b, c, 5, 12, T6);
SET(c, d, a, b, 6, 17, T7);
SET(b, c, d, a, 7, 22, T8);
SET(a, b, c, d, 8, 7, T9);
SET(d, a, b, c, 9, 12, T10);
SET(c, d, a, b, 10, 17, T11);
SET(b, c, d, a, 11, 22, T12);
SET(a, b, c, d, 12, 7, T13);
SET(d, a, b, c, 13, 12, T14);
SET(c, d, a, b, 14, 17, T15);
SET(b, c, d, a, 15, 22, T16);
#undef SET
/* Round 2. */
/* Let [abcd k s i] denote the operation
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + G(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 1, 5, T17);
SET(d, a, b, c, 6, 9, T18);
SET(c, d, a, b, 11, 14, T19);
SET(b, c, d, a, 0, 20, T20);
SET(a, b, c, d, 5, 5, T21);
SET(d, a, b, c, 10, 9, T22);
SET(c, d, a, b, 15, 14, T23);
SET(b, c, d, a, 4, 20, T24);
SET(a, b, c, d, 9, 5, T25);
SET(d, a, b, c, 14, 9, T26);
SET(c, d, a, b, 3, 14, T27);
SET(b, c, d, a, 8, 20, T28);
SET(a, b, c, d, 13, 5, T29);
SET(d, a, b, c, 2, 9, T30);
SET(c, d, a, b, 7, 14, T31);
SET(b, c, d, a, 12, 20, T32);
#undef SET
/* Round 3. */
/* Let [abcd k s t] denote the operation
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define SET(a, b, c, d, k, s, Ti)\
t = a + H(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 5, 4, T33);
SET(d, a, b, c, 8, 11, T34);
SET(c, d, a, b, 11, 16, T35);
SET(b, c, d, a, 14, 23, T36);
SET(a, b, c, d, 1, 4, T37);
SET(d, a, b, c, 4, 11, T38);
SET(c, d, a, b, 7, 16, T39);
SET(b, c, d, a, 10, 23, T40);
SET(a, b, c, d, 13, 4, T41);
SET(d, a, b, c, 0, 11, T42);
SET(c, d, a, b, 3, 16, T43);
SET(b, c, d, a, 6, 23, T44);
SET(a, b, c, d, 9, 4, T45);
SET(d, a, b, c, 12, 11, T46);
SET(c, d, a, b, 15, 16, T47);
SET(b, c, d, a, 2, 23, T48);
#undef SET
/* Round 4. */
/* Let [abcd k s t] denote the operation
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
#define SET(a, b, c, d, k, s, Ti)\
t = a + I(b,c,d) + X[k] + Ti;\
a = ROTATE_LEFT(t, s) + b
/* Do the following 16 operations. */
SET(a, b, c, d, 0, 6, T49);
SET(d, a, b, c, 7, 10, T50);
SET(c, d, a, b, 14, 15, T51);
SET(b, c, d, a, 5, 21, T52);
SET(a, b, c, d, 12, 6, T53);
SET(d, a, b, c, 3, 10, T54);
SET(c, d, a, b, 10, 15, T55);
SET(b, c, d, a, 1, 21, T56);
SET(a, b, c, d, 8, 6, T57);
SET(d, a, b, c, 15, 10, T58);
SET(c, d, a, b, 6, 15, T59);
SET(b, c, d, a, 13, 21, T60);
SET(a, b, c, d, 4, 6, T61);
SET(d, a, b, c, 11, 10, T62);
SET(c, d, a, b, 2, 15, T63);
SET(b, c, d, a, 9, 21, T64);
#undef SET
/* Then perform the following additions. (That is increment each
of the four registers by the value it had before this block
was started.) */
pms->abcd[0] += a;
pms->abcd[1] += b;
pms->abcd[2] += c;
pms->abcd[3] += d;
}
void
md5_init(md5_state_t *pms)
{
pms->count[0] = pms->count[1] = 0;
pms->abcd[0] = 0x67452301;
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
pms->abcd[3] = 0x10325476;
}
void
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
{
const md5_byte_t *p = data;
int left = nbytes;
int offset = (pms->count[0] >> 3) & 63;
md5_word_t nbits = (md5_word_t)(nbytes << 3);
if (nbytes <= 0)
return;
/* Update the message length. */
pms->count[1] += nbytes >> 29;
pms->count[0] += nbits;
if (pms->count[0] < nbits)
pms->count[1]++;
/* Process an initial partial block. */
if (offset) {
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
memcpy(pms->buf + offset, p, copy);
if (offset + copy < 64)
return;
p += copy;
left -= copy;
md5_process(pms, pms->buf);
}
/* Process full blocks. */
for (; left >= 64; p += 64, left -= 64)
md5_process(pms, p);
/* Process a final partial block. */
if (left)
memcpy(pms->buf, p, left);
}
void
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
{
static const md5_byte_t pad[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
md5_byte_t data[8];
int i;
/* Save the length before padding. */
for (i = 0; i < 8; ++i)
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
/* Pad to 56 bytes mod 64. */
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
/* Append the length. */
md5_append(pms, data, 8);
for (i = 0; i < 16; ++i)
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
}

View file

@ -1,90 +0,0 @@
/*
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
L. Peter Deutsch
ghost@aladdin.com
*/
/*
Independent implementation of MD5 (RFC 1321).
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
copyrighted.
The original and principal author of md5.h is L. Peter Deutsch
<ghost@aladdin.com>. Other authors are noted in the change history
that follows (in reverse chronological order):
2002-04-13 lpd Removed support for non-ANSI compilers; removed
references to Ghostscript; clarified derivation from RFC 1321;
now handles byte order either statically or dynamically.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
added conditionalization for C++ compilation from Martin
Purschke <purschke@bnl.gov>.
1999-05-03 lpd Original version.
*/
#ifndef md5_INCLUDED
# define md5_INCLUDED
/*
* This package supports both compile-time and run-time determination of CPU
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
* defined as non-zero, the code will be compiled to run only on big-endian
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
* run on either big- or little-endian CPUs, but will run slightly less
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
*/
typedef unsigned char md5_byte_t; /* 8-bit byte */
typedef unsigned int md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
typedef struct md5_state_s {
md5_word_t count[2]; /* message length in bits, lsw first */
md5_word_t abcd[4]; /* digest buffer */
md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
#ifdef __cplusplus
extern "C"
{
#endif
/* Initialize the algorithm. */
void md5_init(md5_state_t *pms);
/* Append a string to the message. */
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
/* Finish the message and return the digest. */
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
#ifdef __cplusplus
} /* end extern "C" */
#endif
#endif /* md5_INCLUDED */

View file

@ -25,6 +25,7 @@
string orig_label(bool is_orig); string orig_label(bool is_orig);
void free_X509(void *); void free_X509(void *);
X509* d2i_X509_binpac(X509** px, const uint8** in, int len); X509* d2i_X509_binpac(X509** px, const uint8** in, int len);
string handshake_type_label(int type);
%} %}
%code{ %code{
@ -46,6 +47,27 @@ string orig_label(bool is_orig)
return d2i_X509(px, (u_char**) in, len); return d2i_X509(px, (u_char**) in, len);
#endif #endif
} }
string handshake_type_label(int type)
{
switch ( type ) {
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");
case SERVER_HELLO_DONE: return string("SERVER_HELLO_DONE");
case CERTIFICATE_VERIFY: return string("CERTIFICATE_VERIFY");
case CLIENT_KEY_EXCHANGE: return string("CLIENT_KEY_EXCHANGE");
case FINISHED: return string("FINISHED");
case CERTIFICATE_URL: return string("CERTIFICATE_URL");
case CERTIFICATE_STATUS: return string("CERTIFICATE_STATUS");
default: return string(fmt("UNKNOWN (%d)", type));
}
}
%} %}
@ -88,15 +110,15 @@ refine connection SSL_Conn += {
eof=0; eof=0;
%} %}
%eof{ #%eof{
if ( ! eof && # if ( ! eof &&
state_ != STATE_CONN_ESTABLISHED && # state_ != STATE_CONN_ESTABLISHED &&
state_ != STATE_TRACK_LOST && # state_ != STATE_TRACK_LOST &&
state_ != STATE_INITIAL ) # state_ != STATE_INITIAL )
bro_analyzer()->ProtocolViolation(fmt("unexpected end of connection in state %s", # bro_analyzer()->ProtocolViolation(fmt("unexpected end of connection in state %s",
state_label(state_).c_str())); # state_label(state_).c_str()));
++eof; # ++eof;
%} #%}
%cleanup{ %cleanup{
%} %}
@ -133,11 +155,6 @@ refine connection SSL_Conn += {
cipher_suites16 : uint16[], cipher_suites16 : uint16[],
cipher_suites24 : uint24[]) : bool cipher_suites24 : uint24[]) : bool
%{ %{
if ( state_ == STATE_TRACK_LOST )
bro_analyzer()->ProtocolViolation(fmt("unexpected client hello message from %s in state %s",
orig_label(${rec.is_orig}).c_str(),
state_label(old_state_).c_str()));
if ( ! version_ok(version) ) if ( ! version_ok(version) )
bro_analyzer()->ProtocolViolation(fmt("unsupported client SSL version 0x%04x", version)); bro_analyzer()->ProtocolViolation(fmt("unsupported client SSL version 0x%04x", version));
@ -175,11 +192,6 @@ refine connection SSL_Conn += {
cipher_suites24 : uint24[], cipher_suites24 : uint24[],
comp_method : uint8) : bool comp_method : uint8) : bool
%{ %{
if ( state_ == STATE_TRACK_LOST )
bro_analyzer()->ProtocolViolation(fmt("unexpected server hello message from %s in state %s",
orig_label(${rec.is_orig}).c_str(),
state_label(old_state_).c_str()));
if ( ! version_ok(version) ) if ( ! version_ok(version) )
bro_analyzer()->ProtocolViolation(fmt("unsupported server SSL version 0x%04x", version)); bro_analyzer()->ProtocolViolation(fmt("unsupported server SSL version 0x%04x", version));
else else
@ -229,11 +241,6 @@ refine connection SSL_Conn += {
function proc_certificate(rec: SSLRecord, certificates : bytestring[]) : bool function proc_certificate(rec: SSLRecord, certificates : bytestring[]) : bool
%{ %{
if ( state_ == STATE_TRACK_LOST )
bro_analyzer()->ProtocolViolation(fmt("unexpected certificate message from %s in state %s",
orig_label(${rec.is_orig}).c_str(),
state_label(old_state_).c_str()));
if ( certificates->size() == 0 ) if ( certificates->size() == 0 )
return true; return true;
@ -362,6 +369,7 @@ refine connection SSL_Conn += {
handshake_type_label(${hs.msg_type}).c_str(), handshake_type_label(${hs.msg_type}).c_str(),
orig_label(is_orig).c_str(), orig_label(is_orig).c_str(),
state_label(old_state_).c_str())); state_label(old_state_).c_str()));
return true; return true;
%} %}

View file

@ -17,35 +17,6 @@ enum ContentType {
UNKNOWN_OR_V2_ENCRYPTED = 400 UNKNOWN_OR_V2_ENCRYPTED = 400
}; };
%code{
string* record_type_label(int type)
{
switch ( type ) {
case CHANGE_CIPHER_SPEC:
return new string("CHANGE_CIPHER_SPEC");
case ALERT:
return new string("ALERT");
case HANDSHAKE:
return new string("HANDSHAKE");
case APPLICATION_DATA:
return new string("APPLICATION_DATA");
case V2_ERROR:
return new string("V2_ERROR");
case V2_CLIENT_HELLO:
return new string("V2_CLIENT_HELLO");
case V2_CLIENT_MASTER_KEY:
return new string("V2_CLIENT_MASTER_KEY");
case V2_SERVER_HELLO:
return new string("V2_SERVER_HELLO");
case UNKNOWN_OR_V2_ENCRYPTED:
return new string("UNKNOWN_OR_V2_ENCRYPTED");
default:
return new string(fmt("UNEXPECTED (%d)", type));
}
}
%}
enum SSLVersions { enum SSLVersions {
UNKNOWN_VERSION = 0x0000, UNKNOWN_VERSION = 0x0000,
SSLv20 = 0x0002, SSLv20 = 0x0002,

View file

@ -23,7 +23,6 @@ type uint24 = record {
string state_label(int state_nr); string state_label(int state_nr);
double get_time_from_asn1(const ASN1_TIME * atime); double get_time_from_asn1(const ASN1_TIME * atime);
string handshake_type_label(int type);
%} %}
extern type to_int; extern type to_int;
@ -268,28 +267,6 @@ enum HandshakeType {
CERTIFICATE_STATUS = 22, # RFC 3546 CERTIFICATE_STATUS = 22, # RFC 3546
}; };
%code{
string handshake_type_label(int type)
{
switch ( type ) {
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");
case SERVER_HELLO_DONE: return string("SERVER_HELLO_DONE");
case CERTIFICATE_VERIFY: return string("CERTIFICATE_VERIFY");
case CLIENT_KEY_EXCHANGE: return string("CLIENT_KEY_EXCHANGE");
case FINISHED: return string("FINISHED");
case CERTIFICATE_URL: return string("CERTIFICATE_URL");
case CERTIFICATE_STATUS: return string("CERTIFICATE_STATUS");
default: return string(fmt("UNKNOWN (%d)", type));
}
}
%}
###################################################################### ######################################################################
# V3 Change Cipher Spec Protocol (7.1.) # V3 Change Cipher Spec Protocol (7.1.)
@ -425,6 +402,10 @@ type ServerHello(rec: SSLRecord) = record {
session_id : uint8[session_len]; session_id : uint8[session_len];
cipher_suite : uint16[1]; cipher_suite : uint16[1];
compression_method : uint8; compression_method : uint8;
# 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(rec)[] &until($input.length() == 0);
} &let { } &let {
state_changed : bool = state_changed : bool =
$context.connection.transition(STATE_CLIENT_HELLO_RCVD, $context.connection.transition(STATE_CLIENT_HELLO_RCVD,

View file

@ -27,6 +27,8 @@
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <libgen.h> #include <libgen.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#ifdef HAVE_MALLINFO #ifdef HAVE_MALLINFO
# include <malloc.h> # include <malloc.h>
@ -35,7 +37,6 @@
#include "input.h" #include "input.h"
#include "util.h" #include "util.h"
#include "Obj.h" #include "Obj.h"
#include "md5.h"
#include "Val.h" #include "Val.h"
#include "NetVar.h" #include "NetVar.h"
#include "Net.h" #include "Net.h"
@ -546,24 +547,6 @@ bool is_dir(const char* path)
return S_ISDIR(st.st_mode); return S_ISDIR(st.st_mode);
} }
void hash_md5(size_t size, const unsigned char* bytes, unsigned char digest[16])
{
md5_state_s h;
md5_init(&h);
md5_append(&h, bytes, size);
md5_finish(&h, digest);
}
const char* md5_digest_print(const unsigned char digest[16])
{
static char digest_print[256];
for ( int i = 0; i < 16; ++i )
snprintf(digest_print + i * 2, 3, "%02x", digest[i]);
return digest_print;
}
int hmac_key_set = 0; int hmac_key_set = 0;
uint8 shared_hmac_md5_key[16]; uint8 shared_hmac_md5_key[16];
@ -572,12 +555,12 @@ void hmac_md5(size_t size, const unsigned char* bytes, unsigned char digest[16])
if ( ! hmac_key_set ) if ( ! hmac_key_set )
reporter->InternalError("HMAC-MD5 invoked before the HMAC key is set"); reporter->InternalError("HMAC-MD5 invoked before the HMAC key is set");
hash_md5(size, bytes, digest); MD5(bytes, size, digest);
for ( int i = 0; i < 16; ++i ) for ( int i = 0; i < 16; ++i )
digest[i] ^= shared_hmac_md5_key[i]; digest[i] ^= shared_hmac_md5_key[i];
hash_md5(16, digest, digest); MD5(digest, 16, digest);
} }
static bool read_random_seeds(const char* read_file, uint32* seed, static bool read_random_seeds(const char* read_file, uint32* seed,
@ -724,7 +707,7 @@ void init_random_seed(uint32 seed, const char* read_file, const char* write_file
if ( ! hmac_key_set ) if ( ! hmac_key_set )
{ {
hash_md5(sizeof(buf), (u_char*) buf, shared_hmac_md5_key); MD5((const u_char*) buf, sizeof(buf), shared_hmac_md5_key);
hmac_key_set = 1; hmac_key_set = 1;
} }

View file

@ -136,16 +136,12 @@ extern bool ensure_dir(const char *dirname);
bool is_dir(const char* path); bool is_dir(const char* path);
extern uint8 shared_hmac_md5_key[16]; extern uint8 shared_hmac_md5_key[16];
extern void hash_md5(size_t size, const unsigned char* bytes,
unsigned char digest[16]);
extern int hmac_key_set; extern int hmac_key_set;
extern unsigned char shared_hmac_md5_key[16]; extern unsigned char shared_hmac_md5_key[16];
extern void hmac_md5(size_t size, const unsigned char* bytes, extern void hmac_md5(size_t size, const unsigned char* bytes,
unsigned char digest[16]); unsigned char digest[16]);
extern const char* md5_digest_print(const unsigned char digest[16]);
// Initializes RNGs for bro_random() and MD5 usage. If seed is given, then // Initializes RNGs for bro_random() and MD5 usage. If seed is given, then
// it is used (to provide determinism). If load_file is given, the seeds // it is used (to provide determinism). If load_file is given, the seeds
// (both random & MD5) are loaded from that file. This takes precedence // (both random & MD5) are loaded from that file. This takes precedence

View file

@ -0,0 +1,4 @@
f97c5d29941bfb1b2fdab0874906ab82
7b0391feb2e0cd271f1cf39aafb4376f
f97c5d29941bfb1b2fdab0874906ab82
7b0391feb2e0cd271f1cf39aafb4376f

View file

@ -0,0 +1,4 @@
fe05bcdcdc4928012781a5f1a2a77cbb5398e106
3e949019500deb1369f13d9644d420d3a920aa5e
fe05bcdcdc4928012781a5f1a2a77cbb5398e106
3e949019500deb1369f13d9644d420d3a920aa5e

View file

@ -0,0 +1,4 @@
7692c3ad3540bb803c020b3aee66cd8887123234ea0c6e7143c0add73ff431ed
4592092e1061c7ea85af2aed194621cc17a2762bae33a79bf8ce33fd0168b801
7692c3ad3540bb803c020b3aee66cd8887123234ea0c6e7143c0add73ff431ed
4592092e1061c7ea85af2aed194621cc17a2762bae33a79bf8ce33fd0168b801

View file

@ -0,0 +1,4 @@
opened
write 0
write 3
write 6

View file

@ -0,0 +1,4 @@
opened
write 1
write 4
write 7

View file

@ -0,0 +1,4 @@
opened
write 2
write 5
write 8

View file

@ -0,0 +1,6 @@
opened
write 0
opened
write 3
opened
write 6

View file

@ -0,0 +1,6 @@
opened
write 1
opened
write 4
opened
write 7

View file

@ -0,0 +1,6 @@
opened
write 2
opened
write 5
opened
write 8

View file

@ -0,0 +1,8 @@
#separator \x09
#set_separator ,
#empty_field (empty)
#unset_field -
#path ssl
#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p version cipher server_name session_id subject issuer_subject not_valid_before not_valid_after last_alert
#types time string addr port addr port string string string string string string time time string
1335538392.319381 UWkUyAuUGXf 192.168.1.105 62045 74.125.224.79 443 TLSv10 TLS_ECDHE_RSA_WITH_RC4_128_SHA ssl.gstatic.com - CN=*.gstatic.com,O=Google Inc,L=Mountain View,ST=California,C=US CN=Google Internet Authority,O=Google Inc,C=US 1334102677.000000 1365639277.000000 -

Binary file not shown.

View file

@ -0,0 +1,16 @@
# @TEST-EXEC: bro -b %INPUT >output
# @TEST-EXEC: btest-diff output
print md5_hash("one");
print md5_hash("one", "two", "three");
md5_hash_init("a");
md5_hash_init("b");
md5_hash_update("a", "one");
md5_hash_update("b", "one");
md5_hash_update("b", "two");
md5_hash_update("b", "three");
print md5_hash_finish("a");
print md5_hash_finish("b");

View file

@ -0,0 +1,16 @@
# @TEST-EXEC: bro -b %INPUT >output
# @TEST-EXEC: btest-diff output
print sha1_hash("one");
print sha1_hash("one", "two", "three");
sha1_hash_init("a");
sha1_hash_init("b");
sha1_hash_update("a", "one");
sha1_hash_update("b", "one");
sha1_hash_update("b", "two");
sha1_hash_update("b", "three");
print sha1_hash_finish("a");
print sha1_hash_finish("b");

View file

@ -0,0 +1,16 @@
# @TEST-EXEC: bro -b %INPUT >output
# @TEST-EXEC: btest-diff output
print sha256_hash("one");
print sha256_hash("one", "two", "three");
sha256_hash_init("a");
sha256_hash_init("b");
sha256_hash_update("a", "one");
sha256_hash_update("b", "one");
sha256_hash_update("b", "two");
sha256_hash_update("b", "three");
print sha256_hash_finish("a");
print sha256_hash_finish("b");

View file

@ -0,0 +1,49 @@
# This checks that the interactions between open-file caching and
# serialization works ok. In the first case, all files can fit
# in the cache, but get serialized before every write. In the
# second case, files are eventually forced out of the cache and
# undergo serialization, which requires re-opening.
# @TEST-EXEC: bro -b %INPUT "test_file_prefix=one"
# @TEST-EXEC: btest-diff one0
# @TEST-EXEC: btest-diff one1
# @TEST-EXEC: btest-diff one2
# @TEST-EXEC: bro -b %INPUT "test_file_prefix=two" "max_files_in_cache=2"
# @TEST-EXEC: btest-diff two0
# @TEST-EXEC: btest-diff two1
# @TEST-EXEC: btest-diff two2
const test_file_prefix = "" &redef;
global file_table: table[string] of file;
global iterations: vector of count = vector(0,1,2,3,4,5,6,7,8);
function write_to_file(c: count)
{
local f: file;
# Take turns writing across three output files.
local filename = fmt("%s%s", test_file_prefix, c % 3 );
if ( filename in file_table )
f = file_table[filename];
else
{
f = open(filename);
file_table[filename] = f;
}
# This when block is a trick to get the frame cloned
# and thus serialize the local file value
when ( local s = fmt("write %d", c) )
print f, s;
}
event file_opened(f: file)
{
print f, "opened";
}
event bro_init()
{
for ( i in iterations )
write_to_file(iterations[i]);
}

View file

@ -0,0 +1,4 @@
# This tests a normal SSL connection and the log it outputs.
# @TEST-EXEC: bro -r $TRACES/tls-conn-with-extensions.trace %INPUT
# @TEST-EXEC: btest-diff ssl.log