Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

Populating authorized_keys with Expect

by cmv (Chaplain)
on Nov 24, 2008 at 18:46 UTC ( #725668=perlquestion: print w/replies, xml ) Need Help??

cmv has asked for the wisdom of the Perl Monks concerning the following question:


I have 2 questions here:

1.) Is this a reasonable implementation for populating the authorized_keys file for a user on a remote system under their login?
2.) Is doing this compromising security any?

The implementation relies on using expect to handle transporting the users typed-in password to ssh in order to populate far-end authorized_keys the first time. Thereafter the users ssh requests will not need a password anymore.

This requires that the user already has a public and private key setup on their local system. It does not need to worry about wether or not the private key is password protected or not. It just ships the public key over to the target system and installs it into their authorized_keys file.

The only thing I came up with in super-search on this topic, was scp and ssh without passwd, and I couldn't understand why doing this was effecting security any.



PS - Also, any suggested improvements are welcome!

UPDATE: s/crap/authorized_keys in example program

use strict; use warnings; use Expect; use Term::ReadKey; my $exp = new Expect; my $usr = 'myuser'; my $host = 'myhost'; my $pubkey = `cat $ENV{HOME}/.ssh/`; if(!$pubkey) { die "No public key" }; $exp->spawn("ssh $usr\@$host 'echo \"$pubkey\" >>.ssh/authorized_keys' +") || die "Dead Spawn"; $exp->expect(15, # This handles a first-time query from ssh about adding the target # machine to your known_hosts file if it isn't already there... [ '-re', '.*\(yes/no\)\? ', sub{ $exp->send("yes\n"); $exp->exp_continue; } ], # This handles the password prompt... [ 'assword: ', sub{ $exp->send(_GetPass($host, $usr) . "\r"); $exp->exp_continue; } ], # Handling EOF... [eof => sub { print "\nERROR: Got an EOF...\n"; } ], # Handling timeouts... [timeout => sub { die "\nERROR: Got a Timeout..\n"; } ], ); # This normally would be a GUI popup... sub _GetPass { my $host = shift || die "Missing host"; my $usr = shift || die "Missing usr"; ReadMode('noecho'); print "Enter $usr" . '@' . "$host Password: "; chomp(my $pw = ReadLine(0)); ReadMode('restore'); print "\n"; return ( $pw ); }

Replies are listed 'Best First'.
Re: Populating authorized_keys with Expect
by almut (Canon) on Nov 24, 2008 at 19:52 UTC

    Not sure I understand the specific benefits of using this script - compared to simply scp-ing the public key from the command line - but if a GUI popup for entering the password is preferred... why not.  Looks like a reasonable implementation to me.

    As to compromising security, I think it depends on how paranoid you are. The more the password gets passed around, i.e. the more locations in memory it'll ultimately be left behind, the easier it might be for someone to get hold of it... Whether that's an issue, depends on the particular circumstances, e.g. if this is a private machine of yours in a secured environment, and you're the only user, etc.

      One specific problem with scp is that it overwrites, not appends.

      I generally scp / sftp the credentials to a temporary file and then append or edit authorized_keys in an interactive session.

      Sometimes I drive it the other way: scp the existing authorized_keys from the remote machine, append the new credential locally and scp it back again.

      Neither of these approaches appear to solve the particular problem posed.

Re: Populating authorized_keys with Expect
by salva (Canon) on Nov 24, 2008 at 21:15 UTC
    You are not automating the process too much as the script is still querying the user for her password...

    You can do the same with just some shell lines:

    $hosts ="host1 host2 host3" # use ssh-keyscan to populate your "known_hosts" file first: ssh-keyscan $hosts >>~/.ssh/known_hosts # then append your key on the remote hosts: for h in $hosts do echo "*** copying key to $h ***" cat ~/.ssh/ | ssh $h 'cat >>~/.authorized_hosts' done
    update: read also ssh-copy-id man page!
Re: Populating authorized_keys with Expect
by jethro (Monsignor) on Nov 24, 2008 at 20:47 UTC

    I think your method is ok if you use it the right way:

    Never replace ssh with it, you have to name your script something else. That way you or anyone using it knows that he is doing something more than ssh. Otherwise someone (even you yourself in sleepy mode) might use ssh to do (for example) a login to a root account and make that root account vulnerable.

    Also you should be careful what connections you enable. Use this script only to connect from accounts you view as more or equally as secure as the accounts you connect to. Don't connect every account with every other account you have

    Public key access and passwords have different weaknesses. Passwords are vulnerable to keyboard sniffers, brute force password guessers and social hacks (the most simple: looking over the shoulder while you type it in). But an attacker needs time to break more of your accounts if he gets access to one of them. public keys are relatively safe against all of above, but an attacker gets them all as soon as he breaks into one.

Why I'm Populating authorized_keys with Expect
by cmv (Chaplain) on Nov 25, 2008 at 15:13 UTC

    Thanks to everyone for replying - I appreciate all comments!

    In this case, I failed to give you the context in which this script will be running. This may clear up some of the confusion on why I'm using this script.

    I have a perl script running on a PC. The goal is to get UDP packets flowing from remote machine B (remB) to the PC. The problem is that PC cannot directly connect to remB, and must go through remote machine A (remA) first. The remA machine is tightly controlled and I don't have many options to choose from. Here's what I'm planning (comments welcome):

    --------- -------- -------- | PC |-------| remA |-------| remB | --------- -------- --------

    The PC uses Net::SSH::Perl to contact remote machine A (remA) and sets up a UDP forwarder by remotely executing a short perl script there. Once that is done, we need to get remA to be able to remotely execute commands on remB to start the UDP flow. I can't use Net::SSH::Perl from remA because it's not installed there. Also, I can't use remA as a proxy to remB because sshd is setup to prevent that (hence the UDP forwarder). I also can't play any games with port forwarding because that's blocked as well.

    The idea is to prompt PC user to enter the password for remB then run the above perl script on remA to allow for password-less remote execute between the two. Now remA can run a bunch of commands on remB to get the UDP flow started (and do some other stuff). The UDP packets go from remB to remA, through the UDP forwarder and finally over to the PC.

    I'm open to other suggestions if there's a better way to do this, but this is what I came up with.



      With out knowing exactly what you can and can not do on remA it will difficult to help you!

      Can you run nc or ssh on remA?

      Is tunnel forwarding also disabled in remB sshd configuration?

        I cannot run nc on remA, since it is not installed, however I can use ssh.

        The nc binary does not exist on remA, and there is resistance to do what they consider as "downloading" programs to the machine. Since the machine already has perl, it was easier for me to write the simple UDP forwarding perl script and run it there.

        Running ssh on remA is no problem, which is why I'm using this solution. As you surmised, tunnel forwarding is disabled.

        Many thanks for helping, even with limited information. Please feel free to ask or point me to any other possibilities that might occur to you.



Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://725668]
Approved by almut
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (2)
As of 2023-10-01 13:14 GMT
Find Nodes?
    Voting Booth?

    No recent polls found