class RadiusRB::Packet
Constants
- CODES
- HDRLEN
- P_ATTR
- P_HDR
Attributes
attributes[R]
authenticator[R]
code[RW]
id[R]
Public Class Methods
new(dictionary, id, data = nil)
click to toggle source
# File lib/radiusrb/packet.rb, line 38 def initialize(dictionary, id, data = nil) @dict = dictionary @id = id unset_all_attributes if data @packed = data self.unpack end self end
Public Instance Methods
attribute(name)
click to toggle source
# File lib/radiusrb/packet.rb, line 128 def attribute(name) if @attributes[name] @attributes[name].value end end
decode_attribute(name, secret)
click to toggle source
# File lib/radiusrb/packet.rb, line 142 def decode_attribute(name, secret) if @attributes[name] decode(@attributes[name].value.to_s, secret) end end
gen_acct_authenticator(secret)
click to toggle source
# File lib/radiusrb/packet.rb, line 73 def gen_acct_authenticator(secret) # From RFC2866 # Request Authenticator # # In Accounting-Request Packets, the Authenticator value is a 16 # octet MD5 [5] checksum, called the Request Authenticator. # # The NAS and RADIUS accounting server share a secret. The Request # Authenticator field in Accounting-Request packets contains a one- # way MD5 hash calculated over a stream of octets consisting of the # Code + Identifier + Length + 16 zero octets + request attributes + # shared secret (where + indicates concatenation). The 16 octet MD5 # hash value is stored in the Authenticator field of the # Accounting-Request packet. # # Note that the Request Authenticator of an Accounting-Request can # not be done the same way as the Request Authenticator of a RADIUS # Access-Request, because there is no User-Password attribute in an # Accounting-Request. # @authenticator = "\000"*16 @authenticator = Digest::MD5.digest(pack + secret) @packed = nil @authenticator end
gen_auth_authenticator()
click to toggle source
Generate an authenticator. It will try to use /dev/urandom if possible, or the system rand call if that’s not available.
# File lib/radiusrb/packet.rb, line 59 def gen_auth_authenticator if (File.exist?("/dev/urandom")) File.open("/dev/urandom") do |urandom| @authenticator = urandom.read(16) end else @authenticator = [] 8.times do @authenticator << rand(65536) end @authenticator = @authenticator.pack("n8") end end
gen_response_authenticator(secret, request_authenticator)
click to toggle source
# File lib/radiusrb/packet.rb, line 99 def gen_response_authenticator(secret, request_authenticator) @authenticator = request_authenticator @authenticator = Digest::MD5.digest(pack + secret) @packed = nil @authenticator end
increment_id()
click to toggle source
# File lib/radiusrb/packet.rb, line 49 def increment_id @id = (@id + 1) & 0xff end
pack()
click to toggle source
# File lib/radiusrb/packet.rb, line 148 def pack attstr = "" @attributes.values.each do |attribute| attstr += attribute.pack end @packed = [CODES[@code], @id, attstr.length + HDRLEN, @authenticator, attstr].pack(P_HDR) end
set_attribute(name, value)
click to toggle source
# File lib/radiusrb/packet.rb, line 120 def set_attribute(name, value) @attributes[name] = Attribute.new(@dict, name, value) end
set_encoded_attribute(name, value, secret)
click to toggle source
# File lib/radiusrb/packet.rb, line 138 def set_encoded_attribute(name, value, secret) @attributes[name] = Attribute.new(@dict, name, encode(value, secret)) end
to_a()
click to toggle source
# File lib/radiusrb/packet.rb, line 53 def to_a @attributes.to_a end
unset_all_attributes()
click to toggle source
# File lib/radiusrb/packet.rb, line 134 def unset_all_attributes @attributes = {} end
unset_attribute(name)
click to toggle source
# File lib/radiusrb/packet.rb, line 124 def unset_attribute(name) @attributes.delete(name) end
validate_acct_authenticator(secret)
click to toggle source
# File lib/radiusrb/packet.rb, line 106 def validate_acct_authenticator(secret) if @authenticator original_authenticator = @authenticator if gen_acct_authenticator(secret) == original_authenticator true else @authenticator = original_authenticator false end else false end end
Protected Instance Methods
decode(value, secret)
click to toggle source
# File lib/radiusrb/packet.rb, line 211 def decode(value, secret) decoded_value = "" lastround = @authenticator 0.step(value.length-1, 16) do |i| decoded_value = xor_str(value[i, 16], Digest::MD5.digest(secret + lastround)) lastround = value[i, 16] end decoded_value.gsub!(/\000+/, "") if decoded_value decoded_value[value.length, -1] = "" unless (decoded_value.length <= value.length) return decoded_value end
encode(value, secret)
click to toggle source
# File lib/radiusrb/packet.rb, line 199 def encode(value, secret) lastround = @authenticator encoded_value = "" # pad to 16n bytes value += "\000" * (15-(15 + value.length) % 16) 0.step(value.length-1, 16) do |i| lastround = xor_str(value[i, 16], Digest::MD5.digest(secret + lastround) ) encoded_value += lastround end encoded_value end
unpack()
click to toggle source
# File lib/radiusrb/packet.rb, line 158 def unpack @code, @id, len, @authenticator, attribute_data = @packed.unpack(P_HDR) @code = CODES.key(@code) unset_all_attributes while attribute_data.length > 0 do length = attribute_data.unpack("xC").first.to_i attribute_type, attribute_value = attribute_data.unpack("Cxa#{length-2}") attribute_type = attribute_type.to_i attribute = @dict.find_attribute_by_id(attribute_type) attribute_value = case attribute.type when 'string' attribute_value when 'integer' attribute.has_values? ? attribute.find_values_by_id(attribute_value.unpack("N")[0]).name : attribute_value.unpack("N")[0] when 'ipaddr' attribute_value.unpack("N")[0].to_ip.to_s when 'time' attribute_value.unpack("N")[0] when 'date' attribute_value.unpack("N")[0] end set_attribute(attribute.name, attribute_value) if attribute attribute_data[0, length] = "" end end
xor_str(str1, str2)
click to toggle source
# File lib/radiusrb/packet.rb, line 188 def xor_str(str1, str2) i = 0 newstr = "" str1.each_byte do |c1| c2 = str2.bytes.to_a[i] newstr = newstr << (c1 ^ c2) i = i+1 end newstr end