dguerri-radiustar 0.0.4

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 ADDED
@@ -0,0 +1,7 @@
1
+ .DS_Store
2
+ announcement.txt
3
+ coverage
4
+ doc
5
+ pkg
6
+ *.gem
7
+ **/.DS_Store
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,7 @@
1
+ module Radiustar
2
+
3
+ def inspect
4
+ "#<#{self.class}:#{self.name}>"
5
+ end
6
+
7
+ 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
@@ -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