rubyntlm 0.6.5 → 0.6.7
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/CHANGELOG.md +9 -0
- data/README.md +48 -48
- data/lib/net/ntlm/blob.rb +11 -10
- data/lib/net/ntlm/channel_binding.rb +13 -9
- data/lib/net/ntlm/client/session.rb +34 -141
- data/lib/net/ntlm/client/session_crypto.rb +126 -0
- data/lib/net/ntlm/client.rb +8 -9
- data/lib/net/ntlm/encode_util.rb +39 -38
- data/lib/net/ntlm/exceptions.rb +3 -0
- data/lib/net/ntlm/field.rb +29 -31
- data/lib/net/ntlm/field_set.rb +39 -18
- data/lib/net/ntlm/int16_le.rb +8 -8
- data/lib/net/ntlm/int32_le.rb +8 -7
- data/lib/net/ntlm/int64_le.rb +8 -7
- data/lib/net/ntlm/md4.rb +102 -63
- data/lib/net/ntlm/message/type0.rb +4 -7
- data/lib/net/ntlm/message/type1.rb +8 -9
- data/lib/net/ntlm/message/type2.rb +87 -67
- data/lib/net/ntlm/message/type3.rb +49 -59
- data/lib/net/ntlm/message.rb +116 -111
- data/lib/net/ntlm/rc4.rb +51 -44
- data/lib/net/ntlm/response.rb +112 -0
- data/lib/net/ntlm/security_buffer.rb +13 -15
- data/lib/net/ntlm/string.rb +8 -7
- data/lib/net/ntlm/target_info.rb +52 -44
- data/lib/net/ntlm/version.rb +3 -1
- data/lib/net/ntlm.rb +37 -125
- data/lib/rubyntlm.rb +3 -1
- metadata +10 -141
- data/.devcontainer/devcontainer.json +0 -22
- data/.github/dependabot.yml +0 -10
- data/.github/workflows/build.yml +0 -24
- data/.gitignore +0 -5
- data/.rspec +0 -2
- data/Gemfile +0 -3
- data/Rakefile +0 -25
- data/examples/http.rb +0 -86
- data/examples/imap.rb +0 -73
- data/examples/smtp.rb +0 -94
- data/rubyntlm.gemspec +0 -31
- data/spec/lib/net/ntlm/blob_spec.rb +0 -16
- data/spec/lib/net/ntlm/channel_binding_spec.rb +0 -17
- data/spec/lib/net/ntlm/client/session_spec.rb +0 -87
- data/spec/lib/net/ntlm/client_spec.rb +0 -64
- data/spec/lib/net/ntlm/encode_util_spec.rb +0 -16
- data/spec/lib/net/ntlm/field_set_spec.rb +0 -33
- data/spec/lib/net/ntlm/field_spec.rb +0 -34
- data/spec/lib/net/ntlm/int16_le_spec.rb +0 -18
- data/spec/lib/net/ntlm/int32_le_spec.rb +0 -19
- data/spec/lib/net/ntlm/int64_le_spec.rb +0 -19
- data/spec/lib/net/ntlm/message/type0_spec.rb +0 -21
- data/spec/lib/net/ntlm/message/type1_spec.rb +0 -131
- data/spec/lib/net/ntlm/message/type2_spec.rb +0 -132
- data/spec/lib/net/ntlm/message/type3_spec.rb +0 -267
- data/spec/lib/net/ntlm/message_spec.rb +0 -17
- data/spec/lib/net/ntlm/security_buffer_spec.rb +0 -64
- data/spec/lib/net/ntlm/string_spec.rb +0 -72
- data/spec/lib/net/ntlm/target_info_spec.rb +0 -76
- data/spec/lib/net/ntlm/version_spec.rb +0 -27
- data/spec/lib/net/ntlm_spec.rb +0 -135
- data/spec/spec_helper.rb +0 -22
- data/spec/support/certificates/sha_256_hash.pem +0 -19
- data/spec/support/shared/examples/net/ntlm/field_shared.rb +0 -25
- data/spec/support/shared/examples/net/ntlm/fieldset_shared.rb +0 -239
- data/spec/support/shared/examples/net/ntlm/int_shared.rb +0 -43
- data/spec/support/shared/examples/net/ntlm/message_shared.rb +0 -35
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
# encoding: UTF-8
|
|
2
|
-
require 'spec_helper'
|
|
3
|
-
|
|
4
|
-
describe Net::NTLM::Message::Type2 do
|
|
5
|
-
|
|
6
|
-
fields = [
|
|
7
|
-
{ :name => :sign, :class => Net::NTLM::String, :value => Net::NTLM::SSP_SIGN, :active => true },
|
|
8
|
-
{ :name => :type, :class => Net::NTLM::Int32LE, :value => 2, :active => true },
|
|
9
|
-
{ :name => :challenge, :class => Net::NTLM::Int64LE, :value => 0, :active => true },
|
|
10
|
-
{ :name => :context, :class => Net::NTLM::Int64LE, :value => 0, :active => false },
|
|
11
|
-
{ :name => :flag, :class => Net::NTLM::Int32LE, :value => Net::NTLM::DEFAULT_FLAGS[:TYPE2], :active => true },
|
|
12
|
-
{ :name => :target_name, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
|
13
|
-
{ :name => :target_info, :class => Net::NTLM::SecurityBuffer, :value => '', :active => false },
|
|
14
|
-
{ :name => :os_version, :class => Net::NTLM::String, :value => '', :active => false },
|
|
15
|
-
]
|
|
16
|
-
flags = [
|
|
17
|
-
:UNICODE
|
|
18
|
-
]
|
|
19
|
-
it_behaves_like 'a fieldset', fields
|
|
20
|
-
it_behaves_like 'a message', flags
|
|
21
|
-
|
|
22
|
-
let(:type2_packet) {"TlRMTVNTUAACAAAAHAAcADgAAAAFgooCJ+UA1//+ZM4AAAAAAAAAAJAAkABUAAAABgGxHQAAAA9WAEEARwBSAEEATgBUAC0AMgAwADAAOABSADIAAgAcAFYAQQBHAFIAQQBOAFQALQAyADAAMAA4AFIAMgABABwAVgBBAEcAUgBBAE4AVAAtADIAMAAwADgAUgAyAAQAHAB2AGEAZwByAGEAbgB0AC0AMgAwADAAOABSADIAAwAcAHYAYQBnAHIAYQBuAHQALQAyADAAMAA4AFIAMgAHAAgAZBMdFHQnzgEAAAAA"}
|
|
23
|
-
let(:type3_packet) {"TlRMTVNTUAADAAAAGAAYAEQAAADAAMAAXAAAAAAAAAAcAQAADgAOABwBAAAUABQAKgEAAAAAAAA+AQAABYKKAgAAAADVS27TfQGmWxSSbXmolTUQyxJmD8ISQuBKKHFKC8GksUZISYc8Ps9RAQEAAAAAAAAANasTdCfOAcsSZg/CEkLgAAAAAAIAHABWAEEARwBSAEEATgBUAC0AMgAwADAAOABSADIAAQAcAFYAQQBHAFIAQQBOAFQALQAyADAAMAA4AFIAMgAEABwAdgBhAGcAcgBhAG4AdAAtADIAMAAwADgAUgAyAAMAHAB2AGEAZwByAGEAbgB0AC0AMgAwADAAOABSADIABwAIAGQTHRR0J84BAAAAAAAAAAB2AGEAZwByAGEAbgB0AGsAbwBiAGUALgBsAG8AYwBhAGwA"}
|
|
24
|
-
|
|
25
|
-
it 'should deserialize' do
|
|
26
|
-
t2 = Net::NTLM::Message.decode64(type2_packet)
|
|
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")
|
|
33
|
-
|
|
34
|
-
t2_target_info = Net::NTLM::EncodeUtil.decode_utf16le(t2.target_info)
|
|
35
|
-
if RUBY_VERSION == "1.8.7"
|
|
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")
|
|
37
|
-
else
|
|
38
|
-
expect(t2_target_info).to eq("\u0002\u001CVAGRANT-2008R2\u0001\u001CVAGRANT-2008R2\u0004\u001Cvagrant-2008R2\u0003\u001Cvagrant-2008R2\a\b፤ᐝ❴ǎ\0\0")
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
expect(Net::NTLM::EncodeUtil.decode_utf16le(t2.target_name)).to eq("VAGRANT-2008R2")
|
|
42
|
-
expect(t2.type).to eq(2)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
it 'should serialize' do
|
|
46
|
-
source = Net::NTLM::Message.decode64(type2_packet)
|
|
47
|
-
|
|
48
|
-
t2 = Net::NTLM::Message::Type2.new
|
|
49
|
-
t2.challenge = source.challenge
|
|
50
|
-
t2.context = source.context
|
|
51
|
-
t2.flag = source.flag
|
|
52
|
-
t2.os_version = source.os_version
|
|
53
|
-
t2.sign = source.sign
|
|
54
|
-
t2.target_info = source.target_info
|
|
55
|
-
t2.target_name = source.target_name
|
|
56
|
-
t2.type = source.type
|
|
57
|
-
t2.enable(:context)
|
|
58
|
-
t2.enable(:target_info)
|
|
59
|
-
t2.enable(:os_version)
|
|
60
|
-
|
|
61
|
-
expect(t2.encode64).to eq(type2_packet)
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
it 'should generate a type 3 response' do
|
|
65
|
-
t2 = Net::NTLM::Message.decode64(type2_packet)
|
|
66
|
-
|
|
67
|
-
type3_known = Net::NTLM::Message.decode64(type3_packet)
|
|
68
|
-
type3_known.flag = 0x028a8205
|
|
69
|
-
type3_known.enable(:session_key)
|
|
70
|
-
type3_known.enable(:flag)
|
|
71
|
-
|
|
72
|
-
t3 = t2.response({:user => 'vagrant', :password => 'vagrant', :domain => ''}, {:ntlmv2 => true, :workstation => 'kobe.local'})
|
|
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('')
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
it 'should upcase domain when provided' do
|
|
82
|
-
t2 = Net::NTLM::Message.decode64(type2_packet)
|
|
83
|
-
t3 = t2.response({:user => 'vagrant', :password => 'vagrant', :domain => 'domain'}, {:ntlmv2 => true, :workstation => 'kobe.local'})
|
|
84
|
-
expect(t3.domain).to eq("D\0O\0M\0A\0I\0N\0")
|
|
85
|
-
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
|
|
@@ -1,267 +0,0 @@
|
|
|
1
|
-
require 'spec_helper'
|
|
2
|
-
|
|
3
|
-
describe Net::NTLM::Message::Type3 do
|
|
4
|
-
|
|
5
|
-
fields = [
|
|
6
|
-
{ :name => :sign, :class => Net::NTLM::String, :value => Net::NTLM::SSP_SIGN, :active => true },
|
|
7
|
-
{ :name => :type, :class => Net::NTLM::Int32LE, :value => 3, :active => true },
|
|
8
|
-
{ :name => :lm_response, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
|
9
|
-
{ :name => :ntlm_response, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
|
10
|
-
{ :name => :domain, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
|
11
|
-
{ :name => :user, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
|
12
|
-
{ :name => :workstation, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
|
|
13
|
-
{ :name => :session_key, :class => Net::NTLM::SecurityBuffer, :value => '', :active => false },
|
|
14
|
-
{ :name => :flag, :class => Net::NTLM::Int32LE, :value => 0, :active => false },
|
|
15
|
-
]
|
|
16
|
-
flags = []
|
|
17
|
-
it_behaves_like 'a fieldset', fields
|
|
18
|
-
it_behaves_like 'a message', flags
|
|
19
|
-
|
|
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
|
-
describe '#serialize' do
|
|
226
|
-
context 'when the username contains non-ASCI characters' do
|
|
227
|
-
let(:t3) {
|
|
228
|
-
t2 = Net::NTLM::Message::Type2.new
|
|
229
|
-
t2.response(
|
|
230
|
-
{
|
|
231
|
-
:user => 'Hélène',
|
|
232
|
-
:password => '123456',
|
|
233
|
-
:domain => ''
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
:ntlmv2 => true,
|
|
237
|
-
:workstation => 'testlab.local'
|
|
238
|
-
}
|
|
239
|
-
)
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
it 'serializes without error' do
|
|
243
|
-
expect { t3.serialize }.not_to raise_error
|
|
244
|
-
end
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
subject(:message) { described_class.create(opts) }
|
|
248
|
-
context 'with the UNICODE flag set' do
|
|
249
|
-
let(:opts) { {lm_response: "\x00".b, ntlm_response: '', domain: '', workstation: '', user: '', flag: Net::NTLM::DEFAULT_FLAGS[:TYPE3] | Net::NTLM::FLAGS[:UNICODE] } }
|
|
250
|
-
|
|
251
|
-
it 'should pad the domain field to a multiple of 2' do
|
|
252
|
-
message.serialize
|
|
253
|
-
expect(message[:domain][:offset].value % 2).to eq 0
|
|
254
|
-
end
|
|
255
|
-
|
|
256
|
-
it 'should pad the user field to a multiple of 2' do
|
|
257
|
-
message.serialize
|
|
258
|
-
expect(message[:user][:offset].value % 2).to eq 0
|
|
259
|
-
end
|
|
260
|
-
|
|
261
|
-
it 'should pad the workstation field to a multiple of 2' do
|
|
262
|
-
message.serialize
|
|
263
|
-
expect(message[:workstation][:offset].value % 2).to eq 0
|
|
264
|
-
end
|
|
265
|
-
end
|
|
266
|
-
end
|
|
267
|
-
end
|
|
@@ -1,17 +0,0 @@
|
|
|
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
|
-
end
|
|
@@ -1,64 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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,76 +0,0 @@
|
|
|
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 +0,0 @@
|
|
|
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
|