Imported Upstream version 2.103+dfsg
This commit is contained in:
191
examples/example-client.pl
Normal file
191
examples/example-client.pl
Normal 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
124
examples/example-menu.pl
Normal 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
84
examples/example-unix.pl
Normal 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
58
examples/example-yes.pl
Normal 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
142
examples/radius2ldap.pl
Normal 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
104
examples/tutorial.pl
Normal 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...
|
||||
Reference in New Issue
Block a user