rubyntlm 0.4.0 → 0.5.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
- data/.rspec +2 -3
- data/README.md +9 -2
- data/Rakefile +8 -0
- data/examples/http.rb +1 -1
- data/lib/net/ntlm.rb +10 -9
- data/lib/net/ntlm/blob.rb +17 -6
- data/lib/net/ntlm/client.rb +61 -0
- data/lib/net/ntlm/client/session.rb +223 -0
- data/lib/net/ntlm/encode_util.rb +2 -2
- data/lib/net/ntlm/field_set.rb +9 -5
- data/lib/net/ntlm/message.rb +23 -9
- data/lib/net/ntlm/message/type1.rb +1 -26
- data/lib/net/ntlm/message/type2.rb +11 -37
- data/lib/net/ntlm/message/type3.rb +77 -14
- data/lib/net/ntlm/version.rb +1 -1
- data/rubyntlm.gemspec +3 -2
- data/spec/lib/net/ntlm/blob_spec.rb +1 -1
- data/spec/lib/net/ntlm/client/session_spec.rb +68 -0
- data/spec/lib/net/ntlm/client_spec.rb +64 -0
- data/spec/lib/net/ntlm/encode_util_spec.rb +3 -3
- data/spec/lib/net/ntlm/field_set_spec.rb +4 -4
- data/spec/lib/net/ntlm/field_spec.rb +5 -5
- data/spec/lib/net/ntlm/message/type1_spec.rb +99 -10
- data/spec/lib/net/ntlm/message/type2_spec.rb +68 -24
- data/spec/lib/net/ntlm/message/type3_spec.rb +207 -2
- data/spec/lib/net/ntlm/security_buffer_spec.rb +8 -8
- data/spec/lib/net/ntlm/string_spec.rb +14 -14
- data/spec/lib/net/ntlm/version_spec.rb +7 -6
- data/spec/lib/net/ntlm_spec.rb +20 -22
- data/spec/spec_helper.rb +1 -2
- data/spec/support/shared/examples/net/ntlm/field_shared.rb +3 -3
- data/spec/support/shared/examples/net/ntlm/fieldset_shared.rb +34 -34
- data/spec/support/shared/examples/net/ntlm/int_shared.rb +8 -8
- data/spec/support/shared/examples/net/ntlm/message_shared.rb +3 -3
- metadata +36 -16
@@ -4,13 +4,13 @@ describe Net::NTLM::EncodeUtil do
|
|
4
4
|
|
5
5
|
context '#encode_utf16le' do
|
6
6
|
it 'should convert an ASCII string to UTF' do
|
7
|
-
Net::NTLM::EncodeUtil.encode_utf16le('Test').
|
7
|
+
expect(Net::NTLM::EncodeUtil.encode_utf16le('Test')).to eq("T\x00e\x00s\x00t\x00")
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
11
|
context '#decode_utf16le' do
|
12
12
|
it 'should convert a UTF string to ASCII' do
|
13
|
-
Net::NTLM::EncodeUtil.decode_utf16le("T\x00e\x00s\x00t\x00").
|
13
|
+
expect(Net::NTLM::EncodeUtil.decode_utf16le("T\x00e\x00s\x00t\x00")).to eq('Test')
|
14
14
|
end
|
15
15
|
end
|
16
|
-
end
|
16
|
+
end
|
@@ -18,16 +18,16 @@ describe Net::NTLM::FieldSet do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'should serialize all the fields' do
|
21
|
-
fieldset_object.serialize.
|
21
|
+
expect(fieldset_object.serialize).to eq('TestFoo')
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'should parse a string across the fields' do
|
25
25
|
fieldset_object.parse('FooBarBaz')
|
26
|
-
fieldset_object.serialize.
|
26
|
+
expect(fieldset_object.serialize).to eq('FooBarB')
|
27
27
|
end
|
28
28
|
|
29
29
|
it 'should return an aggregate size of all the fields' do
|
30
|
-
fieldset_object.size.
|
30
|
+
expect(fieldset_object.size).to eq(7)
|
31
31
|
end
|
32
32
|
end
|
33
|
-
end
|
33
|
+
end
|
@@ -7,12 +7,12 @@ describe Net::NTLM::Field do
|
|
7
7
|
context 'with no size specified' do
|
8
8
|
let (:field_without_size) { Net::NTLM::Field.new({ :value => 'Foo', :active => true }) }
|
9
9
|
it 'should set size to 0 if not active' do
|
10
|
-
field_without_size.size.
|
10
|
+
expect(field_without_size.size).to eq(0)
|
11
11
|
end
|
12
12
|
|
13
13
|
it 'should return 0 if active but no size specified' do
|
14
14
|
field_without_size.active = true
|
15
|
-
field_without_size.size.
|
15
|
+
expect(field_without_size.size).to eq(0)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
@@ -20,15 +20,15 @@ describe Net::NTLM::Field do
|
|
20
20
|
let (:field_with_size) { Net::NTLM::Field.new({ :value => 'Foo', :active => true, :size => 100 }) }
|
21
21
|
|
22
22
|
it 'should return the size provided in the initialize options if active' do
|
23
|
-
field_with_size.size.
|
23
|
+
expect(field_with_size.size).to eq(100)
|
24
24
|
end
|
25
25
|
|
26
26
|
it 'should still return 0 if not active' do
|
27
27
|
field_with_size.active = false
|
28
|
-
field_with_size.size.
|
28
|
+
expect(field_with_size.size).to eq(0)
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
|
33
33
|
|
34
|
-
end
|
34
|
+
end
|
@@ -7,7 +7,7 @@ describe Net::NTLM::Message::Type1 do
|
|
7
7
|
{ :name => :flag, :class => Net::NTLM::Int32LE, :value => Net::NTLM::DEFAULT_FLAGS[:TYPE1], :active => true },
|
8
8
|
{ :name => :domain, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
9
9
|
{ :name => :workstation, :class => Net::NTLM::SecurityBuffer, :value => Socket.gethostname, :active => true },
|
10
|
-
{ :name => :
|
10
|
+
{ :name => :os_version, :class => Net::NTLM::String, :value => '', :active => false },
|
11
11
|
]
|
12
12
|
flags = [
|
13
13
|
:UNICODE,
|
@@ -24,19 +24,108 @@ describe Net::NTLM::Message::Type1 do
|
|
24
24
|
|
25
25
|
it 'should deserialize' do
|
26
26
|
t1 = Net::NTLM::Message.decode64(type1_packet)
|
27
|
-
t1.class.
|
28
|
-
t1.domain.
|
29
|
-
t1.flag.
|
30
|
-
t1.
|
31
|
-
t1.sign.
|
32
|
-
t1.type.
|
33
|
-
t1.workstation.
|
27
|
+
expect(t1.class).to eq(Net::NTLM::Message::Type1)
|
28
|
+
expect(t1.domain).to eq('')
|
29
|
+
expect(t1.flag).to eq(557575)
|
30
|
+
expect(t1.os_version).to eq('')
|
31
|
+
expect(t1.sign).to eq("NTLMSSP\0")
|
32
|
+
expect(t1.type).to eq(1)
|
33
|
+
expect(t1.workstation).to eq('')
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'should serialize' do
|
37
37
|
t1 = Net::NTLM::Message::Type1.new
|
38
38
|
t1.workstation = ''
|
39
|
-
t1.encode64.
|
39
|
+
expect(t1.encode64).to eq(type1_packet)
|
40
40
|
end
|
41
41
|
|
42
|
-
|
42
|
+
describe '.parse' do
|
43
|
+
subject(:message) { described_class.parse(data) }
|
44
|
+
# http://davenport.sourceforge.net/ntlm.html#appendixC7
|
45
|
+
context 'NTLM2 Session Response Authentication; NTLM2 Signing and Sealing Using the 128-bit NTLM2 Session Response User Session Key With Key Exchange Negotiated' do
|
46
|
+
let(:data) do
|
47
|
+
['4e544c4d5353500001000000b78208e000000000000000000000000000000000'].pack('H*')
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should set the magic' do
|
51
|
+
expect(message.sign).to eql(Net::NTLM::SSP_SIGN)
|
52
|
+
end
|
53
|
+
it 'should set the type' do
|
54
|
+
expect(message.type).to eq(1)
|
55
|
+
end
|
56
|
+
it 'should set the flags' do
|
57
|
+
expect(message.flag).to eq(0xe00882b7)
|
58
|
+
expect(message).to have_flag(:UNICODE)
|
59
|
+
expect(message).to have_flag(:OEM)
|
60
|
+
expect(message).to have_flag(:REQUEST_TARGET)
|
61
|
+
expect(message).to have_flag(:SIGN)
|
62
|
+
expect(message).to have_flag(:SEAL)
|
63
|
+
expect(message).to have_flag(:NTLM)
|
64
|
+
expect(message).to have_flag(:ALWAYS_SIGN)
|
65
|
+
expect(message).to have_flag(:NTLM2_KEY)
|
66
|
+
expect(message).to have_flag(:KEY128)
|
67
|
+
expect(message).to have_flag(:KEY_EXCHANGE)
|
68
|
+
expect(message).to have_flag(:KEY56)
|
69
|
+
end
|
70
|
+
it 'should have empty workstation' do
|
71
|
+
expect(message.workstation).to be_empty
|
72
|
+
end
|
73
|
+
it 'should have empty domain' do
|
74
|
+
expect(message.domain).to be_empty
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
# http://davenport.sourceforge.net/ntlm.html#appendixC9
|
80
|
+
context 'NTLMv2 Authentication; NTLM1 Signing and Sealing Using the 40-bit NTLMv2 User Session Key' do
|
81
|
+
let(:data) { ['4e544c4d53535000010000003782000000000000000000000000000000000000'].pack('H*') }
|
82
|
+
|
83
|
+
it 'should set the magic' do
|
84
|
+
expect(message.sign).to eql(Net::NTLM::SSP_SIGN)
|
85
|
+
end
|
86
|
+
it 'should set the type' do
|
87
|
+
expect(message.type).to eq(1)
|
88
|
+
end
|
89
|
+
it 'should set the flags' do
|
90
|
+
expect(message.flag).to eq(0x00008237)
|
91
|
+
expect(message).to have_flag(:UNICODE)
|
92
|
+
expect(message).to have_flag(:OEM)
|
93
|
+
expect(message).to have_flag(:REQUEST_TARGET)
|
94
|
+
expect(message).to have_flag(:SIGN)
|
95
|
+
expect(message).to have_flag(:SEAL)
|
96
|
+
expect(message).to have_flag(:NTLM)
|
97
|
+
expect(message).to have_flag(:ALWAYS_SIGN)
|
98
|
+
end
|
99
|
+
it 'should have empty workstation' do
|
100
|
+
expect(message.workstation).to be_empty
|
101
|
+
end
|
102
|
+
it 'should have empty domain' do
|
103
|
+
expect(message.domain).to be_empty
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'NTLMv2 with OS version' do
|
108
|
+
let(:data) { ['4e544c4d5353500001000000978208e2000000000000000000000000000000000602f0230000000f'].pack('H*') }
|
109
|
+
|
110
|
+
it 'should set the magic' do
|
111
|
+
expect(message.sign).to eql(Net::NTLM::SSP_SIGN)
|
112
|
+
end
|
113
|
+
it 'should set the type' do
|
114
|
+
expect(message.type).to eq(1)
|
115
|
+
end
|
116
|
+
it 'should have empty workstation' do
|
117
|
+
expect(message.workstation).to be_empty
|
118
|
+
end
|
119
|
+
it 'should have empty domain' do
|
120
|
+
expect(message.domain).to be_empty
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'should set OS version info' do
|
124
|
+
expect(message.os_version).to eq(['0602f0230000000f'].pack('H*'))
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
@@ -11,7 +11,7 @@ describe Net::NTLM::Message::Type2 do
|
|
11
11
|
{ :name => :flag, :class => Net::NTLM::Int32LE, :value => Net::NTLM::DEFAULT_FLAGS[:TYPE2], :active => true },
|
12
12
|
{ :name => :target_name, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
13
13
|
{ :name => :target_info, :class => Net::NTLM::SecurityBuffer, :value => '', :active => false },
|
14
|
-
{ :name => :
|
14
|
+
{ :name => :os_version, :class => Net::NTLM::String, :value => '', :active => false },
|
15
15
|
]
|
16
16
|
flags = [
|
17
17
|
:UNICODE
|
@@ -24,24 +24,22 @@ describe Net::NTLM::Message::Type2 do
|
|
24
24
|
|
25
25
|
it 'should deserialize' do
|
26
26
|
t2 = Net::NTLM::Message.decode64(type2_packet)
|
27
|
-
t2.class.
|
28
|
-
t2.challenge.
|
29
|
-
t2.context.
|
30
|
-
t2.flag.
|
31
|
-
|
32
|
-
|
33
|
-
end
|
34
|
-
t2.sign.should == "NTLMSSP\0"
|
27
|
+
expect(t2.class).to eq(Net::NTLM::Message::Type2)
|
28
|
+
expect(t2.challenge).to eq(14872292244261496103)
|
29
|
+
expect(t2.context).to eq(0)
|
30
|
+
expect(t2.flag).to eq(42631685)
|
31
|
+
expect(t2.os_version).to eq(['0601b11d0000000f'].pack('H*'))
|
32
|
+
expect(t2.sign).to eq("NTLMSSP\0")
|
35
33
|
|
36
34
|
t2_target_info = Net::NTLM::EncodeUtil.decode_utf16le(t2.target_info)
|
37
35
|
if RUBY_VERSION == "1.8.7"
|
38
|
-
t2_target_info.
|
36
|
+
expect(t2_target_info).to eq("\x02\x1CVAGRANT-2008R2\x01\x1CVAGRANT-2008R2\x04\x1Cvagrant-2008R2\x03\x1Cvagrant-2008R2\a\b\e$(D+&\e(B\0\0")
|
39
37
|
else
|
40
|
-
t2_target_info.
|
38
|
+
expect(t2_target_info).to eq("\u0002\u001CVAGRANT-2008R2\u0001\u001CVAGRANT-2008R2\u0004\u001Cvagrant-2008R2\u0003\u001Cvagrant-2008R2\a\b፤ᐝ❴ǎ\0\0")
|
41
39
|
end
|
42
40
|
|
43
|
-
Net::NTLM::EncodeUtil.decode_utf16le(t2.target_name).
|
44
|
-
t2.type.
|
41
|
+
expect(Net::NTLM::EncodeUtil.decode_utf16le(t2.target_name)).to eq("VAGRANT-2008R2")
|
42
|
+
expect(t2.type).to eq(2)
|
45
43
|
end
|
46
44
|
|
47
45
|
it 'should serialize' do
|
@@ -51,16 +49,16 @@ describe Net::NTLM::Message::Type2 do
|
|
51
49
|
t2.challenge = source.challenge
|
52
50
|
t2.context = source.context
|
53
51
|
t2.flag = source.flag
|
54
|
-
t2.
|
52
|
+
t2.os_version = source.os_version
|
55
53
|
t2.sign = source.sign
|
56
54
|
t2.target_info = source.target_info
|
57
55
|
t2.target_name = source.target_name
|
58
56
|
t2.type = source.type
|
59
57
|
t2.enable(:context)
|
60
58
|
t2.enable(:target_info)
|
61
|
-
t2.enable(:
|
59
|
+
t2.enable(:os_version)
|
62
60
|
|
63
|
-
t2.encode64.
|
61
|
+
expect(t2.encode64).to eq(type2_packet)
|
64
62
|
end
|
65
63
|
|
66
64
|
it 'should generate a type 3 response' do
|
@@ -72,17 +70,63 @@ describe Net::NTLM::Message::Type2 do
|
|
72
70
|
type3_known.enable(:flag)
|
73
71
|
|
74
72
|
t3 = t2.response({:user => 'vagrant', :password => 'vagrant', :domain => ''}, {:ntlmv2 => true, :workstation => 'kobe.local'})
|
75
|
-
t3.domain.
|
76
|
-
t3.flag.
|
77
|
-
t3.sign.
|
78
|
-
t3.workstation.
|
79
|
-
t3.user.
|
80
|
-
t3.session_key.
|
73
|
+
expect(t3.domain).to eq(type3_known.domain)
|
74
|
+
expect(t3.flag).to eq(type3_known.flag)
|
75
|
+
expect(t3.sign).to eq("NTLMSSP\0")
|
76
|
+
expect(t3.workstation).to eq("k\0o\0b\0e\0.\0l\0o\0c\0a\0l\0")
|
77
|
+
expect(t3.user).to eq("v\0a\0g\0r\0a\0n\0t\0")
|
78
|
+
expect(t3.session_key).to eq('')
|
81
79
|
end
|
82
80
|
|
83
81
|
it 'should upcase domain when provided' do
|
84
82
|
t2 = Net::NTLM::Message.decode64(type2_packet)
|
85
83
|
t3 = t2.response({:user => 'vagrant', :password => 'vagrant', :domain => 'domain'}, {:ntlmv2 => true, :workstation => 'kobe.local'})
|
86
|
-
t3.domain.
|
84
|
+
expect(t3.domain).to eq("D\0O\0M\0A\0I\0N\0")
|
87
85
|
end
|
88
|
-
|
86
|
+
|
87
|
+
describe '.parse' do
|
88
|
+
subject(:message) { described_class.parse(data) }
|
89
|
+
# http://davenport.sourceforge.net/ntlm.html#appendixC7
|
90
|
+
context 'NTLM2 Session Response Authentication; NTLM2 Signing and Sealing Using the 128-bit NTLM2 Session Response User Session Key With Key Exchange Negotiated' do
|
91
|
+
let(:data) do
|
92
|
+
[
|
93
|
+
'4e544c4d53535000020000000c000c0030000000358289e0677f1c557a5ee96c' \
|
94
|
+
'0000000000000000460046003c00000054004500530054004e00540002000c00' \
|
95
|
+
'54004500530054004e00540001000c004d0045004d0042004500520003001e00' \
|
96
|
+
'6d0065006d006200650072002e0074006500730074002e0063006f006d000000' \
|
97
|
+
'0000'
|
98
|
+
].pack('H*')
|
99
|
+
end
|
100
|
+
|
101
|
+
it 'should set the magic' do
|
102
|
+
expect(message.sign).to eql(Net::NTLM::SSP_SIGN)
|
103
|
+
end
|
104
|
+
it 'should set the type' do
|
105
|
+
expect(message.type).to eq(2)
|
106
|
+
end
|
107
|
+
it 'should set the target name' do
|
108
|
+
# TESTNT
|
109
|
+
expect(message.target_name).to eq(["54004500530054004e005400"].pack('H*'))
|
110
|
+
end
|
111
|
+
it 'should set the flags' do
|
112
|
+
expect(message.flag).to eq(0xe0898235)
|
113
|
+
end
|
114
|
+
it 'should set the challenge' do
|
115
|
+
expect(message.challenge).to eq(0x6ce95e7a551c7f67)
|
116
|
+
end
|
117
|
+
it 'should set an empty context' do
|
118
|
+
expect(message.context).to be_zero
|
119
|
+
end
|
120
|
+
it 'should set target info' do
|
121
|
+
ti = [
|
122
|
+
'02000c0054004500530054004e00540001000c004d0045004d00420045005200' \
|
123
|
+
'03001e006d0065006d006200650072002e0074006500730074002e0063006f00' \
|
124
|
+
'6d0000000000'
|
125
|
+
].pack('H*')
|
126
|
+
expect(message.target_info).to eq(ti)
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
@@ -5,16 +5,221 @@ describe Net::NTLM::Message::Type3 do
|
|
5
5
|
fields = [
|
6
6
|
{ :name => :sign, :class => Net::NTLM::String, :value => Net::NTLM::SSP_SIGN, :active => true },
|
7
7
|
{ :name => :type, :class => Net::NTLM::Int32LE, :value => 3, :active => true },
|
8
|
-
{ :name => :flag, :class => Net::NTLM::Int64LE, :value => 0, :active => false },
|
9
8
|
{ :name => :lm_response, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
10
9
|
{ :name => :ntlm_response, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
11
10
|
{ :name => :domain, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
12
11
|
{ :name => :user, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
13
12
|
{ :name => :workstation, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
14
13
|
{ :name => :session_key, :class => Net::NTLM::SecurityBuffer, :value => '', :active => false },
|
14
|
+
{ :name => :flag, :class => Net::NTLM::Int32LE, :value => 0, :active => false },
|
15
15
|
]
|
16
16
|
flags = []
|
17
17
|
it_behaves_like 'a fieldset', fields
|
18
18
|
it_behaves_like 'a message', flags
|
19
19
|
|
20
|
-
|
20
|
+
describe '.parse' do
|
21
|
+
subject(:message) { described_class.parse(data) }
|
22
|
+
|
23
|
+
context 'with NTLMv2 data' do
|
24
|
+
let(:data) do
|
25
|
+
# Captured NTLMSSP blob from smbclient with username 'administrator'
|
26
|
+
# and a blank password, i.e.:
|
27
|
+
# smbclient -U 'administrator%' -L //192.168.100.140/
|
28
|
+
[
|
29
|
+
'4e544c4d53535000030000001800180040000000c400c4005800000012001200' \
|
30
|
+
'1c0100001a001a002e0100001a001a0048010000100010006201000015820860' \
|
31
|
+
'ced203d860b80c7350050754b238202a8c1c63134f0ae0f086a3fb147e8b2f9f' \
|
32
|
+
'de3ef1b1b43c83dc010100000000000080512dba020ed0011c5bc2c8339fd29a' \
|
33
|
+
'0000000002001e00570049004e002d00420035004a004e003300520048004700' \
|
34
|
+
'46003300310001001e00570049004e002d00420035004a004e00330052004800' \
|
35
|
+
'470046003300310004001e00570049004e002d00420035004a004e0033005200' \
|
36
|
+
'4800470046003300310003001e00570049004e002d00420035004a004e003300' \
|
37
|
+
'52004800470046003300310007000800a209e5ba020ed0010000000057004f00' \
|
38
|
+
'52004b00470052004f0055005000610064006d0069006e006900730074007200' \
|
39
|
+
'610074006f0072004100550053002d004c004500450054002d00310030003300' \
|
40
|
+
'31007036615cd6d9b19a685ded4312311cd7'
|
41
|
+
].pack('H*')
|
42
|
+
end
|
43
|
+
|
44
|
+
let(:server_challenge) { ['f588469dc96fe809'].pack('H*') }
|
45
|
+
|
46
|
+
it 'should set the magic' do
|
47
|
+
expect(message.sign).to eql(Net::NTLM::SSP_SIGN)
|
48
|
+
end
|
49
|
+
it 'should set the type' do
|
50
|
+
expect(message.type).to eq(3)
|
51
|
+
end
|
52
|
+
it 'should set the LM response' do
|
53
|
+
lm_response = ['ced203d860b80c7350050754b238202a8c1c63134f0ae0f0'].pack('H*')
|
54
|
+
expect(message.lm_response).to eq(lm_response)
|
55
|
+
end
|
56
|
+
it 'should set the NTLM response' do
|
57
|
+
ntlm_response = [
|
58
|
+
'86a3fb147e8b2f9fde3ef1b1b43c83dc010100000000000080512dba020ed001' \
|
59
|
+
'1c5bc2c8339fd29a0000000002001e00570049004e002d00420035004a004e00' \
|
60
|
+
'330052004800470046003300310001001e00570049004e002d00420035004a00' \
|
61
|
+
'4e00330052004800470046003300310004001e00570049004e002d0042003500' \
|
62
|
+
'4a004e00330052004800470046003300310003001e00570049004e002d004200' \
|
63
|
+
'35004a004e00330052004800470046003300310007000800a209e5ba020ed001' \
|
64
|
+
'00000000'
|
65
|
+
].pack('H*')
|
66
|
+
expect(message.ntlm_response).to eq(ntlm_response)
|
67
|
+
end
|
68
|
+
it 'should set the user' do
|
69
|
+
# administrator
|
70
|
+
user = ['610064006d0069006e006900730074007200610074006f007200'].pack('H*')
|
71
|
+
expect(message.user).to eq(user)
|
72
|
+
end
|
73
|
+
it 'should set the domain' do
|
74
|
+
# WORKGROUP
|
75
|
+
domain = ['57004f0052004b00470052004f0055005000'].pack('H*')
|
76
|
+
expect(message.domain).to eq(domain)
|
77
|
+
end
|
78
|
+
it 'should set the workstation' do
|
79
|
+
# AUS-LEET-1031
|
80
|
+
workstation = ['4100550053002d004c004500450054002d003100300033003100'].pack('H*')
|
81
|
+
expect(message.workstation).to eq(workstation)
|
82
|
+
end
|
83
|
+
it 'should set the session key' do
|
84
|
+
session_key = ['7036615cd6d9b19a685ded4312311cd7'].pack('H*')
|
85
|
+
expect(message.session_key).to eq(session_key)
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should set the flags' do
|
89
|
+
expect(message.flag).to eq(0x60088215)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should NOT set the OS version structure' do
|
93
|
+
expect(message.os_version).to be_nil
|
94
|
+
end
|
95
|
+
|
96
|
+
describe '#blank_password?' do
|
97
|
+
it 'should be true' do
|
98
|
+
expect(message.blank_password?(server_challenge)).to be true
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#ntlm_version' do
|
103
|
+
let(:ver) { message.ntlm_version }
|
104
|
+
it 'should be :ntlmv2' do
|
105
|
+
expect(ver).to eq(:ntlmv2)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
# http://davenport.sourceforge.net/ntlm.html#appendixC7
|
112
|
+
context 'NTLM2 Session Response Authentication; NTLM2 Signing and Sealing Using the 128-bit NTLM2 Session Response User Session Key With Key Exchange Negotiated' do
|
113
|
+
|
114
|
+
let(:data) do
|
115
|
+
[
|
116
|
+
'4e544c4d5353500003000000180018006000000018001800780000000c000c00' \
|
117
|
+
'40000000080008004c0000000c000c00540000001000100090000000358288e0' \
|
118
|
+
'54004500530054004e00540074006500730074004d0045004d00420045005200' \
|
119
|
+
'404d1b6f6915258000000000000000000000000000000000ea8cc49f24da157f' \
|
120
|
+
'13436637f77693d8b992d619e584c7ee727a5240822ec7af4e9100c43e6fee7f'
|
121
|
+
].pack('H*')
|
122
|
+
end
|
123
|
+
|
124
|
+
it 'should set the LM response' do
|
125
|
+
lm_response = ['404d1b6f6915258000000000000000000000000000000000'].pack('H*')
|
126
|
+
expect(message.lm_response).to eq(lm_response)
|
127
|
+
end
|
128
|
+
it 'should set the NTLM response' do
|
129
|
+
ntlm_response = [ 'ea8cc49f24da157f13436637f77693d8b992d619e584c7ee' ].pack('H*')
|
130
|
+
expect(message.ntlm_response).to eq(ntlm_response)
|
131
|
+
end
|
132
|
+
it 'should set the domain' do
|
133
|
+
# TESTNT
|
134
|
+
domain = ['54004500530054004e005400'].pack('H*')
|
135
|
+
expect(message.domain).to eq(domain)
|
136
|
+
end
|
137
|
+
it 'should set the user' do
|
138
|
+
# test
|
139
|
+
user = ['7400650073007400'].pack('H*')
|
140
|
+
expect(message.user).to eq(user)
|
141
|
+
end
|
142
|
+
it 'should set the workstation' do
|
143
|
+
# MEMBER
|
144
|
+
workstation = ['4d0045004d00420045005200'].pack('H*')
|
145
|
+
expect(message.workstation).to eq(workstation)
|
146
|
+
end
|
147
|
+
it 'should set the session key' do
|
148
|
+
session_key = ['727a5240822ec7af4e9100c43e6fee7f'].pack('H*')
|
149
|
+
expect(message.session_key).to eq(session_key)
|
150
|
+
end
|
151
|
+
|
152
|
+
let(:server_challenge) { ['677f1c557a5ee96c'].pack('H*') }
|
153
|
+
describe '#password?' do
|
154
|
+
it 'should be true for "test1234"' do
|
155
|
+
expect(message.password?('test1234', server_challenge)).to be true
|
156
|
+
end
|
157
|
+
end
|
158
|
+
describe '#blank_password?' do
|
159
|
+
it 'should be false' do
|
160
|
+
expect(message.blank_password?(server_challenge)).to be false
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
describe '#ntlm_version' do
|
165
|
+
let(:ver) { message.ntlm_version }
|
166
|
+
it 'should be :ntlm2_session' do
|
167
|
+
expect(ver).to eq(:ntlm2_session)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
# http://davenport.sourceforge.net/ntlm.html#appendixC9
|
174
|
+
context 'NTLMv2 Authentication; NTLM1 Signing and Sealing Using the 40-bit NTLMv2 User Session Key' do
|
175
|
+
let(:data) do
|
176
|
+
[
|
177
|
+
'4e544c4d5353500003000000180018006000000076007600780000000c000c00' \
|
178
|
+
'40000000080008004c0000000c000c005400000000000000ee00000035828000' \
|
179
|
+
'54004500530054004e00540074006500730074004d0045004d00420045005200' \
|
180
|
+
'5d55a02b60a40526ac9a1e4d15fa45a0f2e6329726c598e8f77c67dad00b9321' \
|
181
|
+
'6242b197fe6addfa0101000000000000502db638677bc301f2e6329726c598e8' \
|
182
|
+
'0000000002000c0054004500530054004e00540001000c004d0045004d004200' \
|
183
|
+
'4500520003001e006d0065006d006200650072002e0074006500730074002e00' \
|
184
|
+
'63006f006d000000000000000000'
|
185
|
+
].pack 'H*'
|
186
|
+
end
|
187
|
+
|
188
|
+
it 'should set the NTLM response' do
|
189
|
+
ntlm_response = [
|
190
|
+
'f77c67dad00b93216242b197fe6addfa0101000000000000502db638677bc301' \
|
191
|
+
'f2e6329726c598e80000000002000c0054004500530054004e00540001000c00' \
|
192
|
+
'4d0045004d0042004500520003001e006d0065006d006200650072002e007400' \
|
193
|
+
'6500730074002e0063006f006d000000000000000000'
|
194
|
+
].pack 'H*'
|
195
|
+
expect(message.ntlm_response).to eq(ntlm_response)
|
196
|
+
end
|
197
|
+
|
198
|
+
it 'should set the domain' do
|
199
|
+
# TESTNT
|
200
|
+
domain = ['54004500530054004e005400'].pack('H*')
|
201
|
+
expect(message.domain).to eq(domain)
|
202
|
+
end
|
203
|
+
it 'should set the user' do
|
204
|
+
# test
|
205
|
+
user = ['7400650073007400'].pack('H*')
|
206
|
+
expect(message.user).to eq(user)
|
207
|
+
end
|
208
|
+
it 'should set the workstation' do
|
209
|
+
# MEMBER
|
210
|
+
workstation = ['4d0045004d00420045005200'].pack('H*')
|
211
|
+
expect(message.workstation).to eq(workstation)
|
212
|
+
end
|
213
|
+
|
214
|
+
describe '#ntlm_version' do
|
215
|
+
let(:ver) { message.ntlm_version }
|
216
|
+
it 'should be :ntlmv2' do
|
217
|
+
expect(ver).to eq(:ntlmv2)
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|