4

I have a simple perl test script which uses Net::SSH2, and I'm having trouble getting it to work with public key authentication.

Note: After reading a couple of replies, I realise that I should mention that I created the script to help narrow down a problem I was having with another application that uses Net::SSH2. It's therefore not possible for me to switch to an alternative package such as Net::OpenSSH or Net::OpenSSH::Compat::SSH2.

Note Update: As salva pointed out, Net::OpenSSH::Compat::SSH2 can be used without having to patch the original application.

Here's the code:

use strict;
use warnings;
use 5.10.0;

use Net::SSH2;

my $ssh2 = Net::SSH2->new();
my $auth;

if ( $ssh2->connect('hostname') ) {

    $auth = $ssh2->auth_publickey(
       'username',
       '/home/mike/.ssh/id_rsa.pub',
       '/home/mike/.ssh/id_rsa',
       'password'
    );  
}   

if ($auth && $ssh2->auth_ok) {
    say 'Success';
} else {
    say join ', ', $ssh2->error;
}  

I have been generating key pairs using ssh-keygen on Ubuntu:

ssh-keygen -t rsa
ssh-copy-id user@server
ssh user@server

The above works correctly - I can SSH to the server.

When I run the Perl code, I get the following error when using a password protected key:

-16, LIBSSH2_ERROR_FILE, Unable to initialize private key from file

If I try with a non-password protected key, it works correctly.

I have the following libraries installed:

Net::SSH2         0.35

libssh2-1         1.2.2-1
libssh2-1-dev     1.2.2-1
ssh               1:5.3p1-3ubuntu6
openssh-server    1:5.3p1-3ubuntu6
openssh-client    1:5.3p1-3ubuntu6
openssl           0.9.8k-7ubuntu8.6
libssl-dev        0.9.8k-7ubuntu8.6

The plot thickens

If I remove libssh2-1 and libssh2-1-dev, I get an error, as expected:

Can't load '/usr/local/lib/perl/5.10.1/auto/Net/SSH2/SSH2.so'

If I then build libssh2 from source, I am unable to reinstall Net::SSH2, as it can't find the development headers. However, if I reinstall libssh2-1 and libssh2-1-dev and then build and install libssh2 from source, it works.

Does that mean that the build of libssh2-1-dev on Ubuntu 10.04 is at fault? If so, how do I install libssh2 from source and correctly install Net::SSH2, without requiring libssh2-1-dev. I presume that the build from source is overwriting or overriding the Ubuntu package.

UPDATE

As noted in Daniel Stenberg's reply, the Ubuntu 10.04 package is now a little out of date (version 1.2.2, compared with the latest stable build at 1.2.8). Installing libssh2 from source 'over the top' of the Ubuntu package solves the problem. However, this feels messy to me. How can I remove the Ubuntu package, install libssh2 from source, and still build Net::SSH2 — how do I tell Net::SSH2 where to find the libssh2 development headers?

UPDATE 2

salva came to the rescue again, and showed how the Net::SSH2 installer can be configured with lib and include directories, so that it may be used with the source install of libssh2. Thanks salva! Note that instead of patching Makefile.PL, it's possible to just override the $lib and $inc variables at the top of Makefile.PL. I wasn't aware of this until I looked at salva's patch.

Community
  • 1
  • 1
Mike
  • 21,301
  • 2
  • 42
  • 65

3 Answers3

1

I have been able to successfully log into a server using a pass-phrase protected key with Net::SSH2 from the the Ubuntu 11.04 libnet-ssh2-perl package.

Anyway, consider using Net::OpenSSH or Net::OpenSSH::Compat::SSH2 instead of Net::SSH2.

Update: Net::OpenSSH::Compat::SSH2 tries to be a replacement for Net::SSH2. There is no need to patch the application in order to try it:

