Imported Upstream version 2.103+dfsg

This commit is contained in:
Mario Fetka
2017-09-15 15:01:34 +02:00
commit 885cfb79ed
115 changed files with 16877 additions and 0 deletions

191
examples/example-client.pl Normal file
View File

@@ -0,0 +1,191 @@
#!/usr/bin/perl
use Time::HiRes qw(gettimeofday tv_interval);
use Net::Inet qw(:routines);
use Net::Radius::Dictionary;
use Net::Radius::Packet;
use Net::Gen qw(:af);
use POSIX qw(uname);
use Net::UDP;
use warnings;
use strict;
use Fcntl;
# This is a simple test program to originate RADIUS authentication
# and accounting requests for testing a RADIUS server.
# $Id: example-client.pl 7 2003-01-08 03:42:41Z lem $
# test user details
my $user = "testuser";
my $password = "testpassword";
# details of RADIUS authentication and accounting servers
my $authhost = "radius.server.domain.com";
my $authport = 1645;
my $accthost = "radius.server.domain.com";
my $acctport = 1646;
my $secret = "testkey"; # Shared secret for this client
# Parse the RADIUS dictionary file (must have dictionary in current dir)
my $dict = new Net::Radius::Dictionary "dictionary"
or die "Couldn't read dictionary: $!";
# Set up the network socket
my $s = new Net::UDP or die $!;
my ($authaddr, $acctaddr, $paddr);
$paddr = gethostbyname($authhost) or die "Can't resolve host $authhost\n";
$authaddr = pack_sockaddr_in(AF_INET, $authport, $paddr);
$paddr = gethostbyname($accthost) or die "Can't resolve host $accthost\n";
$acctaddr = pack_sockaddr_in(AF_INET, $acctport, $paddr);
# discover my own IP address
my $myip = join '.',unpack "C4",gethostbyname((uname)[1]);
my $ident = 1;
my $whence;
# subroutine to make string of 16 random bytes
sub bigrand() {
pack "n8",
rand(65536), rand(65536), rand(65536), rand(65536),
rand(65536), rand(65536), rand(65536), rand(65536);
}
my ($rec, $req, $resp);
# Create a request packet
$req = new Net::Radius::Packet $dict;
$req->set_code('Access-Request');
$req->set_attr('User-Name' => $user);
$req->set_attr('Service-Type' => 'Framed');
$req->set_attr('Framed-Protocol' => 'PPP');
$req->set_attr('NAS-Port' => 1234);
$req->set_attr('NAS-Identifier' => 'PerlTester');
$req->set_attr('NAS-IP-Address' => $myip);
$req->set_attr('Called-Station-Id' => '0000');
$req->set_attr('Calling-Station-Id' => '01234567890');
$req->set_identifier($ident);
$req->set_authenticator(bigrand); # random authenticator required
$req->set_password($password, $secret); # encode and store password
# Send to the server. Encoding with auth_resp is NOT required.
$s->sendto($req->pack, $authaddr);
# $req->dump;
# wait for response
$rec = $s->recv(undef, undef, $whence);
$resp = new Net::Radius::Packet $dict, $rec;
# $resp->dump;
if ($whence ne $authaddr || $resp->identifier != $ident) {
die "unexpected reply to Radius authentication!\n";
}
if ($resp->code ne 'Access-Accept') {
die "Radius response not Access-Accept\n";
}
# note the start time of the session
my $sessiontime = time;
# now construct and send the Accounting-Start packet,
# using the Authentication packet as a starting-point.
$ident = ($ident + 1) & 255;
my $class = $resp->attr('Class'); # to return to Radius
# remove password from packet
$req->unset_attr('User-Password');
# add accounting items
$req->set_code('Accounting-Request');
$req->set_attr('Acct-Status-Type', 'Start');
$req->set_attr('Acct-Delay-Time', 0);
$req->set_attr('Acct-Authentic', 'RADIUS');
$req->set_attr('Class', $class) if $class; # include Class if server gave one
# some example values
$req->set_attr('Acct-Session-Id', '12345678');
$req->set_attr('Framed-IP-Address', '10.0.1.2');
$req->set_identifier($ident);
# for accounting packets, start with a null authenticator
$req->set_authenticator("");
# ... and then hash it with the secret like a response
$s->sendto(auth_resp($req->pack,$secret), $acctaddr);
# $req->dump;
# wait for response
$rec = $s->recv(undef, undef, $whence);
$resp = new Net::Radius::Packet $dict, $rec;
# $resp->dump;
if ($whence ne $acctaddr || $resp->identifier != $ident) {
die "unexpected reply to Radius accounting start!\n";
}
if ($resp->code ne 'Accounting-Response') {
die "Radius response not Accounting-Response\n";
}
# sleep for a while to simulate an online session
sleep 20;
# calculate the duration of the session
$sessiontime = time - $sessiontime;
# now construct and send the Accounting-Stop packet,
# using the Accounting-Start packet as a starting point.
$ident = ($ident + 1) & 255;
# add the end-of-session values
$req->set_attr('Acct-Status-Type', 'Stop');
$req->set_attr('Acct-Delay-Time', 0);
$req->set_attr('Acct-Session-Time', $sessiontime);
# make up some values for this example
$req->set_attr('Acct-Input-Octets', $sessiontime * 3000);
$req->set_attr('Acct-Output-Octets', $sessiontime * 300);
$req->set_attr('Acct-Input-Packets', $sessiontime * 30);
$req->set_attr('Acct-Output-Packets', $sessiontime * 10);
$req->set_attr('Acct-Terminate-Cause', 'User-Request');
$req->set_identifier($ident);
# for accounting packets, start with a null authenticator
$req->set_authenticator("");
# ... and then hash it with the secret like a response
$s->sendto(auth_resp($req->pack,$secret), $acctaddr);
# $req->dump;
# wait for response
$rec = $s->recv(undef, undef, $whence);
$resp = new Net::Radius::Packet $dict, $rec;
# $resp->dump;
if ($whence ne $acctaddr || $resp->identifier != $ident) {
die "unexpected reply to Radius accounting stop!\n";
}
if ($resp->code ne 'Accounting-Response') {
die "Radius response not Accounting-Response\n";
}
exit;

