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/int16_le.rb
CHANGED
@@ -1,26 +1,26 @@
|
|
1
|
-
module Net
|
2
|
-
module NTLM
|
3
|
-
|
4
|
-
class Int16LE < Field
|
5
|
-
|
6
|
-
def initialize(opt)
|
7
|
-
super(opt)
|
8
|
-
@size = 2
|
9
|
-
end
|
10
|
-
|
11
|
-
def parse(str, offset=0)
|
12
|
-
if @active and str.size >= offset + @size
|
13
|
-
@value = str[offset, @size].unpack("v")[0]
|
14
|
-
@size
|
15
|
-
else
|
16
|
-
0
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def serialize
|
21
|
-
[@value].pack("v")
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
1
|
+
module Net
|
2
|
+
module NTLM
|
3
|
+
|
4
|
+
class Int16LE < Field
|
5
|
+
|
6
|
+
def initialize(opt)
|
7
|
+
super(opt)
|
8
|
+
@size = 2
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse(str, offset=0)
|
12
|
+
if @active and str.size >= offset + @size
|
13
|
+
@value = str[offset, @size].unpack("v")[0]
|
14
|
+
@size
|
15
|
+
else
|
16
|
+
0
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def serialize
|
21
|
+
[@value].pack("v")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
26
|
end
|
data/lib/net/ntlm/int32_le.rb
CHANGED
@@ -1,25 +1,25 @@
|
|
1
|
-
module Net
|
2
|
-
module NTLM
|
3
|
-
|
4
|
-
class Int32LE < Field
|
5
|
-
def initialize(opt)
|
6
|
-
super(opt)
|
7
|
-
@size = 4
|
8
|
-
end
|
9
|
-
|
10
|
-
def parse(str, offset=0)
|
11
|
-
if @active and str.size >= offset + @size
|
12
|
-
@value = str.slice(offset, @size).unpack("V")[0]
|
13
|
-
@size
|
14
|
-
else
|
15
|
-
0
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def serialize
|
20
|
-
[@value].pack("V") if @active
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
end
|
1
|
+
module Net
|
2
|
+
module NTLM
|
3
|
+
|
4
|
+
class Int32LE < Field
|
5
|
+
def initialize(opt)
|
6
|
+
super(opt)
|
7
|
+
@size = 4
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse(str, offset=0)
|
11
|
+
if @active and str.size >= offset + @size
|
12
|
+
@value = str.slice(offset, @size).unpack("V")[0]
|
13
|
+
@size
|
14
|
+
else
|
15
|
+
0
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def serialize
|
20
|
+
[@value].pack("V") if @active
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
25
|
end
|
data/lib/net/ntlm/int64_le.rb
CHANGED
@@ -1,26 +1,26 @@
|
|
1
|
-
module Net
|
2
|
-
module NTLM
|
3
|
-
|
4
|
-
class Int64LE < Field
|
5
|
-
def initialize(opt)
|
6
|
-
super(opt)
|
7
|
-
@size = 8
|
8
|
-
end
|
9
|
-
|
10
|
-
def parse(str, offset=0)
|
11
|
-
if @active and str.size >= offset + @size
|
12
|
-
d, u = str.slice(offset, @size).unpack("V2")
|
13
|
-
@value = (u * 0x100000000 + d)
|
14
|
-
@size
|
15
|
-
else
|
16
|
-
0
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def serialize
|
21
|
-
[@value & 0x00000000ffffffff, @value >> 32].pack("V2") if @active
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
1
|
+
module Net
|
2
|
+
module NTLM
|
3
|
+
|
4
|
+
class Int64LE < Field
|
5
|
+
def initialize(opt)
|
6
|
+
super(opt)
|
7
|
+
@size = 8
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse(str, offset=0)
|
11
|
+
if @active and str.size >= offset + @size
|
12
|
+
d, u = str.slice(offset, @size).unpack("V2")
|
13
|
+
@value = (u * 0x100000000 + d)
|
14
|
+
@size
|
15
|
+
else
|
16
|
+
0
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def serialize
|
21
|
+
[@value & 0x00000000ffffffff, @value >> 32].pack("V2") if @active
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
26
|
end
|
data/lib/net/ntlm/message.rb
CHANGED
@@ -1,129 +1,129 @@
|
|
1
|
-
module Net
|
2
|
-
module NTLM
|
3
|
-
|
4
|
-
SSP_SIGN = "NTLMSSP\0"
|
5
|
-
|
6
|
-
FLAGS = {
|
7
|
-
:UNICODE => 0x00000001,
|
8
|
-
:OEM => 0x00000002,
|
9
|
-
:REQUEST_TARGET => 0x00000004,
|
10
|
-
:MBZ9 => 0x00000008,
|
11
|
-
:SIGN => 0x00000010,
|
12
|
-
:SEAL => 0x00000020,
|
13
|
-
:NEG_DATAGRAM => 0x00000040,
|
14
|
-
:NETWARE => 0x00000100,
|
15
|
-
:NTLM => 0x00000200,
|
16
|
-
:NEG_NT_ONLY => 0x00000400,
|
17
|
-
:MBZ7 => 0x00000800,
|
18
|
-
:DOMAIN_SUPPLIED => 0x00001000,
|
19
|
-
:WORKSTATION_SUPPLIED => 0x00002000,
|
20
|
-
:LOCAL_CALL => 0x00004000,
|
21
|
-
:ALWAYS_SIGN => 0x00008000,
|
22
|
-
:TARGET_TYPE_DOMAIN => 0x00010000,
|
23
|
-
:NTLM2_KEY => 0x00080000,
|
24
|
-
:TARGET_INFO => 0x00800000,
|
25
|
-
:KEY128 => 0x20000000,
|
26
|
-
:KEY_EXCHANGE => 0x40000000,
|
27
|
-
:KEY56 => 0x80000000
|
28
|
-
}.freeze
|
29
|
-
|
30
|
-
FLAG_KEYS = FLAGS.keys.sort{|a, b| FLAGS[a] <=> FLAGS[b] }
|
31
|
-
|
32
|
-
DEFAULT_FLAGS = {
|
33
|
-
:TYPE1 => FLAGS[:UNICODE] | FLAGS[:OEM] | FLAGS[:REQUEST_TARGET] | FLAGS[:NTLM] | FLAGS[:ALWAYS_SIGN] | FLAGS[:NTLM2_KEY],
|
34
|
-
:TYPE2 => FLAGS[:UNICODE],
|
35
|
-
:TYPE3 => FLAGS[:UNICODE] | FLAGS[:REQUEST_TARGET] | FLAGS[:NTLM] | FLAGS[:ALWAYS_SIGN] | FLAGS[:NTLM2_KEY]
|
36
|
-
}
|
37
|
-
|
38
|
-
|
39
|
-
# @private false
|
40
|
-
class Message < FieldSet
|
41
|
-
class << Message
|
42
|
-
def parse(str)
|
43
|
-
m = Type0.new
|
44
|
-
m.parse(str)
|
45
|
-
case m.type
|
46
|
-
when 1
|
47
|
-
t = Type1.new.parse(str)
|
48
|
-
when 2
|
49
|
-
t = Type2.new.parse(str)
|
50
|
-
when 3
|
51
|
-
t = Type3.new.parse(str)
|
52
|
-
else
|
53
|
-
raise ArgumentError, "unknown type: #{m.type}"
|
54
|
-
end
|
55
|
-
t
|
56
|
-
end
|
57
|
-
|
58
|
-
def decode64(str)
|
59
|
-
parse(Base64.decode64(str))
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# @return [self]
|
64
|
-
def parse(str)
|
65
|
-
super
|
66
|
-
|
67
|
-
while has_disabled_fields? && serialize.size < str.size
|
68
|
-
# enable the next disabled field
|
69
|
-
self.class.names.find { |name| !self[name].active && enable(name) }
|
70
|
-
super
|
71
|
-
end
|
72
|
-
|
73
|
-
self
|
74
|
-
end
|
75
|
-
|
76
|
-
def has_flag?(flag)
|
77
|
-
(self[:flag].value & FLAGS[flag]) == FLAGS[flag]
|
78
|
-
end
|
79
|
-
|
80
|
-
def set_flag(flag)
|
81
|
-
self[:flag].value |= FLAGS[flag]
|
82
|
-
end
|
83
|
-
|
84
|
-
def dump_flags
|
85
|
-
FLAG_KEYS.each{ |k| print(k, "=", has_flag?(k), "\n") }
|
86
|
-
end
|
87
|
-
|
88
|
-
def serialize
|
89
|
-
deflag
|
90
|
-
super + security_buffers.map{|n, f| f.value}.join
|
91
|
-
end
|
92
|
-
|
93
|
-
def encode64
|
94
|
-
Base64.encode64(serialize).gsub(/\n/, '')
|
95
|
-
end
|
96
|
-
|
97
|
-
def decode64(str)
|
98
|
-
parse(Base64.decode64(str))
|
99
|
-
end
|
100
|
-
|
101
|
-
alias head_size size
|
102
|
-
|
103
|
-
def data_size
|
104
|
-
security_buffers.inject(0){|sum, a| sum += a[1].data_size}
|
105
|
-
end
|
106
|
-
|
107
|
-
def size
|
108
|
-
head_size + data_size
|
109
|
-
end
|
110
|
-
|
111
|
-
|
112
|
-
def security_buffers
|
113
|
-
@alist.find_all{|n, f| f.instance_of?(SecurityBuffer)}
|
114
|
-
end
|
115
|
-
|
116
|
-
def deflag
|
117
|
-
security_buffers.inject(head_size){|cur, a|
|
118
|
-
a[1].offset = cur
|
119
|
-
cur += a[1].data_size
|
120
|
-
}
|
121
|
-
end
|
122
|
-
|
123
|
-
def data_edge
|
124
|
-
security_buffers.map{ |n, f| f.active ? f.offset : size}.min
|
125
|
-
end
|
126
|
-
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
1
|
+
module Net
|
2
|
+
module NTLM
|
3
|
+
|
4
|
+
SSP_SIGN = "NTLMSSP\0"
|
5
|
+
|
6
|
+
FLAGS = {
|
7
|
+
:UNICODE => 0x00000001,
|
8
|
+
:OEM => 0x00000002,
|
9
|
+
:REQUEST_TARGET => 0x00000004,
|
10
|
+
:MBZ9 => 0x00000008,
|
11
|
+
:SIGN => 0x00000010,
|
12
|
+
:SEAL => 0x00000020,
|
13
|
+
:NEG_DATAGRAM => 0x00000040,
|
14
|
+
:NETWARE => 0x00000100,
|
15
|
+
:NTLM => 0x00000200,
|
16
|
+
:NEG_NT_ONLY => 0x00000400,
|
17
|
+
:MBZ7 => 0x00000800,
|
18
|
+
:DOMAIN_SUPPLIED => 0x00001000,
|
19
|
+
:WORKSTATION_SUPPLIED => 0x00002000,
|
20
|
+
:LOCAL_CALL => 0x00004000,
|
21
|
+
:ALWAYS_SIGN => 0x00008000,
|
22
|
+
:TARGET_TYPE_DOMAIN => 0x00010000,
|
23
|
+
:NTLM2_KEY => 0x00080000,
|
24
|
+
:TARGET_INFO => 0x00800000,
|
25
|
+
:KEY128 => 0x20000000,
|
26
|
+
:KEY_EXCHANGE => 0x40000000,
|
27
|
+
:KEY56 => 0x80000000
|
28
|
+
}.freeze
|
29
|
+
|
30
|
+
FLAG_KEYS = FLAGS.keys.sort{|a, b| FLAGS[a] <=> FLAGS[b] }
|
31
|
+
|
32
|
+
DEFAULT_FLAGS = {
|
33
|
+
:TYPE1 => FLAGS[:UNICODE] | FLAGS[:OEM] | FLAGS[:REQUEST_TARGET] | FLAGS[:NTLM] | FLAGS[:ALWAYS_SIGN] | FLAGS[:NTLM2_KEY],
|
34
|
+
:TYPE2 => FLAGS[:UNICODE],
|
35
|
+
:TYPE3 => FLAGS[:UNICODE] | FLAGS[:REQUEST_TARGET] | FLAGS[:NTLM] | FLAGS[:ALWAYS_SIGN] | FLAGS[:NTLM2_KEY]
|
36
|
+
}
|
37
|
+
|
38
|
+
|
39
|
+
# @private false
|
40
|
+
class Message < FieldSet
|
41
|
+
class << Message
|
42
|
+
def parse(str)
|
43
|
+
m = Type0.new
|
44
|
+
m.parse(str)
|
45
|
+
case m.type
|
46
|
+
when 1
|
47
|
+
t = Type1.new.parse(str)
|
48
|
+
when 2
|
49
|
+
t = Type2.new.parse(str)
|
50
|
+
when 3
|
51
|
+
t = Type3.new.parse(str)
|
52
|
+
else
|
53
|
+
raise ArgumentError, "unknown type: #{m.type}"
|
54
|
+
end
|
55
|
+
t
|
56
|
+
end
|
57
|
+
|
58
|
+
def decode64(str)
|
59
|
+
parse(Base64.decode64(str))
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [self]
|
64
|
+
def parse(str)
|
65
|
+
super
|
66
|
+
|
67
|
+
while has_disabled_fields? && serialize.size < str.size
|
68
|
+
# enable the next disabled field
|
69
|
+
self.class.names.find { |name| !self[name].active && enable(name) }
|
70
|
+
super
|
71
|
+
end
|
72
|
+
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
76
|
+
def has_flag?(flag)
|
77
|
+
(self[:flag].value & FLAGS[flag]) == FLAGS[flag]
|
78
|
+
end
|
79
|
+
|
80
|
+
def set_flag(flag)
|
81
|
+
self[:flag].value |= FLAGS[flag]
|
82
|
+
end
|
83
|
+
|
84
|
+
def dump_flags
|
85
|
+
FLAG_KEYS.each{ |k| print(k, "=", has_flag?(k), "\n") }
|
86
|
+
end
|
87
|
+
|
88
|
+
def serialize
|
89
|
+
deflag
|
90
|
+
super + security_buffers.map{|n, f| f.value}.join
|
91
|
+
end
|
92
|
+
|
93
|
+
def encode64
|
94
|
+
Base64.encode64(serialize).gsub(/\n/, '')
|
95
|
+
end
|
96
|
+
|
97
|
+
def decode64(str)
|
98
|
+
parse(Base64.decode64(str))
|
99
|
+
end
|
100
|
+
|
101
|
+
alias head_size size
|
102
|
+
|
103
|
+
def data_size
|
104
|
+
security_buffers.inject(0){|sum, a| sum += a[1].data_size}
|
105
|
+
end
|
106
|
+
|
107
|
+
def size
|
108
|
+
head_size + data_size
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
def security_buffers
|
113
|
+
@alist.find_all{|n, f| f.instance_of?(SecurityBuffer)}
|
114
|
+
end
|
115
|
+
|
116
|
+
def deflag
|
117
|
+
security_buffers.inject(head_size){|cur, a|
|
118
|
+
a[1].offset = cur
|
119
|
+
cur += a[1].data_size
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
def data_edge
|
124
|
+
security_buffers.map{ |n, f| f.active ? f.offset : size}.min
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -1,16 +1,16 @@
|
|
1
|
-
module Net
|
2
|
-
module NTLM
|
3
|
-
class Message
|
4
|
-
|
5
|
-
# sub class definitions
|
6
|
-
class Type0 < Message
|
7
|
-
string :sign, {:size => 8, :value => SSP_SIGN}
|
8
|
-
int32LE :type, {:value => 0}
|
9
|
-
end
|
10
|
-
|
11
|
-
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
|
1
|
+
module Net
|
2
|
+
module NTLM
|
3
|
+
class Message
|
4
|
+
|
5
|
+
# sub class definitions
|
6
|
+
class Type0 < Message
|
7
|
+
string :sign, {:size => 8, :value => SSP_SIGN}
|
8
|
+
int32LE :type, {:value => 0}
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
@@ -1,18 +1,18 @@
|
|
1
|
-
module Net
|
2
|
-
module NTLM
|
3
|
-
class Message
|
4
|
-
|
5
|
-
# @private false
|
6
|
-
class Type1 < Message
|
7
|
-
|
8
|
-
string :sign, {:size => 8, :value => SSP_SIGN}
|
9
|
-
int32LE :type, {:value => 1}
|
10
|
-
int32LE :flag, {:value => DEFAULT_FLAGS[:TYPE1] }
|
11
|
-
security_buffer :domain, {:value => ""}
|
12
|
-
security_buffer :workstation, {:value => Socket.gethostname }
|
13
|
-
string :os_version, {:size => 8, :value => "", :active => false }
|
14
|
-
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
1
|
+
module Net
|
2
|
+
module NTLM
|
3
|
+
class Message
|
4
|
+
|
5
|
+
# @private false
|
6
|
+
class Type1 < Message
|
7
|
+
|
8
|
+
string :sign, {:size => 8, :value => SSP_SIGN}
|
9
|
+
int32LE :type, {:value => 1}
|
10
|
+
int32LE :flag, {:value => DEFAULT_FLAGS[:TYPE1] }
|
11
|
+
security_buffer :domain, {:value => ""}
|
12
|
+
security_buffer :workstation, {:value => Socket.gethostname }
|
13
|
+
string :os_version, {:size => 8, :value => "", :active => false }
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|