########################################### package Net::SSH::AuthorizedKey; ########################################### use base qw(Class::Accessor); __PACKAGE__->mk_accessors(qw(options key exponent keylen email type comment encryption)); use strict; use warnings; use Log::Log4perl qw(:easy); our $VERSION = "0.02"; our %VALID_KEYWORDS = ( command => "s", environment => "s", from => "s", permitopen => "s", tunnel => "n", "no-agent-forwarding" => 1, "no-port-forwarding" => 1, "no-pty" => 1, "no-x11-forwarding" => 1, ); our %VALID_SSH2_KEYWORDS = ( Command => "s", "Keyfilename.pub" => "s", Options => "s", PgpPublicKeyFile => "s", PgpKeyFingerprint => "s", PgpKeyId => "s", PgpKeyName => "s", ); ########################################### sub option_type { ########################################### my($self, $key, $value) = @_; if(exists $VALID_KEYWORDS{$key}) { return $VALID_KEYWORDS{$key}; } if($self->{type} eq "ssh-2" and exists $VALID_SSH2_KEYWORDS{$key}) { return $VALID_SSH2_KEYWORDS{$key}; } return undef; } ########################################### sub option { ########################################### my($self, $key, $value) = @_; $key = lc $key; my $option_type = $self->option_type($key); if(! defined $option_type) { LOGWARN "Illegal option '$key'"; return undef; } if(defined $value) { if($option_type eq "s") { $self->{options}->{$key} = $value; } else { $self->{options}->{$key} = undef; } } return $self->{options}->{$key}; } ########################################### sub option_delete { ########################################### my($self, $key) = @_; $key = lc $key; delete $self->{options}->{$key}; } ########################################### sub options_as_string { ########################################### my($self) = @_; my $string = ""; my @parts = (); for my $option ( keys %{ $self->{options} } ) { if(defined $self->{options}->{$option}) { if(ref($self->{options}->{$option}) eq "ARRAY") { for (@{ $self->{options}->{$option} }) { push @parts, option_quote($option, $_); } } else { push @parts, option_quote($option, $self->{options}->{$option}); } } else { push @parts, $option; } } return join(',', @parts); } ########################################### sub option_quote { ########################################### my($option, $text) = @_; $text =~ s/([\\"])/\\$1/g; return "$option=\"" . $text . "\""; } ########################################### package Net::SSH::AuthorizedKey::SSH1; ########################################### use base qw(Net::SSH::AuthorizedKey); ########################################### sub as_string { ########################################### my($self) = @_; my $string = $self->options_as_string(); $string .= " " if length $string; $string .= "$self->{keylen} $self->{exponent} $self->{key} $self->{email}"; return $string; } ########################################### package Net::SSH::AuthorizedKey::SSH2; ########################################### use base qw(Net::SSH::AuthorizedKey); ########################################### sub as_string { ########################################### my($self) = @_; my $string = $self->options_as_string(); $string .= " " if length $string; $string .= " $self->{encryption} $self->{key} $self->{email}"; return $string; } 1; __END__ =head1 NAME Net::SSH::AuthorizedKey - Holds a single line of the authorized_keys file =head1 SYNOPSIS use Net::SSH::AuthorizedKey; my $akf = Net::SSH::AuthorizedKey->new( options => { from => 'foo@bar.com', "no-agent-forwarding" }, key => "123....890", keylen => 1024, exponent => 35, type => "ssh-1", email => 'issuer@issuer.com', ); =head1 DESCRIPTION Net::SSH::AuthorizedKey objects holds key lines from ssh's authorized_keys files. They just provide getter/setter methods. =head1 METHODS =over 4 =item C