ruby_smb 2.0.2 → 3.0.0
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/.github/workflows/verify.yml +46 -0
- data/README.md +0 -1
- data/examples/anonymous_auth.rb +3 -3
- data/examples/append_file.rb +10 -8
- data/examples/auth_capture.rb +71 -0
- data/examples/authenticate.rb +9 -5
- data/examples/delete_file.rb +8 -6
- data/examples/dump_secrets_from_sid.rb +207 -0
- data/examples/enum_domain_users.rb +75 -0
- data/examples/enum_registry_key.rb +5 -4
- data/examples/enum_registry_values.rb +5 -4
- data/examples/get_computer_info.rb +42 -0
- data/examples/list_directory.rb +8 -6
- 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 +102 -0
- data/examples/read_file.rb +8 -6
- 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/client/authentication.rb +5 -10
- data/lib/ruby_smb/client/echo.rb +2 -4
- data/lib/ruby_smb/client/negotiation.rb +13 -16
- data/lib/ruby_smb/client/tree_connect.rb +2 -4
- data/lib/ruby_smb/client/utils.rb +16 -10
- data/lib/ruby_smb/client/winreg.rb +1 -1
- data/lib/ruby_smb/client.rb +102 -75
- data/lib/ruby_smb/compression/lznt1.rb +164 -0
- data/lib/ruby_smb/compression.rb +7 -0
- data/lib/ruby_smb/dcerpc/bind.rb +28 -20
- data/lib/ruby_smb/dcerpc/bind_ack.rb +29 -28
- data/lib/ruby_smb/dcerpc/client.rb +542 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_bind_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_bind_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_request.rb +57 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_crack_names_response.rb +76 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_request.rb +46 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_domain_controller_info_response.rb +168 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_extensions.rb +56 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_request.rb +121 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_get_nc_changes_response.rb +118 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_unbind_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/drsr/drs_unbind_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/drsr.rb +909 -0
- data/lib/ruby_smb/dcerpc/epm/epm_ept_map_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/epm/epm_ept_map_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/epm/epm_twrt.rb +211 -0
- data/lib/ruby_smb/dcerpc/epm.rb +75 -0
- data/lib/ruby_smb/dcerpc/error.rb +20 -0
- data/lib/ruby_smb/dcerpc/ndr.rb +1204 -80
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response.rb +26 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response.rb +24 -0
- data/lib/ruby_smb/dcerpc/netlogon.rb +102 -0
- data/lib/ruby_smb/dcerpc/p_syntax_id_t.rb +4 -3
- data/lib/ruby_smb/dcerpc/pdu_header.rb +7 -7
- data/lib/ruby_smb/dcerpc/ptypes.rb +1 -0
- data/lib/ruby_smb/dcerpc/request.rb +85 -19
- data/lib/ruby_smb/dcerpc/response.rb +45 -10
- data/lib/ruby_smb/dcerpc/rpc_auth3.rb +28 -0
- data/lib/ruby_smb/dcerpc/rpc_security_attributes.rb +34 -0
- data/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string.rb +118 -0
- data/lib/ruby_smb/dcerpc/samr/rpc_sid.rb +150 -0
- data/lib/ruby_smb/dcerpc/samr/samr_close_handle_request.rb +23 -0
- data/lib/ruby_smb/dcerpc/samr/samr_close_handle_response.rb +24 -0
- data/lib/ruby_smb/dcerpc/samr/samr_connect_request.rb +32 -0
- data/lib/ruby_smb/dcerpc/samr/samr_connect_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response.rb +55 -0
- data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_request.rb +48 -0
- data/lib/ruby_smb/dcerpc/samr/samr_get_alias_membership_response.rb +38 -0
- data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_request.rb +23 -0
- data/lib/ruby_smb/dcerpc/samr/samr_get_groups_for_user_response.rb +48 -0
- data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request.rb +24 -0
- data/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response.rb +25 -0
- data/lib/ruby_smb/dcerpc/samr/samr_open_domain_request.rb +27 -0
- data/lib/ruby_smb/dcerpc/samr/samr_open_domain_response.rb +24 -0
- data/lib/ruby_smb/dcerpc/samr/samr_open_user_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/samr/samr_open_user_response.rb +24 -0
- data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request.rb +23 -0
- data/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/samr.rb +613 -0
- data/lib/ruby_smb/dcerpc/sec_trailer.rb +26 -0
- data/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all.rb +56 -79
- data/lib/ruby_smb/dcerpc/srvsvc.rb +27 -4
- data/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request.rb +36 -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 +25 -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 +23 -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 +45 -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 +26 -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/svcctl.rb +477 -0
- data/lib/ruby_smb/dcerpc/uuid.rb +3 -0
- data/lib/ruby_smb/dcerpc/winreg/close_key_response.rb +2 -2
- data/lib/ruby_smb/dcerpc/winreg/create_key_request.rb +62 -0
- data/lib/ruby_smb/dcerpc/winreg/create_key_response.rb +36 -0
- data/lib/ruby_smb/dcerpc/winreg/enum_key_request.rb +2 -19
- data/lib/ruby_smb/dcerpc/winreg/enum_key_response.rb +3 -20
- data/lib/ruby_smb/dcerpc/winreg/enum_value_request.rb +5 -14
- data/lib/ruby_smb/dcerpc/winreg/enum_value_response.rb +5 -14
- data/lib/ruby_smb/dcerpc/winreg/open_key_request.rb +1 -9
- data/lib/ruby_smb/dcerpc/winreg/open_key_response.rb +4 -3
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_request.rb +6 -7
- data/lib/ruby_smb/dcerpc/winreg/open_root_key_response.rb +2 -2
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_request.rb +1 -1
- data/lib/ruby_smb/dcerpc/winreg/query_info_key_response.rb +9 -18
- data/lib/ruby_smb/dcerpc/winreg/query_value_request.rb +4 -13
- data/lib/ruby_smb/dcerpc/winreg/query_value_response.rb +7 -15
- data/lib/ruby_smb/dcerpc/winreg/regsam.rb +3 -1
- data/lib/ruby_smb/dcerpc/winreg/save_key_request.rb +28 -0
- data/lib/ruby_smb/dcerpc/winreg/save_key_response.rb +23 -0
- data/lib/ruby_smb/dcerpc/winreg.rb +99 -22
- data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request.rb +26 -0
- data/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response.rb +88 -0
- data/lib/ruby_smb/dcerpc/wkssvc.rb +65 -0
- data/lib/ruby_smb/dcerpc.rb +45 -11
- data/lib/ruby_smb/dialect.rb +45 -0
- data/lib/ruby_smb/dispatcher/base.rb +1 -1
- data/lib/ruby_smb/dispatcher/socket.rb +2 -2
- data/lib/ruby_smb/error.rb +21 -5
- data/lib/ruby_smb/field/file_time.rb +1 -1
- data/lib/ruby_smb/field/string16.rb +5 -1
- data/lib/ruby_smb/field/stringz16.rb +17 -1
- data/lib/ruby_smb/generic_packet.rb +11 -1
- data/lib/ruby_smb/gss/provider/authenticator.rb +42 -0
- data/lib/ruby_smb/gss/provider/ntlm.rb +303 -0
- data/lib/ruby_smb/gss/provider.rb +35 -0
- data/lib/ruby_smb/gss.rb +56 -63
- data/lib/ruby_smb/nbss/session_header.rb +4 -4
- data/lib/ruby_smb/ntlm.rb +61 -0
- data/lib/ruby_smb/server/server_client/negotiation.rb +156 -0
- data/lib/ruby_smb/server/server_client/session_setup.rb +82 -0
- data/lib/ruby_smb/server/server_client.rb +162 -0
- data/lib/ruby_smb/server.rb +54 -0
- data/lib/ruby_smb/signing.rb +59 -0
- data/lib/ruby_smb/smb1/file.rb +10 -25
- data/lib/ruby_smb/smb1/packet/negotiate_response.rb +11 -11
- data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +1 -1
- data/lib/ruby_smb/smb1/packet/session_setup_request.rb +1 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_first2_response.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans2/find_next2_response.rb +0 -1
- data/lib/ruby_smb/smb1/packet/trans2/open2_response.rb +1 -2
- data/lib/ruby_smb/smb1/packet/trans2/set_file_information_response.rb +1 -13
- data/lib/ruby_smb/smb1/pipe.rb +12 -6
- data/lib/ruby_smb/smb1/tree.rb +13 -9
- data/lib/ruby_smb/smb2/file.rb +33 -33
- data/lib/ruby_smb/smb2/negotiate_context.rb +18 -2
- data/lib/ruby_smb/smb2/packet/compression_transform_header.rb +4 -0
- data/lib/ruby_smb/smb2/packet/negotiate_request.rb +9 -0
- data/lib/ruby_smb/smb2/packet/negotiate_response.rb +0 -1
- data/lib/ruby_smb/smb2/packet/session_setup_response.rb +2 -2
- data/lib/ruby_smb/smb2/packet/tree_connect_request.rb +1 -1
- data/lib/ruby_smb/smb2/pipe.rb +13 -6
- data/lib/ruby_smb/smb2/tree.rb +21 -11
- data/lib/ruby_smb/smb2.rb +3 -1
- data/lib/ruby_smb/version.rb +1 -1
- data/lib/ruby_smb.rb +5 -3
- data/spec/lib/ruby_smb/client_spec.rb +199 -86
- data/spec/lib/ruby_smb/compression/lznt1_spec.rb +32 -0
- data/spec/lib/ruby_smb/dcerpc/bind_ack_spec.rb +69 -41
- data/spec/lib/ruby_smb/dcerpc/bind_spec.rb +75 -21
- data/spec/lib/ruby_smb/dcerpc/client_spec.rb +714 -0
- data/spec/lib/ruby_smb/dcerpc/drsr_spec.rb +2169 -0
- data/spec/lib/ruby_smb/dcerpc/ndr_spec.rb +3977 -239
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_request_spec.rb +69 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_authenticate3_response_spec.rb +53 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_request_spec.rb +69 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_password_set2_response_spec.rb +37 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_request_spec.rb +45 -0
- data/spec/lib/ruby_smb/dcerpc/netlogon/netr_server_req_challenge_response_spec.rb +37 -0
- data/spec/lib/ruby_smb/dcerpc/p_syntax_id_t_spec.rb +18 -4
- data/spec/lib/ruby_smb/dcerpc/pdu_header_spec.rb +27 -1
- data/spec/lib/ruby_smb/dcerpc/request_spec.rb +76 -11
- data/spec/lib/ruby_smb/dcerpc/response_spec.rb +99 -9
- data/spec/lib/ruby_smb/dcerpc/rpc_auth3_spec.rb +75 -0
- data/spec/lib/ruby_smb/dcerpc/rpc_security_attributes_spec.rb +162 -0
- data/spec/lib/ruby_smb/dcerpc/rrp_rpc_unicode_string_spec.rb +340 -0
- data/spec/lib/ruby_smb/dcerpc/samr/rpc_sid_spec.rb +116 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_request_spec.rb +40 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_close_handle_response_spec.rb +48 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_request_spec.rb +56 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_connect_response_spec.rb +47 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_request_spec.rb +63 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_enumerate_users_in_domain_response_spec.rb +265 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_request_spec.rb +52 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_lookup_domain_in_sam_server_response_spec.rb +36 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_request_spec.rb +56 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_open_domain_response_spec.rb +48 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_request_spec.rb +48 -0
- data/spec/lib/ruby_smb/dcerpc/samr/samr_rid_to_sid_response_spec.rb +42 -0
- data/spec/lib/ruby_smb/dcerpc/samr_spec.rb +420 -0
- data/spec/lib/ruby_smb/dcerpc/sec_trailer_spec.rb +92 -0
- data/spec/lib/ruby_smb/dcerpc/srvsvc/net_share_enum_all_spec.rb +149 -110
- data/spec/lib/ruby_smb/dcerpc/srvsvc_spec.rb +21 -17
- data/spec/lib/ruby_smb/dcerpc/svcctl/change_service_config_w_request_spec.rb +168 -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 +68 -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 +53 -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 +76 -0
- data/spec/lib/ruby_smb/dcerpc/svcctl/start_service_w_request_spec.rb +47 -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 +508 -0
- data/spec/lib/ruby_smb/dcerpc/uuid_spec.rb +15 -23
- data/spec/lib/ruby_smb/dcerpc/winreg/close_key_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/create_key_request_spec.rb +73 -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 +4 -56
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_key_response_spec.rb +4 -56
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_request_spec.rb +10 -34
- data/spec/lib/ruby_smb/dcerpc/winreg/enum_value_response_spec.rb +10 -34
- data/spec/lib/ruby_smb/dcerpc/winreg/open_key_request_spec.rb +2 -26
- data/spec/lib/ruby_smb/dcerpc/winreg/open_key_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_request_spec.rb +17 -20
- data/spec/lib/ruby_smb/dcerpc/winreg/open_root_key_response_spec.rb +2 -2
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_request_spec.rb +0 -4
- data/spec/lib/ruby_smb/dcerpc/winreg/query_info_key_response_spec.rb +20 -44
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_request_spec.rb +8 -32
- data/spec/lib/ruby_smb/dcerpc/winreg/query_value_response_spec.rb +18 -42
- data/spec/lib/ruby_smb/dcerpc/winreg/regsam_spec.rb +4 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/save_key_request_spec.rb +45 -0
- data/spec/lib/ruby_smb/dcerpc/winreg/save_key_response_spec.rb +22 -0
- data/spec/lib/ruby_smb/dcerpc/winreg_spec.rb +219 -62
- data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_request_spec.rb +43 -0
- data/spec/lib/ruby_smb/dcerpc/wkssvc/netr_wksta_get_info_response_spec.rb +410 -0
- data/spec/lib/ruby_smb/dcerpc/wkssvc_spec.rb +70 -0
- data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +10 -10
- data/spec/lib/ruby_smb/error_spec.rb +34 -5
- data/spec/lib/ruby_smb/field/string16_spec.rb +22 -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/gss/provider/ntlm/account_spec.rb +32 -0
- data/spec/lib/ruby_smb/gss/provider/ntlm/authenticator_spec.rb +101 -0
- data/spec/lib/ruby_smb/gss/provider/ntlm/os_version_spec.rb +32 -0
- data/spec/lib/ruby_smb/gss/provider/ntlm_spec.rb +113 -0
- data/spec/lib/ruby_smb/nbss/session_header_spec.rb +4 -11
- data/spec/lib/ruby_smb/server/server_client_spec.rb +156 -0
- data/spec/lib/ruby_smb/server_spec.rb +32 -0
- data/spec/lib/ruby_smb/smb1/file_spec.rb +2 -4
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_first2_response_spec.rb +0 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/find_next2_response_spec.rb +0 -1
- data/spec/lib/ruby_smb/smb1/packet/trans2/open2_response_spec.rb +0 -5
- data/spec/lib/ruby_smb/smb1/packet/trans2/set_file_information_response_spec.rb +0 -6
- data/spec/lib/ruby_smb/smb1/pipe_spec.rb +20 -14
- data/spec/lib/ruby_smb/smb1/tree_spec.rb +22 -0
- data/spec/lib/ruby_smb/smb2/file_spec.rb +61 -9
- data/spec/lib/ruby_smb/smb2/negotiate_context_spec.rb +2 -2
- data/spec/lib/ruby_smb/smb2/pipe_spec.rb +20 -14
- data/spec/lib/ruby_smb/smb2/tree_spec.rb +58 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/support/bin_helper.rb +9 -0
- data.tar.gz.sig +0 -0
- metadata +229 -23
- metadata.gz.sig +0 -0
- data/.travis.yml +0 -6
- data/lib/ruby_smb/client/signing.rb +0 -64
- data/lib/ruby_smb/dcerpc/rrp_unicode_string.rb +0 -35
- data/spec/lib/ruby_smb/dcerpc/rrp_unicode_string_spec.rb +0 -98
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
RSpec.describe RubySMB::Gss::Provider::NTLM::Authenticator do
|
|
2
|
+
let(:username) { 'RubySMB' }
|
|
3
|
+
let(:domain) { 'WORKGROUP' }
|
|
4
|
+
let(:password) { 'password' }
|
|
5
|
+
let(:provider) { RubySMB::Gss::Provider::NTLM.new.tap { |provider| provider.put_account(username, password, domain: domain) } }
|
|
6
|
+
let(:authenticator) { described_class.new(provider, nil) }
|
|
7
|
+
let(:type1_msg) do
|
|
8
|
+
Net::NTLM::Message::Type1.new.tap do |msg|
|
|
9
|
+
msg.domain = domain
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
let(:type3_msg) do
|
|
13
|
+
Net::NTLM::Message::Type2.new.response(user: username, password: '', domain: domain)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
describe '#initialize' do
|
|
17
|
+
it 'defaults to a null session key' do
|
|
18
|
+
expect(authenticator.session_key).to be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'defaults to a null server challenge' do
|
|
22
|
+
expect(authenticator.server_challenge).to be_nil
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe '#process' do
|
|
27
|
+
it 'should handle an empty GSS buffer' do
|
|
28
|
+
result = authenticator.process
|
|
29
|
+
expect(result).to be_a RubySMB::Gss::Provider::Result
|
|
30
|
+
expect(result.nt_status).to eq WindowsError::NTStatus::STATUS_SUCCESS
|
|
31
|
+
expect(result.buffer).to_not be_empty
|
|
32
|
+
expect(result.identity).to be_nil
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'should handle an embedded NTLM type 1 message' do
|
|
36
|
+
expect(authenticator).to receive(:process_ntlm_type1).and_call_original
|
|
37
|
+
result = authenticator.process(RubySMB::Gss.gss_type1(type1_msg.serialize))
|
|
38
|
+
expect(result).to be_a RubySMB::Gss::Provider::Result
|
|
39
|
+
expect(result.nt_status).to eq WindowsError::NTStatus::STATUS_MORE_PROCESSING_REQUIRED
|
|
40
|
+
expect(result.buffer).to_not be_empty
|
|
41
|
+
expect(result.identity).to be_nil
|
|
42
|
+
expect(authenticator.session_key).to be_nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'should handle an embedded NTLM type 3 message' do
|
|
46
|
+
authenticator.server_challenge = Random.new.bytes(8)
|
|
47
|
+
expect(authenticator).to receive(:process_ntlm_type3).and_call_original
|
|
48
|
+
result = authenticator.process(RubySMB::Gss.gss_type3(type3_msg.serialize))
|
|
49
|
+
expect(result).to be_a RubySMB::Gss::Provider::Result
|
|
50
|
+
expect(result.nt_status).to eq WindowsError::NTStatus::STATUS_LOGON_FAILURE
|
|
51
|
+
expect(result.buffer).to be_nil
|
|
52
|
+
expect(result.identity).to be_nil
|
|
53
|
+
expect(authenticator.session_key).to be_nil
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#process_ntlm_type1' do
|
|
58
|
+
it 'should process a NTLM type 1 message and return a type2 message' do
|
|
59
|
+
expect(authenticator.process_ntlm_type1(type1_msg)).to be_a Net::NTLM::Message::Type2
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe '#process_ntlm_type3' do
|
|
64
|
+
it 'should process a NTLM type 3 message and return an error code' do
|
|
65
|
+
expect(authenticator.process_ntlm_type3(type3_msg)).to be_a WindowsError::ErrorCode
|
|
66
|
+
expect(authenticator.process_ntlm_type3(type3_msg)).to eq WindowsError::NTStatus::STATUS_LOGON_FAILURE
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe '#reset!' do
|
|
71
|
+
it 'should clear the server challenge' do
|
|
72
|
+
authenticator.instance_variable_set(:@server_challenge, Random.new.bytes(8))
|
|
73
|
+
authenticator.reset!
|
|
74
|
+
expect(authenticator.instance_variable_get(:@server_challenge)).to be_nil
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it 'should clear the session key' do
|
|
78
|
+
authenticator.instance_variable_set(:@session_key, Random.new.bytes(16))
|
|
79
|
+
authenticator.reset!
|
|
80
|
+
expect(authenticator.instance_variable_get(:@session_key)).to be_nil
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
describe 'a full Net-NTLMv2 authentication exchange' do
|
|
85
|
+
let(:type2_msg) { authenticator.process_ntlm_type1(type1_msg)}
|
|
86
|
+
|
|
87
|
+
it 'should respond to a correct password with STATUS_SUCCESS' do
|
|
88
|
+
type3_msg = type2_msg.response({user: username, domain: domain, password: password}, ntlmv2: true)
|
|
89
|
+
type3_msg.user.force_encoding('UTF-16LE')
|
|
90
|
+
type3_msg.domain.force_encoding('UTF-16LE')
|
|
91
|
+
expect(authenticator.process_ntlm_type3(type3_msg)).to eq WindowsError::NTStatus::STATUS_SUCCESS
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it 'should respond to an incorrect password with STATUS_LOGON_FAILURE' do
|
|
95
|
+
type3_msg = type2_msg.response({user: username, domain: domain, password: password + rand(0x41..0x5b).chr}, ntlmv2: true)
|
|
96
|
+
type3_msg.user.force_encoding('UTF-16LE')
|
|
97
|
+
type3_msg.domain.force_encoding('UTF-16LE')
|
|
98
|
+
expect(authenticator.process_ntlm_type3(type3_msg)).to eq WindowsError::NTStatus::STATUS_LOGON_FAILURE
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
RSpec.describe RubySMB::Gss::Provider::NTLM::OSVersion do
|
|
2
|
+
subject(:os_version) { RubySMB::Gss::Provider::NTLM::OSVersion.new }
|
|
3
|
+
|
|
4
|
+
it { is_expected.to respond_to :major }
|
|
5
|
+
it { is_expected.to respond_to :minor }
|
|
6
|
+
it { is_expected.to respond_to :build }
|
|
7
|
+
it { is_expected.to respond_to :ntlm_revision }
|
|
8
|
+
|
|
9
|
+
describe '#initialize' do
|
|
10
|
+
it 'defaults to an NTLM revision of 15' do
|
|
11
|
+
expect(os_version.ntlm_revision).to eq 15
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe '#read' do
|
|
16
|
+
it 'reads a packed version correctly' do
|
|
17
|
+
# Version 6.1 (Build 7601); NTLM Current Revision 15
|
|
18
|
+
os_version = RubySMB::Gss::Provider::NTLM::OSVersion.read("\x06\x01\xb1\x1d\x00\x00\x00\x0f")
|
|
19
|
+
expect(os_version.major).to eq 6
|
|
20
|
+
expect(os_version.minor).to eq 1
|
|
21
|
+
expect(os_version.build).to eq 7601
|
|
22
|
+
expect(os_version.ntlm_revision).to eq 15
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe '#to_s' do
|
|
27
|
+
it 'creates a string representation of the OS version' do
|
|
28
|
+
expect(os_version.to_s).to be_a String
|
|
29
|
+
expect(os_version.to_s).to match /Version \d+\.\d+ \(Build \d+\); NTLM Current Revision \d+/
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe RubySMB::Gss::Provider::NTLM do
|
|
4
|
+
let(:provider) { described_class.new }
|
|
5
|
+
|
|
6
|
+
it { is_expected.to respond_to :allow_anonymous }
|
|
7
|
+
it { is_expected.to respond_to :default_domain }
|
|
8
|
+
|
|
9
|
+
describe '#initialize' do
|
|
10
|
+
it 'defaults to false for allowing anonymous access' do
|
|
11
|
+
expect(provider.allow_anonymous).to be false
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'defaults to a default domain of WORKGROUP' do
|
|
15
|
+
expect(provider.default_domain).to eq 'WORKGROUP'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'defaults to a random challenge generator' do
|
|
19
|
+
expect(provider.generate_server_challenge).to_not eq provider.generate_server_challenge
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe '#generate_server_challenge' do
|
|
24
|
+
it 'generates a valid 8-byte challenge' do
|
|
25
|
+
challenge = provider.generate_server_challenge
|
|
26
|
+
expect(challenge).to be_a String
|
|
27
|
+
expect(challenge.length).to eq 8
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'should take a generator block' do
|
|
31
|
+
random_challenge = Random.new.bytes(8)
|
|
32
|
+
provider.generate_server_challenge do
|
|
33
|
+
random_challenge
|
|
34
|
+
end
|
|
35
|
+
expect(provider.generate_server_challenge).to eq random_challenge
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe '#get_account' do
|
|
40
|
+
let(:username) { 'RubySMB' }
|
|
41
|
+
let(:password) { 'password' }
|
|
42
|
+
let(:domain) { 'WORKGROUP' }
|
|
43
|
+
|
|
44
|
+
context 'when getting accounts' do
|
|
45
|
+
before(:each) do
|
|
46
|
+
provider.put_account(username, password)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'should return nil for an unknown account' do
|
|
50
|
+
account = provider.get_account('Spencer')
|
|
51
|
+
expect(account).to be_nil
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it 'should work with a case sensitive name' do
|
|
55
|
+
account = provider.get_account(username)
|
|
56
|
+
expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
|
|
57
|
+
expect(account.username).to eq username
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it 'should work with a case insensitive name' do
|
|
61
|
+
account = provider.get_account(username.downcase)
|
|
62
|
+
expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
|
|
63
|
+
expect(account.username).to eq username
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'should work with a case sensitive domain' do
|
|
67
|
+
account = provider.get_account(username, domain: domain)
|
|
68
|
+
expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
|
|
69
|
+
expect(account.domain).to eq domain
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'should work with a case insensitive domain' do
|
|
73
|
+
account = provider.get_account(username, domain: domain.downcase)
|
|
74
|
+
expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
|
|
75
|
+
expect(account.domain).to eq domain
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'should work with the special . domain' do
|
|
79
|
+
account = provider.get_account(username, domain: '.')
|
|
80
|
+
expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
|
|
81
|
+
expect(account.domain).to eq domain
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# UTF-16LE is optionally used for encoding some Net-NTLM message fields, the #get_account method should handle it
|
|
85
|
+
# transparently
|
|
86
|
+
it 'should work with a UTF16-LE name' do
|
|
87
|
+
account = provider.get_account(username.encode('UTF-16LE'))
|
|
88
|
+
expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
|
|
89
|
+
expect(account.username).to eq username
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it 'should work with a UTF16-LE domain' do
|
|
93
|
+
account = provider.get_account(username, domain: domain.encode('UTF-16LE'))
|
|
94
|
+
expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
|
|
95
|
+
expect(account.domain).to eq domain
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
context 'when putting accounts' do
|
|
100
|
+
it 'should accept new accounts with the default domain' do
|
|
101
|
+
provider.put_account(username, password)
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
after(:each) do
|
|
105
|
+
account = provider.get_account(username, domain: domain)
|
|
106
|
+
expect(account).to be_a RubySMB::Gss::Provider::NTLM::Account
|
|
107
|
+
expect(account.username).to eq username
|
|
108
|
+
expect(account.password).to eq password
|
|
109
|
+
expect(account.domain).to eq domain
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -2,8 +2,7 @@ RSpec.describe RubySMB::Nbss::SessionHeader do
|
|
|
2
2
|
subject(:session_header) { described_class.new }
|
|
3
3
|
|
|
4
4
|
it { is_expected.to respond_to :session_packet_type }
|
|
5
|
-
it { is_expected.to respond_to :
|
|
6
|
-
it { is_expected.to respond_to :packet_length }
|
|
5
|
+
it { is_expected.to respond_to :stream_protocol_length }
|
|
7
6
|
|
|
8
7
|
it 'is big endian' do
|
|
9
8
|
expect(described_class.fields.instance_variable_get(:@hints)[:endian]).to eq :big
|
|
@@ -15,15 +14,9 @@ RSpec.describe RubySMB::Nbss::SessionHeader do
|
|
|
15
14
|
end
|
|
16
15
|
end
|
|
17
16
|
|
|
18
|
-
describe '#
|
|
19
|
-
it 'is a
|
|
20
|
-
expect(session_header.
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
describe '#packet_length' do
|
|
25
|
-
it 'is a 17-bit Unsigned Integer' do
|
|
26
|
-
expect(session_header.packet_length).to be_a BinData::Bit17
|
|
17
|
+
describe '#stream_protocol_length' do
|
|
18
|
+
it 'is a 24-bit Unsigned Integer' do
|
|
19
|
+
expect(session_header.stream_protocol_length).to be_a BinData::Uint24be
|
|
27
20
|
end
|
|
28
21
|
end
|
|
29
22
|
end
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
RSpec.describe RubySMB::Server::ServerClient do
|
|
2
|
+
let(:server) { RubySMB::Server.new(server_sock: ::TCPServer.new(0)) }
|
|
3
|
+
let(:sock) { double('Socket', peeraddr: '192.168.1.5') }
|
|
4
|
+
let(:dispatcher) { RubySMB::Dispatcher::Socket.new(sock) }
|
|
5
|
+
subject(:server_client) { described_class.new(server, dispatcher) }
|
|
6
|
+
|
|
7
|
+
it { is_expected.to respond_to :dialect }
|
|
8
|
+
it { is_expected.to respond_to :identity }
|
|
9
|
+
it { is_expected.to respond_to :state }
|
|
10
|
+
it { is_expected.to respond_to :session_key }
|
|
11
|
+
|
|
12
|
+
describe '#disconnect!' do
|
|
13
|
+
it 'closes the socket' do
|
|
14
|
+
expect(dispatcher.tcp_socket).to receive(:close).with(no_args).and_return(nil)
|
|
15
|
+
server_client.disconnect!
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe '#initialize' do
|
|
20
|
+
it 'starts in the negotiate state' do
|
|
21
|
+
expect(server_client.state).to eq :negotiate
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'starts without a dialect' do
|
|
25
|
+
expect(server_client.dialect).to be_nil
|
|
26
|
+
expect(server_client.metadialect).to be_nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'starts without an identity' do
|
|
30
|
+
expect(server_client.identity).to be_nil
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'starts without a session_key' do
|
|
34
|
+
expect(server_client.session_key).to be_nil
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'creates a new authenticator instance' do
|
|
38
|
+
expect(server.gss_provider).to receive(:new_authenticator).and_call_original
|
|
39
|
+
described_class.new(server, dispatcher)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe '#process_gss' do
|
|
44
|
+
before(:each) do
|
|
45
|
+
expect(server_client.instance_eval { @gss_authenticator }).to receive(:process).and_call_original
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'should handle an empty GSS buffer' do
|
|
49
|
+
result = server_client.process_gss
|
|
50
|
+
expect(result).to be_a RubySMB::Gss::Provider::Result
|
|
51
|
+
expect(result.nt_status).to eq WindowsError::NTStatus::STATUS_SUCCESS
|
|
52
|
+
expect(result.buffer).to_not be_empty
|
|
53
|
+
expect(result.identity).to be_nil
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '#recv_packet' do
|
|
58
|
+
it 'receives a new packet from the dispatcher' do
|
|
59
|
+
expect(dispatcher).to receive(:recv_packet).with(no_args)
|
|
60
|
+
server_client.recv_packet
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
describe '#run' do
|
|
65
|
+
let(:packet) { Random.new.bytes(16) }
|
|
66
|
+
before(:each) do
|
|
67
|
+
expect(server_client).to receive(:recv_packet).and_return(packet)
|
|
68
|
+
# this hook should ensure that the dispatcher loop returns after processing a single request
|
|
69
|
+
expect(dispatcher.tcp_socket).to receive(:closed?).and_return(true)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'calls #handle_negotiate when the state is negotiate' do
|
|
73
|
+
expect(server_client).to receive(:handle_negotiate).with(packet).and_return(nil)
|
|
74
|
+
server_client.instance_eval { @state = :negotiate }
|
|
75
|
+
server_client.run
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'calls #handle_session_setup when the state is session_setup' do
|
|
79
|
+
expect(server_client).to receive(:handle_session_setup).with(packet).and_return(nil)
|
|
80
|
+
server_client.instance_eval { @state = :session_setup }
|
|
81
|
+
server_client.run
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it 'calls #authenticated when the state is authenticated' do
|
|
85
|
+
expect(server_client).to receive(:handle_authenticated).with(packet).and_return(nil)
|
|
86
|
+
server_client.instance_eval { @state = :authenticated }
|
|
87
|
+
server_client.run
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
describe '#send_packet' do
|
|
92
|
+
let(:packet) { RubySMB::GenericPacket.new }
|
|
93
|
+
|
|
94
|
+
before(:each) do
|
|
95
|
+
expect(dispatcher).to receive(:send_packet).with(packet).and_return(nil)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'sends a packet to the dispatcher' do
|
|
99
|
+
server_client.send_packet(packet)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
%w{ 0x0202 0x0210 0x0300 0x0302 0x0311 }.each do |dialect|
|
|
103
|
+
context "when the dialect is #{dialect}" do
|
|
104
|
+
before(:each) do
|
|
105
|
+
server_client.instance_eval { @dialect = dialect }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context 'and the state is authenticated' do
|
|
109
|
+
before(:each) do
|
|
110
|
+
server_client.instance_eval { @state = :authenticated }
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
context 'and the identity is anonymous' do
|
|
114
|
+
before(:each) do
|
|
115
|
+
server_client.instance_eval { @identity = RubySMB::Gss::Provider::IDENTITY_ANONYMOUS }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it 'does not sign packets' do
|
|
119
|
+
expect(server_client).to_not receive(:smb2_sign)
|
|
120
|
+
expect(server_client).to_not receive(:smb3_sign)
|
|
121
|
+
server_client.send_packet(packet)
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
context 'and the identity is not anonymous' do
|
|
126
|
+
before(:each) do
|
|
127
|
+
server_client.instance_eval { @identity = 'WORKGROUP\RubySMB'; @session_key = Random.new.bytes(16) }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'does sign packets' do
|
|
131
|
+
packet = RubySMB::GenericPacket.new
|
|
132
|
+
dialect_family = RubySMB::Dialect[dialect].family
|
|
133
|
+
if dialect_family == RubySMB::Dialect::FAMILY_SMB2
|
|
134
|
+
expect(server_client).to receive(:smb2_sign).with(packet).and_return(packet)
|
|
135
|
+
expect(server_client).to_not receive(:smb3_sign)
|
|
136
|
+
elsif dialect_family == RubySMB::Dialect::FAMILY_SMB3
|
|
137
|
+
expect(server_client).to receive(:smb3_sign).with(packet).and_return(packet)
|
|
138
|
+
expect(server_client).to_not receive(:smb2_sign)
|
|
139
|
+
end
|
|
140
|
+
server_client.send_packet(packet)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
describe '#update_preauth_hash' do
|
|
149
|
+
it 'raises an EncryptionError exception if the preauth integrity hash algorithm is not known' do
|
|
150
|
+
expect { server_client.update_preauth_hash('Test') }.to raise_error(
|
|
151
|
+
RubySMB::Error::EncryptionError,
|
|
152
|
+
'Cannot compute the Preauth Integrity Hash value: Preauth Integrity Hash Algorithm is nil'
|
|
153
|
+
)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
RSpec.describe RubySMB::Server do
|
|
2
|
+
before(:each) do
|
|
3
|
+
allow(::TCPServer).to receive(:new).and_return(::TCPServer.new(0))
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
it { is_expected.to respond_to :dialects }
|
|
7
|
+
it { is_expected.to respond_to :gss_provider }
|
|
8
|
+
it { is_expected.to respond_to :guid }
|
|
9
|
+
|
|
10
|
+
describe '#initialize' do
|
|
11
|
+
it 'should bind to TCP port 445 by default' do
|
|
12
|
+
expect(::TCPServer).to receive(:new).with(445).and_return(::TCPServer.new(0))
|
|
13
|
+
described_class.new
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'should create a new NTLM GSS provider by default' do
|
|
17
|
+
expect(RubySMB::Gss::Provider::NTLM).to receive(:new).and_call_original
|
|
18
|
+
described_class.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'should generate a random 16-byte GUID' do
|
|
22
|
+
server_guid = described_class.new.guid
|
|
23
|
+
expect(server_guid).to be_a String
|
|
24
|
+
expect(server_guid.length).to eq 16
|
|
25
|
+
expect(server_guid).to_not eq described_class.new.guid
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'should support some dialects' do
|
|
29
|
+
expect(described_class.new.dialects).to_not be_empty
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -473,7 +473,7 @@ RSpec.describe RubySMB::SMB1::File do
|
|
|
473
473
|
end
|
|
474
474
|
|
|
475
475
|
it 'sets the File Information #rename_pending field of the packet' do
|
|
476
|
-
expect(file.rename_packet(filename).data_block.trans2_data.info_level_struct.file_name).to eq filename
|
|
476
|
+
expect(file.rename_packet(filename).data_block.trans2_data.info_level_struct.file_name).to eq filename
|
|
477
477
|
end
|
|
478
478
|
|
|
479
479
|
it 'sets the Trans2 ParameterBlock fields' do
|
|
@@ -521,9 +521,7 @@ RSpec.describe RubySMB::SMB1::File do
|
|
|
521
521
|
|
|
522
522
|
it 'raises an InvalidPacket exception if the response is not valid' do
|
|
523
523
|
allow(response).to receive(:valid?).and_return(false)
|
|
524
|
-
|
|
525
|
-
allow(response).to receive(:smb_header).and_return(smb_header)
|
|
526
|
-
allow(smb_header).to receive_messages(:protocol => nil, :command => nil)
|
|
524
|
+
allow(response).to receive(:packet_smb_version)
|
|
527
525
|
expect { file.close }.to raise_error(RubySMB::Error::InvalidPacket)
|
|
528
526
|
end
|
|
529
527
|
|
|
@@ -32,7 +32,6 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindFirst2Response do
|
|
|
32
32
|
describe '#data_block' do
|
|
33
33
|
subject(:data_block) { packet.data_block }
|
|
34
34
|
|
|
35
|
-
it { is_expected.to respond_to :name }
|
|
36
35
|
it { is_expected.to respond_to :trans2_parameters }
|
|
37
36
|
it { is_expected.to respond_to :trans2_data }
|
|
38
37
|
|
|
@@ -32,7 +32,6 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::FindNext2Response do
|
|
|
32
32
|
describe '#data_block' do
|
|
33
33
|
subject(:data_block) { packet.data_block }
|
|
34
34
|
|
|
35
|
-
it { is_expected.to respond_to :name }
|
|
36
35
|
it { is_expected.to respond_to :trans2_parameters }
|
|
37
36
|
it { is_expected.to respond_to :trans2_data }
|
|
38
37
|
|
|
@@ -35,16 +35,11 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::Open2Response do
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
it { is_expected.to respond_to :trans2_parameters }
|
|
38
|
-
it { is_expected.to respond_to :trans2_data }
|
|
39
38
|
|
|
40
39
|
it 'should keep #trans2_parameters 4-byte aligned' do
|
|
41
40
|
expect(data_block.trans2_parameters.abs_offset % 4).to eq 0
|
|
42
41
|
end
|
|
43
42
|
|
|
44
|
-
it 'should keep #trans2_data 4-byte aligned' do
|
|
45
|
-
expect(data_block.trans2_data.abs_offset % 4).to eq 0
|
|
46
|
-
end
|
|
47
|
-
|
|
48
43
|
describe '#trans2_parameters' do
|
|
49
44
|
subject(:parameters) { data_block.trans2_parameters }
|
|
50
45
|
|
|
@@ -28,18 +28,12 @@ RSpec.describe RubySMB::SMB1::Packet::Trans2::SetFileInformationResponse do
|
|
|
28
28
|
describe '#data_block' do
|
|
29
29
|
subject(:data_block) { packet.data_block }
|
|
30
30
|
|
|
31
|
-
it { is_expected.to respond_to :name }
|
|
32
31
|
it { is_expected.to respond_to :trans2_parameters }
|
|
33
|
-
it { is_expected.to respond_to :trans2_data }
|
|
34
32
|
|
|
35
33
|
it 'should keep #trans2_parameters 4-byte aligned' do
|
|
36
34
|
expect(data_block.trans2_parameters.abs_offset % 4).to eq 0
|
|
37
35
|
end
|
|
38
36
|
|
|
39
|
-
it 'should keep #trans2_data 4-byte aligned' do
|
|
40
|
-
expect(data_block.trans2_data.abs_offset % 4).to eq 0
|
|
41
|
-
end
|
|
42
|
-
|
|
43
37
|
describe '#trans2_parameters' do
|
|
44
38
|
subject(:parameters) { data_block.trans2_parameters }
|
|
45
39
|
|
|
@@ -80,9 +80,7 @@ RSpec.describe RubySMB::SMB1::Pipe do
|
|
|
80
80
|
|
|
81
81
|
it 'raises an InvalidPacket exception if the response is not valid' do
|
|
82
82
|
allow(response).to receive(:valid?).and_return(false)
|
|
83
|
-
|
|
84
|
-
allow(response).to receive(:smb_header).and_return(smb_header)
|
|
85
|
-
allow(smb_header).to receive_messages(:protocol => nil, :command => nil)
|
|
83
|
+
allow(response).to receive(:packet_smb_version)
|
|
86
84
|
expect { pipe.peek }.to raise_error(RubySMB::Error::InvalidPacket)
|
|
87
85
|
end
|
|
88
86
|
|
|
@@ -142,17 +140,26 @@ RSpec.describe RubySMB::SMB1::Pipe do
|
|
|
142
140
|
expect(pipe.size_on_disk).to eq(nt_create_andx_response.parameter_block.allocation_size)
|
|
143
141
|
end
|
|
144
142
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
143
|
+
{
|
|
144
|
+
netlogon: RubySMB::Dcerpc::Netlogon,
|
|
145
|
+
srvsvc: RubySMB::Dcerpc::Srvsvc,
|
|
146
|
+
svcctl: RubySMB::Dcerpc::Svcctl,
|
|
147
|
+
winreg: RubySMB::Dcerpc::Winreg,
|
|
148
|
+
samr: RubySMB::Dcerpc::Samr,
|
|
149
|
+
wkssvc: RubySMB::Dcerpc::Wkssvc
|
|
150
|
+
}.each do |endpoint, klass|
|
|
151
|
+
context "with \'#{endpoint}\' filename" do
|
|
152
|
+
it "extends #{klass} class" do
|
|
153
|
+
pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: endpoint.to_s)
|
|
154
|
+
expect(pipe).to be_a klass
|
|
155
|
+
end
|
|
149
156
|
end
|
|
150
|
-
end
|
|
151
157
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
158
|
+
context "with \'\\#{endpoint}\' filename" do
|
|
159
|
+
it "extends #{klass} class" do
|
|
160
|
+
pipe = described_class.new(tree: tree, response: nt_create_andx_response, name: "\\#{endpoint.to_s}")
|
|
161
|
+
expect(pipe).to be_a klass
|
|
162
|
+
end
|
|
156
163
|
end
|
|
157
164
|
end
|
|
158
165
|
end
|
|
@@ -238,8 +245,7 @@ RSpec.describe RubySMB::SMB1::Pipe do
|
|
|
238
245
|
|
|
239
246
|
context 'when the response is not a Trans packet' do
|
|
240
247
|
it 'raises an InvalidPacket exception' do
|
|
241
|
-
allow(trans_nmpipe_response).to
|
|
242
|
-
allow(trans_nmpipe_response).to receive_message_chain(:smb_header, :command)
|
|
248
|
+
allow(trans_nmpipe_response).to receive(:packet_smb_version)
|
|
243
249
|
allow(trans_nmpipe_response).to receive(:valid?).and_return(false)
|
|
244
250
|
expect { pipe.dcerpc_request(stub_packet, options) }.to raise_error(RubySMB::Error::InvalidPacket)
|
|
245
251
|
end
|
|
@@ -492,4 +492,26 @@ RSpec.describe RubySMB::SMB1::Tree do
|
|
|
492
492
|
end
|
|
493
493
|
end
|
|
494
494
|
|
|
495
|
+
describe '#open_pipe' do
|
|
496
|
+
let(:opts) { { filename: 'test', write: true } }
|
|
497
|
+
before :example do
|
|
498
|
+
allow(tree).to receive(:open_file)
|
|
499
|
+
end
|
|
500
|
+
|
|
501
|
+
it 'calls #open_file with the provided options' do
|
|
502
|
+
opts[:filename] ='\\test'
|
|
503
|
+
expect(tree).to receive(:open_file).with(opts)
|
|
504
|
+
tree.open_pipe(**opts)
|
|
505
|
+
end
|
|
506
|
+
|
|
507
|
+
it 'prepends the filename with \\ if needed' do
|
|
508
|
+
expect(tree).to receive(:open_file).with(filename: '\\test', write: true)
|
|
509
|
+
tree.open_pipe(**opts)
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
it 'does not modify the original option hash' do
|
|
513
|
+
tree.open_pipe(**opts)
|
|
514
|
+
expect(opts).to eq( { filename: 'test', write: true } )
|
|
515
|
+
end
|
|
516
|
+
end
|
|
495
517
|
end
|