mirror of
https://github.com/zeek/zeek.git
synced 2025-10-13 03:58:20 +00:00
Kerberos analyzer
This commit is contained in:
parent
3cea6ab1eb
commit
ca55d203cb
16 changed files with 1432 additions and 0 deletions
|
@ -2971,6 +2971,158 @@ export {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@load base/bif/plugins/Bro_KRB.types.bif
|
||||||
|
|
||||||
|
module KRB;
|
||||||
|
export {
|
||||||
|
## The data from the ERROR_MSG message. See :rfc:`4120`.
|
||||||
|
type KRB::Error_Msg: record {
|
||||||
|
## Protocol version number (5 for KRB5)
|
||||||
|
pvno: count;
|
||||||
|
## The message type (30 for ERROR_MSG)
|
||||||
|
msg_type: count;
|
||||||
|
## Current time on the client
|
||||||
|
client_time: time &optional;
|
||||||
|
## Current time on the server
|
||||||
|
server_time: time;
|
||||||
|
## The specific error code
|
||||||
|
error_code: count;
|
||||||
|
## Realm of the ticket
|
||||||
|
client_realm: string &optional;
|
||||||
|
## Name on the ticket
|
||||||
|
client_name: string &optional;
|
||||||
|
## Realm of the service
|
||||||
|
service_realm: string;
|
||||||
|
## Name of the service
|
||||||
|
service_name: string;
|
||||||
|
## Additional text to explain the error
|
||||||
|
error_text: string &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
## KDC Options. See :rfc:`4120`
|
||||||
|
type KRB::KDC_Options: record {
|
||||||
|
## The ticket to be issued should have its forwardable flag set.
|
||||||
|
forwardable : bool;
|
||||||
|
## A (TGT) request for forwarding.
|
||||||
|
forwarded : bool;
|
||||||
|
## The ticket to be issued should have its proxiable flag set.
|
||||||
|
proxiable : bool;
|
||||||
|
## A request for a proxy.
|
||||||
|
proxy : bool;
|
||||||
|
## The ticket to be issued should have its may-postdate flag set.
|
||||||
|
allow_postdate : bool;
|
||||||
|
## A request for a postdated ticket.
|
||||||
|
postdated : bool;
|
||||||
|
## The ticket to be issued should have its renewable flag set.
|
||||||
|
renewable : bool;
|
||||||
|
## Reserved for opt_hardware_auth
|
||||||
|
opt_hardware_auth : bool;
|
||||||
|
## Request that the KDC not check the transited field of a TGT against
|
||||||
|
## the policy of the local realm before it will issue derivative tickets
|
||||||
|
## based on the TGT.
|
||||||
|
disable_transited_check : bool;
|
||||||
|
## If a ticket with the requested lifetime cannot be issued, a renewable
|
||||||
|
## ticket is acceptable
|
||||||
|
renewable_ok : bool;
|
||||||
|
## The ticket for the end server is to be encrypted in the session key
|
||||||
|
## from the additional TGT provided
|
||||||
|
enc_tkt_in_skey : bool;
|
||||||
|
## The request is for a renewal
|
||||||
|
renew : bool;
|
||||||
|
## The request ist to validate a postdated ticket.
|
||||||
|
validate : bool;
|
||||||
|
};
|
||||||
|
|
||||||
|
## Used in a few places in the Kerberos analyzer for elements
|
||||||
|
## that have a type and a string value.
|
||||||
|
type KRB::Type_Value: record {
|
||||||
|
## The data type
|
||||||
|
data_type : count;
|
||||||
|
## The data value
|
||||||
|
val : string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB::Type_Value_Vector: vector of KRB::Type_Value;
|
||||||
|
|
||||||
|
## A Kerberos ticket. See :rfc:`4120`.
|
||||||
|
type KRB::Ticket: record {
|
||||||
|
## Protocol version number (5 for KRB5)
|
||||||
|
pvno : count;
|
||||||
|
## Realm
|
||||||
|
realm : string;
|
||||||
|
## Name of the service
|
||||||
|
service_name: string;
|
||||||
|
## Cipher the ticket was encrypted with
|
||||||
|
cipher : count;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB::Ticket_Vector: vector of KRB::Ticket;
|
||||||
|
|
||||||
|
## A Kerberos host address See :rfc:`4120`.
|
||||||
|
type KRB::Host_Address: record {
|
||||||
|
## IPv4 or IPv6 address
|
||||||
|
ip : addr &optional;
|
||||||
|
## NetBIOS address
|
||||||
|
netbios : string &optional;
|
||||||
|
## Some other type that we don't support yet
|
||||||
|
unknown : KRB::Type_Value &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB::Host_Address_Vector: vector of KRB::Host_Address;
|
||||||
|
|
||||||
|
## The data from the AS_REQ and TGS_REQ messages. See :rfc:`4120`.
|
||||||
|
type KRB::KDC_Request: record {
|
||||||
|
## Protocol version number (5 for KRB5)
|
||||||
|
pvno : count;
|
||||||
|
## The message type (10 for AS_REQ, 12 for TGS_REQ)
|
||||||
|
msg_type : count;
|
||||||
|
## Optional pre-authentication data
|
||||||
|
pa_data : vector of KRB::Type_Value &optional;
|
||||||
|
## Options specified in the request
|
||||||
|
kdc_options : KRB::KDC_Options;
|
||||||
|
## Name on the ticket
|
||||||
|
client_name : string &optional;
|
||||||
|
|
||||||
|
## Realm of the service
|
||||||
|
service_realm : string;
|
||||||
|
## Name of the service
|
||||||
|
service_name : string &optional;
|
||||||
|
## Time the ticket is good from
|
||||||
|
from : time &optional;
|
||||||
|
## Time the ticket is good till
|
||||||
|
till : time;
|
||||||
|
## The requested renew-till time
|
||||||
|
rtime : time &optional;
|
||||||
|
|
||||||
|
## A random nonce generated by the client
|
||||||
|
nonce : count;
|
||||||
|
## The desired encryption algorithms, in order of preference
|
||||||
|
encryption_types : vector of count;
|
||||||
|
## Any additional addresses the ticket should be valid for
|
||||||
|
host_addrs : vector of KRB::Host_Address &optional;
|
||||||
|
## Additional tickets may be included for certain transactions
|
||||||
|
additional_tickets : vector of KRB::Ticket &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
## The data from the AS_REQ and TGS_REQ messages. See :rfc:`4120`.
|
||||||
|
type KRB::KDC_Reply: record {
|
||||||
|
## Protocol version number (5 for KRB5)
|
||||||
|
pvno : count;
|
||||||
|
## The message type (11 for AS_REP, 13 for TGS_REP)
|
||||||
|
msg_type : count;
|
||||||
|
## Optional pre-authentication data
|
||||||
|
pa_data : vector of KRB::Type_Value &optional;
|
||||||
|
## Realm on the ticket
|
||||||
|
client_realm : string &optional;
|
||||||
|
## Name on the service
|
||||||
|
client_name : string;
|
||||||
|
|
||||||
|
## The ticket that was issued
|
||||||
|
ticket : KRB::Ticket;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
module GLOBAL;
|
module GLOBAL;
|
||||||
|
|
||||||
@load base/bif/event.bif
|
@load base/bif/event.bif
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
@load base/protocols/ftp
|
@load base/protocols/ftp
|
||||||
@load base/protocols/http
|
@load base/protocols/http
|
||||||
@load base/protocols/irc
|
@load base/protocols/irc
|
||||||
|
@load base/protocols/krb
|
||||||
@load base/protocols/modbus
|
@load base/protocols/modbus
|
||||||
@load base/protocols/pop3
|
@load base/protocols/pop3
|
||||||
@load base/protocols/radius
|
@load base/protocols/radius
|
||||||
|
|
2
scripts/base/protocols/krb/__load__.bro
Normal file
2
scripts/base/protocols/krb/__load__.bro
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
@load ./main
|
||||||
|
@load-sigs ./dpd.sig
|
76
scripts/base/protocols/krb/consts.bro
Normal file
76
scripts/base/protocols/krb/consts.bro
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
module KRB;
|
||||||
|
|
||||||
|
export {
|
||||||
|
|
||||||
|
const error_msg: table[count] of string = {
|
||||||
|
[0] = "KDC_ERR_NONE",
|
||||||
|
[1] = "KDC_ERR_NAME_EXP",
|
||||||
|
[2] = "KDC_ERR_SERVICE_EXP",
|
||||||
|
[3] = "KDC_ERR_BAD_PVNO",
|
||||||
|
[4] = "KDC_ERR_C_OLD_MAST_KVNO",
|
||||||
|
[5] = "KDC_ERR_S_OLD_MAST_KVNO",
|
||||||
|
[6] = "KDC_ERR_C_PRINCIPAL_UNKNOWN",
|
||||||
|
[7] = "KDC_ERR_S_PRINCIPAL_UNKNOWN",
|
||||||
|
[8] = "KDC_ERR_PRINCIPAL_NOT_UNIQUE",
|
||||||
|
[9] = "KDC_ERR_NULL_KEY",
|
||||||
|
[10] = "KDC_ERR_CANNOT_POSTDATE",
|
||||||
|
[11] = "KDC_ERR_NEVER_VALID",
|
||||||
|
[12] = "KDC_ERR_POLICY",
|
||||||
|
[13] = "KDC_ERR_BADOPTION",
|
||||||
|
[14] = "KDC_ERR_ETYPE_NOSUPP",
|
||||||
|
[15] = "KDC_ERR_SUMTYPE_NOSUPP",
|
||||||
|
[16] = "KDC_ERR_PADATA_TYPE_NOSUPP",
|
||||||
|
[17] = "KDC_ERR_TRTYPE_NOSUPP",
|
||||||
|
[18] = "KDC_ERR_CLIENT_REVOKED",
|
||||||
|
[19] = "KDC_ERR_SERVICE_REVOKED",
|
||||||
|
[20] = "KDC_ERR_TGT_REVOKED",
|
||||||
|
[21] = "KDC_ERR_CLIENT_NOTYET",
|
||||||
|
[22] = "KDC_ERR_SERVICE_NOTYET",
|
||||||
|
[23] = "KDC_ERR_KEY_EXPIRED",
|
||||||
|
[24] = "KDC_ERR_PREAUTH_FAILED",
|
||||||
|
[25] = "KDC_ERR_PREAUTH_REQUIRED",
|
||||||
|
[26] = "KDC_ERR_SERVER_NOMATCH",
|
||||||
|
[27] = "KDC_ERR_MUST_USE_USER2USER",
|
||||||
|
[28] = "KDC_ERR_PATH_NOT_ACCEPTED",
|
||||||
|
[29] = "KDC_ERR_SVC_UNAVAILABLE",
|
||||||
|
[31] = "KRB_AP_ERR_BAD_INTEGRITY",
|
||||||
|
[32] = "KRB_AP_ERR_TKT_EXPIRED",
|
||||||
|
[33] = "KRB_AP_ERR_TKT_NYV",
|
||||||
|
[34] = "KRB_AP_ERR_REPEAT",
|
||||||
|
[35] = "KRB_AP_ERR_NOT_US",
|
||||||
|
[36] = "KRB_AP_ERR_BADMATCH",
|
||||||
|
[37] = "KRB_AP_ERR_SKEW",
|
||||||
|
[38] = "KRB_AP_ERR_BADADDR",
|
||||||
|
[39] = "KRB_AP_ERR_BADVERSION",
|
||||||
|
[40] = "KRB_AP_ERR_MSG_TYPE",
|
||||||
|
[41] = "KRB_AP_ERR_MODIFIED",
|
||||||
|
[42] = "KRB_AP_ERR_BADORDER",
|
||||||
|
[44] = "KRB_AP_ERR_BADKEYVER",
|
||||||
|
[45] = "KRB_AP_ERR_NOKEY",
|
||||||
|
[46] = "KRB_AP_ERR_MUT_FAIL",
|
||||||
|
[47] = "KRB_AP_ERR_BADDIRECTION",
|
||||||
|
[48] = "KRB_AP_ERR_METHOD",
|
||||||
|
[49] = "KRB_AP_ERR_BADSEQ",
|
||||||
|
[50] = "KRB_AP_ERR_INAPP_CKSUM",
|
||||||
|
[51] = "KRB_AP_PATH_NOT_ACCEPTED",
|
||||||
|
[52] = "KRB_ERR_RESPONSE_TOO_BIG",
|
||||||
|
[60] = "KRB_ERR_GENERIC",
|
||||||
|
[61] = "KRB_ERR_FIELD_TOOLONG",
|
||||||
|
[62] = "KDC_ERROR_CLIENT_NOT_TRUSTED",
|
||||||
|
[63] = "KDC_ERROR_KDC_NOT_TRUSTED",
|
||||||
|
[64] = "KDC_ERROR_INVALID_SIG",
|
||||||
|
[65] = "KDC_ERR_KEY_TOO_WEAK",
|
||||||
|
[66] = "KDC_ERR_CERTIFICATE_MISMATCH",
|
||||||
|
[67] = "KRB_AP_ERR_NO_TGT",
|
||||||
|
[68] = "KDC_ERR_WRONG_REALM",
|
||||||
|
[69] = "KRB_AP_ERR_USER_TO_USER_REQUIRED",
|
||||||
|
[70] = "KDC_ERR_CANT_VERIFY_CERTIFICATE",
|
||||||
|
[71] = "KDC_ERR_INVALID_CERTIFICATE",
|
||||||
|
[72] = "KDC_ERR_REVOKED_CERTIFICATE",
|
||||||
|
[73] = "KDC_ERR_REVOCATION_STATUS_UNKNOWN",
|
||||||
|
[74] = "KDC_ERR_REVOCATION_STATUS_UNAVAILABLE",
|
||||||
|
[75] = "KDC_ERR_CLIENT_NAME_MISMATCH",
|
||||||
|
[76] = "KDC_ERR_KDC_NAME_MISMATCH",
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
5
scripts/base/protocols/krb/dpd.sig
Normal file
5
scripts/base/protocols/krb/dpd.sig
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
signature dpd_krb {
|
||||||
|
ip-proto == udp
|
||||||
|
payload /\x6c...\x30...\xa1\x03\x02\x05/
|
||||||
|
enable "krb"
|
||||||
|
}
|
190
scripts/base/protocols/krb/main.bro
Normal file
190
scripts/base/protocols/krb/main.bro
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
##! Implements base functionality for KRB analysis. Generates the krb.log file.
|
||||||
|
|
||||||
|
module KRB;
|
||||||
|
|
||||||
|
@load ./consts
|
||||||
|
|
||||||
|
export {
|
||||||
|
redef enum Log::ID += { LOG };
|
||||||
|
|
||||||
|
type Info: record {
|
||||||
|
## Timestamp for when the event happened.
|
||||||
|
ts: time &log;
|
||||||
|
## Unique ID for the connection.
|
||||||
|
uid: string &log;
|
||||||
|
## The connection's 4-tuple of endpoint addresses/ports.
|
||||||
|
id: conn_id &log;
|
||||||
|
## Client
|
||||||
|
client: string &log &optional;
|
||||||
|
## Service
|
||||||
|
service:string &log;
|
||||||
|
## Ticket valid from
|
||||||
|
from: time &log &optional;
|
||||||
|
## Ticket valid till
|
||||||
|
till: time &log &optional;
|
||||||
|
## Result
|
||||||
|
result: string &log &default="unknown";
|
||||||
|
## Error code
|
||||||
|
error_code: count &log &optional;
|
||||||
|
## Error message
|
||||||
|
error_msg: string &log &optional;
|
||||||
|
## We've already logged this
|
||||||
|
logged: bool &default=F;
|
||||||
|
};
|
||||||
|
|
||||||
|
## Event that can be handled to access the KRB record as it is sent on
|
||||||
|
## to the loggin framework.
|
||||||
|
global log_krb: event(rec: Info);
|
||||||
|
}
|
||||||
|
|
||||||
|
redef record connection += {
|
||||||
|
krb: Info &optional;
|
||||||
|
};
|
||||||
|
|
||||||
|
const ports = { 88/udp };
|
||||||
|
|
||||||
|
event bro_init() &priority=5
|
||||||
|
{
|
||||||
|
Log::create_stream(KRB::LOG, [$columns=Info, $ev=log_krb]);
|
||||||
|
Analyzer::register_for_ports(Analyzer::ANALYZER_KRB, ports);
|
||||||
|
}
|
||||||
|
|
||||||
|
event krb_error(c: connection, msg: Error_Msg)
|
||||||
|
{
|
||||||
|
local info: Info;
|
||||||
|
|
||||||
|
if ( c?$krb && c$krb$logged )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( c?$krb )
|
||||||
|
info = c$krb;
|
||||||
|
|
||||||
|
if ( ! info?$ts )
|
||||||
|
{
|
||||||
|
info$ts = network_time();
|
||||||
|
info$uid = c$uid;
|
||||||
|
info$id = c$id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! info?$client )
|
||||||
|
if ( msg?$client_name || msg?$client_realm )
|
||||||
|
info$client = fmt("%s%s", msg?$client_name ? msg$client_name + "/" : "",
|
||||||
|
msg?$client_realm ? msg$client_realm : "");
|
||||||
|
|
||||||
|
info$service = msg$service_name;
|
||||||
|
info$result = "failed";
|
||||||
|
|
||||||
|
info$error_code = msg$error_code;
|
||||||
|
|
||||||
|
if ( msg?$error_text )
|
||||||
|
info$error_msg = msg$error_text;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ( msg$error_code in error_msg )
|
||||||
|
info$error_msg = error_msg[msg$error_code];
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::write(KRB::LOG, info);
|
||||||
|
info$logged = T;
|
||||||
|
|
||||||
|
c$krb = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
event krb_as_req(c: connection, msg: KDC_Request)
|
||||||
|
{
|
||||||
|
if ( c?$krb && c$krb$logged )
|
||||||
|
return;
|
||||||
|
|
||||||
|
local info: Info;
|
||||||
|
info$ts = network_time();
|
||||||
|
info$uid = c$uid;
|
||||||
|
info$id = c$id;
|
||||||
|
info$client = fmt("%s/%s", msg$client_name, msg$service_realm);
|
||||||
|
info$service = msg$service_name;
|
||||||
|
if ( msg?$from )
|
||||||
|
info$from = msg$from;
|
||||||
|
info$till = msg$till;
|
||||||
|
|
||||||
|
c$krb = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
event krb_tgs_req(c: connection, msg: KDC_Request)
|
||||||
|
{
|
||||||
|
if ( c?$krb && c$krb$logged )
|
||||||
|
return;
|
||||||
|
|
||||||
|
local info: Info;
|
||||||
|
info$ts = network_time();
|
||||||
|
info$uid = c$uid;
|
||||||
|
info$id = c$id;
|
||||||
|
info$service = msg$service_name;
|
||||||
|
if ( msg?$from )
|
||||||
|
info$from = msg$from;
|
||||||
|
info$till = msg$till;
|
||||||
|
|
||||||
|
c$krb = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
event krb_as_rep(c: connection, msg: KDC_Reply)
|
||||||
|
{
|
||||||
|
local info: Info;
|
||||||
|
|
||||||
|
if ( c?$krb && c$krb$logged )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( c?$krb )
|
||||||
|
info = c$krb;
|
||||||
|
|
||||||
|
if ( ! info?$ts )
|
||||||
|
{
|
||||||
|
info$ts = network_time();
|
||||||
|
info$uid = c$uid;
|
||||||
|
info$id = c$id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! info?$client )
|
||||||
|
info$client = fmt("%s/%s", msg$client_name, msg$client_realm);
|
||||||
|
|
||||||
|
info$service = msg$ticket$service_name;
|
||||||
|
info$result = "success";
|
||||||
|
|
||||||
|
Log::write(KRB::LOG, info);
|
||||||
|
info$logged = T;
|
||||||
|
|
||||||
|
c$krb = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
event krb_tgs_rep(c: connection, msg: KDC_Reply)
|
||||||
|
{
|
||||||
|
local info: Info;
|
||||||
|
|
||||||
|
if ( c?$krb && c$krb$logged )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( c?$krb )
|
||||||
|
info = c$krb;
|
||||||
|
|
||||||
|
if ( ! info?$ts )
|
||||||
|
{
|
||||||
|
info$ts = network_time();
|
||||||
|
info$uid = c$uid;
|
||||||
|
info$id = c$id;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! info?$client )
|
||||||
|
info$client = fmt("%s/%s", msg$client_name, msg$client_realm);
|
||||||
|
|
||||||
|
info$service = msg$ticket$service_name;
|
||||||
|
info$result = "success";
|
||||||
|
|
||||||
|
Log::write(KRB::LOG, info);
|
||||||
|
info$logged = T;
|
||||||
|
|
||||||
|
c$krb = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
event connection_state_remove(c: connection)
|
||||||
|
{
|
||||||
|
if ( c?$krb && ! c$krb$logged )
|
||||||
|
Log::write(KRB::LOG, c$krb);
|
||||||
|
}
|
11
src/analyzer/protocol/krb/CMakeLists.txt
Normal file
11
src/analyzer/protocol/krb/CMakeLists.txt
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
include(BroPlugin)
|
||||||
|
|
||||||
|
include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
bro_plugin_begin(Bro KRB)
|
||||||
|
bro_plugin_cc(KRB.cc Plugin.cc)
|
||||||
|
bro_plugin_bif(types.bif)
|
||||||
|
bro_plugin_bif(events.bif)
|
||||||
|
bro_plugin_pac(krb.pac krb-protocol.pac krb-analyzer.pac)
|
||||||
|
bro_plugin_end()
|
37
src/analyzer/protocol/krb/KRB.cc
Normal file
37
src/analyzer/protocol/krb/KRB.cc
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#include "KRB.h"
|
||||||
|
|
||||||
|
#include "types.bif.h"
|
||||||
|
#include "events.bif.h"
|
||||||
|
|
||||||
|
using namespace analyzer::krb;
|
||||||
|
|
||||||
|
KRB_Analyzer::KRB_Analyzer(Connection* conn)
|
||||||
|
: Analyzer("KRB", conn)
|
||||||
|
{
|
||||||
|
interp = new binpac::KRB::KRB_Conn(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
KRB_Analyzer::~KRB_Analyzer()
|
||||||
|
{
|
||||||
|
delete interp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRB_Analyzer::Done()
|
||||||
|
{
|
||||||
|
Analyzer::Done();
|
||||||
|
}
|
||||||
|
|
||||||
|
void KRB_Analyzer::DeliverPacket(int len, const u_char* data,
|
||||||
|
bool orig, uint64 seq, const IP_Hdr* ip, int caplen)
|
||||||
|
{
|
||||||
|
Analyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
interp->NewData(orig, data, data + len);
|
||||||
|
}
|
||||||
|
catch ( const binpac::Exception& e )
|
||||||
|
{
|
||||||
|
printf(fmt("Binpac exception: %s\n", e.c_msg()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
28
src/analyzer/protocol/krb/KRB.h
Normal file
28
src/analyzer/protocol/krb/KRB.h
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef ANALYZER_PROTOCOL_KRB_KRB_H
|
||||||
|
#define ANALYZER_PROTOCOL_KRB_KRB_H
|
||||||
|
|
||||||
|
#include "analyzer/protocol/udp/UDP.h"
|
||||||
|
|
||||||
|
#include "krb_pac.h"
|
||||||
|
|
||||||
|
namespace analyzer { namespace krb {
|
||||||
|
|
||||||
|
class KRB_Analyzer : public analyzer::Analyzer {
|
||||||
|
public:
|
||||||
|
KRB_Analyzer(Connection* conn);
|
||||||
|
virtual ~KRB_Analyzer();
|
||||||
|
|
||||||
|
virtual void Done();
|
||||||
|
virtual void DeliverPacket(int len, const u_char* data, bool orig,
|
||||||
|
uint64 seq, const IP_Hdr* ip, int caplen);
|
||||||
|
|
||||||
|
static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn)
|
||||||
|
{ return new KRB_Analyzer(conn); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
binpac::KRB::KRB_Conn* interp;
|
||||||
|
};
|
||||||
|
|
||||||
|
} } // namespace analyzer::*
|
||||||
|
|
||||||
|
#endif
|
11
src/analyzer/protocol/krb/Plugin.cc
Normal file
11
src/analyzer/protocol/krb/Plugin.cc
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
#include "plugin/Plugin.h"
|
||||||
|
|
||||||
|
#include "KRB.h"
|
||||||
|
|
||||||
|
BRO_PLUGIN_BEGIN(Bro, KRB)
|
||||||
|
BRO_PLUGIN_DESCRIPTION("Kerberos analyzer");
|
||||||
|
BRO_PLUGIN_ANALYZER("KRB", krb::KRB_Analyzer);
|
||||||
|
BRO_PLUGIN_BIF_FILE(types);
|
||||||
|
BRO_PLUGIN_BIF_FILE(events);
|
||||||
|
BRO_PLUGIN_END
|
39
src/analyzer/protocol/krb/events.bif
Normal file
39
src/analyzer/protocol/krb/events.bif
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
## A Kerberos 5 ``Authentication Server (AS) Request`` as defined
|
||||||
|
## in :rfc:`4120`.
|
||||||
|
##
|
||||||
|
## c: The connection over which this Kerberos message was sent.
|
||||||
|
##
|
||||||
|
## msg: A Kerberos KDC request message data structure.
|
||||||
|
event krb_as_req%(c: connection, msg: KRB::KDC_Request%);
|
||||||
|
|
||||||
|
## A Kerberos 5 ``Ticket-Granting Service (TGS) Request`` as defined
|
||||||
|
## in :rfc:`4120`.
|
||||||
|
##
|
||||||
|
## c: The connection over which this Kerberos message was sent.
|
||||||
|
##
|
||||||
|
## msg: A Kerberos KDC request message data structure.
|
||||||
|
event krb_tgs_req%(c: connection, msg: KRB::KDC_Request%);
|
||||||
|
|
||||||
|
## A Kerberos 5 ``Authentication Server (AS) Reply`` as defined
|
||||||
|
## in :rfc:`4120`.
|
||||||
|
##
|
||||||
|
## c: The connection over which this Kerberos message was sent.
|
||||||
|
##
|
||||||
|
## msg: A Kerberos KDC reply message data structure.
|
||||||
|
event krb_as_rep%(c: connection, msg: KRB::KDC_Reply%);
|
||||||
|
|
||||||
|
## A Kerberos 5 ``Ticket-Granting Service (TGS) Reply`` as defined
|
||||||
|
## in :rfc:`4120`.
|
||||||
|
##
|
||||||
|
## c: The connection over which this Kerberos message was sent.
|
||||||
|
##
|
||||||
|
## msg: A Kerberos KDC reply message data structure.
|
||||||
|
event krb_tgs_rep%(c: connection, msg: KRB::KDC_Reply%);
|
||||||
|
|
||||||
|
## A Kerberos 5 ``ERROR_MSG`` as defined in :rfc:`4120`.
|
||||||
|
##
|
||||||
|
## c: The connection over which this Kerberos message was sent.
|
||||||
|
##
|
||||||
|
## msg: A Kerberos error message data structure.
|
||||||
|
event krb_error%(c: connection, msg: KRB::Error_Msg%);
|
||||||
|
|
456
src/analyzer/protocol/krb/krb-analyzer.pac
Normal file
456
src/analyzer/protocol/krb/krb-analyzer.pac
Normal file
|
@ -0,0 +1,456 @@
|
||||||
|
connection KRB_Conn(bro_analyzer: BroAnalyzer) {
|
||||||
|
upflow = KRB_Flow(true);
|
||||||
|
downflow = KRB_Flow(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
flow KRB_Flow(is_orig: bool) {
|
||||||
|
datagram = KRB_PDU withcontext(connection, this);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
%header{
|
||||||
|
Val* GetTimeFromAsn1(const KRB_Time* atime);
|
||||||
|
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);
|
||||||
|
%}
|
||||||
|
|
||||||
|
%code{
|
||||||
|
Val* GetTimeFromAsn1(const KRB_Time* atime)
|
||||||
|
{
|
||||||
|
time_t lResult = 0;
|
||||||
|
|
||||||
|
char lBuffer[16];
|
||||||
|
char* pBuffer = lBuffer;
|
||||||
|
|
||||||
|
size_t lTimeLength = atime->time().length();
|
||||||
|
char * pString = (char *) atime->time().data();
|
||||||
|
|
||||||
|
if ( lTimeLength != 15 )
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
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), 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);
|
||||||
|
|
||||||
|
rv->Assign(0, new Val(opts->forwardable(), TYPE_BOOL));
|
||||||
|
rv->Assign(1, new Val(opts->forwarded(), TYPE_BOOL));
|
||||||
|
rv->Assign(2, new Val(opts->proxiable(), TYPE_BOOL));
|
||||||
|
rv->Assign(3, new Val(opts->proxy(), TYPE_BOOL));
|
||||||
|
rv->Assign(4, new Val(opts->allow_postdate(), TYPE_BOOL));
|
||||||
|
rv->Assign(5, new Val(opts->postdated(), TYPE_BOOL));
|
||||||
|
rv->Assign(6, new Val(opts->renewable(), TYPE_BOOL));
|
||||||
|
rv->Assign(7, new Val(opts->opt_hardware_auth(), TYPE_BOOL));
|
||||||
|
rv->Assign(8, new Val(opts->disable_transited_check(), TYPE_BOOL));
|
||||||
|
rv->Assign(9, new Val(opts->renewable_ok(), TYPE_BOOL));
|
||||||
|
rv->Assign(10, new Val(opts->enc_tkt_in_skey(), TYPE_BOOL));
|
||||||
|
rv->Assign(11, new Val(opts->renew(), TYPE_BOOL));
|
||||||
|
rv->Assign(12, new Val(opts->validate(), TYPE_BOOL));
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
refine connection KRB_Conn += {
|
||||||
|
|
||||||
|
function proc_krb_kdc_req(msg: KRB_KDC_REQ): bool
|
||||||
|
%{
|
||||||
|
|
||||||
|
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 10 ) && ! krb_as_req )
|
||||||
|
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);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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.data.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.data}, 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 10 ) )
|
||||||
|
BifEvent::generate_krb_as_req(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||||
|
|
||||||
|
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 12 ) )
|
||||||
|
BifEvent::generate_krb_tgs_req(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function proc_krb_kdc_rep(msg: KRB_KDC_REP): bool
|
||||||
|
%{
|
||||||
|
|
||||||
|
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 11 ) && ! krb_as_rep )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 13 ) && ! krb_tgs_rep )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
|
||||||
|
RecordVal* rv = new RecordVal(BifType::Record::KRB::KDC_Reply);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
rv->Assign(3, bytestring_to_val(${msg.client_realm.encoding.content}));
|
||||||
|
rv->Assign(4, GetStringFromPrincipalName(${msg.client_name}));
|
||||||
|
|
||||||
|
RecordVal* ticket = new RecordVal(BifType::Record::KRB::Ticket);
|
||||||
|
|
||||||
|
ticket->Assign(0, asn1_integer_to_val(${msg.ticket.tkt_vno.data}, TYPE_COUNT));
|
||||||
|
ticket->Assign(1, bytestring_to_val(${msg.ticket.realm.data.content}));
|
||||||
|
ticket->Assign(2, GetStringFromPrincipalName(${msg.ticket.sname}));
|
||||||
|
ticket->Assign(3, asn1_integer_to_val(${msg.ticket.enc_part.etype.data}, TYPE_COUNT));
|
||||||
|
|
||||||
|
rv->Assign(5, ticket);
|
||||||
|
|
||||||
|
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 11 ) )
|
||||||
|
BifEvent::generate_krb_as_rep(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||||
|
|
||||||
|
if ( ( binary_to_int64(${msg.msg_type.data.content}) == 13 ) )
|
||||||
|
BifEvent::generate_krb_tgs_rep(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function proc_krb_ap_req(msg: KRB_AP_REQ): bool
|
||||||
|
%{
|
||||||
|
// Not implemented
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function proc_krb_ap_rep(msg: KRB_AP_REP): bool
|
||||||
|
%{
|
||||||
|
// Not implemented
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function proc_krb_error_msg(msg: KRB_ERROR_MSG): bool
|
||||||
|
%{
|
||||||
|
if ( krb_error )
|
||||||
|
{
|
||||||
|
RecordVal* rv = new RecordVal(BifType::Record::KRB::Error_Msg);
|
||||||
|
for ( uint i = 0; i < ${msg.args}->size(); i++ )
|
||||||
|
{
|
||||||
|
switch ( ${msg.args[i].seq_meta.index} )
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
rv->Assign(0, asn1_integer_to_val(${msg.args[i].args.pvno}, TYPE_COUNT));
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
rv->Assign(1, asn1_integer_to_val(${msg.args[i].args.msg_type}, TYPE_COUNT));
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
rv->Assign(2, GetTimeFromAsn1(${msg.args[i].args.ctime}));
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
rv->Assign(3, GetTimeFromAsn1(${msg.args[i].args.stime}));
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
// TODO
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
rv->Assign(4, asn1_integer_to_val(${msg.args[i].args.error_code}, TYPE_COUNT));
|
||||||
|
break;
|
||||||
|
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;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BifEvent::generate_krb_error(bro_analyzer(), bro_analyzer()->Conn(), rv);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function proc_krb_safe_msg(msg: KRB_SAFE_MSG): bool
|
||||||
|
%{
|
||||||
|
// Not implemented
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function proc_krb_priv_msg(msg: KRB_PRIV_MSG): bool
|
||||||
|
%{
|
||||||
|
// Not implemented
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
|
function proc_krb_cred_msg(msg: KRB_CRED_MSG): bool
|
||||||
|
%{
|
||||||
|
// Not implemented
|
||||||
|
return true;
|
||||||
|
%}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
refine typeattr KRB_AS_REQ += &let {
|
||||||
|
proc: bool = $context.connection.proc_krb_kdc_req(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
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);
|
||||||
|
};
|
||||||
|
|
52
src/analyzer/protocol/krb/krb-asn1.pac
Normal file
52
src/analyzer/protocol/krb/krb-asn1.pac
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
type ASN1Encoding = record {
|
||||||
|
meta: ASN1EncodingMeta;
|
||||||
|
content: bytestring &length = meta.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ASN1EncodingMeta = record {
|
||||||
|
tag: uint8;
|
||||||
|
len: uint8;
|
||||||
|
more_len: bytestring &length = long_len ? len & 0x7f : 0;
|
||||||
|
} &let {
|
||||||
|
long_len: bool = len & 0x80;
|
||||||
|
length: uint64 = long_len ? binary_to_int64(more_len) : len & 0x7f;
|
||||||
|
index: uint8 = tag - 160;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ASN1Integer = record {
|
||||||
|
encoding: ASN1Encoding;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ASN1OctetString = record {
|
||||||
|
encoding: ASN1Encoding;
|
||||||
|
};
|
||||||
|
|
||||||
|
type SequenceElement(grab_content: bool) = record {
|
||||||
|
index_meta: ASN1EncodingMeta;
|
||||||
|
have_content: case grab_content of {
|
||||||
|
true -> data: ASN1Encoding;
|
||||||
|
false -> meta: ASN1EncodingMeta;
|
||||||
|
};
|
||||||
|
} &let {
|
||||||
|
index: uint8 = index_meta.index;
|
||||||
|
length: uint64 = index_meta.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Array = record {
|
||||||
|
array_meta: ASN1EncodingMeta;
|
||||||
|
data: ASN1Encoding[];
|
||||||
|
};
|
||||||
|
|
||||||
|
function binary_to_int64(bs: bytestring): int64
|
||||||
|
%{
|
||||||
|
int64 rval = 0;
|
||||||
|
|
||||||
|
for ( int i = 0; i < bs.length(); ++i )
|
||||||
|
{
|
||||||
|
uint64 byte = bs[i];
|
||||||
|
rval |= byte << (8 * (bs.length() - (i + 1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
%}
|
||||||
|
|
343
src/analyzer/protocol/krb/krb-protocol.pac
Normal file
343
src/analyzer/protocol/krb/krb-protocol.pac
Normal file
|
@ -0,0 +1,343 @@
|
||||||
|
%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,
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_PDU = record {
|
||||||
|
app_meta : ASN1EncodingMeta;
|
||||||
|
msg_type : case (app_meta.tag - 96) of {
|
||||||
|
AS_REQ -> as_req : KRB_AS_REQ;
|
||||||
|
AS_REP -> as_rep : KRB_AS_REP;
|
||||||
|
TGS_REQ -> tgs_req : KRB_TGS_REQ;
|
||||||
|
TGS_REP -> tgs_rep : KRB_TGS_REP;
|
||||||
|
AP_REQ -> ap_req : KRB_AP_REQ;
|
||||||
|
AP_REP -> ap_rep : KRB_AP_REP;
|
||||||
|
KRB_SAFE -> krb_safe : KRB_SAFE_MSG;
|
||||||
|
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;
|
||||||
|
|
||||||
|
type KRB_AS_REQ = record {
|
||||||
|
data: KRB_KDC_REQ;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_TGS_REQ = record {
|
||||||
|
data: KRB_KDC_REQ;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_AS_REP = record {
|
||||||
|
data: KRB_KDC_REP;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_TGS_REP = record {
|
||||||
|
data: KRB_KDC_REP;
|
||||||
|
};
|
||||||
|
|
||||||
|
### KDC_REQ
|
||||||
|
|
||||||
|
type KRB_KDC_REQ = 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 &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: uint8 = has_padata ? meta2.length : padata_meta.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_PA_Data_Sequence = record {
|
||||||
|
seq_meta : ASN1EncodingMeta;
|
||||||
|
padata_elems: KRB_PA_Data[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_PA_Data = record {
|
||||||
|
seq_meta : ASN1EncodingMeta;
|
||||||
|
pa_data_type : SequenceElement(true);
|
||||||
|
pa_data_elem_meta : ASN1EncodingMeta;
|
||||||
|
pa_data_element : KRB_PA_Data_Element(data_type);
|
||||||
|
} &let {
|
||||||
|
data_type: int64 = binary_to_int64(pa_data_type.data.content);
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_PA_Data_Element(type: int64) = case type of {
|
||||||
|
1 -> pa_tgs_req : KRB_AP_REQ;
|
||||||
|
2 -> pa_enc_timestamp : KRB_Encrypted_Data;
|
||||||
|
3 -> pa_pw_salt : ASN1OctetString;
|
||||||
|
default -> unknown : bytestring &restofdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_REQ_Body = record {
|
||||||
|
seq_meta : ASN1EncodingMeta;
|
||||||
|
args : KRB_REQ_Arg[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_REQ_Arg = record {
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
10 -> auth_data : ASN1OctetString; # TODO
|
||||||
|
11 -> addl_tkts : KRB_Ticket_Sequence;
|
||||||
|
default -> unknown : bytestring &restofdata;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_KDC_Options = record {
|
||||||
|
meta : ASN1EncodingMeta;
|
||||||
|
flags: uint32;
|
||||||
|
} &let {
|
||||||
|
reserved : bool = flags & 0x80000000;
|
||||||
|
forwardable : bool = flags & 0x40000000;
|
||||||
|
forwarded : bool = flags & 0x20000000;
|
||||||
|
proxiable : bool = flags & 0x10000000;
|
||||||
|
proxy : bool = flags & 0x8000000;
|
||||||
|
allow_postdate : bool = flags & 0x4000000;
|
||||||
|
postdated : bool = flags & 0x2000000;
|
||||||
|
unused7 : bool = flags & 0x1000000;
|
||||||
|
renewable : bool = flags & 0x800000;
|
||||||
|
unused9 : bool = flags & 0x400000;
|
||||||
|
unused10 : bool = flags & 0x200000;
|
||||||
|
opt_hardware_auth : bool = flags & 0x100000;
|
||||||
|
unused12 : bool = flags & 0x80000;
|
||||||
|
unused13 : bool = flags & 0x40000;
|
||||||
|
# ...
|
||||||
|
unused15 : bool = flags & 0x10000;
|
||||||
|
# ...
|
||||||
|
disable_transited_check : bool = flags & 0x10;
|
||||||
|
renewable_ok : bool = flags & 0x8;
|
||||||
|
enc_tkt_in_skey : bool = flags & 0x4;
|
||||||
|
renew : bool = flags & 0x2;
|
||||||
|
validate : bool = flags & 0x1;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_Principal_Name = record {
|
||||||
|
seq_meta : ASN1EncodingMeta;
|
||||||
|
name_meta : ASN1EncodingMeta;
|
||||||
|
name_type : ASN1Integer;
|
||||||
|
seq_meta_1: ASN1EncodingMeta;
|
||||||
|
seq_meta_2: ASN1EncodingMeta;
|
||||||
|
data : ASN1OctetString[] &length=seq_meta_2.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
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: SequenceElement(true);
|
||||||
|
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;
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
|
### KDC_REP
|
||||||
|
|
||||||
|
type KRB_KDC_REP = 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 &length=padata_meta.length;
|
||||||
|
false -> n1 : empty;
|
||||||
|
};
|
||||||
|
tmp2 : case has_padata of {
|
||||||
|
true -> meta2 : ASN1EncodingMeta;
|
||||||
|
false -> n2 : empty;
|
||||||
|
};
|
||||||
|
client_realm: ASN1OctetString &length=realm_length;
|
||||||
|
client_name : KRB_Principal_Name;
|
||||||
|
ticket : KRB_Ticket(true);
|
||||||
|
enc_part : KRB_Encrypted_Data_in_Seq;
|
||||||
|
} &let {
|
||||||
|
has_padata : bool = padata_meta.index == 2;
|
||||||
|
realm_length: uint8 = has_padata ? meta2.length : padata_meta.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
### AP_REQ
|
||||||
|
|
||||||
|
type KRB_AP_REQ = record {
|
||||||
|
string_meta : ASN1EncodingMeta;
|
||||||
|
app_meta : ASN1EncodingMeta;
|
||||||
|
seq_meta : ASN1EncodingMeta;
|
||||||
|
pvno : SequenceElement(true);
|
||||||
|
msg_type : SequenceElement(true);
|
||||||
|
ap_options : KRB_AP_Options;
|
||||||
|
ticket : KRB_Ticket(true);
|
||||||
|
enc_part : KRB_Encrypted_Data_in_Seq;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_AP_Options = record {
|
||||||
|
meta : SequenceElement(false);
|
||||||
|
flags : uint32;
|
||||||
|
: padding[1];
|
||||||
|
} &let {
|
||||||
|
reserved : bool = flags & 0x80000000;
|
||||||
|
use_session_key : bool = flags & 0x40000000;
|
||||||
|
mutual_required : bool = flags & 0x20000000;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
### AP_REP
|
||||||
|
|
||||||
|
type KRB_AP_REP = record {
|
||||||
|
pvno : SequenceElement(true);
|
||||||
|
msg_type: SequenceElement(true);
|
||||||
|
enc_part: KRB_Encrypted_Data_in_Seq;
|
||||||
|
};
|
||||||
|
|
||||||
|
### KRB_ERROR
|
||||||
|
|
||||||
|
type KRB_ERROR_MSG = record {
|
||||||
|
seq_meta: ASN1EncodingMeta;
|
||||||
|
args : KRB_ERROR_Arg[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_ERROR_Arg = record {
|
||||||
|
seq_meta: ASN1EncodingMeta;
|
||||||
|
args : KRB_ERROR_Arg_Data(seq_meta.index) &length=seq_meta.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_ERROR_Arg_Data(index: uint8) = 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 -> error_code : ASN1Integer;
|
||||||
|
7 -> crealm : ASN1OctetString;
|
||||||
|
8 -> cname : KRB_Principal_Name;
|
||||||
|
9 -> realm : ASN1OctetString;
|
||||||
|
10 -> sname : KRB_Principal_Name;
|
||||||
|
11 -> e_text : ASN1OctetString;
|
||||||
|
12 -> e_data : ASN1OctetString;
|
||||||
|
};
|
||||||
|
|
||||||
|
### KRB_SAFE
|
||||||
|
|
||||||
|
type KRB_SAFE_MSG = record {
|
||||||
|
pvno : SequenceElement(true);
|
||||||
|
msg_type : SequenceElement(true);
|
||||||
|
safe_body: KRB_SAFE_Body;
|
||||||
|
checksum : KRB_Checksum;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_SAFE_Body = record {
|
||||||
|
seq_meta: ASN1EncodingMeta;
|
||||||
|
args : KRB_SAFE_Arg[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_SAFE_Arg = record {
|
||||||
|
seq_meta: ASN1EncodingMeta;
|
||||||
|
args : KRB_SAFE_Arg_Data(seq_meta.index) &length=seq_meta.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_SAFE_Arg_Data(index: uint8) = case index of {
|
||||||
|
0 -> user_data : ASN1OctetString;
|
||||||
|
1 -> timestamp : KRB_Time;
|
||||||
|
2 -> usec : ASN1Integer;
|
||||||
|
3 -> seq_number : ASN1Integer;
|
||||||
|
4 -> sender_addr: KRB_Host_Address;
|
||||||
|
5 -> recp_addr : KRB_Host_Address;
|
||||||
|
};
|
||||||
|
|
||||||
|
type KRB_Checksum = record {
|
||||||
|
checksum_type: SequenceElement(true);
|
||||||
|
checksum : SequenceElement(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
### KRB_PRIV
|
||||||
|
|
||||||
|
type KRB_PRIV_MSG = record {
|
||||||
|
pvno : SequenceElement(true);
|
||||||
|
msg_type: SequenceElement(true);
|
||||||
|
enc_part: KRB_Encrypted_Data_in_Seq;
|
||||||
|
};
|
||||||
|
|
||||||
|
### KRB_CRED
|
||||||
|
|
||||||
|
type KRB_CRED_MSG = record {
|
||||||
|
pvno : SequenceElement(true);
|
||||||
|
msg_type : SequenceElement(true);
|
||||||
|
tkts_meta: SequenceElement(false);
|
||||||
|
tickets : KRB_Ticket_Sequence;
|
||||||
|
enc_part : KRB_Encrypted_Data_in_Seq;
|
||||||
|
};
|
15
src/analyzer/protocol/krb/krb.pac
Normal file
15
src/analyzer/protocol/krb/krb.pac
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
%include binpac.pac
|
||||||
|
%include bro.pac
|
||||||
|
|
||||||
|
%extern{
|
||||||
|
#include "types.bif.h"
|
||||||
|
#include "events.bif.h"
|
||||||
|
%}
|
||||||
|
|
||||||
|
analyzer KRB withcontext {
|
||||||
|
connection: KRB_Conn;
|
||||||
|
flow: KRB_Flow;
|
||||||
|
};
|
||||||
|
|
||||||
|
%include krb-protocol.pac
|
||||||
|
%include krb-analyzer.pac
|
14
src/analyzer/protocol/krb/types.bif
Normal file
14
src/analyzer/protocol/krb/types.bif
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
module KRB;
|
||||||
|
|
||||||
|
type Error_Msg: record;
|
||||||
|
|
||||||
|
type KDC_Options: record;
|
||||||
|
type Type_Value: record;
|
||||||
|
type Ticket: record;
|
||||||
|
type Host_Address: record;
|
||||||
|
|
||||||
|
type KDC_Request: record;
|
||||||
|
|
||||||
|
type KDC_Reply: record;
|
||||||
|
|
||||||
|
module GLOBAL;
|
Loading…
Add table
Add a link
Reference in a new issue