124
examples/example-menu.pl Normal file
View File

@@ -0,0 +1,124 @@
#!/usr/bin/perl
use Net::Radius::Dictionary;
use Net::Radius::Packet;
use Net::Inet;
use Net::UDP;
use warnings;
use strict;
use Fcntl;
# This is a VERY simple RADIUS authentication server which accepts
# any user whos User-Name and Password match according to the Unix
# getpwnam() function. It then displays a menu asking whether they
# wish to telnet or start PPP. If telnet is chosen, they are asked
# for a host name.
# NOTE - This server must be run as root on systems with shadow passwords.
# $Id: example-menu.pl 7 2003-01-08 03:42:41Z lem $
my $secret = "mysecret"; # Shared secret on the term server
# Function to check name and password. Returns undef if no such user.
sub check_pass {
my ($user, $pass) = @_;
if (my $pwd = (getpwnam($user))[1]) {
$pwd =~ /^\$.+\$(.+)\$/ or $pwd =~ /^(..)/;
my $salt = $1;
if (crypt($pass, $salt) eq $pwd) {
return 1;
}
else {
return 0;
}
}
else {
return undef;
}
}
# Parse the RADIUS dictionary file (must have dictionary in current dir)
my $dict = new Net::Radius::Dictionary "dictionary"
or die "Couldn't read dictionary: $!";
# Set up the network socket (must have radius in /etc/services)
my $s = new Net::UDP { thisservice => "radius" } or die $!;
$s->bind or die "Couldn't bind: $!";
$s->fcntl(F_SETFL, $s->fcntl(F_GETFL,0) | O_NONBLOCK)
or die "Couldn't make socket non-blocking: $!";
# Loop forever, recieving packets and replying to them
while (1) {
my ($rec, $whence);
# Wait for a packet
my $nfound = $s->select(1, 0, 1, undef);
if ($nfound > 0) {
# Get the data
$rec = $s->recv(undef, undef, $whence);
# Unpack it
my $p = new Net::Radius::Packet $dict, $rec;
if ($p->code eq 'Access-Request') {
# Initialize the response packet we'll send back
my $rp = new Net::Radius::Packet $dict;
$rp->set_identifier($p->identifier);
$rp->set_authenticator($p->authenticator);
if (not defined($p->attr('State'))) {
print $p->attr('User-Name'), " attempting login with password ",
$p->password($secret), "\n";
# Check against the Unix passwd file
if (check_pass($p->attr('User-Name'), $p->password($secret))) {
print "Login valid. Sending menu.\n";
$rp->set_code('Access-Challenge');
$rp->set_attr('State', 'menu');
$rp->set_attr('Reply-Message',
"\r\nWelcome to BlahNet.\r\n" .
"Please choose from the following menu:\r\n\r\n" .
"1: PPP\r\n2: Telnet\r\n");
}
else {
print "Invalid login.\n";
$rp->set_code('Access-Reject');
$rp->set_attr('Reply-Message', "\r\nInvalid login.\r\n");
}
}
else {
# We are dealing with a response to a previous challenge
if ($p->attr('State') eq 'menu') {
if ($p->password($secret) eq '1') {
print "PPP login selected.\n";
$rp->set_code('Access-Accept');
$rp->set_attr('Service-Type', 'Framed-User');
$rp->set_attr('Framed-Protocol', 'PPP');
}
elsif ($p->password($secret) eq '2') {
print "Telnet login selected.\n";
$rp->set_code('Access-Challenge');
$rp->set_attr('Reply-Message', "\r\nWhich host?\r\n");
$rp->set_attr('State', 'host');
}
else {
print "Invalid menu option.\n";
$rp->set_code('Access-Reject');
$rp->set_attr('Reply-Message', "\r\nInvalid response.\r\n");
}
}
elsif ($p->attr('State') eq 'host') {
print "Telnet host chosen: ", $p->password($secret), "\n";
$rp->set_code('Access-Accept');
$rp->set_attr('Service-Type', 'Login-User');
$rp->set_attr('Login-Service', 'Telnet');
$rp->set_attr('Login-IP-Host', $p->password($secret));
$rp->set_attr('Reply-Message', "Connecting...\r\n");
}
}
# Authenticate with the secret and send to the server.
$s->sendto(auth_resp($rp->pack, $secret), $whence);
}
else {
# It's not an Access-Request
print "Unexpected packet type recieved.";
$p->dump;
}
}
}

