ruby_smb 1.1.0 → 2.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
 - checksums.yaml.gz.sig +0 -0
 - data.tar.gz.sig +0 -0
 - data/.travis.yml +3 -5
 - data/Gemfile +6 -2
 - data/examples/anonymous_auth.rb +3 -3
 - data/examples/append_file.rb +10 -8
 - data/examples/authenticate.rb +9 -5
 - data/examples/delete_file.rb +8 -6
 - data/examples/enum_registry_key.rb +5 -4
 - data/examples/enum_registry_values.rb +5 -4
 - data/examples/list_directory.rb +8 -6
 - data/examples/negotiate.rb +51 -8
 - data/examples/negotiate_with_netbios_service.rb +9 -5
 - data/examples/net_share_enum_all.rb +6 -4
 - data/examples/pipes.rb +11 -12
 - data/examples/query_service_status.rb +64 -0
 - data/examples/read_file.rb +8 -6
 - data/examples/read_file_encryption.rb +56 -0
 - data/examples/read_registry_key_value.rb +6 -5
 - data/examples/rename_file.rb +9 -7
 - data/examples/tree_connect.rb +7 -5
 - data/examples/write_file.rb +9 -7
 - data/lib/ruby_smb.rb +4 -0
 - data/lib/ruby_smb/client.rb +246 -26
 - data/lib/ruby_smb/client/authentication.rb +32 -18
 - data/lib/ruby_smb/client/echo.rb +2 -4
 - data/lib/ruby_smb/client/encryption.rb +62 -0
 - data/lib/ruby_smb/client/negotiation.rb +156 -16
 - data/lib/ruby_smb/client/signing.rb +19 -0
 - data/lib/ruby_smb/client/tree_connect.rb +6 -8
 - data/lib/ruby_smb/client/utils.rb +24 -17
 - data/lib/ruby_smb/client/winreg.rb +1 -1
 - data/lib/ruby_smb/crypto.rb +30 -0
 - data/lib/ruby_smb/dcerpc.rb +2 -0
 - data/lib/ruby_smb/dcerpc/error.rb +3 -0
 - data/lib/ruby_smb/dcerpc/ndr.rb +209 -44
 - data/lib/ruby_smb/dcerpc/request.rb +13 -0
 - data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +34 -0
 - data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +9 -6
 - data/lib/ruby_smb/dcerpc/svcctl.rb +479 -0
 - data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +48 -0
 - data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response.rb +26 -0
 - data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request.rb +25 -0
 - data/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response.rb +26 -0
 - data/lib/ruby_smb/dcerpc/svcctl/control_service_request.rb +26 -0
 - data/lib/ruby_smb/dcerpc/svcctl/control_service_response.rb +26 -0
 - data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request.rb +35 -0
 - data/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response.rb +23 -0
 - data/lib/ruby_smb/dcerpc/svcctl/open_service_w_request.rb +31 -0
 - data/lib/ruby_smb/dcerpc/svcctl/open_service_w_response.rb +23 -0
 - data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request.rb +25 -0
 - data/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response.rb +44 -0
 - data/lib/ruby_smb/dcerpc/svcctl/query_service_status_request.rb +23 -0
 - data/lib/ruby_smb/dcerpc/svcctl/query_service_status_response.rb +27 -0
 - data/lib/ruby_smb/dcerpc/svcctl/service_status.rb +25 -0
 - data/lib/ruby_smb/dcerpc/svcctl/start_service_w_request.rb +27 -0
 - data/lib/ruby_smb/dcerpc/svcctl/start_service_w_response.rb +25 -0
 - data/lib/ruby_smb/dcerpc/winreg.rb +98 -17
 - data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +73 -0
 - data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +36 -0
 - data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +1 -1
 - data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +1 -1
 - data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +1 -1
 - data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +4 -4
 - data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +1 -1
 - data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +7 -6
 - data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +10 -10
 - data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +37 -0
 - data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +23 -0
 - data/lib/ruby_smb/dispatcher/base.rb +1 -1
 - data/lib/ruby_smb/dispatcher/socket.rb +5 -4
 - data/lib/ruby_smb/error.rb +49 -6
 - data/lib/ruby_smb/field/stringz16.rb +17 -1
 - data/lib/ruby_smb/generic_packet.rb +11 -1
 - data/lib/ruby_smb/nbss/session_header.rb +4 -4
 - data/lib/ruby_smb/smb1/commands.rb +1 -1
 - data/lib/ruby_smb/smb1/file.rb +13 -28
 - data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +1 -1
 - data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +2 -2
 - data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
 - data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -2
 - data/lib/ruby_smb/smb1/packet/write_andx_request.rb +1 -1
 - data/lib/ruby_smb/smb1/pipe.rb +8 -8
 - data/lib/ruby_smb/smb1/tree.rb +25 -12
 - data/lib/ruby_smb/smb2/bit_field/session_flags.rb +2 -1
 - data/lib/ruby_smb/smb2/bit_field/share_flags.rb +6 -4
 - data/lib/ruby_smb/smb2/file.rb +59 -77
 - data/lib/ruby_smb/smb2/negotiate_context.rb +108 -0
 - data/lib/ruby_smb/smb2/packet.rb +2 -0
 - data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +41 -0
 - data/lib/ruby_smb/smb2/packet/negotiate_request.rb +51 -14
 - data/lib/ruby_smb/smb2/packet/negotiate_response.rb +50 -4
 - data/lib/ruby_smb/smb2/packet/transform_header.rb +84 -0
 - data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +92 -6
 - data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +8 -26
 - data/lib/ruby_smb/smb2/pipe.rb +8 -20
 - data/lib/ruby_smb/smb2/smb2_header.rb +1 -1
 - data/lib/ruby_smb/smb2/tree.rb +44 -28
 - data/lib/ruby_smb/version.rb +1 -1
 - data/ruby_smb.gemspec +3 -1
 - data/spec/lib/ruby_smb/client_spec.rb +1408 -70
 - data/spec/lib/ruby_smb/crypto_spec.rb +25 -0
 - data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +1396 -77
 - data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +161 -0
 - data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +49 -12
 - data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +191 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_response_spec.rb +38 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_request_spec.rb +30 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/close_service_handle_response_spec.rb +38 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_request_spec.rb +39 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/control_service_response_spec.rb +38 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_request_spec.rb +78 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/open_sc_manager_w_response_spec.rb +38 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_request_spec.rb +59 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/open_service_w_response_spec.rb +38 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_request_spec.rb +38 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_config_w_response_spec.rb +152 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_request_spec.rb +30 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/query_service_status_response_spec.rb +38 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/service_status_spec.rb +72 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +46 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_response_spec.rb +30 -0
 - data/spec/lib/ruby_smb/dcerpc/svcctl_spec.rb +512 -0
 - data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +110 -0
 - data/spec/lib/ruby_smb/dcerpc/winreg/create_key_response_spec.rb +44 -0
 - data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_request_spec.rb +0 -4
 - data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +2 -2
 - data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +2 -2
 - data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +9 -4
 - data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +0 -4
 - data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +17 -17
 - data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +11 -23
 - data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +57 -0
 - data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +22 -0
 - data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +227 -41
 - data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +12 -12
 - data/spec/lib/ruby_smb/error_spec.rb +88 -0
 - data/spec/lib/ruby_smb/field/stringz16_spec.rb +12 -0
 - data/spec/lib/ruby_smb/generic_packet_spec.rb +7 -0
 - data/spec/lib/ruby_smb/nbss/session_header_spec.rb +4 -11
 - data/spec/lib/ruby_smb/smb1/file_spec.rb +1 -3
 - data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +2 -2
 - data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +2 -2
 - data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +2 -2
 - data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +1 -1
 - data/spec/lib/ruby_smb/smb1/pipe_spec.rb +30 -5
 - data/spec/lib/ruby_smb/smb1/tree_spec.rb +22 -0
 - data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +9 -0
 - data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +27 -0
 - data/spec/lib/ruby_smb/smb2/file_spec.rb +147 -71
 - data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +332 -0
 - data/spec/lib/ruby_smb/smb2/packet/compression_transform_header_spec.rb +108 -0
 - data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +138 -3
 - data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +120 -2
 - data/spec/lib/ruby_smb/smb2/packet/transform_header_spec.rb +220 -0
 - data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +339 -9
 - data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +3 -30
 - data/spec/lib/ruby_smb/smb2/pipe_spec.rb +9 -45
 - data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +2 -2
 - data/spec/lib/ruby_smb/smb2/tree_spec.rb +111 -9
 - metadata +194 -75
 - metadata.gz.sig +2 -1
 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            RSpec.describe RubySMB::Dcerpc::Winreg::SaveKeyResponse do
         
     | 
