dguerri-radiustar 0.0.4

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