ruby_smb 0.0.8

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.
Files changed (102) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/.gitignore +21 -0
  4. data/.rspec +3 -0
  5. data/.simplecov +42 -0
  6. data/.travis.yml +5 -0
  7. data/.yardopts +1 -0
  8. data/CONTRIBUTING.md +119 -0
  9. data/Gemfile +13 -0
  10. data/LICENSE.txt +18 -0
  11. data/README.md +64 -0
  12. data/Rakefile +22 -0
  13. data/examples/authenticate.rb +30 -0
  14. data/examples/negotiate.rb +25 -0
  15. data/lib/ruby_smb/client/authentication.rb +236 -0
  16. data/lib/ruby_smb/client/negotiation.rb +126 -0
  17. data/lib/ruby_smb/client/signing.rb +48 -0
  18. data/lib/ruby_smb/client.rb +164 -0
  19. data/lib/ruby_smb/dispatcher/base.rb +18 -0
  20. data/lib/ruby_smb/dispatcher/socket.rb +53 -0
  21. data/lib/ruby_smb/dispatcher.rb +4 -0
  22. data/lib/ruby_smb/error.rb +17 -0
  23. data/lib/ruby_smb/field/file_time.rb +62 -0
  24. data/lib/ruby_smb/field/nt_status.rb +16 -0
  25. data/lib/ruby_smb/field/stringz16.rb +55 -0
  26. data/lib/ruby_smb/field.rb +7 -0
  27. data/lib/ruby_smb/generic_packet.rb +179 -0
  28. data/lib/ruby_smb/gss.rb +109 -0
  29. data/lib/ruby_smb/smb1/andx_block.rb +13 -0
  30. data/lib/ruby_smb/smb1/bit_field/capabilities.rb +39 -0
  31. data/lib/ruby_smb/smb1/bit_field/header_flags.rb +19 -0
  32. data/lib/ruby_smb/smb1/bit_field/header_flags2.rb +27 -0
  33. data/lib/ruby_smb/smb1/bit_field/security_mode.rb +16 -0
  34. data/lib/ruby_smb/smb1/bit_field.rb +10 -0
  35. data/lib/ruby_smb/smb1/commands.rb +9 -0
  36. data/lib/ruby_smb/smb1/data_block.rb +42 -0
  37. data/lib/ruby_smb/smb1/dialect.rb +11 -0
  38. data/lib/ruby_smb/smb1/packet/error_packet.rb +14 -0
  39. data/lib/ruby_smb/smb1/packet/negotiate_request.rb +52 -0
  40. data/lib/ruby_smb/smb1/packet/negotiate_response.rb +46 -0
  41. data/lib/ruby_smb/smb1/packet/negotiate_response_extended.rb +47 -0
  42. data/lib/ruby_smb/smb1/packet/session_setup_request.rb +71 -0
  43. data/lib/ruby_smb/smb1/packet/session_setup_response.rb +48 -0
  44. data/lib/ruby_smb/smb1/packet.rb +12 -0
  45. data/lib/ruby_smb/smb1/parameter_block.rb +42 -0
  46. data/lib/ruby_smb/smb1/smb_header.rb +21 -0
  47. data/lib/ruby_smb/smb1.rb +16 -0
  48. data/lib/ruby_smb/smb2/bit_field/session_flags.rb +17 -0
  49. data/lib/ruby_smb/smb2/bit_field/smb2_capabailities.rb +23 -0
  50. data/lib/ruby_smb/smb2/bit_field/smb2_header_flags.rb +23 -0
  51. data/lib/ruby_smb/smb2/bit_field/smb2_security_mode.rb +15 -0
  52. data/lib/ruby_smb/smb2/bit_field/smb2_security_mode_single.rb +14 -0
  53. data/lib/ruby_smb/smb2/bit_field.rb +11 -0
  54. data/lib/ruby_smb/smb2/commands.rb +25 -0
  55. data/lib/ruby_smb/smb2/packet/negotiate_request.rb +50 -0
  56. data/lib/ruby_smb/smb2/packet/negotiate_response.rb +33 -0
  57. data/lib/ruby_smb/smb2/packet/session_setup_request.rb +53 -0
  58. data/lib/ruby_smb/smb2/packet/session_setup_response.rb +38 -0
  59. data/lib/ruby_smb/smb2/packet.rb +10 -0
  60. data/lib/ruby_smb/smb2/smb2_header.rb +22 -0
  61. data/lib/ruby_smb/smb2.rb +12 -0
  62. data/lib/ruby_smb/version.rb +3 -0
  63. data/lib/ruby_smb.rb +22 -0
  64. data/ruby_smb.gemspec +38 -0
  65. data/spec/lib/ruby_smb/client_spec.rb +638 -0
  66. data/spec/lib/ruby_smb/dispatcher/dispatcher_base_spec.rb +22 -0
  67. data/spec/lib/ruby_smb/dispatcher/socket_spec.rb +60 -0
  68. data/spec/lib/ruby_smb/field/file_time_spec.rb +59 -0
  69. data/spec/lib/ruby_smb/field/nt_status_spec.rb +19 -0
  70. data/spec/lib/ruby_smb/field/stringz16_spec.rb +50 -0
  71. data/spec/lib/ruby_smb/generic_packet_spec.rb +58 -0
  72. data/spec/lib/ruby_smb/smb1/andx_block_spec.rb +41 -0
  73. data/spec/lib/ruby_smb/smb1/bit_field/capabilities_spec.rb +245 -0
  74. data/spec/lib/ruby_smb/smb1/bit_field/header_flags2_spec.rb +146 -0
  75. data/spec/lib/ruby_smb/smb1/bit_field/header_flags_spec.rb +102 -0
  76. data/spec/lib/ruby_smb/smb1/bit_field/security_mode_spec.rb +44 -0
  77. data/spec/lib/ruby_smb/smb1/data_block_spec.rb +26 -0
  78. data/spec/lib/ruby_smb/smb1/dialect_spec.rb +26 -0
  79. data/spec/lib/ruby_smb/smb1/packet/error_packet_spec.rb +39 -0
  80. data/spec/lib/ruby_smb/smb1/packet/negotiate_request_spec.rb +77 -0
  81. data/spec/lib/ruby_smb/smb1/packet/negotiate_response_extended_spec.rb +149 -0
  82. data/spec/lib/ruby_smb/smb1/packet/negotiate_response_spec.rb +150 -0
  83. data/spec/lib/ruby_smb/smb1/packet/session_setup_request_spec.rb +100 -0
  84. data/spec/lib/ruby_smb/smb1/packet/session_setup_response_spec.rb +72 -0
  85. data/spec/lib/ruby_smb/smb1/parameter_block_spec.rb +26 -0
  86. data/spec/lib/ruby_smb/smb1/smb_header_spec.rb +96 -0
  87. data/spec/lib/ruby_smb/smb2/bit_field/header_flags_spec.rb +81 -0
  88. data/spec/lib/ruby_smb/smb2/bit_field/session_flags_spec.rb +28 -0
  89. data/spec/lib/ruby_smb/smb2/bit_field/smb2_capabilities_spec.rb +72 -0
  90. data/spec/lib/ruby_smb/smb2/bit_field/smb_secruity_mode_spec.rb +22 -0
  91. data/spec/lib/ruby_smb/smb2/packet/negotiate_request_spec.rb +122 -0
  92. data/spec/lib/ruby_smb/smb2/packet/negotiate_response_spec.rb +147 -0
  93. data/spec/lib/ruby_smb/smb2/packet/session_setup_request_spec.rb +79 -0
  94. data/spec/lib/ruby_smb/smb2/packet/session_setup_response_spec.rb +54 -0
  95. data/spec/lib/ruby_smb/smb2/smb2_header_spec.rb +127 -0
  96. data/spec/lib/ruby_smb_spec.rb +2 -0
  97. data/spec/spec_helper.rb +100 -0
  98. data/spec/support/mock_socket_dispatcher.rb +8 -0
  99. data/spec/support/shared/examples/bit_field_single_flag.rb +14 -0
  100. data.tar.gz.sig +0 -0
  101. metadata +384 -0
  102. metadata.gz.sig +0 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 203527ee7c807b85b3af96aea81bdc9f543b5f16
