radiustar 0.0.1
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/.gitignore +7 -0
- data/History.txt +2 -0
- data/README.rdoc +67 -0
- data/Rakefile +20 -0
- data/lib/radiustar/dictionary/attributes.rb +54 -0
- data/lib/radiustar/dictionary/values.rb +39 -0
- data/lib/radiustar/dictionary.rb +66 -0
- data/lib/radiustar/packet.rb +181 -0
- data/lib/radiustar/radiustar.rb +3 -0
- data/lib/radiustar/request.rb +66 -0
- data/lib/radiustar.rb +65 -0
- data/spec/radiustar_spec.rb +6 -0
- data/spec/spec_helper.rb +15 -0
- data/templates/default.txt +207 -0
- data/test/test_radiustar.rb +0 -0
- data/version.txt +1 -0
- metadata +94 -0
data/.gitignore
ADDED
data/History.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
== RADIUSTAR
|
2
|
+
|
3
|
+
..................................................................................................
|
4
|
+
..........................................................................H.......................
|
5
|
+
.........................................................................HHH......................
|
6
|
+
........................................................................HHHHH.....................
|
7
|
+
......................................................................HHHHHHHH....................
|
8
|
+
...............................................................@_’’’@HHHHHHHHHHH3HdHdddHd’........
|
9
|
+
.......................................................dWE9p_^^&@d3HHHHHHHHHHHHHHHdHHHH@..........
|
10
|
+
....................................................z933333HHHHHHHHHHHHHHHHHHHHddHdddd’...........
|
11
|
+
..................................................pWp33Hdd@&&dHHHHHHHHHHHHHHHddHHHHd..............
|
12
|
+
............................................33p3p3H@&&_@&@&&__^&3HHHHHHHHHHHHddHdH^...............
|
13
|
+
........................................W3Hd&_&&_&@&_^@WN7WH3H_’.HHHHHHHHHHHHddHdd................
|
14
|
+
...................................WWpHd@&___’’^^@HpNW7JJEENppd’&3HHHHHHHHHHHHddHd&...............
|
15
|
+
................................pH@d&&&@&___^_&&d@HW7JzJEJJ7N3@’3HHHHHdHHHHHHHHHHHd...............
|
16
|
+
........................3ppW3d@^_&__^^&&_^^_d3d39QzEEEE97EENp3&H333HHHdddHHH33HdHdH^..............
|
17
|
+
.....................dd@@dd@&&_^^&__&&d@dHddH@@3EJEWWN7W7EN3H&^p3HHdddHdH&...&dHHHdd..............
|
18
|
+
................&&^__@&_@_^^_^^_&&dpWd3H&&&_HdpWW9EWppHWWHHH&^d3HHHHHHHH’........’_d’.............
|
19
|
+
............_&@@@&&_^’’^_&@&HH33HpWW3dHd^^_’33pp97NWWHHHd@@^’^3HdddHHd^...........................
|
20
|
+
........&d__@’’’’_^’’_&@&@&&3dH@@Hdd&_@____&@Hd@H@@_’’’’’....’^H&HHHH.............................
|
21
|
+
....@@____^’^__^’&&@@@@H3d&@ddd@d^^^@__^d&_’.’’.................HHH...............................
|
22
|
+
Hdd@@____^_&&dd@@d_d__&&__&@^’&__^_’’.’...........................................................
|
23
|
+
@__&&__@&&&_&@@dH&^&^^^’^^^_^’’...................................................................
|
24
|
+
&_ddd@@@&___&&_&’^^’.’’...........................................................................
|
25
|
+
|
26
|
+
by pjdavis
|
27
|
+
http://github.com/pjdavis/radiustar
|
28
|
+
|
29
|
+
== DESCRIPTION:
|
30
|
+
|
31
|
+
Ruby Radius Library
|
32
|
+
|
33
|
+
== FEATURES
|
34
|
+
|
35
|
+
* Import your own radius dictionary
|
36
|
+
* Test authentication
|
37
|
+
* Check radius replies
|
38
|
+
|
39
|
+
== COMING SOON
|
40
|
+
|
41
|
+
* Use vendor specific attributes
|
42
|
+
|
43
|
+
== SYNOPSIS:
|
44
|
+
|
45
|
+
require 'radiustar'
|
46
|
+
|
47
|
+
req = Radiustar::Request.new('server', 'my_ip_address')
|
48
|
+
resp = req.authenticate('my_user', 'my_password', 'shared_secret')
|
49
|
+
resp #=> true
|
50
|
+
|
51
|
+
attrs = req.get_attributes('my_user', 'my_password', 'shared_secret')
|
52
|
+
attrs #=> ["Access-Accept", {"Service-Type"=>"Framed-User",
|
53
|
+
"Framed-Protocol"=>"PPP",
|
54
|
+
"Framed-IP-Address"=>"255.255.255.254",
|
55
|
+
"Framed-IP-Netmask"=>"255.255.255.255"} ]
|
56
|
+
|
57
|
+
== REQUIREMENTS:
|
58
|
+
|
59
|
+
* Ruby 1.8
|
60
|
+
|
61
|
+
== INSTALL:
|
62
|
+
|
63
|
+
gem install radiustar
|
64
|
+
|
65
|
+
== LICENSE:
|
66
|
+
|
67
|
+
Copyright (c) 2010 [PJ Davis], released under the CC0 1.0 Universal license.
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
begin
|
3
|
+
require 'bones'
|
4
|
+
rescue LoadError
|
5
|
+
abort '### Please install the "bones" gem ###'
|
6
|
+
end
|
7
|
+
|
8
|
+
task :default => 'test:run'
|
9
|
+
task 'gem:release' => 'test:run'
|
10
|
+
|
11
|
+
Bones {
|
12
|
+
name 'radiustar'
|
13
|
+
authors 'PJ Davis'
|
14
|
+
email 'pj.davis@gmail.com'
|
15
|
+
url 'http://github.com/pjdavis/radiustar'
|
16
|
+
ignore_file '.gitignore'
|
17
|
+
readme_file 'README.rdoc'
|
18
|
+
|
19
|
+
}
|
20
|
+
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Radiustar
|
2
|
+
|
3
|
+
class AttributesCollection
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@collection = {}
|
7
|
+
@revcollection = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(name, id, type)
|
11
|
+
@collection[name] ||= Attribute.new(name, id.to_i, type)
|
12
|
+
@revcollection[id.to_i] ||= @collection[name]
|
13
|
+
end
|
14
|
+
|
15
|
+
def find_by_name(name)
|
16
|
+
@collection[name]
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_by_id(id)
|
20
|
+
@revcollection[id.to_i]
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
class Attribute
|
26
|
+
|
27
|
+
attr_reader :name, :id, :type
|
28
|
+
|
29
|
+
def initialize(name, id, type)
|
30
|
+
@values = ValuesCollection.new
|
31
|
+
@name = name
|
32
|
+
@id = id.to_i
|
33
|
+
@type = type
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_value(name, id)
|
37
|
+
@values.add(name, id.to_i)
|
38
|
+
end
|
39
|
+
|
40
|
+
def find_values_by_name(name)
|
41
|
+
@values.find_by_name(name)
|
42
|
+
end
|
43
|
+
|
44
|
+
def find_values_by_id(id)
|
45
|
+
@values.find_by_id(id.to_i)
|
46
|
+
end
|
47
|
+
|
48
|
+
def has_values?
|
49
|
+
!@values.empty?
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Radiustar
|
2
|
+
|
3
|
+
class ValuesCollection
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@collection = {}
|
7
|
+
@revcollection = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(name, id)
|
11
|
+
@collection[name] ||= Value.new(name, id)
|
12
|
+
@revcollection[id.to_i] ||= @collection[name]
|
13
|
+
end
|
14
|
+
|
15
|
+
def find_by_name(name)
|
16
|
+
@collection[name]
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_by_id(id)
|
20
|
+
@revcollection[id]
|
21
|
+
end
|
22
|
+
|
23
|
+
def empty?
|
24
|
+
@collection.empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
class Value
|
30
|
+
attr_accessor :name
|
31
|
+
|
32
|
+
def initialize(name, id)
|
33
|
+
@name = name
|
34
|
+
@id = id.to_i
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Radiustar
|
2
|
+
|
3
|
+
class Dictionary
|
4
|
+
|
5
|
+
DEFAULT_DICTIONARY_PATH = ::File.join(::File.dirname(__FILE__), '..', '..', 'templates', 'default.txt')
|
6
|
+
|
7
|
+
def initialize(initial_path = nil)
|
8
|
+
@attributes = AttributesCollection.new
|
9
|
+
|
10
|
+
read initial_path if initial_path
|
11
|
+
end
|
12
|
+
|
13
|
+
def read(path)
|
14
|
+
file = File.open(path) do |f|
|
15
|
+
f.each_line do |line|
|
16
|
+
next if line =~ /^\#/ # discard comments
|
17
|
+
split_line = line.split(/\s+/)
|
18
|
+
next if split_line == []
|
19
|
+
case split_line.first.upcase
|
20
|
+
when "ATTRIBUTE"
|
21
|
+
set_attr(split_line)
|
22
|
+
when "VALUE"
|
23
|
+
set_value(split_line)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_attribute_by_name(name)
|
29
|
+
@attributes.find_by_name(name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_attribute_by_id(id)
|
33
|
+
@attributes.find_by_id(id)
|
34
|
+
end
|
35
|
+
|
36
|
+
def attribute_name_defined?(name)
|
37
|
+
!@attributes.find_by_name(name).nil?
|
38
|
+
end
|
39
|
+
|
40
|
+
def attribute_id_defined?(id)
|
41
|
+
!@attributes.find_by_id(id).nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
class << self
|
47
|
+
|
48
|
+
def default
|
49
|
+
new DEFAULT_DICTIONARY_PATH
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def set_attr(line)
|
57
|
+
@attributes.add(line[1], line[2], line[3])
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_value(line)
|
61
|
+
@attributes.find_by_name(line[1]).add_value(line[2], line[3])
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
module Radiustar
|
2
|
+
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
class Packet
|
6
|
+
|
7
|
+
CODES = { 'Access-Request' => 1, 'Access-Accept' => 2,
|
8
|
+
'Access-Reject' => 3, 'Accounting-Request' => 4,
|
9
|
+
'Accounting-Response' => 5, 'Access-Challenge' => 11,
|
10
|
+
'Status-Server' => 12, 'Status-Client' => 13 }
|
11
|
+
|
12
|
+
|
13
|
+
HDRLEN = 1 + 1 + 2 + 16 # size of packet header
|
14
|
+
P_HDR = "CCna16a*" # pack template for header
|
15
|
+
P_ATTR = "CCa*" # pack template for attribute
|
16
|
+
|
17
|
+
attr_accessor :code
|
18
|
+
attr_reader :id, :attributes
|
19
|
+
|
20
|
+
def initialize(dictionary, id, data = nil)
|
21
|
+
@dict = dictionary
|
22
|
+
@id = id
|
23
|
+
unset_all_attributes
|
24
|
+
if data
|
25
|
+
@packed = data
|
26
|
+
self.unpack
|
27
|
+
end
|
28
|
+
self
|
29
|
+
end
|
30
|
+
|
31
|
+
def increment_id
|
32
|
+
@id = (@id + 1) & 0xff
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_a
|
36
|
+
@attributes.to_a
|
37
|
+
end
|
38
|
+
|
39
|
+
# Generate an authenticator. It will try to use /dev/urandom if
|
40
|
+
# possible, or the system rand call if that's not available.
|
41
|
+
def gen_authenticator
|
42
|
+
authenticator = []
|
43
|
+
8.times do
|
44
|
+
authenticator << rand(65536)
|
45
|
+
end
|
46
|
+
authenticator.pack("n8")
|
47
|
+
if (File.exist?("/dev/urandom"))
|
48
|
+
File.open("/dev/urandom") do |urandom|
|
49
|
+
authenticator = urandom.read(16)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
@authenticator = authenticator
|
53
|
+
end
|
54
|
+
|
55
|
+
def set_attribute(name, value)
|
56
|
+
@attributes[name] = value
|
57
|
+
end
|
58
|
+
|
59
|
+
def unset_attribute(name)
|
60
|
+
@attributes[name] = nil
|
61
|
+
end
|
62
|
+
|
63
|
+
def attribute(name)
|
64
|
+
@attributes[name]
|
65
|
+
end
|
66
|
+
|
67
|
+
def unset_all_attributes
|
68
|
+
@attributes = Hash.new
|
69
|
+
end
|
70
|
+
|
71
|
+
def set_encoded_attribute(name, value, secret)
|
72
|
+
@attributes[name] = encode(value, secret)
|
73
|
+
end
|
74
|
+
|
75
|
+
def pack
|
76
|
+
|
77
|
+
attstr = ""
|
78
|
+
@attributes.each_pair do |attribute, value|
|
79
|
+
attribute = @dict.find_attribute_by_name(attribute)
|
80
|
+
anum = attribute.id
|
81
|
+
val = case attribute.type
|
82
|
+
when "string"
|
83
|
+
value
|
84
|
+
when "integer"
|
85
|
+
[attribute.has_values? ? attribute.find_values_by_id(value) : value].pack("N")
|
86
|
+
when "ipaddr"
|
87
|
+
[inet_aton(value)].pack("N")
|
88
|
+
when "date"
|
89
|
+
[value].pack("N")
|
90
|
+
when "time"
|
91
|
+
[value].pack("N")
|
92
|
+
else
|
93
|
+
next
|
94
|
+
end
|
95
|
+
attstr += [attribute.id, val.length + 2, val].pack(P_ATTR)
|
96
|
+
end
|
97
|
+
|
98
|
+
@packed = [CODES[@code], @id, attstr.length + HDRLEN, @authenticator, attstr].pack(P_HDR)
|
99
|
+
end
|
100
|
+
|
101
|
+
protected
|
102
|
+
|
103
|
+
def unpack
|
104
|
+
@code, @id, len, @authenticator, attribute_data = @packed.unpack(P_HDR)
|
105
|
+
@code = CODES.index(@code)
|
106
|
+
|
107
|
+
unset_all_attributes
|
108
|
+
|
109
|
+
while attribute_data.length > 0 do
|
110
|
+
length = attribute_data.unpack("xC").first.to_i
|
111
|
+
attribute_type, attribute_value = attribute_data.unpack("Cxa#{length-2}")
|
112
|
+
attribute_type = attribute_type.to_i
|
113
|
+
|
114
|
+
attribute = @dict.find_attribute_by_id(attribute_type)
|
115
|
+
attribute_value = case attribute.type
|
116
|
+
when 'string'
|
117
|
+
attribute_value
|
118
|
+
when 'integer'
|
119
|
+
attribute.has_values? ? attribute.find_values_by_id(attribute_value.unpack("N")[0]).name : attribute_value.unpack("N")[0]
|
120
|
+
when 'ipaddr'
|
121
|
+
inet_ntoa(attribute_value.unpack("N")[0])
|
122
|
+
when 'time'
|
123
|
+
attribute_value.unpack("N")[0]
|
124
|
+
when 'date'
|
125
|
+
attribute_value.unpack("N")[0]
|
126
|
+
end
|
127
|
+
|
128
|
+
set_attribute(attribute.name, attribute_value)
|
129
|
+
attribute_data[0, length] = ""
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def inet_aton(hostname)
|
134
|
+
if (hostname =~ /([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/)
|
135
|
+
return (($1.to_i & 0xff) << 24) + (($2.to_i & 0xff) << 16) + (($3.to_i & 0xff) << 8) + (($4.to_i & 0xff))
|
136
|
+
end
|
137
|
+
0
|
138
|
+
end
|
139
|
+
|
140
|
+
def inet_ntoa(iaddr)
|
141
|
+
sprintf("%d.%d.%d.%d", (iaddr >> 24) & 0xff, (iaddr >> 16) & 0xff, (iaddr >> 8) & 0xff, (iaddr) & 0xff)
|
142
|
+
end
|
143
|
+
|
144
|
+
def xor_str(str1, str2)
|
145
|
+
i = 0
|
146
|
+
newstr = ""
|
147
|
+
str1.each_byte do |c1|
|
148
|
+
c2 = str2[i]
|
149
|
+
newstr = newstr << (c1 ^ c2)
|
150
|
+
i = i+1
|
151
|
+
end
|
152
|
+
newstr
|
153
|
+
end
|
154
|
+
|
155
|
+
def encode(value, secret)
|
156
|
+
lastround = @authenticator
|
157
|
+
encoded_value = ""
|
158
|
+
# pad to 16n bytes
|
159
|
+
value += "\000" * (15-(15 + value.length) % 16)
|
160
|
+
0.step(value.length-1, 16) do |i|
|
161
|
+
lastround = xor_str(value[i, 16], Digest::MD5.digest(secret + lastround) )
|
162
|
+
encoded_value += lastround
|
163
|
+
end
|
164
|
+
encoded_value
|
165
|
+
end
|
166
|
+
|
167
|
+
def decode(value, secret)
|
168
|
+
decoded_value = ""
|
169
|
+
lastround = @authenticator
|
170
|
+
0.step(value.length-1, 16) do |i|
|
171
|
+
decoded_value = xor_str(value[i, 16], Digest::MD5.digest(secret + lastround))
|
172
|
+
lastround = value[i, 16]
|
173
|
+
end
|
174
|
+
|
175
|
+
decoded_value.gsub!(/\000+/, "") if decoded_value
|
176
|
+
decoded_value[value.length, -1] = "" unless (decoded_value.length <= value.length)
|
177
|
+
return decoded_value
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Radiustar
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
class Request
|
6
|
+
|
7
|
+
def initialize(server, my_ip, dict_file = nil)
|
8
|
+
@dict = dict_file.nil? ? Dictionary.default : Dictionary.new(dict_file)
|
9
|
+
@my_ip = my_ip
|
10
|
+
@host, @port = server.split(":")
|
11
|
+
@port = Socket.getservbyname("radius", "udp") unless @port
|
12
|
+
@port = 1812 unless @port
|
13
|
+
@port = @port.to_i # just in case
|
14
|
+
@socket = UDPSocket.open
|
15
|
+
@socket.connect(@host, @port)
|
16
|
+
end
|
17
|
+
|
18
|
+
def authenticate(name, password, secret)
|
19
|
+
@packet = Packet.new(@dict, Process.pid & 0xff)
|
20
|
+
@packet.code = 'Access-Request'
|
21
|
+
@packet.gen_authenticator
|
22
|
+
@packet.set_attribute('User-Name', name)
|
23
|
+
@packet.set_attribute('NAS-IP-Address', @my_ip)
|
24
|
+
@packet.set_encoded_attribute('User-Password', password, secret)
|
25
|
+
send_packet
|
26
|
+
@recieved_packet = recv_packet
|
27
|
+
return @recieved_packet.code == 'Access-Accept'
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_attributes(name, password, secret)
|
31
|
+
@packet = Packet.new(@dict, Process.pid & 0xff)
|
32
|
+
@packet.code = 'Access-Request'
|
33
|
+
@packet.gen_authenticator
|
34
|
+
@packet.set_attribute('User-Name', name)
|
35
|
+
@packet.set_attribute('NAS-IP-Address', @my_ip)
|
36
|
+
@packet.set_encoded_attribute('User-Password', password, secret)
|
37
|
+
send_packet
|
38
|
+
@recieved_packet = recv_packet
|
39
|
+
recieved_thing = [@recieved_packet.code]
|
40
|
+
recieved_thing << @recieved_packet.attributes
|
41
|
+
end
|
42
|
+
|
43
|
+
def inspect
|
44
|
+
to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def send_packet
|
50
|
+
data = @packet.pack
|
51
|
+
@packet.increment_id
|
52
|
+
@socket.send(data, 0)
|
53
|
+
end
|
54
|
+
|
55
|
+
def recv_packet
|
56
|
+
if select([@socket], nil, nil, 60) == nil
|
57
|
+
raise "Timed out waiting for response packet from server"
|
58
|
+
end
|
59
|
+
data = @socket.recvfrom(64)
|
60
|
+
Packet.new(@dict, Process.pid & 0xff, data[0])
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/lib/radiustar.rb
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
|
2
|
+
module Radiustar
|
3
|
+
|
4
|
+
# :stopdoc:
|
5
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
6
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
7
|
+
# :startdoc:
|
8
|
+
|
9
|
+
# Returns the version string for the library.
|
10
|
+
#
|
11
|
+
def self.version
|
12
|
+
@version ||= File.read(path('version.txt')).strip
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns the library path for the module. If any arguments are given,
|
16
|
+
# they will be joined to the end of the libray path using
|
17
|
+
# <tt>File.join</tt>.
|
18
|
+
#
|
19
|
+
def self.libpath( *args, &block )
|
20
|
+
rv = args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
|
21
|
+
if block
|
22
|
+
begin
|
23
|
+
$LOAD_PATH.unshift LIBPATH
|
24
|
+
rv = block.call
|
25
|
+
ensure
|
26
|
+
$LOAD_PATH.shift
|
27
|
+
end
|
28
|
+
end
|
29
|
+
return rv
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the lpath for the module. If any arguments are given,
|
33
|
+
# they will be joined to the end of the path using
|
34
|
+
# <tt>File.join</tt>.
|
35
|
+
#
|
36
|
+
def self.path( *args, &block )
|
37
|
+
rv = args.empty? ? PATH : ::File.join(PATH, args.flatten)
|
38
|
+
if block
|
39
|
+
begin
|
40
|
+
$LOAD_PATH.unshift PATH
|
41
|
+
rv = block.call
|
42
|
+
ensure
|
43
|
+
$LOAD_PATH.shift
|
44
|
+
end
|
45
|
+
end
|
46
|
+
return rv
|
47
|
+
end
|
48
|
+
|
49
|
+
# Utility method used to require all files ending in .rb that lie in the
|
50
|
+
# directory below this file that has the same name as the filename passed
|
51
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
52
|
+
# the _filename_ does not have to be equivalent to the directory.
|
53
|
+
#
|
54
|
+
def self.require_all_libs_relative_to( fname, dir = nil )
|
55
|
+
dir ||= ::File.basename(fname, '.*')
|
56
|
+
search_me = ::File.expand_path(
|
57
|
+
::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
58
|
+
|
59
|
+
Dir.glob(search_me).sort.each {|rb| require rb}
|
60
|
+
end
|
61
|
+
|
62
|
+
end # module Radiustar
|
63
|
+
|
64
|
+
Radiustar.require_all_libs_relative_to(__FILE__)
|
65
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
|
2
|
+
require File.expand_path(
|
3
|
+
File.join(File.dirname(__FILE__), %w[.. lib radiustar]))
|
4
|
+
|
5
|
+
Spec::Runner.configure do |config|
|
6
|
+
# == Mock Framework
|
7
|
+
#
|
8
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
9
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
10
|
+
#
|
11
|
+
# config.mock_with :mocha
|
12
|
+
# config.mock_with :flexmock
|
13
|
+
# config.mock_with :rr
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,207 @@
|
|
1
|
+
#
|
2
|
+
# This file contains dictionary translations for parsing
|
3
|
+
# requests and generating responses. All transactions are
|
4
|
+
# composed of Attribute/Value Pairs. The value of each attribute
|
5
|
+
# is specified as one of 4 data types. Valid data types are:
|
6
|
+
#
|
7
|
+
# string - 0-253 octets
|
8
|
+
# ipaddr - 4 octets in network byte order
|
9
|
+
# integer - 32 bit value in big endian order (high byte first)
|
10
|
+
# date - 32 bit value in big endian order - seconds since
|
11
|
+
# 00:00:00 GMT, Jan. 1, 1970
|
12
|
+
#
|
13
|
+
# Enumerated values are stored in the user file with dictionary
|
14
|
+
# VALUE translations for easy administration.
|
15
|
+
#
|
16
|
+
# Example:
|
17
|
+
#
|
18
|
+
# ATTRIBUTE VALUE
|
19
|
+
# --------------- -----
|
20
|
+
# Framed-Protocol = PPP
|
21
|
+
# 7 = 1 (integer encoding)
|
22
|
+
#
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
#
|
27
|
+
# Proper names for everything - use this instead of the above
|
28
|
+
#
|
29
|
+
ATTRIBUTE User-Name 1 string
|
30
|
+
ATTRIBUTE User-Password 2 string
|
31
|
+
ATTRIBUTE CHAP-Password 3 string
|
32
|
+
ATTRIBUTE NAS-IP-Address 4 ipaddr
|
33
|
+
ATTRIBUTE NAS-Port 5 integer
|
34
|
+
ATTRIBUTE Service-Type 6 integer
|
35
|
+
ATTRIBUTE Framed-Protocol 7 integer
|
36
|
+
ATTRIBUTE Framed-IP-Address 8 ipaddr
|
37
|
+
ATTRIBUTE Framed-IP-Netmask 9 ipaddr
|
38
|
+
ATTRIBUTE Framed-Routing 10 integer
|
39
|
+
ATTRIBUTE Filter-Id 11 string
|
40
|
+
ATTRIBUTE Framed-MTU 12 integer
|
41
|
+
ATTRIBUTE Framed-Compression 13 integer
|
42
|
+
ATTRIBUTE Login-IP-Host 14 ipaddr
|
43
|
+
ATTRIBUTE Login-Service 15 integer
|
44
|
+
ATTRIBUTE Login-TCP-Port 16 integer
|
45
|
+
ATTRIBUTE Reply-Message 18 string
|
46
|
+
ATTRIBUTE Callback-Number 19 string
|
47
|
+
ATTRIBUTE Callback-Id 20 string
|
48
|
+
ATTRIBUTE Expiration 21 date
|
49
|
+
ATTRIBUTE Framed-Route 22 string
|
50
|
+
ATTRIBUTE Framed-IPX-Network 23 ipaddr
|
51
|
+
ATTRIBUTE State 24 string
|
52
|
+
ATTRIBUTE Session-Timeout 27 integer
|
53
|
+
ATTRIBUTE Idle-Timeout 28 integer
|
54
|
+
ATTRIBUTE Termination-Action 29 integer
|
55
|
+
ATTRIBUTE Called-Station-Id 30 string
|
56
|
+
ATTRIBUTE Calling-Station-Id 31 string
|
57
|
+
ATTRIBUTE Acct-Status-Type 40 integer
|
58
|
+
ATTRIBUTE Acct-Delay-Time 41 integer
|
59
|
+
ATTRIBUTE Acct-Input-Octets 42 integer
|
60
|
+
ATTRIBUTE Acct-Output-Octets 43 integer
|
61
|
+
ATTRIBUTE Acct-Session-Id 44 string
|
62
|
+
ATTRIBUTE Acct-Authentic 45 integer
|
63
|
+
ATTRIBUTE Acct-Session-Time 46 integer
|
64
|
+
ATTRIBUTE Acct-Terminate-Cause 49 integer
|
65
|
+
ATTRIBUTE NAS-Port-Type 61 integer
|
66
|
+
ATTRIBUTE Port-Limit 62 integer
|
67
|
+
|
68
|
+
|
69
|
+
#
|
70
|
+
# Integer Translations
|
71
|
+
#
|
72
|
+
|
73
|
+
# User Types
|
74
|
+
|
75
|
+
VALUE Service-Type Login-User 1
|
76
|
+
VALUE Service-Type Framed-User 2
|
77
|
+
VALUE Service-Type Callback-Login-User 3
|
78
|
+
VALUE Service-Type Callback-Framed-User 4
|
79
|
+
VALUE Service-Type Outbound-User 5
|
80
|
+
VALUE Service-Type Administrative-User 6
|
81
|
+
VALUE Service-Type NAS-Prompt-User 7
|
82
|
+
|
83
|
+
# Framed Protocols
|
84
|
+
|
85
|
+
VALUE Framed-Protocol PPP 1
|
86
|
+
VALUE Framed-Protocol SLIP 2
|
87
|
+
|
88
|
+
# Framed Routing Values
|
89
|
+
|
90
|
+
VALUE Framed-Routing None 0
|
91
|
+
VALUE Framed-Routing Broadcast 1
|
92
|
+
VALUE Framed-Routing Listen 2
|
93
|
+
VALUE Framed-Routing Broadcast-Listen 3
|
94
|
+
|
95
|
+
# Framed Compression Types
|
96
|
+
|
97
|
+
VALUE Framed-Compression None 0
|
98
|
+
VALUE Framed-Compression Van-Jacobson-TCP-IP 1
|
99
|
+
|
100
|
+
# Login Services
|
101
|
+
|
102
|
+
VALUE Login-Service Telnet 0
|
103
|
+
VALUE Login-Service Rlogin 1
|
104
|
+
VALUE Login-Service TCP-Clear 2
|
105
|
+
VALUE Login-Service PortMaster 3
|
106
|
+
|
107
|
+
# Status Types
|
108
|
+
|
109
|
+
VALUE Acct-Status-Type Start 1
|
110
|
+
VALUE Acct-Status-Type Stop 2
|
111
|
+
|
112
|
+
# Authentication Types
|
113
|
+
|
114
|
+
VALUE Acct-Authentic RADIUS 1
|
115
|
+
VALUE Acct-Authentic Local 2
|
116
|
+
VALUE Acct-Authentic PowerLink128 100
|
117
|
+
|
118
|
+
# Termination Options
|
119
|
+
|
120
|
+
VALUE Termination-Action Default 0
|
121
|
+
VALUE Termination-Action RADIUS-Request 1
|
122
|
+
|
123
|
+
# NAS Port Types, available in ComOS 3.3.1 and later
|
124
|
+
|
125
|
+
VALUE NAS-Port-Type Async 0
|
126
|
+
VALUE NAS-Port-Type Sync 1
|
127
|
+
VALUE NAS-Port-Type ISDN 2
|
128
|
+
VALUE NAS-Port-Type ISDN-V120 3
|
129
|
+
VALUE NAS-Port-Type ISDN-V110 4
|
130
|
+
|
131
|
+
# Acct Terminate Causes, available in ComOS 3.3.2 and later
|
132
|
+
|
133
|
+
VALUE Acct-Terminate-Cause User-Request 1
|
134
|
+
VALUE Acct-Terminate-Cause Lost-Carrier 2
|
135
|
+
VALUE Acct-Terminate-Cause Lost-Service 3
|
136
|
+
VALUE Acct-Terminate-Cause Idle-Timeout 4
|
137
|
+
VALUE Acct-Terminate-Cause Session-Timeout 5
|
138
|
+
VALUE Acct-Terminate-Cause Admin-Reset 6
|
139
|
+
VALUE Acct-Terminate-Cause Admin-Reboot 7
|
140
|
+
VALUE Acct-Terminate-Cause Port-Error 8
|
141
|
+
VALUE Acct-Terminate-Cause NAS-Error 9
|
142
|
+
VALUE Acct-Terminate-Cause NAS-Request 10
|
143
|
+
VALUE Acct-Terminate-Cause NAS-Reboot 11
|
144
|
+
VALUE Acct-Terminate-Cause Port-Unneeded 12
|
145
|
+
VALUE Acct-Terminate-Cause Port-Preempted 13
|
146
|
+
VALUE Acct-Terminate-Cause Port-Suspended 14
|
147
|
+
VALUE Acct-Terminate-Cause Service-Unavailable 15
|
148
|
+
VALUE Acct-Terminate-Cause Callback 16
|
149
|
+
VALUE Acct-Terminate-Cause User-Error 17
|
150
|
+
VALUE Acct-Terminate-Cause Host-Request 18
|
151
|
+
|
152
|
+
|
153
|
+
#
|
154
|
+
# Obsolete names for backwards compatibility with older users files
|
155
|
+
# If you want RADIUS accounting logs to use the new names instead of
|
156
|
+
# these, move this section to the beginning of the dictionary file
|
157
|
+
# and kill and restart radiusd
|
158
|
+
# If you don't have a RADIUS 1.16 users file that you're still using,
|
159
|
+
# you can delete or ignore this section.
|
160
|
+
#
|
161
|
+
ATTRIBUTE Client-Id 4 ipaddr
|
162
|
+
ATTRIBUTE Client-Port-Id 5 integer
|
163
|
+
ATTRIBUTE User-Service-Type 6 integer
|
164
|
+
ATTRIBUTE Framed-Address 8 ipaddr
|
165
|
+
ATTRIBUTE Framed-Netmask 9 ipaddr
|
166
|
+
ATTRIBUTE Framed-Filter-Id 11 string
|
167
|
+
ATTRIBUTE Login-Host 14 ipaddr
|
168
|
+
ATTRIBUTE Login-Port 16 integer
|
169
|
+
ATTRIBUTE Old-Password 17 string
|
170
|
+
ATTRIBUTE Port-Message 18 string
|
171
|
+
ATTRIBUTE Dialback-No 19 string
|
172
|
+
ATTRIBUTE Dialback-Name 20 string
|
173
|
+
ATTRIBUTE Challenge-State 24 string
|
174
|
+
VALUE Service-Type Dialback-Login-User 3
|
175
|
+
VALUE Service-Type Dialback-Framed-User 4
|
176
|
+
VALUE Service-Type Shell-User 6
|
177
|
+
VALUE Framed-Compression Van-Jacobsen-TCP-IP 1
|
178
|
+
#VALUE Auth-Type Unix 1
|
179
|
+
#
|
180
|
+
# END of obsolete names for backwards compatibility
|
181
|
+
#
|
182
|
+
|
183
|
+
#
|
184
|
+
# Configuration Values
|
185
|
+
# uncomment out these two lines to turn account expiration on
|
186
|
+
#
|
187
|
+
|
188
|
+
#VALUE Server-Config Password-Expiration 30
|
189
|
+
#VALUE Server-Config Password-Warning 5
|
190
|
+
|
191
|
+
##
|
192
|
+
## VENDOR SPECIFIC ATTRIBUTES
|
193
|
+
##
|
194
|
+
## The following entries demonstrate the use of VSAs
|
195
|
+
##
|
196
|
+
|
197
|
+
# cisco-avpair is used for various functions by cisco IOS. Most
|
198
|
+
# notably, it's used to create VPDN tunnels.
|
199
|
+
#
|
200
|
+
VENDORATTR 9 cisco-avpair 1 string
|
201
|
+
|
202
|
+
# This is a fake attribute to demonstrate how to write named-value
|
203
|
+
# attributes.
|
204
|
+
VENDORATTR 1 ibm-enum 254 integer
|
205
|
+
VENDORVALUE 1 ibm-enum value-1 1
|
206
|
+
VENDORVALUE 1 ibm-enum value-2 2
|
207
|
+
VENDORVALUE 1 ibm-enum value-3 3
|
File without changes
|
data/version.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: radiustar
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
version: 0.0.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- PJ Davis
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-04-15 00:00:00 -05:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: bones
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 3
|
29
|
+
- 4
|
30
|
+
- 1
|
31
|
+
version: 3.4.1
|
32
|
+
type: :development
|
33
|
+
version_requirements: *id001
|
34
|
+
description: Ruby Radius Library
|
35
|
+
email: pj.davis@gmail.com
|
36
|
+
executables: []
|
37
|
+
|
38
|
+
extensions: []
|
39
|
+
|
40
|
+
extra_rdoc_files:
|
41
|
+
- History.txt
|
42
|
+
- README.rdoc
|
43
|
+
- templates/default.txt
|
44
|
+
- version.txt
|
45
|
+
files:
|
46
|
+
- .gitignore
|
47
|
+
- History.txt
|
48
|
+
- README.rdoc
|
49
|
+
- Rakefile
|
50
|
+
- lib/radiustar.rb
|
51
|
+
- lib/radiustar/dictionary.rb
|
52
|
+
- lib/radiustar/dictionary/attributes.rb
|
53
|
+
- lib/radiustar/dictionary/values.rb
|
54
|
+
- lib/radiustar/packet.rb
|
55
|
+
- lib/radiustar/radiustar.rb
|
56
|
+
- lib/radiustar/request.rb
|
57
|
+
- spec/radiustar_spec.rb
|
58
|
+
- spec/spec_helper.rb
|
59
|
+
- templates/default.txt
|
60
|
+
- test/test_radiustar.rb
|
61
|
+
- version.txt
|
62
|
+
has_rdoc: true
|
63
|
+
homepage: http://github.com/pjdavis/radiustar
|
64
|
+
licenses: []
|
65
|
+
|
66
|
+
post_install_message:
|
67
|
+
rdoc_options:
|
68
|
+
- --main
|
69
|
+
- README.rdoc
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
version: "0"
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
segments:
|
84
|
+
- 0
|
85
|
+
version: "0"
|
86
|
+
requirements: []
|
87
|
+
|
88
|
+
rubyforge_project: radiustar
|
89
|
+
rubygems_version: 1.3.6
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: Ruby Radius Library
|
93
|
+
test_files:
|
94
|
+
- test/test_radiustar.rb
|