rubyntlm 0.3.4 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +3 -0
  3. data/.travis.yml +0 -1
  4. data/LICENSE +20 -0
  5. data/Rakefile +8 -15
  6. data/lib/net/ntlm.rb +22 -654
  7. data/lib/net/ntlm/blob.rb +17 -0
  8. data/lib/net/ntlm/encode_util.rb +49 -0
  9. data/lib/net/ntlm/field.rb +35 -0
  10. data/lib/net/ntlm/field_set.rb +125 -0
  11. data/lib/net/ntlm/int16_le.rb +26 -0
  12. data/lib/net/ntlm/int32_le.rb +25 -0
  13. data/lib/net/ntlm/int64_le.rb +26 -0
  14. data/lib/net/ntlm/message.rb +115 -0
  15. data/lib/net/ntlm/message/type0.rb +16 -0
  16. data/lib/net/ntlm/message/type1.rb +43 -0
  17. data/lib/net/ntlm/message/type2.rb +126 -0
  18. data/lib/net/ntlm/message/type3.rb +68 -0
  19. data/lib/net/ntlm/security_buffer.rb +48 -0
  20. data/lib/net/ntlm/string.rb +35 -0
  21. data/lib/net/ntlm/version.rb +11 -0
  22. data/rubyntlm.gemspec +4 -1
  23. data/spec/lib/net/ntlm/blob_spec.rb +16 -0
  24. data/spec/lib/net/ntlm/encode_util_spec.rb +16 -0
  25. data/spec/lib/net/ntlm/field_set_spec.rb +33 -0
  26. data/spec/lib/net/ntlm/field_spec.rb +34 -0
  27. data/spec/lib/net/ntlm/int16_le_spec.rb +18 -0
  28. data/spec/lib/net/ntlm/int32_le_spec.rb +19 -0
  29. data/spec/lib/net/ntlm/int64_le_spec.rb +19 -0
  30. data/spec/lib/net/ntlm/message/type0_spec.rb +21 -0
  31. data/spec/lib/net/ntlm/message/type1_spec.rb +42 -0
  32. data/spec/lib/net/ntlm/message/type2_spec.rb +88 -0
  33. data/spec/lib/net/ntlm/message/type3_spec.rb +20 -0
  34. data/spec/lib/net/ntlm/message_spec.rb +17 -0
  35. data/spec/lib/net/ntlm/security_buffer_spec.rb +64 -0
  36. data/spec/lib/net/ntlm/string_spec.rb +72 -0
  37. data/spec/lib/net/ntlm/version_spec.rb +26 -0
  38. data/spec/lib/net/ntlm_spec.rb +121 -0
  39. data/spec/spec_helper.rb +21 -0
  40. data/spec/support/shared/examples/net/ntlm/field_shared.rb +25 -0
  41. data/spec/support/shared/examples/net/ntlm/fieldset_shared.rb +239 -0
  42. data/spec/support/shared/examples/net/ntlm/int_shared.rb +43 -0
  43. data/spec/support/shared/examples/net/ntlm/message_shared.rb +35 -0
  44. metadata +77 -5
  45. data/spec/unit/ntlm_spec.rb +0 -183
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ describe Net::NTLM::Int64LE do
4
+
5
+ int_values = {
6
+ :default => 5294967295,
7
+ :default_hex => [5294967295 & 0x00000000ffffffff, 5294967295 >> 32].pack("V2"),
8
+ :alt => 5294967294,
9
+ :alt_hex => [5294967294 & 0x00000000ffffffff, 5294967294 >> 32].pack("V2"),
10
+ :small => "\x5C\x24\x10\x0f",
11
+ :size => 8,
12
+ :bits => 64
13
+ }
14
+
15
+
16
+ it_behaves_like 'a field', 252716124, false
17
+ it_behaves_like 'an integer field', int_values
18
+
19
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Net::NTLM::Message::Type0 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 => 0, :active => true },
8
+ ]
9
+ flags = [
10
+ :UNICODE,
11
+ :OEM,
12
+ :REQUEST_TARGET,
13
+ :NTLM,
14
+ :ALWAYS_SIGN,
15
+ :NTLM2_KEY
16
+ ]
17
+ it_behaves_like 'a fieldset', fields
18
+ it_behaves_like 'a message', flags
19
+
20
+
21
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Net::NTLM::Message::Type1 do
4
+ fields = [
5
+ { :name => :sign, :class => Net::NTLM::String, :value => Net::NTLM::SSP_SIGN, :active => true },
6
+ { :name => :type, :class => Net::NTLM::Int32LE, :value => 1, :active => true },
7
+ { :name => :flag, :class => Net::NTLM::Int32LE, :value => Net::NTLM::DEFAULT_FLAGS[:TYPE1], :active => true },
8
+ { :name => :domain, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
9
+ { :name => :workstation, :class => Net::NTLM::SecurityBuffer, :value => Socket.gethostname, :active => true },
10
+ { :name => :padding, :class => Net::NTLM::String, :value => '', :active => false },
11
+ ]
12
+ flags = [
13
+ :UNICODE,
14
+ :OEM,
15
+ :REQUEST_TARGET,
16
+ :NTLM,
17
+ :ALWAYS_SIGN,
18
+ :NTLM2_KEY
19
+ ]
20
+ it_behaves_like 'a fieldset', fields
21
+ it_behaves_like 'a message', flags
22
+
23
+ let(:type1_packet) {"TlRMTVNTUAABAAAAB4IIAAAAAAAgAAAAAAAAACAAAAA="}
24
+
25
+ it 'should deserialize' do
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 == ''
34
+ end
35
+
36
+ it 'should serialize' do
37
+ t1 = Net::NTLM::Message::Type1.new
38
+ t1.workstation = ''
39
+ t1.encode64.should == type1_packet
40
+ end
41
+
42
+ end
@@ -0,0 +1,88 @@
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 => :padding, :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
+ 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"
35
+
36
+ t2_target_info = Net::NTLM::EncodeUtil.decode_utf16le(t2.target_info)
37
+ 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"
39
+ else
40
+ t2_target_info.should == "\u0002\u001CVAGRANT-2008R2\u0001\u001CVAGRANT-2008R2\u0004\u001Cvagrant-2008R2\u0003\u001Cvagrant-2008R2\a\b፤ᐝ❴ǎ\0\0"
41
+ end
42
+
43
+ Net::NTLM::EncodeUtil.decode_utf16le(t2.target_name).should == "VAGRANT-2008R2"
44
+ t2.type.should == 2
45
+ end
46
+
47
+ it 'should serialize' do
48
+ source = Net::NTLM::Message.decode64(type2_packet)
49
+
50
+ t2 = Net::NTLM::Message::Type2.new
51
+ t2.challenge = source.challenge
52
+ t2.context = source.context
53
+ t2.flag = source.flag
54
+ t2.padding = source.padding
55
+ t2.sign = source.sign
56
+ t2.target_info = source.target_info
57
+ t2.target_name = source.target_name
58
+ t2.type = source.type
59
+ t2.enable(:context)
60
+ t2.enable(:target_info)
61
+ t2.enable(:padding)
62
+
63
+ t2.encode64.should == type2_packet
64
+ end
65
+
66
+ it 'should generate a type 3 response' do
67
+ t2 = Net::NTLM::Message.decode64(type2_packet)
68
+
69
+ type3_known = Net::NTLM::Message.decode64(type3_packet)
70
+ type3_known.flag = 0x028a8205
71
+ type3_known.enable(:session_key)
72
+ type3_known.enable(:flag)
73
+
74
+ 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 == ''
81
+ end
82
+
83
+ it 'should upcase domain when provided' do
84
+ t2 = Net::NTLM::Message.decode64(type2_packet)
85
+ 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"
87
+ end
88
+ end
@@ -0,0 +1,20 @@
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 => :flag, :class => Net::NTLM::Int64LE, :value => 0, :active => false },
9
+ { :name => :lm_response, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
10
+ { :name => :ntlm_response, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
11
+ { :name => :domain, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
12
+ { :name => :user, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
13
+ { :name => :workstation, :class => Net::NTLM::SecurityBuffer, :value => '', :active => true },
14
+ { :name => :session_key, :class => Net::NTLM::SecurityBuffer, :value => '', :active => false },
15
+ ]
16
+ flags = []
17
+ it_behaves_like 'a fieldset', fields
18
+ it_behaves_like 'a message', flags
19
+
20
+ end
@@ -0,0 +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
+
17
+ end
@@ -0,0 +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
+ domain_security_buffer.value.should == 'DOMAIN1'
28
+ end
29
+
30
+ it 'should adjust the length field to the size of the new value' do
31
+ domain_security_buffer.length.should == 7
32
+ end
33
+
34
+ it 'should adjust the allocated field to the size of the new value' do
35
+ domain_security_buffer.allocated.should == 7
36
+ end
37
+ end
38
+
39
+ context '#data_size' do
40
+ it 'should return the size of the value if active' do
41
+ domain_security_buffer.data_size.should == 11
42
+ end
43
+
44
+ it 'should return 0 if inactive' do
45
+ domain_security_buffer.active = false
46
+ domain_security_buffer.data_size.should == 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
+ domain_security_buffer.parse(string_to_parse).should == 8
60
+ domain_security_buffer.value.should == 'FooBarBa'
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +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
+ active.serialize.should == 'Test'
26
+ end
27
+
28
+ it 'should return an empty string when inactive' do
29
+ inactive.serialize.should == ''
30
+ end
31
+
32
+ it 'should coerce non-string values into strings' do
33
+ active.value = 15
34
+ active.serialize.should == '15'
35
+ end
36
+
37
+ it 'should return empty string on a nil' do
38
+ active.value = nil
39
+ active.serialize.should == ''
40
+ end
41
+ end
42
+
43
+ context '#value=' do
44
+ it 'should set active to false if it empty' do
45
+ active.value = ''
46
+ active.active.should == false
47
+ end
48
+
49
+ it 'should adjust the size based on the value set' do
50
+ active.size.should == 4
51
+ active.value = 'Foobar'
52
+ active.size.should == 6
53
+ end
54
+ end
55
+
56
+ context '#parse' do
57
+ it 'should read in a string of the proper size' do
58
+ active.parse('tseT').should == 4
59
+ active.value.should == 'tseT'
60
+ end
61
+
62
+ it 'should not read in a string that is too small' do
63
+ active.parse('B').should == 0
64
+ active.value.should == 'Test'
65
+ end
66
+
67
+ it 'should be able to read from an offset and only for the given size' do
68
+ active.parse('FooBarBaz',3).should == 4
69
+ active.value.should == 'BarB'
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Net::NTLM::VERSION do
4
+
5
+ it 'should contain an integer value for Major Version' do
6
+ Net::NTLM::VERSION::MAJOR.should be_an Integer
7
+ end
8
+
9
+ it 'should contain an integer value for Minor Version' do
10
+ Net::NTLM::VERSION::MINOR.should be_an Integer
11
+ end
12
+
13
+ it 'should contain an integer value for Patch Version' do
14
+ Net::NTLM::VERSION::TINY.should be_an Integer
15
+ end
16
+
17
+ it 'should contain an aggregate version string' do
18
+ string = [
19
+ Net::NTLM::VERSION::MAJOR,
20
+ Net::NTLM::VERSION::MINOR,
21
+ Net::NTLM::VERSION::TINY
22
+ ].join('.')
23
+ Net::NTLM::VERSION::STRING.should be_a String
24
+ Net::NTLM::VERSION::STRING.should == string
25
+ end
26
+ end
@@ -0,0 +1,121 @@
1
+
2
+ require 'rspec'
3
+ require 'net/ntlm'
4
+
5
+ describe Net::NTLM do
6
+ let(:passwd) {"SecREt01"}
7
+ let(:user) {"user"}
8
+ let(:domain) {"domain"}
9
+ let(:challenge) {["0123456789abcdef"].pack("H*")}
10
+ let(:client_ch) {["ffffff0011223344"].pack("H*")}
11
+ let(:timestamp) {1055844000}
12
+ let(:trgt_info) {[
13
+ "02000c0044004f004d00410049004e00" +
14
+ "01000c00530045005200560045005200" +
15
+ "0400140064006f006d00610069006e00" +
16
+ "2e0063006f006d000300220073006500" +
17
+ "72007600650072002e0064006f006d00" +
18
+ "610069006e002e0063006f006d000000" +
19
+ "0000"
20
+ ].pack("H*")}
21
+ let(:padded_pwd) { passwd.upcase.ljust(14, "\0")}
22
+ let(:keys) { Net::NTLM.gen_keys(padded_pwd)}
23
+
24
+ it 'should convert a value to 64-bit LE Integer' do
25
+ Net::NTLM.pack_int64le(42).should == "\x2A\x00\x00\x00\x00\x00\x00\x00"
26
+ end
27
+
28
+ it 'should split a string into an array of slices, 7 chars or less' do
29
+ Net::NTLM.split7("HelloWorld!").should == [ 'HelloWo', 'rld!']
30
+ end
31
+
32
+ it 'should generate DES keys from the supplied string' do
33
+ first_key = ["52a2516b252a5161"].pack('H*')
34
+ second_key = ["3180010101010101"].pack('H*')
35
+ Net::NTLM.gen_keys(padded_pwd).should == [first_key, second_key]
36
+ end
37
+
38
+ it 'should encrypt the string with DES for each key supplied' do
39
+ first_crypt = ["ff3750bcc2b22412"].pack('H*')
40
+ second_crypt = ["c2265b23734e0dac"].pack('H*')
41
+ Net::NTLM::apply_des(Net::NTLM::LM_MAGIC, keys).should == [first_crypt, second_crypt]
42
+ end
43
+
44
+ it 'should generate an lm_hash' do
45
+ Net::NTLM::lm_hash(passwd).should == ["ff3750bcc2b22412c2265b23734e0dac"].pack("H*")
46
+ end
47
+
48
+ it 'should generate an ntlm_hash' do
49
+ Net::NTLM::ntlm_hash(passwd).should == ["cd06ca7c7e10c99b1d33b7485a2ed808"].pack("H*")
50
+ end
51
+
52
+ it 'should generate an ntlmv2_hash' do
53
+ Net::NTLM::ntlmv2_hash(user, passwd, domain).should == ["04b8e0ba74289cc540826bab1dee63ae"].pack("H*")
54
+ end
55
+
56
+ it 'should generate an lm_response' do
57
+ Net::NTLM::lm_response(
58
+ {
59
+ :lm_hash => Net::NTLM::lm_hash(passwd),
60
+ :challenge => challenge
61
+ }
62
+ ).should == ["c337cd5cbd44fc9782a667af6d427c6de67c20c2d3e77c56"].pack("H*")
63
+ end
64
+
65
+ it 'should generate an ntlm_response' do
66
+ ntlm_hash = Net::NTLM::ntlm_hash(passwd)
67
+ Net::NTLM::ntlm_response(
68
+ {
69
+ :ntlm_hash => ntlm_hash,
70
+ :challenge => challenge
71
+ }
72
+ ).should == ["25a98c1c31e81847466b29b2df4680f39958fb8c213a9cc6"].pack("H*")
73
+ end
74
+
75
+ it 'should generate a lvm2_response' do
76
+ Net::NTLM::lmv2_response(
77
+ {
78
+ :ntlmv2_hash => Net::NTLM::ntlmv2_hash(user, passwd, domain),
79
+ :challenge => challenge
80
+ },
81
+ { :client_challenge => client_ch }
82
+ ).should == ["d6e6152ea25d03b7c6ba6629c2d6aaf0ffffff0011223344"].pack("H*")
83
+ end
84
+
85
+ it 'should generate a ntlmv2_response' do
86
+ Net::NTLM::ntlmv2_response(
87
+ {
88
+ :ntlmv2_hash => Net::NTLM::ntlmv2_hash(user, passwd, domain),
89
+ :challenge => challenge,
90
+ :target_info => trgt_info
91
+ },
92
+ {
93
+ :timestamp => timestamp,
94
+ :client_challenge => client_ch
95
+ }
96
+ ).should == [
97
+ "cbabbca713eb795d04c97abc01ee4983" +
98
+ "01010000000000000090d336b734c301" +
99
+ "ffffff00112233440000000002000c00" +
100
+ "44004f004d00410049004e0001000c00" +
101
+ "53004500520056004500520004001400" +
102
+ "64006f006d00610069006e002e006300" +
103
+ "6f006d00030022007300650072007600" +
104
+ "650072002e0064006f006d0061006900" +
105
+ "6e002e0063006f006d00000000000000" +
106
+ "0000"
107
+ ].pack("H*")
108
+ end
109
+
110
+ it 'should generate a ntlm2_session' do
111
+ session = Net::NTLM::ntlm2_session(
112
+ {
113
+ :ntlm_hash => Net::NTLM::ntlm_hash(passwd),
114
+ :challenge => challenge
115
+ },
116
+ { :client_challenge => client_ch }
117
+ )
118
+ session[0].should == ["ffffff001122334400000000000000000000000000000000"].pack("H*")
119
+ session[1].should == ["10d550832d12b2ccb79d5ad1f4eed3df82aca4c3681dd455"].pack("H*")
120
+ end
121
+ end