perl -MNet::OpenSSH::Compat=Net::SSH2 yor_app.pl
salva
  • 9,943
  • 4
  • 29
  • 57
  • Thanks for the reply. My test script was to help narrow down the problem with another application which uses Net::SSH2, so unfortunately, I'm stuck with it. The app is open source, so I may eventually submit a patch that allows it to use one of the alternatives. In the mean time, I've got it to work by installing from source, but I'd like to resolve the messy situation of having both the Ubuntu package and the source-built package installed. – Mike May 27 '11 at 07:00
  • Thanks for the update - that's very cool. I've tried it on my test script, and it works perfectly. It should be simple enough to override Net::SSH2 in the proper app too. What's more, it's a really simple patch to add to future releases - the app can use Net::OpenSSH::Compat::SSH2 if it is available, and fall back to Net::SSH2 if not. Thanks. – Mike May 27 '11 at 08:43
  • Net::OpenSSH::Compat::SSH2 is not a mature module yet. Don't hesitate to report any bug or problem you may find. – salva May 27 '11 at 09:50
  • If I enable Net::OpenSSH::Compat::SSH2 and add `$ssh2->method('HOSTKEY', 'ssh-rsa');` just before the `auth_publickey` method in my test script, it fails with the following error: `Can't locate object method "method" via package "Net::SSH2" at ssh.pm line 13.` Would you like me to submit a bug report? – Mike May 27 '11 at 16:14
  • I have just uploaded to CPAN a new version of the module with support for the "method" method. – salva May 28 '11 at 22:28
1

When you install libssh2 from the source package it will by default install itself in /usr/local, while the default package installs in /usr which probably is why it only finds the "stock" installed version.

Unfortunately it seems your Ubuntu has a fairly old libssh2 version as it has been bugfixed a lot since then.

I recommend using the libssh2-devel mailing list for in-depth libssh2 questions. It's a small but friendly community.

Daniel Stenberg
  • 54,736
  • 17
  • 146
  • 222
  • Yes, the Ubuntu libssh2 package is at version 1.2.2, whereas the latest stable build is at version 1.2.8. The latest build does solve the problem, but I'd like to know how to build and compile the Net::SSH2 without having the Ubuntu package installed. That is, how do I tell the Net::SSH2 installer where to find the development headers? – Mike May 27 '11 at 07:10
1

I have created a patch for Net::SSH2 Makefile.PL that allows to set the location of libssh2 libs and headers from the command line.

Here is a capture of the full build process for libssh2 + Net::SSH2 using it:

salva@leon:/tmp/salva$ wget http://www.libssh2.org/download/libssh2-1.2.8.tar.gz
--2011-05-27 11:21:10--  http://www.libssh2.org/download/libssh2-1.2.8.tar.gz
Resolving www.libssh2.org... 80.67.6.50
Connecting to www.libssh2.org|80.67.6.50|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 637707 (623K) [application/x-gzip]
Saving to: `libssh2-1.2.8.tar.gz'

100%[================================================================================================================================================================================================>] 637,707      525K/s   in 1.2s    

2011-05-27 11:21:14 (525 KB/s) - `libssh2-1.2.8.tar.gz' saved [637707/637707]

salva@leon:/tmp/salva$ tar xzf libssh2-1.2.8.tar.gz 
salva@leon:/tmp/salva$ cd libssh2-1.2.8
salva@leon:/tmp/salva/libssh2-1.2.8$ ./configure --prefix=/usr/local/libssh2
checking whether to enable maintainer-specific portions of Makefiles... no
checking for sed... /bin/sed
checking for a BSD-compatible install... /usr/bin/install -c
...

salva@leon:/tmp/salva/libssh2-1.2.8$ make
Making all in src
make[1]: Entering directory `/tmp/salva/libssh2-1.2.8/src'
make  all-am
make[2]: Entering directory `/tmp/salva/libssh2-1.2.8/src'
if /bin/bash ../libtool --tag=CC --mode=compile gcc -DHAVE_CONFIG_H   -I../include -I../src   -g -O2 -MT channel.lo -MD -MP -MF ".deps/channel.Tpo" -c -o channel.lo channel.c; \
    then mv -f ".deps/channel.Tpo" ".deps/channel.Plo"; else rm -f ".deps/channel.Tpo"; exit 1; fi
