dguerri-radiustar 0.0.5 → 0.1.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.
- data/History.txt +1 -4
- data/lib/radiustar/dictionary/attributes.rb +21 -5
- data/lib/radiustar/packet.rb +130 -45
- data/lib/radiustar/request.rb +1 -3
- data/lib/radiustar/vendor.rb +2 -2
- data/radiustar.gemspec +7 -4
- data/version.txt +1 -1
- metadata +23 -5
data/History.txt
CHANGED
|
@@ -2,13 +2,20 @@ module Radiustar
|
|
|
2
2
|
|
|
3
3
|
class AttributesCollection < Array
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
attr_accessor :vendor
|
|
6
|
+
|
|
7
|
+
def initialize vendor=nil
|
|
6
8
|
@collection = {}
|
|
7
9
|
@revcollection = {}
|
|
10
|
+
@vendor = vendor if vendor
|
|
8
11
|
end
|
|
9
12
|
|
|
10
13
|
def add(name, id, type)
|
|
11
|
-
|
|
14
|
+
if vendor?
|
|
15
|
+
@collection[name] ||= Attribute.new(name, id.to_i, type, @vendor)
|
|
16
|
+
else
|
|
17
|
+
@collection[name] ||= Attribute.new(name, id.to_i, type)
|
|
18
|
+
end
|
|
12
19
|
@revcollection[id.to_i] ||= @collection[name]
|
|
13
20
|
self << @collection[name]
|
|
14
21
|
end
|
|
@@ -21,19 +28,24 @@ module Radiustar
|
|
|
21
28
|
@revcollection[id]
|
|
22
29
|
end
|
|
23
30
|
|
|
31
|
+
def vendor?
|
|
32
|
+
!!@vendor
|
|
33
|
+
end
|
|
34
|
+
|
|
24
35
|
end
|
|
25
36
|
|
|
26
37
|
class Attribute
|
|
27
38
|
|
|
28
39
|
include Radiustar
|
|
29
40
|
|
|
30
|
-
attr_reader :name, :id, :type
|
|
41
|
+
attr_reader :name, :id, :type, :vendor
|
|
31
42
|
|
|
32
|
-
def initialize(name, id, type)
|
|
43
|
+
def initialize(name, id, type, vendor=nil)
|
|
33
44
|
@values = ValuesCollection.new
|
|
34
45
|
@name = name
|
|
35
46
|
@id = id.to_i
|
|
36
47
|
@type = type
|
|
48
|
+
@vendor = vendor if vendor
|
|
37
49
|
end
|
|
38
50
|
|
|
39
51
|
def add_value(name, id)
|
|
@@ -56,6 +68,10 @@ module Radiustar
|
|
|
56
68
|
@values
|
|
57
69
|
end
|
|
58
70
|
|
|
71
|
+
def vendor?
|
|
72
|
+
!!@vendor
|
|
73
|
+
end
|
|
74
|
+
|
|
59
75
|
end
|
|
60
76
|
|
|
61
|
-
end
|
|
77
|
+
end
|
data/lib/radiustar/packet.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
module Radiustar
|
|
2
2
|
|
|
3
3
|
require 'digest/md5'
|
|
4
|
+
require 'ipaddr_extensions'
|
|
4
5
|
|
|
5
6
|
class Packet
|
|
6
7
|
|
|
@@ -15,7 +16,7 @@ module Radiustar
|
|
|
15
16
|
P_ATTR = "CCa*" # pack template for attribute
|
|
16
17
|
|
|
17
18
|
attr_accessor :code
|
|
18
|
-
attr_reader :id, :attributes
|
|
19
|
+
attr_reader :id, :attributes, :authenticator
|
|
19
20
|
|
|
20
21
|
def initialize(dictionary, id, data = nil)
|
|
21
22
|
@dict = dictionary
|
|
@@ -75,55 +76,63 @@ module Radiustar
|
|
|
75
76
|
@authenticator = "\000"*16
|
|
76
77
|
@authenticator = Digest::MD5.digest(pack + secret)
|
|
77
78
|
@packed = nil
|
|
79
|
+
@authenticator
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def gen_response_authenticator(secret, request_authenticator)
|
|
83
|
+
@authenticator = request_authenticator
|
|
84
|
+
@authenticator = Digest::MD5.digest(pack + secret)
|
|
85
|
+
@packed = nil
|
|
86
|
+
@authenticator
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def validate_acct_authenticator(secret)
|
|
90
|
+
if @authenticator
|
|
91
|
+
original_authenticator = @authenticator
|
|
92
|
+
if gen_acct_authenticator(secret) == original_authenticator
|
|
93
|
+
true
|
|
94
|
+
else
|
|
95
|
+
@authenticator = original_authenticator
|
|
96
|
+
false
|
|
97
|
+
end
|
|
98
|
+
else
|
|
99
|
+
false
|
|
100
|
+
end
|
|
78
101
|
end
|
|
79
102
|
|
|
80
103
|
def set_attribute(name, value)
|
|
81
|
-
@attributes[name] = value
|
|
104
|
+
@attributes[name] = Attribute.new(@dict, name, value)
|
|
82
105
|
end
|
|
83
106
|
|
|
84
107
|
def unset_attribute(name)
|
|
85
|
-
@attributes
|
|
108
|
+
@attributes.delete(name)
|
|
86
109
|
end
|
|
87
110
|
|
|
88
111
|
def attribute(name)
|
|
89
|
-
@attributes[name]
|
|
112
|
+
if @attributes[name]
|
|
113
|
+
@attributes[name].value
|
|
114
|
+
end
|
|
90
115
|
end
|
|
91
116
|
|
|
92
117
|
def unset_all_attributes
|
|
93
|
-
@attributes =
|
|
118
|
+
@attributes = {}
|
|
94
119
|
end
|
|
95
120
|
|
|
96
121
|
def set_encoded_attribute(name, value, secret)
|
|
97
|
-
@attributes[name] = encode(value, secret)
|
|
122
|
+
@attributes[name] = Attribute.new(@dict, name, encode(value, secret))
|
|
98
123
|
end
|
|
99
124
|
|
|
100
|
-
def
|
|
125
|
+
def decode_attribute(name, secret)
|
|
126
|
+
if @attributes[name]
|
|
127
|
+
decode(@attributes[name].value.to_s, secret)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
101
130
|
|
|
131
|
+
def pack
|
|
102
132
|
attstr = ""
|
|
103
|
-
@attributes.
|
|
104
|
-
|
|
105
|
-
raise "Undefned attribute '#{attribute_s}'." if attribute.nil?
|
|
106
|
-
anum = attribute.id
|
|
107
|
-
val = case attribute.type
|
|
108
|
-
when "string"
|
|
109
|
-
value
|
|
110
|
-
when "integer"
|
|
111
|
-
if attribute.has_values?
|
|
112
|
-
raise "Invalid value name '#{value}'" if attribute.find_values_by_name(value).nil?
|
|
113
|
-
end
|
|
114
|
-
[attribute.has_values? ? attribute.find_values_by_name(value).id : value].pack("N")
|
|
115
|
-
when "ipaddr"
|
|
116
|
-
[inet_aton(value)].pack("N")
|
|
117
|
-
when "date"
|
|
118
|
-
[value].pack("N")
|
|
119
|
-
when "time"
|
|
120
|
-
[value].pack("N")
|
|
121
|
-
else
|
|
122
|
-
next
|
|
123
|
-
end
|
|
124
|
-
attstr += [attribute.id, val.length + 2, val].pack(P_ATTR)
|
|
133
|
+
@attributes.values.each do |attribute|
|
|
134
|
+
attstr += attribute.pack
|
|
125
135
|
end
|
|
126
|
-
|
|
127
136
|
@packed = [CODES[@code], @id, attstr.length + HDRLEN, @authenticator, attstr].pack(P_HDR)
|
|
128
137
|
end
|
|
129
138
|
|
|
@@ -131,7 +140,7 @@ module Radiustar
|
|
|
131
140
|
|
|
132
141
|
def unpack
|
|
133
142
|
@code, @id, len, @authenticator, attribute_data = @packed.unpack(P_HDR)
|
|
134
|
-
@code = CODES.
|
|
143
|
+
@code = CODES.key(@code)
|
|
135
144
|
|
|
136
145
|
unset_all_attributes
|
|
137
146
|
|
|
@@ -147,7 +156,7 @@ module Radiustar
|
|
|
147
156
|
when 'integer'
|
|
148
157
|
attribute.has_values? ? attribute.find_values_by_id(attribute_value.unpack("N")[0]).name : attribute_value.unpack("N")[0]
|
|
149
158
|
when 'ipaddr'
|
|
150
|
-
|
|
159
|
+
attribute_value.unpack("N")[0].to_ip.to_s
|
|
151
160
|
when 'time'
|
|
152
161
|
attribute_value.unpack("N")[0]
|
|
153
162
|
when 'date'
|
|
@@ -159,22 +168,11 @@ module Radiustar
|
|
|
159
168
|
end
|
|
160
169
|
end
|
|
161
170
|
|
|
162
|
-
def inet_aton(hostname)
|
|
163
|
-
if (hostname =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/)
|
|
164
|
-
return (($1.to_i & 0xff) << 24) + (($2.to_i & 0xff) << 16) + (($3.to_i & 0xff) << 8) + (($4.to_i & 0xff))
|
|
165
|
-
end
|
|
166
|
-
0
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
def inet_ntoa(iaddr)
|
|
170
|
-
sprintf("%d.%d.%d.%d", (iaddr >> 24) & 0xff, (iaddr >> 16) & 0xff, (iaddr >> 8) & 0xff, (iaddr) & 0xff)
|
|
171
|
-
end
|
|
172
|
-
|
|
173
171
|
def xor_str(str1, str2)
|
|
174
172
|
i = 0
|
|
175
173
|
newstr = ""
|
|
176
174
|
str1.each_byte do |c1|
|
|
177
|
-
c2 = str2[i]
|
|
175
|
+
c2 = str2.bytes.to_a[i]
|
|
178
176
|
newstr = newstr << (c1 ^ c2)
|
|
179
177
|
i = i+1
|
|
180
178
|
end
|
|
@@ -206,5 +204,92 @@ module Radiustar
|
|
|
206
204
|
return decoded_value
|
|
207
205
|
end
|
|
208
206
|
|
|
207
|
+
class Attribute
|
|
208
|
+
|
|
209
|
+
attr_reader :dict, :name, :vendor
|
|
210
|
+
attr_accessor :value
|
|
211
|
+
|
|
212
|
+
def initialize dict, name, value, vendor=nil
|
|
213
|
+
@dict = dict
|
|
214
|
+
# This is the cheapest and easiest way to add VSA's!
|
|
215
|
+
if (name && (chunks = name.split('/')) && (chunks.size == 2))
|
|
216
|
+
@vendor = chunks[0]
|
|
217
|
+
@name = chunks[1]
|
|
218
|
+
else
|
|
219
|
+
@name = name
|
|
220
|
+
end
|
|
221
|
+
@vendor ||= vendor
|
|
222
|
+
@value = value.is_a?(Attribute) ? value.to_s : value
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
def vendor?
|
|
226
|
+
!!@vendor
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
def pack
|
|
230
|
+
attribute = if (vendor? && (@dict.vendors.find_by_name(@vendor)))
|
|
231
|
+
@dict.vendors.find_by_name(@vendor).attributes.find_by_name(@name)
|
|
232
|
+
else
|
|
233
|
+
@dict.find_attribute_by_name(@name)
|
|
234
|
+
end
|
|
235
|
+
raise "Undefined attribute '#{@name}'." if attribute.nil?
|
|
236
|
+
|
|
237
|
+
if vendor?
|
|
238
|
+
pack_vendor_specific_attribute attribute
|
|
239
|
+
else
|
|
240
|
+
pack_attribute attribute
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def inspect
|
|
245
|
+
@value
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def to_s
|
|
249
|
+
@value
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
private
|
|
253
|
+
|
|
254
|
+
def pack_vendor_specific_attribute attribute
|
|
255
|
+
inside_attribute = pack_attribute attribute
|
|
256
|
+
vid = attribute.vendor.id.to_i
|
|
257
|
+
header = [ 26, inside_attribute.size + 6 ].pack("CC") # 26: Type = Vendor-Specific, 4: length of Vendor-Id field
|
|
258
|
+
header += [ 0, vid >> 16, vid >> 8, vid ].pack("CCCC") # first byte of Vendor-Id is 0
|
|
259
|
+
header + inside_attribute
|
|
260
|
+
end
|
|
261
|
+
|
|
262
|
+
def pack_attribute attribute
|
|
263
|
+
anum = attribute.id
|
|
264
|
+
val = case attribute.type
|
|
265
|
+
when "string"
|
|
266
|
+
@value
|
|
267
|
+
when "integer"
|
|
268
|
+
raise "Invalid value name '#{@value}'." if attribute.has_values? && attribute.find_values_by_name(@value).nil?
|
|
269
|
+
[attribute.has_values? ? attribute.find_values_by_name(@value).id : @value].pack("N")
|
|
270
|
+
when "ipaddr"
|
|
271
|
+
[@value.to_ip.to_i].pack("N")
|
|
272
|
+
when "ipv6addr"
|
|
273
|
+
ipi = @value.to_ip.to_i
|
|
274
|
+
[ ipi >> 96, ipi >> 64, ipi >> 32, ipi ].pack("NNNN")
|
|
275
|
+
when "date"
|
|
276
|
+
[@value].pack("N")
|
|
277
|
+
when "time"
|
|
278
|
+
[@value].pack("N")
|
|
279
|
+
else
|
|
280
|
+
""
|
|
281
|
+
end
|
|
282
|
+
begin
|
|
283
|
+
[anum,
|
|
284
|
+
val.length + 2,
|
|
285
|
+
val
|
|
286
|
+
].pack(P_ATTR)
|
|
287
|
+
rescue
|
|
288
|
+
puts "#{@name} => #{@value}"
|
|
289
|
+
puts [anum, val.length + 2, val].inspect
|
|
290
|
+
end
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
end
|
|
209
294
|
end
|
|
210
|
-
end
|
|
295
|
+
end
|
data/lib/radiustar/request.rb
CHANGED
|
@@ -2,8 +2,6 @@ module Radiustar
|
|
|
2
2
|
|
|
3
3
|
require 'socket'
|
|
4
4
|
|
|
5
|
-
MAX_RADIUS_REPLAY_PACKET_LEN = 512
|
|
6
|
-
|
|
7
5
|
class Request
|
|
8
6
|
|
|
9
7
|
def initialize(server, options = {})
|
|
@@ -104,7 +102,7 @@ module Radiustar
|
|
|
104
102
|
if select([@socket], nil, nil, timeout.to_i) == nil
|
|
105
103
|
raise "Timed out waiting for response packet from server"
|
|
106
104
|
end
|
|
107
|
-
data = @socket.recvfrom(
|
|
105
|
+
data = @socket.recvfrom(64)
|
|
108
106
|
Packet.new(@dict, Process.pid & 0xff, data[0])
|
|
109
107
|
end
|
|
110
108
|
|
data/lib/radiustar/vendor.rb
CHANGED
|
@@ -32,7 +32,7 @@ module Radiustar
|
|
|
32
32
|
def initialize(name, id)
|
|
33
33
|
@name = name
|
|
34
34
|
@id = id
|
|
35
|
-
@attributes = AttributesCollection.new
|
|
35
|
+
@attributes = AttributesCollection.new self
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def add_attribute(name, id, type)
|
|
@@ -57,4 +57,4 @@ module Radiustar
|
|
|
57
57
|
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
end
|
|
60
|
+
end
|
data/radiustar.gemspec
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
Gem::Specification.new do |s|
|
|
4
4
|
s.name = %q{dguerri-radiustar}
|
|
5
|
-
s.version = "0.0
|
|
5
|
+
s.version = "0.1.0"
|
|
6
6
|
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
8
|
-
s.authors = ["PJ Davis", "Davide Guerri"]
|
|
9
|
-
s.date = %q{2011-
|
|
8
|
+
s.authors = ["PJ Davis", "Davide Guerri", "James Harton"]
|
|
9
|
+
s.date = %q{2011-09-28}
|
|
10
10
|
s.description = %q{Ruby Radius Library}
|
|
11
|
-
s.email =
|
|
11
|
+
s.email = ["pj.davis@gmail.com", "davide.guerri@gmail.com", "jamesotron@gmail.com"]
|
|
12
12
|
s.extra_rdoc_files = ["History.txt", "README.rdoc", "templates/default.txt", "version.txt"]
|
|
13
13
|
s.files = [".gitignore", "History.txt", "README.rdoc", "Rakefile", "lib/radiustar.rb", "lib/radiustar/dictionary.rb", "lib/radiustar/dictionary/attributes.rb", "lib/radiustar/dictionary/values.rb", "lib/radiustar/packet.rb", "lib/radiustar/radiustar.rb", "lib/radiustar/request.rb", "lib/radiustar/vendor.rb", "radiustar.gemspec", "spec/radiustar_spec.rb", "spec/spec_helper.rb", "templates/default.txt", "templates/dictionary.digium", "templates/gandalf.dictionary", "test/test_radiustar.rb", "version.txt"]
|
|
14
14
|
s.homepage = %q{http://github.com/dguerri/radiustar}
|
|
@@ -25,10 +25,13 @@ Gem::Specification.new do |s|
|
|
|
25
25
|
|
|
26
26
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
|
27
27
|
s.add_development_dependency(%q<bones>, [">= 3.4.1"])
|
|
28
|
+
s.add_development_dependency(%q<ipaddr_extensions>)
|
|
28
29
|
else
|
|
29
30
|
s.add_dependency(%q<bones>, [">= 3.4.1"])
|
|
31
|
+
s.add_dependency(%q<ipaddr_extensions>)
|
|
30
32
|
end
|
|
31
33
|
else
|
|
32
34
|
s.add_dependency(%q<bones>, [">= 3.4.1"])
|
|
35
|
+
s.add_dependency(%q<ipaddr_extensions>)
|
|
33
36
|
end
|
|
34
37
|
end
|
data/version.txt
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.0.
|
|
1
|
+
0.0.4
|
metadata
CHANGED
|
@@ -1,22 +1,23 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dguerri-radiustar
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
hash:
|
|
4
|
+
hash: 27
|
|
5
5
|
prerelease:
|
|
6
6
|
segments:
|
|
7
7
|
- 0
|
|
8
|
+
- 1
|
|
8
9
|
- 0
|
|
9
|
-
|
|
10
|
-
version: 0.0.5
|
|
10
|
+
version: 0.1.0
|
|
11
11
|
platform: ruby
|
|
12
12
|
authors:
|
|
13
13
|
- PJ Davis
|
|
14
14
|
- Davide Guerri
|
|
15
|
+
- James Harton
|
|
15
16
|
autorequire:
|
|
16
17
|
bindir: bin
|
|
17
18
|
cert_chain: []
|
|
18
19
|
|
|
19
|
-
date: 2011-
|
|
20
|
+
date: 2011-09-28 00:00:00 +02:00
|
|
20
21
|
default_executable:
|
|
21
22
|
dependencies:
|
|
22
23
|
- !ruby/object:Gem::Dependency
|
|
@@ -35,8 +36,25 @@ dependencies:
|
|
|
35
36
|
version: 3.4.1
|
|
36
37
|
type: :development
|
|
37
38
|
version_requirements: *id001
|
|
39
|
+
- !ruby/object:Gem::Dependency
|
|
40
|
+
name: ipaddr_extensions
|
|
41
|
+
prerelease: false
|
|
42
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
|
43
|
+
none: false
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
hash: 3
|
|
48
|
+
segments:
|
|
49
|
+
- 0
|
|
50
|
+
version: "0"
|
|
51
|
+
type: :development
|
|
52
|
+
version_requirements: *id002
|
|
38
53
|
description: Ruby Radius Library
|
|
39
|
-
email:
|
|
54
|
+
email:
|
|
55
|
+
- pj.davis@gmail.com
|
|
56
|
+
- davide.guerri@gmail.com
|
|
57
|
+
- jamesotron@gmail.com
|
|
40
58
|
executables: []
|
|
41
59
|
|
|
42
60
|
extensions: []
|