| 
      
 2 
     | 
    
         
            +
              subject(:packet) { described_class.new }
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
              it { is_expected.to respond_to :error_status }
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              it 'is little endian' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              describe '#error_status' do
         
     | 
| 
      
 11 
     | 
    
         
            +
                it 'is a 32-bit unsigned integer' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                  expect(packet.error_status).to be_a BinData::Uint32le
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              describe '#initialize_instance' do
         
     | 
| 
      
 17 
     | 
    
         
            +
                it 'sets #opnum to REG_CREATE_KEY constant' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                  expect(packet.opnum).to eq(RubySMB::Dcerpc::Winreg::REG_CREATE_KEY)
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
         @@ -132,8 +132,7 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       132 
132 
     | 
    
         
             
              describe '#query_value' do
         
     | 
| 
       133 
133 
     | 
    
         
             
                let(:handle)                      { double('Handle') }
         
     | 
| 
       134 
134 
     | 
    
         
             
                let(:value_name)                  { double('Value Name') }
         
     | 
| 
       135 
     | 
    
         
            -
                let(: 
     | 
| 
       136 
     | 
    
         
            -
                let(:query_value_request_packet2) { double('Query Value Request Packet #2') }
         
     | 
| 
      
 135 
     | 
    
         
            +
                let(:query_value_request_packet) { double('Query Value Request Packet #1') }
         
     | 
| 
       137 
136 
     | 
    
         
             
                let(:lp_data1)                    { double('LpData #1') }
         
     | 
| 
       138 
137 
     | 
    
         
             
                let(:lp_data2)                    { double('LpData #2') }
         
     | 
| 
       139 
138 
     | 
    
         
             
                let(:response1)                   { double('Response #1') }
         
     | 
| 
         @@ -142,26 +141,28 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       142 
141 
     | 
    
         
             
                let(:query_value_response2)       { double('Query Value Response #2') }
         
     | 
| 
       143 
142 
     | 
    
         
             
                let(:data)                        { double('Data') }
         
     | 
| 
       144 
143 
     | 
    
         
             
                let(:lpcb_data)                   { double('LpcbData') }
         
     | 
| 
       145 
     | 
    
         
            -
                let(:lpcb_data_referent)          { double(' 
     | 
| 
      
 144 
     | 
    
         
            +
                let(:lpcb_data_referent)          { double('LpcbData Referent') }
         
     | 
| 
      
 145 
     | 
    
         
            +
                let(:lp_data2_referent)           { double('LpData Referent') }
         
     | 
| 
       146 
146 
     | 
    
         
             
                before :example do
         
     | 
| 
      
 147 
     | 
    
         
            +
                  allow(described_class::QueryValueRequest).to receive(:new).and_return(query_value_request_packet)
         
     | 
| 
      
 148 
     | 
    
         
            +
                  allow(query_value_request_packet).to receive_messages(
         
     | 
| 
      
 149 
     | 
    
         
            +
                    :lp_type=   => nil,
         
     | 
| 
      
 150 
     | 
    
         
            +
                    :lpcb_data= => nil,
         
     | 
| 
      
 151 
     | 
    
         
            +
                    :lpcb_len=  => nil,
         
     | 
| 
      
 152 
     | 
    
         
            +
                    :lp_data=   => nil,
         
     | 
| 
      
 153 
     | 
    
         
            +
                    :lp_data    => lp_data2,
         
     | 
| 
      
 154 
     | 
    
         
            +
                  )
         
     | 
| 
      
 155 
     | 
    
         
            +
                  allow(lp_data2).to receive(:referent).and_return(lp_data2_referent)
         
     | 
| 
      
 156 
     | 
    
         
            +
                  allow(lp_data2_referent).to receive(:max_count=)
         
     | 
| 
       147 
157 
     | 
    
         
             
                  first_request = true
         
     | 
| 
       148 
     | 
    
         
            -
                  allow( 
     | 
| 
      
 158 
     | 
    
         
            +
                  allow(winreg).to receive(:dcerpc_request) do |arg|
         
     | 
| 
       149 
159 
     | 
    
         
             
                    if first_request
         
     | 
| 
       150 
160 
     | 
    
         
             
                      first_request = false
         
     | 
| 
       151 
     | 
    
         
            -
                       
     | 
| 
      
 161 
     | 
    
         
            +
                      response1
         
     | 
| 
       152 
162 
     | 
    
         
             
                    else
         
     | 
| 
       153 
     | 
    
         
            -
                       
     | 
| 
      
 163 
     | 
    
         
            +
                      response2
         
     | 
| 
       154 
164 
     | 
    
         
             
                    end
         
     | 
| 
       155 
165 
     | 
    
         
             
                  end
         
     | 
| 
       156 
     | 
    
         
            -
                  allow(query_value_request_packet1).to receive(:lp_data).and_return(lp_data1)
         
     | 
| 
       157 
     | 
    
         
            -
                  allow(query_value_request_packet2).to receive_messages(
         
     | 
| 
       158 
     | 
    
         
            -
                    :lp_data    => lp_data2,
         
     | 
| 
       159 
     | 
    
         
            -
                    :lpcb_data= => nil
         
     | 
| 
       160 
     | 
    
         
            -
                  )
         
     | 
| 
       161 
     | 
    
         
            -
                  allow(lp_data1).to receive(:referent_identifier=)
         
     | 
| 
       162 
     | 
    
         
            -
                  allow(lp_data2).to receive(:max_count=)
         
     | 
| 
       163 
     | 
    
         
            -
                  allow(winreg).to receive(:dcerpc_request).with(query_value_request_packet1).and_return(response1)
         
     | 
| 
       164 
     | 
    
         
            -
                  allow(winreg).to receive(:dcerpc_request).with(query_value_request_packet2).and_return(response2)
         
     | 
| 
       165 
166 
     | 
    
         
             
                  allow(described_class::QueryValueResponse).to receive(:read).with(response1).and_return(query_value_response1)
         
     | 
| 
       166 
167 
     | 
    
         
             
                  allow(described_class::QueryValueResponse).to receive(:read).with(response2).and_return(query_value_response2)
         
     | 
| 
       167 
168 
     | 
    
         
             
                  allow(query_value_response1).to receive(:error_status).and_return(WindowsError::Win32::ERROR_SUCCESS)
         
     | 
| 
         @@ -175,24 +176,22 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       175 
176 
     | 
    
         | 
| 
       176 
177 
     | 
    
         
             
                it 'create the expected QueryValueRequest packets' do
         
     | 
| 
       177 
178 
     | 
    
         
             
                  winreg.query_value(handle, value_name)
         
     | 
| 
       178 
     | 
    
         
            -
                  expect(described_class::QueryValueRequest).to have_received(:new).with(hkey: handle, lp_value_name: value_name) 
     | 
| 
       179 
     | 
    
         
            -
                end
         
     | 
| 
       180 
     | 
    
         
            -
             
     | 
| 
       181 
     | 
    
         
            -
                it 'sets the expected user rights on the first request packet' do
         
     | 
| 
       182 
     | 
    
         
            -
                  winreg.query_value(handle, value_name)
         
     | 
| 
       183 
     | 
    
         
            -
                  expect(lp_data1).to have_received(:referent_identifier=).with(0)
         
     | 
| 
      
 179 
     | 
    
         
            +
                  expect(described_class::QueryValueRequest).to have_received(:new).with(hkey: handle, lp_value_name: value_name)
         
     | 
| 
       184 
180 
     | 
    
         
             
                end
         
     | 
| 
       185 
181 
     | 
    
         | 
| 
       186 
     | 
    
         
            -
                it 'sets the expected  
     | 
| 
      
 182 
     | 
    
         
            +
                it 'sets the expected fields on the request packet' do
         
     | 
| 
       187 
183 
     | 
    
         
             
                  winreg.query_value(handle, value_name)
         
     | 
| 
       188 
     | 
    
         
            -
                  expect( 
     | 
| 
       189 
     | 
    
         
            -
                  expect( 
     | 
| 
      
 184 
     | 
    
         
            +
                  expect(query_value_request_packet).to have_received(:lp_type=).with(0)
         
     | 
| 
      
 185 
     | 
    
         
            +
                  expect(query_value_request_packet).to have_received(:lpcb_data=).with(0)
         
     | 
| 
      
 186 
     | 
    
         
            +
                  expect(query_value_request_packet).to have_received(:lpcb_len=).with(0)
         
     | 
| 
      
 187 
     | 
    
         
            +
                  expect(query_value_request_packet).to have_received(:lpcb_data=).with(lpcb_data)
         
     | 
| 
      
 188 
     | 
    
         
            +
                  expect(query_value_request_packet).to have_received(:lp_data=).with([])
         
     | 
| 
      
 189 
     | 
    
         
            +
                  expect(lp_data2_referent).to have_received(:max_count=).with(lpcb_data_referent)
         
     | 
| 
       190 
190 
     | 
    
         
             
                end
         
     | 
| 
       191 
191 
     | 
    
         | 
| 
       192 
192 
     | 
    
         
             
                it 'sends the expected dcerpc requests' do
         
     | 
| 
       193 
193 
     | 
    
         
             
                  winreg.query_value(handle, value_name)
         
     | 
| 
       194 
     | 
    
         
            -
                  expect(winreg).to have_received(:dcerpc_request).with( 
     | 
| 
       195 
     | 
    
         
            -
                  expect(winreg).to have_received(:dcerpc_request).with(query_value_request_packet2).once.ordered
         
     | 
| 
      
 194 
     | 
    
         
            +
                  expect(winreg).to have_received(:dcerpc_request).with(query_value_request_packet).twice
         
     | 
| 
       196 
195 
     | 
    
         
             
                end
         
     | 
| 
       197 
196 
     | 
    
         | 
| 
       198 
197 
     | 
    
         
             
                context 'when receiving the first response' do
         
     | 
| 
         @@ -293,8 +292,20 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       293 
292 
     | 
    
         
             
                let(:query_info_key_request_packet) { double('CloseKey Request Packet') }
         
     | 
| 
       294 
293 
     | 
    
         
             
                let(:response)                      { double('Response') }
         
     | 
| 
       295 
294 
     | 
    
         
             
                let(:query_info_key_response)       { double('CloseKey Response') }
         
     | 
| 
      
 295 
     | 
    
         
            +
                let(:lp_class)                      { double('LpClass') }
         
     | 
| 
      
 296 
     | 
    
         
            +
                let(:lp_class_referent)             { double('LpClass referent') }
         
     | 
| 
      
 297 
     | 
    
         
            +
                let(:lp_class_buf_ref)              { double('LpClass buffer referent') }
         
     | 
| 
       296 
298 
     | 
    
         
             
                before :example do
         
     | 
| 
       297 
299 
     | 
    
         
             
                  allow(described_class::QueryInfoKeyRequest).to receive(:new).and_return(query_info_key_request_packet)
         
     | 
| 
      
 300 
     | 
    
         
            +
                  allow(query_info_key_request_packet).to receive_messages(
         
     | 
| 
      
 301 
     | 
    
         
            +
                    :lp_class= => nil,
         
     | 
| 
      
 302 
     | 
    
         
            +
                    :lp_class  => lp_class,
         
     | 
| 
      
 303 
     | 
    
         
            +
                  )
         
     | 
| 
      
 304 
     | 
    
         
            +
                  allow(lp_class).to receive(:referent).and_return(lp_class_referent)
         
     | 
| 
      
 305 
     | 
    
         
            +
                  allow(lp_class_referent).to receive(:actual_count=)
         
     | 
| 
      
 306 
     | 
    
         
            +
                  allow(lp_class).to receive(:maximum_length=)
         
     | 
| 
      
 307 
     | 
    
         
            +
                  allow(lp_class).to receive_message_chain(:buffer, :referent => lp_class_buf_ref)
         
     | 
| 
      
 308 
     | 
    
         
            +
                  allow(lp_class_buf_ref).to receive(:max_count=)
         
     | 
| 
       298 
309 
     | 
    
         
             
                  allow(winreg).to receive(:dcerpc_request).and_return(response)
         
     | 
| 
       299 
310 
     | 
    
         
             
                  allow(described_class::QueryInfoKeyResponse).to receive(:read).and_return(query_info_key_response)
         
     | 
| 
       300 
311 
     | 
    
         
             
                  allow(query_info_key_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_SUCCESS)
         
     | 
| 
         @@ -310,6 +321,14 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       310 
321 
     | 
    
         
             
                  expect(winreg).to have_received(:dcerpc_request).with(query_info_key_request_packet)
         
     | 
| 
       311 
322 
     | 
    
         
             
                end
         
     | 
| 
       312 
323 
     | 
    
         | 
| 
      
 324 
     | 
    
         
            +
                it 'sets the expected fields on the request packet' do
         
     | 
| 
      
 325 
     | 
    
         
            +
                  winreg.query_info_key(handle)
         
     | 
| 
      
 326 
     | 
    
         
            +
                  expect(query_info_key_request_packet).to have_received(:lp_class=).with('')
         
     | 
| 
      
 327 
     | 
    
         
            +
                  expect(lp_class_referent).to have_received(:actual_count=).with(0)
         
     | 
| 
      
 328 
     | 
    
         
            +
                  expect(lp_class).to have_received(:maximum_length=).with(1024)
         
     | 
| 
      
 329 
     | 
    
         
            +
                  expect(lp_class_buf_ref).to have_received(:max_count=).with(1024 / 2)
         
     | 
| 
      
 330 
     | 
    
         
            +
                end
         
     | 
| 
      
 331 
     | 
    
         
            +
             
     | 
| 
       313 
332 
     | 
    
         
             
                it 'creates a QueryInfoKeyResponse structure from the expected dcerpc response' do
         
     | 
| 
       314 
333 
     | 
    
         
             
                  winreg.query_info_key(handle)
         
     | 
| 
       315 
334 
     | 
    
         
             
                  expect(described_class::QueryInfoKeyResponse).to have_received(:read).with(response)
         
     | 
| 
         @@ -338,25 +357,27 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       338 
357 
     | 
    
         
             
                let(:handle)                   { double('Handle') }
         
     | 
| 
       339 
358 
     | 
    
         
             
                let(:index)                    { double('Index') }
         
     | 
| 
       340 
359 
     | 
    
         
             
                let(:enum_key_request_packet)  { double('enum_key Request Packet') }
         
     | 
| 
       341 
     | 
    
         
            -
                let(:lp_class)                 { double('Lp Class') }
         
     | 
| 
       342 
360 
     | 
    
         
             
                let(:lp_name)                  { double('Lp Name') }
         
     | 
| 
       343 
361 
     | 
    
         
             
                let(:buffer)                   { double('Buffer') }
         
     | 
| 
       344 
     | 
    
         
            -
                let(:lp_class_buffer_referent) { double('Lp Class buffer referent') }
         
     | 
| 
       345 
362 
     | 
    
         
             
                let(:lp_name_buffer_referent)  { double('Lp Name buffer referent') }
         
     | 
| 
       346 
363 
     | 
    
         
             
                let(:response)                 { double('Response') }
         
     | 
| 
       347 
364 
     | 
    
         
             
                let(:enum_key_response)        { double('enum_key Response') }
         
     | 
| 
       348 
365 
     | 
    
         
             
                let(:result_str)               { double('Result String') }
         
     | 
| 
      
 366 
     | 
    
         
            +
                let(:lp_class)                 { double('Lp Class') }
         
     | 
| 
      
 367 
     | 
    
         
            +
                let(:lp_class_buffer_referent) { double('Lp Class buffer referent') }
         
     | 
| 
       349 
368 
     | 
    
         
             
                before :example do
         
     | 
| 
       350 
369 
     | 
    
         
             
                  allow(described_class::EnumKeyRequest).to receive(:new).and_return(enum_key_request_packet)
         
     | 
| 
       351 
370 
     | 
    
         
             
                  allow(enum_key_request_packet).to receive_messages(
         
     | 
| 
       352 
371 
     | 
    
         
             
                    :lpft_last_write_time= => nil,
         
     | 
| 
       353 
     | 
    
         
            -
                    :lp_class 
     | 
| 
       354 
     | 
    
         
            -
                    :lp_name               => lp_name
         
     | 
| 
      
 372 
     | 
    
         
            +
                    :lp_class=             => nil,
         
     | 
| 
      
 373 
     | 
    
         
            +
                    :lp_name               => lp_name,
         
     | 
| 
      
 374 
     | 
    
         
            +
                    :lp_class              => lp_class
         
     | 
| 
       355 
375 
     | 
    
         
             
                  )
         
     | 
| 
       356 
376 
     | 
    
         
             
                  allow(lp_class).to receive(:referent).and_return(lp_class_buffer_referent)
         
     | 
| 
      
 377 
     | 
    
         
            +
                  allow(lp_class_buffer_referent).to receive(:buffer=)
         
     | 
| 
       357 
378 
     | 
    
         
             
                  allow(lp_name).to receive(:buffer).and_return(buffer)
         
     | 
| 
      
 379 
     | 
    
         
            +
                  allow(lp_name).to receive(:buffer=)
         
     | 
| 
       358 
380 
     | 
    
         
             
                  allow(buffer).to receive(:referent).and_return(lp_name_buffer_referent)
         
     | 
| 
       359 
     | 
    
         
            -
                  allow(lp_class_buffer_referent).to receive(:buffer=)
         
     | 
| 
       360 
381 
     | 
    
         
             
                  allow(lp_name_buffer_referent).to receive(:max_count=)
         
     | 
| 
       361 
382 
     | 
    
         
             
                  allow(winreg).to receive(:dcerpc_request).and_return(response)
         
     | 
| 
       362 
383 
     | 
    
         
             
                  allow(described_class::EnumKeyResponse).to receive(:read).and_return(enum_key_response)
         
     | 
| 
         @@ -369,10 +390,12 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       369 
390 
     | 
    
         
             
                  expect(described_class::EnumKeyRequest).to have_received(:new).with(hkey: handle, dw_index: index)
         
     | 
| 
       370 
391 
     | 
    
         
             
                end
         
     | 
| 
       371 
392 
     | 
    
         | 
| 
       372 
     | 
    
         
            -
                it 'sets the expected  
     | 
| 
      
 393 
     | 
    
         
            +
                it 'sets the expected parameters on the request packet' do
         
     | 
| 
       373 
394 
     | 
    
         
             
                  winreg.enum_key(handle, index)
         
     | 
| 
       374 
395 
     | 
    
         
             
                  expect(enum_key_request_packet).to have_received(:lpft_last_write_time=).with(0)
         
     | 
| 
       375 
     | 
    
         
            -
                  expect( 
     | 
| 
      
 396 
     | 
    
         
            +
                  expect(enum_key_request_packet).to have_received(:lp_class=).with('')
         
     | 
| 
      
 397 
     | 
    
         
            +
                  expect(lp_class_buffer_referent).to have_received(:buffer=).with(:null)
         
     | 
| 
      
 398 
     | 
    
         
            +
                  expect(lp_name).to have_received(:buffer=).with('')
         
     | 
| 
       376 
399 
     | 
    
         
             
                  expect(lp_name_buffer_referent).to have_received(:max_count=).with(256)
         
     | 
| 
       377 
400 
     | 
    
         
             
                end
         
     | 
| 
       378 
401 
     | 
    
         | 
| 
         @@ -410,7 +433,6 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       410 
433 
     | 
    
         
             
                let(:index)                     { double('Index') }
         
     | 
| 
       411 
434 
     | 
    
         
             
                let(:enum_value_request_packet) { double('EnumValue Request Packet') }
         
     | 
| 
       412 
435 
     | 
    
         
             
                let(:lp_value_name)             { double('Lp Value Name') }
         
     | 
| 
       413 
     | 
    
         
            -
                let(:lp_data)                   { double('Lp Data') }
         
     | 
| 
       414 
436 
     | 
    
         
             
                let(:buffer)                    { double('Buffer') }
         
     | 
| 
       415 
437 
     | 
    
         
             
                let(:referent)                  { double('Referent') }
         
     | 
| 
       416 
438 
     | 
    
         
             
                let(:response)                  { double('Response') }
         
     | 
| 
         @@ -418,14 +440,11 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       418 
440 
     | 
    
         
             
                let(:result_str)                { double('Result String') }
         
     | 
| 
       419 
441 
     | 
    
         
             
                before :example do
         
     | 
| 
       420 
442 
     | 
    
         
             
                  allow(described_class::EnumValueRequest).to receive(:new).and_return(enum_value_request_packet)
         
     | 
| 
       421 
     | 
    
         
            -
                  allow(enum_value_request_packet).to  
     | 
| 
       422 
     | 
    
         
            -
                    :lp_value_name => lp_value_name,
         
     | 
| 
       423 
     | 
    
         
            -
                    :lp_data       => lp_data
         
     | 
| 
       424 
     | 
    
         
            -
                  )
         
     | 
| 
      
 443 
     | 
    
         
            +
                  allow(enum_value_request_packet).to receive(:lp_value_name).and_return(lp_value_name)
         
     | 
| 
       425 
444 
     | 
    
         
             
                  allow(lp_value_name).to receive(:buffer).and_return(buffer)
         
     | 
| 
      
 445 
     | 
    
         
            +
                  allow(lp_value_name).to receive(:buffer=)
         
     | 
| 
       426 
446 
     | 
    
         
             
                  allow(buffer).to receive(:referent).and_return(referent)
         
     | 
| 
       427 
447 
     | 
    
         
             
                  allow(referent).to receive(:max_count=)
         
     | 
| 
       428 
     | 
    
         
            -
                  allow(lp_data).to receive(:referent_identifier=)
         
     | 
| 
       429 
448 
     | 
    
         
             
                  allow(winreg).to receive(:dcerpc_request).and_return(response)
         
     | 
| 
       430 
449 
     | 
    
         
             
                  allow(described_class::EnumValueResponse).to receive(:read).and_return(enum_value_response)
         
     | 
| 
       431 
450 
     | 
    
         
             
                  allow(enum_value_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_SUCCESS)
         
     | 
| 
         @@ -437,10 +456,10 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       437 
456 
     | 
    
         
             
                  expect(described_class::EnumValueRequest).to have_received(:new).with(hkey: handle, dw_index: index)
         
     | 
| 
       438 
457 
     | 
    
         
             
                end
         
     | 
| 
       439 
458 
     | 
    
         | 
| 
       440 
     | 
    
         
            -
                it 'sets the expected  
     | 
| 
      
 459 
     | 
    
         
            +
                it 'sets the expected buffer on the request packet' do
         
     | 
| 
       441 
460 
     | 
    
         
             
                  winreg.enum_value(handle, index)
         
     | 
| 
       442 
461 
     | 
    
         
             
                  expect(referent).to have_received(:max_count=).with(256)
         
     | 
| 
       443 
     | 
    
         
            -
                  expect( 
     | 
| 
      
 462 
     | 
    
         
            +
                  expect(lp_value_name).to have_received(:buffer=).with('')
         
     | 
| 
       444 
463 
     | 
    
         
             
                end
         
     | 
| 
       445 
464 
     | 
    
         | 
| 
       446 
465 
     | 
    
         
             
                it 'sends the expected dcerpc request' do
         
     | 
| 
         @@ -492,6 +511,11 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       492 
511 
     | 
    
         
             
                  expect(winreg).to have_received(:bind).with(endpoint: RubySMB::Dcerpc::Winreg)
         
     | 
| 
       493 
512 
     | 
    
         
             
                end
         
     | 
| 
       494 
513 
     | 
    
         | 
| 
      
 514 
     | 
    
         
            +
                it 'does not bind a DCERPC connection if #bind argument is false' do
         
     | 
| 
      
 515 
     | 
    
         
            +
                  winreg.has_registry_key?(key, bind: false)
         
     | 
| 
      
 516 
     | 
    
         
            +
                  expect(winreg).to_not have_received(:bind)
         
     | 
| 
      
 517 
     | 
    
         
            +
                end
         
     | 
| 
      
 518 
     | 
    
         
            +
             
     | 
| 
       495 
519 
     | 
    
         
             
                it 'opens the expected root key' do
         
     | 
| 
       496 
520 
     | 
    
         
             
                  winreg.has_registry_key?(key)
         
     | 
| 
       497 
521 
     | 
    
         
             
                  expect(winreg).to have_received(:open_root_key).with(root_key)
         
     | 
| 
         @@ -519,6 +543,7 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       519 
543 
     | 
    
         
             
                it 'closes the key' do
         
     | 
| 
       520 
544 
     | 
    
         
             
                  winreg.has_registry_key?(key)
         
     | 
| 
       521 
545 
     | 
    
         
             
                  expect(winreg).to have_received(:close_key).with(subkey_handle)
         
     | 
| 
      
 546 
     | 
    
         
            +
                  expect(winreg).to have_received(:close_key).with(root_key_handle)
         
     | 
| 
       522 
547 
     | 
    
         
             
                end
         
     | 
| 
       523 
548 
     | 
    
         | 
| 
       524 
549 
     | 
    
         
             
                it 'returns true when no error occurs' do
         
     | 
| 
         @@ -549,6 +574,11 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       549 
574 
     | 
    
         
             
                  expect(winreg).to have_received(:bind).with(endpoint: RubySMB::Dcerpc::Winreg)
         
     | 
| 
       550 
575 
     | 
    
         
             
                end
         
     | 
| 
       551 
576 
     | 
    
         | 
| 
      
 577 
     | 
    
         
            +
                it 'does not bind a DCERPC connection if #bind argument is false' do
         
     | 
| 
      
 578 
     | 
    
         
            +
                  winreg.read_registry_key_value(key, value_name, bind: false)
         
     | 
| 
      
 579 
     | 
    
         
            +
                  expect(winreg).to_not have_received(:bind)
         
     | 
| 
      
 580 
     | 
    
         
            +
                end
         
     | 
| 
      
 581 
     | 
    
         
            +
             
     | 
| 
       552 
582 
     | 
    
         
             
                it 'opens the expected root key' do
         
     | 
| 
       553 
583 
     | 
    
         
             
                  winreg.read_registry_key_value(key, value_name)
         
     | 
| 
       554 
584 
     | 
    
         
             
                  expect(winreg).to have_received(:open_root_key).with(root_key)
         
     | 
| 
         @@ -567,6 +597,7 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       567 
597 
     | 
    
         
             
                it 'closes the key' do
         
     | 
| 
       568 
598 
     | 
    
         
             
                  winreg.read_registry_key_value(key, value_name)
         
     | 
| 
       569 
599 
     | 
    
         
             
                  expect(winreg).to have_received(:close_key).with(subkey_handle)
         
     | 
| 
      
 600 
     | 
    
         
            +
                  expect(winreg).to have_received(:close_key).with(root_key_handle)
         
     | 
| 
       570 
601 
     | 
    
         
             
                end
         
     | 
| 
       571 
602 
     | 
    
         | 
| 
       572 
603 
     | 
    
         
             
                it 'returns expect registry key value' do
         
     | 
| 
         @@ -600,6 +631,11 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       600 
631 
     | 
    
         
             
                  expect(winreg).to have_received(:bind).with(endpoint: RubySMB::Dcerpc::Winreg)
         
     | 
| 
       601 
632 
     | 
    
         
             
                end
         
     | 
| 
       602 
633 
     | 
    
         | 
| 
      
 634 
     | 
    
         
            +
                it 'does not bind a DCERPC connection if #bind argument is false' do
         
     | 
| 
      
 635 
     | 
    
         
            +
                  winreg.enum_registry_key(key, bind: false)
         
     | 
| 
      
 636 
     | 
    
         
            +
                  expect(winreg).to_not have_received(:bind)
         
     | 
| 
      
 637 
     | 
    
         
            +
                end
         
     | 
| 
      
 638 
     | 
    
         
            +
             
     | 
| 
       603 
639 
     | 
    
         
             
                it 'opens the expected root key' do
         
     | 
| 
       604 
640 
     | 
    
         
             
                  winreg.enum_registry_key(key)
         
     | 
| 
       605 
641 
     | 
    
         
             
                  expect(winreg).to have_received(:open_root_key).with(root_key)
         
     | 
| 
         @@ -630,6 +666,13 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       630 
666 
     | 
    
         
             
                it 'closes the key' do
         
     | 
| 
       631 
667 
     | 
    
         
             
                  winreg.enum_registry_key(key)
         
     | 
| 
       632 
668 
     | 
    
         
             
                  expect(winreg).to have_received(:close_key).with(subkey_handle)
         
     | 
| 
      
 669 
     | 
    
         
            +
                  expect(winreg).to have_received(:close_key).with(root_key_handle)
         
     | 
| 
      
 670 
     | 
    
         
            +
                end
         
     | 
| 
      
 671 
     | 
    
         
            +
             
     | 
| 
      
 672 
     | 
    
         
            +
                it 'only closes the key once when there is no subkey' do
         
     | 
| 
      
 673 
     | 
    
         
            +
                  winreg.enum_registry_key(root_key)
         
     | 
| 
      
 674 
     | 
    
         
            +
                  expect(winreg).to have_received(:close_key).once
         
     | 
| 
      
 675 
     | 
    
         
            +
                  expect(winreg).to have_received(:close_key).with(root_key_handle)
         
     | 
| 
       633 
676 
     | 
    
         
             
                end
         
     | 
| 
       634 
677 
     | 
    
         | 
| 
       635 
678 
     | 
    
         
             
                it 'returns the expected array of enumerated keys' do
         
     | 
| 
         @@ -667,6 +710,11 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       667 
710 
     | 
    
         
             
                  expect(winreg).to have_received(:bind).with(endpoint: RubySMB::Dcerpc::Winreg)
         
     | 
| 
       668 
711 
     | 
    
         
             
                end
         
     | 
| 
       669 
712 
     | 
    
         | 
| 
      
 713 
     | 
    
         
            +
                it 'does not bind a DCERPC connection if #bind argument is false' do
         
     | 
| 
      
 714 
     | 
    
         
            +
                  winreg.enum_registry_values(key, bind: false)
         
     | 
| 
      
 715 
     | 
    
         
            +
                  expect(winreg).to_not have_received(:bind)
         
     | 
| 
      
 716 
     | 
    
         
            +
                end
         
     | 
| 
      
 717 
     | 
    
         
            +
             
     | 
| 
       670 
718 
     | 
    
         
             
                it 'opens the expected root key' do
         
     | 
| 
       671 
719 
     | 
    
         
             
                  winreg.enum_registry_values(key)
         
     | 
| 
       672 
720 
     | 
    
         
             
                  expect(winreg).to have_received(:open_root_key).with(root_key)
         
     | 
| 
         @@ -697,6 +745,13 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       697 
745 
     | 
    
         
             
                it 'closes the key' do
         
     | 
| 
       698 
746 
     | 
    
         
             
                  winreg.enum_registry_values(key)
         
     | 
| 
       699 
747 
     | 
    
         
             
                  expect(winreg).to have_received(:close_key).with(subkey_handle)
         
     | 
| 
      
 748 
     | 
    
         
            +
                  expect(winreg).to have_received(:close_key).with(root_key_handle)
         
     | 
| 
      
 749 
     | 
    
         
            +
                end
         
     | 
| 
      
 750 
     | 
    
         
            +
             
     | 
| 
      
 751 
     | 
    
         
            +
                it 'only closes the key once when there is no subkey' do
         
     | 
| 
      
 752 
     | 
    
         
            +
                  winreg.enum_registry_values(root_key)
         
     | 
| 
      
 753 
     | 
    
         
            +
                  expect(winreg).to have_received(:close_key).once
         
     | 
| 
      
 754 
     | 
    
         
            +
                  expect(winreg).to have_received(:close_key).with(root_key_handle)
         
     | 
| 
       700 
755 
     | 
    
         
             
                end
         
     | 
| 
       701 
756 
     | 
    
         | 
| 
       702 
757 
     | 
    
         
             
                it 'returns the expected array of enumerated keys' do
         
     | 
| 
         @@ -707,4 +762,135 @@ RSpec.describe RubySMB::Dcerpc::Winreg do 
     | 
|
| 
       707 
762 
     | 
    
         
             
                  expect(winreg.enum_registry_values(key)).to eq([value1, value2])
         
     | 
| 
       708 
763 
     | 
    
         
             
                end
         
     | 
| 
       709 
764 
     | 
    
         
             
              end
         
     | 
| 
      
 765 
     | 
    
         
            +
             
     | 
| 
      
 766 
     | 
    
         
            +
              describe '#create_key' do
         
     | 
| 
      
 767 
     | 
    
         
            +
                let(:handle)              { double('Handle') }
         
     | 
| 
      
 768 
     | 
    
         
            +
                let(:sub_key)             { double('Sub key') }
         
     | 
| 
      
 769 
     | 
    
         
            +
                let(:create_key_request)  { double('CreateKey Request') }
         
     | 
| 
      
 770 
     | 
    
         
            +
                let(:response)            { double('Response') }
         
     | 
| 
      
 771 
     | 
    
         
            +
                let(:create_key_response) { double('CreateKey Response') }
         
     | 
| 
      
 772 
     | 
    
         
            +
                let(:hkey)                { double('hkey') }
         
     | 
| 
      
 773 
     | 
    
         
            +
                before :example do
         
     | 
| 
      
 774 
     | 
    
         
            +
                  allow(described_class::CreateKeyRequest).to receive(:new).and_return(create_key_request)
         
     | 
| 
      
 775 
     | 
    
         
            +
                  allow(winreg).to receive(:dcerpc_request).and_return(response)
         
     | 
| 
      
 776 
     | 
    
         
            +
                  allow(described_class::CreateKeyResponse).to receive(:read).and_return(create_key_response)
         
     | 
| 
      
 777 
     | 
    
         
            +
                  allow(create_key_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_SUCCESS)
         
     | 
| 
      
 778 
     | 
    
         
            +
                  allow(create_key_response).to receive(:hkey).and_return(hkey)
         
     | 
| 
      
 779 
     | 
    
         
            +
                end
         
     | 
| 
      
 780 
     | 
    
         
            +
             
     | 
| 
      
 781 
     | 
    
         
            +
                it 'create the expected CreateKeyRequest packet with the default options' do
         
     | 
| 
      
 782 
     | 
    
         
            +
                  opts = {
         
     | 
| 
      
 783 
     | 
    
         
            +
                    hkey:                   handle,
         
     | 
| 
      
 784 
     | 
    
         
            +
                    lp_sub_key:             sub_key,
         
     | 
| 
      
 785 
     | 
    
         
            +
                    lp_class:               :null,
         
     | 
| 
      
 786 
     | 
    
         
            +
                    dw_options:             RubySMB::Dcerpc::Winreg::CreateKeyRequest::REG_KEY_TYPE_VOLATILE,
         
     | 
| 
      
 787 
     | 
    
         
            +
                    sam_desired:            RubySMB::Dcerpc::Winreg::Regsam.new(maximum: 1),
         
     | 
| 
      
 788 
     | 
    
         
            +
                    lp_security_attributes: RubySMB::Dcerpc::RpcSecurityAttributes.new,
         
     | 
| 
      
 789 
     | 
    
         
            +
                    lpdw_disposition:       RubySMB::Dcerpc::Winreg::CreateKeyRequest::REG_CREATED_NEW_KEY
         
     | 
| 
      
 790 
     | 
    
         
            +
                  }
         
     | 
| 
      
 791 
     | 
    
         
            +
                  winreg.create_key(handle, sub_key)
         
     | 
| 
      
 792 
     | 
    
         
            +
                  expect(described_class::CreateKeyRequest).to have_received(:new).with(opts)
         
     | 
| 
      
 793 
     | 
    
         
            +
                end
         
     | 
| 
      
 794 
     | 
    
         
            +
             
     | 
| 
      
 795 
     | 
    
         
            +
                it 'create the expected CreateKeyRequest packet with custom options' do
         
     | 
| 
      
 796 
     | 
    
         
            +
                  opts = {
         
     | 
| 
      
 797 
     | 
    
         
            +
                    hkey:                  handle,
         
     | 
| 
      
 798 
     | 
    
         
            +
                    lp_sub_key:            sub_key,
         
     | 
| 
      
 799 
     | 
    
         
            +
                    lp_class:              'MyClass',
         
     | 
| 
      
 800 
     | 
    
         
            +
                    dw_options:             RubySMB::Dcerpc::Winreg::CreateKeyRequest::REG_KEY_TYPE_SYMLINK,
         
     | 
| 
      
 801 
     | 
    
         
            +
                    sam_desired:            RubySMB::Dcerpc::Winreg::Regsam.new(key_set_value: 1),
         
     | 
| 
      
 802 
     | 
    
         
            +
                    lp_security_attributes: RubySMB::Dcerpc::RpcSecurityAttributes.new(n_length: 3),
         
     | 
| 
      
 803 
     | 
    
         
            +
                    lpdw_disposition:       RubySMB::Dcerpc::Winreg::CreateKeyRequest::REG_OPENED_EXISTING_KEY
         
     | 
| 
      
 804 
     | 
    
         
            +
                  }
         
     | 
| 
      
 805 
     | 
    
         
            +
                  winreg.create_key(handle, sub_key, opts)
         
     | 
| 
      
 806 
     | 
    
         
            +
                  expect(described_class::CreateKeyRequest).to have_received(:new).with(opts)
         
     | 
| 
      
 807 
     | 
    
         
            +
                end
         
     | 
| 
      
 808 
     | 
    
         
            +
             
     | 
| 
      
 809 
     | 
    
         
            +
                it 'sends the expected dcerpc request' do
         
     | 
| 
      
 810 
     | 
    
         
            +
                  winreg.create_key(handle, sub_key)
         
     | 
| 
      
 811 
     | 
    
         
            +
                  expect(winreg).to have_received(:dcerpc_request).with(create_key_request)
         
     | 
| 
      
 812 
     | 
    
         
            +
                end
         
     | 
| 
      
 813 
     | 
    
         
            +
             
     | 
| 
      
 814 
     | 
    
         
            +
                it 'creates a CreateKeyResponse structure from the expected dcerpc response' do
         
     | 
| 
      
 815 
     | 
    
         
            +
                  winreg.create_key(handle, sub_key)
         
     | 
| 
      
 816 
     | 
    
         
            +
                  expect(described_class::CreateKeyResponse).to have_received(:read).with(response)
         
     | 
| 
      
 817 
     | 
    
         
            +
                end
         
     | 
| 
      
 818 
     | 
    
         
            +
             
     | 
| 
      
 819 
     | 
    
         
            +
                context 'when an IOError occurs while parsing the response' do
         
     | 
| 
      
 820 
     | 
    
         
            +
                  it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
         
     | 
| 
      
 821 
     | 
    
         
            +
                    allow(described_class::CreateKeyResponse).to receive(:read).and_raise(IOError)
         
     | 
| 
      
 822 
     | 
    
         
            +
                    expect { winreg.create_key(handle, sub_key) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
         
     | 
| 
      
 823 
     | 
    
         
            +
                  end
         
     | 
| 
      
 824 
     | 
    
         
            +
                end
         
     | 
| 
      
 825 
     | 
    
         
            +
             
     | 
| 
      
 826 
     | 
    
         
            +
                context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
         
     | 
| 
      
 827 
     | 
    
         
            +
                  it 'raises a RubySMB::Dcerpc::Error::WinregError' do
         
     | 
| 
      
 828 
     | 
    
         
            +
                    allow(create_key_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
         
     | 
| 
      
 829 
     | 
    
         
            +
                    expect { winreg.create_key(handle, sub_key) }.to raise_error(RubySMB::Dcerpc::Error::WinregError)
         
     | 
| 
      
 830 
     | 
    
         
            +
                  end
         
     | 
| 
      
 831 
     | 
    
         
            +
                end
         
     | 
| 
      
 832 
     | 
    
         
            +
             
     | 
| 
      
 833 
     | 
    
         
            +
                it 'returns the expected key name' do
         
     | 
| 
      
 834 
     | 
    
         
            +
                  expect(winreg.create_key(handle, sub_key)).to eq(hkey)
         
     | 
| 
      
 835 
     | 
    
         
            +
                end
         
     | 
| 
      
 836 
     | 
    
         
            +
              end
         
     | 
| 
      
 837 
     | 
    
         
            +
             
     | 
| 
      
 838 
     | 
    
         
            +
              describe '#save_key' do
         
     | 
| 
      
 839 
     | 
    
         
            +
                let(:handle)              { double('Handle') }
         
     | 
| 
      
 840 
     | 
    
         
            +
                let(:filename)            { double('Filename') }
         
     | 
| 
      
 841 
     | 
    
         
            +
                let(:save_key_request)    { double('CreateKey Request') }
         
     | 
| 
      
 842 
     | 
    
         
            +
                let(:response)            { double('Response') }
         
     | 
| 
      
 843 
     | 
    
         
            +
                let(:save_key_response)   { double('CreateKey Response') }
         
     | 
| 
      
 844 
     | 
    
         
            +
                let(:hkey)                { double('hkey') }
         
     | 
| 
      
 845 
     | 
    
         
            +
                before :example do
         
     | 
| 
      
 846 
     | 
    
         
            +
                  allow(described_class::SaveKeyRequest).to receive(:new).and_return(save_key_request)
         
     | 
| 
      
 847 
     | 
    
         
            +
                  allow(winreg).to receive(:dcerpc_request).and_return(response)
         
     | 
| 
      
 848 
     | 
    
         
            +
                  allow(described_class::SaveKeyResponse).to receive(:read).and_return(save_key_response)
         
     | 
| 
      
 849 
     | 
    
         
            +
                  allow(save_key_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_SUCCESS)
         
     | 
| 
      
 850 
     | 
    
         
            +
                end
         
     | 
| 
      
 851 
     | 
    
         
            +
             
     | 
| 
      
 852 
     | 
    
         
            +
                it 'create the expected SaveKeyRequest packet with the default options' do
         
     | 
| 
      
 853 
     | 
    
         
            +
                  opts = {
         
     | 
| 
      
 854 
     | 
    
         
            +
                    hkey:                   handle,
         
     | 
| 
      
 855 
     | 
    
         
            +
                    lp_file:                filename,
         
     | 
| 
      
 856 
     | 
    
         
            +
                    lp_security_attributes: :null,
         
     | 
| 
      
 857 
     | 
    
         
            +
                  }
         
     | 
| 
      
 858 
     | 
    
         
            +
                  winreg.save_key(handle, filename)
         
     | 
| 
      
 859 
     | 
    
         
            +
                  expect(described_class::SaveKeyRequest).to have_received(:new).with(opts)
         
     | 
| 
      
 860 
     | 
    
         
            +
                end
         
     | 
| 
      
 861 
     | 
    
         
            +
             
     | 
| 
      
 862 
     | 
    
         
            +
                it 'create the expected SaveKeyRequest packet with custom options' do
         
     | 
| 
      
 863 
     | 
    
         
            +
                  opts = {
         
     | 
| 
      
 864 
     | 
    
         
            +
                    hkey:                   handle,
         
     | 
| 
      
 865 
     | 
    
         
            +
                    lp_file:                filename,
         
     | 
| 
      
 866 
     | 
    
         
            +
                    lp_security_attributes: RubySMB::Dcerpc::RpcSecurityAttributes.new,
         
     | 
| 
      
 867 
     | 
    
         
            +
                  }
         
     | 
| 
      
 868 
     | 
    
         
            +
                  winreg.save_key(handle, filename, opts)
         
     | 
| 
      
 869 
     | 
    
         
            +
                  expect(described_class::SaveKeyRequest).to have_received(:new).with(opts)
         
     | 
| 
      
 870 
     | 
    
         
            +
                end
         
     | 
| 
      
 871 
     | 
    
         
            +
             
     | 
| 
      
 872 
     | 
    
         
            +
                it 'sends the expected dcerpc request' do
         
     | 
| 
      
 873 
     | 
    
         
            +
                  winreg.save_key(handle, filename)
         
     | 
| 
      
 874 
     | 
    
         
            +
                  expect(winreg).to have_received(:dcerpc_request).with(save_key_request)
         
     | 
| 
      
 875 
     | 
    
         
            +
                end
         
     | 
| 
      
 876 
     | 
    
         
            +
             
     | 
| 
      
 877 
     | 
    
         
            +
                it 'creates a SaveKeyResponse structure from the expected dcerpc response' do
         
     | 
| 
      
 878 
     | 
    
         
            +
                  winreg.save_key(handle, filename)
         
     | 
| 
      
 879 
     | 
    
         
            +
                  expect(described_class::SaveKeyResponse).to have_received(:read).with(response)
         
     | 
| 
      
 880 
     | 
    
         
            +
                end
         
     | 
| 
      
 881 
     | 
    
         
            +
             
     | 
| 
      
 882 
     | 
    
         
            +
                context 'when an IOError occurs while parsing the response' do
         
     | 
| 
      
 883 
     | 
    
         
            +
                  it 'raises a RubySMB::Dcerpc::Error::InvalidPacket' do
         
     | 
| 
      
 884 
     | 
    
         
            +
                    allow(described_class::SaveKeyResponse).to receive(:read).and_raise(IOError)
         
     | 
| 
      
 885 
     | 
    
         
            +
                    expect { winreg.save_key(handle, filename) }.to raise_error(RubySMB::Dcerpc::Error::InvalidPacket)
         
     | 
| 
      
 886 
     | 
    
         
            +
                  end
         
     | 
| 
      
 887 
     | 
    
         
            +
                end
         
     | 
| 
      
 888 
     | 
    
         
            +
             
     | 
| 
      
 889 
     | 
    
         
            +
                context 'when the response error status is not WindowsError::Win32::ERROR_SUCCESS' do
         
     | 
| 
      
 890 
     | 
    
         
            +
                  it 'raises a RubySMB::Dcerpc::Error::WinregError' do
         
     | 
| 
      
 891 
     | 
    
         
            +
                    allow(save_key_response).to receive(:error_status).and_return(WindowsError::Win32::ERROR_INVALID_DATA)
         
     | 
| 
      
 892 
     | 
    
         
            +
                    expect { winreg.save_key(handle, filename) }.to raise_error(RubySMB::Dcerpc::Error::WinregError)
         
     | 
| 
      
 893 
     | 
    
         
            +
                  end
         
     | 
| 
      
 894 
     | 
    
         
            +
                end
         
     | 
| 
      
 895 
     | 
    
         
            +
              end
         
     | 
| 
       710 
896 
     | 
    
         
             
            end
         
     | 
| 
         @@ -51,9 +51,9 @@ RSpec.describe RubySMB::Dispatcher::Socket do 
     | 
|
| 
       51 
51 
     | 
    
         
             
                let(:session_header)  { RubySMB::Nbss::SessionHeader.new }
         
     | 
| 
       52 
52 
     | 
    
         | 
| 
       53 
53 
     | 
    
         
             
                context 'when reading from the socket results in a nil value' do
         
     | 
| 
       54 
     | 
    
         
            -
                  it 'should raise Error:: 
     | 
| 
      
 54 
     | 
    
         
            +
                  it 'should raise Error::CommunicationError' do
         
     | 
| 
       55 
55 
     | 
    
         
             
                    smb_socket.tcp_socket = blank_socket
         
     | 
| 
       56 
     | 
    
         
            -
                    expect { smb_socket.recv_packet }.to raise_error(::RubySMB::Error:: 
     | 
| 
      
 56 
     | 
    
         
            +
                    expect { smb_socket.recv_packet }.to raise_error(::RubySMB::Error::CommunicationError)
         
     | 
| 
       57 
57 
     | 
    
         
             
                  end
         
     | 
| 
       58 
58 
     | 
    
         
             
                end
         
     | 
| 
       59 
59 
     | 
    
         | 
| 
         @@ -102,26 +102,26 @@ RSpec.describe RubySMB::Dispatcher::Socket do 
     | 
|
| 
       102 
102 
     | 
    
         
             
                  end
         
     | 
| 
       103 
103 
     | 
    
         | 
| 
       104 
104 
     | 
    
         
             
                  it 'reads the number of bytes specified in the nbss header' do
         
     | 
| 
       105 
     | 
    
         
            -
                     
     | 
| 
       106 
     | 
    
         
            -
                    session_header. 
     | 
| 
      
 105 
     | 
    
         
            +
                    stream_protocol_length = 10
         
     | 
| 
      
 106 
     | 
    
         
            +
                    session_header.stream_protocol_length = stream_protocol_length
         
     | 
| 
       107 
107 
     | 
    
         
             
                    allow(RubySMB::Nbss::SessionHeader).to receive(:read).and_return(session_header)
         
     | 
| 
       108 
108 
     | 
    
         
             
                    expect(response_socket).to receive(:read).with(4).and_return(session_header)
         
     | 
| 
       109 
     | 
    
         
            -
                    expect(response_socket).to receive(:read).with( 
     | 
| 
      
 109 
     | 
    
         
            +
                    expect(response_socket).to receive(:read).with(stream_protocol_length).and_return('A' * stream_protocol_length)
         
     | 
| 
       110 
110 
     | 
    
         
             
                    smb_socket.recv_packet
         
     | 
| 
       111 
111 
     | 
    
         
             
                  end
         
     | 
| 
       112 
112 
     | 
    
         | 
| 
       113 
113 
     | 
    
         
             
                  context 'when the socket does not return everything the first time' do
         
     | 
| 
       114 
114 
     | 
    
         
             
                    it 'calls #read several times until everything is returned' do
         
     | 
| 
       115 
     | 
    
         
            -
                       
     | 
| 
      
 115 
     | 
    
         
            +
                      stream_protocol_length = 67
         
     | 
| 
       116 
116 
     | 
    
         
             
                      returned_length = 10
         
     | 
| 
       117 
     | 
    
         
            -
                      session_header. 
     | 
| 
      
 117 
     | 
    
         
            +
                      session_header.stream_protocol_length = stream_protocol_length
         
     | 
| 
       118 
118 
     | 
    
         
             
                      allow(RubySMB::Nbss::SessionHeader).to receive(:read).and_return(session_header)
         
     | 
| 
       119 
119 
     | 
    
         | 
| 
       120 
120 
     | 
    
         
             
                      expect(response_socket).to receive(:read).with(4).and_return(session_header)
         
     | 
| 
       121 
121 
     | 
    
         
             
                      loop do
         
     | 
| 
       122 
     | 
    
         
            -
                        expect(response_socket).to receive(:read).with( 
     | 
| 
       123 
     | 
    
         
            -
                         
     | 
| 
       124 
     | 
    
         
            -
                        break if  
     | 
| 
      
 122 
     | 
    
         
            +
                        expect(response_socket).to receive(:read).with(stream_protocol_length).and_return('A' * returned_length).once
         
     | 
| 
      
 123 
     | 
    
         
            +
                        stream_protocol_length -= returned_length
         
     | 
| 
      
 124 
     | 
    
         
            +
                        break if stream_protocol_length <= 0
         
     | 
| 
       125 
125 
     | 
    
         
             
                      end
         
     | 
| 
       126 
126 
     | 
    
         
             
                      smb_socket.recv_packet
         
     | 
| 
       127 
127 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -134,7 +134,7 @@ RSpec.describe RubySMB::Dispatcher::Socket do 
     | 
|
| 
       134 
134 
     | 
    
         | 
| 
       135 
135 
     | 
    
         
             
                    context 'when the SMB packet is empty' do
         
     | 
| 
       136 
136 
     | 
    
         
             
                      it 'returns the nbss header only' do
         
     | 
| 
       137 
     | 
    
         
            -
                        session_header. 
     | 
| 
      
 137 
     | 
    
         
            +
                        session_header.stream_protocol_length = 0
         
     | 
| 
       138 
138 
     | 
    
         
             
                        allow(RubySMB::Nbss::SessionHeader).to receive(:read).and_return(session_header)
         
     | 
| 
       139 
139 
     | 
    
         
             
                        expect(smb_socket.recv_packet(full_response: true)).to eq(session_header.to_binary_s)
         
     | 
| 
       140 
140 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -148,7 +148,7 @@ RSpec.describe RubySMB::Dispatcher::Socket do 
     | 
|
| 
       148 
148 
     | 
    
         | 
| 
       149 
149 
     | 
    
         
             
                    context 'when the SMB packet is empty' do
         
     | 
| 
       150 
150 
     | 
    
         
             
                      it 'returns an empty string' do
         
     | 
| 
       151 
     | 
    
         
            -
                        session_header. 
     | 
| 
      
 151 
     | 
    
         
            +
                        session_header.stream_protocol_length = 0
         
     | 
| 
       152 
152 
     | 
    
         
             
                        allow(RubySMB::Nbss::SessionHeader).to receive(:read).and_return(session_header)
         
     | 
| 
       153 
153 
     | 
    
         
             
                        expect(smb_socket.recv_packet(full_response: false)).to eq('')
         
     | 
| 
       154 
154 
     | 
    
         
             
                      end
         
     |