84
examples/example-unix.pl Normal file
View File

@@ -0,0 +1,84 @@
#!/usr/bin/perl
use Net::Radius::Dictionary;
use Net::Radius::Packet;
use Net::Inet;
use Net::UDP;
use warnings;
use strict;
use Fcntl;
# This is a VERY simple RADIUS authentication server which accepts
# any user whos User-Name and Password match according to the Unix
# getpwnam() function.
# NOTE - This server must be run as root on systems with shadow passwords.
my $secret = "mysecret"; # Shared secret on the term server
# Function to check name and password. Returns undef if no such user.
sub check_pass {
my ($user, $pass) = @_;
if (my $pwd = (getpwnam($user))[1]) {
$pwd =~ /^\$.+\$(.+)\$/ or $pwd =~ /^(..)/;
my $salt = $1;
if (crypt($pass, $salt) eq $pwd) {
return 1;
}
else {
return 0;
}
}
else {
return undef;
}
}
# Parse the RADIUS dictionary file (must have dictionary in current dir)
my $dict = new Net::Radius::Dictionary "dictionary"
or die "Couldn't read dictionary: $!";
# Set up the network socket (must have radius in /etc/services)
my $s = new Net::UDP { thisservice => "radius" } or die $!;
$s->bind or die "Couldn't bind: $!";
$s->fcntl(F_SETFL, $s->fcntl(F_GETFL,0) | O_NONBLOCK)
or die "Couldn't make socket non-blocking: $!";
# Loop forever, recieving packets and replying to them
while (1) {
my ($rec, $whence);
# Wait for a packet
my $nfound = $s->select(1, 0, 1, undef);
if ($nfound > 0) {
# Get the data
$rec = $s->recv(undef, undef, $whence);
# Unpack it
my $p = new Net::Radius::Packet $dict, $rec;
if ($p->code eq 'Access-Request') {
# Print some details about the incoming request (try ->dump here)
print $p->attr('User-Name'), " attempting login with password ",
$p->password($secret), "\n";
# Initialize the response packet we'll send back
my $rp = new Net::Radius::Packet $dict;
$rp->set_identifier($p->identifier);
$rp->set_authenticator($p->authenticator);
# Check against the Unix passwd file
if (check_pass($p->attr('User-Name'), $p->password($secret))) {
print "Login valid.\n";
$rp->set_code('Access-Accept');
}
else {
print "Invalid login.\n";
$rp->set_code('Access-Reject');
$rp->set_attr('Reply-Message', "\r\nInvalid login.\r\n");
}
# Authenticate with the secret and send to the server.
$s->sendto(auth_resp($rp->pack, $secret), $whence);
}
else {
# It's not an Access-Request
print "Unexpected packet type recieved.";
$p->dump;
}
}
}

