rubyntlm 0.5.3 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -3
  3. data/.rspec +2 -2
  4. data/.travis.yml +10 -11
  5. data/CHANGELOG.md +5 -5
  6. data/Gemfile +3 -3
  7. data/LICENSE +19 -19
  8. data/Rakefile +22 -22
  9. data/lib/net/ntlm.rb +266 -263
  10. data/lib/net/ntlm/blob.rb +28 -28
  11. data/lib/net/ntlm/channel_binding.rb +65 -0
  12. data/lib/net/ntlm/client.rb +65 -65
  13. data/lib/net/ntlm/client/session.rb +237 -223
  14. data/lib/net/ntlm/encode_util.rb +49 -49
  15. data/lib/net/ntlm/exceptions.rb +14 -0
  16. data/lib/net/ntlm/field.rb +34 -34
  17. data/lib/net/ntlm/field_set.rb +129 -129
  18. data/lib/net/ntlm/int16_le.rb +25 -25
  19. data/lib/net/ntlm/int32_le.rb +24 -24
  20. data/lib/net/ntlm/int64_le.rb +25 -25
  21. data/lib/net/ntlm/message.rb +129 -129
  22. data/lib/net/ntlm/message/type0.rb +16 -16
  23. data/lib/net/ntlm/message/type1.rb +18 -18
  24. data/lib/net/ntlm/message/type2.rb +102 -102
  25. data/lib/net/ntlm/message/type3.rb +131 -131
  26. data/lib/net/ntlm/security_buffer.rb +47 -47
  27. data/lib/net/ntlm/string.rb +34 -34
  28. data/lib/net/ntlm/target_info.rb +89 -0
  29. data/lib/net/ntlm/version.rb +11 -11
  30. data/rubyntlm.gemspec +28 -28
  31. data/spec/lib/net/ntlm/blob_spec.rb +16 -16
  32. data/spec/lib/net/ntlm/channel_binding_spec.rb +17 -0
  33. data/spec/lib/net/ntlm/client/session_spec.rb +68 -68
  34. data/spec/lib/net/ntlm/client_spec.rb +64 -64
  35. data/spec/lib/net/ntlm/encode_util_spec.rb +16 -16
  36. data/spec/lib/net/ntlm/field_set_spec.rb +33 -33
  37. data/spec/lib/net/ntlm/field_spec.rb +34 -34
  38. data/spec/lib/net/ntlm/int16_le_spec.rb +17 -17
  39. data/spec/lib/net/ntlm/int32_le_spec.rb +18 -18
  40. data/spec/lib/net/ntlm/int64_le_spec.rb +18 -18
  41. data/spec/lib/net/ntlm/message/type0_spec.rb +20 -20
  42. data/spec/lib/net/ntlm/message/type1_spec.rb +131 -131
  43. data/spec/lib/net/ntlm/message/type2_spec.rb +132 -132
  44. data/spec/lib/net/ntlm/message/type3_spec.rb +225 -225
  45. data/spec/lib/net/ntlm/message_spec.rb +16 -16
  46. data/spec/lib/net/ntlm/security_buffer_spec.rb +64 -64
  47. data/spec/lib/net/ntlm/string_spec.rb +72 -72
  48. data/spec/lib/net/ntlm/target_info_spec.rb +76 -0
  49. data/spec/lib/net/ntlm/version_spec.rb +27 -27
  50. data/spec/lib/net/ntlm_spec.rb +127 -127
  51. data/spec/spec_helper.rb +22 -22
  52. data/spec/support/certificates/sha_256_hash.pem +19 -0
  53. data/spec/support/shared/examples/net/ntlm/field_shared.rb +25 -25
  54. data/spec/support/shared/examples/net/ntlm/fieldset_shared.rb +239 -239
  55. data/spec/support/shared/examples/net/ntlm/int_shared.rb +43 -43
  56. data/spec/support/shared/examples/net/ntlm/message_shared.rb +35 -35
  57. metadata +12 -3
