ruby_smb 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
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