58
examples/example-yes.pl Normal file
View File

@@ -0,0 +1,58 @@
#!/usr/bin/perl
use Net::Radius::Dictionary;
use Net::Radius::Packet;
use Net::Inet;
use Net::UDP;
use warnings;
use strict;
use Fcntl;
# This is a VERY simple RADIUS authentication server which responds
# to Access-Request packets with Access-Accept. This allows anyone
# to log in.
# $Id: example-yes.pl 7 2003-01-08 03:42:41Z lem $
my $secret = "mysecret"; # Shared secret on the term server
# Parse the RADIUS dictionary file (must have dictionary in current dir)
my $dict = new Net::Radius::Dictionary "dictionary"
or die "Couldn't read dictionary: $!";
# Set up the network socket (must have radius in /etc/services)
my $s = new Net::UDP { thisservice => "radius" } or die $!;
$s->bind or die "Couldn't bind: $!";
$s->fcntl(F_SETFL, $s->fcntl(F_GETFL,0) | O_NONBLOCK)
or die "Couldn't make socket non-blocking: $!";
# Loop forever, recieving packets and replying to them
while (1) {
my ($rec, $whence);
# Wait for a packet
my $nfound = $s->select(1, 0, 1, undef);
if ($nfound > 0) {
# Get the data
$rec = $s->recv(undef, undef, $whence);
# Unpack it
my $p = new Net::Radius::Packet $dict, $rec;
if ($p->code eq 'Access-Request') {
# Print some details about the incoming request (try ->dump here)
print $p->attr('User-Name'), " logging in with password ",
$p->password($secret), "\n";
# Create a response packet
my $rp = new Net::Radius::Packet $dict;
$rp->set_code('Access-Accept');
$rp->set_identifier($p->identifier);
$rp->set_authenticator($p->authenticator);
# (No attributes are needed.. but you could set IP addr, etc. here)
# Authenticate with the secret and send to the server.
$s->sendto(auth_resp($rp->pack, $secret), $whence);
}
else {
# It's not an Access-Request
print "Unexpected packet type recieved.";
$p->dump;
}
}
}

142
examples/radius2ldap.pl Normal file
View File

@@ -0,0 +1,142 @@
#!/usr/bin/perl
use Net::Radius::Dictionary;
use Net::Radius::Packet;
use Net::LDAP::Util;
use Net::Inet;
use Net::LDAP;
use Net::UDP;
use warnings;
use Socket;
use strict;
use Fcntl;
# This is a simple RADIUS authentication server which accepts
# any user whose User-Name and Password validiate via LDAP
# NOTE - This server must be run as root on systems with shadow passwords.
# $Id: radius2ldap.pl 7 2003-01-08 03:42:41Z lem $
my $testing = 0; # set non-zero if testing
my %hostname_secret = ('rad1' => 'secret1', 'rad2' => '2secret',
'testhost' => 'testsecret');
my %host_secret; #same as above translated to 4 byte address keys
foreach my $host(keys %hostname_secret) {
$host_secret{inet_aton($host)} = $hostname_secret{$host};
}
my $uselogfile = "/var/log/rad2ldaplog";
my $errlogf = "/var/log/rad2ldaperrs";
open ERRLOG, ">>$errlogf";
print ERRLOG "Started ",scalar(localtime()),"\n";
close ERRLOG;
my $ldap;
connect_and_bind();
# Parse the RADIUS dictionary file
my $dict = new Net::Radius::Dictionary "/usr/local/lib/radius.dictionary"
or die "Couldn't read dictionary: $!";
# Set up the network socket (must have radius in /etc/services)
my $s = new Net::UDP { thisservice => "radius" } or die $!;
$s->bind or die "Couldn't bind: $!";
$s->fcntl(F_SETFL, $s->fcntl(F_GETFL,0) | O_NONBLOCK)
or die "Couldn't make socket non-blocking: $!";
# Loop forever, receiving packets and replying to them
while (1) {
my ($rec, $whence);
# Wait for a packet
my $nfound = $s->select(1, 0, 1, undef);
if ($nfound > 0) {
# Get the data
$rec = $s->recv(undef, undef, $whence);
my $fromname = inet_ntoa(substr($whence,4,4));
print "from $fromname " if $testing;
# Unpack it
my $p = new Net::Radius::Packet $dict, $rec;
if ($p->code eq 'Access-Request') {
open LOG, ">>$uselogfile";
# Print some details about the incoming request (try ->dump here)
print $p->attr('User-Name'), " attempting login with password ",
$p->password($host_secret{substr($whence,4,4)}), "\n" if $testing;
print LOG $p->attr('User-Name');
# Initialize the response packet we'll send back
my $rp = new Net::Radius::Packet $dict;
$rp->set_identifier($p->identifier);
$rp->set_authenticator($p->authenticator);
# Check against the authorization source passwd file
if (check_pass($p->attr('User-Name'),
$p->password($host_secret{substr($whence,4,4)}))) {
$rp->set_code('Access-Accept');
print LOG " OK ";
}
else {
print "Invalid login.\n" if $testing;
$rp->set_code('Access-Reject');
$rp->set_attr('Reply-Message', "\r\nInvalid login.\r\n");
print LOG " bad ";
}
# Authenticate with the secret and send to the server.
$s->sendto(auth_resp($rp->pack,
$host_secret{substr($whence,4,4)}), $whence);
print LOG scalar(localtime()),"\n";
close LOG;
}
else {
# It's not an Access-Request
print "Unexpected packet type recieved." if $testing;
$p->dump;
open ERRLOG, ">>$errlogf";
print ERRLOG "Bad packet type received ",localtime(),"\n";
close ERRLOG;
}
}
}
sub connect_and_bind {
# make a connection to an LDAP server and bind to it.
$ldap->unbind if $ldap;
$ldap = Net::LDAP->new("ldaphost1.dirplace.com");
$ldap = Net::LDAP->new("ldaphost2.dirplace.com") unless $ldap;
$ldap = Net::LDAP->new("ldapbackup.elsewhere.com") unless $ldap;
die "$@" unless $ldap;;
$ldap->bind (version => 3) or die $@;
}
sub check_pass {
# Function to check name and password. Returns undef if no such user.
my ($login, $password) = @_;
return undef unless $password;
my $retries = 0;
while (1) {
return undef if $retries > 2;
my $mesg = $ldap->search(base => "o=myorg",
filter => "(uid=$login)",
attrs => ["sn"]);
# login doesn't exist
return undef
if (Net::LDAP::Util::ldap_error_name($mesg->code)
eq "LDAP_NO_SUCH_OBJECT" ||
(($mesg->code == 0) and ($mesg->count() != 1)));
if ($mesg->code) {
++$retries;
print "retry search due to ", Net::LDAP::Util::ldap_error_name($mesg->code),"\n" if $testing;
open ERRLOG, ">>$errlogf";
print ERRLOG "retry search due to ", Net::LDAP::Util::ldap_error_name($mesg->code),scalar(localtime()),"\n";
close ERRLOG;
connect_and_bind();
next;
}
my $entry = $mesg->entry(0);
my $dn = $entry->dn;
# print "Dn is $dn\n" if $testing;
$mesg = $ldap->bind (dn => $dn, password => $password, version => 3) ;
return 0 if Net::LDAP::Util::ldap_error_name($mesg->code) eq "LDAP_INVALID_CREDENTIALS";
return 1 if $mesg->code == 0;
++$retries;
print "retry auth due to", Net::LDAP::Util::ldap_error_name($mesg->code),"\n" if $testing;
connect_and_bind();
}
}

104
examples/tutorial.pl Normal file
View File

@@ -0,0 +1,104 @@
##
## This file shows the very basics of using these modules by commenting
## on common tasks required within a server or a client. It assumes you're
## familiar with the RADIUS protocol. If you're not, check the included RFCs
## and your equipment's manual.
##
## Luis E. Mu<4D>oz <luismunoz@cpan.org>
##
## THIS FILE IS CURRENTLY UNDER REVIEW. PLEASE REFER TO example-*.pl FOR
## SPECIFIC USAGE EXAMPLES INVOLVING UP TO DATE METHODS.
##
###################################
###################################
use Net::Radius::Packet;
use Net::Radius::Dictionary;
# The first thing you need, is a dictionary file. We will assume that
# this pathname is correct. The dictionary contains the specifications
# for the attributes that this module understands, and must contain
# information for the attributes that your vendor provides. Normally,
# vendors support a set of standard attributes, and might also have
# proprietary attributes that you can add to this file.
my $dict = new Net::Radius::Dictionary "../dictionary"
or die "Cannot read or parse the dictionary: $!\n";
# As you see, there's no point in going on if you do not have a
# dictionary object to work with.
# Our first task, is to fill a packet. Let's create a packet that
# looks like the one sent from a NAS or access device...
my $packet = new Net::Radius::Packet $dict;
# The packet object needs to know which dictionary to use to encode and
# decode the attributes you will use.
# One of the common packets we'll receive from devices are going to be
# 'Access-Request' packets. Let's do it.
$packet->set_code('Access-Request');
# Now let's add an identifier, which is like a counter that the NAS uses
# to keep track of which reply belongs to which request.
$packet->set_identifier(1);
# At this point, we have set some information in the packet. However, we
# should add some useful attributes to it. First, we add some attributes
# that are standard and should be in the dictionary. Otherwise, the generated
# packet won't contain the intended data.
$packet->set_attr('User-Name', 'you');
$packet->set_attr('NAS-IP-Address', '127.0.0.1');
$packet->set_attr('NAS-Port', 1);
# Some equipment also can use a 'Vendor-Specific Attribute' to control
# some part of its behavior. These attributes are there so that each
# vendor can extend the protocol in a somewhat standard way. Let's
# add a vendor attribute for a Cisco piece of equipment. Note that
# Cisco is vendor 9.
$packet->set_vsattr(9, 'cisco-avpair', 'This is my VSA 1');
# You can add multiple instances of the attribute/value to the packetr
# just like below.
$packet->set_vsattr(9, 'cisco-avpair', 'This is my VSA 2');
# At this point, you have a nice example packet. In order to use this
# packet, we must first "sign" it as the NAS would. This is done in
# this particular kind of packet with the help of the user-supplied
# password, as seen below.
$packet->set_attr('User-Password', 'My-Password');
# However the password must be protected by snooping. We do so using
# a 'shared-secret'. This is a secret password that is known only to
# this module and the NAS (as well as your network guys).
$packet->set_attr('User-Password', $packet->password('My-Shared-Secret'));
# Before the actual signing takes place, we must convert the object to
# an actual packet that can be sent through the network, like in this
# example.
my $p = $packet->pack;
# The final step in signing the packet is done below. $data will
# contain the definitive data that must be sent to the server. Note
# that the shared secret MUST be the same used to protect the password
# for authentication to occur.
my $data = auth_resp($p, 'My-Shared-Secret');
# After this, we can take a look at how our finished packed looks...
my $np = new Net::Radius::Packet $dict, $data;
$np->dump;
# The accompaining examples in this directory explain what to do at the
# server...