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.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -3
  3. data/README.md +9 -2
  4. data/Rakefile +8 -0
  5. data/examples/http.rb +1 -1
  6. data/lib/net/ntlm.rb +10 -9
  7. data/lib/net/ntlm/blob.rb +17 -6
  8. data/lib/net/ntlm/client.rb +61 -0
  9. data/lib/net/ntlm/client/session.rb +223 -0
  10. data/lib/net/ntlm/encode_util.rb +2 -2
  11. data/lib/net/ntlm/field_set.rb +9 -5
  12. data/lib/net/ntlm/message.rb +23 -9
  13. data/lib/net/ntlm/message/type1.rb +1 -26
  14. data/lib/net/ntlm/message/type2.rb +11 -37
  15. data/lib/net/ntlm/message/type3.rb +77 -14
  16. data/lib/net/ntlm/version.rb +1 -1
  17. data/rubyntlm.gemspec +3 -2
  18. data/spec/lib/net/ntlm/blob_spec.rb +1 -1
  19. data/spec/lib/net/ntlm/client/session_spec.rb +68 -0
  20. data/spec/lib/net/ntlm/client_spec.rb +64 -0
  21. data/spec/lib/net/ntlm/encode_util_spec.rb +3 -3
  22. data/spec/lib/net/ntlm/field_set_spec.rb +4 -4
  23. data/spec/lib/net/ntlm/field_spec.rb +5 -5
  24. data/spec/lib/net/ntlm/message/type1_spec.rb +99 -10
  25. data/spec/lib/net/ntlm/message/type2_spec.rb +68 -24
  26. data/spec/lib/net/ntlm/message/type3_spec.rb +207 -2
  27. data/spec/lib/net/ntlm/security_buffer_spec.rb +8 -8
  28. data/spec/lib/net/ntlm/string_spec.rb +14 -14
  29. data/spec/lib/net/ntlm/version_spec.rb +7 -6
  30. data/spec/lib/net/ntlm_spec.rb +20 -22
  31. data/spec/spec_helper.rb +1 -2
  32. data/spec/support/shared/examples/net/ntlm/field_shared.rb +3 -3
  33. data/spec/support/shared/examples/net/ntlm/fieldset_shared.rb +34 -34
  34. data/spec/support/shared/examples/net/ntlm/int_shared.rb +8 -8
  35. data/spec/support/shared/examples/net/ntlm/message_shared.rb +3 -3
  36. 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').should == "T\x00e\x00s\x00t\x00"
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").should == 'Test'
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.should == 'TestFoo'
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.should == 'FooBarB'
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.should == 7
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.should == 0
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.should == 0
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.should == 100
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.should == 0
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 => :padding, :class => Net::NTLM::String, :value => '', :active => false },
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.should == Net::NTLM::Message::Type1
28
- t1.domain.should == ''
29
- t1.flag.should == 557575
30
- t1.padding.should == ''
31
- t1.sign.should == "NTLMSSP\0"
32
- t1.type.should == 1
33
- t1.workstation.should == ''
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.should == type1_packet
39
+ expect(t1.encode64).to eq(type1_packet)
40
40
  end
41
41
 
42
- end
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 => :padding, :class => Net::NTLM::String, :value => '', :active => false },
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.should == Net::NTLM::Message::Type2
28
- t2.challenge.should == 14872292244261496103
29
- t2.context.should == 0
30
- t2.flag.should == 42631685
31
- if "".respond_to?(:force_encoding)
32
- t2.padding.should == ("\x06\x01\xB1\x1D\0\0\0\x0F".force_encoding('ASCII-8BIT'))
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.should == "\x02\x1CVAGRANT-2008R2\x01\x1CVAGRANT-2008R2\x04\x1Cvagrant-2008R2\x03\x1Cvagrant-2008R2\a\b\e$(D+&\e(B\0\0"
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.should == "\u0002\u001CVAGRANT-2008R2\u0001\u001CVAGRANT-2008R2\u0004\u001Cvagrant-2008R2\u0003\u001Cvagrant-2008R2\a\b፤ᐝ❴ǎ\0\0"
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).should == "VAGRANT-2008R2"
44
- t2.type.should == 2
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.padding = source.padding
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(:padding)
59
+ t2.enable(:os_version)
62
60
 
63
- t2.encode64.should == type2_packet
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.should == type3_known.domain
76
- t3.flag.should == type3_known.flag
77
- t3.sign.should == "NTLMSSP\0"
78
- t3.workstation.should == "k\0o\0b\0e\0.\0l\0o\0c\0a\0l\0"
79
- t3.user.should == "v\0a\0g\0r\0a\0n\0t\0"
80
- t3.session_key.should == ''
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.should == "D\0O\0M\0A\0I\0N\0"
84
+ expect(t3.domain).to eq("D\0O\0M\0A\0I\0N\0")
87
85
  end
88
- end
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
- end
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