diff -urN RADIUS-1.0-dist/RADIUS/Packet.pm RADIUS-1.0/RADIUS/Packet.pm --- RADIUS-1.0-dist/RADIUS/Packet.pm Wed Aug 20 20:44:17 1997 +++ RADIUS-1.0/RADIUS/Packet.pm Thu Dec 3 14:11:32 1998 @@ -4,10 +4,10 @@ require Exporter; use vars qw($VERSION @ISA @EXPORT @EXPORT_OK); @ISA = qw(Exporter); -@EXPORT = qw(auth_resp); +@EXPORT = qw(auth_resp set_auth_resp); @EXPORT_OK = qw( ); -$VERSION = '1.0'; +$VERSION = '1.0.5'; use RADIUS::Dictionary; use Socket; @@ -41,22 +41,36 @@ sub attr { $_[0]->{Attributes}->{$_[1]}; } sub set_attr { $_[0]->{Attributes}->{$_[1]} = $_[2]; } -# Decode the password -sub password { - my ($self, $secret) = @_; - my $lastround = $self->authenticator; - my $pwdin = $self->attr("Password"); +# En/Decode the password +sub code_password { + my ($pwdin, $secret, $authenticator) = @_; + my $lastround = $authenticator; my $pwdout; + $pwdin .= "\000" x ((16 - length($pwdin)) % 16); for (my $i = 0; $i < length($pwdin); $i += 16) { $pwdout .= substr($pwdin, $i, 16) ^ MD5->hash($secret . $lastround); $lastround = substr($pwdin, $i, 16); } + return $pwdout; +} + +sub password { + my ($self, $secret) = @_; + my $pwdout = code_password ($self->attr("Password"), $secret, + $self->authenticator); $pwdout =~ s/\000*$//; return $pwdout; } -# Set response authenticator in binary packet +# Figure the response authenticator for a binary packet sub auth_resp { + my ($packet, $secret, $request_auth) = @_; + substr($packet, 4, 16) = $request_auth; + return MD5->hash ($packet . $secret); +} + +# Set response authenticator in binary packet +sub set_auth_resp { my $new = $_[0]; substr($new, 4, 16) = MD5->hash($_[0] . $_[1]); return $new; @@ -86,6 +100,7 @@ sub pack { my $self = shift; + my $secret = shift; my $hdrlen = 1 + 1 + 2 + 16; # Size of packet header my $p_hdr = "C C n a16 a*"; # Pack template for header my $p_attr = "C C a*"; # Pack template for attribute @@ -112,6 +127,12 @@ # Pack the attributes foreach my $attr ($self->attributes) { + # If a secret was provided and this is the password, hide the password + if ($secret && ($attr eq "Password")) { + $self->set_attr($attr, code_password ($self->attr($attr), $secret, + $self->authenticator)); + } + my $val = &{$packer{$self->{Dict}->attr_type($attr)}}($self->attr($attr), $self->{Dict}->attr_num($attr)); $attstr .= pack $p_attr, $self->{Dict}->attr_num($attr), length($val)+2, $val; @@ -189,7 +210,7 @@ $resp->set_identifier($p->identifier); $resp->set_authenticator($p->authenticator); $resp->set_attr('Reply-Message') = "Welcome, Larry!\r\n"; - my $respdat = auth_resp($resp->pack, "mysecret"); + my $respdat = set_auth_resp($resp->pack, "mysecret"); ... =head1 DESCRIPTION @@ -298,7 +319,12 @@ =over 4 -=item I($packed_packet, $secret) +=item I($packed_packet, $secret, $request_auth) + +Given a (packed) RADIUS packet, a shared secret, and the Authenticator from +a request packet, returns the Response Authenticator. + +=item I($packed_packet, $secret) Given a (packed) RADIUS packet and a shared secret, returns a new packet with the Authenticator field changed in accordace with RADIUS @@ -320,7 +346,7 @@ Copy the Identifier and Authenticator fields from the request, set the Code as appropriate, and fill in whatever Attributes you wish to convey in to the server. - 5. Call the pack method and use the auth_resp function to + 5. Call the pack method and use the set_auth_resp function to authenticate it with your shared secret. 6. Send the response back over the network. 7. Lather, rinse, repeat. @@ -373,7 +399,7 @@ $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); + $s->sendto(set_auth_resp($rp->pack, $secret), $whence); } else { # It's not an Access-Request