ovftool is a command-line utility from VMware that lets one do useful things
with VMs on ESXi and vSphere remote systems.
I had installed
ovftool and was trying to use it copy a VM between two ESXi
servers, based on this useful post from virtuallyGhetto. For various
reasons, it’s often a better idea to use
ovftool for copying VMs than by just
scp on the raw files.
Immediately, I ran into a WTF? moment.
$ ovftool vi://firstname.lastname@example.org/ Enter login information for source vi://10.1.2.3/ Username: root Password: ******* Error: Could not lookup host: root
Error: Could not lookup host: root???
This confused the living daylights out of me. This has nothing at all to do with looking up a host.
And the answer is… drum roll…
Locators. At least, the URI-flavored ones. A locator points to different resource types like VMs or hosts.
ovftool gets a URI, it’s more or less of the form
protocol can be one of the standard schemes like
VMware-specific ones like
ovftool gets a URI without the password - which I would imagine most
security conscious people would prefer - it quite sensibly prompts for a
password and captures it without displaying it.
At this point, it appears that
ovftool forms the full URI - including
password - and uses that to authenticate with the remote system.
You can see where this is going.
ovftool PDF manual clearly notes (but not clearly enough, in my view):
Encoding Special Characters in URL Locators When you use URIs as locators, you must escape special characters using % followed by their ASCII hex value. For instance, if you use a “@” in your password, it must be escaped with %40 as in vi://foo:b%40r@hostname, and a slash in a Windows domain name (\) can be specified as %5c.
Now I get it.
ovftoolcaptures the password from stdin and does not urlencode it.
ovftoolforms the URI with the unencoded password, and does not check it for validity.
ovftooluses the URI to contact the remote system.
- The malformed URI is interpreted such that the user name -
rootin this case - is considered to be the remote system’s host name.
- The connection attempt dies with the oh-so-misleading message,
Error: Could not lookup host: root.
- I get a headache.
This hypothesis can be proven as follows.
- urlencode the failing password;
- Feed the encoded password to
What I think
ovftool does wrong
ovftoolviolates The principle of Least Astonishment. When a tool accepts a password for input, it is expected that the tool does any necessary transformations to it prior to using it.
ovftoolmust urlencode the password if it obtains it via a password prompt.
ovftoolfails to check that the URI is well-formed. The characters that must be urlencoded in the various parts of a URI are well-known, and it should be fairly easy to test this.
- A more minor, yet valid quibble, is that
ovftoolechoes asterisks once the password has been entered, which is ok, except that it echoes the same number of asterisks as the number of characters in the password. Exact password length can give a useful clue to a would-be attacker (who would need to be looking over your shoulder, but still, it’s so easy to avoid this mistake).
A simple workaround
A simple workaround is to urlencode the password yourself on the command line. If you have access to a clipboard-copy-paste utility, the entire thing can be done without displaying the password.
Let’s say that your password is
This code snippet will prompt for the unencoded password, urlencode it, and put it into the clipboard, ready for pasting. The advantage of using this over the various command-line urlencoding utilities - that might or might not be available - is that Python is available just about everywhere these days. If not, there’s always Perl.
python -c 'import urllib; import getpass; print(urllib.quote_plus(getpass.getpass()))' | $CLIPUTIL
Possible values of
- Windows 10:
clip(or redirect to
/dev/clipboardin older versions)
- Linux (X):
xclip -selection c