isislovecruft / python-gnupg

A modified version of python-gnupg, including security patches, extensive documentation, and extra features.
Other
424 stars 172 forks source link

Popen Failing due to invalid _make_args #214

Open Tuxprogrammer opened 6 years ago

Tuxprogrammer commented 6 years ago

I'm using the 2.3.1 release version running on Python 3.6.1 64-bit. This issue is probably related to issue #161 and #144.

I noticed when debugging that the _make_args() function in _meta.py is not generating command line arguments correctly, because it is stripping self.binary of path separators on Windows.

cmd = shlex.split(' '.join(self._make_args(args, passphrase)))

This is the resulting array from that command: <class 'list'>: ['C:gnupggpg.exe', '--no-options', '--no-emit-version', '--no-tty', '--status-fd', '2', '--homedir', "'C:\\Users\\tuxpr\\AppData\\Roaming\\gnupg\\'", '--no-default-keyring', '--keyring', 'C:\\Users\\tuxpr\\AppData\\Roaming\\gnupg\\pubring.gpg', '--secret-keyring', 'C:\\Users\\tuxpr\\AppData\\Roaming\\gnupg\\secring.gpg', '--no-use-agent', '--debug-all', '--debug-level=basic', '--list-config', '--with-colons']

Notice the first element, 'C:gnupggpg.exe' should be 'C:\\gnupg\\gpg.exe'. I can manually inject that value during debug, but there is still another problem with the control of the Popen call.

Spaces present an entirely new problem. Here is another cmd array: <class 'list'>: ['C:Program', 'Files', '(x86)GnuPGbingpg.exe', '--no-options', '--no-emit-version', '--no-tty', '--status-fd', '2', '--homedir', "'C:\\Users\\tuxpr\\AppData\\Roaming\\gnupg\\'", '--no-default-keyring', '--keyring', 'C:\\Users\\tuxpr\\AppData\\Roaming\\gnupg\\pubring.gpg', '--secret-keyring', 'C:\\Users\\tuxpr\\AppData\\Roaming\\gnupg\\secring.gpg', '--no-use-agent', '--debug-all', '--debug-level=basic', '--list-config', '--with-colons']

The path for that call is supposed to be "C:\\Program Files (x86)\\GnuPG\\bin\\gpg.exe", but it seems to be splitting on each space, and stripping the path separators.

After Popen is called, you must call proc.wait() in _check_sane_and_get_gpg_version before reading any values back from the subprocess, otherwise no execution has occurred.

After proc.wait() returns, you can then access the proc.returncode and read output data from the process. If proc.wait() hangs, then gpg has been invoked but doesn't understand the arguments given, and is waiting for user input by default.

Hope this helps someone on the code side of things. I'm not familiar enough with the way that shlex.split() works or I'd write it myself.