home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2004 December / PCpro_2004_12.ISO / files / webserver / tsw / TSW_3.4.0.exe / Apache2 / perl / AuthMgr.pm < prev    next >
Encoding:
Perl POD Document  |  2003-12-03  |  4.8 KB  |  182 lines

  1. # $Id: AuthMgr.pm,v 1.6 2003/12/03 15:35:21 autarch Exp $
  2.  
  3. package Net::SSH::Perl::AuthMgr;
  4. use strict;
  5.  
  6. use Carp qw( croak );
  7.  
  8. use Net::SSH::Perl::Agent;
  9. use Net::SSH::Perl::Auth;
  10. use Net::SSH::Perl::Constants qw(
  11.     SSH2_MSG_SERVICE_REQUEST
  12.     SSH2_MSG_SERVICE_ACCEPT
  13.     SSH2_MSG_USERAUTH_BANNER
  14.     SSH2_MSG_USERAUTH_REQUEST
  15.     SSH2_MSG_USERAUTH_SUCCESS
  16.     SSH2_MSG_USERAUTH_FAILURE );
  17.  
  18. use Scalar::Util qw(weaken);
  19.  
  20. use vars qw( %AUTH_MAP );
  21. %AUTH_MAP = ( password => 'Password',
  22.               publickey => 'PublicKey',
  23.              'keyboard-interactive' => 'KeyboardInt' );
  24.  
  25. sub new {
  26.     my $class = shift;
  27.     my $ssh = shift;
  28.     my $amgr = bless { ssh => $ssh }, $class;
  29.     weaken $amgr->{ssh};
  30.     $amgr->init(@_);
  31. }
  32.  
  33. sub init {
  34.     my $amgr = shift;
  35.     my $ssh = $amgr->{ssh};
  36.     my($packet);
  37.  
  38.     $ssh->debug("Sending request for user-authentication service.");
  39.     $packet = $ssh->packet_start(SSH2_MSG_SERVICE_REQUEST);
  40.     $packet->put_str("ssh-userauth");
  41.     $packet->send;
  42.  
  43.     $packet = Net::SSH::Perl::Packet->read($ssh);
  44.     croak "Server denied SSH2_MSG_SERVICE_ACCEPT: ", $packet->type
  45.         unless $packet->type == SSH2_MSG_SERVICE_ACCEPT;
  46.     $ssh->debug("Service accepted: " . $packet->get_str . ".");
  47.  
  48.     $amgr->{agent} = Net::SSH::Perl::Agent->new(2);
  49.     $amgr->{service} = "ssh-connection";
  50.  
  51.     $amgr->send_auth_none;
  52.  
  53.     $amgr;
  54. }
  55.  
  56. sub agent { $_[0]->{agent} }
  57.  
  58. sub send_auth_none {
  59.     my $amgr = shift;
  60.     my $ssh = $amgr->{ssh};
  61.     $ssh->debug("Trying empty user-authentication request.");
  62.     my $packet = $ssh->packet_start(SSH2_MSG_USERAUTH_REQUEST);
  63.     $packet->put_str($ssh->config->get('user'));
  64.     $packet->put_str("ssh-connection");
  65.     $packet->put_str("none");
  66.     $packet->send;
  67. }
  68.  
  69. sub authenticate {
  70.     my $amgr = shift;
  71.     my $ssh = $amgr->{ssh};
  72.     my($packet);
  73.  
  74.     my $valid = 0;
  75.     $amgr->{_done} = 0;
  76.     $amgr->register_handler(SSH2_MSG_USERAUTH_SUCCESS, sub {
  77.         $valid++;
  78.         $amgr->{_done}++
  79.     });
  80.     $amgr->register_handler(SSH2_MSG_USERAUTH_BANNER, sub {
  81.         my $amgr = shift;
  82.         my($packet) = @_;
  83.         if ($amgr->{ssh}->config->get('interactive')) {
  84.             print $packet->get_str, "\n";
  85.         }
  86.     });
  87.     $amgr->register_handler(SSH2_MSG_USERAUTH_FAILURE, \&auth_failure);
  88.     $amgr->register_error(
  89.         sub { croak "userauth error: bad message during auth" } );
  90.     $amgr->run( \$amgr->{_done} );
  91.  
  92.     $amgr->{agent}->close_socket if $amgr->{agent};
  93.  
  94.     $valid;
  95. }
  96.  
  97. sub auth_failure {
  98.     my $amgr = shift;
  99.     my($packet) = @_;
  100.     my $ssh = $amgr->{ssh};
  101.  
  102.     my $authlist = $packet->get_str;
  103.     my $partial = $packet->get_int8;
  104.     $ssh->debug("Authentication methods that can continue: $authlist.");
  105.  
  106.     my($found);
  107.     for my $meth ( split /,/, $authlist ) {
  108.         $found = 0;
  109.         next if !exists $AUTH_MAP{$meth};
  110.         my $auth = $amgr->{_auth_objects}{$meth};
  111.         unless ($auth) {
  112.             $auth = $amgr->{_auth_objects}{$meth} =
  113.                 Net::SSH::Perl::Auth->new($AUTH_MAP{$meth}, $ssh);
  114.             $auth->mgr($amgr);
  115.         }
  116.         next unless $auth->enabled;
  117.         $ssh->debug("Next method to try is $meth.");
  118.         $found++;
  119.         if ($auth->authenticate($amgr->{_auth_tried}{$meth}++)) {
  120.             last;
  121.         }
  122.         else {
  123.             $auth->enabled(0);
  124.             delete $amgr->{_auth_objects}{$meth};
  125.             $found = 0;
  126.         }
  127.     }
  128.  
  129.     $amgr->{_done} = 1 unless $found;
  130. }
  131.  
  132. sub register_handler { $_[0]->{__handlers}{$_[1]} = $_[2] }
  133. sub remove_handler { delete $_[0]->{__handlers}{$_[1]} }
  134. sub register_error { $_[0]->{__error_handler} = $_[1] }
  135. sub handler_for { $_[0]->{__handlers}{$_[1]} }
  136. sub error_handler { $_[0]->{__error_handler} }
  137.  
  138. sub run {
  139.     my $amgr = shift;
  140.     my($end, @args) = @_;
  141.     until ($$end) {
  142.         my $packet = Net::SSH::Perl::Packet->read($amgr->{ssh});
  143.         my $code = $amgr->handler_for($packet->type);
  144.         unless (defined $code) {
  145.             $code = $amgr->error_handler ||
  146.                 sub { croak "Protocol error: received type ", $packet->type };
  147.         }
  148.         $code->($amgr, $packet, @args);
  149.     }
  150. }
  151.  
  152. 1;
  153. __END__
  154.  
  155. =head1 NAME
  156.  
  157. Net::SSH::Perl::AuthMgr - Authentication manager/context for SSH-2
  158.  
  159. =head1 SYNOPSIS
  160.  
  161.     use Net::SSH::Perl::AuthMgr;
  162.     my $amgr = Net::SSH::Perl::AuthMgr->new($ssh);
  163.     $amgr->authenticate;
  164.  
  165. =head1 DESCRIPTION
  166.  
  167. I<Net::SSH::Perl::AuthMgr> manages authentication methods and auth
  168. context for the SSH-2 authentication process. At its heart is a
  169. dispatch mechanism that waits for incoming packets and responds as
  170. necessary, based on a handler table that maps packet types to
  171. code references.
  172.  
  173. You should never need to use I<AuthMgr> directly, as it will be
  174. automatically invoked when you call I<login>.
  175.  
  176. =head1 AUTHOR & COPYRIGHTS
  177.  
  178. Please see the Net::SSH::Perl manpage for author, copyright,
  179. and license information.
  180.  
  181. =cut
  182.