libtool: compile:  gcc -DHAVE_CONFIG_H -I../include -I../src -g -O2 -MT channel.lo -MD -MP -MF .deps/channel.Tpo -c channel.c  -fPIC -DPIC -o .libs/channel.o
...

salva@leon:/tmp/salva/libssh2-1.2.8$ sudo make install
Making install in src
make[1]: Entering directory `/tmp/salva/libssh2-1.2.8/src'
make[2]: Entering directory `/tmp/salva/libssh2-1.2.8/src'
test -z "/usr/local/libssh2/lib" || mkdir -p -- "/usr/local/libssh2/lib"
 /bin/bash ../libtool --mode=install /usr/bin/install -c  'libssh2.la' '/usr/local/libssh2/lib/libssh2.la'
libtool: install: /usr/bin/install -c .libs/libssh2.so.1.0.1 /usr/local/libssh2/lib/libssh2.so.1.0.1
...

salva@leon:/tmp/salva/libssh2-1.2.8$ cd ..
salva@leon:/tmp/salva$ wget http://search.cpan.org/CPAN/authors/id/R/RK/RKITOVER/Net-SSH2-0.35.tar.gz
--2011-05-27 11:22:56--  http://search.cpan.org/CPAN/authors/id/R/RK/RKITOVER/Net-SSH2-0.35.tar.gz
Resolving search.cpan.org... 207.115.101.144
Connecting to search.cpan.org|207.115.101.144|:80... connected.
HTTP request sent, awaiting response... 302 Found
Location: http://osl.ugr.es/CPAN/authors/id/R/RK/RKITOVER/Net-SSH2-0.35.tar.gz [following]
--2011-05-27 11:22:59--  http://osl.ugr.es/CPAN/authors/id/R/RK/RKITOVER/Net-SSH2-0.35.tar.gz
Resolving osl.ugr.es... 150.214.21.7
Connecting to osl.ugr.es|150.214.21.7|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 92434 (90K) [application/x-gzip]
Saving to: `Net-SSH2-0.35.tar.gz'

100%[================================================================================================================================================================================================>] 92,434       328K/s   in 0.3s    

2011-05-27 11:22:59 (328 KB/s) - `Net-SSH2-0.35.tar.gz' saved [92434/92434]

salva@leon:/tmp/salva$ tar xzf Net-SSH2-0.35.tar.gz 
salva@leon:/tmp/salva$ cd Net-SSH2-0.35
salva@leon:/tmp/salva/Net-SSH2-0.35$ wget -q --no-check-certificate -O - https://github.com/salva/net-ssh2/commit/3c7261f4584137f4240d204731e20f709f1addb1.patch|patch -p1
patching file Makefile.PL
salva@leon:/tmp/salva/Net-SSH2-0.35$ perl Makefile.PL lib=/usr/local/libssh2/lib/ inc=/usr/local/libssh2/include/

The libssh2 library is required by this module.  If you don't have it, you can
download it from http://www.libssh2.org; you may also need OpenSSL, which can be
obtained from http://www.openssl.org.

Debian:   sudo aptitude install libssh2-1-dev
OpenSUSE: sudo zypper in libssh2-1 libssh2-devel

