ruby_smb 0.0.18 → 0.0.19
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +247 -7
- data/examples/anonymous_auth.rb +6 -3
- data/examples/append_file.rb +40 -0
- data/examples/authenticate.rb +12 -7
- data/examples/delete_file.rb +40 -0
- data/examples/list_directory.rb +45 -0
- data/examples/negotiate.rb +0 -1
- data/examples/negotiate_with_netbios_service.rb +36 -0
- data/examples/net_share_enum_all.rb +30 -0
- data/examples/read_file.rb +39 -0
- data/examples/rename_file.rb +41 -0
- data/examples/tree_connect.rb +2 -4
- data/examples/write_file.rb +40 -0
- data/lib/ruby_smb.rb +5 -0
- data/lib/ruby_smb/client.rb +196 -43
- data/lib/ruby_smb/client/authentication.rb +89 -48
- data/lib/ruby_smb/client/echo.rb +1 -4
- data/lib/ruby_smb/client/negotiation.rb +46 -45
- data/lib/ruby_smb/client/signing.rb +9 -16
- data/lib/ruby_smb/client/tree_connect.rb +8 -13
- data/lib/ruby_smb/client/utils.rb +79 -0
- data/lib/ruby_smb/dcerpc.rb +30 -0
- data/lib/ruby_smb/dcerpc/bind.rb +60 -0
- data/lib/ruby_smb/dcerpc/handle.rb +60 -0
- data/lib/ruby_smb/dcerpc/ndr.rb +41 -0
- data/lib/ruby_smb/dcerpc/request.rb +43 -0
- data/lib/ruby_smb/dcerpc/response.rb +46 -0
- data/lib/ruby_smb/dcerpc/srvsvc.rb +17 -0
- data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +93 -0
- data/lib/ruby_smb/dcerpc/uuid.rb +28 -0
- data/lib/ruby_smb/dispatcher.rb +7 -3
- data/lib/ruby_smb/dispatcher/base.rb +23 -14
- data/lib/ruby_smb/dispatcher/socket.rb +71 -51
- data/lib/ruby_smb/dispositions.rb +32 -0
- data/lib/ruby_smb/error.rb +24 -18
- data/lib/ruby_smb/field.rb +5 -2
- data/lib/ruby_smb/field/extended_attribute_flag.rb +1 -1
- data/lib/ruby_smb/field/file_time.rb +3 -1
- data/lib/ruby_smb/field/security_descriptor.rb +6 -6
- data/lib/ruby_smb/field/smb2_fileid.rb +11 -0
- data/lib/ruby_smb/field/smb_fea.rb +3 -3
- data/lib/ruby_smb/field/smb_fea_list.rb +3 -3
- data/lib/ruby_smb/field/smb_gea.rb +12 -0
- data/lib/ruby_smb/field/smb_gea_list.rb +13 -0
- data/lib/ruby_smb/field/string16.rb +14 -0
- data/lib/ruby_smb/field/stringz16.rb +3 -7
- data/lib/ruby_smb/field/utime.rb +11 -10
- data/lib/ruby_smb/fscc.rb +12 -0
- data/lib/ruby_smb/fscc/control_codes.rb +26 -0
- data/lib/ruby_smb/{field → fscc}/ea_info_array.rb +12 -14
- data/lib/ruby_smb/fscc/file_attributes.rb +29 -0
- data/lib/ruby_smb/{field → fscc}/file_full_ea_info.rb +5 -5
- data/lib/ruby_smb/fscc/file_information.rb +60 -0
- data/lib/ruby_smb/fscc/file_information/file_both_directory_information.rb +29 -0
- data/lib/ruby_smb/fscc/file_information/file_directory_information.rb +25 -0
- data/lib/ruby_smb/fscc/file_information/file_disposition_information.rb +15 -0
- data/lib/ruby_smb/fscc/file_information/file_full_directory_information.rb +26 -0
- data/lib/ruby_smb/fscc/file_information/file_id_both_directory_information.rb +31 -0
- data/lib/ruby_smb/fscc/file_information/file_id_full_directory_information.rb +28 -0
- data/lib/ruby_smb/fscc/file_information/file_names_information.rb +18 -0
- data/lib/ruby_smb/fscc/file_information/file_rename_information.rb +44 -0
- data/lib/ruby_smb/generic_packet.rb +40 -18
- data/lib/ruby_smb/gss.rb +49 -56
- data/lib/ruby_smb/impersonation_levels.rb +7 -2
- data/lib/ruby_smb/nbss.rb +16 -0
- data/lib/ruby_smb/nbss/negative_session_response.rb +30 -0
- data/lib/ruby_smb/nbss/session_header.rb +13 -0
- data/lib/ruby_smb/nbss/session_request.rb +13 -0
- data/lib/ruby_smb/smb1.rb +20 -17
- data/lib/ruby_smb/smb1/bit_field.rb +3 -0
- data/lib/ruby_smb/smb1/bit_field/create_options.rb +5 -5
- data/lib/ruby_smb/smb1/bit_field/file_status_flags.rb +18 -0
- data/lib/ruby_smb/smb1/bit_field/open2_access_mode.rb +11 -11
- data/lib/ruby_smb/smb1/bit_field/open2_open_mode.rb +1 -1
- data/lib/ruby_smb/smb1/bit_field/optional_support.rb +0 -1
- data/lib/ruby_smb/smb1/bit_field/security_flags.rb +15 -0
- data/lib/ruby_smb/smb1/bit_field/share_access.rb +2 -3
- data/lib/ruby_smb/smb1/bit_field/smb_ext_file_attributes.rb +21 -24
- data/lib/ruby_smb/smb1/bit_field/smb_file_attributes.rb +1 -1
- data/lib/ruby_smb/smb1/commands.rb +5 -0
- data/lib/ruby_smb/smb1/create_actions.rb +3 -5
- data/lib/ruby_smb/smb1/file.rb +289 -0
- data/lib/ruby_smb/smb1/oplock_levels.rb +2 -4
- data/lib/ruby_smb/smb1/packet.rb +10 -0
- data/lib/ruby_smb/smb1/packet/close_request.rb +31 -0
- data/lib/ruby_smb/smb1/packet/close_response.rb +28 -0
- data/lib/ruby_smb/smb1/packet/echo_request.rb +5 -7
- data/lib/ruby_smb/smb1/packet/echo_response.rb +5 -7
- data/lib/ruby_smb/smb1/packet/empty_packet.rb +1 -2
- data/lib/ruby_smb/smb1/packet/logoff_request.rb +1 -4
- data/lib/ruby_smb/smb1/packet/logoff_response.rb +1 -4
- data/lib/ruby_smb/smb1/packet/negotiate_response.rb +22 -0
- data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +22 -0
- data/lib/ruby_smb/smb1/packet/nt_create_andx_request.rb +62 -0
- data/lib/ruby_smb/smb1/packet/nt_create_andx_response.rb +66 -0
- data/lib/ruby_smb/smb1/packet/nt_trans.rb +1 -2
- data/lib/ruby_smb/smb1/packet/nt_trans/create_request.rb +19 -13
- data/lib/ruby_smb/smb1/packet/nt_trans/create_response.rb +8 -10
- data/lib/ruby_smb/smb1/packet/nt_trans/request.rb +11 -11
- data/lib/ruby_smb/smb1/packet/nt_trans/response.rb +10 -10
- data/lib/ruby_smb/smb1/packet/nt_trans/subcommands.rb +8 -1
- data/lib/ruby_smb/smb1/packet/read_andx_request.rb +84 -0
- data/lib/ruby_smb/smb1/packet/read_andx_response.rb +47 -0
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_request.rb +2 -6
- data/lib/ruby_smb/smb1/packet/session_setup_legacy_response.rb +1 -4
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -6
- data/lib/ruby_smb/smb1/packet/session_setup_response.rb +2 -4
- data/lib/ruby_smb/smb1/packet/trans2.rb +8 -2
- data/lib/ruby_smb/smb1/packet/trans2/data_block.rb +6 -7
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_request.rb +77 -0
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +87 -0
- data/lib/ruby_smb/smb1/packet/trans2/find_information_level.rb +32 -0
- data/lib/ruby_smb/smb1/packet/trans2/find_information_level/find_file_full_directory_info.rb +45 -0
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_request.rb +77 -0
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +86 -0
- data/lib/ruby_smb/smb1/packet/trans2/open2_request.rb +10 -10
- data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +10 -12
- data/lib/ruby_smb/smb1/packet/trans2/request.rb +15 -17
- data/lib/ruby_smb/smb1/packet/trans2/request_secondary.rb +8 -10
- data/lib/ruby_smb/smb1/packet/trans2/response.rb +11 -13
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_request.rb +66 -0
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +57 -0
- data/lib/ruby_smb/smb1/packet/trans2/subcommands.rb +5 -2
- data/lib/ruby_smb/smb1/packet/tree_connect_request.rb +4 -6
- data/lib/ruby_smb/smb1/packet/tree_connect_response.rb +5 -7
- data/lib/ruby_smb/smb1/packet/tree_disconnect_request.rb +2 -4
- data/lib/ruby_smb/smb1/packet/tree_disconnect_response.rb +2 -4
- data/lib/ruby_smb/smb1/packet/write_andx_request.rb +68 -0
- data/lib/ruby_smb/smb1/packet/write_andx_response.rb +35 -0
- data/lib/ruby_smb/smb1/resource_type.rb +18 -0
- data/lib/ruby_smb/smb1/tree.rb +188 -5
- data/lib/ruby_smb/smb2.rb +16 -11
- data/lib/ruby_smb/smb2/bit_field.rb +1 -0
- data/lib/ruby_smb/smb2/bit_field/file_access_mask.rb +1 -1
- data/lib/ruby_smb/smb2/bit_field/session_flags.rb +1 -2
- data/lib/ruby_smb/smb2/bit_field/share_flags.rb +4 -6
- data/lib/ruby_smb/smb2/create_context.rb +29 -0
- data/lib/ruby_smb/smb2/file.rb +251 -0
- data/lib/ruby_smb/smb2/info_type.rb +21 -0
- data/lib/ruby_smb/smb2/packet.rb +16 -0
- data/lib/ruby_smb/smb2/packet/close_request.rb +22 -0
- data/lib/ruby_smb/smb2/packet/close_response.rb +29 -0
- data/lib/ruby_smb/smb2/packet/create_request.rb +54 -0
- data/lib/ruby_smb/smb2/packet/create_response.rb +35 -0
- data/lib/ruby_smb/smb2/packet/echo_request.rb +1 -3
- data/lib/ruby_smb/smb2/packet/echo_response.rb +1 -3
- data/lib/ruby_smb/smb2/packet/error_packet.rb +1 -3
- data/lib/ruby_smb/smb2/packet/ioctl_request.rb +54 -0
- data/lib/ruby_smb/smb2/packet/ioctl_response.rb +39 -0
- data/lib/ruby_smb/smb2/packet/logoff_request.rb +1 -4
- data/lib/ruby_smb/smb2/packet/logoff_response.rb +1 -4
- data/lib/ruby_smb/smb2/packet/negotiate_request.rb +1 -1
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +1 -1
- data/lib/ruby_smb/smb2/packet/query_directory_request.rb +35 -0
- data/lib/ruby_smb/smb2/packet/query_directory_response.rb +45 -0
- data/lib/ruby_smb/smb2/packet/read_request.rb +30 -0
- data/lib/ruby_smb/smb2/packet/read_response.rb +26 -0
- data/lib/ruby_smb/smb2/packet/session_setup_request.rb +2 -5
- data/lib/ruby_smb/smb2/packet/session_setup_response.rb +4 -7
- data/lib/ruby_smb/smb2/packet/set_info_request.rb +58 -0
- data/lib/ruby_smb/smb2/packet/set_info_response.rb +20 -0
- data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +3 -4
- data/lib/ruby_smb/smb2/packet/tree_connect_response.rb +5 -9
- data/lib/ruby_smb/smb2/packet/tree_disconnect_request.rb +1 -4
- data/lib/ruby_smb/smb2/packet/tree_disconnect_response.rb +1 -4
- data/lib/ruby_smb/smb2/packet/write_request.rb +29 -0
- data/lib/ruby_smb/smb2/packet/write_response.rb +26 -0
- data/lib/ruby_smb/smb2/tree.rb +163 -7
- data/lib/ruby_smb/version.rb +1 -1
- data/spec/lib/ruby_smb/client_spec.rb +459 -120
- data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +14 -0
- data/spec/lib/ruby_smb/dcerpc/handle_spec.rb +31 -0
- data/spec/lib/ruby_smb/dcerpc/request_spec.rb +21 -0
- data/spec/lib/ruby_smb/dcerpc/response_spec.rb +15 -0
- data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +13 -0
- data/spec/lib/ruby_smb/dcerpc/uuid_spec.rb +12 -0
- data/spec/lib/ruby_smb/dispatcher/base_spec.rb +26 -0
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +118 -18
- data/spec/lib/ruby_smb/field/extended_attribute_flag_spec.rb +0 -3
- data/spec/lib/ruby_smb/field/file_time_spec.rb +4 -2
- data/spec/lib/ruby_smb/field/security_descriptor.rb +0 -1
- data/spec/lib/ruby_smb/field/smb2_fileid_spec.rb +10 -0
- data/spec/lib/ruby_smb/field/smb_fea_list_spec.rb +3 -5
- data/spec/lib/ruby_smb/field/smb_gea_list_spec.rb +37 -0
- data/spec/lib/ruby_smb/field/smb_gea_spec.rb +22 -0
- data/spec/lib/ruby_smb/field/stringz16_spec.rb +7 -9
- data/spec/lib/ruby_smb/field/utime_spec.rb +4 -2
- data/spec/lib/ruby_smb/{field → fscc}/ea_info_array_spec.rb +7 -9
- data/spec/lib/ruby_smb/{field → fscc}/file_full_ea_info_spec.rb +2 -3
- data/spec/lib/ruby_smb/fscc/file_information/file_both_directory_information_spec.rb +71 -0
- data/spec/lib/ruby_smb/fscc/file_information/file_directory_information_spec.rb +68 -0
- data/spec/lib/ruby_smb/fscc/file_information/file_disposition_information_spec.rb +26 -0
- data/spec/lib/ruby_smb/fscc/file_information/file_full_directory_information_spec.rb +69 -0
- data/spec/lib/ruby_smb/fscc/file_information/file_id_both_directory_information_spec.rb +72 -0
- data/spec/lib/ruby_smb/fscc/file_information/file_id_full_directory_information_spec.rb +70 -0
- data/spec/lib/ruby_smb/fscc/file_information/file_names_information_spec.rb +41 -0
- data/spec/lib/ruby_smb/fscc/file_information/file_rename_information_spec.rb +133 -0
- data/spec/lib/ruby_smb/fscc/fscc_file_attributes_spec.rb +143 -0
- data/spec/lib/ruby_smb/generic_packet_spec.rb +46 -21
- data/spec/lib/ruby_smb/nbss/negative_session_response_spec.rb +29 -0
- data/spec/lib/ruby_smb/nbss/session_header_spec.rb +30 -0
- data/spec/lib/ruby_smb/nbss/session_request_spec.rb +30 -0
- data/spec/lib/ruby_smb/smb1/bit_field/create_options_spec.rb +9 -1
- data/spec/lib/ruby_smb/smb1/bit_field/directory_access_mask_spec.rb +0 -2
- data/spec/lib/ruby_smb/smb1/bit_field/file_access_mask_spec.rb +0 -2
- data/spec/lib/ruby_smb/smb1/bit_field/file_status_flags_spec.rb +35 -0
- data/spec/lib/ruby_smb/smb1/bit_field/open2_access_mode_spec.rb +1 -3
- data/spec/lib/ruby_smb/smb1/bit_field/open2_flags_spec.rb +0 -2
- data/spec/lib/ruby_smb/smb1/bit_field/open2_open_mode_spec.rb +0 -1
- data/spec/lib/ruby_smb/smb1/bit_field/optional_support_spec.rb +0 -1
- data/spec/lib/ruby_smb/smb1/bit_field/security_flags_spec.rb +26 -0
- data/spec/lib/ruby_smb/smb1/bit_field/share_access_spec.rb +0 -3
- data/spec/lib/ruby_smb/smb1/bit_field/smb_ext_file_attributes_spec.rb +20 -39
- data/spec/lib/ruby_smb/smb1/bit_field/smb_file_attributes_spec.rb +0 -6
- data/spec/lib/ruby_smb/smb1/bit_field/smb_nmpipe_status_spec.rb +0 -2
- data/spec/lib/ruby_smb/smb1/bit_field/trans2_flags_spec.rb +0 -2
- data/spec/lib/ruby_smb/smb1/bit_field/tree_connect_flags_spec.rb +0 -2
- data/spec/lib/ruby_smb/smb1/file_spec.rb +469 -0
- data/spec/lib/ruby_smb/smb1/packet/close_request_spec.rb +54 -0
- data/spec/lib/ruby_smb/smb1/packet/close_response_spec.rb +45 -0
- data/spec/lib/ruby_smb/smb1/packet/echo_request_spec.rb +1 -4
- data/spec/lib/ruby_smb/smb1/packet/echo_response_spec.rb +1 -4
- data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +1 -3
- data/spec/lib/ruby_smb/smb1/packet/logoff_request_spec.rb +1 -4
- data/spec/lib/ruby_smb/smb1/packet/logoff_response_spec.rb +1 -4
- data/spec/lib/ruby_smb/smb1/packet/negotiate_request_spec.rb +1 -1
- data/spec/lib/ruby_smb/smb1/packet/negotiate_response_extended_spec.rb +37 -0
- data/spec/lib/ruby_smb/smb1/packet/negotiate_response_spec.rb +37 -0
- data/spec/lib/ruby_smb/smb1/packet/nt_create_andx_request_spec.rb +151 -0
- data/spec/lib/ruby_smb/smb1/packet/nt_create_andx_response_spec.rb +157 -0
- data/spec/lib/ruby_smb/smb1/packet/nt_trans/create_request_spec.rb +13 -6
- data/spec/lib/ruby_smb/smb1/packet/nt_trans/create_response_spec.rb +1 -7
- data/spec/lib/ruby_smb/smb1/packet/nt_trans/request_spec.rb +1 -6
- data/spec/lib/ruby_smb/smb1/packet/nt_trans/response_spec.rb +1 -5
- data/spec/lib/ruby_smb/smb1/packet/read_andx_request_spec.rb +149 -0
- data/spec/lib/ruby_smb/smb1/packet/read_andx_response_spec.rb +93 -0
- data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_request_spec.rb +1 -5
- data/spec/lib/ruby_smb/smb1/packet/session_setup_legacy_response_spec.rb +1 -5
- data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +3 -8
- data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +2 -4
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_request_spec.rb +180 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +104 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_information_level/find_file_full_directory_info_spec.rb +128 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_request_spec.rb +174 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +102 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/open2_request_spec.rb +1 -6
- data/spec/lib/ruby_smb/smb1/packet/trans2/open2_response_spec.rb +2 -7
- data/spec/lib/ruby_smb/smb1/packet/trans2/request_secondary_spec.rb +1 -5
- data/spec/lib/ruby_smb/smb1/packet/trans2/request_spec.rb +1 -5
- data/spec/lib/ruby_smb/smb1/packet/trans2/response_spec.rb +1 -4
- data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_request_spec.rb +98 -0
- data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +56 -0
- data/spec/lib/ruby_smb/smb1/packet/tree_connect_request_spec.rb +1 -5
- data/spec/lib/ruby_smb/smb1/packet/tree_connect_response_spec.rb +1 -6
- data/spec/lib/ruby_smb/smb1/packet/tree_disconnect_request_spec.rb +1 -4
- data/spec/lib/ruby_smb/smb1/packet/tree_disconnect_response_spec.rb +1 -4
- data/spec/lib/ruby_smb/smb1/packet/write_andx_request_spec.rb +148 -0
- data/spec/lib/ruby_smb/smb1/packet/write_andx_response_spec.rb +54 -0
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +409 -7
- data/spec/lib/ruby_smb/smb2/bit_field/directory_access_mask_spec.rb +0 -2
- data/spec/lib/ruby_smb/smb2/bit_field/file_access_mask_spec.rb +0 -2
- data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +1 -1
- data/spec/lib/ruby_smb/smb2/bit_field/share_capabilities_spec.rb +0 -1
- data/spec/lib/ruby_smb/smb2/bit_field/share_flags_spec.rb +0 -2
- data/spec/lib/ruby_smb/smb2/create_context_spec.rb +42 -0
- data/spec/lib/ruby_smb/smb2/file_spec.rb +233 -0
- data/spec/lib/ruby_smb/smb2/packet/close_request_spec.rb +40 -0
- data/spec/lib/ruby_smb/smb2/packet/close_response_spec.rb +40 -0
- data/spec/lib/ruby_smb/smb2/packet/create_request_spec.rb +101 -0
- data/spec/lib/ruby_smb/smb2/packet/create_response_spec.rb +64 -0
- data/spec/lib/ruby_smb/smb2/packet/echo_request_spec.rb +1 -3
- data/spec/lib/ruby_smb/smb2/packet/echo_response_spec.rb +1 -3
- data/spec/lib/ruby_smb/smb2/packet/ioctl_request_spec.rb +48 -0
- data/spec/lib/ruby_smb/smb2/packet/logoff_request_spec.rb +1 -3
- data/spec/lib/ruby_smb/smb2/packet/logoff_response_spec.rb +1 -3
- data/spec/lib/ruby_smb/smb2/packet/query_directory_request_spec.rb +80 -0
- data/spec/lib/ruby_smb/smb2/packet/query_directory_response_spec.rb +64 -0
- data/spec/lib/ruby_smb/smb2/packet/read_request_spec.rb +43 -0
- data/spec/lib/ruby_smb/smb2/packet/read_response_spec.rb +50 -0
- data/spec/lib/ruby_smb/smb2/packet/session_setup_request_spec.rb +3 -4
- data/spec/lib/ruby_smb/smb2/packet/session_setup_response_spec.rb +2 -3
- data/spec/lib/ruby_smb/smb2/packet/set_info_request_spec.rb +205 -0
- data/spec/lib/ruby_smb/smb2/packet/set_info_response_spec.rb +32 -0
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_request_spec.rb +3 -5
- data/spec/lib/ruby_smb/smb2/packet/tree_connect_response_spec.rb +1 -2
- data/spec/lib/ruby_smb/smb2/packet/tree_disconnect_request_spec.rb +1 -3
- data/spec/lib/ruby_smb/smb2/packet/tree_disconnect_response_spec.rb +1 -3
- data/spec/lib/ruby_smb/smb2/packet/write_request_spec.rb +51 -0
- data/spec/lib/ruby_smb/smb2/packet/write_response_spec.rb +38 -0
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +191 -5
- data/spec/spec_helper.rb +1 -1
- metadata +195 -12
- metadata.gz.sig +0 -0
- data/lib/ruby_smb/smb1/dispositions.rb +0 -36
- data/spec/lib/ruby_smb/dispatcher/dispatcher_base_spec.rb +0 -22
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe RubySMB::Fscc::FileInformation::FileIdFullDirectoryInformation do
|
4
|
+
it 'references the correct class level' do
|
5
|
+
expect(described_class).to be_const_defined(:CLASS_LEVEL)
|
6
|
+
expect(described_class::CLASS_LEVEL).to be RubySMB::Fscc::FileInformation::FILE_ID_FULL_DIRECTORY_INFORMATION
|
7
|
+
end
|
8
|
+
|
9
|
+
subject(:struct) { described_class.new }
|
10
|
+
|
11
|
+
it { should respond_to :next_offset }
|
12
|
+
it { should respond_to :file_index }
|
13
|
+
it { should respond_to :create_time }
|
14
|
+
it { should respond_to :last_access }
|
15
|
+
it { should respond_to :last_write }
|
16
|
+
it { should respond_to :last_change }
|
17
|
+
it { should respond_to :end_of_file }
|
18
|
+
it { should respond_to :allocation_size }
|
19
|
+
it { should respond_to :file_attributes }
|
20
|
+
it { should respond_to :file_name_length }
|
21
|
+
it { should respond_to :ea_size }
|
22
|
+
it { should respond_to :file_id }
|
23
|
+
it { should respond_to :file_name }
|
24
|
+
|
25
|
+
it 'is little endian' do
|
26
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'tracks the creation time in a Filetime field' do
|
30
|
+
expect(struct.create_time).to be_a RubySMB::Field::FileTime
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'tracks the last access time in a Filetime field' do
|
34
|
+
expect(struct.last_access).to be_a RubySMB::Field::FileTime
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'tracks the last write time in a Filetime field' do
|
38
|
+
expect(struct.last_write).to be_a RubySMB::Field::FileTime
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'tracks the last modified time in a Filetime field' do
|
42
|
+
expect(struct.last_change).to be_a RubySMB::Field::FileTime
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'contains the file attributes of the file' do
|
46
|
+
expect(struct.file_attributes).to be_a RubySMB::Fscc::FileAttributes
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'tracks the length of the file_name field' do
|
50
|
+
struct.file_name = 'Hello.txt'
|
51
|
+
expect(struct.file_name_length).to eq struct.file_name.do_num_bytes
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'automatically encodes the file name in UTF-16LE' do
|
55
|
+
name = 'Hello_world.txt'
|
56
|
+
struct.file_name = name
|
57
|
+
expect(struct.file_name.force_encoding('utf-16le')).to eq name.encode('utf-16le')
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'reading in from a blob' do
|
61
|
+
it 'uses the file_name_length to know when to stop reading' do
|
62
|
+
name = 'Hello_world.txt'
|
63
|
+
struct.file_name = name
|
64
|
+
blob = struct.to_binary_s
|
65
|
+
blob << 'AAAA'
|
66
|
+
new_from_blob = described_class.read(blob)
|
67
|
+
expect(new_from_blob.file_name.force_encoding('utf-16le')).to eq name.encode('utf-16le')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe RubySMB::Fscc::FileInformation::FileNamesInformation do
|
4
|
+
it 'references the correct class level' do
|
5
|
+
expect(described_class).to be_const_defined(:CLASS_LEVEL)
|
6
|
+
expect(described_class::CLASS_LEVEL).to be RubySMB::Fscc::FileInformation::FILE_NAMES_INFORMATION
|
7
|
+
end
|
8
|
+
|
9
|
+
subject(:struct) { described_class.new }
|
10
|
+
|
11
|
+
it { should respond_to :next_offset }
|
12
|
+
it { should respond_to :file_index }
|
13
|
+
it { should respond_to :file_name_length }
|
14
|
+
it { should respond_to :file_name }
|
15
|
+
|
16
|
+
it 'is little endian' do
|
17
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'tracks the length of the file_name field' do
|
21
|
+
struct.file_name = 'Hello.txt'
|
22
|
+
expect(struct.file_name_length).to eq struct.file_name.do_num_bytes
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'automatically encodes the file name in UTF-16LE' do
|
26
|
+
name = 'Hello_world.txt'
|
27
|
+
struct.file_name = name
|
28
|
+
expect(struct.file_name.force_encoding('utf-16le')).to eq name.encode('utf-16le')
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'reading in from a blob' do
|
32
|
+
it 'uses the file_name_length to know when to stop reading' do
|
33
|
+
name = 'Hello_world.txt'
|
34
|
+
struct.file_name = name
|
35
|
+
blob = struct.to_binary_s
|
36
|
+
blob << 'AAAA'
|
37
|
+
new_from_blob = described_class.read(blob)
|
38
|
+
expect(new_from_blob.file_name.force_encoding('utf-16le')).to eq name.encode('utf-16le')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
RSpec.describe RubySMB::Fscc::FileInformation::FileRenameInformation do
|
4
|
+
it 'references the correct class level' do
|
5
|
+
expect(described_class).to be_const_defined(:CLASS_LEVEL)
|
6
|
+
expect(described_class::CLASS_LEVEL).to be RubySMB::Fscc::FileInformation::FILE_ID_FULL_DIRECTORY_INFORMATION
|
7
|
+
end
|
8
|
+
|
9
|
+
subject(:struct) { described_class.new }
|
10
|
+
|
11
|
+
it { should respond_to :replace_if_exists }
|
12
|
+
it { should respond_to :reserved }
|
13
|
+
it { should respond_to :root_directory }
|
14
|
+
it { should respond_to :file_name_length }
|
15
|
+
it { should respond_to :file_name }
|
16
|
+
|
17
|
+
it 'is little endian' do
|
18
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'reading in from a blob' do
|
22
|
+
it 'uses the file_name_length to know when to stop reading' do
|
23
|
+
name = 'Hello_world.txt'
|
24
|
+
struct.file_name = name
|
25
|
+
blob = struct.to_binary_s
|
26
|
+
blob << 'AAAA'
|
27
|
+
new_from_blob = described_class.read(blob)
|
28
|
+
expect(new_from_blob.file_name).to eq name
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#replace_if_exists' do
|
33
|
+
it 'is a 8-bit field' do
|
34
|
+
expect(struct.replace_if_exists).to be_a BinData::Uint8
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#reserved' do
|
39
|
+
context 'with SMB1' do
|
40
|
+
it 'is a 3-bytes field' do
|
41
|
+
allow(struct).to receive(:get_smb_version).and_return 1
|
42
|
+
expect(struct.reserved.do_num_bytes).to eq 3
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'with SMB2' do
|
47
|
+
it 'is a 7-bytes field' do
|
48
|
+
allow(struct).to receive(:get_smb_version).and_return 2
|
49
|
+
expect(struct.reserved.do_num_bytes).to eq 7
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#root_directory' do
|
55
|
+
context 'with SMB1' do
|
56
|
+
before :example do
|
57
|
+
allow(struct).to receive(:get_smb_version).and_return 1
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'is a 4-bytes field' do
|
61
|
+
expect(struct.root_directory.do_num_bytes).to eq 4
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'should have a default value of 0' do
|
65
|
+
expect(struct.root_directory).to eq 0
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context 'with SMB2' do
|
70
|
+
before :example do
|
71
|
+
allow(struct).to receive(:get_smb_version).and_return 2
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'is a 8-bytes field' do
|
75
|
+
expect(struct.root_directory.do_num_bytes).to eq 8
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'should have a default value of 0' do
|
79
|
+
expect(struct.root_directory).to eq 0
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
describe '#file_name_length' do
|
86
|
+
it 'is a 32-bit field' do
|
87
|
+
expect(struct.file_name_length).to be_a BinData::Uint32le
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'should have a default value of 0' do
|
91
|
+
expect(struct.file_name_length).to eq 0
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'tracks the length of the file_name field' do
|
95
|
+
struct.file_name = 'Hello.txt'
|
96
|
+
expect(struct.file_name_length).to eq struct.file_name.do_num_bytes
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#file_name' do
|
101
|
+
it 'is a string field' do
|
102
|
+
expect(struct.file_name).to be_a BinData::String
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
describe '#get_smb_version' do
|
107
|
+
it 'is a recurssive method' do
|
108
|
+
parent = double('parent object')
|
109
|
+
allow(struct).to receive(:parent).and_return(parent)
|
110
|
+
expect(struct).to receive(:respond_to?).and_return(false).twice.ordered
|
111
|
+
expect(parent).to receive(:respond_to?).and_return(true).once.ordered
|
112
|
+
struct.get_smb_version
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'returns version 1 if smb_header structure is found in parents' do
|
116
|
+
allow(struct).to receive(:respond_to?).with(:smb_header).and_return(true)
|
117
|
+
expect(struct.get_smb_version).to eq 1
|
118
|
+
end
|
119
|
+
|
120
|
+
it 'returns version 2 if smb2_header structure is found in parents' do
|
121
|
+
allow(struct).to receive(:respond_to?).with(:smb_header).and_return(false)
|
122
|
+
allow(struct).to receive(:respond_to?).with(:smb2_header).and_return(true)
|
123
|
+
expect(struct.get_smb_version).to eq 2
|
124
|
+
end
|
125
|
+
|
126
|
+
it 'returns version 1 if no header structure is found in parents' do
|
127
|
+
allow(struct).to receive(:parent)
|
128
|
+
allow(struct).to receive(:respond_to?).with(:smb_header).and_return(false)
|
129
|
+
allow(struct).to receive(:respond_to?).with(:smb2_header).and_return(false)
|
130
|
+
expect(struct.get_smb_version).to eq 1
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
RSpec.describe RubySMB::Fscc::FileAttributes do
|
2
|
+
subject(:attrs) { described_class.new }
|
3
|
+
|
4
|
+
it { is_expected.to respond_to :normal }
|
5
|
+
it { is_expected.to respond_to :device }
|
6
|
+
it { is_expected.to respond_to :archive }
|
7
|
+
it { is_expected.to respond_to :directory }
|
8
|
+
it { is_expected.to respond_to :volume }
|
9
|
+
it { is_expected.to respond_to :system }
|
10
|
+
it { is_expected.to respond_to :hidden }
|
11
|
+
it { is_expected.to respond_to :read_only }
|
12
|
+
it { is_expected.to respond_to :encrypted }
|
13
|
+
it { is_expected.to respond_to :content_indexed }
|
14
|
+
it { is_expected.to respond_to :offline }
|
15
|
+
it { is_expected.to respond_to :compressed }
|
16
|
+
it { is_expected.to respond_to :reparse_point }
|
17
|
+
it { is_expected.to respond_to :sparse }
|
18
|
+
it { is_expected.to respond_to :temp }
|
19
|
+
|
20
|
+
it 'is little endian' do
|
21
|
+
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :little
|
22
|
+
end
|
23
|
+
|
24
|
+
describe 'read_only' do
|
25
|
+
it 'should be a 1-bit field per the SMB spec' do
|
26
|
+
expect(attrs.read_only).to be_a BinData::Bit1
|
27
|
+
end
|
28
|
+
|
29
|
+
it_behaves_like 'bit field with one flag set', :read_only, 'V', 0x00000001
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'hidden' do
|
33
|
+
it 'should be a 1-bit field per the SMB spec' do
|
34
|
+
expect(attrs.hidden).to be_a BinData::Bit1
|
35
|
+
end
|
36
|
+
|
37
|
+
it_behaves_like 'bit field with one flag set', :hidden, 'V', 0x00000002
|
38
|
+
end
|
39
|
+
|
40
|
+
describe 'system' do
|
41
|
+
it 'should be a 1-bit field per the SMB spec' do
|
42
|
+
expect(attrs.system).to be_a BinData::Bit1
|
43
|
+
end
|
44
|
+
|
45
|
+
it_behaves_like 'bit field with one flag set', :system, 'V', 0x00000004
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'volume' do
|
49
|
+
it 'should be a 1-bit field per the SMB spec' do
|
50
|
+
expect(attrs.volume).to be_a BinData::Bit1
|
51
|
+
end
|
52
|
+
|
53
|
+
it_behaves_like 'bit field with one flag set', :volume, 'V', 0x00000008
|
54
|
+
end
|
55
|
+
|
56
|
+
describe 'directory' do
|
57
|
+
it 'should be a 1-bit field per the SMB spec' do
|
58
|
+
expect(attrs.directory).to be_a BinData::Bit1
|
59
|
+
end
|
60
|
+
|
61
|
+
it_behaves_like 'bit field with one flag set', :directory, 'V', 0x00000010
|
62
|
+
end
|
63
|
+
|
64
|
+
describe 'archive' do
|
65
|
+
it 'should be a 1-bit field per the SMB spec' do
|
66
|
+
expect(attrs.archive).to be_a BinData::Bit1
|
67
|
+
end
|
68
|
+
|
69
|
+
it_behaves_like 'bit field with one flag set', :archive, 'V', 0x00000020
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'device' do
|
73
|
+
it 'should be a 1-bit field per the SMB spec' do
|
74
|
+
expect(attrs.device).to be_a BinData::Bit1
|
75
|
+
end
|
76
|
+
|
77
|
+
it_behaves_like 'bit field with one flag set', :device, 'V', 0x00000040
|
78
|
+
end
|
79
|
+
|
80
|
+
describe 'normal' do
|
81
|
+
it 'should be a 1-bit field per the SMB spec' do
|
82
|
+
expect(attrs.normal).to be_a BinData::Bit1
|
83
|
+
end
|
84
|
+
|
85
|
+
it_behaves_like 'bit field with one flag set', :normal, 'V', 0x00000080
|
86
|
+
end
|
87
|
+
|
88
|
+
describe 'temp' do
|
89
|
+
it 'should be a 1-bit field per the SMB spec' do
|
90
|
+
expect(attrs.temp).to be_a BinData::Bit1
|
91
|
+
end
|
92
|
+
|
93
|
+
it_behaves_like 'bit field with one flag set', :temp, 'V', 0x00000100
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'sparse' do
|
97
|
+
it 'should be a 1-bit field per the SMB spec' do
|
98
|
+
expect(attrs.sparse).to be_a BinData::Bit1
|
99
|
+
end
|
100
|
+
|
101
|
+
it_behaves_like 'bit field with one flag set', :sparse, 'V', 0x00000200
|
102
|
+
end
|
103
|
+
|
104
|
+
describe 'reparse_point' do
|
105
|
+
it 'should be a 1-bit field per the SMB spec' do
|
106
|
+
expect(attrs.reparse_point).to be_a BinData::Bit1
|
107
|
+
end
|
108
|
+
|
109
|
+
it_behaves_like 'bit field with one flag set', :reparse_point, 'V', 0x00000400
|
110
|
+
end
|
111
|
+
|
112
|
+
describe 'compressed' do
|
113
|
+
it 'should be a 1-bit field per the SMB spec' do
|
114
|
+
expect(attrs.compressed).to be_a BinData::Bit1
|
115
|
+
end
|
116
|
+
|
117
|
+
it_behaves_like 'bit field with one flag set', :compressed, 'V', 0x00000800
|
118
|
+
end
|
119
|
+
|
120
|
+
describe 'offline' do
|
121
|
+
it 'should be a 1-bit field per the SMB spec' do
|
122
|
+
expect(attrs.offline).to be_a BinData::Bit1
|
123
|
+
end
|
124
|
+
|
125
|
+
it_behaves_like 'bit field with one flag set', :offline, 'V', 0x00001000
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'content_indexed' do
|
129
|
+
it 'should be a 1-bit field per the SMB spec' do
|
130
|
+
expect(attrs.content_indexed).to be_a BinData::Bit1
|
131
|
+
end
|
132
|
+
|
133
|
+
it_behaves_like 'bit field with one flag set', :content_indexed, 'V', 0x00002000
|
134
|
+
end
|
135
|
+
|
136
|
+
describe 'encrypted' do
|
137
|
+
it 'should be a 1-bit field per the SMB spec' do
|
138
|
+
expect(attrs.encrypted).to be_a BinData::Bit1
|
139
|
+
end
|
140
|
+
|
141
|
+
it_behaves_like 'bit field with one flag set', :encrypted, 'V', 0x00004000
|
142
|
+
end
|
143
|
+
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
RSpec.describe RubySMB::GenericPacket do
|
4
|
-
|
5
4
|
class TestPacket < RubySMB::GenericPacket
|
6
5
|
endian :little
|
7
6
|
uint8 :first_value, initial_value: 0x01
|
@@ -9,7 +8,7 @@ RSpec.describe RubySMB::GenericPacket do
|
|
9
8
|
array :array_value, type: :dialect, read_until: :eof
|
10
9
|
end
|
11
10
|
|
12
|
-
class ParentTestPacket <
|
11
|
+
class ParentTestPacket < RubySMB::GenericPacket
|
13
12
|
endian :little
|
14
13
|
uint8 :header
|
15
14
|
test_packet :test_packet
|
@@ -20,39 +19,65 @@ RSpec.describe RubySMB::GenericPacket do
|
|
20
19
|
|
21
20
|
describe '#describe class method' do
|
22
21
|
it 'outputs a string representing the structure of the packet' do
|
23
|
-
str = "\nFirst_value (Uint8) \n"
|
24
|
-
|
25
|
-
|
22
|
+
str = "\nFirst_value (Uint8) \n"\
|
23
|
+
"Second_value (Uint16le) \n"\
|
24
|
+
'Array_value (Array) '
|
26
25
|
expect(TestPacket.describe).to eq str
|
27
26
|
end
|
28
27
|
|
29
28
|
it 'handles nested record structures as well' do
|
30
|
-
str = "\nHeader (Uint8) \n"
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
29
|
+
str = "\nHeader (Uint8) \n"\
|
30
|
+
"TEST_PACKET \n"\
|
31
|
+
"\tFirst_value (Uint8) \n"\
|
32
|
+
"\tSecond_value (Uint16le) \n"\
|
33
|
+
"\tArray_value (Array) "
|
35
34
|
expect(ParentTestPacket.describe).to eq str
|
36
35
|
end
|
37
36
|
end
|
38
37
|
|
39
38
|
describe '#display' do
|
40
39
|
it 'shows the actual contents of the packet fields' do
|
41
|
-
str = "\nFIRST_VALUE 16\n"
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
40
|
+
str = "\nFIRST_VALUE 16\n" \
|
41
|
+
"SECOND_VALUE 4056\n" \
|
42
|
+
"ARRAY_VALUE\n" \
|
43
|
+
"\tBuffer Format ID 2\n" \
|
44
|
+
"\tDialect Name test"
|
46
45
|
expect(test_packet.display).to eq str
|
47
46
|
end
|
48
47
|
|
49
48
|
it 'handles nested record structures as well' do
|
50
|
-
str = "\nHEADER 0\n"
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
49
|
+
str = "\nHEADER 0\n" \
|
50
|
+
"TEST_PACKET\n" \
|
51
|
+
"\tFirst_value 1\n" \
|
52
|
+
"\tSecond_value 2\n" \
|
53
|
+
"\tARRAY_VALUE"
|
55
54
|
expect(parent_packet.display).to eq str
|
56
55
|
end
|
57
56
|
end
|
58
|
-
|
57
|
+
|
58
|
+
describe '#read' do
|
59
|
+
context 'when reading an SMB1 packet' do
|
60
|
+
let(:smb1_error_packet) { RubySMB::SMB1::Packet::EmptyPacket.new }
|
61
|
+
|
62
|
+
it 'returns the error packet instead of the asked for class' do
|
63
|
+
expect(RubySMB::SMB1::Packet::NegotiateResponse.read(smb1_error_packet.to_binary_s)).to be_a RubySMB::SMB1::Packet::EmptyPacket
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'reraises the exception if it is not a valid error packet either' do
|
67
|
+
expect{RubySMB::SMB1::Packet::NegotiateResponse.read('a')}.to raise_error(EOFError)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when reading an SMB2 packet' do
|
72
|
+
let(:smb2_error_packet) { RubySMB::SMB2::Packet::ErrorPacket.new }
|
73
|
+
|
74
|
+
it 'returns the error packet instead of the asked for class' do
|
75
|
+
expect(RubySMB::SMB2::Packet::NegotiateResponse.read(smb2_error_packet.to_binary_s)).to be_a RubySMB::SMB2::Packet::ErrorPacket
|
76
|
+
end
|
77
|
+
|
78
|
+
it 'reraises the exception if it is not a valid error packet either' do
|
79
|
+
expect{RubySMB::SMB2::Packet::NegotiateResponse.read('a')}.to raise_error(EOFError)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|