@@ -1,17 +1,17 @@
1
- require 'spec_helper'
2
-
3
- describe Net::NTLM::Message do
4
-
5
- fields = []
6
- flags = [
7
- :UNICODE,
8
- :OEM,
9
- :REQUEST_TARGET,
10
- :NTLM,
11
- :ALWAYS_SIGN,
12
- :NTLM2_KEY
13
- ]
14
- it_behaves_like 'a fieldset', fields
15
- it_behaves_like 'a message', flags
16
-
1
+ require 'spec_helper'
2
+
3
+ describe Net::NTLM::Message do
4
+
5
+ fields = []
6
+ flags = [
7
+ :UNICODE,
8
+ :OEM,
9
+ :REQUEST_TARGET,
10
+ :NTLM,
11
+ :ALWAYS_SIGN,
12
+ :NTLM2_KEY
13
+ ]
14
+ it_behaves_like 'a fieldset', fields
15
+ it_behaves_like 'a message', flags
16
+
17
17
  end
@@ -1,64 +1,64 @@
1
- require 'spec_helper'
2
-
3
- describe Net::NTLM::SecurityBuffer do
4
-
5
- fields = [
6
- { :name => :length, :class => Net::NTLM::Int16LE, :value => 0, :active => true },
7
- { :name => :allocated, :class => Net::NTLM::Int16LE, :value => 0, :active => true },
8
- { :name => :offset, :class => Net::NTLM::Int32LE, :value => 0, :active => true },
9
- ]
10
-
11
- it_behaves_like 'a fieldset', fields
12
- it_behaves_like 'a field', 'WORKSTATION', true
13
-
14
-
15
- subject(:domain_security_buffer) do
16
- Net::NTLM::SecurityBuffer.new({
17
- :value => 'WORKSTATION',
18
- :active => true
19
- })
20
- end
21
-
22
- context 'when setting the value directly' do
23
- before(:each) do
24
- domain_security_buffer.value = 'DOMAIN1'
25
- end
26
- it 'should change the value' do
27
- expect(domain_security_buffer.value).to eq('DOMAIN1')
28
- end
29
-
30
- it 'should adjust the length field to the size of the new value' do
31
- expect(domain_security_buffer.length).to eq(7)
32
- end
33
-
34
- it 'should adjust the allocated field to the size of the new value' do
35
- expect(domain_security_buffer.allocated).to eq(7)
36
- end
37
- end
38
-
39
- context '#data_size' do
40
- it 'should return the size of the value if active' do
41
- expect(domain_security_buffer.data_size).to eq(11)
42
- end
43
-
44
- it 'should return 0 if inactive' do
45
- domain_security_buffer.active = false
46
- expect(domain_security_buffer.data_size).to eq(0)
47
- end
48
- end
49
-
50
- context '#parse' do
51
- it 'should read in a properly formatted string' do
52
- # Length of the string is 8
53
- length = "\x08\x00"
54
- # Space allocated is 8
55
- allocated = "\x08\x00"
56
- # The offset that the actual value begins at is also 8
57
- offset = "\x08\x00\x00\x00"
58
- string_to_parse = "#{length}#{allocated}#{offset}FooBarBaz"
59
- expect(domain_security_buffer.parse(string_to_parse)).to eq(8)
60
- expect(domain_security_buffer.value).to eq('FooBarBa')
61
- end
62
-
63
- end
64
- end
1
+ require 'spec_helper'
2
+
3
+ describe Net::NTLM::SecurityBuffer do
4
+
5
+ fields = [
6
+ { :name => :length, :class => Net::NTLM::Int16LE, :value => 0, :active => true },
7
+ { :name => :allocated, :class => Net::NTLM::Int16LE, :value => 0, :active => true },
8
+ { :name => :offset, :class => Net::NTLM::Int32LE, :value => 0, :active => true },
9
+ ]
10
+
11
+ it_behaves_like 'a fieldset', fields
12
+ it_behaves_like 'a field', 'WORKSTATION', true
13
+
14
+
15
+ subject(:domain_security_buffer) do
16
+ Net::NTLM::SecurityBuffer.new({
17
+ :value => 'WORKSTATION',
18
+ :active => true
19
+ })
20
+ end
21
+
22
+ context 'when setting the value directly' do
23
+ before(:each) do
24
+ domain_security_buffer.value = 'DOMAIN1'
25
+ end
26
+ it 'should change the value' do
27
+ expect(domain_security_buffer.value).to eq('DOMAIN1')
28
+ end
29
+
30
+ it 'should adjust the length field to the size of the new value' do
31
+ expect(domain_security_buffer.length).to eq(7)
32
+ end
33
+
34
+ it 'should adjust the allocated field to the size of the new value' do
35
+ expect(domain_security_buffer.allocated).to eq(7)
36
+ end
37
+ end
38
+
39
+ context '#data_size' do
40
+ it 'should return the size of the value if active' do
41
+ expect(domain_security_buffer.data_size).to eq(11)
42
+ end
43
+
44
+ it 'should return 0 if inactive' do
45
+ domain_security_buffer.active = false
46
+ expect(domain_security_buffer.data_size).to eq(0)
47
+ end
48
+ end
49
+
50
+ context '#parse' do
51
+ it 'should read in a properly formatted string' do
52
+ # Length of the string is 8
53
+ length = "\x08\x00"
54
+ # Space allocated is 8
55
+ allocated = "\x08\x00"
56
+ # The offset that the actual value begins at is also 8
57
+ offset = "\x08\x00\x00\x00"
58
+ string_to_parse = "#{length}#{allocated}#{offset}FooBarBaz"
59
+ expect(domain_security_buffer.parse(string_to_parse)).to eq(8)
60
+ expect(domain_security_buffer.value).to eq('FooBarBa')
61
+ end
62
+
63
+ end
64
+ end
@@ -1,72 +1,72 @@
1
- require 'spec_helper'
2
-
3
- describe Net::NTLM::String do
4
-
5
- it_behaves_like 'a field', 'Foo', false
6
-
7
- let(:active) {
8
- Net::NTLM::String.new({
9
- :value => 'Test',
10
- :active => true,
11
- :size => 4
12
- })
13
- }
14
-
15
- let(:inactive) {
16
- Net::NTLM::String.new({
17
- :value => 'Test',
18
- :active => false,
19
- :size => 4
20
- })
21
- }
22
-
23
- context '#serialize' do
24
- it 'should return the value when active' do
25
- expect(active.serialize).to eq('Test')
26
- end
27
-
28
- it 'should return an empty string when inactive' do
29
- expect(inactive.serialize).to eq('')
30
- end
31
-
32
- it 'should coerce non-string values into strings' do
33
- active.value = 15
34
- expect(active.serialize).to eq('15')
35
- end
36
-
37
- it 'should return empty string on a nil' do
38
- active.value = nil
39
- expect(active.serialize).to eq('')
40
- end
41
- end
42
-
43
- context '#value=' do
44
- it 'should set active to false if it empty' do
45
- active.value = ''
46
- expect(active.active).to eq(false)
47
- end
48
-
49
- it 'should adjust the size based on the value set' do
50
- expect(active.size).to eq(4)
51
- active.value = 'Foobar'
52
- expect(active.size).to eq(6)
53
- end
54
- end
55
-
56
- context '#parse' do
57
- it 'should read in a string of the proper size' do
58
- expect(active.parse('tseT')).to eq(4)
59
- expect(active.value).to eq('tseT')
60
- end
61
-
62
- it 'should not read in a string that is too small' do
63
- expect(active.parse('B')).to eq(0)
64
- expect(active.value).to eq('Test')
65
- end
66
-
67
- it 'should be able to read from an offset and only for the given size' do
68
- expect(active.parse('FooBarBaz',3)).to eq(4)
69
- expect(active.value).to eq('BarB')
70
- end
71
- end
72
- end
1
+ require 'spec_helper'
2
+
3
+ describe Net::NTLM::String do
4
+
5
+ it_behaves_like 'a field', 'Foo', false
6
+
7
+ let(:active) {
8
+ Net::NTLM::String.new({
9
+ :value => 'Test',
10
+ :active => true,
11
+ :size => 4
12
+ })
13
+ }
14
+
15
+ let(:inactive) {
16
+ Net::NTLM::String.new({
17
+ :value => 'Test',
18
+ :active => false,
19
+ :size => 4
20
+ })
21
+ }
22
+
23
+ context '#serialize' do
24
+ it 'should return the value when active' do
25
+ expect(active.serialize).to eq('Test')
26
+ end
27
+
28
+ it 'should return an empty string when inactive' do
29
+ expect(inactive.serialize).to eq('')
30
+ end
31
+
32
+ it 'should coerce non-string values into strings' do
33
+ active.value = 15
34
+ expect(active.serialize).to eq('15')
35
+ end
36
+
37
+ it 'should return empty string on a nil' do
38
+ active.value = nil
39
+ expect(active.serialize).to eq('')
40
+ end
41
+ end
42
+
43
+ context '#value=' do
44
+ it 'should set active to false if it empty' do
45
+ active.value = ''
46
+ expect(active.active).to eq(false)
47
+ end
48
+
49
+ it 'should adjust the size based on the value set' do
50
+ expect(active.size).to eq(4)
51
+ active.value = 'Foobar'
52
+ expect(active.size).to eq(6)
53
+ end
54
+ end
55
+
56
+ context '#parse' do
57
+ it 'should read in a string of the proper size' do
58
+ expect(active.parse('tseT')).to eq(4)
59
+ expect(active.value).to eq('tseT')
60
+ end
61
+
62
+ it 'should not read in a string that is too small' do
63
+ expect(active.parse('B')).to eq(0)
64
+ expect(active.value).to eq('Test')
65
+ end
66
+
67
+ it 'should be able to read from an offset and only for the given size' do
68
+ expect(active.parse('FooBarBaz',3)).to eq(4)
69
+ expect(active.value).to eq('BarB')
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ describe Net::NTLM::TargetInfo do
4
+ let(:key1) { Net::NTLM::TargetInfo::MSV_AV_NB_COMPUTER_NAME }
5
+ let(:value1) { 'some data' }
6
+ let(:key2) { Net::NTLM::TargetInfo::MSV_AV_NB_DOMAIN_NAME }
7
+ let(:value2) { 'some other data' }
8
+ let(:data) do
9
+ dt = key1.dup
10
+ dt << [value1.length].pack('S')
11
+ dt << value1
12
+ dt << key2.dup
13
+ dt << [value2.length].pack('S')
14
+ dt << value2
15
+ dt << Net::NTLM::TargetInfo::MSV_AV_EOL
16
+ dt << [0].pack('S')
17
+ dt.force_encoding(Encoding::ASCII_8BIT)
18
+ end
19
+
20
+ subject { Net::NTLM::TargetInfo.new(data) }
21
+
22
+ describe 'invalid data' do
23
+
24
+ context 'invalid pair id' do
25
+ let(:data) { "\xFF\x00" }
26
+
27
+ it 'returns an error' do
28
+ expect{subject}.to raise_error Net::NTLM::InvalidTargetDataError
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '#av_pairs' do
34
+
35
+ it 'returns the pair values with the given keys' do
36
+ expect(subject.av_pairs[key1]).to eq value1
37
+ expect(subject.av_pairs[key2]).to eq value2
38
+ end
39
+
40
+ context "target data is nil" do
41
+ subject { Net::NTLM::TargetInfo.new(nil) }
42
+
43
+ it 'returns the pair values with the given keys' do
44
+ expect(subject.av_pairs).to be_empty
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '#to_s' do
50
+ let(:data) do
51
+ dt = key1.dup
52
+ dt << [value1.length].pack('S')
53
+ dt << value1
54
+ dt << key2.dup
55
+ dt << [value2.length].pack('S')
56
+ dt << value2
57
+ dt.force_encoding(Encoding::ASCII_8BIT)
58
+ end
59
+ let(:new_key) { Net::NTLM::TargetInfo::MSV_AV_CHANNEL_BINDINGS }
60
+ let(:new_value) { 'bindings' }
61
+ let(:new_data) do
62
+ dt = data
63
+ dt << new_key
64
+ dt << [new_value.length].pack('S')
65
+ dt << new_value
66
+ dt << Net::NTLM::TargetInfo::MSV_AV_EOL
67
+ dt << [0].pack('S')
68
+ dt.force_encoding(Encoding::ASCII_8BIT)
69
+ end
70
+
71
+ it 'returns bytes with any new data added' do
72
+ subject.av_pairs[new_key] = new_value
73
+ expect(subject.to_s).to eq new_data
74
+ end
75
+ end
76
+ end
@@ -1,27 +1,27 @@
1
- require 'spec_helper'
2
- require File.expand_path("#{File.dirname(__FILE__)}/../../../../lib/net/ntlm/version")
3
-
4
- describe Net::NTLM::VERSION do
5
-
6
- it 'should contain an integer value for Major Version' do
7
- expect(Net::NTLM::VERSION::MAJOR).to be_an Integer
8
- end
9
-
10
- it 'should contain an integer value for Minor Version' do
11
- expect(Net::NTLM::VERSION::MINOR).to be_an Integer
12
- end
13
-
14
- it 'should contain an integer value for Patch Version' do
15
- expect(Net::NTLM::VERSION::TINY).to be_an Integer
16
- end
17
-
18
- it 'should contain an aggregate version string' do
19
- string = [
20
- Net::NTLM::VERSION::MAJOR,
21
- Net::NTLM::VERSION::MINOR,
22
- Net::NTLM::VERSION::TINY
23
- ].join('.')
24
- expect(Net::NTLM::VERSION::STRING).to be_a String
25
- expect(Net::NTLM::VERSION::STRING).to eq(string)
26
- end
27
- end
1
+ require 'spec_helper'
2
+ require File.expand_path("#{File.dirname(__FILE__)}/../../../../lib/net/ntlm/version")
3
+
4
+ describe Net::NTLM::VERSION do
5
+
6
+ it 'should contain an integer value for Major Version' do
7
+ expect(Net::NTLM::VERSION::MAJOR).to be_an Integer
8
+ end
9
+
10
+ it 'should contain an integer value for Minor Version' do
11
+ expect(Net::NTLM::VERSION::MINOR).to be_an Integer
12
+ end
13
+
14
+ it 'should contain an integer value for Patch Version' do
15
+ expect(Net::NTLM::VERSION::TINY).to be_an Integer
16
+ end
17
+
18
+ it 'should contain an aggregate version string' do
19
+ string = [
20
+ Net::NTLM::VERSION::MAJOR,
21
+ Net::NTLM::VERSION::MINOR,
22
+ Net::NTLM::VERSION::TINY
23
+ ].join('.')
24
+ expect(Net::NTLM::VERSION::STRING).to be_a String
25
+ expect(Net::NTLM::VERSION::STRING).to eq(string)
26
+ end
27
+ end
@@ -1,127 +1,127 @@
1
- require "spec_helper"
2
-
3
- describe Net::NTLM do
4
- let(:passwd) {"SecREt01"}
5
- let(:user) {"user"}
6
- let(:domain) {"DOMAIN"}
7
- let(:challenge) {["0123456789abcdef"].pack("H*")}
8
- let(:client_ch) {["ffffff0011223344"].pack("H*")}
9
- let(:timestamp) {1055844000}
10
- let(:trgt_info) {[
11
- "02000c0044004f004d00410049004e00" +
12
- "01000c00530045005200560045005200" +
13
- "0400140064006f006d00610069006e00" +
14
- "2e0063006f006d000300220073006500" +
15
- "72007600650072002e0064006f006d00" +
16
- "610069006e002e0063006f006d000000" +
17
- "0000"
18
- ].pack("H*")}
19
- let(:padded_pwd) { passwd.upcase.ljust(14, "\0")}
20
- let(:keys) { Net::NTLM.gen_keys(padded_pwd)}
21
-
22
- it 'should convert a value to 64-bit LE Integer' do
23
- expect(Net::NTLM.pack_int64le(42)).to eq("\x2A\x00\x00\x00\x00\x00\x00\x00")
24
- end
25
-
26
- it 'should split a string into an array of slices, 7 chars or less' do
27
- expect(Net::NTLM.split7("HelloWorld!")).to eq([ 'HelloWo', 'rld!'])
28
- end
29
-
30
- it 'should generate DES keys from the supplied string' do
31
- first_key = ["52a2516b252a5161"].pack('H*')
32
- second_key = ["3180010101010101"].pack('H*')
33
- expect(Net::NTLM.gen_keys(padded_pwd)).to eq([first_key, second_key])
34
- end
35
-
36
- it 'should encrypt the string with DES for each key supplied' do
37
- first_crypt = ["ff3750bcc2b22412"].pack('H*')
38
- second_crypt = ["c2265b23734e0dac"].pack('H*')
39
- expect(Net::NTLM::apply_des(Net::NTLM::LM_MAGIC, keys)).to eq([first_crypt, second_crypt])
40
- end
41
-
42
- it 'should generate an lm_hash' do
43
- expect(Net::NTLM::lm_hash(passwd)).to eq(["ff3750bcc2b22412c2265b23734e0dac"].pack("H*"))
44
- end
45
-
46
- it 'should generate an ntlm_hash' do
47
- expect(Net::NTLM::ntlm_hash(passwd)).to eq(["cd06ca7c7e10c99b1d33b7485a2ed808"].pack("H*"))
48
- end
49
-
50
- it 'should generate an ntlmv2_hash' do
51
- expect(Net::NTLM::ntlmv2_hash(user, passwd, domain)).to eq(["04b8e0ba74289cc540826bab1dee63ae"].pack("H*"))
52
- end
53
-
54
- context 'when a user passes an NTLM hash for pass-the-hash' do
55
- let(:passwd) { Net::NTLM::EncodeUtil.encode_utf16le('ff3750bcc2b22412c2265b23734e0dac:cd06ca7c7e10c99b1d33b7485a2ed808') }
56
-
57
- it 'should return the correct ntlmv2 hash' do
58
- expect(Net::NTLM::ntlmv2_hash(user, passwd, domain)).to eq(["04b8e0ba74289cc540826bab1dee63ae"].pack("H*"))
59
- end
60
- end
61
-
62
- it 'should generate an lm_response' do
63
- expect(Net::NTLM::lm_response(
64
- {
65
- :lm_hash => Net::NTLM::lm_hash(passwd),
66
- :challenge => challenge
67
- }
68
- )).to eq(["c337cd5cbd44fc9782a667af6d427c6de67c20c2d3e77c56"].pack("H*"))
69
- end
70
-
71
- it 'should generate an ntlm_response' do
72
- ntlm_hash = Net::NTLM::ntlm_hash(passwd)
73
- expect(Net::NTLM::ntlm_response(
74
- {
75
- :ntlm_hash => ntlm_hash,
76
- :challenge => challenge
77
- }
78
- )).to eq(["25a98c1c31e81847466b29b2df4680f39958fb8c213a9cc6"].pack("H*"))
79
- end
80
-
81
- it 'should generate a lvm2_response' do
82
- expect(Net::NTLM::lmv2_response(
83
- {
84
- :ntlmv2_hash => Net::NTLM::ntlmv2_hash(user, passwd, domain),
85
- :challenge => challenge
86
- },
87
- { :client_challenge => client_ch }
88
- )).to eq(["d6e6152ea25d03b7c6ba6629c2d6aaf0ffffff0011223344"].pack("H*"))
89
- end
90
-
91
- it 'should generate a ntlmv2_response' do
92
- expect(Net::NTLM::ntlmv2_response(
93
- {
94
- :ntlmv2_hash => Net::NTLM::ntlmv2_hash(user, passwd, domain),
95
- :challenge => challenge,
96
- :target_info => trgt_info
97
- },
98
- {
99
- :timestamp => timestamp,
100
- :client_challenge => client_ch
101
- }
102
- )).to eq([
103
- "cbabbca713eb795d04c97abc01ee4983" +
104
- "01010000000000000090d336b734c301" +
105
- "ffffff00112233440000000002000c00" +
106
- "44004f004d00410049004e0001000c00" +
107
- "53004500520056004500520004001400" +
108
- "64006f006d00610069006e002e006300" +
109
- "6f006d00030022007300650072007600" +
110
- "650072002e0064006f006d0061006900" +
111
- "6e002e0063006f006d00000000000000" +
112
- "0000"
113
- ].pack("H*"))
114
- end
115
-
116
- it 'should generate a ntlm2_session' do
117
- session = Net::NTLM::ntlm2_session(
118
- {
119
- :ntlm_hash => Net::NTLM::ntlm_hash(passwd),
120
- :challenge => challenge
121
- },
122
- { :client_challenge => client_ch }
123
- )
124
- expect(session[0]).to eq(["ffffff001122334400000000000000000000000000000000"].pack("H*"))
125
- expect(session[1]).to eq(["10d550832d12b2ccb79d5ad1f4eed3df82aca4c3681dd455"].pack("H*"))
126
- end
127
- end
1
+ require "spec_helper"
2
+
3
+ describe Net::NTLM do
4
+ let(:passwd) {"SecREt01"}
5
+ let(:user) {"user"}
6
+ let(:domain) {"DOMAIN"}
7
+ let(:challenge) {["0123456789abcdef"].pack("H*")}
8
+ let(:client_ch) {["ffffff0011223344"].pack("H*")}
9
+ let(:timestamp) {1055844000}
10
+ let(:trgt_info) {[
11
+ "02000c0044004f004d00410049004e00" +
12
+ "01000c00530045005200560045005200" +
13
+ "0400140064006f006d00610069006e00" +
14
+ "2e0063006f006d000300220073006500" +
15
+ "72007600650072002e0064006f006d00" +
16
+ "610069006e002e0063006f006d000000" +
17
+ "0000"
18
+ ].pack("H*")}
19
+ let(:padded_pwd) { passwd.upcase.ljust(14, "\0")}
20
+ let(:keys) { Net::NTLM.gen_keys(padded_pwd)}
21
+
22
+ it 'should convert a value to 64-bit LE Integer' do
23
+ expect(Net::NTLM.pack_int64le(42)).to eq("\x2A\x00\x00\x00\x00\x00\x00\x00")
24
+ end
25
+
26
+ it 'should split a string into an array of slices, 7 chars or less' do
27
+ expect(Net::NTLM.split7("HelloWorld!")).to eq([ 'HelloWo', 'rld!'])
28
+ end
29
+
30
+ it 'should generate DES keys from the supplied string' do
31
+ first_key = ["52a2516b252a5161"].pack('H*')
32
+ second_key = ["3180010101010101"].pack('H*')
33
+ expect(Net::NTLM.gen_keys(padded_pwd)).to eq([first_key, second_key])
34
+ end
35
+
36
+ it 'should encrypt the string with DES for each key supplied' do
37
+ first_crypt = ["ff3750bcc2b22412"].pack('H*')
38
+ second_crypt = ["c2265b23734e0dac"].pack('H*')
39
+ expect(Net::NTLM::apply_des(Net::NTLM::LM_MAGIC, keys)).to eq([first_crypt, second_crypt])
40
+ end
41
+
42
+ it 'should generate an lm_hash' do
43
+ expect(Net::NTLM::lm_hash(passwd)).to eq(["ff3750bcc2b22412c2265b23734e0dac"].pack("H*"))
44
+ end
45
+
46
+ it 'should generate an ntlm_hash' do
47
+ expect(Net::NTLM::ntlm_hash(passwd)).to eq(["cd06ca7c7e10c99b1d33b7485a2ed808"].pack("H*"))
48
+ end
49
+
50
+ it 'should generate an ntlmv2_hash' do
51
+ expect(Net::NTLM::ntlmv2_hash(user, passwd, domain)).to eq(["04b8e0ba74289cc540826bab1dee63ae"].pack("H*"))
52
+ end
53
+
54
+ context 'when a user passes an NTLM hash for pass-the-hash' do
55
+ let(:passwd) { Net::NTLM::EncodeUtil.encode_utf16le('ff3750bcc2b22412c2265b23734e0dac:cd06ca7c7e10c99b1d33b7485a2ed808') }
56
+
57
+ it 'should return the correct ntlmv2 hash' do
58
+ expect(Net::NTLM::ntlmv2_hash(user, passwd, domain)).to eq(["04b8e0ba74289cc540826bab1dee63ae"].pack("H*"))
59
+ end
60
+ end
61
+
62
+ it 'should generate an lm_response' do
63
+ expect(Net::NTLM::lm_response(
64
+ {
65
+ :lm_hash => Net::NTLM::lm_hash(passwd),
66
+ :challenge => challenge
67
+ }
68
+ )).to eq(["c337cd5cbd44fc9782a667af6d427c6de67c20c2d3e77c56"].pack("H*"))
69
+ end
70
+
71
+ it 'should generate an ntlm_response' do
72
+ ntlm_hash = Net::NTLM::ntlm_hash(passwd)
73
+ expect(Net::NTLM::ntlm_response(
74
+ {
75
+ :ntlm_hash => ntlm_hash,
76
+ :challenge => challenge
77
+ }
78
+ )).to eq(["25a98c1c31e81847466b29b2df4680f39958fb8c213a9cc6"].pack("H*"))
79
+ end
80
+
81
+ it 'should generate a lvm2_response' do
82
+ expect(Net::NTLM::lmv2_response(
83
+ {
84
+ :ntlmv2_hash => Net::NTLM::ntlmv2_hash(user, passwd, domain),
85
+ :challenge => challenge
86
+ },
87
+ { :client_challenge => client_ch }
88
+ )).to eq(["d6e6152ea25d03b7c6ba6629c2d6aaf0ffffff0011223344"].pack("H*"))
89
+ end
90
+
91
+ it 'should generate a ntlmv2_response' do
92
+ expect(Net::NTLM::ntlmv2_response(
93
+ {
94
+ :ntlmv2_hash => Net::NTLM::ntlmv2_hash(user, passwd, domain),
95
+ :challenge => challenge,
96
+ :target_info => trgt_info
97
+ },
98
+ {
99
+ :timestamp => timestamp,
100
+ :client_challenge => client_ch
101
+ }
102
+ )).to eq([
103
+ "cbabbca713eb795d04c97abc01ee4983" +
104
+ "01010000000000000090d336b734c301" +
105
+ "ffffff00112233440000000002000c00" +
106
+ "44004f004d00410049004e0001000c00" +
107
+ "53004500520056004500520004001400" +
108
+ "64006f006d00610069006e002e006300" +
109
+ "6f006d00030022007300650072007600" +
110
+ "650072002e0064006f006d0061006900" +
111
+ "6e002e0063006f006d00000000000000" +
112
+ "0000"
113
+ ].pack("H*"))
114
+ end
115
+
116
+ it 'should generate a ntlm2_session' do
117
+ session = Net::NTLM::ntlm2_session(
118
+ {
119
+ :ntlm_hash => Net::NTLM::ntlm_hash(passwd),
120
+ :challenge => challenge
121
+ },
122
+ { :client_challenge => client_ch }
123
+ )
124
+ expect(session[0]).to eq(["ffffff001122334400000000000000000000000000000000"].pack("H*"))
125
+ expect(session[1]).to eq(["10d550832d12b2ccb79d5ad1f4eed3df82aca4c3681dd455"].pack("H*"))
126
+ end
127
+ end