diff --git a/scripts/base/init-bare.bro b/scripts/base/init-bare.bro index bd2206ceab..9b2f58ec46 100644 --- a/scripts/base/init-bare.bro +++ b/scripts/base/init-bare.bro @@ -4222,6 +4222,7 @@ export { module KRB; export { + const keytab = "/etc/krb5.keytab" &redef; ## KDC Options. See :rfc:`4120` type KRB::KDC_Options: record { ## The ticket to be issued should have its forwardable flag set. @@ -4344,6 +4345,8 @@ export { cipher : count; ## Cipher text of the ticket ciphertext : string &optional; + ## Authentication info + authenticationinfo: string &optional; }; type KRB::Ticket_Vector: vector of KRB::Ticket; diff --git a/src/analyzer/protocol/krb/CMakeLists.txt b/src/analyzer/protocol/krb/CMakeLists.txt index 1cac35d626..95f6d672a1 100644 --- a/src/analyzer/protocol/krb/CMakeLists.txt +++ b/src/analyzer/protocol/krb/CMakeLists.txt @@ -9,6 +9,7 @@ bro_plugin_cc(KRB.cc) bro_plugin_cc(KRB_TCP.cc) bro_plugin_bif(types.bif) bro_plugin_bif(events.bif) +bro_plugin_link_library(-lkrb5) bro_plugin_pac(krb.pac krb-protocol.pac krb-analyzer.pac krb-asn1.pac krb-defs.pac diff --git a/src/analyzer/protocol/krb/KRB.cc b/src/analyzer/protocol/krb/KRB.cc index ba7dbd9ccd..f080efa7f0 100644 --- a/src/analyzer/protocol/krb/KRB.cc +++ b/src/analyzer/protocol/krb/KRB.cc @@ -7,13 +7,47 @@ using namespace analyzer::krb; KRB_Analyzer::KRB_Analyzer(Connection* conn) - : Analyzer("KRB", conn) + : Analyzer("KRB", conn), + krb_available(false) { interp = new binpac::KRB::KRB_Conn(this); + + const char* keytab_filename = BifConst::KRB::keytab->CheckString(); + if (access(keytab_filename, R_OK) != 0) + { + reporter->Warning("KRB: Can't access keytab (%s)", keytab_filename); + return; + } + + krb5_error_code retval = krb5_init_context(&krb_context); + if (retval) + { + reporter->Warning("KRB: Couldn't initialize the context (%s)", krb5_get_error_message(krb_context, retval)); + } + else + { + krb_available = true; + + retval = krb5_kt_resolve(krb_context, keytab_filename, &krb_keytab); + if (retval) + { + reporter->Warning("KRB: Couldn't resolve keytab (%s)", krb5_get_error_message(krb_context, retval)); + } + } + } KRB_Analyzer::~KRB_Analyzer() { + if (krb_available) + { + krb5_error_code retval = krb5_kt_close(krb_context, krb_keytab); + if (retval) + { + reporter->Warning("KRB: Couldn't close keytab (%s)", krb5_get_error_message(krb_context, retval)); + } + krb5_free_context(krb_context); + } delete interp; } @@ -37,3 +71,67 @@ void KRB_Analyzer::DeliverPacket(int len, const u_char* data, bool orig, } } +StringVal* KRB_Analyzer::GetAuthenticationInfo(const BroString* principal, const BroString* ciphertext, const bro_uint_t enctype) + { + StringVal* ret = new StringVal("nouser"); + if (!krb_available) + { + return ret; + } + + BroString delim("/"); + int pos = principal->FindSubstring(&delim); + if (pos == -1) + { + reporter->Warning("KRB: Couldn't parse principal (%s)", principal->CheckString()); + return ret; + } + BroString* service(principal->GetSubstring(0, pos)); + BroString* hostname(principal->GetSubstring(pos + 1, -1)); + if (!service || !hostname) + { + reporter->Warning("KRB: Couldn't parse principal (%s)", principal->CheckString()); + if (!service) + free(service); + if (!hostname) + free(hostname); + return ret; + } + krb5_principal sprinc; + krb5_error_code retval = krb5_sname_to_principal(krb_context, reinterpret_cast(hostname->Bytes()), reinterpret_cast(service->Bytes()), KRB5_NT_SRV_HST, &sprinc); + if (retval) + { + reporter->Warning("KRB: Couldn't generate principal name (%s)", krb5_get_error_message(krb_context, retval)); + return ret; + } + free(service); + free(hostname); + + krb5_ticket tkt; + tkt.server = sprinc; + tkt.enc_part.enctype = enctype; + tkt.enc_part.ciphertext.data = reinterpret_cast(ciphertext->Bytes()); + tkt.enc_part.ciphertext.length = ciphertext->Len(); + + retval = krb5_server_decrypt_ticket_keytab(krb_context, krb_keytab, &tkt); + if (retval) + { + reporter->Warning("KRB: Couldn't decrypt ticket (%s)", krb5_get_error_message(krb_context, retval)); + return ret; + } + + char* cp; + retval = krb5_unparse_name(krb_context, tkt.enc_part2->client, &cp); + if (retval) + { + reporter->Warning("KRB: Couldn't unparse name (%s)", krb5_get_error_message(krb_context, retval)); + return ret; + } + free(ret); + ret = new StringVal(cp); + + krb5_free_unparsed_name(krb_context, cp); + + return ret; + + } diff --git a/src/analyzer/protocol/krb/KRB.h b/src/analyzer/protocol/krb/KRB.h index 99e0529ff1..52cf9fa2bb 100644 --- a/src/analyzer/protocol/krb/KRB.h +++ b/src/analyzer/protocol/krb/KRB.h @@ -5,6 +5,8 @@ #include "krb_pac.h" +#include + namespace analyzer { namespace krb { class KRB_Analyzer : public analyzer::Analyzer { @@ -20,9 +22,15 @@ public: static analyzer::Analyzer* Instantiate(Connection* conn) { return new KRB_Analyzer(conn); } + StringVal* GetAuthenticationInfo(const BroString* principal, const BroString* ciphertext, const bro_uint_t enctype); + protected: binpac::KRB::KRB_Conn* interp; + + bool krb_available; + krb5_context krb_context; + krb5_keytab krb_keytab; }; } } // namespace analyzer::* diff --git a/src/analyzer/protocol/krb/KRB_TCP.h b/src/analyzer/protocol/krb/KRB_TCP.h index 0ce4d5f65d..f6c679be63 100644 --- a/src/analyzer/protocol/krb/KRB_TCP.h +++ b/src/analyzer/protocol/krb/KRB_TCP.h @@ -22,6 +22,8 @@ public: // Overriden from tcp::TCP_ApplicationAnalyzer. void EndpointEOF(bool is_orig) override; + StringVal* GetAuthenticationInfo(const BroString* principal, const BroString* ciphertext, const bro_uint_t enctype) { return new StringVal(""); } + static analyzer::Analyzer* Instantiate(Connection* conn) { return new KRB_Analyzer(conn); } diff --git a/src/analyzer/protocol/krb/krb-analyzer.pac b/src/analyzer/protocol/krb/krb-analyzer.pac index 6390fb8fd0..2af70fff98 100644 --- a/src/analyzer/protocol/krb/krb-analyzer.pac +++ b/src/analyzer/protocol/krb/krb-analyzer.pac @@ -245,8 +245,11 @@ refine connection KRB_Conn += { rv->Assign(0, new Val(${msg.ap_options.use_session_key}, TYPE_BOOL)); rv->Assign(1, new Val(${msg.ap_options.mutual_required}, TYPE_BOOL)); + RecordVal* rvticket = proc_ticket(${msg.ticket}); + StringVal* authenticationinfo = bro_analyzer()->GetAuthenticationInfo(rvticket->Lookup(2)->AsString(), rvticket->Lookup(4)->AsString(), rvticket->Lookup(3)->AsCount()); + rvticket->Assign(5, authenticationinfo); BifEvent::generate_krb_ap_request(bro_analyzer(), bro_analyzer()->Conn(), - proc_ticket(${msg.ticket}), rv); + rvticket, rv); } return true; %} diff --git a/src/analyzer/protocol/krb/krb.pac b/src/analyzer/protocol/krb/krb.pac index 508fb78a7a..9a3b290ad1 100644 --- a/src/analyzer/protocol/krb/krb.pac +++ b/src/analyzer/protocol/krb/krb.pac @@ -4,14 +4,22 @@ %extern{ #include "types.bif.h" #include "events.bif.h" + +namespace analyzer { namespace krb { class KRB_Analyzer; } } +namespace binpac { namespace KRB { class KRB_Conn; } } +typedef analyzer::krb::KRB_Analyzer* KRBAnalyzer; + +#include "KRB.h" %} +extern type KRBAnalyzer; + analyzer KRB withcontext { connection: KRB_Conn; flow: KRB_Flow; }; -connection KRB_Conn(bro_analyzer: BroAnalyzer) { +connection KRB_Conn(bro_analyzer: KRBAnalyzer) { upflow = KRB_Flow(true); downflow = KRB_Flow(false); }; diff --git a/src/analyzer/protocol/krb/krb_TCP.pac b/src/analyzer/protocol/krb/krb_TCP.pac index 6748c5fcbb..6611a549e4 100644 --- a/src/analyzer/protocol/krb/krb_TCP.pac +++ b/src/analyzer/protocol/krb/krb_TCP.pac @@ -4,14 +4,22 @@ %extern{ #include "types.bif.h" #include "events.bif.h" + +namespace analyzer { namespace krb_tcp { class KRB_Analyzer; } } +namespace binpac { namespace KRB_TCP { class KRB_Conn; } } +typedef analyzer::krb_tcp::KRB_Analyzer* KRBTCPAnalyzer; + +#include "KRB_TCP.h" %} +extern type KRBTCPAnalyzer; + analyzer KRB_TCP withcontext { connection: KRB_Conn; flow: KRB_Flow; }; -connection KRB_Conn(bro_analyzer: BroAnalyzer) { +connection KRB_Conn(bro_analyzer: KRBTCPAnalyzer) { upflow = KRB_Flow(true); downflow = KRB_Flow(false); }; diff --git a/src/analyzer/protocol/krb/types.bif b/src/analyzer/protocol/krb/types.bif index 8393adbf3c..11a80781f8 100644 --- a/src/analyzer/protocol/krb/types.bif +++ b/src/analyzer/protocol/krb/types.bif @@ -1,5 +1,7 @@ module KRB; +const keytab: string; + type Error_Msg: record; type SAFE_Msg: record;