Merge remote-tracking branch 'origin/topic/jsiwek/custom-b64-alphabet'

* origin/topic/jsiwek/custom-b64-alphabet:
  Add decode_base64_custom BiF to allow alternate base64 alphabets.

Simplified the code a little bit.

Closes #670.
This commit is contained in:
Robin Sommer 2011-11-15 17:03:23 -08:00
commit 8de3614afa
5 changed files with 86 additions and 20 deletions

View file

@ -1,14 +1,27 @@
#include "config.h" #include "config.h"
#include "Base64.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 ) static bool default_table_initialized = false;
return;
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; int i;
for ( i = 0; i < 256; ++i ) for ( i = 0; i < 256; ++i )
@ -16,28 +29,36 @@ static void init_base64_table()
for ( i = 0; i < 26; ++i ) for ( i = 0; i < 26; ++i )
{ {
base64_table['A' + i] = i; base64_table[int(alphabet[0 + i])] = i;
base64_table['a' + i] = i + 26; base64_table[int(alphabet[26 + i])] = i + 26;
} }
for ( i = 0; i < 10; ++i ) 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. // Casts to avoid compiler warnings.
base64_table[int('+')] = 62; base64_table[int(alphabet[62])] = 62;
base64_table[int('/')] = 63; base64_table[int(alphabet[63])] = 63;
base64_table[int('=')] = 0; 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_group_next = 0;
base64_padding = base64_after_padding = 0; base64_padding = base64_after_padding = 0;
errored = 0; errored = 0;
analyzer = arg_analyzer; 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 Base64Decoder::Decode(int len, const char* data, int* pblen, char** pbuf)
{ {
int blen; int blen;
@ -142,13 +163,21 @@ int Base64Decoder::Done(int* pblen, char** pbuf)
return 0; 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 buf_len = int((s->Len() + 3) / 4) * 3 + 1;
int rlen2, rlen = buf_len; int rlen2, rlen = buf_len;
char* rbuf2, *rbuf = new char[rlen]; 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 ) if ( dec.Decode(s->Len(), (const char*) s->Bytes(), &rlen, &rbuf) == -1 )
goto err; goto err;

View file

@ -13,11 +13,11 @@
class Base64Decoder { class Base64Decoder {
public: public:
// <analyzer> is used for error reporting, and it should be zero // <analyzer> is used for error reporting, and it should be zero when
// when the decoder is called by the built-in function // the decoder is called by the built-in function decode_base64().
// decode_base64(). // Empty alphabet indicates the default base64 alphabet.
Base64Decoder(Analyzer* analyzer); Base64Decoder(Analyzer* analyzer, const string& alphabet = "");
~Base64Decoder() { } ~Base64Decoder();
// A note on Decode(): // A note on Decode():
// //
@ -57,8 +57,13 @@ protected:
int base64_after_padding; int base64_after_padding;
int errored; // if true, we encountered an error - skip further processing int errored; // if true, we encountered an error - skip further processing
Analyzer* analyzer; 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 */ #endif /* base64_h */

View file

@ -1860,6 +1860,18 @@ function decode_base64%(s: string%): string
} }
%} %}
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" #include "DCE_RPC.h"

View file

@ -0,0 +1,6 @@
bro
bro
bro
bro
bro
bro

View file

@ -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);