4
+ data.tar.gz: f80aa766405b6b813a5ac9a65aca3778d24f20a0
5
+ SHA512:
6
+ metadata.gz: 79add85ae366057d7c77cafa684c6c3d6e842777bbf161d768dd8e206a344f712fc3cf5684a0d625c77162e1a07f8dcb7e43bf92292b9fedd0bfd8169a873375
7
+ data.tar.gz: 5866aa5f7aed28b0dfa8b3c147434ebefe6a6e4964618ba7d4762349f5090e826c1461950ec79a53fc52074f75eb99abc8b6a488d9901f2701b537c28aec5601
checksums.yaml.gz.sig ADDED
Binary file
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /.idea/
4
+ /Gemfile.lock
5
+ /_yardoc/
6
+ /coverage/
7
+ /doc/
8
+ /pkg/
9
+ /spec/reports/
10
+ /tmp/
11
+ *.bundle
12
+ *.so
13
+ *.o
14
+ *.a
15
+ mkmf.log
16
+ *.gem
17
+ /tags
18
+
19
+ # RVM control
20
+ .ruby-version
21
+ .ruby-gemset
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.simplecov ADDED
@@ -0,0 +1,42 @@
1
+ # RM_INFO is set when using Rubymine. In Rubymine, starting SimpleCov is
2
+ # controlled by running with coverage, so don't explicitly start coverage (and
3
+ # therefore generate a report) when in Rubymine. This _will_ generate a report
4
+ # whenever `rake spec` is run.
5
+ unless ENV['RM_INFO']
6
+ SimpleCov.start
7
+ end
8
+
9
+ SimpleCov.configure do
10
+ # ignore this file
11
+ add_filter '.simplecov'
12
+
13
+ # Rake tasks aren't tested with rspec
14
+ add_filter 'Rakefile'
15
+ add_filter 'lib/tasks'
16
+
17
+ #
18
+ # Changed Files in Git Group
19
+ # @see http://fredwu.me/post/35625566267/simplecov-test-coverage-for-changed-files-only
20
+ #
21
+
22
+ untracked = `git ls-files --exclude-standard --others`
23
+ unstaged = `git diff --name-only`
24
+ staged = `git diff --name-only --cached`
25
+ all = untracked + unstaged + staged
26
+ changed_filenames = all.split("\n")
27
+
28
+ add_group 'Changed' do |source_file|
29
+ changed_filenames.detect { |changed_filename|
30
+ source_file.filename.end_with?(changed_filename)
31
+ }
32
+ end
33
+
34
+ add_group 'Libraries', 'lib'
35
+
36
+ #
37
+ # Specs are reported on to ensure that all examples are being run and all
38
+ # lets, befores, afters, etc are being used.
39
+ #
40
+
41
+ add_group 'Specs', 'spec'
42
+ end
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ sudo: false
3
+ rvm:
4
+ - '2.2'
5
+ - 'jruby-9000'
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ -m markdown
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,119 @@
1
+ # Contributing
2
+
3
+ ## Forking
4
+
5
+ [Fork this repository](https://github.com/rapid7/smb2/fork)
6
+
7
+ ## Branching
8
+
9
+ Branch names follow the format `TYPE/ISSUE/SUMMARY`. You can create it with `git checkout -b TYPE/ISSUE/SUMMARY`.
10
+
11
+ ### `TYPE`
12
+
13
+ `TYPE` can be `bug`, `chore`, or `feature`.
14
+
15
+ ### `ISSUE`
16
+
17
+ `ISSUE` is either a [Github issue](https://github.com/rapid7/smb2/issues) or an issue from some other
18
+ issue tracking software.
19
+
20
+ ### `SUMMARY`
21
+
22
+ `SUMMARY` is is short summary of the purpose of the branch composed of lower case words separated by '-' so that it is a valid `PRERELEASE` for the Gem version.
23
+
24
+ ## Changes
25
+
26
+ ### `PRERELEASE`
27
+
28
+ 1. Update `PRERELEASE` to match the `SUMMARY` in the branch name. If you branched from `master`, and [version.rb](lib/ruby_smb/version.rb) does not have `PRERELEASE` defined, then adding the following lines after `PATCH`:
29
+ ```
30
+ # The prerelease version, scoped to the {MAJOR}, {MINOR}, and {PATCH} version number.
31
+ PRERELEASE = '<SUMMARY>'
32
+ ```
33
+ 2. `rake spec`
34
+ 3. Verify the specs pass, which indicates that `PRERELEASE` was updated correctly.
35
+ 4. Commit the change `git commit -a`
36
+
37
+ ### Your changes
38
+
39
+ Make your changes or however many commits you like, committing each with `git commit`.
40
+
41
+ ### Pre-Pull Request Testing
42
+
43
+ 1. Run specs one last time before opening the Pull Request: `rake spec`
44
+ 2. Verify there was no failures.
45
+
46
+ ### Push
47
+
48
+ Push your branch to your fork on gitub: `git push TYPE/ISSUE/SUMMARY`
49
+
50
+ ### Pull Request
51
+
52
+ * [Create new Pull Request](https://github.com/rapid7/smb2/compare/)
53
+ * Add a Verification Steps to the description comment
54
+
55
+ ```
56
+ # Verification Steps
57
+
58
+ - [ ] `bundle install`
59
+
60
+ ## `rake spec`
61
+ - [ ] `rake spec`
62
+ - [ ] VERIFY no failures
63
+ ```
64
+
65
+ You should also include at least one scenario to manually check the changes outside of specs.
66
+
67
+ * Add a Post-merge Steps comment
68
+
69
+ The 'Post-merge Steps' are a reminder to the reviewer of the Pull Request of how to update the [`PRERELEASE`](lib/windows_error/version.rb) so that [version_spec.rb](spec/lib/windows_error/version.rb_spec.rb) passes on the target branch after the merge.
70
+
71
+ DESTINATION is the name of the destination branch into which the merge is being made. SOURCE_SUMMARY is the SUMMARY from TYPE/ISSUE/SUMMARY branch name for the SOURCE branch that is being made.
72
+
73
+ When merging to `master`:
74
+
75
+ ```
76
+ # Post-merge Steps
77
+
78
+ Perform these steps prior to pushing to master or the build will be broke on master.
79
+
80
+ ## Version
81
+ - [ ] Edit `lib/ruby_smb/version.rb`
82
+ - [ ] Remove `PRERELEASE` and its comment as `PRERELEASE` is not defined on master.
83
+
84
+ ## Gem build
85
+ - [ ] gem build *.gemspec
86
+ - [ ] VERIFY the gem has no '.pre' version suffix.
87
+
88
+ ## RSpec
89
+ - [ ] `rake spec`
90
+ - [ ] VERIFY version examples pass without failures
91
+
92
+ ## Commit & Push
93
+ - [ ] `git commit -a`
94
+ - [ ] `git push origin master`
95
+ ```
96
+
97
+ When merging to DESTINATION other than `master`:
98
+
99
+ ```
100
+ # Post-merge Steps
101
+
102
+ Perform these steps prior to pushing to DESTINATION or the build will be broke on DESTINATION.
103
+
104
+ ## Version
105
+ - [ ] Edit `lib/windows_error/version.rb`
106
+ - [ ] Change `PRERELEASE` from `SOURCE_SUMMARY` to `DESTINATION_SUMMARY` to match the branch (DESTINATION) summary (DESTINATION_SUMMARY)
107
+
108
+ ## Gem build
109
+ - [ ] gem build windows_error.gemspec
110
+ - [ ] VERIFY the prerelease suffix has change on the gem.
111
+
112
+ ## RSpec
113
+ - [ ] `rake spec`
114
+ - [ ] VERIFY version examples pass without failures
115
+
116
+ ## Commit & Push
117
+ - [ ] `git commit -a`
118
+ - [ ] `git push origin DESTINATION`
119
+ ```
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ gem 'pry'
5
+
6
+ group :test do
7
+ # simplecov test formatter and uploader for Coveralls.io
8
+ gem 'coveralls', require: false
9
+ # Testing
10
+ gem 'rspec'
11
+ # Coverage reports
12
+ gem 'simplecov', require: false
13
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,18 @@
1
+ Copyright 2014, Rapid7, Inc.
2
+
3
+ License: BSD-3-clause
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ * Redistributions of source code must retain the above copyright notice,
9
+ this list of conditions and the following disclaimer.
10
+
11
+ * Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+
15
+ * Neither the name of the copyright holder nor the names of its contributors
16
+ may be used to endorse or promote products derived from this software
17
+ without specific prior written permission.
18
+
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # RubySMB
2
+
3
+ [![Build Status](https://travis-ci.org/rapid7/ruby_smb.svg?branch=master)](https://travis-ci.org/rapid7/ruby_smb)
4
+ [![Code Climate](https://codeclimate.com/github/rapid7/ruby_smb.png)](https://codeclimate.com/github/rapid7/ruby_smb)
5
+ [![Coverage Status](https://coveralls.io/repos/github/rapid7/ruby_smb/badge.svg?branch=master)](https://coveralls.io/github/rapid7/ruby_smb?branch=master)
6
+
7
+ A packet parsing and manipulation library for the SMB family of protocols.
8
+
9
+ See Microsoft's [[MS-SMB2]](http://msdn.microsoft.com/en-us/library/cc246482.aspx)
10
+
11
+ It supports authentication via NTLM using the [ruby ntlm gem](https://rubygems.org/gems/rubyntlm)
12
+
13
+ ## Installation
14
+
15
+ This gem has not yet been released, but when it is, do this:
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ ```ruby
20
+ gem 'ruby_smb'
21
+ ```
22
+
23
+ And then execute:
24
+
25
+ $ bundle
26
+
27
+ Or install it yourself as:
28
+
29
+ $ gem install ruby_smb
30
+
31
+ ## Usage
32
+
33
+ Updated Usage Docs coming soon
34
+
35
+ ## Developer tips
36
+ You'll want to have Wireshark and perhaps a tool like Impacket (which provides a small SMB client in one of its examples) installed to help with your work:
37
+
38
+ ### Wireshark
39
+ - `sudo apt-get install wireshark`
40
+ - `sudo dpkg-reconfigure wireshark-common`
41
+ - `sudo addgroup wireshark`
42
+ - `sudo usermod -a -G wireshark <USERNAME>`
43
+
44
+ ### Impacket
45
+ - `sudo apt-get install python-setuptools`
46
+ - `sudo easy_install pyasn1 pycrypto`
47
+ - Download from GitHub (https://github.com/coresecurity/impacket)
48
+ - `sudo python setup.py install`
49
+ - `cd examples && python smbclient.py <USER>:<PASS>@<WINDOWS HOST IP>`
50
+
51
+
52
+
53
+ ## License
54
+
55
+ `ruby_smb` is released under a 3-clause BSD license. See [LICENSE.txt](LICENSE.txt) for full text.
56
+
57
+
58
+ ## Contributing
59
+
60
+ 1. Fork it ( https://github.com/rapid7/smb2/fork )
61
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
62
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
63
+ 4. Push to the branch (`git push origin my-new-feature`)
64
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,22 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ require 'yard'
6
+ require 'yard/rake/yardoc_task'
7
+
8
+ RSpec::Core::RakeTask.new(:spec)
9
+
10
+ YARD::Rake::YardocTask.new do |t|
11
+ t.options = [
12
+ '-m', 'markdown'
13
+ ]
14
+ t.options += Dir.glob('yard_extensions/*.rb').flat_map { |e| ['-e', e] }
15
+ t.files = [
16
+ 'lib/**/*.rb',
17
+ '-',
18
+ 'README.md', 'LICENSE.txt'
19
+ ]
20
+ end
21
+
22
+ task default: :spec
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This script tests a full Authentication/Session Setup cycle
4
+ # including protocol negotiation and authentication.
5
+
6
+ require 'bundler/setup'
7
+ require 'ruby_smb'
8
+
9
+
10
+ def run_authentication(address, smb1, smb2, username, password)
11
+ # Create our socket and add it to the dispatcher
12
+ sock = TCPSocket.new address, 445
13
+ dispatcher = RubySMB::Dispatcher::Socket.new(sock)
14
+
15
+ client = RubySMB::Client.new(dispatcher, smb1: smb1, smb2: smb2, username: username, password: password)
16
+ protocol = client.negotiate
17
+ status = client.authenticate
18
+ puts "#{protocol} : #{status}"
19
+ end
20
+
21
+ address = ARGV[0]
22
+ username = ARGV[1]
23
+ password = ARGV[2]
24
+
25
+ # Negotiate with both SMB1 and SMB2 enabled on the client
26
+ run_authentication(address, true, true, username, password)
27
+ # Negotiate with only SMB1 enabled
28
+ run_authentication(address, true, false, username, password)
29
+ # Negotiate with only SMB2 enabled
30
+ run_authentication(address, false, true, username, password)
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/ruby
2
+
3
+ #
4
+ # This script is for testing the Protocol Negotiation in the library
5
+ # without any other parts.
6
+
7
+ require 'bundler/setup'
8
+ require 'ruby_smb'
9
+
10
+
11
+ def run_negotiation(address, smb1, smb2)
12
+ # Create our socket and add it to the dispatcher
13
+ sock = TCPSocket.new address, 445
14
+ dispatcher = RubySMB::Dispatcher::Socket.new(sock)
15
+
16
+ client = RubySMB::Client.new(dispatcher, smb1: smb1, smb2: smb2, username: 'msfadmin', password: 'msfadmin')
17
+ client.negotiate
18
+ end
19
+
20
+ # Negotiate with both SMB1 and SMB2 enabled on the client
21
+ run_negotiation(ARGV[0], true, true)
22
+ # Negotiate with only SMB1 enabled
23
+ run_negotiation(ARGV[0], true, false)
24
+ # Negotiate with only SMB2 enabled
25
+ run_negotiation(ARGV[0], false, true)
@@ -0,0 +1,236 @@
1
+ module RubySMB
2
+ class Client
3
+ # This module holds all the backend client methods for authentication.
4
+ module Authentication
5
+
6
+ # Responsible for handling Authentication and Session Setup for
7
+ # the SMB Client. It returns the final Status code from the authentication
8
+ # exchange.
9
+ #
10
+ # @return [WindowsError::NTStatus] the NTStatus object from the SessionSetup exchange.
11
+ def authenticate
12
+ if self.smb1
13
+ smb1_authenticate
14
+ else
15
+ smb2_authenticate
16
+ end
17
+ end
18
+
19
+ #
20
+ # SMB1 Methods
21
+ #
22
+
23
+ # Handles the SMB1 NTLMSSP 4-way handshake for Authentication
24
+ def smb1_authenticate
25
+ response = smb1_ntlmssp_negotiate
26
+ challenge_packet = smb1_ntlmssp_challenge_packet(response)
27
+ user_id = challenge_packet.smb_header.uid
28
+ challenge_message = smb1_type2_message(challenge_packet)
29
+ raw = smb1_ntlmssp_authenticate(challenge_message, user_id)
30
+ response = smb1_ntlmssp_final_packet(raw)
31
+ response_code = response.status_code
32
+ self.user_id = user_id if response_code.name == "STATUS_SUCCESS"
33
+ response_code
34
+ end
35
+
36
+ # Sends the {RubySMB::SMB1::Packet::SessionSetupRequest} packet and
37
+ # receives the response.
38
+ #
39
+ # @return [String] the binary string response from the server
40
+ def smb1_ntlmssp_negotiate
41
+ packet = smb1_ntlmssp_negotiate_packet
42
+ send_recv(packet)
43
+ end
44
+
45
+ # Takes the Base64 encoded NTLM Type 2 (Challenge) message
46
+ # and calls the routines to build the Auth packet, sends the packet
47
+ # and receives the raw response
48
+ #
49
+ # @param type2_string [String] the Base64 Encoded NTLM Type 2 message
50
+ # @param user_id [Integer] the temporary user ID from the Type 2 response
51
+ # @return [String] the raw binary response from the server
52
+ def smb1_ntlmssp_authenticate(type2_string,user_id)
53
+ packet = smb1_ntlmssp_auth_packet(type2_string,user_id)
54
+ send_recv(packet)
55
+ end
56
+
57
+ # Generates the {RubySMB::SMB1::Packet::SessionSetupRequest} packet
58
+ # with the NTLM Type 3 (Auth) message in the security_blob field.
59
+ #
60
+ # @param type2_string [String] the Base64 encoded Type2 challenge to respond to
61
+ # @param user_id [Integer] the temporary user ID from the Type 2 response
62
+ # @return [RubySMB::SMB1::Packet::SessionSetupRequest] the second authentication packet to send
63
+ def smb1_ntlmssp_auth_packet(type2_string,user_id)
64
+ type3_message = ntlm_client.init_context(type2_string)
65
+ self.session_key = ntlm_client.session_key
66
+ packet = RubySMB::SMB1::Packet::SessionSetupRequest.new
67
+ packet.smb_header.uid = user_id
68
+ packet.set_type3_blob(type3_message.serialize)
69
+ packet.parameter_block.max_buffer_size = 4356
70
+ packet.parameter_block.max_mpx_count = 50
71
+ packet.smb_header.flags2.extended_security = 1
72
+ packet
73
+ end
74
+
75
+ # Creates the {RubySMB::SMB1::Packet::SessionSetupRequest} packet
76
+ # for the first part of the NTLMSSP 4-way hnadshake. This packet
77
+ # initializes negotiations for the NTLMSSP authentication
78
+ #
79
+ # @return [RubySMB::SMB1::Packet::SessionSetupRequest] the first authentication packet to send
80
+ def smb1_ntlmssp_negotiate_packet
81
+ type1_message = ntlm_client.init_context
82
+ packet = RubySMB::SMB1::Packet::SessionSetupRequest.new
83
+ packet.set_type1_blob(type1_message.serialize)
84
+ packet.parameter_block.max_buffer_size = 4356
85
+ packet.parameter_block.max_mpx_count = 50
86
+ packet.smb_header.flags2.extended_security = 1
87
+ packet
88
+ end
89
+
90
+ # Takes the raw binary string and returns a {RubySMB::SMB1::Packet::SessionSetupResponse}
91
+ def smb1_ntlmssp_final_packet(raw_response)
92
+ begin
93
+ packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response)
94
+ rescue
95
+ packet = RubySMB::SMB1::Packet::ErrorPacket.read(raw_response)
96
+ end
97
+
98
+ unless packet.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
99
+ raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb_header.command} and not #{RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP}"
100
+ end
101
+ packet
102
+ end
103
+
104
+ # Takes the raw binary string and returns a {RubySMB::SMB1::Packet::SessionSetupResponse}
105
+ def smb1_ntlmssp_challenge_packet(raw_response)
106
+ packet = RubySMB::SMB1::Packet::SessionSetupResponse.read(raw_response)
107
+ status_code = packet.status_code
108
+
109
+ unless status_code.name == "STATUS_MORE_PROCESSING_REQUIRED"
110
+ raise RubySMB::Error::UnexpectedStatusCode, status_code.to_s
111
+ end
112
+
113
+ unless packet.smb_header.command == RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP
114
+ raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb_header.command} and not #{RubySMB::SMB1::Commands::SMB_COM_SESSION_SETUP}"
115
+ end
116
+ packet
117
+ end
118
+
119
+ # Parses out the NTLM Type 2 Message from a {RubySMB::SMB1::Packet::SessionSetupResponse}
120
+ #
121
+ # @param response_packet [RubySMB::SMB1::Packet::SessionSetupResponse] the response packet to get the NTLM challenge from
122
+ # @return [String] the base64 encoded NTLM Challenge (Type2 Message) from the response
123
+ def smb1_type2_message(response_packet)
124
+ sec_blob = response_packet.data_block.security_blob
125
+ ntlmssp_offset = sec_blob.index("NTLMSSP")
126
+ type2_blob = sec_blob.slice(ntlmssp_offset..-1)
127
+ [type2_blob].pack("m")
128
+ end
129
+
130
+ #
131
+ # SMB 2 Methods
132
+ #
133
+
134
+ # Handles the SMB1 NTLMSSP 4-way handshake for Authentication
135
+ def smb2_authenticate
136
+ response = smb2_ntlmssp_negotiate
137
+ challenge_packet = smb2_ntlmssp_challenge_packet(response)
138
+ session_id = challenge_packet.smb2_header.session_id
139
+ challenge_message = smb2_type2_message(challenge_packet)
140
+ raw = smb2_ntlmssp_authenticate(challenge_message, session_id)
141
+ response = smb2_ntlmssp_final_packet(raw)
142
+ response_code = response.status_code
143
+ self.session_id = response.smb2_header.session_id if response_code.name == "STATUS_SUCCESS"
144
+ response_code
145
+ end
146
+
147
+ # Takes the raw binary string and returns a {RubySMB::SMB2::Packet::SessionSetupResponse}
148
+ def smb2_ntlmssp_final_packet(raw_response)
149
+ packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response)
150
+ unless packet.smb2_header.command == RubySMB::SMB2::Commands::SESSION_SETUP
151
+ raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb2_header.command} and not #{RubySMB::SMB2::Commands::SESSION_SETUP}"
152
+ end
153
+ packet
154
+ end
155
+
156
+ # Takes the raw binary string and returns a {RubySMB::SMB2::Packet::SessionSetupResponse}
157
+ def smb2_ntlmssp_challenge_packet(raw_response)
158
+ packet = RubySMB::SMB2::Packet::SessionSetupResponse.read(raw_response)
159
+ status_code = packet.status_code
160
+ unless status_code.name == "STATUS_MORE_PROCESSING_REQUIRED"
161
+ raise RubySMB::Error::UnexpectedStatusCode, status_code.to_s
162
+ end
163
+
164
+ unless packet.smb2_header.command == RubySMB::SMB2::Commands::SESSION_SETUP
165
+ raise RubySMB::Error::InvalidPacket, "Command was #{packet.smb2_header.command} and not #{RubySMB::SMB2::Commands::SESSION_SETUP}"
166
+ end
167
+ packet
168
+ end
169
+
170
+ # Sends the {RubySMB::SMB2::Packet::SessionSetupRequest} packet and
171
+ # receives the response.
172
+ #
173
+ # @return [String] the binary string response from the server
174
+ def smb2_ntlmssp_negotiate
175
+ packet = smb2_ntlmssp_negotiate_packet
176
+ send_recv(packet)
177
+ end
178
+
179
+ # Creates the {RubySMB::SMB2::Packet::SessionSetupRequest} packet
180
+ # for the first part of the NTLMSSP 4-way handshake. This packet
181
+ # initializes negotiations for the NTLMSSP authentication
182
+ #
183
+ # @return [RubySMB::SMB2::Packet::SessionSetupRequest] the first authentication packet to send
184
+ def smb2_ntlmssp_negotiate_packet
185
+ type1_message = ntlm_client.init_context
186
+ packet = RubySMB::SMB2::Packet::SessionSetupRequest.new
187
+ packet.set_type1_blob(type1_message.serialize)
188
+ packet.smb2_header.message_id = 1 #self.smb2_message_id
189
+ self.smb2_message_id = 2
190
+ packet
191
+ end
192
+
193
+ # Parses out the NTLM Type 2 Message from a {RubySMB::SMB2::Packet::SessionSetupResponse}
194
+ #
195
+ # @param response_packet [RubySMB::SMB2::Packet::SessionSetupResponse] the response packet to get the NTLM challenge from
196
+ # @return [String] the base64 encoded NTLM Challenge (Type2 Message) from the response
197
+ def smb2_type2_message(response_packet)
198
+ sec_blob = response_packet.buffer
199
+ ntlmssp_offset = sec_blob.index("NTLMSSP")
200
+ type2_blob = sec_blob.slice(ntlmssp_offset..-1)
201
+ [type2_blob].pack("m")
202
+ end
203
+
204
+ # Takes the Base64 encoded NTLM Type 2 (Challenge) message
205
+ # and calls the routines to build the Auth packet, sends the packet
206
+ # and receives the raw response
207
+ #
208
+ # @param type2_string [String] the Base64 Encoded NTLM Type 2 message
209
+ # @param user_id [Integer] the temporary user ID from the Type 2 response
210
+ # @return [String] the raw binary response from the server
211
+ def smb2_ntlmssp_authenticate(type2_string,user_id)
212
+ packet = smb2_ntlmssp_auth_packet(type2_string,user_id)
213
+ send_recv(packet)
214
+ end
215
+
216
+ # Generates the {RubySMB::SMB2::Packet::SessionSetupRequest} packet
217
+ # with the NTLM Type 3 (Auth) message in the security_blob field.
218
+ #
219
+ # @param type2_string [String] the Base64 encoded Type2 challenge to respond to
220
+ # @param session_id [Integer] the temporary session id from the Type 2 response
221
+ # @return [RubySMB::SMB2::Packet::SessionSetupRequest] the second authentication packet to send
222
+ def smb2_ntlmssp_auth_packet(type2_string, session_id)
223
+ type3_message = ntlm_client.init_context(type2_string)
224
+ self.session_key = ntlm_client.session_key
225
+ packet = RubySMB::SMB2::Packet::SessionSetupRequest.new
226
+ packet.smb2_header.session_id = session_id
227
+ packet.set_type3_blob(type3_message.serialize)
228
+ packet.smb2_header.message_id = self.smb2_message_id
229
+ self.smb2_message_id += 1
230
+ packet
231
+ end
232
+
233
+
234
+ end
235
+ end
236
+ end