dguerri-radiustar 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +7 -0
- data/History.txt +11 -0
- data/README.rdoc +90 -0
- data/Rakefile +20 -0
- data/lib/radiustar.rb +65 -0
- data/lib/radiustar/dictionary.rb +140 -0
- data/lib/radiustar/dictionary/attributes.rb +61 -0
- data/lib/radiustar/dictionary/values.rb +43 -0
- data/lib/radiustar/packet.rb +210 -0
- data/lib/radiustar/radiustar.rb +7 -0
- data/lib/radiustar/request.rb +124 -0
- data/lib/radiustar/vendor.rb +60 -0
- data/radiustar.gemspec +34 -0
- data/spec/radiustar_spec.rb +16 -0
- data/spec/spec_helper.rb +15 -0
- data/templates/default.txt +207 -0
- data/templates/dictionary.digium +36 -0
- data/templates/gandalf.dictionary +105 -0
- data/test/test_radiustar.rb +0 -0
- data/version.txt +1 -0
- metadata +106 -0
data/.gitignore
ADDED
data/History.txt
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
== 0.0.4 / 2010-12/04
|
2
|
+
* github fork (dguerri)
|
3
|
+
* bugfixes
|
4
|
+
* added multiple dictionary files support
|
5
|
+
* added accounting support
|
6
|
+
|
7
|
+
== 0.0.3 / 2010-06-30
|
8
|
+
* no longer require to specify your own IP (via bwlang)
|
9
|
+
|
10
|
+
== 0.0.1 / 2010-04-14
|
11
|
+
* winning at radius
|
data/README.rdoc
ADDED
@@ -0,0 +1,90 @@
|
|
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 dictionaries
|
36
|
+
* Authentication
|
37
|
+
* Accounting
|
38
|
+
|
39
|
+
== SYNOPSIS:
|
40
|
+
|
41
|
+
require 'rubygems'
|
42
|
+
require 'radiustar'
|
43
|
+
|
44
|
+
# Load dictionaries from freeradius directory
|
45
|
+
dict = Radiustar::Dictionary.new('/usr/share/freeradius/')
|
46
|
+
|
47
|
+
# Lets get authenticated
|
48
|
+
auth_custom_attr = {
|
49
|
+
'Framed-Address' => '127.0.0.1',
|
50
|
+
'NAS-Port' => 0,
|
51
|
+
'NAS-Port-Type' => 'Ethernet'
|
52
|
+
}
|
53
|
+
|
54
|
+
req = Radiustar::Request.new('127.0.0.1', { :dict => dict })
|
55
|
+
reply = req.authenticate('John Doe', 'hello', 'testing123', auth_custom_attr)
|
56
|
+
|
57
|
+
if reply[:code] == 'Access-Accept'
|
58
|
+
req = Radiustar::Request.new('127.0.0.1:1813', { :dict => dict })
|
59
|
+
|
60
|
+
acct_custom_attr = {
|
61
|
+
'Framed-Address' => '127.0.0.1',
|
62
|
+
'NAS-Port' => 0,
|
63
|
+
'NAS-Port-Type' => 'Ethernet',
|
64
|
+
'Acct-Session-Time' => 0
|
65
|
+
}
|
66
|
+
|
67
|
+
timings = Time.now
|
68
|
+
reply = req.accounting_start('John Doe', 'testing123', '123456', acct_custom_attr)
|
69
|
+
|
70
|
+
sleep(rand 5)
|
71
|
+
acct_custom_attr['Acct-Session-Time'] = Time.now - timings
|
72
|
+
reply = req.accounting_update('John Doe', 'testing123', '123456', acct_custom_attr)
|
73
|
+
|
74
|
+
sleep(rand 5)
|
75
|
+
acct_custom_attr['Acct-Session-Time'] = Time.now - timings
|
76
|
+
reply = req.accounting_stop('John Doe', 'testing123', '123456', acct_custom_attr)
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
== REQUIREMENTS:
|
81
|
+
|
82
|
+
* Ruby 1.8
|
83
|
+
|
84
|
+
== INSTALL:
|
85
|
+
|
86
|
+
gem install radiustar
|
87
|
+
|
88
|
+
== LICENSE:
|
89
|
+
|
90
|
+
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 'dguerri-radiustar'
|
13
|
+
authors 'PJ Davis', 'Davide Guerri'
|
14
|
+
email 'davide.guerri@gmail.com'
|
15
|
+
url 'http://github.com/dguerri/radiustar'
|
16
|
+
ignore_file '.gitignore'
|
17
|
+
readme_file 'README.rdoc'
|
18
|
+
|
19
|
+
}
|
20
|
+
|
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
|
+
|
@@ -0,0 +1,140 @@
|
|
1
|
+
module Radiustar
|
2
|
+
|
3
|
+
class Dictionary
|
4
|
+
|
5
|
+
include Radiustar
|
6
|
+
|
7
|
+
DEFAULT_DICTIONARIES_PATH = ::File.join(::File.dirname(__FILE__), '..', '..', 'templates')
|
8
|
+
|
9
|
+
def initialize(initial_path = nil)
|
10
|
+
@attributes = AttributesCollection.new
|
11
|
+
@vendors = VendorCollection.new
|
12
|
+
|
13
|
+
read_files initial_path if initial_path
|
14
|
+
end
|
15
|
+
|
16
|
+
def read_files(path)
|
17
|
+
dict_files = File.join(path, "*")
|
18
|
+
Dir.glob(dict_files) { |file|
|
19
|
+
read_attributes(file)
|
20
|
+
}
|
21
|
+
Dir.glob(dict_files) { |file|
|
22
|
+
read_values(file)
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def find_attribute_by_name(name)
|
27
|
+
@attributes.find_by_name(name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def find_attribute_by_id(id)
|
31
|
+
@attributes.find_by_id(id)
|
32
|
+
end
|
33
|
+
|
34
|
+
def attribute_name_defined?(name)
|
35
|
+
!@attributes.find_by_name(name).nil?
|
36
|
+
end
|
37
|
+
|
38
|
+
def attribute_id_defined?(id)
|
39
|
+
!@attributes.find_by_id(id).nil?
|
40
|
+
end
|
41
|
+
|
42
|
+
def vendors
|
43
|
+
@vendors
|
44
|
+
end
|
45
|
+
|
46
|
+
def attributes
|
47
|
+
@attributes
|
48
|
+
end
|
49
|
+
|
50
|
+
def name
|
51
|
+
"Dictionary"
|
52
|
+
end
|
53
|
+
|
54
|
+
class << self
|
55
|
+
|
56
|
+
def default
|
57
|
+
new DEFAULT_DICTIONARIES_PATH
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
|
64
|
+
def read_attributes(path)
|
65
|
+
file = File.open(path) do |f|
|
66
|
+
current_vendor = nil
|
67
|
+
f.each_line do |line|
|
68
|
+
next if line =~ /^\#/ # discard comments
|
69
|
+
split_line = line.split(/\s+/)
|
70
|
+
next if split_line == []
|
71
|
+
case split_line.first.upcase
|
72
|
+
when "ATTRIBUTE"
|
73
|
+
current_vendor.nil? ? set_attr(split_line) : set_vendor_attr(current_vendor, split_line)
|
74
|
+
when "VENDOR"
|
75
|
+
add_vendor(split_line)
|
76
|
+
when "BEGIN-VENDOR"
|
77
|
+
current_vendor = set_vendor(split_line)
|
78
|
+
when "END-VENDOR"
|
79
|
+
current_vendor = nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def read_values(path)
|
86
|
+
file = File.open(path) do |f|
|
87
|
+
current_vendor = nil
|
88
|
+
f.each_line do |line|
|
89
|
+
next if line =~ /^\#/ # discard comments
|
90
|
+
split_line = line.split(/\s+/)
|
91
|
+
next if split_line == []
|
92
|
+
case split_line.first.upcase
|
93
|
+
when "VALUE"
|
94
|
+
if current_vendor.nil?
|
95
|
+
set_value(split_line)
|
96
|
+
else
|
97
|
+
begin
|
98
|
+
set_vendor_value(current_vendor, split_line)
|
99
|
+
rescue
|
100
|
+
set_value(split_line)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
when "BEGIN-VENDOR"
|
104
|
+
current_vendor = set_vendor(split_line)
|
105
|
+
when "END-VENDOR"
|
106
|
+
current_vendor = nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def set_attr(line)
|
115
|
+
@attributes.add(line[1], line[2], line[3])
|
116
|
+
end
|
117
|
+
|
118
|
+
def set_value(line)
|
119
|
+
@attributes.find_by_name(line[1]).add_value(line[2], line[3])
|
120
|
+
end
|
121
|
+
|
122
|
+
def add_vendor(line)
|
123
|
+
@vendors.add(line[2], line[1])
|
124
|
+
end
|
125
|
+
|
126
|
+
def set_vendor(line)
|
127
|
+
@vendors.find_by_name(line[1])
|
128
|
+
end
|
129
|
+
|
130
|
+
def set_vendor_attr(vendor, line)
|
131
|
+
vendor.add_attribute(line[1], line[2], line[3])
|
132
|
+
end
|
133
|
+
|
134
|
+
def set_vendor_value(vendor, line)
|
135
|
+
vendor.find_attribute_by_name(line[1]).add_value(line[2], line[3])
|
136
|
+
end
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Radiustar
|
2
|
+
|
3
|
+
class AttributesCollection < Array
|
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
|
+
self << @collection[name]
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_by_name(name)
|
17
|
+
@collection[name]
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_by_id(id)
|
21
|
+
@revcollection[id]
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
class Attribute
|
27
|
+
|
28
|
+
include Radiustar
|
29
|
+
|
30
|
+
attr_reader :name, :id, :type
|
31
|
+
|
32
|
+
def initialize(name, id, type)
|
33
|
+
@values = ValuesCollection.new
|
34
|
+
@name = name
|
35
|
+
@id = id.to_i
|
36
|
+
@type = type
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_value(name, id)
|
40
|
+
@values.add(name, id.to_i)
|
41
|
+
end
|
42
|
+
|
43
|
+
def find_values_by_name(name)
|
44
|
+
@values.find_by_name(name)
|
45
|
+
end
|
46
|
+
|
47
|
+
def find_values_by_id(id)
|
48
|
+
@values.find_by_id(id.to_i)
|
49
|
+
end
|
50
|
+
|
51
|
+
def has_values?
|
52
|
+
!@values.empty?
|
53
|
+
end
|
54
|
+
|
55
|
+
def values
|
56
|
+
@values
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Radiustar
|
2
|
+
|
3
|
+
class ValuesCollection < Array
|
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
|
+
self << @collection[name]
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_by_name(name)
|
17
|
+
@collection[name]
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_by_id(id)
|
21
|
+
@revcollection[id]
|
22
|
+
end
|
23
|
+
|
24
|
+
def empty?
|
25
|
+
@collection.empty?
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
class Value
|
31
|
+
|
32
|
+
include Radiustar
|
33
|
+
|
34
|
+
attr_accessor :name, :id
|
35
|
+
|
36
|
+
def initialize(name, id)
|
37
|
+
@name = name
|
38
|
+
@id = id.to_i
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,210 @@
|
|
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_auth_authenticator
|
42
|
+
if (File.exist?("/dev/urandom"))
|
43
|
+
File.open("/dev/urandom") do |urandom|
|
44
|
+
@authenticator = urandom.read(16)
|
45
|
+
end
|
46
|
+
else
|
47
|
+
@authenticator = []
|
48
|
+
8.times do
|
49
|
+
@authenticator << rand(65536)
|
50
|
+
end
|
51
|
+
@authenticator = @authenticator.pack("n8")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def gen_acct_authenticator(secret)
|
56
|
+
# From RFC2866
|
57
|
+
# Request Authenticator
|
58
|
+
#
|
59
|
+
# In Accounting-Request Packets, the Authenticator value is a 16
|
60
|
+
# octet MD5 [5] checksum, called the Request Authenticator.
|
61
|
+
#
|
62
|
+
# The NAS and RADIUS accounting server share a secret. The Request
|
63
|
+
# Authenticator field in Accounting-Request packets contains a one-
|
64
|
+
# way MD5 hash calculated over a stream of octets consisting of the
|
65
|
+
# Code + Identifier + Length + 16 zero octets + request attributes +
|
66
|
+
# shared secret (where + indicates concatenation). The 16 octet MD5
|
67
|
+
# hash value is stored in the Authenticator field of the
|
68
|
+
# Accounting-Request packet.
|
69
|
+
#
|
70
|
+
# Note that the Request Authenticator of an Accounting-Request can
|
71
|
+
# not be done the same way as the Request Authenticator of a RADIUS
|
72
|
+
# Access-Request, because there is no User-Password attribute in an
|
73
|
+
# Accounting-Request.
|
74
|
+
#
|
75
|
+
@authenticator = "\000"*16
|
76
|
+
@authenticator = Digest::MD5.digest(pack + secret)
|
77
|
+
@packed = nil
|
78
|
+
end
|
79
|
+
|
80
|
+
def set_attribute(name, value)
|
81
|
+
@attributes[name] = value
|
82
|
+
end
|
83
|
+
|
84
|
+
def unset_attribute(name)
|
85
|
+
@attributes[name] = nil
|
86
|
+
end
|
87
|
+
|
88
|
+
def attribute(name)
|
89
|
+
@attributes[name]
|
90
|
+
end
|
91
|
+
|
92
|
+
def unset_all_attributes
|
93
|
+
@attributes = Hash.new
|
94
|
+
end
|
95
|
+
|
96
|
+
def set_encoded_attribute(name, value, secret)
|
97
|
+
@attributes[name] = encode(value, secret)
|
98
|
+
end
|
99
|
+
|
100
|
+
def pack
|
101
|
+
|
102
|
+
attstr = ""
|
103
|
+
@attributes.each_pair do |attribute_s, value|
|
104
|
+
attribute = @dict.find_attribute_by_name(attribute_s)
|
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)
|
125
|
+
end
|
126
|
+
|
127
|
+
@packed = [CODES[@code], @id, attstr.length + HDRLEN, @authenticator, attstr].pack(P_HDR)
|
128
|
+
end
|
129
|
+
|
130
|
+
protected
|
131
|
+
|
132
|
+
def unpack
|
133
|
+
@code, @id, len, @authenticator, attribute_data = @packed.unpack(P_HDR)
|
134
|
+
@code = CODES.index(@code)
|
135
|
+
|
136
|
+
unset_all_attributes
|
137
|
+
|
138
|
+
while attribute_data.length > 0 do
|
139
|
+
length = attribute_data.unpack("xC").first.to_i
|
140
|
+
attribute_type, attribute_value = attribute_data.unpack("Cxa#{length-2}")
|
141
|
+
attribute_type = attribute_type.to_i
|
142
|
+
|
143
|
+
attribute = @dict.find_attribute_by_id(attribute_type)
|
144
|
+
attribute_value = case attribute.type
|
145
|
+
when 'string'
|
146
|
+
attribute_value
|
147
|
+
when 'integer'
|
148
|
+
attribute.has_values? ? attribute.find_values_by_id(attribute_value.unpack("N")[0]).name : attribute_value.unpack("N")[0]
|
149
|
+
when 'ipaddr'
|
150
|
+
inet_ntoa(attribute_value.unpack("N")[0])
|
151
|
+
when 'time'
|
152
|
+
attribute_value.unpack("N")[0]
|
153
|
+
when 'date'
|
154
|
+
attribute_value.unpack("N")[0]
|
155
|
+
end
|
156
|
+
|
157
|
+
set_attribute(attribute.name, attribute_value) if attribute
|
158
|
+
attribute_data[0, length] = ""
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
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
|
+
def xor_str(str1, str2)
|
174
|
+
i = 0
|
175
|
+
newstr = ""
|
176
|
+
str1.each_byte do |c1|
|
177
|
+
c2 = str2[i]
|
178
|
+
newstr = newstr << (c1 ^ c2)
|
179
|
+
i = i+1
|
180
|
+
end
|
181
|
+
newstr
|
182
|
+
end
|
183
|
+
|
184
|
+
def encode(value, secret)
|
185
|
+
lastround = @authenticator
|
186
|
+
encoded_value = ""
|
187
|
+
# pad to 16n bytes
|
188
|
+
value += "\000" * (15-(15 + value.length) % 16)
|
189
|
+
0.step(value.length-1, 16) do |i|
|
190
|
+
lastround = xor_str(value[i, 16], Digest::MD5.digest(secret + lastround) )
|
191
|
+
encoded_value += lastround
|
192
|
+
end
|
193
|
+
encoded_value
|
194
|
+
end
|
195
|
+
|
196
|
+
def decode(value, secret)
|
197
|
+
decoded_value = ""
|
198
|
+
lastround = @authenticator
|
199
|
+
0.step(value.length-1, 16) do |i|
|
200
|
+
decoded_value = xor_str(value[i, 16], Digest::MD5.digest(secret + lastround))
|
201
|
+
lastround = value[i, 16]
|
202
|
+
end
|
203
|
+
|
204
|
+
decoded_value.gsub!(/\000+/, "") if decoded_value
|
205
|
+
decoded_value[value.length, -1] = "" unless (decoded_value.length <= value.length)
|
206
|
+
return decoded_value
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Radiustar
|
2
|
+
|
3
|
+
require 'socket'
|
4
|
+
|
5
|
+
class Request
|
6
|
+
|
7
|
+
def initialize(server, options = {})
|
8
|
+
@dict = options[:dict].nil? ? Dictionary.default : options[:dict]
|
9
|
+
@nas_ip = options[:nas_ip] || get_my_ip(@host)
|
10
|
+
@nas_identifier = options[:nas_identifier] || @nas_ip
|
11
|
+
@reply_timeout = options[:reply_timeout].nil? ? 60 : options[:reply_timeout].to_i
|
12
|
+
@retries_number = options[:retries_number].nil? ? 1 : options[:retries_number].to_i
|
13
|
+
|
14
|
+
@host, @port = server.split(":")
|
15
|
+
|
16
|
+
@port = Socket.getservbyname("radius", "udp") unless @port
|
17
|
+
@port = 1812 unless @port
|
18
|
+
@port = @port.to_i # just in case
|
19
|
+
@socket = UDPSocket.open
|
20
|
+
@socket.connect(@host, @port)
|
21
|
+
end
|
22
|
+
|
23
|
+
def authenticate(name, password, secret, user_attributes = {})
|
24
|
+
@packet = Packet.new(@dict, Process.pid & 0xff)
|
25
|
+
@packet.gen_auth_authenticator
|
26
|
+
@packet.code = 'Access-Request'
|
27
|
+
@packet.set_attribute('User-Name', name)
|
28
|
+
@packet.set_attribute('NAS-Identifier', @nas_identifier)
|
29
|
+
@packet.set_attribute('NAS-IP-Address', @nas_ip)
|
30
|
+
@packet.set_encoded_attribute('User-Password', password, secret)
|
31
|
+
|
32
|
+
user_attributes.each_pair do |name, value|
|
33
|
+
@packet.set_attribute(name, value)
|
34
|
+
end
|
35
|
+
|
36
|
+
begin
|
37
|
+
send_packet
|
38
|
+
@recieved_packet = recv_packet(@reply_timeout)
|
39
|
+
rescue Exception => e
|
40
|
+
retry if (@retries_number -= 1) > 0
|
41
|
+
raise
|
42
|
+
end
|
43
|
+
|
44
|
+
reply = { :code => @recieved_packet.code }
|
45
|
+
reply.merge @recieved_packet.attributes
|
46
|
+
end
|
47
|
+
|
48
|
+
def accounting_request(status_type, name, secret, sessionid, user_attributes = {})
|
49
|
+
|
50
|
+
@packet = Packet.new(@dict, Process.pid & 0xff)
|
51
|
+
@packet.code = 'Accounting-Request'
|
52
|
+
|
53
|
+
@packet.set_attribute('User-Name', name)
|
54
|
+
@packet.set_attribute('NAS-Identifier', @nas_identifier)
|
55
|
+
@packet.set_attribute('NAS-IP-Address', @nas_ip)
|
56
|
+
@packet.set_attribute('Acct-Status-Type', status_type)
|
57
|
+
@packet.set_attribute('Acct-Session-Id', sessionid)
|
58
|
+
@packet.set_attribute('Acct-Authentic', 'RADIUS')
|
59
|
+
|
60
|
+
user_attributes.each_pair do |name, value|
|
61
|
+
@packet.set_attribute(name, value)
|
62
|
+
end
|
63
|
+
|
64
|
+
@packet.gen_acct_authenticator(secret)
|
65
|
+
|
66
|
+
begin
|
67
|
+
send_packet
|
68
|
+
@recieved_packet = recv_packet(@reply_timeout)
|
69
|
+
rescue Exception => e
|
70
|
+
retry if (@retries_number -= 1) > 0
|
71
|
+
raise
|
72
|
+
end
|
73
|
+
|
74
|
+
return true
|
75
|
+
end
|
76
|
+
|
77
|
+
def accounting_start(name, secret, sessionid, options = {})
|
78
|
+
accounting_request('Start', name, secret, sessionid, options)
|
79
|
+
end
|
80
|
+
|
81
|
+
def accounting_update(name, secret, sessionid, options = {})
|
82
|
+
accounting_request('Interim-Update', name, secret, sessionid, options)
|
83
|
+
end
|
84
|
+
|
85
|
+
def accounting_stop(name, secret, sessionid, options = {})
|
86
|
+
accounting_request('Stop', name, secret, sessionid, options)
|
87
|
+
end
|
88
|
+
|
89
|
+
def inspect
|
90
|
+
to_s
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def send_packet
|
96
|
+
data = @packet.pack
|
97
|
+
@packet.increment_id
|
98
|
+
@socket.send(data, 0)
|
99
|
+
end
|
100
|
+
|
101
|
+
def recv_packet(timeout)
|
102
|
+
if select([@socket], nil, nil, timeout.to_i) == nil
|
103
|
+
raise "Timed out waiting for response packet from server"
|
104
|
+
end
|
105
|
+
data = @socket.recvfrom(64)
|
106
|
+
Packet.new(@dict, Process.pid & 0xff, data[0])
|
107
|
+
end
|
108
|
+
|
109
|
+
#looks up the source IP address with a route to the specified destination
|
110
|
+
def get_my_ip(dest_address)
|
111
|
+
orig_reverse_lookup_setting = Socket.do_not_reverse_lookup
|
112
|
+
Socket.do_not_reverse_lookup = true
|
113
|
+
|
114
|
+
UDPSocket.open do |sock|
|
115
|
+
sock.connect dest_address, 1
|
116
|
+
sock.addr.last
|
117
|
+
end
|
118
|
+
ensure
|
119
|
+
Socket.do_not_reverse_lookup = orig_reverse_lookup_setting
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Radiustar
|
2
|
+
|
3
|
+
class VendorCollection < Array
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@collection = {}
|
7
|
+
@revcollection = []
|
8
|
+
end
|
9
|
+
|
10
|
+
def add(id, name)
|
11
|
+
@collection[name] ||= Vendor.new(name, id)
|
12
|
+
@revcollection[id.to_i] ||= @collection[name]
|
13
|
+
self << @collection[name]
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_by_name(name)
|
17
|
+
@collection[name]
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_by_id(id)
|
21
|
+
@revcollection[id.to_i]
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
class Vendor
|
27
|
+
|
28
|
+
include Radiustar
|
29
|
+
|
30
|
+
attr_reader :name, :id
|
31
|
+
|
32
|
+
def initialize(name, id)
|
33
|
+
@name = name
|
34
|
+
@id = id
|
35
|
+
@attributes = AttributesCollection.new
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_attribute(name, id, type)
|
39
|
+
@attributes.add(name, id, type)
|
40
|
+
end
|
41
|
+
|
42
|
+
def find_attribute_by_name(name)
|
43
|
+
@attributes.find_by_name(name)
|
44
|
+
end
|
45
|
+
|
46
|
+
def find_attribute_by_id(id)
|
47
|
+
@attributes.find_by_id(id.to_i)
|
48
|
+
end
|
49
|
+
|
50
|
+
def has_attributes?
|
51
|
+
!@attributes.empty?
|
52
|
+
end
|
53
|
+
|
54
|
+
def attributes
|
55
|
+
@attributes
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
data/radiustar.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{dguerri-radiustar}
|
5
|
+
s.version = "0.0.4"
|
6
|
+
|
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{2010-12-04}
|
10
|
+
s.description = %q{Ruby Radius Library}
|
11
|
+
s.email = %q{davide.guerri@gmail.com}
|
12
|
+
s.extra_rdoc_files = ["History.txt", "README.rdoc", "templates/default.txt", "version.txt"]
|
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
|
+
s.homepage = %q{http://github.com/dguerri/radiustar}
|
15
|
+
s.rdoc_options = ["--main", "README.rdoc"]
|
16
|
+
s.require_paths = ["lib"]
|
17
|
+
s.rubyforge_project = %q{radiustar}
|
18
|
+
s.rubygems_version = %q{1.3.6}
|
19
|
+
s.summary = %q{Ruby Radius Library}
|
20
|
+
s.test_files = ["test/test_radiustar.rb"]
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
|
+
s.specification_version = 3
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
27
|
+
s.add_development_dependency(%q<bones>, [">= 3.4.1"])
|
28
|
+
else
|
29
|
+
s.add_dependency(%q<bones>, [">= 3.4.1"])
|
30
|
+
end
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<bones>, [">= 3.4.1"])
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), %w[spec_helper])
|
2
|
+
|
3
|
+
describe Radiustar::Packet do
|
4
|
+
it "gen_authenticator generates a random string without /dev/urandom" do
|
5
|
+
File.stub(:exist?).and_return(false)
|
6
|
+
packet = Radiustar::Packet.new(nil, nil)
|
7
|
+
packet.gen_authenticator.class.should == String
|
8
|
+
end
|
9
|
+
|
10
|
+
if File.exist?("/dev/urandom") # don't fail if specs are running on a platform without /dev/urandom
|
11
|
+
it "gen_authenticator generates a random string with /dev/urandom" do
|
12
|
+
packet = Radiustar::Packet.new(nil, nil)
|
13
|
+
packet.gen_authenticator.class.should == String
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
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
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# -*- text -*-
|
2
|
+
##############################################################################
|
3
|
+
#
|
4
|
+
# Digium's Asterisk specific radius attributes
|
5
|
+
# markster@digium.com
|
6
|
+
#
|
7
|
+
# http://bugs.digium.com/file_download.php\?file_id=9688\&type=bug
|
8
|
+
#
|
9
|
+
# $Id$
|
10
|
+
#
|
11
|
+
##############################################################################
|
12
|
+
|
13
|
+
VENDOR Digium 22736
|
14
|
+
|
15
|
+
BEGIN-VENDOR Digium
|
16
|
+
|
17
|
+
ATTRIBUTE Asterisk-Acc-Code 101 string
|
18
|
+
ATTRIBUTE Asterisk-Src 102 string
|
19
|
+
ATTRIBUTE Asterisk-Dst 103 string
|
20
|
+
ATTRIBUTE Asterisk-Dst-Ctx 104 string
|
21
|
+
ATTRIBUTE Asterisk-Clid 105 string
|
22
|
+
ATTRIBUTE Asterisk-Chan 106 string
|
23
|
+
ATTRIBUTE Asterisk-Dst-Chan 107 string
|
24
|
+
ATTRIBUTE Asterisk-Last-App 108 string
|
25
|
+
ATTRIBUTE Asterisk-Last-Data 109 string
|
26
|
+
ATTRIBUTE Asterisk-Start-Time 110 string
|
27
|
+
ATTRIBUTE Asterisk-Answer-Time 111 string
|
28
|
+
ATTRIBUTE Asterisk-End-Time 112 string
|
29
|
+
ATTRIBUTE Asterisk-Duration 113 integer
|
30
|
+
ATTRIBUTE Asterisk-Bill-Sec 114 integer
|
31
|
+
ATTRIBUTE Asterisk-Disposition 115 string
|
32
|
+
ATTRIBUTE Asterisk-AMA-Flags 116 string
|
33
|
+
ATTRIBUTE Asterisk-Unique-ID 117 string
|
34
|
+
ATTRIBUTE Asterisk-User-Field 118 string
|
35
|
+
|
36
|
+
END-VENDOR Digium
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# -*- text -*-
|
2
|
+
# Gandalf dictionary
|
3
|
+
#
|
4
|
+
# Version: 1.00 24-July-2003 Blaise St-Laurent <bstlaurent@okiok.com>
|
5
|
+
#
|
6
|
+
# Notes: Dictionary was made specifically for the Gandalf XpressWay
|
7
|
+
# RLAN with Link Authentication through RADIUS
|
8
|
+
#
|
9
|
+
# $Id$
|
10
|
+
#
|
11
|
+
VENDOR Gandalf 64
|
12
|
+
|
13
|
+
#
|
14
|
+
# Vendor-specific attributes
|
15
|
+
#
|
16
|
+
BEGIN-VENDOR Gandalf
|
17
|
+
|
18
|
+
ATTRIBUTE Gandalf-Remote-LAN-Name 0 string
|
19
|
+
ATTRIBUTE Gandalf-Operational-Modes 1 integer
|
20
|
+
ATTRIBUTE Gandalf-Compression-Status 2 integer
|
21
|
+
ATTRIBUTE Gandalf-Min-Outgoing-Bearer 3 integer
|
22
|
+
ATTRIBUTE Gandalf-Authentication-String 5 string
|
23
|
+
ATTRIBUTE Gandalf-PPP-Authentication 6 integer
|
24
|
+
ATTRIBUTE Gandalf-PPP-NCP-Type 7 integer
|
25
|
+
ATTRIBUTE Gandalf-Fwd-Multicast-In 8 integer
|
26
|
+
ATTRIBUTE Gandalf-Fwd-Broadcast-In 9 integer
|
27
|
+
ATTRIBUTE Gandalf-Fwd-Unicast-In 10 integer
|
28
|
+
ATTRIBUTE Gandalf-Fwd-Multicast-Out 11 integer
|
29
|
+
ATTRIBUTE Gandalf-Fwd-Broadcast-Out 12 integer
|
30
|
+
ATTRIBUTE Gandalf-Fwd-Unicast-Out 13 integer
|
31
|
+
ATTRIBUTE Gandalf-Around-The-Corner 14 integer
|
32
|
+
ATTRIBUTE Gandalf-Channel-Group-Name-1 15 string
|
33
|
+
ATTRIBUTE Gandalf-Dial-Prefix-Name-1 16 string
|
34
|
+
ATTRIBUTE Gandalf-Phone-Number-1 17 string
|
35
|
+
ATTRIBUTE Gandalf-Calling-Line-ID-1 18 string
|
36
|
+
ATTRIBUTE Gandalf-Channel-Group-Name-2 19 string
|
37
|
+
ATTRIBUTE Gandalf-Dial-Prefix-Name-2 20 string
|
38
|
+
ATTRIBUTE Gandalf-Phone-Number-2 21 string
|
39
|
+
ATTRIBUTE Gandalf-Calling-Line-ID-2 22 string
|
40
|
+
ATTRIBUTE Gandalf-IPX-Spoofing-State 23 integer
|
41
|
+
ATTRIBUTE Gandalf-IPX-Watchdog-Spoof 24 integer
|
42
|
+
ATTRIBUTE Gandalf-SAP-Group-Name-1 25 string
|
43
|
+
ATTRIBUTE Gandalf-SAP-Group-Name-2 26 string
|
44
|
+
ATTRIBUTE Gandalf-SAP-Group-Name-3 27 string
|
45
|
+
ATTRIBUTE Gandalf-SAP-Group-Name-4 28 string
|
46
|
+
ATTRIBUTE Gandalf-SAP-Group-Name-5 29 string
|
47
|
+
ATTRIBUTE Gandalf-Hunt-Group 30 string
|
48
|
+
ATTRIBUTE Gandalf-Modem-Mode 31 integer
|
49
|
+
ATTRIBUTE Gandalf-Modem-Required-1 32 integer
|
50
|
+
ATTRIBUTE Gandalf-Modem-Required-2 33 integer
|
51
|
+
|
52
|
+
VALUE Gandalf-Operational-Modes Disabled 1
|
53
|
+
VALUE Gandalf-Operational-Modes Called-Only 2
|
54
|
+
VALUE Gandalf-Operational-Modes Calling-Called 3
|
55
|
+
VALUE Gandalf-Operational-Modes Calling-Only 4
|
56
|
+
|
57
|
+
VALUE Gandalf-Compression-Status Disabled 1
|
58
|
+
VALUE Gandalf-Compression-Status Enabled 2
|
59
|
+
|
60
|
+
VALUE Gandalf-Min-Outgoing-Bearer Unrestricted-64K 1
|
61
|
+
VALUE Gandalf-Min-Outgoing-Bearer Digital-56K 2
|
62
|
+
VALUE Gandalf-Min-Outgoing-Bearer 3100Hz-Audio 3
|
63
|
+
|
64
|
+
VALUE Gandalf-PPP-Authentication CHAP 1
|
65
|
+
VALUE Gandalf-PPP-Authentication PAP 2
|
66
|
+
VALUE Gandalf-PPP-Authentication PAP-Sending-on-Incoming-Calls 3
|
67
|
+
|
68
|
+
VALUE Gandalf-PPP-NCP-Type BCP 2
|
69
|
+
VALUE Gandalf-PPP-NCP-Type IPCP 3
|
70
|
+
|
71
|
+
VALUE Gandalf-Fwd-Multicast-In Disabled 1
|
72
|
+
VALUE Gandalf-Fwd-Multicast-In Enabled 2
|
73
|
+
|
74
|
+
VALUE Gandalf-Fwd-Broadcast-In Disabled 1
|
75
|
+
VALUE Gandalf-Fwd-Broadcast-In Enabled 2
|
76
|
+
|
77
|
+
VALUE Gandalf-Fwd-Unicast-In Disabled 1
|
78
|
+
VALUE Gandalf-Fwd-Unicast-In Enabled 2
|
79
|
+
|
80
|
+
VALUE Gandalf-Fwd-Multicast-Out Disabled 1
|
81
|
+
VALUE Gandalf-Fwd-Multicast-Out Enabled 2
|
82
|
+
|
83
|
+
VALUE Gandalf-Fwd-Broadcast-Out Disabled 1
|
84
|
+
VALUE Gandalf-Fwd-Broadcast-Out Enabled 2
|
85
|
+
|
86
|
+
VALUE Gandalf-Fwd-Unicast-Out Disabled 1
|
87
|
+
VALUE Gandalf-Fwd-Unicast-Out Enabled 2
|
88
|
+
|
89
|
+
VALUE Gandalf-IPX-Spoofing-State Forward 1
|
90
|
+
VALUE Gandalf-IPX-Spoofing-State Spoof 2
|
91
|
+
VALUE Gandalf-IPX-Spoofing-State Filter-all-outgoing-RIP-SAP 3
|
92
|
+
|
93
|
+
VALUE Gandalf-IPX-Watchdog-Spoof Disabled 1
|
94
|
+
VALUE Gandalf-IPX-Watchdog-Spoof Enabled 2
|
95
|
+
|
96
|
+
VALUE Gandalf-Modem-Mode Disabled 1
|
97
|
+
VALUE Gandalf-Modem-Mode Enabled 2
|
98
|
+
|
99
|
+
VALUE Gandalf-Modem-Required-1 Disabled 1
|
100
|
+
VALUE Gandalf-Modem-Required-1 Enabled 2
|
101
|
+
|
102
|
+
VALUE Gandalf-Modem-Required-2 Disabled 1
|
103
|
+
VALUE Gandalf-Modem-Required-2 Enabled 2
|
104
|
+
|
105
|
+
END-VENDOR Gandalf
|
File without changes
|
data/version.txt
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.4
|
metadata
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dguerri-radiustar
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 23
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- PJ Davis
|
14
|
+
- Davide Guerri
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2010-12-04 00:00:00 +01:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: bones
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 21
|
31
|
+
segments:
|
32
|
+
- 3
|
33
|
+
- 4
|
34
|
+
- 1
|
35
|
+
version: 3.4.1
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id001
|
38
|
+
description: Ruby Radius Library
|
39
|
+
email: davide.guerri@gmail.com
|
40
|
+
executables: []
|
41
|
+
|
42
|
+
extensions: []
|
43
|
+
|
44
|
+
extra_rdoc_files:
|
45
|
+
- History.txt
|
46
|
+
- README.rdoc
|
47
|
+
- templates/default.txt
|
48
|
+
- version.txt
|
49
|
+
files:
|
50
|
+
- .gitignore
|
51
|
+
- History.txt
|
52
|
+
- README.rdoc
|
53
|
+
- Rakefile
|
54
|
+
- lib/radiustar.rb
|
55
|
+
- lib/radiustar/dictionary.rb
|
56
|
+
- lib/radiustar/dictionary/attributes.rb
|
57
|
+
- lib/radiustar/dictionary/values.rb
|
58
|
+
- lib/radiustar/packet.rb
|
59
|
+
- lib/radiustar/radiustar.rb
|
60
|
+
- lib/radiustar/request.rb
|
61
|
+
- lib/radiustar/vendor.rb
|
62
|
+
- radiustar.gemspec
|
63
|
+
- spec/radiustar_spec.rb
|
64
|
+
- spec/spec_helper.rb
|
65
|
+
- templates/default.txt
|
66
|
+
- templates/dictionary.digium
|
67
|
+
- templates/gandalf.dictionary
|
68
|
+
- test/test_radiustar.rb
|
69
|
+
- version.txt
|
70
|
+
has_rdoc: true
|
71
|
+
homepage: http://github.com/dguerri/radiustar
|
72
|
+
licenses: []
|
73
|
+
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options:
|
76
|
+
- --main
|
77
|
+
- README.rdoc
|
78
|
+
require_paths:
|
79
|
+
- lib
|
80
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
hash: 3
|
86
|
+
segments:
|
87
|
+
- 0
|
88
|
+
version: "0"
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
hash: 3
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
version: "0"
|
98
|
+
requirements: []
|
99
|
+
|
100
|
+
rubyforge_project: radiustar
|
101
|
+
rubygems_version: 1.3.7
|
102
|
+
signing_key:
|
103
|
+
specification_version: 3
|
104
|
+
summary: Ruby Radius Library
|
105
|
+
test_files:
|
106
|
+
- test/test_radiustar.rb
|