mirror of
https://github.com/zeek/zeek.git
synced 2025-10-11 02:58:20 +00:00
Kerberos analyzer updates:
- Split up the (quite length) krb-protocol.pac into krb-protocol, krb-defs, krb-types and krb-padata - Add some supporting types to get rid of awkward and difficult to read case true/false statements - Clean up the conversion code in krb-analyzer.pac
This commit is contained in:
parent
1f41c0470c
commit
2d11fafd5e
6 changed files with 565 additions and 591 deletions
|
@ -4,8 +4,8 @@
|
|||
|
||||
|
||||
%header{
|
||||
Val* GetTimeFromAsn1(const KRB_Time* atime);
|
||||
Val* GetTimeFromAsn1(StringVal* atime);
|
||||
Val* GetTimeFromAsn1(const KRB_Time* atime, int64 usecs);
|
||||
Val* GetTimeFromAsn1(StringVal* atime, int64 usecs);
|
||||
|
||||
Val* GetStringFromPrincipalName(const KRB_Principal_Name* pname);
|
||||
|
||||
|
@ -13,15 +13,24 @@ Val* asn1_integer_to_val(const ASN1Encoding* i, TypeTag t);
|
|||
Val* asn1_integer_to_val(const ASN1Integer* i, TypeTag t);
|
||||
|
||||
RecordVal* proc_krb_kdc_options(const KRB_KDC_Options* opts);
|
||||
RecordVal* proc_krb_kdc_req_arguments(KRB_KDC_REQ* msg, const BroAnalyzer bro_analyzer);
|
||||
|
||||
VectorVal* proc_padata(const KRB_PA_Data_Sequence* data, const BroAnalyzer bro_analyzer, bool is_error);
|
||||
|
||||
VectorVal* proc_cipher_list(const Array* list);
|
||||
VectorVal* proc_host_address_list(const KRB_Host_Addresses* list);
|
||||
VectorVal* proc_tickets(const KRB_Ticket_Sequence* list);
|
||||
|
||||
bool proc_error_arguments(RecordVal* rv, const std::vector<KRB_ERROR_Arg*>* args, int64 error_code);
|
||||
%}
|
||||
|
||||
%code{
|
||||
Val* GetTimeFromAsn1(const KRB_Time* atime)
|
||||
Val* GetTimeFromAsn1(const KRB_Time* atime, int64 usecs)
|
||||
{
|
||||
return GetTimeFromAsn1(bytestring_to_val(atime->time()));
|
||||
return GetTimeFromAsn1(bytestring_to_val(atime->time()), usecs);
|
||||
}
|
||||
|
||||
Val* GetTimeFromAsn1(StringVal* atime)
|
||||
Val* GetTimeFromAsn1(StringVal* atime, int64 usecs)
|
||||
{
|
||||
time_t lResult = 0;
|
||||
|
||||
|
@ -57,7 +66,7 @@ Val* GetTimeFromAsn1(StringVal* atime)
|
|||
if ( !lResult )
|
||||
lResult = 0;
|
||||
|
||||
return new Val(double(lResult), TYPE_TIME);
|
||||
return new Val(double(lResult + (usecs/100000)), TYPE_TIME);
|
||||
}
|
||||
|
||||
Val* GetStringFromPrincipalName(const KRB_Principal_Name* pname)
|
||||
|
@ -101,6 +110,294 @@ RecordVal* proc_krb_kdc_options(const KRB_KDC_Options* opts)
|
|||
return rv;
|
||||
}
|
||||
|
||||
VectorVal* proc_padata(const KRB_PA_Data_Sequence* data, const BroAnalyzer bro_analyzer, bool is_error)
|
||||
{
|
||||
VectorVal* vv = new VectorVal(internal_type("KRB::Type_Value_Vector")->AsVectorType());
|
||||
for ( uint i = 0; i < data->padata_elems()->size(); ++i)
|
||||
{
|
||||
KRB_PA_Data* element = (*data->padata_elems())[i];
|
||||
int64 data_type = element->data_type();
|
||||
|
||||
if ( is_error && ( data_type == 16 || data_type == 17 ) )
|
||||
data_type = 0;
|
||||
|
||||
switch( data_type )
|
||||
{
|
||||
case 1:
|
||||
// will be generated as separate event
|
||||
break;
|
||||
case 2:
|
||||
// encrypted timestamp is unreadable
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
RecordVal * type_val = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
type_val->Assign(0, new Val(element->data_type(), TYPE_COUNT));
|
||||
type_val->Assign(1, bytestring_to_val(element->pa_data_element()->pa_pw_salt()->encoding()->content()));
|
||||
vv->Assign(vv->Size(), type_val);
|
||||
break;
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
const bytestring& cert = element->pa_data_element()->pa_pk_as_req()->cert();
|
||||
|
||||
ODesc common;
|
||||
common.AddRaw("Analyzer::ANALYZER_KRB");
|
||||
common.Add(bro_analyzer->Conn()->StartTime());
|
||||
common.AddRaw("T", 1);
|
||||
bro_analyzer->Conn()->IDString(&common);
|
||||
|
||||
ODesc file_handle;
|
||||
file_handle.Add(common.Description());
|
||||
file_handle.Add(0);
|
||||
|
||||
string file_id = file_mgr->HashHandle(file_handle.Description());
|
||||
|
||||
file_mgr->DataIn(reinterpret_cast<const u_char*>(cert.data()),
|
||||
cert.length(), bro_analyzer->GetAnalyzerTag(),
|
||||
bro_analyzer->Conn(), true, file_id);
|
||||
file_mgr->EndOfFile(file_id);
|
||||
|
||||
break;
|
||||
}
|
||||
case 17:
|
||||
{
|
||||
const bytestring& cert = element->pa_data_element()->pa_pk_as_rep()->cert();
|
||||
|
||||
ODesc common;
|
||||
common.AddRaw("Analyzer::ANALYZER_KRB");
|
||||
common.Add(bro_analyzer->Conn()->StartTime());
|
||||
common.AddRaw("F", 1);
|
||||
bro_analyzer->Conn()->IDString(&common);
|
||||
|
||||
ODesc file_handle;
|
||||
file_handle.Add(common.Description());
|
||||
file_handle.Add(1);
|
||||
|
||||
string file_id = file_mgr->HashHandle(file_handle.Description());
|
||||
|
||||
file_mgr->DataIn(reinterpret_cast<const u_char*>(cert.data()),
|
||||
cert.length(), bro_analyzer->GetAnalyzerTag(),
|
||||
bro_analyzer->Conn(), false, file_id);
|
||||
file_mgr->EndOfFile(file_id);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if ( ! is_error && element->pa_data_element()->unknown().length() )
|
||||
{
|
||||
RecordVal * type_val = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
type_val->Assign(0, new Val(element->data_type(), TYPE_COUNT));
|
||||
type_val->Assign(1, bytestring_to_val(element->pa_data_element()->unknown()));
|
||||
vv->Assign(vv->Size(), type_val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return vv;
|
||||
}
|
||||
|
||||
VectorVal* proc_cipher_list(const Array* list)
|
||||
{
|
||||
VectorVal* ciphers = new VectorVal(internal_type("index_vec")->AsVectorType());
|
||||
for ( uint i = 0; i < list->data()->size(); ++i )
|
||||
ciphers->Assign(ciphers->Size(), asn1_integer_to_val((*list->data())[i], TYPE_COUNT));
|
||||
return ciphers;
|
||||
}
|
||||
|
||||
VectorVal* proc_host_address_list(const KRB_Host_Addresses* list)
|
||||
{
|
||||
VectorVal* addrs = new VectorVal(internal_type("KRB::Host_Address_Vector")->AsVectorType());
|
||||
|
||||
for ( uint i = 0; i < list->addresses()->size(); ++i )
|
||||
{
|
||||
RecordVal* addr = new RecordVal(BifType::Record::KRB::Host_Address);
|
||||
KRB_Host_Address* element = (*list->addresses())[i];
|
||||
|
||||
switch ( binary_to_int64(element->addr_type()->encoding()->content()) )
|
||||
{
|
||||
case 2:
|
||||
addr->Assign(0, new AddrVal(IPAddr(IPv4,
|
||||
(const uint32_t*) c_str(element->address()->data()->content()),
|
||||
IPAddr::Network)));
|
||||
break;
|
||||
case 24:
|
||||
addr->Assign(0, new AddrVal(IPAddr(IPv6,
|
||||
(const uint32_t*) c_str(element->address()->data()->content()),
|
||||
IPAddr::Network)));
|
||||
break;
|
||||
case 20:
|
||||
addr->Assign(1, bytestring_to_val(element->address()->data()->content()));
|
||||
break;
|
||||
default:
|
||||
RecordVal* unk = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
unk->Assign(0, asn1_integer_to_val(element->addr_type(), TYPE_COUNT));
|
||||
unk->Assign(1, bytestring_to_val(element->address()->data()->content()));
|
||||
addr->Assign(2, unk);
|
||||
break;
|
||||
}
|
||||
addrs->Assign(addrs->Size(), addr);
|
||||
}
|
||||
|
||||
return addrs;
|
||||
}
|
||||
|
||||
|
||||
VectorVal* proc_tickets(const KRB_Ticket_Sequence* list)
|
||||
{
|
||||
VectorVal* tickets = new VectorVal(internal_type("KRB::Ticket_Vector")->AsVectorType());
|
||||
for ( uint i = 0; i < list->tickets()->size(); ++i )
|
||||
{
|
||||
KRB_Ticket* element = (*list->tickets())[i];
|
||||
RecordVal* ticket = new RecordVal(BifType::Record::KRB::Ticket);
|
||||
|
||||
ticket->Assign(0, asn1_integer_to_val(element->tkt_vno()->data(), TYPE_COUNT));
|
||||
ticket->Assign(1, bytestring_to_val(element->realm()->data()->content()));
|
||||
ticket->Assign(2, GetStringFromPrincipalName(element->sname()));
|
||||
ticket->Assign(3, asn1_integer_to_val(element->enc_part()->etype()->data(), TYPE_COUNT));
|
||||
tickets->Assign(tickets->Size(), ticket);
|
||||
}
|
||||
|
||||
return tickets;
|
||||
}
|
||||
|
||||
bool proc_error_arguments(RecordVal* rv, const std::vector<KRB_ERROR_Arg*>* args, int64 error_code )
|
||||
{
|
||||
uint ctime_i = 0, ctime_usecs_i = 0, stime_i = 0, stime_usecs_i = 0;
|
||||
int64 ctime_usecs = 0, stime_usecs = 0;
|
||||
|
||||
// We need to do a pass first, to see if we have microseconds for the timestamp values, which are optional
|
||||
|
||||
for ( uint i = 0; i < args->size(); i++ )
|
||||
{
|
||||
switch ( (*args)[i]->seq_meta()->index() )
|
||||
{
|
||||
case 2:
|
||||
ctime_i = i;
|
||||
break;
|
||||
case 3:
|
||||
ctime_usecs_i = i;
|
||||
break;
|
||||
case 4:
|
||||
stime_i = i;
|
||||
break;
|
||||
case 5:
|
||||
stime_usecs_i = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ctime_usecs_i ) ctime_usecs = binary_to_int64((*args)[ctime_usecs_i]->args()->cusec()->encoding()->content());
|
||||
if ( ctime_i ) rv->Assign(2, GetTimeFromAsn1((*args)[ctime_i]->args()->ctime(), ctime_usecs));
|
||||
|
||||
if ( stime_usecs_i ) stime_usecs = binary_to_int64((*args)[stime_usecs_i]->args()->susec()->encoding()->content());
|
||||
if ( stime_i ) rv->Assign(3, GetTimeFromAsn1((*args)[stime_i]->args()->stime(), stime_usecs));
|
||||
|
||||
for ( uint i = 0; i < args->size(); i++ )
|
||||
{
|
||||
switch ( (*args)[i]->seq_meta()->index() )
|
||||
{
|
||||
case 0:
|
||||
rv->Assign(0, asn1_integer_to_val((*args)[i]->args()->pvno(), TYPE_COUNT));
|
||||
break;
|
||||
case 1:
|
||||
rv->Assign(1, asn1_integer_to_val((*args)[i]->args()->msg_type(), TYPE_COUNT));
|
||||
break;
|
||||
// ctime/stime handled above
|
||||
case 7:
|
||||
rv->Assign(5, bytestring_to_val((*args)[i]->args()->crealm()->encoding()->content()));
|
||||
break;
|
||||
case 8:
|
||||
rv->Assign(6, GetStringFromPrincipalName((*args)[i]->args()->cname()));
|
||||
break;
|
||||
case 9:
|
||||
rv->Assign(7, bytestring_to_val((*args)[i]->args()->realm()->encoding()->content()));
|
||||
break;
|
||||
case 10:
|
||||
rv->Assign(8, GetStringFromPrincipalName((*args)[i]->args()->sname()));
|
||||
break;
|
||||
case 11:
|
||||
rv->Assign(9, bytestring_to_val((*args)[i]->args()->e_text()->encoding()->content()));
|
||||
break;
|
||||
case 12:
|
||||
if ( error_code == 25 )
|
||||
rv->Assign(10, proc_padata((*args)[i]->args()->e_data()->padata(), NULL, true));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RecordVal* proc_krb_kdc_req_arguments(KRB_KDC_REQ* msg, const BroAnalyzer bro_analyzer)
|
||||
{
|
||||
RecordVal* rv = new RecordVal(BifType::Record::KRB::KDC_Request);
|
||||
|
||||
rv->Assign(0, asn1_integer_to_val(msg->pvno()->data(), TYPE_COUNT));
|
||||
rv->Assign(1, asn1_integer_to_val(msg->msg_type()->data(), TYPE_COUNT));
|
||||
|
||||
if ( msg->padata()->has_padata() )
|
||||
rv->Assign(2, proc_padata(msg->padata()->padata()->padata(), bro_analyzer, false));
|
||||
|
||||
for ( uint i = 0; i < msg->body_args()->size(); ++i )
|
||||
{
|
||||
KRB_REQ_Arg* element = (*msg->body_args())[i];
|
||||
switch ( element->seq_meta()->index() )
|
||||
{
|
||||
case 0:
|
||||
rv->Assign(3, proc_krb_kdc_options(element->data()->options()));
|
||||
break;
|
||||
case 1:
|
||||
rv->Assign(4, GetStringFromPrincipalName(element->data()->principal()));
|
||||
break;
|
||||
case 2:
|
||||
rv->Assign(5, bytestring_to_val(element->data()->realm()->encoding()->content()));
|
||||
break;
|
||||
case 3:
|
||||
rv->Assign(6, GetStringFromPrincipalName(element->data()->sname()));
|
||||
break;
|
||||
case 4:
|
||||
rv->Assign(7, GetTimeFromAsn1(element->data()->from(), 0));
|
||||
break;
|
||||
case 5:
|
||||
rv->Assign(8, GetTimeFromAsn1(element->data()->till(), 0));
|
||||
break;
|
||||
case 6:
|
||||
rv->Assign(9, GetTimeFromAsn1(element->data()->rtime(), 0));
|
||||
break;
|
||||
case 7:
|
||||
rv->Assign(10, asn1_integer_to_val(element->data()->nonce(), TYPE_COUNT));
|
||||
break;
|
||||
case 8:
|
||||
if ( element->data()->etype()->data()->size() )
|
||||
rv->Assign(11, proc_cipher_list(element->data()->etype()));
|
||||
|
||||
break;
|
||||
case 9:
|
||||
if ( element->data()->addrs()->addresses()->size() )
|
||||
rv->Assign(12, proc_host_address_list(element->data()->addrs()));
|
||||
|
||||
break;
|
||||
case 10:
|
||||
// TODO
|
||||
break;
|
||||
case 11:
|
||||
if ( element->data()->addl_tkts()->tickets()->size() )
|
||||
rv->Assign(13, proc_tickets(element->data()->addl_tkts()));
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
refine connection KRB_Conn += {
|
||||
|
@ -112,168 +409,9 @@ refine connection KRB_Conn += {
|
|||
return false;
|
||||
|
||||
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 12 ) && ! krb_tgs_req )
|
||||
return false;
|
||||
|
||||
|
||||
RecordVal* rv = new RecordVal(BifType::Record::KRB::KDC_Request);
|
||||
return false;
|
||||
|
||||
rv->Assign(0, asn1_integer_to_val(${msg.pvno.data}, TYPE_COUNT));
|
||||
rv->Assign(1, asn1_integer_to_val(${msg.msg_type.data}, TYPE_COUNT));
|
||||
|
||||
if ( ${msg.has_padata} )
|
||||
{
|
||||
VectorVal* padata = new VectorVal(internal_type("KRB::Type_Value_Vector")->AsVectorType());
|
||||
|
||||
for ( uint i = 0; i < ${msg.padata.padata_elems}->size(); ++i)
|
||||
{
|
||||
switch( ${msg.padata.padata_elems[i].data_type} )
|
||||
{
|
||||
case 1:
|
||||
// will be generated as separate event
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
RecordVal * type_val = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
type_val->Assign(0, new Val(${msg.padata.padata_elems[i].data_type}, TYPE_COUNT));
|
||||
type_val->Assign(1, bytestring_to_val(${msg.padata.padata_elems[i].pa_data_element.pa_pw_salt.encoding.content}));
|
||||
padata->Assign(padata->Size(), type_val);
|
||||
break;
|
||||
}
|
||||
case 16:
|
||||
{
|
||||
const bytestring& cert = ${msg.padata.padata_elems[i].pa_data_element.pa_pk_as_req.cert};
|
||||
|
||||
ODesc common;
|
||||
common.AddRaw("Analyzer::ANALYZER_KRB");
|
||||
common.Add(bro_analyzer()->Conn()->StartTime());
|
||||
common.AddRaw("T", 1);
|
||||
bro_analyzer()->Conn()->IDString(&common);
|
||||
|
||||
ODesc file_handle;
|
||||
file_handle.Add(common.Description());
|
||||
file_handle.Add(0);
|
||||
|
||||
string file_id = file_mgr->HashHandle(file_handle.Description());
|
||||
|
||||
file_mgr->DataIn(reinterpret_cast<const u_char*>(cert.data()),
|
||||
cert.length(), bro_analyzer()->GetAnalyzerTag(),
|
||||
bro_analyzer()->Conn(), true, file_id);
|
||||
file_mgr->EndOfFile(file_id);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if ( ${msg.padata.padata_elems[i].pa_data_element.unknown}.length() )
|
||||
{
|
||||
RecordVal * type_val = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
type_val->Assign(0, new Val(${msg.padata.padata_elems[i].data_type}, TYPE_COUNT));
|
||||
type_val->Assign(1, bytestring_to_val(${msg.padata.padata_elems[i].pa_data_element.unknown}));
|
||||
padata->Assign(padata->Size(), type_val);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rv->Assign(2, padata);
|
||||
}
|
||||
|
||||
for ( uint i = 0; i < ${msg.body.args}->size(); ++i )
|
||||
{
|
||||
switch ( ${msg.body.args[i].seq_meta.index} )
|
||||
{
|
||||
case 0:
|
||||
rv->Assign(3, proc_krb_kdc_options(${msg.body.args[i].data.options}));
|
||||
break;
|
||||
case 1:
|
||||
rv->Assign(4, GetStringFromPrincipalName(${msg.body.args[i].data.principal}));
|
||||
break;
|
||||
case 2:
|
||||
rv->Assign(5, bytestring_to_val(${msg.body.args[i].data.realm.encoding.content}));
|
||||
break;
|
||||
case 3:
|
||||
rv->Assign(6, GetStringFromPrincipalName(${msg.body.args[i].data.sname}));
|
||||
break;
|
||||
case 4:
|
||||
rv->Assign(7, GetTimeFromAsn1(${msg.body.args[i].data.from}));
|
||||
break;
|
||||
case 5:
|
||||
rv->Assign(8, GetTimeFromAsn1(${msg.body.args[i].data.till}));
|
||||
break;
|
||||
case 6:
|
||||
rv->Assign(9, GetTimeFromAsn1(${msg.body.args[i].data.rtime}));
|
||||
break;
|
||||
case 7:
|
||||
rv->Assign(10, asn1_integer_to_val(${msg.body.args[i].data.nonce}, TYPE_COUNT));
|
||||
break;
|
||||
case 8:
|
||||
if ( ${msg.body.args[i].data.etype.data}->size() )
|
||||
{
|
||||
VectorVal* ciphers = new VectorVal(internal_type("index_vec")->AsVectorType());
|
||||
|
||||
for ( uint j = 0; j < ${msg.body.args[i].data.etype.data}->size(); ++j )
|
||||
ciphers->Assign(ciphers->Size(), asn1_integer_to_val(${msg.body.args[i].data.etype.data[j]}, TYPE_COUNT));
|
||||
|
||||
rv->Assign(11, ciphers);
|
||||
}
|
||||
break;
|
||||
case 9:
|
||||
if ( ${msg.body.args[i].data.addrs.addresses}->size() )
|
||||
{
|
||||
VectorVal* addrs = new VectorVal(internal_type("KRB::Host_Address_Vector")->AsVectorType());
|
||||
|
||||
for ( uint j = 0; j < ${msg.body.args[i].data.addrs.addresses}->size(); ++j )
|
||||
{
|
||||
RecordVal* addr = new RecordVal(BifType::Record::KRB::Host_Address);
|
||||
switch ( binary_to_int64(${msg.body.args[i].data.addrs.addresses[j].addr_type.encoding.content}) )
|
||||
{
|
||||
case 2:
|
||||
addr->Assign(0, new AddrVal(IPAddr(IPv4, (const uint32_t*) c_str(${msg.body.args[i].data.addrs.addresses[j].address.data.content}), IPAddr::Network)));
|
||||
break;
|
||||
case 24:
|
||||
addr->Assign(0, new AddrVal(IPAddr(IPv6, (const uint32_t*) c_str(${msg.body.args[i].data.addrs.addresses[j].address.data.content}), IPAddr::Network)));
|
||||
break;
|
||||
case 20:
|
||||
addr->Assign(1, bytestring_to_val(${msg.body.args[i].data.addrs.addresses[j].address.data.content}));
|
||||
break;
|
||||
default:
|
||||
RecordVal* unk = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
unk->Assign(0, asn1_integer_to_val(${msg.body.args[i].data.addrs.addresses[j].addr_type}, TYPE_COUNT));
|
||||
unk->Assign(1, bytestring_to_val(${msg.body.args[i].data.addrs.addresses[j].address.data.content}));
|
||||
addr->Assign(2, unk);
|
||||
break;
|
||||
}
|
||||
addrs->Assign(addrs->Size(), addr);
|
||||
}
|
||||
|
||||
rv->Assign(12, addrs);
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
// TODO
|
||||
break;
|
||||
case 11:
|
||||
if ( ${msg.body.args[i].data.addl_tkts.tickets}->size() )
|
||||
{
|
||||
VectorVal* tickets = new VectorVal(internal_type("KRB::Ticket_Vector")->AsVectorType());
|
||||
|
||||
for ( uint j = 0; j < ${msg.body.args[i].data.addl_tkts.tickets}->size(); ++j )
|
||||
{
|
||||
RecordVal* ticket = new RecordVal(BifType::Record::KRB::Ticket);
|
||||
|
||||
ticket->Assign(0, asn1_integer_to_val(${msg.body.args[i].data.addl_tkts.tickets[j].tkt_vno.data}, TYPE_COUNT));
|
||||
ticket->Assign(1, bytestring_to_val(${msg.body.args[i].data.addl_tkts.tickets[j].realm.data.content}));
|
||||
ticket->Assign(2, GetStringFromPrincipalName(${msg.body.args[i].data.addl_tkts.tickets[j].sname}));
|
||||
ticket->Assign(3, asn1_integer_to_val(${msg.body.args[i].data.addl_tkts.tickets[j].enc_part.etype.data}, TYPE_COUNT));
|
||||
tickets->Assign(tickets->Size(), ticket);
|
||||
}
|
||||
rv->Assign(13, tickets);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
RecordVal* rv = proc_krb_kdc_req_arguments(${msg}, bro_analyzer());
|
||||
|
||||
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 10 ) )
|
||||
BifEvent::generate_krb_as_req(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||
|
@ -300,63 +438,8 @@ refine connection KRB_Conn += {
|
|||
rv->Assign(0, asn1_integer_to_val(${msg.pvno.data}, TYPE_COUNT));
|
||||
rv->Assign(1, asn1_integer_to_val(${msg.msg_type.data}, TYPE_COUNT));
|
||||
|
||||
if ( ${msg.has_padata} )
|
||||
{
|
||||
VectorVal* padata = new VectorVal(internal_type("KRB::Type_Value_Vector")->AsVectorType());
|
||||
|
||||
for ( uint i = 0; i < ${msg.padata.padata_elems}->size(); ++i)
|
||||
{
|
||||
switch( ${msg.padata.padata_elems[i].data_type} )
|
||||
{
|
||||
case 1:
|
||||
// will be generated as separate event
|
||||
break;
|
||||
case 2:
|
||||
// encrypted timestamp is unreadable
|
||||
break;
|
||||
case 3:
|
||||
{
|
||||
RecordVal * type_val = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
type_val->Assign(0, new Val(${msg.padata.padata_elems[i].data_type}, TYPE_COUNT));
|
||||
type_val->Assign(1, bytestring_to_val(${msg.padata.padata_elems[i].pa_data_element.pa_pw_salt.encoding.content}));
|
||||
padata->Assign(padata->Size(), type_val);
|
||||
break;
|
||||
}
|
||||
case 17:
|
||||
{
|
||||
const bytestring& cert = ${msg.padata.padata_elems[i].pa_data_element.pa_pk_as_rep.cert};
|
||||
|
||||
ODesc common;
|
||||
common.AddRaw("Analyzer::ANALYZER_KRB");
|
||||
common.Add(bro_analyzer()->Conn()->StartTime());
|
||||
common.AddRaw("F", 1);
|
||||
bro_analyzer()->Conn()->IDString(&common);
|
||||
|
||||
ODesc file_handle;
|
||||
file_handle.Add(common.Description());
|
||||
file_handle.Add(1);
|
||||
|
||||
string file_id = file_mgr->HashHandle(file_handle.Description());
|
||||
|
||||
file_mgr->DataIn(reinterpret_cast<const u_char*>(cert.data()),
|
||||
cert.length(), bro_analyzer()->GetAnalyzerTag(),
|
||||
bro_analyzer()->Conn(), false, file_id);
|
||||
file_mgr->EndOfFile(file_id);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
RecordVal * type_val = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
type_val->Assign(0, new Val(${msg.padata.padata_elems[i].data_type}, TYPE_COUNT));
|
||||
type_val->Assign(1, bytestring_to_val(${msg.padata.padata_elems[i].pa_data_element.unknown}));
|
||||
padata->Assign(padata->Size(), type_val);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
rv->Assign(2, padata);
|
||||
}
|
||||
if ( ${msg.padata.has_padata} )
|
||||
rv->Assign(2, proc_padata(${msg.padata.padata.padata}, bro_analyzer(), false));
|
||||
|
||||
rv->Assign(3, bytestring_to_val(${msg.client_realm.encoding.content}));
|
||||
rv->Assign(4, GetStringFromPrincipalName(${msg.client_name}));
|
||||
|
@ -399,79 +482,10 @@ refine connection KRB_Conn += {
|
|||
if ( krb_error )
|
||||
{
|
||||
RecordVal* rv = new RecordVal(BifType::Record::KRB::Error_Msg);
|
||||
rv->Assign(0, asn1_integer_to_val(${msg.pvno.data}, TYPE_COUNT));
|
||||
rv->Assign(1, asn1_integer_to_val(${msg.msg_type.data}, TYPE_COUNT));
|
||||
if ( ${msg.has_ctime} )
|
||||
rv->Assign(2, GetTimeFromAsn1(bytestring_to_val(${msg.ctime})));
|
||||
|
||||
// TODO: if ( ${msg.has_cusec} )
|
||||
|
||||
rv->Assign(3, GetTimeFromAsn1(bytestring_to_val(${msg.stime})));
|
||||
// TODO: ${msg.susec}
|
||||
|
||||
|
||||
rv->Assign(4, asn1_integer_to_val(${msg.error_code.data}, TYPE_COUNT));
|
||||
|
||||
for ( uint i = 0; i < ${msg.args}->size(); i++ )
|
||||
{
|
||||
switch ( ${msg.args[i].seq_meta.index} )
|
||||
{
|
||||
case 7:
|
||||
rv->Assign(5, bytestring_to_val(${msg.args[i].args.crealm.encoding.content}));
|
||||
break;
|
||||
case 8:
|
||||
rv->Assign(6, GetStringFromPrincipalName(${msg.args[i].args.cname}));
|
||||
break;
|
||||
case 9:
|
||||
rv->Assign(7, bytestring_to_val(${msg.args[i].args.realm.encoding.content}));
|
||||
break;
|
||||
case 10:
|
||||
rv->Assign(8, GetStringFromPrincipalName(${msg.args[i].args.sname}));
|
||||
break;
|
||||
case 11:
|
||||
rv->Assign(9, bytestring_to_val(${msg.args[i].args.e_text.encoding.content}));
|
||||
break;
|
||||
case 12:
|
||||
// if ( ${msg.error_code.data.content}[0] == 25 )
|
||||
// {
|
||||
// VectorVal* padata = new VectorVal(internal_type("KRB::Type_Value_Vector")->AsVectorType());
|
||||
|
||||
// for ( uint j = 0; j < ${msg.args[i].args.e_data.padata.padata_elems}->size(); ++j)
|
||||
// {
|
||||
// switch( ${msg.args[i].args.e_data.padata.padata_elems[j].data_type} )
|
||||
// {
|
||||
// case 1:
|
||||
// // will be generated as separate event
|
||||
// break;
|
||||
// case 3:
|
||||
// {
|
||||
// RecordVal * type_val = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
// type_val->Assign(0, new Val(${msg.args[i].args.e_data.padata.padata_elems[j].data_type}, TYPE_COUNT));
|
||||
// type_val->Assign(1, bytestring_to_val(${msg.args[i].args.e_data.padata.padata_elems[j].pa_data_element.pa_pw_salt.encoding.content}));
|
||||
// padata->Assign(padata->Size(), type_val);
|
||||
// break;
|
||||
// }
|
||||
// default:
|
||||
// {
|
||||
// if ( ${msg.args[i].args.e_data.padata.padata_elems[j].pa_data_element.unknown}.length() )
|
||||
// {
|
||||
// RecordVal * type_val = new RecordVal(BifType::Record::KRB::Type_Value);
|
||||
// type_val->Assign(0, new Val(${msg.args[i].args.e_data.padata.padata_elems[j].data_type}, TYPE_COUNT));
|
||||
// type_val->Assign(1, bytestring_to_val(${msg.args[i].args.e_data.padata.padata_elems[j].pa_data_element.unknown}));
|
||||
// padata->Assign(padata->Size(), type_val);
|
||||
// }
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// rv->Assign(10, padata);
|
||||
// }
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
BifEvent::generate_krb_error(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||
proc_error_arguments(rv, ${msg.args1}, 0);
|
||||
rv->Assign(4, asn1_integer_to_val(${msg.error_code}, TYPE_COUNT));
|
||||
proc_error_arguments(rv, ${msg.args2}, binary_to_int64(${msg.error_code.encoding.content}));
|
||||
BifEvent::generate_krb_error(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
@ -505,7 +519,13 @@ refine connection KRB_Conn += {
|
|||
|
||||
function debug_asn1_encoding_meta(msg: ASN1EncodingMeta): bool
|
||||
%{
|
||||
printf("ASN1 Element tag=%x, length=%d\n", ${msg.tag}, ${msg.length});
|
||||
printf("DeBuG ASN1 Element tag=%x, length=%d\n", ${msg.tag}, ${msg.length});
|
||||
return true;
|
||||
%}
|
||||
|
||||
function debug_krb_error_arg(msg: KRB_ERROR_Arg): bool
|
||||
%{
|
||||
printf("DeBuG KRB Error index=%d\n", ${msg.seq_meta.index});
|
||||
return true;
|
||||
%}
|
||||
}
|
||||
|
@ -555,7 +575,10 @@ refine typeattr KRB_CRED_MSG += &let {
|
|||
# proc: bool = $context.connection.debug_req_arg(this);
|
||||
#};
|
||||
|
||||
#refine typeattr ASN1EncodingMeta += &let {
|
||||
# proc: bool = $context.connection.debug_asn1_encoding_meta(this);
|
||||
#};
|
||||
refine typeattr ASN1EncodingMeta += &let {
|
||||
proc: bool = $context.connection.debug_asn1_encoding_meta(this);
|
||||
};
|
||||
|
||||
refine typeattr KRB_ERROR_Arg += &let {
|
||||
proc: bool = $context.connection.debug_krb_error_arg(this);
|
||||
};
|
|
@ -14,6 +14,13 @@ type ASN1EncodingMeta = record {
|
|||
index: uint8 = tag - 160;
|
||||
};
|
||||
|
||||
type ASN1OptionalEncodingMeta(is_present: bool, previous_metadata: ASN1EncodingMeta) = case is_present of {
|
||||
true -> data: ASN1EncodingMeta;
|
||||
false -> none: empty;
|
||||
} &let {
|
||||
length: uint64 = is_present ? data.length : previous_metadata.length;
|
||||
};
|
||||
|
||||
type ASN1Integer = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
|
13
src/analyzer/protocol/krb/krb-defs.pac
Normal file
13
src/analyzer/protocol/krb/krb-defs.pac
Normal file
|
@ -0,0 +1,13 @@
|
|||
enum KRBMessageTypes {
|
||||
AS_REQ = 10,
|
||||
AS_REP = 11,
|
||||
TGS_REQ = 12,
|
||||
TGS_REP = 13,
|
||||
AP_REQ = 14,
|
||||
AP_REP = 15,
|
||||
KRB_SAFE = 20,
|
||||
KRB_PRIV = 21,
|
||||
KRB_CRED = 22,
|
||||
KRB_ERROR = 30,
|
||||
};
|
||||
|
76
src/analyzer/protocol/krb/krb-padata.pac
Normal file
76
src/analyzer/protocol/krb/krb-padata.pac
Normal file
|
@ -0,0 +1,76 @@
|
|||
# Kerberos pre-authentication data is a significant piece of the complexity,
|
||||
# so we're splitting this off
|
||||
|
||||
type KRB_PA_Data_Optional(pkt_type: uint8, desired_index: uint8) = record {
|
||||
first_meta : ASN1EncodingMeta;
|
||||
padata : KRB_PA_Data_Field(has_padata, pkt_type, first_meta.length);
|
||||
next_meta : ASN1OptionalEncodingMeta(has_padata, first_meta);
|
||||
} &let {
|
||||
has_padata : bool = first_meta.index == desired_index;
|
||||
};
|
||||
|
||||
type KRB_PA_Data_Field(is_present: bool, pkt_type: uint8, length: uint64) = case is_present of {
|
||||
true -> padata: KRB_PA_Data_Sequence(pkt_type) &length=length;
|
||||
false -> none: empty;
|
||||
};
|
||||
|
||||
type KRB_PA_Data_Sequence(pkt_type: uint8) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
padata_elems: KRB_PA_Data(pkt_type)[];
|
||||
};
|
||||
|
||||
type KRB_PA_Data(pkt_type: uint8) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
pa_data_type : SequenceElement(true);
|
||||
pa_data_elem_meta : ASN1EncodingMeta;
|
||||
have_data : case pkt_type of {
|
||||
KRB_ERROR -> pa_data_placeholder: bytestring &length=pa_data_elem_meta.length;
|
||||
default -> pa_data_element : KRB_PA_Data_Element(data_type, pa_data_elem_meta.length);
|
||||
} &requires(data_type);
|
||||
} &let {
|
||||
data_type: int64 = binary_to_int64(pa_data_type.data.content);
|
||||
};
|
||||
|
||||
type KRB_PA_Data_Element(type: int64, length: uint64) = case type of {
|
||||
1 -> pa_tgs_req : KRB_AP_REQ;
|
||||
3 -> pa_pw_salt : ASN1OctetString;
|
||||
16 -> pa_pk_as_req : KRB_PA_PK_AS_Req &length=length;
|
||||
17 -> pa_pk_as_rep : KRB_PA_PK_AS_Rep &length=length;
|
||||
default -> unknown : bytestring &length=length;
|
||||
};
|
||||
|
||||
type KRB_PA_PK_AS_Req = record {
|
||||
string_meta : ASN1EncodingMeta;
|
||||
seq_meta1 : ASN1EncodingMeta;
|
||||
elem_0_meta1: ASN1EncodingMeta;
|
||||
seq_meta2 : ASN1EncodingMeta;
|
||||
oid : ASN1Encoding;
|
||||
elem_0_meta2: ASN1EncodingMeta;
|
||||
seq_meta3 : ASN1EncodingMeta;
|
||||
version : ASN1Encoding;
|
||||
digest_algs : ASN1Encoding;
|
||||
signed_data : ASN1Encoding;
|
||||
cert_meta : ASN1EncodingMeta;
|
||||
cert : bytestring &length=cert_meta.length;
|
||||
# Ignore everything else
|
||||
: bytestring &restofdata &transient;
|
||||
};
|
||||
|
||||
type KRB_PA_PK_AS_Rep = record {
|
||||
string_meta : ASN1EncodingMeta;
|
||||
elem_0_meta1: ASN1EncodingMeta;
|
||||
seq_meta1 : ASN1EncodingMeta;
|
||||
elem_0_meta2: ASN1EncodingMeta;
|
||||
seq_meta2 : ASN1EncodingMeta;
|
||||
oid : ASN1Encoding;
|
||||
elem_0_meta3: ASN1EncodingMeta;
|
||||
seq_meta3 : ASN1EncodingMeta;
|
||||
version : ASN1Encoding;
|
||||
digest_algs : ASN1Encoding;
|
||||
signed_data : ASN1Encoding;
|
||||
cert_meta : ASN1EncodingMeta;
|
||||
cert : bytestring &length=cert_meta.length;
|
||||
# Ignore everything else
|
||||
: bytestring &restofdata &transient;
|
||||
};
|
||||
|
|
@ -1,20 +1,18 @@
|
|||
# ASN1 parsing
|
||||
%include krb-asn1.pac
|
||||
|
||||
enum KRBMessageTypes {
|
||||
AS_REQ = 10,
|
||||
AS_REP = 11,
|
||||
TGS_REQ = 12,
|
||||
TGS_REP = 13,
|
||||
AP_REQ = 14,
|
||||
AP_REP = 15,
|
||||
KRB_SAFE = 20,
|
||||
KRB_PRIV = 21,
|
||||
KRB_CRED = 22,
|
||||
KRB_ERROR = 30,
|
||||
};
|
||||
# Constants
|
||||
%include krb-defs.pac
|
||||
|
||||
# Basic types
|
||||
%include krb-types.pac
|
||||
|
||||
# Preauth data parsing
|
||||
%include krb-padata.pac
|
||||
|
||||
# KRB over TCP is the same as over UDP, but prefixed with a uint32 denoting the size
|
||||
type KRB_PDU_TCP = record {
|
||||
size: uint32;
|
||||
size : uint32;
|
||||
pdu : KRB_PDU;
|
||||
} &length=size+4 &byteorder=bigendian;
|
||||
|
||||
|
@ -31,7 +29,6 @@ type KRB_PDU = record {
|
|||
KRB_PRIV -> krb_priv : KRB_PRIV_MSG;
|
||||
KRB_CRED -> krb_cred : KRB_CRED_MSG;
|
||||
KRB_ERROR -> krb_error: KRB_ERROR_MSG;
|
||||
default -> unknown : bytestring &restofdata;
|
||||
};
|
||||
} &byteorder=bigendian;
|
||||
|
||||
|
@ -51,131 +48,33 @@ type KRB_TGS_REP = record {
|
|||
data: KRB_KDC_REP(TGS_REP);
|
||||
};
|
||||
|
||||
### KDC_REQ
|
||||
### A Kerberos ticket-granting-service or authentication-service request
|
||||
|
||||
type KRB_KDC_REQ(pkt_type: uint8) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
pvno : SequenceElement(true);
|
||||
msg_type : SequenceElement(true);
|
||||
padata_meta: ASN1EncodingMeta;
|
||||
tmp1 : case has_padata of {
|
||||
true -> padata : KRB_PA_Data_Sequence(pkt_type) &length=padata_meta.length;
|
||||
false -> n1 : empty;
|
||||
};
|
||||
tmp2 : case has_padata of {
|
||||
true -> meta2 : ASN1EncodingMeta;
|
||||
false -> n2 : empty;
|
||||
};
|
||||
body : KRB_REQ_Body &length=body_length;
|
||||
} &let {
|
||||
has_padata : bool = padata_meta.index == 3;
|
||||
body_length: uint64 = has_padata ? meta2.length : padata_meta.length;
|
||||
};
|
||||
|
||||
type KRB_PA_Data_Sequence(pkt_type: uint8) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
padata_elems: KRB_PA_Data(pkt_type)[];
|
||||
};
|
||||
|
||||
type KRB_PA_Data(pkttype: uint8) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
pa_data_type : SequenceElement(true);
|
||||
pa_data_elem_meta : ASN1EncodingMeta;
|
||||
have_data : case ( pkttype == 30 ) of {
|
||||
true -> pa_data_placeholder: bytestring &length=pa_data_elem_meta.length;
|
||||
false -> pa_data_element : KRB_PA_Data_Element(binary_to_int64(pa_data_type.data.content), pa_data_elem_meta.length);
|
||||
};
|
||||
} &let {
|
||||
data_type: int64 = binary_to_int64(pa_data_type.data.content);
|
||||
};
|
||||
|
||||
type KRB_PA_Data_Element(type: int64, length: uint64) = case type of {
|
||||
1 -> pa_tgs_req : KRB_AP_REQ;
|
||||
3 -> pa_pw_salt : ASN1OctetString;
|
||||
16 -> pa_pk_as_req : KRB_PA_PK_AS_Req &length=length;
|
||||
17 -> pa_pk_as_rep : KRB_PA_PK_AS_Rep &length=length;
|
||||
default -> unknown : bytestring &length=length;
|
||||
};
|
||||
|
||||
# Octet string metadata
|
||||
# -- Sequence metadata
|
||||
# ---- [0] metadata
|
||||
# ------ Sequence metadata
|
||||
# -------- OID
|
||||
# ---------- [0] metadata
|
||||
# ------------ Sequence metadata
|
||||
# -------------- version
|
||||
# -------------- digestAlgorithms
|
||||
# -------------- signedData
|
||||
# -------------- certificates
|
||||
type KRB_PA_PK_AS_Req = record {
|
||||
string_meta : ASN1EncodingMeta;
|
||||
seq_meta1 : ASN1EncodingMeta;
|
||||
elem_0_meta1: ASN1EncodingMeta;
|
||||
seq_meta2 : ASN1EncodingMeta;
|
||||
oid : ASN1Encoding;
|
||||
elem_0_meta2: ASN1EncodingMeta;
|
||||
seq_meta3 : ASN1EncodingMeta;
|
||||
version : ASN1Encoding;
|
||||
digest_algs : ASN1Encoding;
|
||||
signed_data : ASN1Encoding;
|
||||
cert_meta : ASN1EncodingMeta;
|
||||
cert : bytestring &length=cert_meta.length;
|
||||
# Ignore everything else
|
||||
: bytestring &restofdata &transient;
|
||||
};
|
||||
|
||||
# Octet string metadata
|
||||
# -- [0] metadata
|
||||
# ---- Sequence metadata
|
||||
# ------ [0] metadata
|
||||
# -------- Sequence metadata
|
||||
# ---------- OID
|
||||
# ------------ [0] metadata
|
||||
# -------------- Sequence metadata
|
||||
# ---------------- version
|
||||
# ---------------- digestAlgorithms
|
||||
# ---------------- signedData
|
||||
# ---------------- certificates
|
||||
type KRB_PA_PK_AS_Rep = record {
|
||||
string_meta : ASN1EncodingMeta;
|
||||
elem_0_meta1: ASN1EncodingMeta;
|
||||
seq_meta1 : ASN1EncodingMeta;
|
||||
elem_0_meta2: ASN1EncodingMeta;
|
||||
seq_meta2 : ASN1EncodingMeta;
|
||||
oid : ASN1Encoding;
|
||||
elem_0_meta3: ASN1EncodingMeta;
|
||||
seq_meta3 : ASN1EncodingMeta;
|
||||
version : ASN1Encoding;
|
||||
digest_algs : ASN1Encoding;
|
||||
signed_data : ASN1Encoding;
|
||||
cert_meta : ASN1EncodingMeta;
|
||||
cert : bytestring &length=cert_meta.length;
|
||||
# Ignore everything else
|
||||
: bytestring &restofdata &transient;
|
||||
};
|
||||
|
||||
type KRB_REQ_Body = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
args : KRB_REQ_Arg[];
|
||||
padata : KRB_PA_Data_Optional(pkt_type, 3);
|
||||
body_meta : ASN1EncodingMeta;
|
||||
body_args : KRB_REQ_Arg[];
|
||||
};
|
||||
|
||||
type KRB_REQ_Arg = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
data : KRB_REQ_Arg_Data(seq_meta.index) &length=seq_meta.length;
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
data : KRB_REQ_Arg_Data(seq_meta.index) &length=seq_meta.length;
|
||||
};
|
||||
|
||||
type KRB_REQ_Arg_Data(index: uint8) = case index of {
|
||||
0 -> options : KRB_KDC_Options;
|
||||
0 -> options : KRB_KDC_Options;
|
||||
1 -> principal : KRB_Principal_Name;
|
||||
2 -> realm : ASN1OctetString;
|
||||
3 -> sname : KRB_Principal_Name;
|
||||
4 -> from : KRB_Time;
|
||||
5 -> till : KRB_Time;
|
||||
6 -> rtime : KRB_Time;
|
||||
7 -> nonce : ASN1Integer;
|
||||
8 -> etype : Array;
|
||||
9 -> addrs : KRB_Host_Addresses;
|
||||
2 -> realm : ASN1OctetString;
|
||||
3 -> sname : KRB_Principal_Name;
|
||||
4 -> from : KRB_Time;
|
||||
5 -> till : KRB_Time;
|
||||
6 -> rtime : KRB_Time;
|
||||
7 -> nonce : ASN1Integer;
|
||||
8 -> etype : Array;
|
||||
9 -> addrs : KRB_Host_Addresses;
|
||||
10 -> auth_data : ASN1OctetString; # TODO
|
||||
11 -> addl_tkts : KRB_Ticket_Sequence;
|
||||
default -> unknown : bytestring &restofdata;
|
||||
|
@ -186,94 +85,28 @@ type KRB_KDC_Options = record {
|
|||
pad: uint8;
|
||||
flags: uint32;
|
||||
} &let {
|
||||
reserved : bool = (flags & 0x80000000) > 0;
|
||||
forwardable : bool = (flags & 0x40000000) > 0;
|
||||
forwarded : bool = (flags & 0x20000000) > 0;
|
||||
proxiable : bool = (flags & 0x10000000) > 0;
|
||||
proxy : bool = (flags & 0x8000000) > 0;
|
||||
allow_postdate : bool = (flags & 0x4000000) > 0;
|
||||
postdated : bool = (flags & 0x2000000) > 0;
|
||||
unused7 : bool = (flags & 0x1000000) > 0;
|
||||
renewable : bool = (flags & 0x800000) > 0;
|
||||
unused9 : bool = (flags & 0x400000) > 0;
|
||||
unused10 : bool = (flags & 0x200000) > 0;
|
||||
opt_hardware_auth : bool = (flags & 0x100000) > 0;
|
||||
unused12 : bool = (flags & 0x80000) > 0;
|
||||
unused13 : bool = (flags & 0x40000) > 0;
|
||||
reserved : bool = (flags & 0x80000000) > 0;
|
||||
forwardable : bool = (flags & 0x40000000) > 0;
|
||||
forwarded : bool = (flags & 0x20000000) > 0;
|
||||
proxiable : bool = (flags & 0x10000000) > 0;
|
||||
proxy : bool = (flags & 0x8000000) > 0;
|
||||
allow_postdate : bool = (flags & 0x4000000) > 0;
|
||||
postdated : bool = (flags & 0x2000000) > 0;
|
||||
unused7 : bool = (flags & 0x1000000) > 0;
|
||||
renewable : bool = (flags & 0x800000) > 0;
|
||||
unused9 : bool = (flags & 0x400000) > 0;
|
||||
unused10 : bool = (flags & 0x200000) > 0;
|
||||
opt_hardware_auth : bool = (flags & 0x100000) > 0;
|
||||
unused12 : bool = (flags & 0x80000) > 0;
|
||||
unused13 : bool = (flags & 0x40000) > 0;
|
||||
# ...
|
||||
unused15 : bool = (flags & 0x10000) > 0;
|
||||
unused15 : bool = (flags & 0x10000) > 0;
|
||||
# ...
|
||||
disable_transited_check : bool = (flags & 0x10) > 0;
|
||||
renewable_ok : bool = (flags & 0x8) > 0;
|
||||
enc_tkt_in_skey : bool = (flags & 0x4) > 0;
|
||||
renew : bool = (flags & 0x2) > 0;
|
||||
validate : bool = (flags & 0x1) > 0;
|
||||
};
|
||||
|
||||
type KRB_Principal_Name = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
name_meta : ASN1EncodingMeta;
|
||||
name_type : ASN1Integer;
|
||||
seq_meta_1: ASN1EncodingMeta;
|
||||
seq_meta_2: ASN1EncodingMeta;
|
||||
data : ASN1OctetString[];
|
||||
};
|
||||
|
||||
type KRB_Time = record {
|
||||
meta: ASN1EncodingMeta;
|
||||
time: bytestring &restofdata;
|
||||
};
|
||||
|
||||
type KRB_Host_Addresses = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
addresses: KRB_Host_Address[];
|
||||
};
|
||||
|
||||
type KRB_Host_Address = record {
|
||||
addr_type_meta : SequenceElement(false);
|
||||
addr_type : ASN1Integer;
|
||||
address : SequenceElement(true);
|
||||
};
|
||||
|
||||
type KRB_Ticket(in_sequence: bool) = record {
|
||||
have_seq : case in_sequence of {
|
||||
true -> meta: ASN1EncodingMeta;
|
||||
false -> none: empty;
|
||||
};
|
||||
app_meta : ASN1EncodingMeta;
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
tkt_vno : SequenceElement(true);
|
||||
realm : SequenceElement(true);
|
||||
sname_meta: ASN1EncodingMeta;
|
||||
sname : KRB_Principal_Name &length=sname_meta.length;
|
||||
enc_part : KRB_Encrypted_Data;
|
||||
};
|
||||
|
||||
type KRB_Ticket_Sequence = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
tickets : KRB_Ticket(true)[] &length=seq_meta.length;
|
||||
};
|
||||
|
||||
type KRB_Encrypted_Data_in_Seq = record {
|
||||
index_meta : ASN1EncodingMeta;
|
||||
data : KRB_Encrypted_Data &length=index_meta.length;
|
||||
};
|
||||
|
||||
type KRB_Encrypted_Data = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
etype : SequenceElement(true);
|
||||
kvno_meta : ASN1EncodingMeta;
|
||||
case_kvno : case have_kvno of {
|
||||
true -> kvno : ASN1Integer;
|
||||
false -> none : empty;
|
||||
};
|
||||
grab_next_meta : case have_kvno of {
|
||||
true -> next_meta: ASN1EncodingMeta;
|
||||
false -> none_meta: empty;
|
||||
};
|
||||
ciphertext : bytestring &length=have_kvno ? next_meta.length : kvno_meta.length;
|
||||
} &let {
|
||||
have_kvno : bool = kvno_meta.index == 1;
|
||||
renewable_ok : bool = (flags & 0x8) > 0;
|
||||
enc_tkt_in_skey : bool = (flags & 0x4) > 0;
|
||||
renew : bool = (flags & 0x2) > 0;
|
||||
validate : bool = (flags & 0x1) > 0;
|
||||
};
|
||||
|
||||
### KDC_REP
|
||||
|
@ -282,23 +115,12 @@ type KRB_KDC_REP(pkt_type: uint8) = record {
|
|||
seq_meta : ASN1EncodingMeta;
|
||||
pvno : SequenceElement(true);
|
||||
msg_type : SequenceElement(true);
|
||||
padata_meta : ASN1EncodingMeta;
|
||||
tmp1 : case has_padata of {
|
||||
true -> padata : KRB_PA_Data_Sequence(pkt_type) &length=padata_meta.length;
|
||||
false -> n1 : empty;
|
||||
};
|
||||
tmp2 : case has_padata of {
|
||||
true -> meta2 : ASN1EncodingMeta;
|
||||
false -> n2 : empty;
|
||||
};
|
||||
client_realm: ASN1OctetString &length=realm_length;
|
||||
cname_meta : ASN1EncodingMeta;
|
||||
padata : KRB_PA_Data_Optional(pkt_type, 2);
|
||||
client_realm: ASN1OctetString &length=padata.next_meta.length;
|
||||
cname_meta : ASN1EncodingMeta;
|
||||
client_name : KRB_Principal_Name &length=cname_meta.length;
|
||||
ticket : KRB_Ticket(true);
|
||||
enc_part : KRB_Encrypted_Data_in_Seq;
|
||||
} &let {
|
||||
has_padata : bool = padata_meta.index == 2;
|
||||
realm_length: uint64 = has_padata ? meta2.length : padata_meta.length;
|
||||
};
|
||||
|
||||
### AP_REQ
|
||||
|
@ -319,7 +141,7 @@ type KRB_AP_Options = record {
|
|||
flags : uint32;
|
||||
: padding[1];
|
||||
} &let {
|
||||
reserved : bool = (flags & 0x80000000) > 0;
|
||||
reserved : bool = (flags & 0x80000000) > 0;
|
||||
use_session_key : bool = (flags & 0x40000000) > 0;
|
||||
mutual_required : bool = (flags & 0x20000000) > 0;
|
||||
};
|
||||
|
@ -335,77 +157,42 @@ type KRB_AP_REP = record {
|
|||
|
||||
### KRB_ERROR
|
||||
|
||||
# pvno [0] INTEGER (5),
|
||||
# msg-type [1] INTEGER (30),
|
||||
# ctime [2] KerberosTime OPTIONAL,
|
||||
# cusec [3] Microseconds OPTIONAL,
|
||||
# stime [4] KerberosTime,
|
||||
# susec [5] Microseconds,
|
||||
# error-code [6] Int32,
|
||||
# crealm [7] Realm OPTIONAL,
|
||||
# cname [8] PrincipalName OPTIONAL,
|
||||
# realm [9] Realm -- service realm --,
|
||||
# sname [10] PrincipalName -- service name --,
|
||||
# e-text [11] KerberosString OPTIONAL,
|
||||
|
||||
type KRB_ERROR_MSG = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
pvno : SequenceElement(true);
|
||||
msg_type : SequenceElement(true);
|
||||
ctime_meta : ASN1EncodingMeta;
|
||||
tmp1 : case has_ctime of {
|
||||
true -> ctime : bytestring &length=ctime_meta.length;
|
||||
false -> n1 : empty;
|
||||
};
|
||||
tmp2 : case has_ctime of {
|
||||
true -> cusec_meta : ASN1EncodingMeta;
|
||||
false -> n2 : empty;
|
||||
};
|
||||
tmp3 : case has_cusec of {
|
||||
true -> cusec : ASN1Integer;
|
||||
false -> n3 : empty;
|
||||
};
|
||||
tmp4 : case has_cusec of {
|
||||
true -> stime_meta : ASN1EncodingMeta;
|
||||
false -> n4 : empty;
|
||||
};
|
||||
stime : bytestring &length=stime_length;
|
||||
susec : SequenceElement(true);
|
||||
error_code : SequenceElement(true);
|
||||
args : KRB_ERROR_Arg(binary_to_int64(error_code.data.content))[];
|
||||
} &let {
|
||||
has_ctime: bool = ctime_meta.index == 2;
|
||||
has_cusec: bool = has_ctime ? cusec_meta.index == 3 : ctime_meta.index == 3;
|
||||
stime_length: uint64 = has_ctime ? (has_cusec ? stime_meta.length : cusec_meta.length) : (has_cusec ? stime_meta.length : ctime_meta.length);
|
||||
args1 : KRB_ERROR_Arg(0)[] &until ($element.process_in_parent);
|
||||
error_code : ASN1Integer;
|
||||
args2 : KRB_ERROR_Arg(binary_to_int64(error_code.encoding.content))[];
|
||||
};
|
||||
|
||||
type KRB_ERROR_Arg(error_code: uint64) = record {
|
||||
type KRB_ERROR_Arg(error_code: int64) = record {
|
||||
seq_meta: ASN1EncodingMeta;
|
||||
args : KRB_ERROR_Arg_Data(seq_meta.index, error_code) &length=seq_meta.length;
|
||||
args : KRB_ERROR_Arg_Data(seq_meta.index, error_code) &length=arg_length;
|
||||
} &let {
|
||||
process_in_parent: bool = seq_meta.index == 6;
|
||||
arg_length : uint64 = ( process_in_parent ? 0 : seq_meta.length);
|
||||
};
|
||||
|
||||
type KRB_ERROR_Arg_Data(index: uint8, error_code: uint64) = case index of {
|
||||
7 -> crealm : ASN1OctetString;
|
||||
8 -> cname : KRB_Principal_Name;
|
||||
9 -> realm : ASN1OctetString;
|
||||
10 -> sname : KRB_Principal_Name;
|
||||
11 -> e_text : ASN1OctetString;
|
||||
12 -> e_data : KRB_ERROR_E_Data(error_code);
|
||||
type KRB_ERROR_Arg_Data(index: uint8, error_code: int64) = case index of {
|
||||
0 -> pvno : ASN1Integer;
|
||||
1 -> msg_type : ASN1Integer;
|
||||
2 -> ctime : KRB_Time;
|
||||
3 -> cusec : ASN1Integer;
|
||||
4 -> stime : KRB_Time;
|
||||
5 -> susec : ASN1Integer;
|
||||
6 -> err_code : empty;
|
||||
7 -> crealm : ASN1OctetString;
|
||||
8 -> cname : KRB_Principal_Name;
|
||||
9 -> realm : ASN1OctetString;
|
||||
10 -> sname : KRB_Principal_Name;
|
||||
11 -> e_text : ASN1OctetString;
|
||||
12 -> e_data : KRB_ERROR_E_Data(error_code);
|
||||
};
|
||||
|
||||
type KRB_ERROR_E_Data(error_code: uint64) = case ( error_code == 25 ) of {
|
||||
true -> padata : KRB_ERROR_PA_Data;
|
||||
true -> padata : KRB_PA_Data_Sequence(KRB_ERROR);
|
||||
false -> unknown : bytestring &restofdata;
|
||||
};
|
||||
|
||||
type KRB_ERROR_PA_Data = record {
|
||||
meta : ASN1EncodingMeta;
|
||||
have_padata : case ( meta.tag == 30 ) of {
|
||||
true -> padata : KRB_PA_Data_Sequence(KRB_ERROR);
|
||||
false -> unknown : bytestring &restofdata;
|
||||
};
|
||||
};
|
||||
|
||||
### KRB_SAFE
|
||||
|
||||
type KRB_SAFE_MSG = record {
|
||||
|
@ -434,11 +221,6 @@ type KRB_SAFE_Arg_Data(index: uint8) = case index of {
|
|||
5 -> recp_addr : KRB_Host_Address;
|
||||
};
|
||||
|
||||
type KRB_Checksum = record {
|
||||
checksum_type: SequenceElement(true);
|
||||
checksum : SequenceElement(true);
|
||||
};
|
||||
|
||||
### KRB_PRIV
|
||||
|
||||
type KRB_PRIV_MSG = record {
|
||||
|
|
73
src/analyzer/protocol/krb/krb-types.pac
Normal file
73
src/analyzer/protocol/krb/krb-types.pac
Normal file
|
@ -0,0 +1,73 @@
|
|||
# Fundamental KRB types
|
||||
|
||||
type KRB_Principal_Name = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
name_meta : ASN1EncodingMeta;
|
||||
name_type : ASN1Integer;
|
||||
seq_meta_1: ASN1EncodingMeta;
|
||||
seq_meta_2: ASN1EncodingMeta;
|
||||
data : ASN1OctetString[];
|
||||
};
|
||||
|
||||
type KRB_Time = record {
|
||||
meta: ASN1EncodingMeta;
|
||||
time: bytestring &restofdata;
|
||||
};
|
||||
|
||||
type KRB_Host_Addresses = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
addresses: KRB_Host_Address[];
|
||||
};
|
||||
|
||||
type KRB_Host_Address = record {
|
||||
addr_type_meta : SequenceElement(false);
|
||||
addr_type : ASN1Integer;
|
||||
address : SequenceElement(true);
|
||||
};
|
||||
|
||||
type KRB_Ticket(in_sequence: bool) = record {
|
||||
have_seq : case in_sequence of {
|
||||
true -> meta: ASN1EncodingMeta;
|
||||
false -> none: empty;
|
||||
};
|
||||
app_meta : ASN1EncodingMeta;
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
tkt_vno : SequenceElement(true);
|
||||
realm : SequenceElement(true);
|
||||
sname_meta: ASN1EncodingMeta;
|
||||
sname : KRB_Principal_Name &length=sname_meta.length;
|
||||
enc_part : KRB_Encrypted_Data;
|
||||
};
|
||||
|
||||
type KRB_Ticket_Sequence = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
tickets : KRB_Ticket(true)[] &length=seq_meta.length;
|
||||
};
|
||||
|
||||
type KRB_Encrypted_Data_in_Seq = record {
|
||||
index_meta : ASN1EncodingMeta;
|
||||
data : KRB_Encrypted_Data &length=index_meta.length;
|
||||
};
|
||||
|
||||
type KRB_Encrypted_Data = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
etype : SequenceElement(true);
|
||||
kvno_meta : ASN1EncodingMeta;
|
||||
case_kvno : case have_kvno of {
|
||||
true -> kvno : ASN1Integer;
|
||||
false -> none : empty;
|
||||
};
|
||||
grab_next_meta : case have_kvno of {
|
||||
true -> next_meta: ASN1EncodingMeta;
|
||||
false -> none_meta: empty;
|
||||
};
|
||||
ciphertext : bytestring &length=have_kvno ? next_meta.length : kvno_meta.length;
|
||||
} &let {
|
||||
have_kvno : bool = kvno_meta.index == 1;
|
||||
};
|
||||
|
||||
type KRB_Checksum = record {
|
||||
checksum_type: SequenceElement(true);
|
||||
checksum : SequenceElement(true);
|
||||
};
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue