Imported Upstream version 2.103+dfsg
This commit is contained in:
7
t/00-load.t
Normal file
7
t/00-load.t
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
# $Id: 00-load.t 9 2003-10-16 20:10:25Z lem $
|
||||
|
||||
use Test::More tests => 2;
|
||||
use_ok("Net::Radius::Dictionary");
|
||||
use_ok("Net::Radius::Packet");
|
||||
|
||||
10
t/00-pod.t
Normal file
10
t/00-pod.t
Normal file
@@ -0,0 +1,10 @@
|
||||
|
||||
# 00-pod.t: Verify all the POD documentation
|
||||
|
||||
use strict;
|
||||
use Test::More;
|
||||
|
||||
eval "use Test::Pod 1.00";
|
||||
plan skip_all => 'Test::Pod is not available' if $@;
|
||||
all_pod_files_ok();
|
||||
|
||||
111
t/attrdict.t
Normal file
111
t/attrdict.t
Normal file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Test the parsing of individual attributes
|
||||
|
||||
# $Id: attrdict.t 27 2006-08-09 16:00:01Z lem $
|
||||
|
||||
use IO::File;
|
||||
use Test::More;
|
||||
use Data::Dumper;
|
||||
use Net::Radius::Dictionary;
|
||||
|
||||
my $dictfile = "dict$$.tmp";
|
||||
|
||||
END
|
||||
{
|
||||
unlink $dictfile;
|
||||
};
|
||||
|
||||
my @dicts = ();
|
||||
my @refs = ();
|
||||
|
||||
{
|
||||
local $/ = "EOD\n";
|
||||
@dicts = map { (s/EOD\n$//, $_)[1] } <DATA>;
|
||||
};
|
||||
|
||||
$refs[0] = bless {
|
||||
'vsattr' => {},
|
||||
'rattr' => {},
|
||||
'vendors' => {},
|
||||
'rvsaval' => {},
|
||||
'val' => {},
|
||||
'rvsattr' => {},
|
||||
'attr' => {},
|
||||
'rval' => {},
|
||||
'vsaval' => {}
|
||||
}, 'Net::Radius::Dictionary';
|
||||
|
||||
$refs[1] = bless {
|
||||
'vsattr' => {
|
||||
'9' => {
|
||||
'Cisco-AVPair' => ['1', 'string' ],
|
||||
'cisco-thing' => ['2', 'string' ]
|
||||
}
|
||||
},
|
||||
'rattr' => {
|
||||
'1' => ['User-Name', 'string'],
|
||||
'23' => ['Framed-IPX-Network', 'ipaddr'],
|
||||
'10' => ['Framed-Routing', 'integer']
|
||||
},
|
||||
'vendors' => {
|
||||
'Cisco' => '9'
|
||||
},
|
||||
'rvsaval' => {},
|
||||
'val' => {},
|
||||
'rvsattr' => {
|
||||
'9' => {
|
||||
'1' => ['Cisco-AVPair', 'string'],
|
||||
'2' => ['cisco-thing', 'string']
|
||||
}
|
||||
},
|
||||
'attr' => {
|
||||
'Framed-IPX-Network' => ['23', 'ipaddr'],
|
||||
'Framed-Routing' => ['10', 'integer'],
|
||||
'User-Name' => ['1', 'string']
|
||||
},
|
||||
'rval' => {},
|
||||
'vsaval' => {}
|
||||
}, 'Net::Radius::Dictionary';
|
||||
|
||||
sub _write
|
||||
{
|
||||
my $dict = shift;
|
||||
my $fh = new IO::File;
|
||||
$fh->open($dictfile, "w") or diag "Failed to write dict $dictfile: $!";
|
||||
print $fh $dict;
|
||||
$fh->close;
|
||||
}
|
||||
|
||||
plan tests => 20 * scalar @dicts;
|
||||
|
||||
for my $i (0 .. $#dicts)
|
||||
{
|
||||
|
||||
_write $dicts[$i];
|
||||
|
||||
my $d;
|
||||
|
||||
eval { $d = new Net::Radius::Dictionary $dictfile; };
|
||||
|
||||
isa_ok($d, 'Net::Radius::Dictionary');
|
||||
ok(!$@, "No errors during parse");
|
||||
diag $@ if $@;
|
||||
|
||||
for my $k (keys %{$refs[$i]})
|
||||
{
|
||||
ok(exists $d->{$k}, "Element $k exists in the object");
|
||||
is_deeply($d->{$k}, $refs[$i]->{$k}, "Same contents in element $k");
|
||||
}
|
||||
}
|
||||
|
||||
__END__
|
||||
# Empty dictionary
|
||||
EOD
|
||||
# Sample dictionary
|
||||
ATTRIBUTE User-Name 1 string
|
||||
ATTRIBUTE Framed-Routing 10 integer
|
||||
ATTRIBUTE Framed-IPX-Network 23 ipaddr
|
||||
VENDOR Cisco 9
|
||||
ATTRIBUTE Cisco-AVPair 1 string Cisco
|
||||
VENDORATTR 9 cisco-thing 2 string
|
||||
72
t/attrover.t
Normal file
72
t/attrover.t
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Test the attribute overriding code as well as access to the
|
||||
# attribute stack
|
||||
|
||||
# $Id: attrover.t 56 2007-01-08 20:52:18Z lem $
|
||||
|
||||
|
||||
no utf8;
|
||||
use IO::File;
|
||||
use Test::More 'no_plan';
|
||||
use Net::Radius::Packet;
|
||||
use Net::Radius::Dictionary;
|
||||
|
||||
# Init the dictionary for our test run...
|
||||
BEGIN {
|
||||
my $fh = new IO::File "dict.$$", ">";
|
||||
print $fh <<EOF;
|
||||
ATTRIBUTE User-Name 1 string
|
||||
ATTRIBUTE Reply-Message 18 string
|
||||
EOF
|
||||
|
||||
close $fh;
|
||||
};
|
||||
|
||||
END { unlink 'dict.' . $$; }
|
||||
|
||||
my $d = new Net::Radius::Dictionary "dict.$$";
|
||||
isa_ok($d, 'Net::Radius::Dictionary');
|
||||
|
||||
# Build a request and test it is ok
|
||||
my $p = new Net::Radius::Packet $d;
|
||||
isa_ok($p, 'Net::Radius::Packet');
|
||||
$p->set_identifier(42);
|
||||
$p->set_authenticator("\x66" x 16);
|
||||
$p->set_code("Access-Reject");
|
||||
$p->set_attr("Reply-Message" => 'line-1');
|
||||
$p->set_attr("Reply-Message" => 'line-2', 1);
|
||||
|
||||
# There should be one attribute, a single Reply-Message
|
||||
is($p->attr_slots, 1, "Correct number of attribute slots");
|
||||
|
||||
is($p->attr_slot_name(0), 'Reply-Message', "Correct name for slot 0");
|
||||
is($p->attr_slot_val(0), 'line-2', "Correct value for slot 0");
|
||||
|
||||
is($p->attr_slot_name(1), undef, "Undef slot 1 name");
|
||||
is($p->attr_slot_val(1), undef, "Undef slot 1 value");
|
||||
|
||||
# Now there should be 3 attributes
|
||||
|
||||
$p = new Net::Radius::Packet $d;
|
||||
isa_ok($p, 'Net::Radius::Packet');
|
||||
$p->set_identifier(42);
|
||||
$p->set_authenticator("\x66" x 16);
|
||||
$p->set_code("Access-Reject");
|
||||
$p->set_attr("Reply-Message" => 'line-1');
|
||||
$p->set_attr("Reply-Message" => 'line-2');
|
||||
$p->set_attr("Reply-Message" => 'line-3', 1);
|
||||
|
||||
is($p->attr_slots, 3, "Correct number of attribute slots");
|
||||
|
||||
is($p->attr_slot_name(0), 'Reply-Message', "Correct name for slot 0");
|
||||
is($p->attr_slot_val(0), 'line-1', "Correct value for slot 0");
|
||||
|
||||
is($p->attr_slot_name(1), 'Reply-Message', "Correct name for slot 1");
|
||||
is($p->attr_slot_val(1), 'line-2', "Correct value for slot 1");
|
||||
|
||||
is($p->attr_slot_name(2), 'Reply-Message', "Correct name for slot 2");
|
||||
is($p->attr_slot_val(2), 'line-3', "Correct value for slot 2");
|
||||
|
||||
is($p->attr_slot_name(3), undef, "Undef slot 3 name");
|
||||
is($p->attr_slot_val(3), undef, "Undef slot 3 value");
|
||||
163
t/attrslot.t
Normal file
163
t/attrslot.t
Normal file
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Test the attribute slot management
|
||||
|
||||
# $Id: attrslot.t 77 2007-01-30 15:15:48Z lem $
|
||||
|
||||
|
||||
no utf8;
|
||||
use IO::File;
|
||||
use Test::More tests => 61;
|
||||
use Net::Radius::Packet;
|
||||
use Net::Radius::Dictionary;
|
||||
|
||||
# Init the dictionary for our test run...
|
||||
BEGIN {
|
||||
my $fh = new IO::File "dict.$$", ">";
|
||||
print $fh <<EOF;
|
||||
ATTRIBUTE User-Name 1 string
|
||||
ATTRIBUTE NAS-IP-Address 4 ipaddr
|
||||
ATTRIBUTE NAS-Port 5 integer
|
||||
ATTRIBUTE Reply-Message 18 string
|
||||
EOF
|
||||
|
||||
close $fh;
|
||||
};
|
||||
|
||||
END { unlink 'dict.' . $$; }
|
||||
|
||||
my $d = new Net::Radius::Dictionary "dict.$$";
|
||||
isa_ok($d, 'Net::Radius::Dictionary');
|
||||
|
||||
# Build a request and test it is ok
|
||||
my $p = new Net::Radius::Packet $d;
|
||||
isa_ok($p, 'Net::Radius::Packet');
|
||||
$p->set_identifier(42);
|
||||
$p->set_authenticator("\x66" x 16);
|
||||
$p->set_code("Access-Reject");
|
||||
|
||||
is($p->attr_slots, 0, "Correct number of attribute slots in empty packet");
|
||||
is($p->attr_slot_name(0), undef, "Undefined slot 0 name (e)");
|
||||
is($p->attr_slot_val(0), undef, "Undefined slot 0 value (e)");
|
||||
|
||||
$p->set_attr("Reply-Message" => 'line-1');
|
||||
$p->set_attr("Reply-Message" => 'line-2');
|
||||
|
||||
my $q = new Net::Radius::Packet $d, $p->pack;
|
||||
isa_ok($q, 'Net::Radius::Packet');
|
||||
|
||||
is($p->attr_slots, 2, "Correct number of attribute slots");
|
||||
|
||||
is($p->attr_slot_name(0), 'Reply-Message', "Correct name for slot 0");
|
||||
is($p->attr_slot_val(0), 'line-1', "Correct value for slot 0");
|
||||
|
||||
is($p->attr_slot_name(1), 'Reply-Message', "Correct name for slot 1");
|
||||
is($p->attr_slot_val(1), 'line-2', "Correct value for slot 1");
|
||||
|
||||
is($p->attr_slot_name(2), undef, "Undefined slot 2 name");
|
||||
is($p->attr_slot_val(2), undef, "Undefined slot 2 value");
|
||||
|
||||
$q = new Net::Radius::Packet $d, $p->pack;
|
||||
isa_ok($q, 'Net::Radius::Packet');
|
||||
|
||||
is($q->attr_slot_name(0), 'Reply-Message', "Correct name for slot 0 (q)");
|
||||
is($q->attr_slot_val(0), 'line-1', "Correct value for slot 0 (q)");
|
||||
|
||||
is($q->attr_slot_name(1), 'Reply-Message', "Correct name for slot 1 (q)");
|
||||
is($q->attr_slot_val(1), 'line-2', "Correct value for slot 1 (q)");
|
||||
|
||||
is($q->attr_slot_name(2), undef, "Undefined slot 2 name (q)");
|
||||
is($q->attr_slot_val(2), undef, "Undefined slot 2 value (q)");
|
||||
|
||||
# Add a third attribute to the packet and verify what happens
|
||||
|
||||
$p->set_attr("NAS-Port" => "42");
|
||||
is($p->attr_slots, 3, "Correct number of attribute slots");
|
||||
|
||||
is($p->attr_slot_name(2), 'NAS-Port', "Correct name for slot 2");
|
||||
is($p->attr_slot_val(2), '42', "Correct value for slot 2");
|
||||
|
||||
is($p->attr_slot_name(3), undef, "Undefined slot 3 name");
|
||||
is($p->attr_slot_val(3), undef, "Undefined slot 3 value");
|
||||
|
||||
# Remove attr slot 1 and check what happened
|
||||
|
||||
$p->unset_attr_slot(1);
|
||||
|
||||
is($p->attr_slots, 2, "Correct number of attribute slots");
|
||||
|
||||
is($p->attr_slot_name(0), 'Reply-Message', "Correct name for slot 0 (q)");
|
||||
is($p->attr_slot_val(0), 'line-1', "Correct value for slot 0 (q)");
|
||||
|
||||
is($p->attr_slot_name(1), 'NAS-Port', "Correct name for slot 1");
|
||||
is($p->attr_slot_val(1), '42', "Correct value for slot 1");
|
||||
|
||||
is($p->attr_slot_name(2), undef, "Undefined slot 2 name");
|
||||
is($p->attr_slot_val(2), undef, "Undefined slot 2 value");
|
||||
|
||||
# Remove an already unexistant slot
|
||||
|
||||
$p->unset_attr_slot(2);
|
||||
|
||||
is($p->attr_slots, 2, "Correct number of attribute slots");
|
||||
|
||||
is($p->attr_slot_name(0), 'Reply-Message', "Correct name for slot 0 (q)");
|
||||
is($p->attr_slot_val(0), 'line-1', "Correct value for slot 0 (q)");
|
||||
|
||||
is($p->attr_slot_name(1), 'NAS-Port', "Correct name for slot 1");
|
||||
is($p->attr_slot_val(1), '42', "Correct value for slot 1");
|
||||
|
||||
is($p->attr_slot_name(2), undef, "Undefined slot 2 name");
|
||||
is($p->attr_slot_val(2), undef, "Undefined slot 2 value");
|
||||
|
||||
# Remove slot 1
|
||||
|
||||
$p->unset_attr_slot(1);
|
||||
|
||||
is($p->attr_slots, 1, "Correct number of attribute slots");
|
||||
|
||||
is($p->attr_slot_name(0), 'Reply-Message', "Correct name for slot 0 (q)");
|
||||
is($p->attr_slot_val(0), 'line-1', "Correct value for slot 0 (q)");
|
||||
|
||||
is($p->attr_slot_name(1), undef, "Undefined slot 1 name");
|
||||
is($p->attr_slot_val(1), undef, "Undefined slot 1 value");
|
||||
|
||||
# Remove last slot
|
||||
|
||||
$p->unset_attr_slot(0);
|
||||
|
||||
is($p->attr_slots, 0, "Correct number of attribute slots");
|
||||
|
||||
is($p->attr_slot_name(0), undef, "Undefined slot 0 name");
|
||||
is($p->attr_slot_val(0), undef, "Undefined slot 0 value");
|
||||
|
||||
# Remove last slot (again)
|
||||
|
||||
$p->unset_attr_slot(0);
|
||||
|
||||
is($p->attr_slots, 0, "Correct number of attribute slots");
|
||||
|
||||
is($p->attr_slot_name(0), undef, "Undefined slot 0 name");
|
||||
is($p->attr_slot_val(0), undef, "Undefined slot 0 value");
|
||||
|
||||
# Remove first slot
|
||||
|
||||
$q->set_attr("NAS-Port" => "42");
|
||||
is($q->attr_slots, 3, "Correct number of attribute slots");
|
||||
|
||||
is($q->attr_slot_name(2), 'NAS-Port', "Correct name for slot 2");
|
||||
is($q->attr_slot_val(2), '42', "Correct value for slot 2");
|
||||
|
||||
is($q->attr_slot_name(3), undef, "Undefined slot 3 name");
|
||||
is($q->attr_slot_val(3), undef, "Undefined slot 3 value");
|
||||
|
||||
$q->unset_attr_slot(0);
|
||||
|
||||
is($q->attr_slot_name(0), 'Reply-Message', "Correct name for slot 0 (q)");
|
||||
is($q->attr_slot_val(0), 'line-2', "Correct value for slot 0 (q)");
|
||||
|
||||
is($q->attr_slot_name(1), 'NAS-Port', "Correct name for slot 1 (q)");
|
||||
is($q->attr_slot_val(1), '42', "Correct value for slot 1 (q)");
|
||||
|
||||
is($q->attr_slot_name(2), undef, "Undefined slot 2 name (q)");
|
||||
is($q->attr_slot_val(2), undef, "Undefined slot 2 value (q)");
|
||||
55
t/attrunset.t
Normal file
55
t/attrunset.t
Normal file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Test attribute unsetting attributes with ASCII and non-ASCII (8-bit) values
|
||||
|
||||
# $Id: attrunset.t 81 2007-04-26 20:25:21Z lem $
|
||||
|
||||
|
||||
use IO::File;
|
||||
use Test::More qw/no_plan/;
|
||||
use Net::Radius::Packet;
|
||||
use Net::Radius::Dictionary;
|
||||
|
||||
# Init the dictionary for our test run...
|
||||
BEGIN {
|
||||
my $fh = new IO::File "dict.$$", ">";
|
||||
print $fh <<EOF;
|
||||
ATTRIBUTE User-Name 1 string
|
||||
ATTRIBUTE NAS-IP-Address 4 ipaddr
|
||||
ATTRIBUTE NAS-Port 5 integer
|
||||
ATTRIBUTE Reply-Message 18 string
|
||||
EOF
|
||||
|
||||
close $fh;
|
||||
};
|
||||
|
||||
END { unlink 'dict.' . $$; }
|
||||
|
||||
my $d = new Net::Radius::Dictionary "dict.$$";
|
||||
isa_ok($d, 'Net::Radius::Dictionary');
|
||||
|
||||
# Build a request and test it is ok
|
||||
my $p = new Net::Radius::Packet $d;
|
||||
isa_ok($p, 'Net::Radius::Packet');
|
||||
$p->set_identifier(42);
|
||||
$p->set_authenticator("\x66" x 16);
|
||||
$p->set_code("Access-Accept");
|
||||
$p->set_attr('Reply-Message' => 'Hello World 1');
|
||||
|
||||
is($p->attr('Reply-Message'), 'Hello World 1', 'ASCII Reply-Message loaded');
|
||||
|
||||
$p->unset_attr('Reply-Message', $p->attr('Reply-Message'));
|
||||
is($p->attr('Reply-Message'), undef, 'ASCII Reply-Message deleted');
|
||||
|
||||
$p->set_attr('Reply-Message' => '¡Hola Mundo!');
|
||||
is($p->attr('Reply-Message'), '¡Hola Mundo!', 'UTF-8 Reply-Message loaded');
|
||||
|
||||
$p->unset_attr('Reply-Message', $p->attr('Reply-Message'));
|
||||
is($p->attr('Reply-Message'), undef, 'UTF-8 Reply-Message loaded');
|
||||
|
||||
$p->set_attr('Reply-Message' => "\xde\xad\x00\xbe\xef");
|
||||
is($p->attr('Reply-Message'), "\xde\xad\x00\xbe\xef",
|
||||
'8-bit Reply-Message present');
|
||||
|
||||
$p->unset_attr('Reply-Message', $p->attr('Reply-Message'));
|
||||
is($p->attr('Reply-Message'), undef, '8-bit Reply-Message deleted');
|
||||
106
t/auth.t
Normal file
106
t/auth.t
Normal file
@@ -0,0 +1,106 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Test packet auth code
|
||||
|
||||
# $Id: auth.t 48 2006-11-14 20:05:11Z lem $
|
||||
|
||||
|
||||
no utf8;
|
||||
use IO::File;
|
||||
use Test::More 'no_plan';
|
||||
use Net::Radius::Packet;
|
||||
use Net::Radius::Dictionary;
|
||||
|
||||
# Init the dictionary for our test run...
|
||||
BEGIN {
|
||||
my $fh = new IO::File "dict.$$", ">";
|
||||
print $fh <<EOF;
|
||||
ATTRIBUTE User-Name 1 string
|
||||
ATTRIBUTE User-Password 2 string
|
||||
ATTRIBUTE NAS-IP-Address 4 ipaddr
|
||||
ATTRIBUTE NAS-Port 5 integer
|
||||
ATTRIBUTE Service-Type 6 integer
|
||||
ATTRIBUTE Framed-Protocol 7 integer
|
||||
ATTRIBUTE Called-Station-Id 30 string
|
||||
ATTRIBUTE Calling-Station-Id 31 string
|
||||
ATTRIBUTE Acct-Status-Type 40 integer
|
||||
ATTRIBUTE Acct-Session-Id 44 string
|
||||
ATTRIBUTE Acct-Authentic 45 integer
|
||||
ATTRIBUTE NAS-Port-Type 61 integer
|
||||
|
||||
VALUE Service-Type Framed-User 2
|
||||
VALUE Framed-Protocol PPP 1
|
||||
VALUE Acct-Authentic RADIUS 1
|
||||
VALUE NAS-Port-Type Virtual 5
|
||||
VALUE Acct-Status-Type Stop 2
|
||||
EOF
|
||||
|
||||
close $fh;
|
||||
};
|
||||
|
||||
END { unlink 'dict.' . $$; }
|
||||
|
||||
my $d = new Net::Radius::Dictionary "dict.$$";
|
||||
isa_ok($d, 'Net::Radius::Dictionary');
|
||||
|
||||
# Build a request and test it is ok
|
||||
my $p = new Net::Radius::Packet $d;
|
||||
isa_ok($p, 'Net::Radius::Packet');
|
||||
$p->set_identifier(42);
|
||||
$p->set_authenticator("\x66" x 16);
|
||||
$p->set_code("Access-Request");
|
||||
$p->set_attr("User-Name" => 'foo');
|
||||
$p->set_attr('NAS-Port-Type' => 'Virtual');
|
||||
$p->set_attr('NAS-IP-Address' => '10.10.10.10');
|
||||
$p->set_attr('Service-Type' => 'Framed-User');
|
||||
$p->set_attr('NAS-Port' => '42');
|
||||
$p->set_attr('Calling-Station-Id' => '5551212');
|
||||
$p->set_attr('Called-Station-Id' => '5551111');
|
||||
$p->set_attr('Framed-Protocol' => 'PPP');
|
||||
$p->set_password('bar', 'good-secret', 'User-Password');
|
||||
|
||||
my $q = new Net::Radius::Packet $d, $p->pack;
|
||||
isa_ok($q, 'Net::Radius::Packet');
|
||||
|
||||
my $pass = $q->password('good-secret');
|
||||
is($pass, 'bar', 'Correct password when good secret used');
|
||||
|
||||
$pass = $q->password('bad-secret');
|
||||
isnt($pass, 'bar', 'Bad password when bad secret used');
|
||||
|
||||
# Now test the response authentication scheme
|
||||
my $r = new Net::Radius::Packet $d;
|
||||
isa_ok($r, 'Net::Radius::Packet');
|
||||
$r->set_code('Access-Accept');
|
||||
$r->set_attr("User-Name" => 'foo');
|
||||
$r->set_identifier($p->identifier);
|
||||
$r->set_authenticator($p->authenticator);
|
||||
my $r_data = auth_resp($r->pack, 'good-secret');
|
||||
|
||||
ok(auth_req_verify($r_data, 'good-secret', $p->authenticator),
|
||||
"Response matches request with proper secret");
|
||||
ok(!auth_req_verify($r_data, 'bad-secret', $p->authenticator),
|
||||
"Response doesn't match request with bad secret");
|
||||
|
||||
# Now test the accounting authentication scheme
|
||||
$p = new Net::Radius::Packet $d;
|
||||
isa_ok($p, 'Net::Radius::Packet');
|
||||
$p->set_identifier(42);
|
||||
$p->set_authenticator("\x0" x 16);
|
||||
$p->set_code("Accounting-Request");
|
||||
$p->set_attr("User-Name" => 'foo');
|
||||
$p->set_attr('NAS-Port-Type' => 'Virtual');
|
||||
$p->set_attr('NAS-IP-Address' => '10.10.10.10');
|
||||
$p->set_attr('Service-Type' => 'Framed-User');
|
||||
$p->set_attr('NAS-Port' => '42');
|
||||
$p->set_attr('Calling-Station-Id' => '5551212');
|
||||
$p->set_attr('Called-Station-Id' => '5551111');
|
||||
$p->set_attr('Framed-Protocol' => 'PPP');
|
||||
|
||||
my $p_data = auth_resp($p->pack, 'good-secret');
|
||||
|
||||
ok(auth_acct_verify($p_data, 'good-secret'),
|
||||
"Validate acct req with good secret");
|
||||
|
||||
ok(!auth_acct_verify($p_data, 'bad-secret'),
|
||||
"Validate acct req with bad secret");
|
||||
1918
t/basedict.t
Normal file
1918
t/basedict.t
Normal file
File diff suppressed because it is too large
Load Diff
193
t/bundled.t
Normal file
193
t/bundled.t
Normal file
@@ -0,0 +1,193 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Test the parsing of the bundled dictionary files...
|
||||
|
||||
# $Id: bundled.t 98 2009-10-14 15:26:33Z lem $
|
||||
|
||||
use Test::Warn;
|
||||
use Test::More;
|
||||
use Net::Radius::Dictionary;
|
||||
|
||||
my %dict =
|
||||
(
|
||||
'dicts/dictionary.base'
|
||||
=> { attr => 39, vendor => undef, vsa => 0 },
|
||||
'dicts/dictionary.3com-o'
|
||||
=> { attr => 3, vendor => 'USR', vsa => 259 },
|
||||
'dicts/dictionary'
|
||||
=> { attr => 78, vendor => undef, vsa => 0 },
|
||||
'dicts/dictionary.3com'
|
||||
=> { attr => 0, vendor => '3com', vsa => 1 },
|
||||
'dicts/dictionary.3gpp2'
|
||||
=> { attr => 0, vendor => '3GPP2', vsa => 74 },
|
||||
'dicts/dictionary.3gpp'
|
||||
=> { attr => 0, vendor => '3GPP', vsa => 17 },
|
||||
'dicts/dictionary.acc'
|
||||
=> { attr => 0, vendor => 'Acc', vsa => 47 },
|
||||
'dicts/dictionary.alcatel'
|
||||
=> { attr => 0, vendor => 'Alcatel', vsa => 21 },
|
||||
'dicts/dictionary.alteon'
|
||||
=> { attr => 0, vendor => 'Alteon', vsa => 1 },
|
||||
'dicts/dictionary.altiga'
|
||||
=> { attr => 0, vendor => 'Altiga', vsa => 29},
|
||||
'dicts/dictionary.aptis'
|
||||
=> { attr => 0, vendor => 'Aptis', vsa => 36 },
|
||||
'dicts/dictionary.ascend'
|
||||
=> { attr => 137, vendor => 'Ascend',vsa => 249 },
|
||||
'dicts/dictionary.bay'
|
||||
=> { attr=>0,vendor=>'Bay-Networks',vsa => 65 },
|
||||
'dicts/dictionary.bintec'
|
||||
=> { attr => 0, vendor => 'BinTec', vsa => 17 },
|
||||
'dicts/dictionary.bristol'
|
||||
=> { attr => 0, vendor => 'Bristol', vsa => 5 },
|
||||
'dicts/dictionary.broadsoft'
|
||||
=> { attr => 0, vendor => 'BroadSoft', vsa => 132 },
|
||||
'dicts/dictionary.cablelabs'
|
||||
=> { attr => 0, vendor => 'CableLabs', vsa => 62 },
|
||||
'dicts/dictionary.cabletron'
|
||||
=> { attr => 0, vendor => 'Cabletron', vsa => 2 },
|
||||
'dicts/dictionary.cisco'
|
||||
=> { attr => 0, vendor => 'Cisco', vsa => 83 },
|
||||
'dicts/dictionary.cisco.bbsm'
|
||||
=> { attr => 0, vendor => 'Cisco-BBSM', vsa => 1 },
|
||||
'dicts/dictionary.cisco.vpn3000'
|
||||
=> { attr => 0, vendor => 'Cisco-VPN3000', vsa => 74 },
|
||||
'dicts/dictionary.cisco.vpn5000'
|
||||
=> { attr => 0, vendor => 'Cisco-VPN5000', vsa => 7 },
|
||||
'dicts/dictionary.colubris'
|
||||
=> { attr => 0, vendor => 'Colubris', vsa => 1 },
|
||||
'dicts/dictionary.columbia_university'
|
||||
=> { attr => 0, vendor => 'Columbia-University', vsa => 4 },
|
||||
'dicts/dictionary.compat'
|
||||
=> { attr => 21, vendor => undef, vsa => 0 },
|
||||
'dicts/dictionary.cosine'
|
||||
=> { attr => 0, vendor => 'Cosine', vsa => 8 },
|
||||
'dicts/dictionary.erx'
|
||||
=> { attr => 0, vendor => 'ERX', vsa => 51 },
|
||||
'dicts/dictionary.extreme'
|
||||
=> { attr => 0, vendor => 'Extreme', vsa => 4 },
|
||||
'dicts/dictionary.foundry'
|
||||
=> { attr => 0, vendor => 'Foundry', vsa => 4 },
|
||||
'dicts/dictionary.freeradius'
|
||||
=> { attr => 0, vendor => 'FreeRADIUS', vsa => 1 },
|
||||
'dicts/dictionary.gandalf'
|
||||
=> { attr => 0, vendor => 'Gandalf', vsa => 33 },
|
||||
'dicts/dictionary.garderos'
|
||||
=> { attr => 0, vendor => 'Garderos', vsa => 2 },
|
||||
'dicts/dictionary.gemtek'
|
||||
=> { attr => 0, vendor => 'Gemtek', vsa => 6 },
|
||||
'dicts/dictionary.huawei'
|
||||
=> { attr => 0, vendor => 'Huawei', vsa => 52 },
|
||||
'dicts/dictionary.itk'
|
||||
=> { attr => 0, vendor => 'ITK', vsa => 32 },
|
||||
'dicts/dictionary.juniper'
|
||||
=> { attr => 0, vendor => 'Juniper', vsa => 5 },
|
||||
'dicts/dictionary.karlnet'
|
||||
=> { attr => 0, vendor => 'KarlNet', vsa => 4 },
|
||||
'dicts/dictionary.livingston'
|
||||
=> { attr => 0, vendor => 'Livingston', vsa => 21 },
|
||||
'dicts/dictionary.localweb'
|
||||
=> { attr => 0, vendor => 'Local-Web', vsa => 15 },
|
||||
'dicts/dictionary.merit'
|
||||
=> { attr => 0, vendor => 'Merit', vsa => 3 },
|
||||
'dicts/dictionary.microsoft'
|
||||
=> { attr => 0, vendor => 'Microsoft', vsa => 33 },
|
||||
'dicts/dictionary.mikrotik'
|
||||
=> { attr => 0, vendor => 'Mikrotik', vsa => 3 },
|
||||
'dicts/dictionary.navini'
|
||||
=> { attr => 0, vendor => 'Navini', vsa => 1 },
|
||||
'dicts/dictionary.netscreen'
|
||||
=> { attr => 0, vendor => 'Netscreen', vsa => 7 },
|
||||
'dicts/dictionary.nokia'
|
||||
=> { attr => 5, vendor => undef, vsa => 0 },
|
||||
'dicts/dictionary.nomadix'
|
||||
=> { attr => 0, vendor => 'Nomadix', vsa => 13 },
|
||||
'dicts/dictionary.propel'
|
||||
=> { attr => 0, vendor => 'Propel', vsa => 5 },
|
||||
'dicts/dictionary.quintum'
|
||||
=> { attr => 0, vendor => 'Quintum', vsa => 23 },
|
||||
'dicts/dictionary.redback'
|
||||
=> { attr => 0, vendor => 'Redback', vsa => 170 },
|
||||
'dicts/dictionary.redcreek'
|
||||
=> { attr => 0, vendor => 'RedCreek', vsa => 9 },
|
||||
'dicts/dictionary.shasta'
|
||||
=> { attr => 0, vendor => 'Shasta', vsa => 3 },
|
||||
'dicts/dictionary.shiva'
|
||||
=> { attr => 0, vendor => 'Shiva', vsa => 16 },
|
||||
'dicts/dictionary.sonicwall'
|
||||
=> { attr => 0, vendor => 'SonicWall', vsa => 4 },
|
||||
'dicts/dictionary.springtide'
|
||||
=> { attr => 0, vendor => 'SpringTide', vsa => 8 },
|
||||
'dicts/dictionary.t_systems_nova'
|
||||
=> { attr => 0, vendor => 'T-Systems-Nova', vsa => 15 },
|
||||
'dicts/dictionary.telebit'
|
||||
=> { attr => 0, vendor => 'Telebit', vsa => 4 },
|
||||
'dicts/dictionary.trapeze'
|
||||
=> { attr => 0, vendor => 'Trapeze', vsa => 8 },
|
||||
'dicts/dictionary.tunnel'
|
||||
=> { attr => 12, vendor => undef, vsa => 0 },
|
||||
'dicts/dictionary.unisphere'
|
||||
=> { attr => 0, vendor => 'Unisphere', vsa => 49 },
|
||||
'dicts/dictionary.unix'
|
||||
=> { attr => 0, vendor => 'Unix', vsa => 6 },
|
||||
'dicts/dictionary.usr'
|
||||
=> { attr => 2, vendor => 'USR', vsa => 259 },
|
||||
'dicts/dictionary.valemount'
|
||||
=> { attr => 0, vendor => 'ValemountNetworks', vsa => 5 },
|
||||
'dicts/dictionary.versanet'
|
||||
=> { attr => 0, vendor => 'Versanet', vsa => 1 },
|
||||
'dicts/dictionary.wispr'
|
||||
=> { attr => 0, vendor => 'WISPr', vsa => 11 },
|
||||
'dicts/dictionary.xedia'
|
||||
=> { attr => 0, vendor => 'Xedia', vsa => 6 },
|
||||
);
|
||||
|
||||
plan tests => 6 * keys %dict;
|
||||
|
||||
# Determine which dicts are not readable and produce the appropiate skip
|
||||
for my $d (keys %dict)
|
||||
{
|
||||
unless (-f $d)
|
||||
{
|
||||
delete $dict{$d};
|
||||
fail "Access $d: $!";
|
||||
SKIP: { skip "(Consequence of previous failure)", 5 };
|
||||
next;
|
||||
}
|
||||
|
||||
$dict{$d}->{dict} = new Net::Radius::Dictionary;
|
||||
isa_ok($dict{$d}->{dict}, 'Net::Radius::Dictionary');
|
||||
}
|
||||
|
||||
# Verify what happens upon reading the dictionary - Check for warnings
|
||||
# if the proper module is available
|
||||
while (my ($dict, $h) = each %dict)
|
||||
{
|
||||
warning_is { $h->{dict}->readfile($dict) } undef,
|
||||
"No warning to readfile('$dict')";
|
||||
}
|
||||
|
||||
# Now check the dictionary contents...
|
||||
|
||||
# XXX - These tests peek inside the object. Probably their methods should
|
||||
# be encapsulated through adequate accessors. However, these functions
|
||||
# are never required for real use
|
||||
|
||||
while (my ($d, $h) = each %dict)
|
||||
{
|
||||
my $dict = $h->{dict};
|
||||
my $attr = $dict->{attr};
|
||||
is(keys %{$attr}, $dict{$d}->{attr}, "Correct number of attributes in $d");
|
||||
my $num = undef;
|
||||
SKIP: {
|
||||
skip "No vendors defined in $d", 3
|
||||
if not defined $dict{$d}->{vendor};
|
||||
warning_is {$num = $dict->vendor_num($dict{$d}->{vendor})} undef,
|
||||
"No warn fetching vendor " . $dict{$d}->{vendor} . " in $d" ;
|
||||
ok(defined $num, "Vendor " . $dict{$d}->{vendor} . " in $d");
|
||||
is(scalar(keys %{$dict->{vsattr}->{$num}}),
|
||||
$dict{$d}->{vsa},
|
||||
"Correct number of VSAs for " . $dict{$d}->{vendor} . " in $d");
|
||||
# print "$_\n" for keys %{$dict->{vsattr}->{$num}};
|
||||
};
|
||||
}
|
||||
146
t/dictover.t
Normal file
146
t/dictover.t
Normal file
@@ -0,0 +1,146 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Test the overriding of specific entries
|
||||
|
||||
# $Id: dictover.t 27 2006-08-09 16:00:01Z lem $
|
||||
|
||||
use IO::File;
|
||||
use Test::More;
|
||||
use Data::Dumper;
|
||||
use Net::Radius::Dictionary;
|
||||
|
||||
my $dictfile = "dict$$.tmp";
|
||||
my $overfile = "over$$.tmp";
|
||||
|
||||
END
|
||||
{
|
||||
unlink $dictfile, $overfile;
|
||||
};
|
||||
|
||||
my @dicts = ();
|
||||
my @refs = ();
|
||||
|
||||
{
|
||||
local $/ = "EOD\n";
|
||||
@dicts = map { (s/EOD\n$//, $_)[1] } <DATA>;
|
||||
};
|
||||
|
||||
$refs[0] = bless {
|
||||
'vsattr' => {},
|
||||
'rattr' => {},
|
||||
'vendors' => {},
|
||||
'rvsaval' => {},
|
||||
'val' => {},
|
||||
'rvsattr' => {},
|
||||
'attr' => {},
|
||||
'rval' => {},
|
||||
'vsaval' => {}
|
||||
}, 'Net::Radius::Dictionary';
|
||||
|
||||
$refs[1] = bless {
|
||||
'vsattr' => {
|
||||
'9' => {
|
||||
'Cisco-AVPair' => ['1', 'string' ],
|
||||
'cisco-thing' => ['2', 'string' ]
|
||||
}
|
||||
},
|
||||
'rattr' => {
|
||||
'1' => ['User-Name', 'string'],
|
||||
'23' => ['Framed-IPX-Network', 'ipaddr'],
|
||||
'10' => ['Framed-Routing', 'integer']
|
||||
},
|
||||
'vendors' => {
|
||||
'Cisco' => '9'
|
||||
},
|
||||
'rvsaval' => {},
|
||||
'val' => {},
|
||||
'rvsattr' => {
|
||||
'9' => {
|
||||
'1' => ['Cisco-AVPair', 'string'],
|
||||
'2' => ['cisco-thing', 'string']
|
||||
}
|
||||
},
|
||||
'attr' => {
|
||||
'Framed-IPX-Network' => ['23', 'ipaddr'],
|
||||
'Framed-Routing' => ['10', 'integer'],
|
||||
'User-Name' => ['1', 'string']
|
||||
},
|
||||
'rval' => {},
|
||||
'vsaval' => {}
|
||||
}, 'Net::Radius::Dictionary';
|
||||
|
||||
sub _write
|
||||
{
|
||||
my $dict = shift;
|
||||
my $fh = new IO::File;
|
||||
$fh->open($dictfile, "w") or diag "Failed to write dict $dictfile: $!";
|
||||
print $fh $dict;
|
||||
$fh->close;
|
||||
}
|
||||
|
||||
plan tests => 27 * scalar @dicts;
|
||||
|
||||
my $fh = new IO::File;
|
||||
$fh->open($overfile, "w") or
|
||||
diag "Failed to create dictionary override file $overfile: $!";
|
||||
print $fh <<EOF;
|
||||
ATTRIBUTE User-Name 255 ipaddr
|
||||
VENDOR Cisco 254
|
||||
ATTRIBUTE Cisco-AVPair 253 string Cisco
|
||||
VENDORATTR 253 cisco-thing 252 string
|
||||
EOF
|
||||
;
|
||||
$fh->close;
|
||||
|
||||
for my $i (0 .. $#dicts)
|
||||
{
|
||||
|
||||
_write $dicts[$i];
|
||||
|
||||
my $d;
|
||||
|
||||
eval { $d = new Net::Radius::Dictionary $dictfile; };
|
||||
|
||||
isa_ok($d, 'Net::Radius::Dictionary');
|
||||
ok(!$@, "No errors during parse");
|
||||
diag $@ if $@;
|
||||
|
||||
for my $k (keys %{$refs[$i]})
|
||||
{
|
||||
ok(exists $d->{$k}, "Element $k exists in the object");
|
||||
is_deeply($d->{$k}, $refs[$i]->{$k}, "Same contents in element $k");
|
||||
}
|
||||
|
||||
eval { $d->readfile($overfile); };
|
||||
ok(!$@, "No errors during parse of override dictionary");
|
||||
diag $@ if $@;
|
||||
|
||||
is($d->attr_num('User-Name'), 255,
|
||||
'Correct number of overriden User-Name');
|
||||
|
||||
is ($d->attr_name(255), 'User-Name',
|
||||
'Correct name for User-Name overriden attribute code');
|
||||
|
||||
is($d->attr_type('User-Name'), 'ipaddr',
|
||||
'Correct type of overriden User-Name');
|
||||
|
||||
is($d->vendor_num('Cisco'), 254,
|
||||
'Correct overriding of vendor code');
|
||||
|
||||
is ($d->vsattr_num(254, 'Cisco-AVPair'), 253,
|
||||
'Correct overriding of VSA Attribute name');
|
||||
|
||||
is ($d->vsattr_name(254, 253), 'Cisco-AVPair',
|
||||
'Correct overriding of VSA Attribute number');
|
||||
}
|
||||
|
||||
__END__
|
||||
# Empty dictionary
|
||||
EOD
|
||||
# Sample dictionary
|
||||
ATTRIBUTE User-Name 1 string
|
||||
ATTRIBUTE Framed-Routing 10 integer
|
||||
ATTRIBUTE Framed-IPX-Network 23 ipaddr
|
||||
VENDOR Cisco 9
|
||||
ATTRIBUTE Cisco-AVPair 1 string Cisco
|
||||
VENDORATTR 9 cisco-thing 2 string
|
||||
72
t/dump.t
Normal file
72
t/dump.t
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Test packet dumping
|
||||
|
||||
# $Id: dump.t 38 2006-11-14 01:46:05Z lem $
|
||||
|
||||
|
||||
no utf8;
|
||||
use IO::File;
|
||||
use Test::More tests => 257;
|
||||
use Net::Radius::Packet;
|
||||
use Net::Radius::Dictionary;
|
||||
|
||||
# Init the dictionary for our test run...
|
||||
BEGIN {
|
||||
my $fh = new IO::File "dict.$$", ">";
|
||||
print $fh <<EOF;
|
||||
ATTRIBUTE User-Name 1 string
|
||||
ATTRIBUTE User-Password 2 string
|
||||
ATTRIBUTE NAS-IP-Address 4 ipaddr
|
||||
EOF
|
||||
|
||||
close $fh;
|
||||
};
|
||||
|
||||
END { unlink 'dict.' . $$; }
|
||||
|
||||
# Build a request and test it is ok
|
||||
my $p = new Net::Radius::Packet;
|
||||
isa_ok($p, 'Net::Radius::Packet');
|
||||
$p->set_dict("dict.$$");
|
||||
$p->set_code("Access-Request");
|
||||
$p->set_attr("User-Name" => 'FOO@MY.DOMAIN');
|
||||
$p->set_attr("NAS-IP-Address" => "127.0.0.1");
|
||||
my $str;
|
||||
|
||||
# Really special chars
|
||||
for my $c (0 .. 31, 127..255)
|
||||
{
|
||||
$p->set_authenticator(substr("Char-" . chr($c) . "\x0" x 16, 0, 16));
|
||||
$str = $p->str_dump;
|
||||
my $re = sprintf('(?m)^Authentic:\s+Char-\\\\x\{%x\}(?:\\\\x\{0\})+$', $c);
|
||||
like($str, qr/$re/, "Correct dump of chr($c)");
|
||||
}
|
||||
|
||||
# Really normal chars
|
||||
for my $c (32..35, 44..45, 47 .. 62, 64 .. 90, 95, 97..122, 124)
|
||||
{
|
||||
$p->set_authenticator(substr("Char-" . chr($c) . "\x0" x 16, 0, 16));
|
||||
$str = $p->str_dump;
|
||||
my $re = sprintf('(?m)^Authentic:\s+Char-%s(?:\\\\x\{0\})+$', chr($c));
|
||||
like($str, qr/$re/, "Correct dump of chr($c)");
|
||||
}
|
||||
|
||||
# Things that mean something special to Perl
|
||||
for my $c (42, 43, 46, 63)
|
||||
{
|
||||
$p->set_authenticator(substr("Char-" . chr($c) . "\x0" x 16, 0, 16));
|
||||
$str = $p->str_dump;
|
||||
my $re = sprintf('(?m)^Authentic:\s+Char-\\%s(?:\\\\x\{0\})+$', chr($c));
|
||||
like($str, qr/$re/, "Correct dump of chr($c)");
|
||||
}
|
||||
|
||||
# Quote-like things
|
||||
for my $c (36..41, 91..94, 96, 123..125)
|
||||
{
|
||||
$p->set_authenticator(substr("Char-" . chr($c) . "\x0" x 16, 0, 16));
|
||||
$str = $p->str_dump;
|
||||
my $re = sprintf('(?m)^Authentic:\s+Char-\\\\\\%s(?:\\\\x\{0\})+$',
|
||||
chr($c));
|
||||
like($str, qr/$re/, "Correct dump of chr($c)");
|
||||
}
|
||||
108
t/packdict.t
Normal file
108
t/packdict.t
Normal file
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Test the parsing of individual attributes
|
||||
|
||||
# $Id: packdict.t 37 2006-11-14 01:42:55Z lem $
|
||||
|
||||
use IO::File;
|
||||
use Test::More tests => 30;
|
||||
use Data::Dumper;
|
||||
use Net::Radius::Dictionary;
|
||||
|
||||
my $dictfile = "dict$$.tmp";
|
||||
|
||||
END
|
||||
{
|
||||
unlink $dictfile;
|
||||
};
|
||||
|
||||
{
|
||||
my $dict;
|
||||
eval { $dict = Net::Radius::Dictionary->new() };
|
||||
isa_ok($dict, 'Net::Radius::Dictionary');
|
||||
ok(!$@, 'No errors during parse');
|
||||
diag $@ if $@;
|
||||
|
||||
# Test presence of some stuff
|
||||
my %number_for = $dict->packet_numbers();
|
||||
is(scalar(keys %number_for), 35, 'Default packet numbers number');
|
||||
is($number_for{'Disconnect-NAK'}, 42, 'Simple mapping presence in hash');
|
||||
|
||||
my %name_for = $dict->packet_names();
|
||||
is(scalar(keys %name_for), 34, 'Default packet names number');
|
||||
is($name_for{40}, 'Disconnect-Request', 'Simple mapping presence in hash');
|
||||
is($name_for{6}, 'Interim-Accounting',
|
||||
'Back-resolution of 6 to Interim Accounting as default');
|
||||
|
||||
# Direct resolution
|
||||
ok($dict->packet_hasname('Access-Reject'),
|
||||
'packet_hasname() to default');
|
||||
is($dict->packet_num('Access-Reject'), 3, 'packet_num() to default');
|
||||
ok($dict->packet_hasnum(2), 'packet_hasnum() to default');
|
||||
is($dict->packet_name(2), 'Access-Accept', 'packet_name() to default');
|
||||
|
||||
ok(! $dict->packet_hasname('@@Inexistent@@'),
|
||||
'packet_hasname() on inexistent');
|
||||
is($dict->packet_num('@@Inexistent@@'), undef,
|
||||
'packet_num() on inexistent');
|
||||
ok(! $dict->packet_hasnum(-1), 'packet_hasnum() on inexistent');
|
||||
is($dict->packet_name(-1), undef, 'packet_name() on inexistent');
|
||||
}
|
||||
|
||||
{
|
||||
my $dict_content = do { local $/; <DATA>; };
|
||||
_write($dict_content);
|
||||
|
||||
my $dict;
|
||||
eval { $dict = Net::Radius::Dictionary->new($dictfile) };
|
||||
isa_ok($dict, 'Net::Radius::Dictionary');
|
||||
ok(!$@, 'No errors during parse');
|
||||
diag $@ if $@;
|
||||
|
||||
# Test presence of some stuff
|
||||
my %number_for = $dict->packet_numbers();
|
||||
|
||||
is(scalar(keys %number_for), 10, 'Packet numbers number');
|
||||
is($number_for{'My-Experiment'}, 250, 'Simple mapping presence in hash');
|
||||
|
||||
my %name_for = $dict->packet_names();
|
||||
is(scalar(keys %name_for), 10, 'Packet names number');
|
||||
is($name_for{1}, 'Access-Request', 'Simple mapping presence in hash');
|
||||
is($name_for{250}, 'My-Experiment', 'Experimental value');
|
||||
|
||||
# Direct resolution
|
||||
ok($dict->packet_hasname('Access-Reject'),
|
||||
'packet_hasname() to default');
|
||||
is($dict->packet_num('Access-Reject'), 3, 'packet_num() to default');
|
||||
ok($dict->packet_hasnum(2), 'packet_hasnum() to default');
|
||||
is($dict->packet_name(2), 'Access-Accept', 'packet_name() to default');
|
||||
|
||||
ok(! $dict->packet_hasname('Disconnect-Request'),
|
||||
'packet_hasname() on inexistent');
|
||||
is($dict->packet_num('Disconnect-NAK'), undef,
|
||||
'packet_num() on inexistent');
|
||||
ok(! $dict->packet_hasnum(41), 'packet_hasnum() on inexistent');
|
||||
is($dict->packet_name(41), undef, 'packet_name() on inexistent');
|
||||
}
|
||||
|
||||
sub _write
|
||||
{
|
||||
my $dict = shift;
|
||||
my $fh = new IO::File;
|
||||
$fh->open($dictfile, "w") or diag "Failed to write dict $dictfile: $!";
|
||||
print $fh $dict;
|
||||
$fh->close;
|
||||
}
|
||||
|
||||
__END__
|
||||
# Sample dictionary
|
||||
PACKET Access-Request 1
|
||||
PACKET Access-Accept 2
|
||||
PACKET Access-Reject 3
|
||||
PACKET Accounting-Request 4
|
||||
PACKET Accounting-Response 5
|
||||
PACKET Accounting-Status 6
|
||||
PACKET Access-Challenge 11
|
||||
PACKET Status-Server 12
|
||||
PACKET Status-Client 13
|
||||
PACKET My-Experiment 250
|
||||
128
t/packets.t
Normal file
128
t/packets.t
Normal file
@@ -0,0 +1,128 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Process each binary packet in the distribution, performing generic tests
|
||||
# on it
|
||||
|
||||
# $Id: packets.t 73 2007-01-30 10:22:35Z lem $
|
||||
|
||||
no utf8;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use IO::File;
|
||||
use File::Find;
|
||||
use Test::More;
|
||||
use Test::Warn;
|
||||
|
||||
use Net::Radius::Packet;
|
||||
use Net::Radius::Dictionary;
|
||||
|
||||
# Pick a default dictionary to use in case none is defined
|
||||
my $def_dict = 'dicts/dictionary';
|
||||
|
||||
# Find all the test inputs we will be processing here
|
||||
my @inputs = ();
|
||||
|
||||
find ({ untaint => 1, follow => 1, no_chdir => 1,
|
||||
wanted => sub
|
||||
{
|
||||
return unless $File::Find::name =~ m/\.p$/;
|
||||
push @inputs, $File::Find::name;
|
||||
},
|
||||
}, qw!packets!);
|
||||
|
||||
# Provide a test plan based in how many test inputs where found
|
||||
plan tests => @inputs * 13;
|
||||
|
||||
# Perform the tests for each test input
|
||||
for my $i (@inputs)
|
||||
{
|
||||
SKIP: {
|
||||
# Read the test input
|
||||
skip "$i not readable", 12 unless -r $i and -r _;
|
||||
|
||||
my $fh = new IO::File $i, "r";
|
||||
my $input = '';
|
||||
our $VAR1 = undef; # Placeholder for the recovered structure
|
||||
ok($fh, "Open test input $i for reading");
|
||||
do {
|
||||
local $/ = undef;
|
||||
ok ($input = <$fh>, "Read non-empty test input");
|
||||
};
|
||||
|
||||
ok(close $fh, "Close the test input after reading");
|
||||
ok(length($input), "Test input is non-empty");
|
||||
like($input, qr/# Net::Radius test input/m,
|
||||
"Input looks like a test input");
|
||||
|
||||
unless (eval "$input" and ok(!$@, "Eval errors"))
|
||||
{
|
||||
diag $@;
|
||||
skip "Problems with eval() of $i", 7;
|
||||
}
|
||||
|
||||
ok(ref($VAR1) eq 'HASH', "Load $i: " .
|
||||
($VAR1->{description} || 'No desc'));
|
||||
|
||||
# Try to build a suitable dictionary for decoding the packet
|
||||
|
||||
my $d;
|
||||
|
||||
if ($VAR1->{dictionary})
|
||||
{
|
||||
# Use bundled dictionary for decoding this packet
|
||||
$d = $VAR1->{dictionary};
|
||||
}
|
||||
else
|
||||
{
|
||||
$d = new Net::Radius::Dictionary;
|
||||
|
||||
if ($VAR1->{opts}->{dictionary})
|
||||
{
|
||||
# Try to load the specified dictionaries - Ignore errors
|
||||
$d->readfile($_) for @{$VAR1->{opts}->{dictionary}};
|
||||
}
|
||||
else
|
||||
{
|
||||
# Try to load the default dictionary
|
||||
$d->readfile($def_dict);
|
||||
}
|
||||
}
|
||||
|
||||
isa_ok($d, 'Net::Radius::Dictionary');
|
||||
|
||||
my $p;
|
||||
warnings_are(sub { $p = new Net::Radius::Packet $d, $VAR1->{packet} },
|
||||
[], "No warnings on packet decode");
|
||||
|
||||
isa_ok($p, 'Net::Radius::Packet');
|
||||
|
||||
if (exists($VAR1->{slots}))
|
||||
{
|
||||
is $p->attr_slots, $VAR1->{slots}, "Correct number of slots";
|
||||
}
|
||||
else
|
||||
{
|
||||
SKIP: { skip "Test input provides no number of slots", 1 };
|
||||
}
|
||||
|
||||
if (exists($VAR1->{identifier}))
|
||||
{
|
||||
is $p->identifier, $VAR1->{identifier}, "Correct identifier";
|
||||
}
|
||||
else
|
||||
{
|
||||
SKIP: { skip "Test input provides no identifier", 1 };
|
||||
}
|
||||
|
||||
if (exists($VAR1->{authenticator}))
|
||||
{
|
||||
is $p->authenticator, $VAR1->{authenticator},
|
||||
"Correct authenticator";
|
||||
}
|
||||
else
|
||||
{
|
||||
SKIP: { skip "Test input provides no authenticator", 1 };
|
||||
}
|
||||
};
|
||||
}
|
||||
84
t/vsa.t
Normal file
84
t/vsa.t
Normal file
@@ -0,0 +1,84 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# Test VSA packing and unpacking
|
||||
|
||||
# $Id: vsa.t 83 2007-06-08 13:57:58Z lem $
|
||||
|
||||
|
||||
use IO::File;
|
||||
use Test::More tests => 14;
|
||||
use Net::Radius::Packet;
|
||||
use Net::Radius::Dictionary;
|
||||
|
||||
# Init the dictionary for our test run...
|
||||
BEGIN {
|
||||
my $fh = new IO::File "dict.$$", ">";
|
||||
print $fh <<EOF;
|
||||
ATTRIBUTE User-Name 1 string
|
||||
ATTRIBUTE NAS-Port 5 integer
|
||||
ATTRIBUTE Service-Type 6 integer
|
||||
|
||||
VALUE Service-Type Framed-User 2
|
||||
|
||||
VENDOR Cisco-VPN3000 3076
|
||||
|
||||
ATTRIBUTE CVPN3000-Access-Hours 1 string Cisco-VPN3000
|
||||
ATTRIBUTE CVPN3000-Simultaneous-Logins 2 integer Cisco-VPN3000
|
||||
|
||||
VENDORATTR 88888 Resource-Name 1 string
|
||||
EOF
|
||||
|
||||
close $fh;
|
||||
};
|
||||
|
||||
END { unlink 'dict.' . $$; }
|
||||
|
||||
my $d = new Net::Radius::Dictionary "dict.$$";
|
||||
isa_ok($d, 'Net::Radius::Dictionary');
|
||||
|
||||
# use Data::Dumper;
|
||||
# diag 'd: ', Data::Dumper->Dump([$d]);
|
||||
|
||||
# Build a request and test it is ok - We're leaving out the
|
||||
# authenticator calculation
|
||||
|
||||
my $p = new Net::Radius::Packet $d;
|
||||
isa_ok($p, 'Net::Radius::Packet');
|
||||
$p->set_identifier(42);
|
||||
$p->set_authenticator("\x66" x 16);
|
||||
$p->set_code("Access-Accept");
|
||||
$p->set_attr("User-Name" => 'foo');
|
||||
$p->set_attr('Service-Type' => 'Framed-User');
|
||||
$p->set_attr('NAS-Port' => '42');
|
||||
$p->set_vsattr('Cisco-VPN3000', 'CVPN3000-Access-Hours', "Access-Hours");
|
||||
$p->set_vsattr('Cisco-VPN3000', 'CVPN3000-Simultaneous-Logins', 63);
|
||||
$p->set_vsattr(88888, 'Resource-Name', 'storage');
|
||||
|
||||
my $q = new Net::Radius::Packet $d, $p->pack;
|
||||
isa_ok($q, 'Net::Radius::Packet');
|
||||
|
||||
is($p->code, 'Access-Accept', "Correct packet code");
|
||||
is($p->attr('User-Name'), 'foo', "Correct User-Name");
|
||||
is($p->attr('Service-Type'), 'Framed-User', "Correct Framed-User");
|
||||
is($p->attr('NAS-Port'), 42, "Correct NAS-Port");
|
||||
is($p->attr('User-Name'), 'foo', "Correct User-Name");
|
||||
is(ref($p->vsattr('Cisco-VPN3000', 'CVPN3000-Access-Hours')),
|
||||
'ARRAY', "Correct type for string VSA");
|
||||
is($p->vsattr('Cisco-VPN3000', 'CVPN3000-Access-Hours')->[0],
|
||||
'Access-Hours', "Correct string VSA");
|
||||
is(ref($p->vsattr('Cisco-VPN3000', 'CVPN3000-Simultaneous-Logins')),
|
||||
'ARRAY', "Correct type for integer VSA");
|
||||
is($p->vsattr('Cisco-VPN3000', 'CVPN3000-Simultaneous-Logins')->[0],
|
||||
'63', "Correct integer VSA");
|
||||
if(ok($p->vsattr(88888, 'Resource-Name'), "Fetch of numeric vid from VSA"))
|
||||
{
|
||||
is($p->vsattr(88888, 'Resource-Name')->[0],
|
||||
'storage', "Correct integer VSA (numeric vid)");
|
||||
}
|
||||
else
|
||||
{
|
||||
# use Data::Dumper;
|
||||
# diag 'q: ', Data::Dumper->Dump([$q]);
|
||||
# diag 'p: ', Data::Dumper->Dump([$p]);
|
||||
fail("Cannot test numeric vid VSA value");
|
||||
}
|
||||
Reference in New Issue
Block a user