0

I am attempting to login to an HP Switch (3500) from a Perl script on a Linux server. I'm stuck with using Net::OpenSSH as the only module available to me.

It hangs everytime I try to log in, though. The code works fine when it's hitting a webserver and I'm just logging in, taking a directory listing, and getting out. When run against a switch, it hangs up.

When logging in manually, here's how it goes:

$ ssh -luser_name 20.xxx.xxx.xxx
We'd like to keep you up to date about:
  * Software feature updates
  * New product announcements
  * Special events
Please register your products now at:  www.hp.com/networking/register


user_name@20.xxx.xxx.xxx's password: [I type that in, hit enter]
ProCurve J8693A Switch 3500yl-48G
Software revision K.15.04.1018m

Copyright (C) 1991-2013 Hewlett-Packard Development Company, L.P.

                   RESTRICTED RIGHTS LEGEND
 Confidential computer software.  Valid license from HP required for possession,
 use or copying. Consistent with FAR 12.211 and 12.212, Commercial Computer
 Software, Computer Software Documentation, and Technical Data for Commercial
 Items are licensed to the U.S. Government under vendor's standard commercial
 license.
                   HEWLETT-PACKARD DEVELOPMENT COMPANY, L.P.
                   20555 State Highway 249, Houston, TX 77070

[delete lots of lines here]

Press any key to continue

I wrote a short script to attempt to log in and issue a single simple command:

use strict;
use Net::OpenSSH;

my $host = '20.xxx.xxx.xxx';
my $user = 'user_name';
my $password = 'password';

my $login_string = $user . ':' . $password . '@' . $host;
my $ssh = Net::OpenSSH->new($login_string);
$ssh->error and die "Cannot open the connection " . $ssh->error;

my @results = $ssh->capture2('show cpu');
map { print;} @results;

It doesn't get very far:

$ perl testopenssh.pl
We'd like to keep you up to date about:
  * Software feature updates
  * New product announcements
  * Special events
Please register your products now at:  www.hp.com/networking/register

That's where it hangs. It's like it doesn't recognize that it's looking for a password and never gets past that point. I hit CTRL-C and it dies. When I do that, debug mode shows this afterwards:

# file object not yet found at /home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440
# passwd/passphrase requested (user_name@20.xxx.xxx.xxx's password:)
# file object not yet found at /home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440
# file object not yet found at /home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440
# file object found at /home/xxxxxx/.libnet-openssh-perl/app-20.xxx.xxx.xxx-21357-620440
# call args: ['ssh','-O','check','-T','-S','/home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440','-l','user_name','20.xxx.xxx.xxx','--']
# open_ex: ['ssh','-O','check','-T','-S','/home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440','-l','user_name','20.xxx.xxx.xxx','--']
# io3 mloop, cin: 0, cout: 1, cerr: 0
# io3 fast, cin: 0, cout: 1, cerr: 0
# stdout, bytes read: 28 at offset 0
#> 4d 61 73 74 65 72 20 72 75 6e 6e 69 6e 67 20 28 70 69 64 3d 32 31 33 35 38 29 0d 0a             | Master running (pid=21358)..
# io3 fast, cin: 0, cout: 1, cerr: 0
# stdout, bytes read: 0 at offset 28
# leaving _io3()
# _waitpid(21362) => pid: 21362, rc:
# call args: ['ssh','-S','/home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440','-l','user_name','20.xxx.xxx.xxx','--','show cpu']
# open_ex: ['ssh','-S','/home/xxxxxx/.libnet-openssh-perl/user_name-20.xxx.xxx.xxx-21357-620440','-l','user_name','20.xxx.xxx.xxx','--','show cpu']
# io3 mloop, cin: 0, cout: 1, cerr: 1
# io3 fast, cin: 0, cout: 1, cerr: 1

Does that mean it's hanging BEFORE it's even looking for the password?

Any ideas for what else I might be able to try?

Thanks!

AugieDB
  • 67
  • 1
  • 8
  • Post the full debugging log and also, activate debugging on the ssh program adding the following arguments into the constructor call: `master_opts => '-v'` – salva Jan 30 '14 at 10:21

2 Answers2

1

As you probably know, there is no way to present a password non-interactively when you use SSH, i.e. no command-line option to include it. If you use password auth with SSH, it has to be interactively provided.

Net::OpenSSH's way of connecting calling one single string:

my $ssh2 = Net::OpenSSH->new('jack:secret@foo.bar.com:10022');

is just a nice way for the programmer to provide a password, but then it mimics interactive password auth. The docs say: "For password authentication, IO::Pty has to be installed"

I'm thinking that switch's pty implementation is probably different than the web servers you log into, therefore the Net::OpenSSH module - or rather, IO::Pty - is unable to get through password auth?

I agree with @Marlon above that expect would fit nicely here. Anywhere you need to emulate human behavior, expect is a good fit. And you don't have to use SSH keys, although it is recommended so as not to have passwords in clear text in a script file. But, your Perl program above is not exactly top-security stuff with the password listed in there, either. So you could easily switch to an expect script that would be able to handle interactive password login easily, at the same security level you are now.

Just my 2c.

James
  • 1,186
  • 9
  • 14
0

I'm using expect and private-key authentication to accomplish this.

I've got a simple expect-script, that I invoke with the IP and the command which is to be executed after the login:

#!/usr/bin/expect
#
# sendswitchcmd.exp
#
set timeout 60

spawn ssh -t -t -o ConnectTimeout=5 -o StrictHostKeyChecking=no -i PATHTOYOURKEY]
expect -re "Press any key to continue"
send "X"
expect -re ".*#"
send "config\n"
expect -re ".*#"
send "[lindex $argv 1] [lindex $argv 2]\n     "
expect -re ".*#"
send "ex\n"
expect -re ".*#"
send "ex\n"
expect -re ".*>"
send "ex\n"
expect -re ".*you want to log out.*"
send "y"

With that I can do things like

./sendswitchcmd.exp [switch-IP] "show vlans"

This I also invoke in some Bash-Scripts that I built for simpler configuration of our switches.

Maybe that helps you along.

Marlon
  • 148
  • 6
  • We've talked about Expect, but it's not currently installed. Might be an issue to do that. And the problem with using private key authentication right now is that we'd be hitting up against a giant number of switches with this. We can't go in and change their configurations. It's one of those projects where it's on us to mimic the way we'd do it by hand. Frustrating, but it's what we've got. – AugieDB Jan 29 '14 at 21:14
  • @AugieDB You can always install Perl modules locally, even if you don't have root access. Take a look at [Net::SSH::Expect](http://search.cpan.org/~bnegrao/Net-SSH-Expect-1.09/lib/Net/SSH/Expect.pod), which is a wrapper for your system's `ssh` and uses [Expect.pm](http://search.cpan.org/~rgiersig/Expect-1.21/Expect.pod). – ThisSuitIsBlackNot Jan 29 '14 at 22:50
  • 1
    @AugieDB: Especially when you deal with a large number of switches it seems to be a good idea to use some way of automatic authentication. Either by public-key, auth or with **expect**. The latter one can easily enter a preset password at the prompt. If you'd like to try this, here is a solution for this: http://stackoverflow.com/questions/459182/using-expect-to-pass-a-password-to-ssh This would also enable you to automatically import you priv-key into all those switches for the more secure key-auth. – Marlon Jan 30 '14 at 09:48