Data-Radius
view release on metacpan or search on metacpan
lib/Data/Radius/Packet.pm view on Meta::CPAN
my $msg_auth;
my $pos = 0;
my $len = length($attributes);
while ($pos < $len) {
my ($attr_val, $vendor_id, $vendor, $vsa_len, $attr, $tag) = ();
# FIXME not supported
my $wimax_cont;
my ($attr_id, $attr_len) = unpack('C C', substr($attributes, $pos, 2));
if ($attr_id == ATTR_VENDOR) {
my $vsa_header_len = 6;
($vendor_id, $attr_id, $vsa_len) = unpack('N C C', substr($attributes, $pos + 2, $vsa_header_len) );
if ($vendor_id == WIMAX_VENDOR) {
# +1 continuation byte
$vsa_header_len = 7;
$wimax_cont = unpack('C', substr($attributes, $pos + 8, 1));
warn 'continuation field is not supported' if ($wimax_cont);
printf "WIMAX cont: %d\n", $wimax_cont;
}
if ($dict) {
$vendor = $dict->vendor_name($vendor_id) // $vendor_id;
$attr = $dict->attribute_name($vendor, $attr_id);
}
$attr_val = substr($attributes, $pos + 2 + $vsa_header_len, $attr_len - 2 - $vsa_header_len);
}
else {
if ($dict) {
$attr = $dict->attribute_name(undef, $attr_id);
}
$attr_val = substr($attributes, $pos + 2, $attr_len - 2);
}
if ($attr_id == ATTR_MSG_AUTH && ! $vendor) {
die "Invalid Message-Authenticator len" if ($attr_len != ATTR_MSG_AUTH_LEN);
$msg_auth = $attr_val;
# zero it to verify later
$attr_val = "\x0" x (ATTR_MSG_AUTH_LEN - 2);
substr($attributes, $pos + 2, $attr_len - 2, $attr_val);
}
$pos += $attr_len;
if (! $attr) {
# raw data for unknown attribute
push @attr, {
Name => $attr_id,
Value => $attr_val,
Type => undef,
Vendor => $vendor,
Tag => undef,
};
next;
}
(my $decoded, $tag) = decode($attr, $attr_val, $self->dict);
if (is_enum_type($attr->{type})) {
# try to convert value to constants
$decoded = $dict->constant($attr->{name}, $decoded) // $decoded;
}
# password is expected only in auth request
if ($type == ACCESS_REQUEST && $attr->{id} == ATTR_PASSWORD && ! $attr->{vendor}) {
$decoded = decrypt_pwd($decoded, $self->secret, $auth);
}
push @attr, {
Name => $attr->{name},
Value => $decoded,
Type => $attr->{type},
Vendor => $vendor,
Tag => $tag,
};
}
if($msg_auth) {
# we already replaced msg auth value to \x0...
my $auth_used;
if ($self->is_reply($type)) {
$auth_used = $orig_auth;
}
elsif ($type == ACCESS_REQUEST) {
$auth_used = $auth;
}
else {
# other type of request should use 00x16
# Message-Authenticator should not be present in ACCOUNTING_REQUEST
$auth_used = "\x00" x 16;
}
my $data = join('',
pack('C C n', $type, $req_id, $length),
$auth_used,
$attributes,
);
my $hmac = Digest::HMAC_MD5->new($self->secret);
$hmac->add( $data );
my $exp_msg_auth = $hmac->digest;
if ($msg_auth ne $exp_msg_auth) {
warn "Message-Authenticator not verified";
return undef;
}
}
return ($type, $req_id, $auth, \@attr);
}
# extract request id from packet header without parsing attributes
# should be used to find original authenticator value for received reply packet to pass it to decode_request()
sub request_id {
my ($self, $packet) = @_;
my $req_id = unpack('C', substr($packet, 1, 1));
return $req_id;
}
sub is_reply {
my ($class, $type) = @_;
return $IS_REPLY{ $type } // 0;
}
sub is_request {
my ($class, $type) = @_;
return $IS_REQUEST{ $type } // 0;
}
1;
__END__
( run in 0.783 second using v1.01-cache-2.11-cpan-39bf76dae61 )