mirror of
https://github.com/zeek/zeek.git
synced 2025-10-05 08:08:19 +00:00
add base64-encode functionality and bif.
This allows replacing an ugly openssl-call from one of the policy scripts. The openssl call is now replaced with a still-but-less-ugly call to base64_encode. I do not know if I split the Base64 classes in a "smart" way... :)
This commit is contained in:
parent
a2556642e6
commit
5e8e12182a
5 changed files with 158 additions and 21 deletions
|
@ -67,11 +67,6 @@ export {
|
|||
## (especially with large file transfers).
|
||||
const disable_analyzer_after_detection = T &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;
|
||||
|
||||
## The maximum amount of time a script can delay records from being logged.
|
||||
const max_log_delay = 15secs &redef;
|
||||
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
##! 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
|
||||
|
@ -35,6 +31,7 @@ event ssl_established(c: connection) &priority=5
|
|||
{
|
||||
if ( ! c$ssl?$cert )
|
||||
return;
|
||||
|
||||
if ( ! addr_matches_host(c$id$resp_h, extract_certs_pem) )
|
||||
return;
|
||||
|
||||
|
@ -42,8 +39,24 @@ event ssl_established(c: connection) &priority=5
|
|||
# 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);
|
||||
local filename = Site::is_local_addr(c$id$resp_h) ? "certs-local.pem" : "certs-remote.pem";
|
||||
local outfile = open_for_append(filename);
|
||||
|
||||
print outfile, "-----BEGIN CERTIFICATE-----";
|
||||
|
||||
# encode to base64 and format to fit 50 lines. Otherwise openssl won't like it later.
|
||||
local lines = split_all(encode_base64(c$ssl$cert), /.{50}/);
|
||||
local i = 1;
|
||||
for ( line in lines )
|
||||
{
|
||||
if ( byte_len(lines[i]) > 0 )
|
||||
{
|
||||
print outfile, lines[i];
|
||||
}
|
||||
i+=1;
|
||||
}
|
||||
|
||||
print outfile, "-----END CERTIFICATE-----";
|
||||
print outfile, "";
|
||||
close(outfile);
|
||||
}
|
||||
|
|
|
@ -1,8 +1,59 @@
|
|||
#include "config.h"
|
||||
#include "Base64.h"
|
||||
#include <math.h>
|
||||
|
||||
int Base64Decoder::default_base64_table[256];
|
||||
const string Base64Decoder::default_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
const string Base64::default_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
Base64Encoder::Base64Encoder(const string& arg_alphabet)
|
||||
{
|
||||
if ( arg_alphabet.size() > 0 )
|
||||
{
|
||||
assert(arg_alphabet.size() == 64);
|
||||
alphabet = arg_alphabet;
|
||||
}
|
||||
else
|
||||
{
|
||||
alphabet = default_alphabet;
|
||||
}
|
||||
}
|
||||
|
||||
void Base64Encoder::Encode(int len, const unsigned char* data, int* pblen, char** pbuf)
|
||||
{
|
||||
int blen;
|
||||
char *buf;
|
||||
|
||||
if ( ! pbuf )
|
||||
reporter->InternalError("nil pointer to encoding result buffer");
|
||||
|
||||
if ( *pbuf && (*pblen % 4 != 0) )
|
||||
reporter->InternalError("Base64 encode buffer not a multiple of 4");
|
||||
|
||||
if ( *pbuf )
|
||||
{
|
||||
buf = *pbuf;
|
||||
blen = *pblen;
|
||||
}
|
||||
else
|
||||
{
|
||||
blen = int( 4 * ceil ( (double) len / 3 ) );
|
||||
*pbuf = buf = new char[blen];
|
||||
*pblen = blen;
|
||||
}
|
||||
|
||||
for ( int i = 0, j = 0; (i < len) && ( j < blen ); )
|
||||
{
|
||||
uint32_t bit32 = ( ( i < len ? data[i++] : 0 ) << 16 ) +
|
||||
( ( i < len ? data[i++] : 0 & i++ ) << 8 ) +
|
||||
( i < len ? data[i++] : 0 & i++ );
|
||||
|
||||
buf[j++] = alphabet[(bit32 >> 18) & 0x3f];
|
||||
buf[j++] = alphabet[(bit32 >> 12) & 0x3f];
|
||||
buf[j++] = ( i == (len+2) ) ? '=' : alphabet[(bit32 >> 6) & 0x3f];
|
||||
buf[j++] = ( i >= (len+1) ) ? '=' : alphabet[bit32 & 0x3f];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int* Base64Decoder::InitBase64Table(const string& alphabet)
|
||||
{
|
||||
|
@ -44,6 +95,8 @@ int* Base64Decoder::InitBase64Table(const string& alphabet)
|
|||
return base64_table;
|
||||
}
|
||||
|
||||
|
||||
|
||||
Base64Decoder::Base64Decoder(Analyzer* arg_analyzer, const string& alphabet)
|
||||
{
|
||||
base64_table = InitBase64Table(alphabet.size() ? alphabet : default_alphabet);
|
||||
|
@ -195,3 +248,21 @@ err:
|
|||
delete [] rbuf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
BroString* encode_base64(const BroString* s, const BroString* a)
|
||||
{
|
||||
if ( a && a->Len() != 64 )
|
||||
{
|
||||
reporter->Error("base64 alphabet is not 64 characters: %s",
|
||||
a->CheckString());
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* outbuf = 0;
|
||||
int outlen = 0;
|
||||
Base64Encoder enc;
|
||||
enc.Encode(s->Len(), (const unsigned char*) s->Bytes(), &outlen, &outbuf);
|
||||
|
||||
return new BroString(1, (u_char*)outbuf, outlen);
|
||||
}
|
||||
|
||||
|
|
26
src/Base64.h
26
src/Base64.h
|
@ -11,7 +11,23 @@
|
|||
|
||||
// Maybe we should have a base class for generic decoders?
|
||||
|
||||
class Base64Decoder {
|
||||
class Base64 {
|
||||
public:
|
||||
protected:
|
||||
static const string default_alphabet;
|
||||
};
|
||||
|
||||
|
||||
class Base64Encoder : public Base64 {
|
||||
public:
|
||||
Base64Encoder(const string& arg_alphabet = "");
|
||||
void Encode(int len, const unsigned char* data, int* blen, char** buf);
|
||||
protected:
|
||||
string alphabet;
|
||||
|
||||
};
|
||||
|
||||
class Base64Decoder : public Base64 {
|
||||
public:
|
||||
// <analyzer> is used for error reporting, and it should be zero when
|
||||
// the decoder is called by the built-in function decode_base64().
|
||||
|
@ -51,19 +67,19 @@ protected:
|
|||
char error_msg[256];
|
||||
|
||||
protected:
|
||||
static int* InitBase64Table(const string& alphabet);
|
||||
static int default_base64_table[256];
|
||||
char base64_group[4];
|
||||
int base64_group_next;
|
||||
int base64_padding;
|
||||
int base64_after_padding;
|
||||
int* base64_table;
|
||||
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, const BroString* a = 0);
|
||||
BroString* encode_base64(const BroString* s, const BroString* a = 0);
|
||||
|
||||
#endif /* base64_h */
|
||||
|
|
42
src/bro.bif
42
src/bro.bif
|
@ -2868,6 +2868,48 @@ function bytestring_to_hexstr%(bytestring: string%): string
|
|||
return new StringVal(hexstr);
|
||||
%}
|
||||
|
||||
## Encodes a Base64-encoded string.
|
||||
##
|
||||
## s: The string to encode
|
||||
##
|
||||
## Returns: The encoded version of *s*.
|
||||
##
|
||||
## .. bro:see:: encode_base64_custom
|
||||
function encode_base64%(s: string%): string
|
||||
%{
|
||||
BroString* t = encode_base64(s->AsString());
|
||||
if ( t )
|
||||
return new StringVal(t);
|
||||
else
|
||||
{
|
||||
reporter->Error("error in encoding string %s", s->CheckString());
|
||||
return new StringVal("");
|
||||
}
|
||||
%}
|
||||
|
||||
## Encodes a Base64-encoded string with a custom alphabet.
|
||||
##
|
||||
## s: The string to encode
|
||||
##
|
||||
## a: The custom alphabet. The empty string indicates the default alphabet. The
|
||||
## length of *a* must be 64. For example, a custom alphabet could be
|
||||
## ``"!#$%&/(),-.:;<>@[]^ `_{|}~abcdefghijklmnopqrstuvwxyz0123456789+?"``.
|
||||
##
|
||||
## Returns: The encoded version of *s*.
|
||||
##
|
||||
## .. bro:see:: encode_base64
|
||||
function encode_base64_custom%(s: string, a: string%): string
|
||||
%{
|
||||
BroString* t = encode_base64(s->AsString(), a->AsString());
|
||||
if ( t )
|
||||
return new StringVal(t);
|
||||
else
|
||||
{
|
||||
reporter->Error("error in encoding string %s", s->CheckString());
|
||||
return new StringVal("");
|
||||
}
|
||||
%}
|
||||
|
||||
## Decodes a Base64-encoded string.
|
||||
##
|
||||
## s: The Base64-encoded string.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue