152 lines
4.0 KiB
Ruby
152 lines
4.0 KiB
Ruby
# -*- coding: binary -*-
|
|
|
|
require 'bindata'
|
|
|
|
# Models for or Krb5 keytab
|
|
module Rex::Proto::Kerberos::Keytab
|
|
class Krb5KeytabCountedOctetString < BinData::Primitive
|
|
endian :big
|
|
search_prefix :krb5_keytab
|
|
|
|
# @!attribute [rw] len
|
|
# @return [Integer]
|
|
uint16 :len, value: -> { data.length }
|
|
|
|
# @!attribute [rw] data
|
|
# @return [String]
|
|
string :data, read_length: :len
|
|
|
|
def get
|
|
data.snapshot
|
|
end
|
|
|
|
def set(v)
|
|
self.data = v
|
|
end
|
|
end
|
|
|
|
class Krb5KeytabKeyblock < BinData::Record
|
|
endian :big
|
|
search_prefix :krb5_keytab
|
|
|
|
# @!attribute [rw] enctype
|
|
# @return [Integer] The encryption type
|
|
# @see Rex::Proto::Kerberos::Crypto::Encryption
|
|
uint16 :enctype
|
|
|
|
# @return [KeytabCountedOctetString]
|
|
counted_octet_string :data
|
|
end
|
|
|
|
class Krb5KeytabEpoch < BinData::Primitive
|
|
endian :big
|
|
search_prefix :krb5_keytab
|
|
|
|
# @!attribute [rw] epoch
|
|
# @return [Integer]
|
|
uint32 :epoch
|
|
|
|
def get
|
|
Time.at(epoch)
|
|
end
|
|
|
|
def set(v)
|
|
self.epoch = v.to_i
|
|
end
|
|
end
|
|
|
|
class Krb5KeytabEntry < BinData::Record
|
|
endian :big
|
|
search_prefix :krb5_keytab
|
|
|
|
# @return [Integer] The number of bytes for the len field
|
|
LEN_FIELD_BYTE_SIZE = 4
|
|
|
|
# @!attribute [rw] len
|
|
# @return [Integer] The number of remaining bytes for this record. The length does not include the 4 bytes for this field
|
|
int32 :len,
|
|
value: -> {
|
|
size = [
|
|
count_of_components,
|
|
realm,
|
|
components,
|
|
name_type,
|
|
timestamp,
|
|
vno8,
|
|
keyblock,
|
|
vno,
|
|
flags
|
|
].sum { |field| field.to_binary_s.bytes.count }
|
|
|
|
size
|
|
}
|
|
|
|
# @!attribute [rw] count_of_components
|
|
# @return [Integer]
|
|
uint16 :count_of_components, value: -> { components.length }
|
|
|
|
# @!attribute [rw] realm#
|
|
# @return [CountedOctetString]
|
|
counted_octet_string :realm
|
|
|
|
# @!attribute [rw] components
|
|
# @return [Array<CountedOctetString>] The components in the principal name, which can be joined by slashes
|
|
# to represent the SPN
|
|
array :components, initial_length: :count_of_components, type: :counted_octet_string
|
|
|
|
# @!attribute [rw] name_type
|
|
# @return [Integer]
|
|
# @see Rex::Proto::Kerberos::Model::NameType
|
|
uint32 :name_type
|
|
|
|
# @!attribute [rw] timestamp
|
|
# @return [Integer] The time the key entry was created; Can be 0 for keytabs generated by ktpass
|
|
epoch :timestamp
|
|
|
|
# @!attribute [rw] vno8
|
|
# @return [Integer] The lower 8 bits of the version number of the key
|
|
uint8 :vno8
|
|
|
|
# @!attribute [rw] keyblock
|
|
# @return [KeytabKeyBlock]
|
|
keyblock :keyblock
|
|
|
|
# @!attribute [rw] vno
|
|
# @return [Integer]
|
|
uint32 :vno,
|
|
initial_value: -> { vno8.to_i },
|
|
# only present if >= 4 bytes left in entry
|
|
onlyif: -> { ((len + LEN_FIELD_BYTE_SIZE) - vno.rel_offset) >= 4 }
|
|
|
|
# @!attribute [rw] flags
|
|
# @return [Integer]
|
|
uint32 :flags,
|
|
# only present if >= 4 bytes left in entry
|
|
onlyif: -> { ((len + LEN_FIELD_BYTE_SIZE) - flags.rel_offset) >= 4 }
|
|
|
|
# @return [String] The principal associated with this key tab entry
|
|
def principal
|
|
"#{components.to_a.join('/')}@#{realm}"
|
|
end
|
|
end
|
|
|
|
# Definition from:
|
|
# https://web.mit.edu/kerberos/krb5-devel/doc/basic/keytab_def.html
|
|
# http://www.ioplex.com/utilities/keytab.txt
|
|
# http://web.mit.edu/freebsd/head/crypto/heimdal/doc/doxyout/krb5/html/krb5_fileformats.html
|
|
#
|
|
class Krb5Keytab < BinData::Record
|
|
endian :big
|
|
search_prefix :krb5_keytab
|
|
|
|
# Older keytab version 0x501 not currently supported
|
|
# @!attribute [r] file_format_version
|
|
# @return [Integer]
|
|
uint16 :file_format_version, asserted_value: 0x502
|
|
|
|
# @!attribute [rw] key_entries
|
|
# @return [Array<KeytabEntry>] the keytab entries
|
|
array :key_entries, type: :entry, read_until: :eof
|
|
end
|
|
end
|