mirror of
https://github.com/zeek/zeek.git
synced 2025-10-15 13:08:20 +00:00
Continue clean-up. Some reformatting, removing hard-coded values, documentation, etc.
This commit is contained in:
parent
2d11fafd5e
commit
0071a1c003
6 changed files with 339 additions and 270 deletions
|
@ -1,94 +1,11 @@
|
|||
%extern{
|
||||
#include "file_analysis/Manager.h"
|
||||
%}
|
||||
|
||||
|
||||
%header{
|
||||
Val* GetTimeFromAsn1(const KRB_Time* atime, int64 usecs);
|
||||
Val* GetTimeFromAsn1(StringVal* atime, int64 usecs);
|
||||
|
||||
Val* GetStringFromPrincipalName(const KRB_Principal_Name* pname);
|
||||
|
||||
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, int64 usecs)
|
||||
{
|
||||
return GetTimeFromAsn1(bytestring_to_val(atime->time()), usecs);
|
||||
}
|
||||
|
||||
Val* GetTimeFromAsn1(StringVal* atime, int64 usecs)
|
||||
{
|
||||
time_t lResult = 0;
|
||||
|
||||
char lBuffer[17];
|
||||
char* pBuffer = lBuffer;
|
||||
|
||||
size_t lTimeLength = atime->Len();
|
||||
char * pString = (char *) atime->Bytes();
|
||||
|
||||
if ( lTimeLength != 15 && lTimeLength != 17 )
|
||||
return 0;
|
||||
|
||||
if (lTimeLength == 17 )
|
||||
pString = pString + 2;
|
||||
|
||||
memcpy(pBuffer, pString, 15);
|
||||
*(pBuffer+15) = '\0';
|
||||
|
||||
tm lTime;
|
||||
lTime.tm_sec = ((lBuffer[12] - '0') * 10) + (lBuffer[13] - '0');
|
||||
lTime.tm_min = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
|
||||
lTime.tm_hour = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
|
||||
lTime.tm_mday = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
|
||||
lTime.tm_mon = (((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0')) - 1;
|
||||
lTime.tm_year = ((lBuffer[0] - '0') * 1000) + ((lBuffer[1] - '0') * 100) + ((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0') - 1900;
|
||||
|
||||
lTime.tm_wday = 0;
|
||||
lTime.tm_yday = 0;
|
||||
lTime.tm_isdst = 0;
|
||||
|
||||
lResult = timegm(&lTime);
|
||||
|
||||
if ( !lResult )
|
||||
lResult = 0;
|
||||
|
||||
return new Val(double(lResult + (usecs/100000)), TYPE_TIME);
|
||||
}
|
||||
|
||||
Val* GetStringFromPrincipalName(const KRB_Principal_Name* pname)
|
||||
{
|
||||
if ( pname->data()->size() == 1 )
|
||||
return bytestring_to_val(pname->data()[0][0]->encoding()->content());
|
||||
if ( pname->data()->size() == 2 )
|
||||
return new StringVal(fmt("%s/%s", (char *) pname->data()[0][0]->encoding()->content().begin(), (char *)pname->data()[0][1]->encoding()->content().begin()));
|
||||
|
||||
return new StringVal("unknown");
|
||||
}
|
||||
|
||||
Val* asn1_integer_to_val(const ASN1Integer* i, TypeTag t)
|
||||
{
|
||||
return asn1_integer_to_val(i->encoding(), t);
|
||||
}
|
||||
|
||||
Val* asn1_integer_to_val(const ASN1Encoding* i, TypeTag t)
|
||||
{
|
||||
return new Val(binary_to_int64(i->content()), t);
|
||||
}
|
||||
|
||||
RecordVal* proc_krb_kdc_options(const KRB_KDC_Options* opts)
|
||||
{
|
||||
RecordVal* rv = new RecordVal(BifType::Record::KRB::KDC_Options);
|
||||
|
@ -110,159 +27,6 @@ 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;
|
||||
|
@ -322,7 +86,7 @@ bool proc_error_arguments(RecordVal* rv, const std::vector<KRB_ERROR_Arg*>* args
|
|||
rv->Assign(9, bytestring_to_val((*args)[i]->args()->e_text()->encoding()->content()));
|
||||
break;
|
||||
case 12:
|
||||
if ( error_code == 25 )
|
||||
if ( error_code == KDC_ERR_PREAUTH_REQUIRED )
|
||||
rv->Assign(10, proc_padata((*args)[i]->args()->e_data()->padata(), NULL, true));
|
||||
break;
|
||||
default:
|
||||
|
@ -537,39 +301,39 @@ refine typeattr KRB_AS_REQ += &let {
|
|||
|
||||
refine typeattr KRB_TGS_REQ += &let {
|
||||
proc: bool = $context.connection.proc_krb_kdc_req(data);
|
||||
};
|
||||
};
|
||||
|
||||
refine typeattr KRB_AS_REP += &let {
|
||||
proc: bool = $context.connection.proc_krb_kdc_rep(data);
|
||||
};
|
||||
};
|
||||
|
||||
refine typeattr KRB_TGS_REP += &let {
|
||||
proc: bool = $context.connection.proc_krb_kdc_rep(data);
|
||||
};
|
||||
};
|
||||
|
||||
refine typeattr KRB_AP_REQ += &let {
|
||||
proc: bool = $context.connection.proc_krb_ap_req(this);
|
||||
};
|
||||
};
|
||||
|
||||
refine typeattr KRB_AP_REP += &let {
|
||||
proc: bool = $context.connection.proc_krb_ap_rep(this);
|
||||
};
|
||||
};
|
||||
|
||||
refine typeattr KRB_ERROR_MSG += &let {
|
||||
proc: bool = $context.connection.proc_krb_error_msg(this);
|
||||
};
|
||||
};
|
||||
|
||||
refine typeattr KRB_SAFE_MSG += &let {
|
||||
proc: bool = $context.connection.proc_krb_safe_msg(this);
|
||||
};
|
||||
};
|
||||
|
||||
refine typeattr KRB_PRIV_MSG += &let {
|
||||
proc: bool = $context.connection.proc_krb_priv_msg(this);
|
||||
};
|
||||
};
|
||||
|
||||
refine typeattr KRB_CRED_MSG += &let {
|
||||
proc: bool = $context.connection.proc_krb_cred_msg(this);
|
||||
};
|
||||
};
|
||||
|
||||
#refine typeattr KRB_REQ_Arg_Data += &let {
|
||||
# proc: bool = $context.connection.debug_req_arg(this);
|
||||
|
|
|
@ -1,3 +1,67 @@
|
|||
%header{
|
||||
Val* GetTimeFromAsn1(const KRB_Time* atime, int64 usecs);
|
||||
Val* GetTimeFromAsn1(StringVal* atime, int64 usecs);
|
||||
|
||||
Val* asn1_integer_to_val(const ASN1Encoding* i, TypeTag t);
|
||||
Val* asn1_integer_to_val(const ASN1Integer* i, TypeTag t);
|
||||
%}
|
||||
|
||||
%code{
|
||||
Val* GetTimeFromAsn1(const KRB_Time* atime, int64 usecs)
|
||||
{
|
||||
return GetTimeFromAsn1(bytestring_to_val(atime->time()), usecs);
|
||||
}
|
||||
|
||||
Val* GetTimeFromAsn1(StringVal* atime, int64 usecs)
|
||||
{
|
||||
time_t lResult = 0;
|
||||
|
||||
char lBuffer[17];
|
||||
char* pBuffer = lBuffer;
|
||||
|
||||
size_t lTimeLength = atime->Len();
|
||||
char * pString = (char *) atime->Bytes();
|
||||
|
||||
if ( lTimeLength != 15 && lTimeLength != 17 )
|
||||
return 0;
|
||||
|
||||
if (lTimeLength == 17 )
|
||||
pString = pString + 2;
|
||||
|
||||
memcpy(pBuffer, pString, 15);
|
||||
*(pBuffer+15) = '\0';
|
||||
|
||||
tm lTime;
|
||||
lTime.tm_sec = ((lBuffer[12] - '0') * 10) + (lBuffer[13] - '0');
|
||||
lTime.tm_min = ((lBuffer[10] - '0') * 10) + (lBuffer[11] - '0');
|
||||
lTime.tm_hour = ((lBuffer[8] - '0') * 10) + (lBuffer[9] - '0');
|
||||
lTime.tm_mday = ((lBuffer[6] - '0') * 10) + (lBuffer[7] - '0');
|
||||
lTime.tm_mon = (((lBuffer[4] - '0') * 10) + (lBuffer[5] - '0')) - 1;
|
||||
lTime.tm_year = ((lBuffer[0] - '0') * 1000) + ((lBuffer[1] - '0') * 100) + ((lBuffer[2] - '0') * 10) + (lBuffer[3] - '0') - 1900;
|
||||
|
||||
lTime.tm_wday = 0;
|
||||
lTime.tm_yday = 0;
|
||||
lTime.tm_isdst = 0;
|
||||
|
||||
lResult = timegm(&lTime);
|
||||
|
||||
if ( !lResult )
|
||||
lResult = 0;
|
||||
|
||||
return new Val(double(lResult + (usecs/100000)), TYPE_TIME);
|
||||
}
|
||||
|
||||
Val* asn1_integer_to_val(const ASN1Integer* i, TypeTag t)
|
||||
{
|
||||
return asn1_integer_to_val(i->encoding(), t);
|
||||
}
|
||||
|
||||
Val* asn1_integer_to_val(const ASN1Encoding* i, TypeTag t)
|
||||
{
|
||||
return new Val(binary_to_int64(i->content()), t);
|
||||
}
|
||||
%}
|
||||
|
||||
type ASN1Encoding = record {
|
||||
meta: ASN1EncodingMeta;
|
||||
content: bytestring &length = meta.length;
|
||||
|
@ -10,8 +74,8 @@ type ASN1EncodingMeta = record {
|
|||
} &let {
|
||||
long_len: bool = (len & 0x80) > 0;
|
||||
length: uint64 = long_len ? binary_to_int64(more_len) : len;
|
||||
has_index: bool = (tag >= 160);
|
||||
index: uint8 = tag - 160;
|
||||
has_index: bool = (tag >= ASN1_INDEX_TAG_OFFSET);
|
||||
index: uint8 = tag - ASN1_INDEX_TAG_OFFSET;
|
||||
};
|
||||
|
||||
type ASN1OptionalEncodingMeta(is_present: bool, previous_metadata: ASN1EncodingMeta) = case is_present of {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
# Defined in RFC 4120
|
||||
enum KRBMessageTypes {
|
||||
AS_REQ = 10,
|
||||
AS_REP = 11,
|
||||
|
@ -11,3 +12,23 @@ enum KRBMessageTypes {
|
|||
KRB_ERROR = 30,
|
||||
};
|
||||
|
||||
# Defined by IANA in Kerberos Parameters - Pre-authentication and Typed Data
|
||||
enum KRBPADataTypes {
|
||||
PA_TGS_REQ = 1,
|
||||
PA_ENC_TIMESTAMP = 2,
|
||||
PA_PW_SALT = 3,
|
||||
PA_PW_AS_REQ = 16,
|
||||
PA_PW_AS_REP = 17,
|
||||
};
|
||||
|
||||
# Defined in RFC 4120
|
||||
enum KRBErrorCodes {
|
||||
KDC_ERR_PREAUTH_REQUIRED = 25,
|
||||
};
|
||||
|
||||
# Defined in ASN.1
|
||||
enum ASN1Consts {
|
||||
ASN1_SEQUENCE_TAG = 48,
|
||||
ASN1_APP_TAG_OFFSET = 96,
|
||||
ASN1_INDEX_TAG_OFFSET = 160,
|
||||
};
|
||||
|
|
|
@ -1,24 +1,156 @@
|
|||
# Kerberos pre-authentication data is a significant piece of the complexity,
|
||||
# so we're splitting this off
|
||||
|
||||
%extern{
|
||||
#include "file_analysis/Manager.h"
|
||||
%}
|
||||
|
||||
%header{
|
||||
VectorVal* proc_padata(const KRB_PA_Data_Sequence* data, const BroAnalyzer bro_analyzer, bool is_error);
|
||||
%}
|
||||
|
||||
%code{
|
||||
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());
|
||||
|
||||
if ( ! data->data()->has_padata() )
|
||||
return vv;
|
||||
|
||||
for ( uint i = 0; i < data->data()->padata_elems()->size(); ++i)
|
||||
{
|
||||
KRB_PA_Data* element = (*data->data()->padata_elems())[i];
|
||||
int64 data_type = element->data_type();
|
||||
|
||||
if ( is_error && ( data_type == PA_PW_AS_REQ || data_type == PA_PW_AS_REP ) )
|
||||
data_type = 0;
|
||||
|
||||
switch( data_type )
|
||||
{
|
||||
case PA_TGS_REQ:
|
||||
// will be generated as separate event
|
||||
break;
|
||||
case PA_ENC_TIMESTAMP:
|
||||
// encrypted timestamp is unreadable
|
||||
break;
|
||||
case PA_PW_SALT:
|
||||
{
|
||||
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 PA_PW_AS_REQ:
|
||||
{
|
||||
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());
|
||||
// Request means is_orig=T
|
||||
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 PA_PW_AS_REP:
|
||||
{
|
||||
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());
|
||||
// Response means is_orig=F
|
||||
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;
|
||||
}
|
||||
%}
|
||||
|
||||
# Basic structure:
|
||||
# 1) In KDC_REQ/KDC_REP packets, the PA_Data is optional and needs a bit of "lookahead."
|
||||
# KRB_PA_Data_Optional -> KRB_PA_Data_Optional_Contents -> KRB_PA_Data_Sequence
|
||||
#
|
||||
# 2) Once we get to the KRB_PA_Data_Sequence level:
|
||||
# KRB_PA_Data_Sequence -> KRB_PA_Data_Container -> KRB_PA_Data -> KRB_PA_Data_Element
|
||||
|
||||
|
||||
# Encapsulating header #1 for KDC_REQ/KDC_REP packets where the PADATA is optional.
|
||||
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);
|
||||
padata : KRB_PA_Data_Optional_Contents(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 {
|
||||
# Encapsulating header #2 for KDC_REQ/KDC_REP packets where the PADATA is optional.
|
||||
#
|
||||
# Note: Split off due to a BinPAC bug
|
||||
type KRB_PA_Data_Optional_Contents(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;
|
||||
};
|
||||
|
||||
# This is our main type
|
||||
type KRB_PA_Data_Sequence(pkt_type: uint8) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
padata_elems: KRB_PA_Data(pkt_type)[];
|
||||
meta : ASN1EncodingMeta;
|
||||
data : KRB_PA_Data_Container(pkt_type, meta.tag, meta.length);
|
||||
};
|
||||
|
||||
# The data in KRB_PA_Data_Sequence is usually (and supposed to be) a sequence, which we'll parse,
|
||||
# but is sometimes an octet string. We'll grab that but ignore it.
|
||||
#
|
||||
# Note: This is a separate type due to a BinPAC bug.
|
||||
type KRB_PA_Data_Container(pkt_type: uint8, tag: uint8, length: uint64) = case tag of {
|
||||
ASN1_SEQUENCE_TAG -> padata_elems : KRB_PA_Data(pkt_type)[];
|
||||
default -> unknown : bytestring &length=length;
|
||||
} &let {
|
||||
has_padata: bool = (tag == ASN1_SEQUENCE_TAG);
|
||||
};
|
||||
|
||||
# The pre-auth data sequence.
|
||||
#
|
||||
# Note: Error packets don't have pre-auth data, they just advertise which mechanisms they support.
|
||||
type KRB_PA_Data(pkt_type: uint8) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
pa_data_type : SequenceElement(true);
|
||||
|
@ -31,21 +163,24 @@ type KRB_PA_Data(pkt_type: uint8) = record {
|
|||
data_type: int64 = binary_to_int64(pa_data_type.data.content);
|
||||
};
|
||||
|
||||
# Each pre-auth element
|
||||
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;
|
||||
PA_TGS_REQ -> pa_tgs_req : KRB_AP_REQ;
|
||||
PA_PW_SALT -> pa_pw_salt : ASN1OctetString;
|
||||
PA_PW_AS_REQ -> pa_pk_as_req : KRB_PA_PK_AS_Req &length=length;
|
||||
PA_PW_AS_REP -> pa_pk_as_rep : KRB_PA_PK_AS_Rep &length=length;
|
||||
default -> unknown : bytestring &length=length;
|
||||
};
|
||||
|
||||
|
||||
# The PKINIT certificate structure for a request
|
||||
type KRB_PA_PK_AS_Req = record {
|
||||
string_meta : ASN1EncodingMeta;
|
||||
string_meta : ASN1EncodingMeta;
|
||||
seq_meta1 : ASN1EncodingMeta;
|
||||
elem_0_meta1: ASN1EncodingMeta;
|
||||
elem_0_meta1 : ASN1EncodingMeta;
|
||||
seq_meta2 : ASN1EncodingMeta;
|
||||
oid : ASN1Encoding;
|
||||
elem_0_meta2: ASN1EncodingMeta;
|
||||
oid : ASN1Encoding;
|
||||
elem_0_meta2 : ASN1EncodingMeta;
|
||||
seq_meta3 : ASN1EncodingMeta;
|
||||
version : ASN1Encoding;
|
||||
digest_algs : ASN1Encoding;
|
||||
|
@ -53,17 +188,18 @@ type KRB_PA_PK_AS_Req = record {
|
|||
cert_meta : ASN1EncodingMeta;
|
||||
cert : bytestring &length=cert_meta.length;
|
||||
# Ignore everything else
|
||||
: bytestring &restofdata &transient;
|
||||
: bytestring &restofdata &transient;
|
||||
};
|
||||
|
||||
# The PKINIT certificate structure for a reply
|
||||
type KRB_PA_PK_AS_Rep = record {
|
||||
string_meta : ASN1EncodingMeta;
|
||||
elem_0_meta1: ASN1EncodingMeta;
|
||||
string_meta : ASN1EncodingMeta;
|
||||
elem_0_meta1 : ASN1EncodingMeta;
|
||||
seq_meta1 : ASN1EncodingMeta;
|
||||
elem_0_meta2: ASN1EncodingMeta;
|
||||
elem_0_meta2 : ASN1EncodingMeta;
|
||||
seq_meta2 : ASN1EncodingMeta;
|
||||
oid : ASN1Encoding;
|
||||
elem_0_meta3: ASN1EncodingMeta;
|
||||
oid : ASN1Encoding;
|
||||
elem_0_meta3 : ASN1EncodingMeta;
|
||||
seq_meta3 : ASN1EncodingMeta;
|
||||
version : ASN1Encoding;
|
||||
digest_algs : ASN1Encoding;
|
||||
|
@ -71,6 +207,6 @@ type KRB_PA_PK_AS_Rep = record {
|
|||
cert_meta : ASN1EncodingMeta;
|
||||
cert : bytestring &length=cert_meta.length;
|
||||
# Ignore everything else
|
||||
: bytestring &restofdata &transient;
|
||||
: bytestring &restofdata &transient;
|
||||
};
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ type KRB_PDU_TCP = record {
|
|||
|
||||
type KRB_PDU = record {
|
||||
app_meta : ASN1EncodingMeta;
|
||||
msg_type : case (app_meta.tag - 96) of {
|
||||
msg_type : case (app_meta.tag - ASN1_APP_TAG_OFFSET) of {
|
||||
AS_REQ -> as_req : KRB_AS_REQ;
|
||||
AS_REP -> as_rep : KRB_AS_REP;
|
||||
TGS_REQ -> tgs_req : KRB_TGS_REQ;
|
||||
|
@ -188,7 +188,7 @@ type KRB_ERROR_Arg_Data(index: uint8, error_code: int64) = case index of {
|
|||
12 -> e_data : KRB_ERROR_E_Data(error_code);
|
||||
};
|
||||
|
||||
type KRB_ERROR_E_Data(error_code: uint64) = case ( error_code == 25 ) of {
|
||||
type KRB_ERROR_E_Data(error_code: uint64) = case ( error_code == KDC_ERR_PREAUTH_REQUIRED ) of {
|
||||
true -> padata : KRB_PA_Data_Sequence(KRB_ERROR);
|
||||
false -> unknown : bytestring &restofdata;
|
||||
};
|
||||
|
|
|
@ -1,5 +1,89 @@
|
|||
# Fundamental KRB types
|
||||
|
||||
%header{
|
||||
Val* GetStringFromPrincipalName(const KRB_Principal_Name* pname);
|
||||
|
||||
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);
|
||||
%}
|
||||
|
||||
%code{
|
||||
Val* GetStringFromPrincipalName(const KRB_Principal_Name* pname)
|
||||
{
|
||||
if ( pname->data()->size() == 1 )
|
||||
return bytestring_to_val(pname->data()[0][0]->encoding()->content());
|
||||
if ( pname->data()->size() == 2 )
|
||||
return new StringVal(fmt("%s/%s", (char *) pname->data()[0][0]->encoding()->content().begin(), (char *)pname->data()[0][1]->encoding()->content().begin()));
|
||||
|
||||
return new StringVal("unknown");
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
%}
|
||||
|
||||
type KRB_Principal_Name = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
name_meta : ASN1EncodingMeta;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue