Initial Commit

This commit is contained in:
Riley Schneider
2025-12-03 16:38:10 +01:00
parent c5e26bf594
commit b732d8d4b5
17680 changed files with 5977495 additions and 2 deletions

View File

@@ -0,0 +1,563 @@
package Net::SSH2::Channel;
use strict;
use warnings;
use Carp;
# methods
sub shell {
$_[0]->process('shell')
}
sub exec {
$_[0]->process(exec => $_[1])
}
sub subsystem {
$_[0]->process(subsystem => $_[1])
}
sub error {
shift->session->error(@_)
}
sub blocking {
shift->session->blocking(@_)
}
sub setenv {
my ($self, %env) = @_;
my $rc = 1;
while (my ($k, $v) = each %env) {
$self->_setenv($k, $v)
or undef $rc;
}
$rc
}
sub read1 {
my $self = shift;
my $buffer;
my $rc = $self->read($buffer, @_);
return (defined $rc ? $buffer : undef);
}
sub read2 {
my ($self, $max_size) = @_;
$max_size = 32678 unless defined $max_size;
my $ssh2 = $self->session;
my $old_blocking = $ssh2->blocking;
my $timeout = $ssh2->timeout;
my $delay = (($timeout and $timeout < 2000) ? 0.0005 * $timeout : 1);
my $deadline;
$deadline = time + 1 + 0.001 * $timeout if $timeout;
$ssh2->blocking(0);
while (1) {
my @out;
my $bytes;
my $fail;
my $zero;
for (0, 1) {
my $rc = $self->read($out[$_], $max_size, $_);
if (defined $rc) {
$rc or $zero++;
$bytes += $rc;
$deadline = time + 1 + 0.001 * $timeout if $timeout;
}
else {
$out[$_] = '';
if ($ssh2->error != Net::SSH2::LIBSSH2_ERROR_EAGAIN()) {
$fail++;
last;
}
}
}
if ($bytes) {
$ssh2->blocking($old_blocking);
return (wantarray ? @out : $out[0])
}
my $eof = $self->eof;
if ($fail or $eof) {
$ssh2->_set_error if $eof;
$ssh2->blocking($old_blocking);
return;
}
unless ($zero) {
return unless $old_blocking;
if ($deadline and time > $deadline) {
$ssh2->_set_error(Net::SSH2::LIBSSH2_ERROR_TIMEOUT(), "Time out waiting for data");
return;
}
my $sock = $ssh2->sock;
my $fn = fileno($sock);
my ($rbm, $wbm) = ('', '');
my $bd = $ssh2->block_directions;
vec($rbm, $fn, 1) = 1 if $bd & Net::SSH2::LIBSSH2_SESSION_BLOCK_INBOUND();
vec($wbm, $fn, 1) = 1 if $bd & Net::SSH2::LIBSSH2_SESSION_BLOCK_OUTBOUND();
select $rbm, $wbm, undef, $delay;
}
}
}
my $readline_non_blocking_warned;
sub readline {
my ($self, $ext, $eol) = @_;
return if $self->eof;
$ext ||= 0;
$eol = $/ unless @_ >= 3;
$self->blocking or $readline_non_blocking_warned++ or
warnings::warnif('Net::SSH2',
"Calling Net::SSH2::Channel::readline in non-blocking mode is usually a programming error");
if (wantarray or not defined $eol) {
my $data = '';
my $buffer;
while (1) {
my $bytes = $self->read($buffer, 32768, $ext);
last unless defined $bytes;
if (!$bytes and $self->eof) {
$self->session->_set_error(Net::SSH2::LIBSSH2_ERROR_NONE());
last;
}
$data .= $buffer;
}
defined $eol and return split /(?<=\Q$eol\E)/s, $data;
wantarray and not length $data and return ();
return $data;
}
else {
my $c;
my $data = '';
while (1) {
$c = $self->getc($ext);
last unless defined $c;
$data .= $c;
if ( (!length($c) and $self->eof) or
$data =~ /\Q$eol\E\z/) {
$self->session->_set_error(Net::SSH2::LIBSSH2_ERROR_NONE());
last;
}
}
return (length $data ? $data : undef);
}
}
sub wait_closed {
my $self = shift;
if ($self->wait_eof) {
$self->flush('all');
return $self->_wait_closed;
}
undef;
}
sub exit_status {
my $self = shift;
return unless $self->wait_closed;
return $self->_exit_status;
}
sub exit_signal {
my $self = shift;
return unless $self->wait_closed;
return $self->_exit_signal;
}
my %signal_number;
sub exit_signal_number {
my $self = shift;
my $signal = $self->exit_signal;
return unless defined $signal;
return 0 unless $signal;
unless (%signal_number) {
require Config;
my @names = split /\s+/, $Config::Config{sig_name};
@signal_number{@names} = 0..$#names;
}
$signal =~ s/\@\.[^\.]+\.config\.guess$//;
my $number = $signal_number{$signal};
$number = 255 unless defined $number;
return $number;
}
my %pty_modes = (TTY_OP_END => 0, VINTR => 1, VQUIT => 2, VERASE => 3, VKILL => 4, VEOF => 5,
VEOL => 6, VEOL2 => 7, VSTART => 8, VSTOP => 9, VSUSP => 10, VDSUSP => 11,
VREPRINT => 12, VWERASE => 13, VLNEXT => 14, VFLUSH => 15, VSWTCH => 16, VSTATUS => 17,
VDISCARD => 18, IGNPAR => 30, PARMRK => 31, INPCK => 32, ISTRIP => 33, INLCR => 34,
IGNCR => 35, ICRNL => 36, IUCLC => 37, IXON => 38, IXANY => 39, IXOFF => 40,
IMAXBEL => 41, ISIG => 50, ICANON => 51, XCASE => 52, ECHO => 53, ECHOE => 54,
ECHOK => 55, ECHONL => 56, NOFLSH => 57, TOSTOP => 58, IEXTEN => 59, ECHOCTL => 60,
ECHOKE => 61, PENDIN => 62, OPOST => 70, OLCUC => 71, ONLCR => 72, OCRNL => 73,
ONOCR => 74, ONLRET => 75, CS7 => 90, CS8 => 91, PARENB => 92, PARODD => 93,
TTY_OP_ISPEED => 128, TTY_OP_OSPEED => 129);
sub pty {
my $self = shift;
if (defined $_[1] and ref $_[1] eq 'HASH') {
my $term = shift;
my $modes = shift;
my $packed = '';
while (my ($k, $v) = each %$modes) {
unless ($k =~ /^\d+$/) {
my $k1 = $pty_modes{uc $k};
defined $k1 or croak "Invalid pty mode key '$k'";
$k = $k1;
}
next if $k == 0; # ignore the TTY_OP_END marker
$k > 159 and croak "Invalid pty mode key '$k'";
$packed .= pack CN => $k, $v;
}
$self->_pty($term, "$packed\x00", @_);
}
else {
$self->_pty(@_);
}
}
# tie interface
sub PRINT {
my $self = shift;
my $sep = defined($,) ? $, : '';
$self->write(join $sep, @_)
}
sub PRINTF {
my $self = shift;
my $template = shift;
$self->write(sprintf $template, @_);
}
sub WRITE {
my ($self, $buf, $len, $offset) = @_;
$self->write(substr($buf, $offset || 0, $len))
}
sub READLINE { shift->readline(0, $/) }
sub READ {
my ($self, undef, $len, $offset) = @_;
my $bytes = $self->read(my($buffer), $len);
substr($_[1], $offset || 0) = $buffer
if defined $bytes;
return $bytes;
}
sub BINMODE { 1 }
sub CLOSE {
my $self = shift;
my $ob = $self->blocking;
$self->blocking(1);
my $rc = undef;
if ($self->close and
$self->wait_closed) {
my $status = $self->exit_status;
my $signal = $self->exit_signal_number;
$self->session->_set_error;
$? = ($status << 8) | $signal;
$rc = 1 if $? == 0;
}
$self->blocking($ob);
$rc;
}
sub EOF {
my $self = shift;
$self->eof;
}
*GETC = \&getc;
1;
__END__
=head1 NAME
Net::SSH2::Channel - SSH2 channel object
=head1 SYNOPSIS
my $chan = $ssh2->channel()
or $ssh2->die_with_error;
$chan->exec("ls -ld /usr/local/libssh2*")
or $ssh2->die_with_error;
$chan->send_eof;
while (<$chan>) {
print "line read: $_";
}
print "exit status: " . $chan->exit_status . "\n";
=head1 DESCRIPTION
A channel object is created by the L<Net::SSH2> C<channel> method. As well
as being an object, it is also a tied filehandle.
=head2 setenv ( key, value ... )
Sets remote environment variables. Note that most servers do not allow
environment variables to be freely set.
Pass in a list of keys and values with the values to set.
It returns a true value if all the given environment variables were
correctly set.
=head2 blocking ( flag )
Enable or disable blocking.
Note that this is currently implemented in libssh2 by setting a
per-session flag. It's equivalent to L<Net::SSH2::blocking>.
=head2 eof
Returns true if the remote server sent an EOF.
=head2 send_eof
Sends an EOF to the remote side.
After an EOF has been sent, no more data may be
sent to the remote process C<STDIN> channel.
Note that if a PTY was requested for the channel, the EOF may be
ignored by the remote server. See L</pty>.
=head2 close
Close the channel (happens automatically on object destruction).
=head2 wait_closed
Wait for a remote close event.
In order to avoid a bug in libssh2 this method discards any unread
data queued in the channel.
=head2 exit_status
Returns the channel's program exit status.
This method blocks until the remote side closes the channel.
=head2 pty ( terminal [, modes [, width [, height ]]] )
Request a terminal on a channel.
C<terminal> is the type of emulation (e.g. vt102, ansi,
etc...).
C<modes> are the terminal mode modifiers, for instance:
$c->pty('vt100', { echo => 0, vintr => ord('k') });
The list of acceptable mode modifiers is available from the SSH Connection
Protocol RFC (L<RFC4254|https://tools.ietf.org/html/rfc4254#section-8>).
If provided, C<width> and C<height> are the width and height in
characters (defaults to 80x24); if negative their absolute values
specify width and height in pixels.
=head2 pty_size ( width, height )
Request a terminal size change on a channel. C<width> and C<height> are the
width and height in characters; if negative their absolute values specify
width and height in pixels.
=head2 ext_data ( mode )
Set extended data handling mode:
=over 4
=item normal (default)
Keep data in separate channels; C<STDERR> is read separately.
=item ignore
Ignore all extended data.
=item merge
Merge into the regular channel.
=back
=head2 process ( request, message )
Start a process on the channel. See also L<shell>, L<exec>, L<subsystem>.
Note that only one invocation of C<process> or any of the shortcuts
C<shell>, C<exec> or C<subsystem> is allowed per channel. In order to
run several commands, shells or/and subsystems, a new C<Channel>
instance must be used for every one.
Alternatively, it is also possible to launch a remote shell (using
L<shell>) and simulate the user interaction printing commands to its
C<stdin> stream and reading data back from its C<stdout> and
C<stderr>. But this approach should be avoided if possible; talking to
a shell is difficult and, in general, unreliable.
=head2 shell
Start a shell on the remote host (calls C<process("shell")>).
=head2 exec ( command )
Execute the command on the remote host (calls C<process("exec", command)>).
Note that the given command is parsed by the remote shell; it should
be properly quoted, specially when passing data from untrusted sources.
=head2 subsystem ( name )
Run subsystem on the remote host (calls C<process("subsystem", name)>).
=head2 read ( buffer, max_size [, ext ] )
Attempts to read up to C<max_size> bytes from the channel into C<buffer>. If
C<ext> is true, reads from the extended data channel (C<STDERR>).
The method returns as soon as some data is available, even if the
given size has not been reached.
Returns number of bytes read or C<undef> on failure. Note that 0 is a
valid return code.
=head2 read2 ( [max_size] )
Attempts to read from both the ordinary (stdout) and the extended
(stderr) channel streams.
Returns two scalars with the data read both from stdout and stderr. It
returns as soon as some data is available and any of the returned
values may be an empty string.
When some error happens it returns the empty list.
Example:
my ($out, $err) = ('', '');
while (!$channel->eof) {
if (my ($o, $e) = $channel->read2) {
$out .= $o;
$err .= $e;
}
else {
$ssh2->die_with_error;
}
}
print "STDOUT:\n$out\nSTDERR:\n$err\n";
=head2 readline ( [ext [, eol ] ] )
Reads the next line from the selected stream (C<ext> defaults to 0:
stdout).
C<$/> is used as the end of line marker when C<eol> is C<undef>.
In list context reads and returns all the remaining lines until some
read error happens or the remote side sends an eof.
Note that this method is only safe when the complementary stream
(e.g. C<!ext>) is guaranteed to not generate data or when L</ext_data>
has been used to discard or merge it; otherwise it may hang. This is a
limitation of libssh2 that hopefully would be removed in a future
release, in the meantime you are advised to use L<read2> instead.
=head2 getc( [ext] )
Reads and returns the next character from the selected stream.
Returns C<undef> on error.
Note that due to some libssh2 quirks, the return value can be the
empty string which may indicate an EOF condition (but not
always!). See L</eof>.
=head2 write ( buffer )
Send the data in C<buffer> through the channel. Returns number of
bytes written, undef on failure.
In versions of this module prior to 0.57, when working in non-blocking
mode, the would-block condition was signaled by returning
C<LIBSSH2_ERROR_EAGAIN> (a negative number) while leaving the session
error status unset. From version 0.59, C<undef> is returned and the
session error status is set to C<LIBSSH2_ERROR_EAGAIN> as for any
other error.
In non-blocking mode, if C<write> fails with a C<LIBSSH2_ERROR_EAGAIN>
error, no other operation must be invoked over any object in the same
SSH session besides L</sock> and L<blocking_directions>.
Once the socket becomes ready again, the exact same former C<write>
call, with exactly the same arguments must be invoked.
Failing to do that would result in a corrupted SSH session. This is a
limitation in libssh2.
=head2 flush ( [ ext ] )
Discards the received but still unread data on the channel; if C<ext>
is present and set, discards data on the extended channel. Returns
number of bytes discarded, C<undef> on error.
=head2 exit_signal
Returns the name of exit signal from the remote command.
In list context returns also the error message and a language tag,
though as of libssh2 1.7.0, those values are always undef.
This method blocks until the remote side closes the channel.
=head2 exit_signal_number
Converts the signal name to a signal number using the local mapping
(which may be different to the remote one if the operating systems
differ).
=head2 window_read
Returns the number of bytes which the remote end may send without
overflowing the window limit.
In list context it also returns the number of bytes that are
immediately available for read and the size of the initial window.
=head2 window_write
Returns the number of bytes which may be safely written to the channel
without blocking at the SSH level. In list context it also returns the
size of the initial window.
Note that this method doesn't take into account the TCP connection
being used under the hood. Getting a positive integer back from this
method does not guarantee that such number of bytes could be written
to the channel without blocking the TCP connection.
=head2 receive_window_adjust (adjustment [, force])
Adjust the channel receive window by the given C<adjustment> bytes.
If the amount to be adjusted is less than C<LIBSSH2_CHANNEL_MINADJUST>
and force is false the adjustment amount will be queued for a later
packet.
On success returns the new size of the receive window. On failure it
returns C<undef>.
=head1 SEE ALSO
L<Net::SSH2>.
=cut

View File

@@ -0,0 +1,32 @@
package
Net::SSH2::Constants;
# This file is generated automatically by util/gen_constants.pl
sub import { die "Do not use Net::SSH2::Constants!"; }
package
Net::SSH2;
use strict;
use warnings;
use base 'Exporter';
our @EXPORT_OK = qw(LIBSSH2_CALLBACK_DEBUG LIBSSH2_CALLBACK_DISCONNECT LIBSSH2_CALLBACK_IGNORE LIBSSH2_CALLBACK_MACERROR LIBSSH2_CALLBACK_X11 LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL SSH_EXTENDED_DATA_STDERR LIBSSH2_EXTENDED_DATA_STDERR LIBSSH2_CHANNEL_FLUSH_ALL LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA LIBSSH2_CHANNEL_FLUSH_STDERR LIBSSH2_CHANNEL_MINADJUST LIBSSH2_CHANNEL_PACKET_DEFAULT LIBSSH2_CHANNEL_WINDOW_DEFAULT LIBSSH2_DH_GEX_MAXGROUP LIBSSH2_DH_GEX_MINGROUP LIBSSH2_DH_GEX_OPTGROUP LIBSSH2_ERROR_ALLOC LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_NONE LIBSSH2_ERROR_BANNER_SEND LIBSSH2_ERROR_CHANNEL_CLOSED LIBSSH2_ERROR_CHANNEL_EOF_SENT LIBSSH2_ERROR_CHANNEL_FAILURE LIBSSH2_ERROR_CHANNEL_OUTOFORDER LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED LIBSSH2_ERROR_CHANNEL_UNKNOWN LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED LIBSSH2_ERROR_DECRYPT LIBSSH2_ERROR_FILE LIBSSH2_ERROR_HOSTKEY_INIT LIBSSH2_ERROR_HOSTKEY_SIGN LIBSSH2_ERROR_INVAL LIBSSH2_ERROR_INVALID_MAC LIBSSH2_ERROR_INVALID_POLL_TYPE LIBSSH2_ERROR_KEX_FAILURE LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE LIBSSH2_ERROR_METHOD_NONE LIBSSH2_ERROR_METHOD_NOT_SUPPORTED LIBSSH2_ERROR_PASSWORD_EXPIRED LIBSSH2_ERROR_PROTO LIBSSH2_ERROR_AUTHENTICATION_FAILED LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED LIBSSH2_ERROR_REQUEST_DENIED LIBSSH2_ERROR_SCP_PROTOCOL LIBSSH2_ERROR_PUBLICKEY_PROTOCOL LIBSSH2_ERROR_SFTP_PROTOCOL LIBSSH2_ERROR_SOCKET_DISCONNECT LIBSSH2_ERROR_SOCKET_NONE LIBSSH2_ERROR_SOCKET_SEND LIBSSH2_ERROR_SOCKET_TIMEOUT LIBSSH2_ERROR_TIMEOUT LIBSSH2_ERROR_ZLIB LIBSSH2_ERROR_KNOWN_HOSTS LIBSSH2_FLAG_SIGPIPE LIBSSH2_FLAG_COMPRESS LIBSSH2_FXF_APPEND LIBSSH2_ERROR_EAGAIN LIBSSH2_SESSION_BLOCK_INBOUND LIBSSH2_SESSION_BLOCK_OUTBOUND LIBSSH2_TRACE_TRANS LIBSSH2_TRACE_KEX LIBSSH2_TRACE_AUTH LIBSSH2_TRACE_CONN LIBSSH2_TRACE_SCP LIBSSH2_TRACE_SFTP LIBSSH2_TRACE_ERROR LIBSSH2_TRACE_PUBLICKEY LIBSSH2_TRACE_SOCKET LIBSSH2_FXF_CREAT LIBSSH2_FXF_EXCL LIBSSH2_FXF_READ LIBSSH2_FXF_TRUNC LIBSSH2_FXF_WRITE LIBSSH2_FX_BAD_MESSAGE LIBSSH2_FX_CONNECTION_LOST LIBSSH2_FX_DIR_NOT_EMPTY LIBSSH2_FX_EOF LIBSSH2_FX_FAILURE LIBSSH2_FX_FILE_ALREADY_EXISTS LIBSSH2_FX_INVALID_FILENAME LIBSSH2_FX_INVALID_HANDLE LIBSSH2_FX_LINK_LOOP LIBSSH2_FX_LOCK_CONFlICT LIBSSH2_FX_NOT_A_DIRECTORY LIBSSH2_FX_NO_CONNECTION LIBSSH2_FX_NO_MEDIA LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM LIBSSH2_FX_NO_SUCH_FILE LIBSSH2_FX_NO_SUCH_PATH LIBSSH2_FX_OK LIBSSH2_FX_OP_UNSUPPORTED LIBSSH2_FX_PERMISSION_DENIED LIBSSH2_FX_QUOTA_EXCEEDED LIBSSH2_FX_UNKNOWN_PRINCIPLE LIBSSH2_FX_WRITE_PROTECT LIBSSH2_H LIBSSH2_HOSTKEY_HASH_MD5 LIBSSH2_HOSTKEY_HASH_SHA1 LIBSSH2_METHOD_COMP_CS LIBSSH2_METHOD_COMP_SC LIBSSH2_METHOD_CRYPT_CS LIBSSH2_METHOD_CRYPT_SC LIBSSH2_METHOD_HOSTKEY LIBSSH2_METHOD_KEX LIBSSH2_METHOD_LANG_CS LIBSSH2_METHOD_LANG_SC LIBSSH2_METHOD_MAC_CS LIBSSH2_METHOD_MAC_SC LIBSSH2_PACKET_MAXCOMP LIBSSH2_PACKET_MAXDECOMP LIBSSH2_PACKET_MAXPAYLOAD LIBSSH2_POLLFD_CHANNEL LIBSSH2_POLLFD_CHANNEL_CLOSED LIBSSH2_POLLFD_LISTENER LIBSSH2_POLLFD_LISTENER_CLOSED LIBSSH2_POLLFD_POLLERR LIBSSH2_POLLFD_POLLEX LIBSSH2_POLLFD_POLLEXT LIBSSH2_POLLFD_POLLHUP LIBSSH2_POLLFD_POLLIN LIBSSH2_POLLFD_POLLNVAL LIBSSH2_POLLFD_POLLOUT LIBSSH2_POLLFD_POLLPRI LIBSSH2_POLLFD_SESSION_CLOSED LIBSSH2_POLLFD_SOCKET LIBSSH2_SFTP_ATTR_ACMODTIME LIBSSH2_SFTP_ATTR_EXTENDED LIBSSH2_SFTP_ATTR_PERMISSIONS LIBSSH2_SFTP_ATTR_SIZE LIBSSH2_SFTP_ATTR_UIDGID LIBSSH2_SFTP_LSTAT LIBSSH2_SFTP_OPENDIR LIBSSH2_SFTP_OPENFILE LIBSSH2_SFTP_PACKET_MAXLEN LIBSSH2_SFTP_READLINK LIBSSH2_SFTP_REALPATH LIBSSH2_SFTP_RENAME_ATOMIC LIBSSH2_SFTP_RENAME_NATIVE LIBSSH2_SFTP_RENAME_OVERWRITE LIBSSH2_SFTP_SETSTAT LIBSSH2_SFTP_STAT LIBSSH2_SFTP_SYMLINK LIBSSH2_SFTP_TYPE_BLOCK_DEVICE LIBSSH2_SFTP_TYPE_CHAR_DEVICE LIBSSH2_SFTP_TYPE_DIRECTORY LIBSSH2_SFTP_TYPE_FIFO LIBSSH2_SFTP_TYPE_REGULAR LIBSSH2_SFTP_TYPE_SOCKET LIBSSH2_SFTP_TYPE_SPECIAL LIBSSH2_SFTP_TYPE_SYMLINK LIBSSH2_SFTP_TYPE_UNKNOWN LIBSSH2_SFTP_VERSION LIBSSH2_SOCKET_POLL_MAXLOOPS LIBSSH2_SOCKET_POLL_UDELAY LIBSSH2_TERM_HEIGHT LIBSSH2_TERM_HEIGHT_PX LIBSSH2_TERM_WIDTH LIBSSH2_TERM_WIDTH_PX LIBSSH2_KNOWNHOST_TYPE_MASK LIBSSH2_KNOWNHOST_TYPE_PLAIN LIBSSH2_KNOWNHOST_TYPE_SHA1 LIBSSH2_KNOWNHOST_TYPE_CUSTOM LIBSSH2_KNOWNHOST_KEYENC_MASK LIBSSH2_KNOWNHOST_KEYENC_RAW LIBSSH2_KNOWNHOST_KEYENC_BASE64 LIBSSH2_KNOWNHOST_KEY_MASK LIBSSH2_KNOWNHOST_KEY_SHIFT LIBSSH2_KNOWNHOST_KEY_RSA1 LIBSSH2_KNOWNHOST_KEY_SSHRSA LIBSSH2_KNOWNHOST_KEY_SSHDSS LIBSSH2_KNOWNHOST_CHECK_MATCH LIBSSH2_KNOWNHOST_CHECK_MISMATCH LIBSSH2_KNOWNHOST_CHECK_NOTFOUND LIBSSH2_KNOWNHOST_CHECK_FAILURE LIBSSH2_HOSTKEY_POLICY_STRICT LIBSSH2_HOSTKEY_POLICY_ASK LIBSSH2_HOSTKEY_POLICY_TOFU LIBSSH2_HOSTKEY_POLICY_ADVISORY);
our %EXPORT_TAGS = (
all => \@EXPORT_OK,
callback => [qw(LIBSSH2_CALLBACK_DEBUG LIBSSH2_CALLBACK_DISCONNECT LIBSSH2_CALLBACK_IGNORE LIBSSH2_CALLBACK_MACERROR LIBSSH2_CALLBACK_X11)],
channel => [qw(LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL LIBSSH2_CHANNEL_FLUSH_ALL LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA LIBSSH2_CHANNEL_FLUSH_STDERR LIBSSH2_CHANNEL_MINADJUST LIBSSH2_CHANNEL_PACKET_DEFAULT LIBSSH2_CHANNEL_WINDOW_DEFAULT)],
error => [qw(LIBSSH2_ERROR_ALLOC LIBSSH2_ERROR_BANNER_NONE LIBSSH2_ERROR_NONE LIBSSH2_ERROR_BANNER_SEND LIBSSH2_ERROR_CHANNEL_CLOSED LIBSSH2_ERROR_CHANNEL_EOF_SENT LIBSSH2_ERROR_CHANNEL_FAILURE LIBSSH2_ERROR_CHANNEL_OUTOFORDER LIBSSH2_ERROR_CHANNEL_PACKET_EXCEEDED LIBSSH2_ERROR_CHANNEL_REQUEST_DENIED LIBSSH2_ERROR_CHANNEL_UNKNOWN LIBSSH2_ERROR_CHANNEL_WINDOW_EXCEEDED LIBSSH2_ERROR_DECRYPT LIBSSH2_ERROR_FILE LIBSSH2_ERROR_HOSTKEY_INIT LIBSSH2_ERROR_HOSTKEY_SIGN LIBSSH2_ERROR_INVAL LIBSSH2_ERROR_INVALID_MAC LIBSSH2_ERROR_INVALID_POLL_TYPE LIBSSH2_ERROR_KEX_FAILURE LIBSSH2_ERROR_KEY_EXCHANGE_FAILURE LIBSSH2_ERROR_METHOD_NONE LIBSSH2_ERROR_METHOD_NOT_SUPPORTED LIBSSH2_ERROR_PASSWORD_EXPIRED LIBSSH2_ERROR_PROTO LIBSSH2_ERROR_AUTHENTICATION_FAILED LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED LIBSSH2_ERROR_REQUEST_DENIED LIBSSH2_ERROR_SCP_PROTOCOL LIBSSH2_ERROR_PUBLICKEY_PROTOCOL LIBSSH2_ERROR_SFTP_PROTOCOL LIBSSH2_ERROR_SOCKET_DISCONNECT LIBSSH2_ERROR_SOCKET_NONE LIBSSH2_ERROR_SOCKET_SEND LIBSSH2_ERROR_SOCKET_TIMEOUT LIBSSH2_ERROR_TIMEOUT LIBSSH2_ERROR_ZLIB LIBSSH2_ERROR_KNOWN_HOSTS LIBSSH2_ERROR_EAGAIN)],
fx => [qw(LIBSSH2_FX_BAD_MESSAGE LIBSSH2_FX_CONNECTION_LOST LIBSSH2_FX_DIR_NOT_EMPTY LIBSSH2_FX_EOF LIBSSH2_FX_FAILURE LIBSSH2_FX_FILE_ALREADY_EXISTS LIBSSH2_FX_INVALID_FILENAME LIBSSH2_FX_INVALID_HANDLE LIBSSH2_FX_LINK_LOOP LIBSSH2_FX_LOCK_CONFlICT LIBSSH2_FX_NOT_A_DIRECTORY LIBSSH2_FX_NO_CONNECTION LIBSSH2_FX_NO_MEDIA LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM LIBSSH2_FX_NO_SUCH_FILE LIBSSH2_FX_NO_SUCH_PATH LIBSSH2_FX_OK LIBSSH2_FX_OP_UNSUPPORTED LIBSSH2_FX_PERMISSION_DENIED LIBSSH2_FX_QUOTA_EXCEEDED LIBSSH2_FX_UNKNOWN_PRINCIPLE LIBSSH2_FX_WRITE_PROTECT)],
fxf => [qw(LIBSSH2_FXF_APPEND LIBSSH2_FXF_CREAT LIBSSH2_FXF_EXCL LIBSSH2_FXF_READ LIBSSH2_FXF_TRUNC LIBSSH2_FXF_WRITE)],
hash => [qw(LIBSSH2_HOSTKEY_HASH_MD5 LIBSSH2_HOSTKEY_HASH_SHA1)],
method => [qw(LIBSSH2_METHOD_COMP_CS LIBSSH2_METHOD_COMP_SC LIBSSH2_METHOD_CRYPT_CS LIBSSH2_METHOD_CRYPT_SC LIBSSH2_METHOD_HOSTKEY LIBSSH2_METHOD_KEX LIBSSH2_METHOD_LANG_CS LIBSSH2_METHOD_LANG_SC LIBSSH2_METHOD_MAC_CS LIBSSH2_METHOD_MAC_SC)],
policy => [qw(LIBSSH2_HOSTKEY_POLICY_STRICT LIBSSH2_HOSTKEY_POLICY_ASK LIBSSH2_HOSTKEY_POLICY_TOFU LIBSSH2_HOSTKEY_POLICY_ADVISORY)],
sftp => [qw(LIBSSH2_SFTP_ATTR_ACMODTIME LIBSSH2_SFTP_ATTR_EXTENDED LIBSSH2_SFTP_ATTR_PERMISSIONS LIBSSH2_SFTP_ATTR_SIZE LIBSSH2_SFTP_ATTR_UIDGID LIBSSH2_SFTP_LSTAT LIBSSH2_SFTP_OPENDIR LIBSSH2_SFTP_OPENFILE LIBSSH2_SFTP_PACKET_MAXLEN LIBSSH2_SFTP_READLINK LIBSSH2_SFTP_REALPATH LIBSSH2_SFTP_RENAME_ATOMIC LIBSSH2_SFTP_RENAME_NATIVE LIBSSH2_SFTP_RENAME_OVERWRITE LIBSSH2_SFTP_SETSTAT LIBSSH2_SFTP_STAT LIBSSH2_SFTP_SYMLINK LIBSSH2_SFTP_TYPE_BLOCK_DEVICE LIBSSH2_SFTP_TYPE_CHAR_DEVICE LIBSSH2_SFTP_TYPE_DIRECTORY LIBSSH2_SFTP_TYPE_FIFO LIBSSH2_SFTP_TYPE_REGULAR LIBSSH2_SFTP_TYPE_SOCKET LIBSSH2_SFTP_TYPE_SPECIAL LIBSSH2_SFTP_TYPE_SYMLINK LIBSSH2_SFTP_TYPE_UNKNOWN LIBSSH2_SFTP_VERSION)],
socket => [qw(LIBSSH2_SOCKET_POLL_MAXLOOPS LIBSSH2_SOCKET_POLL_UDELAY)],
trace => [qw(LIBSSH2_TRACE_TRANS LIBSSH2_TRACE_KEX LIBSSH2_TRACE_AUTH LIBSSH2_TRACE_CONN LIBSSH2_TRACE_SCP LIBSSH2_TRACE_SFTP LIBSSH2_TRACE_ERROR LIBSSH2_TRACE_PUBLICKEY LIBSSH2_TRACE_SOCKET)],
);
1;

View File

@@ -0,0 +1,42 @@
package Net::SSH2::Dir;
use strict;
use warnings;
use Carp;
# methods
1;
__END__
=head1 NAME
Net::SSH2::Dir - SSH 2 SFTP directory object
=head1 DESCRIPTION
An SFTP file object is created by the L<Net::SSH2::SFTP> C<opendir> method.
=head2 read
Returns a hash (hashref in scalar context); keys are C<name> and those returned
by Net::SSH2::SFTP::stat; returns empty list or undef if no more files.
=head1 SEE ALSO
L<Net::SSH2::SFTP>.
=head1 AUTHOR
David B. Robins, E<lt>dbrobins@cpan.orgE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2005, 2006 by David B. Robins; all rights reserved.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.0 or,
at your option, any later version of Perl 5 you may have available.
=cut

View File

@@ -0,0 +1,188 @@
package Net::SSH2::File;
use strict;
use warnings;
use Carp;
# methods
sub readline {
my ($self, $eol) = @_;
$eol = $/ unless @_ >= 2;
if (wantarray or not defined $eol) {
my $data = '';
my $buffer;
while (1) {
$self->read($buffer, 32768) or last;
$data .= $buffer;
}
defined $eol and return split /(?<=\Q$eol\E)/s, $data;
wantarray and not length $data and return ();
return $data;
}
else {
my $c;
my $data = '';
while (1) {
$c = $self->getc;
last unless defined $c;
$data .= $c;
last if $data =~ /\Q$eol\E\z/;
}
return (length $data ? $data : undef);
}
}
# tie interface
sub PRINT {
my $self = shift;
my $sep = defined($,) ? $, : '';
$self->write(join $sep, @_)
}
sub PRINTF {
my $self = shift;
my $template = shift;
$self->write(sprintf $template, @_)
}
sub WRITE {
my ($self, $buf, $len, $offset) = @_;
$self->write(substr($buf, $offset, $len))
}
sub READLINE { shift->readline($/) }
*GETC = \&getc;
sub READ {
my ($self, undef, $len, $offset) = @_;
my $bytes = $self->read(my($buffer), $len);
substr($_[1], $offset || 0) = $buffer
if defined $bytes;
return $bytes;
}
sub CLOSE {
}
sub BINMODE { 1 }
sub EOF { 0 }
1;
__END__
=head1 NAME
Net::SSH2::File - SSH2 SFTP file object
=head1 DESCRIPTION
An SFTP file object is created by the L<Net::SSH2::SFTP> C<open> method.
=head2 read ( buffer, size )
Read size bytes from the file into a given buffer. Returns number of bytes
read, or undef on failure.
=head2 write ( buffer )
Write buffer to the remote file.
The C<libssh2_sftp_write> function wrapped by this method has a
complex and quite difficult (if not impossible at all) to use API. It
tries to hide the packet pipelining being done under the hood in order
to attain decent throughput.
Net::SSH2 can not hide that complexity without negatively affecting
the transmission speed so it provides just a thin wrapper for that
library function.
An excerpt from C<libssh2_sftp_write> manual page follows:
WRITE AHEAD
Starting in libssh2 version 1.2.8, the default behavior of libssh2
is to create several smaller outgoing packets for all data you pass
to this function and it will return a positive number as soon as the
first packet is acknowledged from the server.
This has the effect that sometimes more data has been sent off but
isn't acked yet when this function returns, and when this function
is subsequently called again to write more data, libssh2 will
immediately figure out that the data is already received remotely.
In most normal situation this should not cause any problems, but it
should be noted that if you've once called libssh2_sftp_write() with
data and it returns short, you MUST still assume that the rest of
the data might've been cached so you need to make sure you don't
alter that data and think that the version you have in your next
function invoke will be detected or used.
The reason for this funny behavior is that SFTP can only send 32K
data in each packet and it gets all packets acked individually. This
means we cannot use a simple serial approach if we want to reach
high performance even on high latency connections. And we want that.
This is an example of simple file uploading
use constant BUF_SIZE => 128*1024;
my $sftp = $ssh2->sftp;
open my $fh, '<', '/tmp/doc.txt';
my $sf = $sftp->open('doc.txt', O_CREAT|O_WRONLY|O_TRUNC);
my $buf;
while (sysread($fh, $buf, BUF_SIZE)) {
while (length $buf) {
my $rc = $sf->write($buf);
if (!defined($rc)) {
$sftp->die_with_error('write error');
}
# Remove transferred data from the buffer.
substr($buf, 0, $rc) = '';
}
}
=head2 stat
Returns file attributes; see Net::SSH2::SFTP::stat.
=head2 setstat ( key, value... )
Sets file attributes; see Net::SSH2::SFTP::setstat.
=head2 seek ( offset )
Set the file pointer offset.
=head2 tell
Returns the current file pointer offset.
=head1 SEE ALSO
L<Net::SSH2::SFTP>.
Check L<Net::SFTP::Foreign> for a high level, perlish and easy to use
SFTP client module. It can work on top of Net::SSH2 via the
L<Net::SFTP::Foreign::Backend::Net_SSH2> backend module.
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2005, 2006 by David B. Robins E<lt>dbrobins@cpan.orgE<gt>;
Copyright (C) 2015 by Salvador FandiE<ntilde>o E<lt>sfandino@yahoo.comE<gt>;
All rights reserved.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.0 or,
at your option, any later version of Perl 5 you may have available.
The documentation for this package contains and excerpt from libssh2
manual pages. You can consult the license of the libssh2 project for
the conditions regulating the copyright of that part.
=cut

View File

@@ -0,0 +1,195 @@
package Net::SSH2::KnownHosts;
use strict;
use warnings;
1;
__END__
=head1 NAME
Net::SSH2::KnownHosts - SSH 2 knownhosts object
=head1 SYNOPSIS
#####################################################################
# #
# WARNING: The API provided by Net::SSH2::KnownHosts is #
# experimental and could change in future versions of the module!!! #
# #
#####################################################################
my $kh = $ssh2->known_hosts;
my $n_ent = $kh->readfile($known_hosts_path);
# a non-existent known_hosts file usually is not an error...
unless (defined $n_ent) {
if ($ssh2->error != LIBSSH2_ERROR_FILE or -f $known_hosts_path) {
die; # propagate error;
}
}
my ($key, $type) = $ssh2->remote_hostkey;
my $flags = ( LIBSSH2_KNOWNHOST_TYPE_PLAIN |
LIBSSH2_KNOWNHOST_KEYENC_RAW |
(($type + 1) << LIBSSH2_KNOWNHOST_KEY_SHIFT) );
my $check = $kh->check($hostname, $port, $key, $flags);
if ($check == LIBSSH2_KNOWNHOST_CHECK_MATCH) {
# ok!
}
elsif ($check == LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
die "host verification failed, the key has changed!";
}
elsif ($check == LIBSSH2_KNOWNHOST_CHECK_NOTFOUND) {
die "host verification failed, key not found in known_hosts file"
if $strict_host_key_checking;
# else, save new key to file:
unless ( $kh->add($hostname, '', $key, "Perl added me", $flags) and
$kh->writefile($known_hosts_path) ) {
warn "unable to save known_hosts file: " . ($ssh2->error)[1];
}
}
else {
die "host key verification failed, unknown reason";
}
=head1 DESCRIPTION
#####################################################################
# #
# WARNING: The API provided by Net::SSH2::KnownHosts is #
# experimental and could change in future versions of the module!!! #
# #
#####################################################################
The C<knownhosts> object allows one to manipulate the entries in the
C<known_host> file usually located at C<~/.ssh/known_hosts> and which
contains the public keys of the already known hosts.
The methods currently supported are as follows:
=head2 readfile (filename)
Populates the object with the entries in the given file.
It returns the number or entries read or undef on failure.
=head2 writefile (filename)
Saves the known host entries to the given file.
=head2 add (hostname, salt, key, comment, key_type|host_format|key_format)
Add a host and its associated key to the collection of known hosts.
The C<host_format> argument specifies the format of the given host:
LIBSSH2_KNOWNHOST_TYPE_PLAIN - ascii "hostname.domain.tld"
LIBSSH2_KNOWNHOST_TYPE_SHA1 - SHA1(salt, host) base64-encoded!
LIBSSH2_KNOWNHOST_TYPE_CUSTOM - another hash
If C<SHA1> is selected as host format, the salt must be provided to
the salt argument in base64 format.
The SHA-1 hash is what OpenSSH can be told to use in known_hosts
files. If a custom type is used, salt is ignored and you must provide
the host pre-hashed when checking for it in the C<check> method.
The available key formats are as follow:
LIBSSH2_KNOWNHOST_KEYENC_RAW
LIBSSH2_KNOWNHOST_KEYENC_BASE64
Finally, the available key types are as follow:
LIBSSH2_KNOWNHOST_KEY_RSA1
LIBSSH2_KNOWNHOST_KEY_SSHRSA
LIBSSH2_KNOWNHOST_KEY_SSHDSS
The comment argument may be undef.
=head2 check (hostname, port, key, key_type|host_format|key_format)
Checks a host and its associated key against the collection of known hosts.
The C<key_type|host_format|key_format> argument has the same meaning
as in the L</add> method.
C<undef> may be passed as the port argument.
Returns:
LIBSSH2_KNOWNHOST_CHECK_MATCH (0)
LIBSSH2_KNOWNHOST_CHECK_MISMATCH (1)
LIBSSH2_KNOWNHOST_CHECK_NOTFOUND (2)
LIBSSH2_KNOWNHOST_CHECK_FAILURE (3)
=head2 readline (string)
Read a known_hosts entry from the given string.
For instance, the following piece of code is more or less equivalent
to the L<readfile> method:
my $kh = $ssh2->known_hosts;
if (open my $fh, '<', $known_hosts_path) {
while (<>) {
eval { $kh->readline($_) }
or warn "unable to parse known_hosts entry $_";
}
}
=head2 writeline (hostname, port, key, key_type|host_format|key_format)
Searches the entry matching the given parameters (as described in the
L</check> method) and formats it into a line in the known_hosts
format.
This method returns undef when some error happens.
This method should be considered experimental, the interface may
change.
=head1 SEE ALSO
L<Net::SSH2>, L<sshd(8)>.
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2013-2015 Salvador FandiE<ntilde>o; all rights reserved.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.0 or,
at your option, any later version of Perl 5 you may have available.
The documentation on this file is based on the comments inside
C<libssh2.h> file from the libssh2 distribution which has the
following copyright and license:
Copyright (c) 2004-2009, Sara Golemon <sarag@libssh2.org>
Copyright (c) 2009-2012 Daniel Stenberg
Copyright (c) 2010 Simon Josefsson <simon@josefsson.org>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
Neither the name of the copyright holder nor the names of any other
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
=cut

View File

@@ -0,0 +1,42 @@
package Net::SSH2::Listener;
use strict;
use warnings;
use Carp;
# methods
1;
__END__
=head1 NAME
Net::SSH2::Listener - SSH 2 listener object
=head1 DESCRIPTION
A listener object is created by the L<Net::SSH2> C<listen> method. The
L<Net::SSH2> C<poll> method can be used to check for connections.
=head2 accept
Accept a connection. Returns a channel object on success, undef on failure.
=head1 SEE ALSO
L<Net::SSH2>.
=head1 AUTHOR
David B. Robins, E<lt>dbrobins@cpan.orgE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2005, 2006 by David B. Robins; all rights reserved.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.0 or,
at your option, any later version of Perl 5 you may have available.
=cut

View File

@@ -0,0 +1,46 @@
package Net::SSH2::PublicKey;
use strict;
use warnings;
use Carp;
# methods
1;
__END__
=head1 NAME
Net::SSH2::PublicKey - SSH 2 public key object
=head1 DESCRIPTION
*** WARNING: public key functionality in libssh2 is experimental
*** and mostly abandoned. Don't expect anything on this module to
*** work correctly.
A public key object is created by the L<Net::SSH2> C<public_key> method.
=head1 METHODS
=head2 add ( name, blob, overwrite flag, attributes... )
Adds a new public key; attributes is a list of hashes with C<name>, C<value>,
and C<mandatory> keys; mandatory defaults to false and value to empty.
=head2 remove ( name, blob )
Remove the given public key.
=head2 fetch
Returns a list of public keys in array context (count in scalar context);
each item is a hash with keys C<name>, C<blob>, and C<attr>, with the latter
being a hash with C<name>, C<value>, and C<mandatory> keys.
=head1 SEE ALSO
L<Net::SSH2>.
=cut

View File

@@ -0,0 +1,126 @@
package Net::SSH2::SFTP;
use strict;
use warnings;
use Carp;
sub die_with_error {
my $self = shift;
if (my ($code, $name) = $self->error) {
croak join(": ", @_, "SFTP error $code $name");
}
else {
croak join(": ", @_, "no SFTP error registered");
}
}
1;
__END__
=head1 NAME
Net::SSH2::SFTP - SSH 2 Secure FTP object
=head1 DESCRIPTION
An SFTP object is created by the L<Net::SSH2> C<sftp> method.
=head2 error
Returns the last SFTP error (one of the LIBSSH2_FX_* constants). Use this
when Net::SSH2::error returns LIBSSH2_ERROR_SFTP_PROTOCOL. In list context,
returns (code, error name).
=head2 die_with_error( [message] )
Calls C<die> with the given message and the error information from the
object appended.
=head2 open ( file [, flags [, mode ]]] )
Open or create a file on the remote host. The flags are the standard O_RDONLY,
O_WRONLY, O_RDWR, O_APPEND, O_CREAT, O_TRUNC, and O_EXCL, which may be
combined as usual. Flags default to O_RDONLY and mode to 0666 (create only).
Returns a L<Net::SSH2::File> object on success.
=head2 opendir ( dir )
Open a directory on the remote host; returns a Net::SSH2::Dir object on success.
=head2 unlink ( file )
Delete the remote file.
=head2 rename ( old, new [, flags ] )
Rename old to new. Flags are taken from LIBSSH2_SFTP_RENAME_*, and may be
combined; the default is to use all (overwrite, atomic, native).
=head2 mkdir ( path [, mode ] )
Create directory; mode defaults to 0777.
=head2 rmdir ( path )
Remove directory.
=head2 stat ( path [, follow ] )
Get file attributes for the given path. If follow is set (default), will
follow symbolic links. On success, returns a hash containing the following:
=over 4
=item mode
=item size
=item uid
=item gid
=item atime
=item mtime
=back
=head2 setstat ( path, key, value... )
Set file attributes for given path; keys are the same as those returned by stat;
note that it's not necessary to pass them all.
=head2 symlink ( path, target [, type ] )
Create a symbolic link to a given target.
=head2 readlink ( path )
Return the target of the given link, undef on failure.
=head2 realpath ( path )
Resolve a filename's path; returns the resolved path, or undef on error.
=head1 SEE ALSO
L<Net::SSH2>.
Check L<Net::SFTP::Foreign> for a high level, perlish and easy to use
SFTP client module. It can work on top of Net::SSH2 via the
L<Net::SFTP::Foreign::Backend::Net_SSH2> backend module.
=head1 AUTHOR
David B. Robins, E<lt>dbrobins@cpan.orgE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2005, 2006 by David B. Robins; all rights reserved.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.0 or,
at your option, any later version of Perl 5 you may have available.
=cut