Checking if your kit is complete...
Looks good
Writing Makefile for Net::SSH2
salva@leon:/tmp/salva/Net-SSH2-0.35$ make
cp lib/Net/SSH2/File.pm blib/lib/Net/SSH2/File.pm
cp lib/Net/SSH2/PublicKey.pm blib/lib/Net/SSH2/PublicKey.pm
cp lib/Net/SSH2/Dir.pm blib/lib/Net/SSH2/Dir.pm
cp lib/Net/SSH2/SFTP.pm blib/lib/Net/SSH2/SFTP.pm
cp lib/Net/SSH2/Listener.pm blib/lib/Net/SSH2/Listener.pm
cp lib/Net/SSH2/Channel.pm blib/lib/Net/SSH2/Channel.pm
cp lib/Net/SSH2.pm blib/lib/Net/SSH2.pm
AutoSplitting blib/lib/Net/SSH2.pm (blib/lib/auto/Net/SSH2)
/usr/bin/perl "-Iinc" /usr/local/share/perl/5.10.1/ExtUtils/xsubpp  -typemap /usr/share/perl/5.10/ExtUtils/typemap -typemap typemap  SSH2.xs > SSH2.xsc && mv SSH2.xsc SSH2.c
cc -c  /usr/local/libssh2/include/ -D_REENTRANT -D_GNU_SOURCE -DDEBIAN -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -O2 -g   -DVERSION=\"0.35\" -DXS_VERSION=\"0.35\" -fPIC "-I/usr/lib/perl/5.10/CORE"   SSH2.c
In file included from SSH2.xs:11:0:
ppport.h:3042:0: warning: "PERL_UNUSED_DECL" redefined
/usr/lib/perl/5.10/CORE/perl.h:330:0: note: this is the location of the previous definition
cc: /usr/local/libssh2/include/: linker input file unused because linking not done
Running Mkbootstrap for Net::SSH2 ()
chmod 644 SSH2.bs
rm -f blib/arch/auto/Net/SSH2/SSH2.so
LD_RUN_PATH="/usr/local/libssh2/lib:/lib/x86_64-linux-gnu" cc  -shared -O2 -g -L/usr/local/lib -fstack-protector SSH2.o  -o blib/arch/auto/Net/SSH2/SSH2.so     \
       -L/usr/local/libssh2/lib/ -lssh2 -lz -lssl -lcrypto      \

chmod 755 blib/arch/auto/Net/SSH2/SSH2.so
cp SSH2.bs blib/arch/auto/Net/SSH2/SSH2.bs
chmod 644 blib/arch/auto/Net/SSH2/SSH2.bs
Manifying blib/man3/Net::SSH2::File.3pm
Manifying blib/man3/Net::SSH2::Dir.3pm
Manifying blib/man3/Net::SSH2::PublicKey.3pm
Manifying blib/man3/Net::SSH2::SFTP.3pm
Manifying blib/man3/Net::SSH2::Listener.3pm
Manifying blib/man3/Net::SSH2::Channel.3pm
Manifying blib/man3/Net::SSH2.3pm
salva@leon:/tmp/salva/Net-SSH2-0.35$ ldd ./blib/arch/auto/Net/SSH2/SSH2.so
    linux-vdso.so.1 =>  (0x00007fff20abc000)
    libssh2.so.1 => /usr/local/libssh2/lib/libssh2.so.1 (0x00007f464d52f000)
    libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f464d317000)
    libssl.so.0.9.8 => /lib/libssl.so.0.9.8 (0x00007f464d09a000)
    libcrypto.so.0.9.8 => /lib/libcrypto.so.0.9.8 (0x00007f464cd0b000)
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f464c977000)
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f464c772000)
    /lib64/ld-linux-x86-64.so.2 (0x00007f464d97e000)
salva@leon:/tmp/salva/Net-SSH2-0.35$ sudo make install
...
salva
  • 9,943
  • 4
  • 29
  • 57
  • Thanks for this solution, it's above and beyond the call of duty! I tried it, but Makefile.PL fails with this error: `error while loading shared libraries: libssh2.so.1: cannot open shared object file: No such file or directory wrong result: 'ssh2'` Bizarrely, if I delete the `/usr/local/libssh2/lib/libssh2.so.1` symlink to `/usr/local/libssh2/lib/libssh2.so.1.0.1`, it works. – Mike May 27 '11 at 12:02
  • Rafael Kitover has also released version 0.36 of Net::SSH2 incorporating my patch – salva May 28 '11 at 22:30