Class: Radiustar::Packet

Inherits:
Object
  • Object
show all
Defined in:
lib/radiustar/packet.rb

Defined Under Namespace

Classes: Attribute

Constant Summary collapse

CODES =
{ 'Access-Request' => 1,        'Access-Accept' => 2,
'Access-Reject' => 3,         'Accounting-Request' => 4,
'Accounting-Response' => 5,   'Access-Challenge' => 11,
'Status-Server' => 12,        'Status-Client' => 13,
'Disconnect-Request' => 40,   'Disconnect-ACK' => 41,
'Disconnect-NAK' => 42,       'CoA-Request' => 43,
'CoA-ACK' => 44,              'CoA-NAK' => 45 }
HDRLEN =

size of packet header

1 + 1 + 2 + 16
P_HDR =

pack template for header

"CCna16a*"
P_ATTR =

pack template for attribute

"CCa*"

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dictionary, id, data = nil) ⇒ Packet

Returns a new instance of Packet.



26
27
28
29
30
31
32
33
34
35
# File 'lib/radiustar/packet.rb', line 26

def initialize(dictionary, id, data = nil)
  @dict = dictionary
  @id = id
  unset_all_attributes
  if data
    @packed = data
    self.unpack
  end
  self
end

Instance Attribute Details

#attributes ⇒ Object (readonly)

Returns the value of attribute attributes.



24
25
26
# File 'lib/radiustar/packet.rb', line 24

def attributes
  @attributes
end

#authenticator ⇒ Object (readonly)

Returns the value of attribute authenticator.



24
25
26
# File 'lib/radiustar/packet.rb', line 24

def authenticator
  @authenticator
end

#code ⇒ Object

Returns the value of attribute code.



23
24
25
# File 'lib/radiustar/packet.rb', line 23

def code
  @code
end

#id ⇒ Object (readonly)

Returns the value of attribute id.



24
25
26
# File 'lib/radiustar/packet.rb', line 24

def id
  @id
end

Instance Method Details

#attribute(name) ⇒ Object



116
117
118
119
120
# File 'lib/radiustar/packet.rb', line 116

def attribute(name)
  if @attributes[name]
    @attributes[name].value
  end
end

#decode_attribute(name, secret) ⇒ Object



130
131
132
133
134
# File 'lib/radiustar/packet.rb', line 130

def decode_attribute(name, secret)
  if @attributes[name]
    decode(@attributes[name].value.to_s, secret)
  end
end

#gen_acct_authenticator(secret) ⇒ Object



61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/radiustar/packet.rb', line 61

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 ⇒ Object

Generate an authenticator. It will try to use /dev/urandom if possible, or the system rand call if that's not available.



47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/radiustar/packet.rb', line 47

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) ⇒ Object



87
88
89
90
91
92
# File 'lib/radiustar/packet.rb', line 87

def gen_response_authenticator(secret, request_authenticator)
  @authenticator = request_authenticator
  @authenticator = Digest::MD5.digest(pack + secret)
  @packed = nil
  @authenticator
end

#increment_id ⇒ Object



37
38
39
# File 'lib/radiustar/packet.rb', line 37

def increment_id
  @id = (@id + 1) & 0xff
end

#pack ⇒ Object



136
137
138
139
140
141
142
# File 'lib/radiustar/packet.rb', line 136

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) ⇒ Object



108
109
110
# File 'lib/radiustar/packet.rb', line 108

def set_attribute(name, value)
  @attributes[name] = Attribute.new(@dict, name, value)
end

#set_encoded_attribute(name, value, secret) ⇒ Object



126
127
128
# File 'lib/radiustar/packet.rb', line 126

def set_encoded_attribute(name, value, secret)
  @attributes[name] = Attribute.new(@dict, name, encode(value, secret))
end

#to_a ⇒ Object



41
42
43
# File 'lib/radiustar/packet.rb', line 41

def to_a
  @attributes.to_a
end

#unset_all_attributes ⇒ Object



122
123
124
# File 'lib/radiustar/packet.rb', line 122

def unset_all_attributes
  @attributes = {}
end

#unset_attribute(name) ⇒ Object



112
113
114
# File 'lib/radiustar/packet.rb', line 112

def unset_attribute(name)
  @attributes.delete(name)
end

#validate_acct_authenticator(secret) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/radiustar/packet.rb', line 94

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