mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 08:08:19 +00:00
Merge remote-tracking branch 'origin/master' into topic/johanna/clone
This commit is contained in:
commit
e7c80ae741
68 changed files with 395 additions and 754 deletions
323
src/File.cc
323
src/File.cc
|
@ -18,15 +18,10 @@
|
|||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/pem.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "File.h"
|
||||
#include "Type.h"
|
||||
#include "Timer.h"
|
||||
#include "Expr.h"
|
||||
#include "NetVar.h"
|
||||
#include "Net.h"
|
||||
|
@ -34,46 +29,6 @@
|
|||
#include "Event.h"
|
||||
#include "Reporter.h"
|
||||
|
||||
// Timer which on dispatching rotates the file.
|
||||
class RotateTimer : public Timer {
|
||||
public:
|
||||
RotateTimer(double t, BroFile* f, bool arg_raise) : Timer(t, TIMER_ROTATE)
|
||||
{ file = f; raise = arg_raise; name = copy_string(f->Name()); }
|
||||
~RotateTimer();
|
||||
|
||||
void Dispatch(double t, int is_expire);
|
||||
|
||||
protected:
|
||||
BroFile* file;
|
||||
bool raise;
|
||||
const char* name;
|
||||
};
|
||||
|
||||
RotateTimer::~RotateTimer()
|
||||
{
|
||||
if ( file->rotate_timer == this )
|
||||
file->rotate_timer = 0;
|
||||
|
||||
delete [] name;
|
||||
}
|
||||
|
||||
void RotateTimer::Dispatch(double t, int is_expire)
|
||||
{
|
||||
file->rotate_timer = 0;
|
||||
|
||||
if ( ! is_expire )
|
||||
{
|
||||
if ( raise )
|
||||
{
|
||||
Ref(file);
|
||||
mgr.QueueEvent(rotate_interval, {new Val(file)});
|
||||
}
|
||||
|
||||
file->InstallRotateTimer();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// The following could in principle be part of a "file manager" object.
|
||||
|
||||
#define MAX_FILE_CACHE_SIZE 512
|
||||
|
@ -81,9 +36,6 @@ static int num_files_in_cache = 0;
|
|||
static BroFile* head = 0;
|
||||
static BroFile* tail = 0;
|
||||
|
||||
double BroFile::default_rotation_interval = 0;
|
||||
double BroFile::default_rotation_size = 0;
|
||||
|
||||
// Maximizes the number of open file descriptors and returns the number
|
||||
// that we should use for the cache.
|
||||
static int maximize_num_fds()
|
||||
|
@ -119,9 +71,6 @@ BroFile::BroFile(FILE* arg_f)
|
|||
name = access = 0;
|
||||
t = base_type(TYPE_STRING);
|
||||
is_open = (f != 0);
|
||||
|
||||
if ( f )
|
||||
UpdateFileSize();
|
||||
}
|
||||
|
||||
BroFile::BroFile(FILE* arg_f, const char* arg_name, const char* arg_access)
|
||||
|
@ -132,9 +81,6 @@ BroFile::BroFile(FILE* arg_f, const char* arg_name, const char* arg_access)
|
|||
access = copy_string(arg_access);
|
||||
t = base_type(TYPE_STRING);
|
||||
is_open = (f != 0);
|
||||
|
||||
if ( f )
|
||||
UpdateFileSize();
|
||||
}
|
||||
|
||||
BroFile::BroFile(const char* arg_name, const char* arg_access, BroType* arg_t)
|
||||
|
@ -193,16 +139,6 @@ bool BroFile::Open(FILE* file, const char* mode)
|
|||
|
||||
f = file;
|
||||
|
||||
if ( default_rotation_interval &&
|
||||
(! attrs || ! attrs->FindAttr(ATTR_ROTATE_INTERVAL)) )
|
||||
rotate_interval = default_rotation_interval;
|
||||
|
||||
if ( default_rotation_size &&
|
||||
(! attrs || ! attrs->FindAttr(ATTR_ROTATE_SIZE)) )
|
||||
rotate_size = default_rotation_size;
|
||||
|
||||
InstallRotateTimer();
|
||||
|
||||
if ( ! f )
|
||||
{
|
||||
if ( ! mode )
|
||||
|
@ -221,7 +157,6 @@ bool BroFile::Open(FILE* file, const char* mode)
|
|||
is_open = okay_to_manage = 1;
|
||||
|
||||
InsertAtBeginning();
|
||||
UpdateFileSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -243,7 +178,6 @@ BroFile::~BroFile()
|
|||
|
||||
delete [] name;
|
||||
delete [] access;
|
||||
delete [] cipher_buffer;
|
||||
|
||||
#ifdef USE_PERFTOOLS_DEBUG
|
||||
heap_checker->UnIgnoreObject(this);
|
||||
|
@ -255,18 +189,11 @@ void BroFile::Init()
|
|||
is_open = okay_to_manage = is_in_cache = 0;
|
||||
position = 0;
|
||||
next = prev = 0;
|
||||
rotate_timer = 0;
|
||||
rotate_interval = 0.0;
|
||||
rotate_size = current_size = 0.0;
|
||||
open_time = 0;
|
||||
attrs = 0;
|
||||
buffered = true;
|
||||
print_hook = true;
|
||||
raw_output = false;
|
||||
t = 0;
|
||||
pub_key = 0;
|
||||
cipher_ctx = 0;
|
||||
cipher_buffer = 0;
|
||||
|
||||
#ifdef USE_PERFTOOLS_DEBUG
|
||||
heap_checker->IgnoreObject(this);
|
||||
|
@ -316,8 +243,6 @@ FILE* BroFile::BringIntoCache()
|
|||
return 0;
|
||||
}
|
||||
|
||||
UpdateFileSize();
|
||||
|
||||
if ( fseek(f, position, SEEK_SET) < 0 )
|
||||
{
|
||||
bro_strerror_r(errno, buf, sizeof(buf));
|
||||
|
@ -325,7 +250,6 @@ FILE* BroFile::BringIntoCache()
|
|||
}
|
||||
|
||||
InsertAtBeginning();
|
||||
|
||||
RaiseOpenEvent();
|
||||
|
||||
return f;
|
||||
|
@ -355,17 +279,9 @@ void BroFile::SetBuf(bool arg_buffered)
|
|||
|
||||
int BroFile::Close()
|
||||
{
|
||||
if ( rotate_timer )
|
||||
{
|
||||
timer_mgr->Cancel(rotate_timer);
|
||||
rotate_timer = 0;
|
||||
}
|
||||
|
||||
if ( ! is_open )
|
||||
return 1;
|
||||
|
||||
FinishEncrypt();
|
||||
|
||||
// Do not close stdin/stdout/stderr.
|
||||
if ( f == stdin || f == stdout || f == stderr )
|
||||
return 0;
|
||||
|
@ -516,33 +432,8 @@ void BroFile::SetAttrs(Attributes* arg_attrs)
|
|||
attrs = arg_attrs;
|
||||
Ref(attrs);
|
||||
|
||||
Attr* ef = attrs->FindAttr(ATTR_ROTATE_INTERVAL);
|
||||
if ( ef )
|
||||
rotate_interval = ef->AttrExpr()->ExprVal()->AsInterval();
|
||||
|
||||
ef = attrs->FindAttr(ATTR_ROTATE_SIZE);
|
||||
if ( ef )
|
||||
rotate_size = ef->AttrExpr()->ExprVal()->AsDouble();
|
||||
|
||||
ef = attrs->FindAttr(ATTR_ENCRYPT);
|
||||
if ( ef )
|
||||
{
|
||||
if ( ef->AttrExpr() )
|
||||
InitEncrypt(ef->AttrExpr()->ExprVal()->AsString()->CheckString());
|
||||
else
|
||||
InitEncrypt(opt_internal_string("log_encryption_key")->CheckString());
|
||||
}
|
||||
|
||||
if ( attrs->FindAttr(ATTR_RAW_OUTPUT) )
|
||||
EnableRawOutput();
|
||||
|
||||
InstallRotateTimer();
|
||||
}
|
||||
|
||||
void BroFile::SetRotateInterval(double secs)
|
||||
{
|
||||
rotate_interval = secs;
|
||||
InstallRotateTimer();
|
||||
}
|
||||
|
||||
RecordVal* BroFile::Rotate()
|
||||
|
@ -576,178 +467,17 @@ RecordVal* BroFile::Rotate()
|
|||
return info;
|
||||
}
|
||||
|
||||
void BroFile::InstallRotateTimer()
|
||||
{
|
||||
if ( terminating )
|
||||
return;
|
||||
|
||||
if ( rotate_timer )
|
||||
{
|
||||
timer_mgr->Cancel(rotate_timer);
|
||||
rotate_timer = 0;
|
||||
}
|
||||
|
||||
if ( rotate_interval )
|
||||
{
|
||||
// When this is called for the first time, network_time can
|
||||
// still be zero. If so, we set a timer which fires
|
||||
// immediately but doesn't rotate when it expires.
|
||||
|
||||
if ( ! network_time )
|
||||
rotate_timer = new RotateTimer(1, this, false);
|
||||
else
|
||||
{
|
||||
if ( ! open_time )
|
||||
open_time = network_time;
|
||||
|
||||
const char* base_time = log_rotate_base_time ?
|
||||
log_rotate_base_time->AsString()->CheckString() : 0;
|
||||
|
||||
double base = parse_rotate_base_time(base_time);
|
||||
double delta_t =
|
||||
calc_next_rotate(network_time, rotate_interval, base);
|
||||
rotate_timer = new RotateTimer(network_time + delta_t,
|
||||
this, true);
|
||||
}
|
||||
|
||||
timer_mgr->Add(rotate_timer);
|
||||
}
|
||||
}
|
||||
|
||||
void BroFile::SetDefaultRotation(double interval, double max_size)
|
||||
{
|
||||
for ( BroFile* f = head; f; f = f->next )
|
||||
{
|
||||
if ( ! (f->attrs && f->attrs->FindAttr(ATTR_ROTATE_INTERVAL)) )
|
||||
{
|
||||
f->rotate_interval = interval;
|
||||
f->InstallRotateTimer();
|
||||
}
|
||||
|
||||
if ( ! (f->attrs && f->attrs->FindAttr(ATTR_ROTATE_SIZE)) )
|
||||
f->rotate_size = max_size;
|
||||
}
|
||||
|
||||
default_rotation_interval = interval;
|
||||
default_rotation_size = max_size;
|
||||
}
|
||||
|
||||
void BroFile::CloseCachedFiles()
|
||||
{
|
||||
BroFile* next;
|
||||
for ( BroFile* f = head; f; f = next )
|
||||
{
|
||||
// Send final rotate events (immediately).
|
||||
if ( f->rotate_interval )
|
||||
{
|
||||
Ref(f);
|
||||
Event* event = new Event(::rotate_interval, {new Val(f)});
|
||||
mgr.Dispatch(event, true);
|
||||
}
|
||||
|
||||
if ( f->rotate_size )
|
||||
{
|
||||
Ref(f);
|
||||
Event* event = new ::Event(::rotate_size, {new Val(f)});
|
||||
mgr.Dispatch(event, true);
|
||||
}
|
||||
|
||||
next = f->next;
|
||||
if ( f->is_in_cache )
|
||||
f->Close();
|
||||
}
|
||||
}
|
||||
|
||||
void BroFile::InitEncrypt(const char* keyfile)
|
||||
{
|
||||
if ( ! (pub_key || keyfile) )
|
||||
return;
|
||||
|
||||
if ( ! pub_key )
|
||||
{
|
||||
FILE* key = fopen(keyfile, "r");
|
||||
|
||||
if ( ! key )
|
||||
{
|
||||
reporter->Error("can't open key file %s: %s", keyfile, strerror(errno));
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
pub_key = PEM_read_PUBKEY(key, 0, 0, 0);
|
||||
if ( ! pub_key )
|
||||
{
|
||||
reporter->Error("can't read key from %s: %s", keyfile,
|
||||
ERR_error_string(ERR_get_error(), 0));
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Depending on the OpenSSL version, EVP_*_cbc()
|
||||
// returns a const or a non-const.
|
||||
EVP_CIPHER* cipher_type = (EVP_CIPHER*) EVP_bf_cbc();
|
||||
cipher_ctx = EVP_CIPHER_CTX_new();
|
||||
|
||||
unsigned char secret[EVP_PKEY_size(pub_key)];
|
||||
unsigned char* psecret = secret;
|
||||
unsigned int secret_len;
|
||||
|
||||
int iv_len = EVP_CIPHER_iv_length(cipher_type);
|
||||
unsigned char iv[iv_len];
|
||||
|
||||
if ( ! EVP_SealInit(cipher_ctx, cipher_type, &psecret,
|
||||
(int*) &secret_len, iv, &pub_key, 1) )
|
||||
{
|
||||
reporter->Error("can't init cipher context for %s: %s", keyfile,
|
||||
ERR_error_string(ERR_get_error(), 0));
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
secret_len = htonl(secret_len);
|
||||
|
||||
if ( fwrite("BROENC1", 7, 1, f) < 1 ||
|
||||
fwrite(&secret_len, sizeof(secret_len), 1, f) < 1 ||
|
||||
fwrite(secret, ntohl(secret_len), 1, f) < 1 ||
|
||||
fwrite(iv, iv_len, 1, f) < 1 )
|
||||
{
|
||||
reporter->Error("can't write header to log file %s: %s",
|
||||
name, strerror(errno));
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
int buf_size = MIN_BUFFER_SIZE + EVP_CIPHER_block_size(cipher_type);
|
||||
cipher_buffer = new unsigned char[buf_size];
|
||||
}
|
||||
|
||||
void BroFile::FinishEncrypt()
|
||||
{
|
||||
if ( ! is_open )
|
||||
return;
|
||||
|
||||
if ( ! pub_key )
|
||||
return;
|
||||
|
||||
if ( cipher_ctx )
|
||||
{
|
||||
int outl;
|
||||
EVP_SealFinal(cipher_ctx, cipher_buffer, &outl);
|
||||
|
||||
if ( outl && fwrite(cipher_buffer, outl, 1, f) < 1 )
|
||||
{
|
||||
reporter->Error("write error for %s: %s",
|
||||
name, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
EVP_CIPHER_CTX_free(cipher_ctx);
|
||||
cipher_ctx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int BroFile::Write(const char* data, int len)
|
||||
{
|
||||
if ( ! is_open )
|
||||
|
@ -759,50 +489,9 @@ int BroFile::Write(const char* data, int len)
|
|||
if ( ! len )
|
||||
len = strlen(data);
|
||||
|
||||
if ( cipher_ctx )
|
||||
{
|
||||
while ( len )
|
||||
{
|
||||
int outl;
|
||||
int inl = min(+MIN_BUFFER_SIZE, len);
|
||||
|
||||
if ( ! EVP_SealUpdate(cipher_ctx, cipher_buffer, &outl,
|
||||
(unsigned char*)data, inl) )
|
||||
{
|
||||
reporter->Error("encryption error for %s: %s",
|
||||
name,
|
||||
ERR_error_string(ERR_get_error(), 0));
|
||||
Close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ( outl && fwrite(cipher_buffer, outl, 1, f) < 1 )
|
||||
{
|
||||
reporter->Error("write error for %s: %s",
|
||||
name, strerror(errno));
|
||||
Close();
|
||||
return 0;
|
||||
}
|
||||
|
||||
data += inl;
|
||||
len -= inl;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ( fwrite(data, len, 1, f) < 1 )
|
||||
return false;
|
||||
|
||||
if ( rotate_size && current_size < rotate_size && current_size + len >= rotate_size )
|
||||
{
|
||||
mgr.QueueEvent(::rotate_size, {new Val(this)});
|
||||
}
|
||||
|
||||
// This does not work if we seek around. But none of the logs does that
|
||||
// and we avoid stat()'ing the file all the time.
|
||||
current_size += len;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -816,17 +505,17 @@ void BroFile::RaiseOpenEvent()
|
|||
mgr.Dispatch(event, true);
|
||||
}
|
||||
|
||||
void BroFile::UpdateFileSize()
|
||||
double BroFile::Size()
|
||||
{
|
||||
fflush(f);
|
||||
struct stat s;
|
||||
if ( fstat(fileno(f), &s) < 0 )
|
||||
{
|
||||
reporter->Error("can't stat fd for %s: %s", name, strerror(errno));
|
||||
current_size = 0;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
current_size = double(s.st_size);
|
||||
return s.st_size;
|
||||
}
|
||||
|
||||
bool BroFile::Serialize(SerialInfo* info) const
|
||||
|
@ -887,10 +576,6 @@ BroFile* BroFile::Unserialize(UnserialInfo* info)
|
|||
// *never* be closed anymore (as long the file cache does not overflow).
|
||||
Ref(file);
|
||||
|
||||
// We deliberately override log rotation attributes with our defaults.
|
||||
file->rotate_interval = log_rotate_interval;
|
||||
file->rotate_size = log_max_size;
|
||||
file->InstallRotateTimer();
|
||||
file->SetBuf(file->buffered);
|
||||
|
||||
return file;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue