Digging through Source Code

"Weasel, Gary W Jr CIV DISA RE (US)" <gary.w.weasel2.civ@mail.mil> writes:

case 8:
        if ( element->data()->etype()->data()->size() )
                rv->Assign(11, proc_cipher_list(element->data()->etype()));

Following the breadcrumb trail in the if statement here...

        element is type KRB_REQ_Arg (defined - https://github.com/bro/bro/blob/master/src/analyzer/protocol/krb/krb-protocol.pac)
-> data is type KRB_REQ_Arg_Data (defined - https://github.com/bro/bro/blob/master/src/analyzer/protocol/krb/krb-protocol.pac)
-> etype is type Array (defined - https://github.com/bro/bro/blob/master/src/analyzer/protocol/asn1/asn1.pac)
-> data is type ASN1Encoding (defined - https://github.com/bro/bro/blob/master/src/analyzer/protocol/asn1/asn1.pac)
-> size is type ?

Following this line of thought, I'm a little confused by what "size()"
is supposed to mean here, since it's not an attribute. I can infer
that it's simply returning the size of the record, but I don't have
any information as to how or where that would be defined. I've also
tried looking through the source of BinPAC
(https://www.bro.org/sphinx/components/binpac/README.html) but have
come up empty so far.

I'll add on to what Johanna said. Many attributes in Kerberos are
technically optional (though the Microsoft and MIT implementations don't
necessarily treat them that way). Other attributes aren't optional, but
we check to make sure that they were actually seen before accessing the
underlying data. The if statement is just checking to see if that
attribute was in the request packet (even though etype isn't optional
according to the RFC).

I have a sample of kerberos pcap that populates the msg$pa_data$encryption_type vector (from event krb_tgs_request), so I know that the aforementioned if statement is returning true - - but the other two vectors "host_addrs" and "additional"tickets" (that from documentation seem to imply they're parallel with the encryption_type vector) come up as <uninitialized>.

They're not really parallel. What the RFC has is:

        etype [8] SEQUENCE OF Int32 -- EncryptionType
                                    -- in preference order --,
        addresses [9] HostAddresses OPTIONAL,
        enc-authorization-data [10] EncryptedData OPTIONAL
                                    -- AuthorizationData --,
        additional-tickets [11] SEQUENCE OF Ticket OPTIONAL
                                       -- NOTE: not empty

addresses (called host_addrs by Bro) and additional-tickets are listed
as optional, and likely won't be present in your PCAP (outside of the
padata, at least).

This made me question that maybe there was something wrong with the
code that was causing it to miss the host_addr and ticket data, I
clearly find this data in my pcap sample under padata. This is my
current theory anyway, and wanted to see if I'm making a bad
assumption somewhere or if someone can shed light on what's going on
here.

The padata is in a separate field (pa_data). The overall structure is
that first you have the request itself, with the padata:

KDC-REQ ::= SEQUENCE {
        -- NOTE: first tag is [1], not [0]
        pvno [1] INTEGER (5) ,
        msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --),
        padata [3] SEQUENCE OF PA-DATA OPTIONAL
                            -- NOTE: not empty --,
        req-body [4] KDC-REQ-BODY
}

req-body is then parsed as:

KDC-REQ-BODY ::= SEQUENCE {
        kdc-options [0] KDCOptions,
        cname [1] PrincipalName OPTIONAL
                                    -- Used only in AS-REQ --,
        realm [2] Realm
                                    -- Server's realm
                                    -- Also client's in AS-REQ --,
        sname [3] PrincipalName OPTIONAL,
        from [4] KerberosTime OPTIONAL,
        till [5] KerberosTime,
        rtime [6] KerberosTime OPTIONAL,
        nonce [7] UInt32,
        etype [8] SEQUENCE OF Int32 -- EncryptionType
                                    -- in preference order --,
        addresses [9] HostAddresses OPTIONAL,
        enc-authorization-data [10] EncryptedData OPTIONAL
                                    -- AuthorizationData --,
        additional-tickets [11] SEQUENCE OF Ticket OPTIONAL
                                       -- NOTE: not empty
}

So it's possible that you're seeing these fields in padata, but not in
the req-body.

Hope that helps. I forgot how complex this all was.

  --Vlad