# -*- coding: binary -*- module Rex module Proto module Kerberos module Pac # This class provides a representation of a PAC_TYPE structure, the topmost structure # of the PAC. class Type < Element # @!attribute buffers # @return [Array] The array of PAC_INFO_BUFFER structures attr_accessor :buffers # @!attribute checksum # @return [Fixnum] The type of checksum to use when encoding PAC-TYPE attr_accessor :checksum # Encodes the Rex::Proto::Kerberos::Pac::Type # # @return [String] def encode offset_one = 0 offset_two = 0 draft = '' draft << encode_buffers_length draft << encode_version draft << encode_pac_info_buffers # Encode buffers buffers.each do |buffer| if buffer.class == ServerChecksum offset_one = draft.length + 4 elsif buffer.class == PrivSvrChecksum offset_two = draft.length + 4 end buffer_encoded = buffer.encode draft << buffer_encoded draft << "\x00" * ((buffer_encoded.length + 7) / 8 * 8 - buffer_encoded.length) end checksum_draft = make_checksum(draft) double_checksum = make_checksum(checksum_draft) encoded = '' encoded << draft[0..(offset_one - 1)] encoded << checksum_draft encoded << draft[(offset_one + checksum_draft.length)..(offset_two - 1)] encoded << double_checksum encoded << draft[(offset_two + double_checksum.length)..(draft.length - 1)] encoded end private # Encodes the number of buffers contained in the PAC # # @return [String] def encode_buffers_length [buffers.length].pack('V') end # Encodes the PAC version # # @return [String] def encode_version [VERSION].pack('V') end # Encodes the PAC_INFO_BUFFER data # # @return [String] def encode_pac_info_buffers offset = 8 + buffers.length * 16 encoded = '' buffers.each do |buffer| case buffer when ClientInfo encoded << [PAC_CLIENT_INFO].pack('V') when LogonInfo encoded << [PAC_LOGON_INFO].pack('V') when PrivSvrChecksum encoded << [PAC_PRIVSVR_CHECKSUM].pack('V') when ServerChecksum encoded << [PAC_SERVER_CHECKSUM].pack('V') end buffer_length = buffer.encode.length encoded << [buffer_length].pack('V') encoded << [offset].pack('Q<') offset = (offset + buffer_length + 7) / 8 * 8 end encoded end # Calculates the checksum for the PAC data # # @param data [String] the data to checksum # @return [String] the checksum result # @raise [NotImplementedError] if checksum schema isn't supported def make_checksum(data) res = '' case checksum when RSA_MD5 res = checksum_rsa_md5(data) else raise ::NotImplementedError, 'PAC-TYPE checksum not supported' end res end end end end end end