# -*- coding: binary -*- module Rex module Proto module Kerberos module Pac # @todo Make more fields user controllable, instead of constants. # This class provides a representation of a PAC_LOGON_INFO structure, which contains the # credential information for the client of the Kerberos ticket. class LogonInfo < Element # @!attribute logon_time # @return [Time] The time the client last logged on attr_accessor :logon_time # @!attribute effective_name # @return [String] The client's Windows 2000 user name attr_accessor :effective_name # @!attribute user_id # @return [Fixnum] The relative ID for the client attr_accessor :user_id # @!attribute primary_group_id # @return [Fixnum] The relative ID for the client's primary group attr_accessor :primary_group_id # @!attribute group_ids # @return [Array] Array of relative Ids of the groups which the client is a member attr_accessor :group_ids # @!attribute logon_domain_name # @return [String] The netbios name of the client's domain attr_accessor :logon_domain_name # @!attribute logon_domain_sid # @return [String] The SID of the client's domain attr_accessor :logon_domain_id # Encodes the Rex::Proto::Kerberos::Pac::LogonInfo # # @return [String] def encode elements = [] elements[0] = '' elements[0] << encode_element_id elements[0] << encode_logon_time elements[0] << encode_logoff_time elements[0] << encode_kickoff_time elements[0] << encode_password_last_set elements[0] << encode_password_can_change elements[0] << encode_password_must_change elements[0] << encode_effective_name elements << encode_effective_name_info elements[0] << encode_full_name elements << encode_full_name_info elements[0] << encode_logon_script elements << encode_logon_script_info elements[0] << encode_profile_path elements << encode_profile_path_info elements[0] << encode_home_directory elements << encode_home_directory_info elements[0] << encode_home_directory_drive elements << encode_home_directory_drive_info elements[0] << encode_logon_count elements[0] << encode_bad_password_count elements[0] << encode_user_id elements[0] << encode_primary_group_id elements[0] << encode_group_count elements[0] << encode_group_ids elements << encode_group_ids_info elements[0] << encode_user_flags elements[0] << encode_user_session_key elements[0] << encode_logon_server elements << encode_logon_server_info elements[0] << encode_logon_domain_name elements << encode_logon_domain_name_info elements[0] << encode_logon_domain_id elements << encode_logon_domain_id_info elements[0] << encode_reserved_one elements[0] << encode_user_account_control elements[0] << encode_reserved_three elements[0] << encode_sid_count elements[0] << encode_extra_sids elements[0] << encode_resource_group_domain_sid elements[0] << encode_resource_group_count elements[0] << encode_resource_group_ids decoded = '' elements.each do |elem| decoded << elem decoded << "\x00" * ((elem.length + 3) / 4 * 4 - elem.length) end header = "\x01\x10\x08\x00\xcc\xcc\xcc\xcc" header << [decoded.length, 0].pack('VV') header + decoded end private # Encodes the netlogon type # # @return [String] def encode_element_id [NETLOGON_FLAG].pack('V') end # Encodes the logon_time attribute # # @return [String] def encode_logon_time file_time = (logon_time.to_i + SEC_TO_UNIX_EPOCH) * WINDOWS_TICK encoded = '' encoded << [file_time].pack('Q<') encoded end # Encodes the logoff time (constant) # # @return [String] def encode_logoff_time [NEVER_EXPIRE].pack('Q<') end # Encodes the kickoff time (constant) # # @return [String] def encode_kickoff_time [NEVER_EXPIRE].pack('Q<') end # Encodes the password_last_set (constant) # # @return [String] def encode_password_last_set [0].pack('Q<') end # Encodes the password_can_change (constant) # # @return [String] def encode_password_can_change [0].pack('Q<') end # Encodes the password_must_change (constant) # # @return [String] def encode_password_must_change [NEVER_EXPIRE].pack('Q<') end # Encodes the effective_name id field # # @return [String] def encode_effective_name unicode = Rex::Text.to_unicode(effective_name) encoded = '' encoded << [ unicode.length, unicode.length, 0x20004 ].pack('vvV') encoded end # Encodes the effective_name info field # # @return [String] def encode_effective_name_info unicode = Rex::Text.to_unicode(effective_name) encoded = '' encoded << [ effective_name.length, effective_name.length ].pack('Q> 16, components[1].to_i & 0xffff ].pack('Nn') components[2, components.length].each do |c| encoded << [c.to_i].pack('V') end encoded end # Encodes the reserved_one (constant) # # @return [String] def encode_reserved_one [0, 0].pack('VV') end # Encodes the user_account_control (constant) # # @return [String] def encode_user_account_control [USER_NORMAL_ACCOUNT | USER_DONT_EXPIRE_PASSWORD].pack('V') end # Encodes the reserved_three (constant) # # @return [String] def encode_reserved_three [0, 0, 0, 0, 0, 0, 0].pack('V*') end # Encodes the sid_count (constant) # # @return [String] def encode_sid_count [0].pack('V') end # Encodes the extra_sids (constant) # # @return [String] def encode_extra_sids [0].pack('V') end # Encodes the resource_group_domain_sid (constant) # # @return [String] def encode_resource_group_domain_sid [0].pack('V') end # Encodes the resource_group_count (constant) # # @return [String] def encode_resource_group_count [0].pack('V') end # Encodes the resource_group_ids (constant) # # @return [String] def encode_resource_group_ids [0].pack('V') end end end end end end