0

I need to copy two programs from one server to another after compiling using an automated non-interactive python script. Keys are not an option as this script is for multiple users on company servers and both keys and passwords are required. Passwords are not being stored in the program, but are being asked once at the start of the program using getpass(), and then used for both SCP transfers so that the user doesn't have to enter their password for each scp call. I'm using os.system to call scp:

os.system("/usr/bin/scp %s %s@server:directory" %(prg, uname))
os.system("/usr/bin/scp %s %s@server:directory2" %(prg2, uname))

scp is defined for another program, thus /usr/bin/scp. prg/prg2 is the program's location and uname is the users username on the remote server(s).

I tried piping the password, like described here, however it did not work.

I can't install sshpass, expect, paramiko, or fabric, and I can't use rsync b/c it isn't installed on the receiving server. Is there anything that I can do to automate this?

I'm running AIX 6.1, Python 2.6.2

UPDATE: I can't install external libraries, such as pexpect, either because AIX doesn't have a /config folder in the python install directory. A fix for that is to install python-devel for AIX, but I can't install program, so I'm still stuck.

UPDATE 2: I decided to forgo SCP in favor of FTP. I used a combination of this and this to make my FTP script. Thanks for your answers and helping guide me.

Community
  • 1
  • 1
Jacob Hayes
  • 13
  • 1
  • 4
  • Maybe I'm off-base here, but isn't the requirement for the key an SSH Server side requirement? Thus, unless the server side can be configured to not use keys (some SSH server can, some can't), then this may not be possible – Raceyman Jul 27 '12 at 17:50
  • Yes, but my company doesn't allow key-only logins. They use both pubkeys and passwords to authenticate, which are just accepted on first connection. – Jacob Hayes Jul 27 '12 at 17:53
  • then I can't think of an alternative other than what Igor outlines below. – Raceyman Jul 27 '12 at 18:09
  • You could roll your own "mini-expect" by using functions in the os module (forkpty, etc), or try the subprocess module. – Keith Jul 27 '12 at 18:17

2 Answers2

2

Since you have to implement this in pure Python with no install rights, you're down to reinventing the wheel, and it sucks. What you need in this case is the SSH_ASKPASS loophole.

SSH really doesn't want you to just give it a password - after all, that's what keyfiles are for. However, if the SSH_ASKPASS environment variable is set, and the DISPLAY environment variable is set, and ssh is not running inside a TTY, it'll execute the ASKPASS program (whilst keeping its environment variables from the context that the ASKPASS program was called from). As a result, if you're clever about it, you can set up an echoing program as your ASKPASS and coerce ssh to do what you want that way.

Here's a snippet from code that I've seen used to do this - this is not complete (it's lifted from the middle of a module), but it should get you started. We used base64 to put a fig leaf over our passwords in this one.

def createConnection(self, hostName, username, password):
    """ Because we're setting both stdout and stderr to be pipes, we have
        to worry about one of them clogging - We'll be reading stdout
        constantly through the code, but stderr needs a worker to handle
        it. """

    env = {'SSH_ASKPASS': '/path/to/echo/script',
           'DISPLAY': 'required',
           'ENCODED_PASSWORD': base64.b64encode(password)}
    self.username = username
    self.hostName = hostName
    self.sshProcess = subprocess.Popen(
        ['/usr/bin/ssh', '-T',
         '-o', 'UserKnownHostsFile=/dev/null',
         '-o', 'StrictHostKeyChecking=no',
         '-o', 'NumberOfPasswordPrompts=1',
         '-o', 'ConnectTimeout=10',
         '%s@%s' % (username, hostName),
         '-s', 'xmlagent',
        ],
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        env=env,

        #this kicks it out of the controlling tty session
        preexec_fn=os.setsid
    )

    self.sshStderr = ''
    self.errorThread = threading.Thread(target=self.readStderr)
    self.errorThread.daemon = True
    self.errorThread.start()
Brighid McDonnell
  • 4,293
  • 4
  • 36
  • 61
  • Addendum from my four-years-later self: just in case you hadn't noticed, using this tactic requires opening yourself up to heinous security problems. These problems are language-independent: they are the result of going _way_ far out of your way to tell SSH "hey, behave less securely." Do your best to avoid situations where you need this. – Brighid McDonnell Jul 26 '16 at 22:23
1

You need to use pexpect.

Example of usage (from Automate SSH without using public key authentication or expect(1)):

import pexpect

FILE="/path/to/file"
REMOTE_FILE=""
USER="user"
HOST="example.com"
PASS="mypass"
COMMAND="scp -oPubKeyAuthentication=no %s %s@%s:%s" % (FILE, USER, HOST, REMOTE_FILE)

child = pexpect.spawn(COMMAND)
child.expect('password:')
child.sendline(PASS)
child.expect(pexpect.EOF)
print child.before

You can also try expect (and then run the script from python; it is a good solution if you can't install pexpect):

#!/usr/bin/expect -f
set filename [lindex $argv 0]
set timeout -1
spawn scp $filename myusername@192.168.1.123:/home/myusername/
set pass "mypassword"
expect {
         password: {send "$pass\r" ; exp_continue}
         eof exit
}
Community
  • 1
  • 1
Igor Chubin
  • 61,765
  • 13
  • 122
  • 144
  • Quick reply! When I import pexpect, I get an error saying no module found. Is it standard, or is from an external library? I can't install external libraries, as well, if so. – Jacob Hayes Jul 27 '12 at 17:08
  • yes it is an expternal module. but you can install external modules of course, you need no root-rights for that. This module will be accessible only for you. – Igor Chubin Jul 27 '12 at 17:13
  • @Jakeanator1 -- It is an external module, but, as far as I know, it is written in pure python adding it should be no problem. (worst case scenario you install into `~/my_python_modules` and add that to `PYTHONPATH`). – mgilson Jul 27 '12 at 17:14
  • When I run python ./setup.py install, I get this error: invalid Python installation: unable to open /opt/freeware/lib/python2.6/config/Makefile (No such file or directory) The python2.6 folder is there, but no config folder. I can use python for other things, so it is installed. Any ideas on this error? UPDATE: I think this is a problem related to AIX. I'm looking into it, and will post back later. – Jacob Hayes Jul 27 '12 at 17:35
  • A fix for the /config folder is to install [python-devel](ftp://ftp.software.ibm.com/aix/freeSoftware/aixtoolbox/RPMS/ppc/python/python-devel-2.6.2-1.aix5.3.ppc.rpm) on AIX, however as I can't install things, I'm stuck. – Jacob Hayes Jul 27 '12 at 17:48