rubyntlm 0.6.1 → 0.6.2
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/.gitignore +4 -3
- data/.rspec +2 -2
- data/.travis.yml +13 -12
- data/CHANGELOG.md +118 -6
- data/Gemfile +3 -3
- data/LICENSE +19 -19
- data/Rakefile +25 -22
- data/lib/net/ntlm.rb +266 -266
- data/lib/net/ntlm/blob.rb +28 -28
- data/lib/net/ntlm/channel_binding.rb +65 -65
- data/lib/net/ntlm/client.rb +65 -65
- data/lib/net/ntlm/client/session.rb +237 -237
- data/lib/net/ntlm/encode_util.rb +48 -48
- data/lib/net/ntlm/exceptions.rb +14 -14
- data/lib/net/ntlm/field.rb +34 -34
- data/lib/net/ntlm/field_set.rb +129 -129
- data/lib/net/ntlm/int16_le.rb +25 -25
- data/lib/net/ntlm/int32_le.rb +24 -24
- data/lib/net/ntlm/int64_le.rb +25 -25
- data/lib/net/ntlm/message.rb +129 -129
- data/lib/net/ntlm/message/type0.rb +16 -16
- data/lib/net/ntlm/message/type1.rb +18 -18
- data/lib/net/ntlm/message/type2.rb +102 -102
- data/lib/net/ntlm/message/type3.rb +131 -131
- data/lib/net/ntlm/security_buffer.rb +47 -47
- data/lib/net/ntlm/string.rb +34 -34
- data/lib/net/ntlm/target_info.rb +89 -89
- data/lib/net/ntlm/version.rb +11 -11
- data/rubyntlm.gemspec +29 -28
- data/spec/lib/net/ntlm/blob_spec.rb +16 -16
- data/spec/lib/net/ntlm/channel_binding_spec.rb +17 -17
- data/spec/lib/net/ntlm/client/session_spec.rb +68 -68
- data/spec/lib/net/ntlm/client_spec.rb +64 -64
- data/spec/lib/net/ntlm/encode_util_spec.rb +16 -16
- data/spec/lib/net/ntlm/field_set_spec.rb +33 -33
- data/spec/lib/net/ntlm/field_spec.rb +34 -34
- data/spec/lib/net/ntlm/int16_le_spec.rb +17 -17
- data/spec/lib/net/ntlm/int32_le_spec.rb +18 -18
- data/spec/lib/net/ntlm/int64_le_spec.rb +18 -18
- data/spec/lib/net/ntlm/message/type0_spec.rb +20 -20
- data/spec/lib/net/ntlm/message/type1_spec.rb +131 -131
- data/spec/lib/net/ntlm/message/type2_spec.rb +132 -132
- data/spec/lib/net/ntlm/message/type3_spec.rb +225 -225
- data/spec/lib/net/ntlm/message_spec.rb +16 -16
- data/spec/lib/net/ntlm/security_buffer_spec.rb +64 -64
- data/spec/lib/net/ntlm/string_spec.rb +72 -72
- data/spec/lib/net/ntlm/target_info_spec.rb +76 -76
- data/spec/lib/net/ntlm/version_spec.rb +27 -27
- data/spec/lib/net/ntlm_spec.rb +127 -127
- data/spec/spec_helper.rb +22 -22
- data/spec/support/certificates/sha_256_hash.pem +19 -19
- data/spec/support/shared/examples/net/ntlm/field_shared.rb +25 -25
- data/spec/support/shared/examples/net/ntlm/fieldset_shared.rb +239 -239
- data/spec/support/shared/examples/net/ntlm/int_shared.rb +43 -43
- data/spec/support/shared/examples/net/ntlm/message_shared.rb +35 -35
- metadata +17 -3
data/lib/net/ntlm/encode_util.rb
CHANGED
@@ -1,48 +1,48 @@
|
|
1
|
-
module Net
|
2
|
-
module NTLM
|
3
|
-
|
4
|
-
class EncodeUtil
|
5
|
-
if RUBY_VERSION == "1.8.7"
|
6
|
-
require "kconv"
|
7
|
-
|
8
|
-
# Decode a UTF16 string to a ASCII string
|
9
|
-
# @param [String] str The string to convert
|
10
|
-
def self.decode_utf16le(str)
|
11
|
-
Kconv.kconv(swap16(str), Kconv::ASCII, Kconv::UTF16)
|
12
|
-
end
|
13
|
-
|
14
|
-
# Encodes a ASCII string to a UTF16 string
|
15
|
-
# @param [String] str The string to convert
|
16
|
-
def self.encode_utf16le(str)
|
17
|
-
swap16(Kconv.kconv(str, Kconv::UTF16, Kconv::ASCII))
|
18
|
-
end
|
19
|
-
|
20
|
-
# Taggle the strings endianness between big/little and little/big
|
21
|
-
# @param [String] str The string to swap the endianness on
|
22
|
-
def self.swap16(str)
|
23
|
-
str.unpack("v*").pack("n*")
|
24
|
-
end
|
25
|
-
else # Use native 1.9 string encoding functions
|
26
|
-
|
27
|
-
# Decode a UTF16 string to a ASCII string
|
28
|
-
# @param [String] str The string to convert
|
29
|
-
def self.decode_utf16le(str)
|
30
|
-
str = str.dup.force_encoding(Encoding::UTF_16LE)
|
31
|
-
str.encode(Encoding::UTF_8, Encoding::UTF_16LE).force_encoding('UTF-8')
|
32
|
-
end
|
33
|
-
|
34
|
-
# Encodes a ASCII string to a UTF16 string
|
35
|
-
# @param [String] str The string to convert
|
36
|
-
# @note This implementation may seem stupid but the problem is that UTF16-LE and UTF-8 are incompatiable
|
37
|
-
# encodings. This library uses string contatination to build the packet bytes. The end result is that
|
38
|
-
# you can either marshal the encodings elsewhere of simply know that each time you call encode_utf16le
|
39
|
-
# the function will convert the string bytes to UTF-16LE and note the encoding as UTF-8 so that byte
|
40
|
-
# concatination works seamlessly.
|
41
|
-
def self.encode_utf16le(str)
|
42
|
-
str.dup.force_encoding('UTF-8').encode(Encoding::UTF_16LE, Encoding::UTF_8).force_encoding('UTF-8')
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
end
|
48
|
-
end
|
1
|
+
module Net
|
2
|
+
module NTLM
|
3
|
+
|
4
|
+
class EncodeUtil
|
5
|
+
if RUBY_VERSION == "1.8.7"
|
6
|
+
require "kconv"
|
7
|
+
|
8
|
+
# Decode a UTF16 string to a ASCII string
|
9
|
+
# @param [String] str The string to convert
|
10
|
+
def self.decode_utf16le(str)
|
11
|
+
Kconv.kconv(swap16(str), Kconv::ASCII, Kconv::UTF16)
|
12
|
+
end
|
13
|
+
|
14
|
+
# Encodes a ASCII string to a UTF16 string
|
15
|
+
# @param [String] str The string to convert
|
16
|
+
def self.encode_utf16le(str)
|
17
|
+
swap16(Kconv.kconv(str, Kconv::UTF16, Kconv::ASCII))
|
18
|
+
end
|
19
|
+
|
20
|
+
# Taggle the strings endianness between big/little and little/big
|
21
|
+
# @param [String] str The string to swap the endianness on
|
22
|
+
def self.swap16(str)
|
23
|
+
str.unpack("v*").pack("n*")
|
24
|
+
end
|
25
|
+
else # Use native 1.9 string encoding functions
|
26
|
+
|
27
|
+
# Decode a UTF16 string to a ASCII string
|
28
|
+
# @param [String] str The string to convert
|
29
|
+
def self.decode_utf16le(str)
|
30
|
+
str = str.dup.force_encoding(Encoding::UTF_16LE)
|
31
|
+
str.encode(Encoding::UTF_8, Encoding::UTF_16LE).force_encoding('UTF-8')
|
32
|
+
end
|
33
|
+
|
34
|
+
# Encodes a ASCII string to a UTF16 string
|
35
|
+
# @param [String] str The string to convert
|
36
|
+
# @note This implementation may seem stupid but the problem is that UTF16-LE and UTF-8 are incompatiable
|
37
|
+
# encodings. This library uses string contatination to build the packet bytes. The end result is that
|
38
|
+
# you can either marshal the encodings elsewhere of simply know that each time you call encode_utf16le
|
39
|
+
# the function will convert the string bytes to UTF-16LE and note the encoding as UTF-8 so that byte
|
40
|
+
# concatination works seamlessly.
|
41
|
+
def self.encode_utf16le(str)
|
42
|
+
str.dup.force_encoding('UTF-8').encode(Encoding::UTF_16LE, Encoding::UTF_8).force_encoding('UTF-8')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
data/lib/net/ntlm/exceptions.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
|
-
module Net
|
2
|
-
module NTLM
|
3
|
-
class NtlmError < StandardError; end
|
4
|
-
|
5
|
-
class InvalidTargetDataError < NtlmError
|
6
|
-
attr_reader :data
|
7
|
-
|
8
|
-
def initialize(msg, data)
|
9
|
-
@data = data
|
10
|
-
super(msg)
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
1
|
+
module Net
|
2
|
+
module NTLM
|
3
|
+
class NtlmError < StandardError; end
|
4
|
+
|
5
|
+
class InvalidTargetDataError < NtlmError
|
6
|
+
attr_reader :data
|
7
|
+
|
8
|
+
def initialize(msg, data)
|
9
|
+
@data = data
|
10
|
+
super(msg)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
data/lib/net/ntlm/field.rb
CHANGED
@@ -1,35 +1,35 @@
|
|
1
|
-
module Net
|
2
|
-
module NTLM
|
3
|
-
|
4
|
-
# base classes for primitives
|
5
|
-
# @private
|
6
|
-
class Field
|
7
|
-
attr_accessor :active, :value
|
8
|
-
|
9
|
-
def initialize(opts)
|
10
|
-
@value = opts[:value]
|
11
|
-
@active = opts[:active].nil? ? true : opts[:active]
|
12
|
-
@size = opts[:size].nil? ? 0 : opts[:size]
|
13
|
-
end
|
14
|
-
|
15
|
-
def size
|
16
|
-
@active ? @size : 0
|
17
|
-
end
|
18
|
-
|
19
|
-
# Serializer function for field data
|
20
|
-
# Exists in this class to be overridden by child classes
|
21
|
-
def serialize
|
22
|
-
raise NotImplementedError
|
23
|
-
end
|
24
|
-
|
25
|
-
# Parser function for field data
|
26
|
-
# Exists in this class to be overridden by child classes
|
27
|
-
def parse(str, offset=0)
|
28
|
-
raise NotImplementedError
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
|
34
|
-
end
|
1
|
+
module Net
|
2
|
+
module NTLM
|
3
|
+
|
4
|
+
# base classes for primitives
|
5
|
+
# @private
|
6
|
+
class Field
|
7
|
+
attr_accessor :active, :value
|
8
|
+
|
9
|
+
def initialize(opts)
|
10
|
+
@value = opts[:value]
|
11
|
+
@active = opts[:active].nil? ? true : opts[:active]
|
12
|
+
@size = opts[:size].nil? ? 0 : opts[:size]
|
13
|
+
end
|
14
|
+
|
15
|
+
def size
|
16
|
+
@active ? @size : 0
|
17
|
+
end
|
18
|
+
|
19
|
+
# Serializer function for field data
|
20
|
+
# Exists in this class to be overridden by child classes
|
21
|
+
def serialize
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
# Parser function for field data
|
26
|
+
# Exists in this class to be overridden by child classes
|
27
|
+
def parse(str, offset=0)
|
28
|
+
raise NotImplementedError
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
end
|
35
35
|
end
|
data/lib/net/ntlm/field_set.rb
CHANGED
@@ -1,129 +1,129 @@
|
|
1
|
-
module Net
|
2
|
-
module NTLM
|
3
|
-
|
4
|
-
# base class of data structure
|
5
|
-
class FieldSet
|
6
|
-
class << FieldSet
|
7
|
-
|
8
|
-
# @macro string_security_buffer
|
9
|
-
# @method $1
|
10
|
-
# @method $1=
|
11
|
-
# @return [String]
|
12
|
-
def string(name, opts)
|
13
|
-
add_field(name, Net::NTLM::String, opts)
|
14
|
-
end
|
15
|
-
|
16
|
-
# @macro int16le_security_buffer
|
17
|
-
# @method $1
|
18
|
-
# @method $1=
|
19
|
-
# @return [Int16LE]
|
20
|
-
def int16LE(name, opts)
|
21
|
-
add_field(name, Net::NTLM::Int16LE, opts)
|
22
|
-
end
|
23
|
-
|
24
|
-
# @macro int32le_security_buffer
|
25
|
-
# @method $1
|
26
|
-
# @method $1=
|
27
|
-
# @return [Int32LE]
|
28
|
-
def int32LE(name, opts)
|
29
|
-
add_field(name, Net::NTLM::Int32LE, opts)
|
30
|
-
end
|
31
|
-
|
32
|
-
# @macro int64le_security_buffer
|
33
|
-
# @method $1
|
34
|
-
# @method $1=
|
35
|
-
# @return [Int64]
|
36
|
-
def int64LE(name, opts)
|
37
|
-
add_field(name, Net::NTLM::Int64LE, opts)
|
38
|
-
end
|
39
|
-
|
40
|
-
# @macro security_buffer
|
41
|
-
# @method $1
|
42
|
-
# @method $1=
|
43
|
-
# @return [SecurityBuffer]
|
44
|
-
def security_buffer(name, opts)
|
45
|
-
add_field(name, Net::NTLM::SecurityBuffer, opts)
|
46
|
-
end
|
47
|
-
|
48
|
-
def prototypes
|
49
|
-
@proto
|
50
|
-
end
|
51
|
-
|
52
|
-
def names
|
53
|
-
return [] if @proto.nil?
|
54
|
-
@proto.map{|n, t, o| n}
|
55
|
-
end
|
56
|
-
|
57
|
-
def types
|
58
|
-
return [] if @proto.nil?
|
59
|
-
@proto.map{|n, t, o| t}
|
60
|
-
end
|
61
|
-
|
62
|
-
def opts
|
63
|
-
return [] if @proto.nil?
|
64
|
-
@proto.map{|n, t, o| o}
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
def add_field(name, type, opts)
|
70
|
-
(@proto ||= []).push [name, type, opts]
|
71
|
-
define_accessor name
|
72
|
-
end
|
73
|
-
|
74
|
-
def define_accessor(name)
|
75
|
-
module_eval(<<-End, __FILE__, __LINE__ + 1)
|
76
|
-
def #{name}
|
77
|
-
self['#{name}'].value
|
78
|
-
end
|
79
|
-
|
80
|
-
def #{name}=(val)
|
81
|
-
self['#{name}'].value = val
|
82
|
-
end
|
83
|
-
End
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
def initialize
|
88
|
-
@alist = self.class.prototypes.map{ |n, t, o| [n, t.new(o)] }
|
89
|
-
end
|
90
|
-
|
91
|
-
def parse(str, offset=0)
|
92
|
-
@alist.inject(offset){|cur, a| cur += a[1].parse(str, cur)}
|
93
|
-
end
|
94
|
-
|
95
|
-
def serialize
|
96
|
-
@alist.map{|n, f| f.serialize }.join
|
97
|
-
end
|
98
|
-
|
99
|
-
def size
|
100
|
-
@alist.inject(0){|sum, a| sum += a[1].size}
|
101
|
-
end
|
102
|
-
|
103
|
-
def [](name)
|
104
|
-
a = @alist.assoc(name.to_s.intern)
|
105
|
-
raise ArgumentError, "no such field: #{name}" unless a
|
106
|
-
a[1]
|
107
|
-
end
|
108
|
-
|
109
|
-
def []=(name, val)
|
110
|
-
a = @alist.assoc(name.to_s.intern)
|
111
|
-
raise ArgumentError, "no such field: #{name}" unless a
|
112
|
-
a[1] = val
|
113
|
-
end
|
114
|
-
|
115
|
-
def enable(name)
|
116
|
-
self[name].active = true
|
117
|
-
end
|
118
|
-
|
119
|
-
def disable(name)
|
120
|
-
self[name].active = false
|
121
|
-
end
|
122
|
-
|
123
|
-
def has_disabled_fields?
|
124
|
-
@alist.any? { |name, field| !field.active }
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
end
|
129
|
-
end
|
1
|
+
module Net
|
2
|
+
module NTLM
|
3
|
+
|
4
|
+
# base class of data structure
|
5
|
+
class FieldSet
|
6
|
+
class << FieldSet
|
7
|
+
|
8
|
+
# @macro string_security_buffer
|
9
|
+
# @method $1
|
10
|
+
# @method $1=
|
11
|
+
# @return [String]
|
12
|
+
def string(name, opts)
|
13
|
+
add_field(name, Net::NTLM::String, opts)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @macro int16le_security_buffer
|
17
|
+
# @method $1
|
18
|
+
# @method $1=
|
19
|
+
# @return [Int16LE]
|
20
|
+
def int16LE(name, opts)
|
21
|
+
add_field(name, Net::NTLM::Int16LE, opts)
|
22
|
+
end
|
23
|
+
|
24
|
+
# @macro int32le_security_buffer
|
25
|
+
# @method $1
|
26
|
+
# @method $1=
|
27
|
+
# @return [Int32LE]
|
28
|
+
def int32LE(name, opts)
|
29
|
+
add_field(name, Net::NTLM::Int32LE, opts)
|
30
|
+
end
|
31
|
+
|
32
|
+
# @macro int64le_security_buffer
|
33
|
+
# @method $1
|
34
|
+
# @method $1=
|
35
|
+
# @return [Int64]
|
36
|
+
def int64LE(name, opts)
|
37
|
+
add_field(name, Net::NTLM::Int64LE, opts)
|
38
|
+
end
|
39
|
+
|
40
|
+
# @macro security_buffer
|
41
|
+
# @method $1
|
42
|
+
# @method $1=
|
43
|
+
# @return [SecurityBuffer]
|
44
|
+
def security_buffer(name, opts)
|
45
|
+
add_field(name, Net::NTLM::SecurityBuffer, opts)
|
46
|
+
end
|
47
|
+
|
48
|
+
def prototypes
|
49
|
+
@proto
|
50
|
+
end
|
51
|
+
|
52
|
+
def names
|
53
|
+
return [] if @proto.nil?
|
54
|
+
@proto.map{|n, t, o| n}
|
55
|
+
end
|
56
|
+
|
57
|
+
def types
|
58
|
+
return [] if @proto.nil?
|
59
|
+
@proto.map{|n, t, o| t}
|
60
|
+
end
|
61
|
+
|
62
|
+
def opts
|
63
|
+
return [] if @proto.nil?
|
64
|
+
@proto.map{|n, t, o| o}
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def add_field(name, type, opts)
|
70
|
+
(@proto ||= []).push [name, type, opts]
|
71
|
+
define_accessor name
|
72
|
+
end
|
73
|
+
|
74
|
+
def define_accessor(name)
|
75
|
+
module_eval(<<-End, __FILE__, __LINE__ + 1)
|
76
|
+
def #{name}
|
77
|
+
self['#{name}'].value
|
78
|
+
end
|
79
|
+
|
80
|
+
def #{name}=(val)
|
81
|
+
self['#{name}'].value = val
|
82
|
+
end
|
83
|
+
End
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def initialize
|
88
|
+
@alist = self.class.prototypes.map{ |n, t, o| [n, t.new(o)] }
|
89
|
+
end
|
90
|
+
|
91
|
+
def parse(str, offset=0)
|
92
|
+
@alist.inject(offset){|cur, a| cur += a[1].parse(str, cur)}
|
93
|
+
end
|
94
|
+
|
95
|
+
def serialize
|
96
|
+
@alist.map{|n, f| f.serialize }.join
|
97
|
+
end
|
98
|
+
|
99
|
+
def size
|
100
|
+
@alist.inject(0){|sum, a| sum += a[1].size}
|
101
|
+
end
|
102
|
+
|
103
|
+
def [](name)
|
104
|
+
a = @alist.assoc(name.to_s.intern)
|
105
|
+
raise ArgumentError, "no such field: #{name}" unless a
|
106
|
+
a[1]
|
107
|
+
end
|
108
|
+
|
109
|
+
def []=(name, val)
|
110
|
+
a = @alist.assoc(name.to_s.intern)
|
111
|
+
raise ArgumentError, "no such field: #{name}" unless a
|
112
|
+
a[1] = val
|
113
|
+
end
|
114
|
+
|
115
|
+
def enable(name)
|
116
|
+
self[name].active = true
|
117
|
+
end
|
118
|
+
|
119
|
+
def disable(name)
|
120
|
+
self[name].active = false
|
121
|
+
end
|
122
|
+
|
123
|
+
def has_disabled_fields?
|
124
|
+
@alist.any? { |name, field| !field.active }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
end
|