module RubySMB module Dcerpc module Wkssvc UUID = '6BFFD098-A112-3610-9833-46C3F87E345A' VER_MAJOR = 1 VER_MINOR = 0 # Operation numbers NETR_WKSTA_GET_INFO = 0x0000 NETR_WKSTA_USER_ENUM = 0x0002 PLATFORM_ID = { 0x0000012C => "DOS", 0x00000190 => "OS2", 0x000001F4 => "Win", 0x00000258 => "OSF", 0x000002BC => "VMS" } # Information Level WKSTA_INFO_100 = 0x00000064 WKSTA_INFO_101 = 0x00000065 WKSTA_INFO_102 = 0x00000066 #TODO: WKSTA_INFO_502 = 0x000001F6 # User Enum Information Level WKSTA_USER_INFO_0 = 0x00000000 WKSTA_USER_INFO_1 = 0x00000001 # [2.2.2.1 WKSSVC_IDENTIFY_HANDLE](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-wkst/9ef94a11-0e5c-49d7-9ac7-68d6f03565de) class WkssvcIdentifyHandle < Ndr::NdrWideStringzPtr; end # [2.2.5.9 WKSTA_USER_INFO_0](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wkst/b7c53c6f-8b92-4e5d-9a2e-6462cb4ef1ac) class WkstaUserInfo0 < Ndr::NdrStruct default_parameter byte_align: 4 endian :little ndr_wide_stringz_ptr :wkui0_username end class WkstaUserInfo0ArrayPtr < Ndr::NdrConfArray default_parameter type: :wksta_user_info0 extend Ndr::PointerClassPlugin end # [2.2.5.12 WKSTA_USER_INFO_0_CONTAINER](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wkst/0b0cff8f-09bc-43a8-b0d3-88f0bf7e3664) class WkstaUserInfo0Container < Ndr::NdrStruct default_parameter byte_align: 4 endian :little ndr_uint32 :wkui0_entries_read wksta_user_info0_array_ptr :wkui0_buffer end class PwkstaUserInfo0Container < WkstaUserInfo0Container extend Ndr::PointerClassPlugin end # [2.2.5.10 WKSTA_USER_INFO_1](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wkst/c37b9606-866f-40ac-9490-57b8334968e2) class WkstaUserInfo1 < Ndr::NdrStruct default_parameter byte_align: 4 endian :little ndr_wide_stringz_ptr :wkui1_username ndr_wide_stringz_ptr :wkui1_logon_domain ndr_wide_stringz_ptr :wkui1_oth_domains ndr_wide_stringz_ptr :wkui1_logon_server end class WkstaUserInfo1ArrayPtr < Ndr::NdrConfArray default_parameter type: :wksta_user_info1 extend Ndr::PointerClassPlugin end # [2.2.5.13 WKSTA_USER_INFO_1_CONTAINER](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wkst/22a813e4-fc7d-4fe3-a6d6-78debfd2c0c9) class WkstaUserInfo1Container < Ndr::NdrStruct default_parameter byte_align: 4 endian :little ndr_uint32 :wkui1_entries_read wksta_user_info1_array_ptr :wkui1_buffer end class PwkstaUserInfo1Container < WkstaUserInfo1Container extend Ndr::PointerClassPlugin end # [2.2.5.14 WKSTA_USER_ENUM_STRUCT](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wkst/4041455a-52be-4389-a4fc-82fea3cb3160) class WkstaUserEnumStructure < Ndr::NdrStruct default_parameter byte_align: 4 endian :little ndr_uint32 :level ndr_uint32 :tag, value: -> { self.level } choice :info, selection: :level, byte_align: 4 do pwksta_user_info0_container WKSTA_USER_INFO_0 pwksta_user_info1_container WKSTA_USER_INFO_1 end end require 'ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request' require 'ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response' require 'ruby_smb/dcerpc/wkssvc/netr_wksta_user_enum_request' require 'ruby_smb/dcerpc/wkssvc/netr_wksta_user_enum_response' # Returns details about a computer environment, including # platform-specific information, the names of the domain and local # computer, and the operating system version. # # @param server_name [optional, String] String that identifies the server (optional # since it is ignored by the server) # @param level [optional, Integer] The information level of the data (default: WKSTA_INFO_100) # @return [RubySMB::Dcerpc::Wkssvc::WkstaInfo100, RubySMB::Dcerpc::Wkssvc::WkstaInfo101, # RubySMB::Dcerpc::Wkssvc::WkstaInfo102] The structure containing the requested information # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a # NetrWkstaGetInfoResponse packet # @raise [RubySMB::Dcerpc::Error::WkssvcError] if the response error status # is not STATUS_SUCCESS def netr_wksta_get_info(server_name: '', level: WKSTA_INFO_100) wkst_netr_wksta_get_info_request = NetrWkstaGetInfoRequest.new( server_name: server_name, level: level ) response = dcerpc_request(wkst_netr_wksta_get_info_request) begin wkst_netr_wksta_get_info_response = NetrWkstaGetInfoResponse.read(response) rescue IOError raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading WkstNetrWkstaGetInfoResponse' end unless wkst_netr_wksta_get_info_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS raise RubySMB::Dcerpc::Error::WkssvcError, "Error returned with netr_wksta_get_info: "\ "#{WindowsError::NTStatus.find_by_retval(wkst_netr_wksta_get_info_response.error_status.value).join(',')}" end wkst_netr_wksta_get_info_response.wksta_info.info end # Returns details about users who are currently active on a remote computer. # # @param server_name [optional, String] String that identifies the server (optional # since it is ignored by the server) # @param level [optional, Integer] The information level of the data (default: WKSTA_USER_INFO_0) # @return [RubySMB::Dcerpc::Wkssvc::WkstaUserInfo0, RubySMB::Dcerpc::Wkssvc::WkstaUserInfo1] # The structure containing the requested information # @raise [RubySMB::Dcerpc::Error::InvalidPacket] if the response is not a # NetrWkstaGetInfoResponse packet # @raise [RubySMB::Dcerpc::Error::WkssvcError] if the response error status # is not STATUS_SUCCESS def netr_wksta_user_enum(server_name: '', level: WKSTA_USER_INFO_0) wkst_netr_wksta_enum_user_request = NetrWkstaUserEnumRequest.new( server_name: server_name, user_info: { level: level, tag: level, info: { wkui0_entries_read: 0, }, }, preferred_max_length: 0xFFFFFFFF, result_handle: 0 ) response = dcerpc_request(wkst_netr_wksta_enum_user_request) begin wkst_netr_wksta_enum_user_response = NetrWkstaUserEnumResponse.read(response) rescue IOError raise RubySMB::Dcerpc::Error::InvalidPacket, 'Error reading WkstNetrWkstaUserEnumResponse' end unless wkst_netr_wksta_enum_user_response.error_status == WindowsError::NTStatus::STATUS_SUCCESS raise RubySMB::Dcerpc::Error::WkssvcError, "Error returned with netr_wksta_enum_user: #{wkst_netr_wksta_enum_user_response.error_status.value} - "\ "#{WindowsError::NTStatus.find_by_retval(wkst_netr_wksta_enum_user_response.error_status.value).join(',')}" end wkst_netr_wksta_enum_user_response.user_info.info end end end end