diff --git a/src/analyzer/protocol/krb/krb-analyzer.pac b/src/analyzer/protocol/krb/krb-analyzer.pac index 2cde4e42c1..71d6a48ed5 100644 --- a/src/analyzer/protocol/krb/krb-analyzer.pac +++ b/src/analyzer/protocol/krb/krb-analyzer.pac @@ -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* 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(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(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* 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(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(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); +}; \ No newline at end of file diff --git a/src/analyzer/protocol/krb/krb-asn1.pac b/src/analyzer/protocol/krb/krb-asn1.pac index 38e69dd4f7..5706c02384 100644 --- a/src/analyzer/protocol/krb/krb-asn1.pac +++ b/src/analyzer/protocol/krb/krb-asn1.pac @@ -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; }; diff --git a/src/analyzer/protocol/krb/krb-defs.pac b/src/analyzer/protocol/krb/krb-defs.pac new file mode 100644 index 0000000000..fc801ccffa --- /dev/null +++ b/src/analyzer/protocol/krb/krb-defs.pac @@ -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, +}; + diff --git a/src/analyzer/protocol/krb/krb-padata.pac b/src/analyzer/protocol/krb/krb-padata.pac new file mode 100644 index 0000000000..bcf66ee208 --- /dev/null +++ b/src/analyzer/protocol/krb/krb-padata.pac @@ -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; +}; + diff --git a/src/analyzer/protocol/krb/krb-protocol.pac b/src/analyzer/protocol/krb/krb-protocol.pac index d3c7854099..1ec6e75cca 100644 --- a/src/analyzer/protocol/krb/krb-protocol.pac +++ b/src/analyzer/protocol/krb/krb-protocol.pac @@ -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 { diff --git a/src/analyzer/protocol/krb/krb-types.pac b/src/analyzer/protocol/krb/krb-types.pac new file mode 100644 index 0000000000..9ada8a137c --- /dev/null +++ b/src/analyzer/protocol/krb/krb-types.pac @@ -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); +}; +