radiustar 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|