From 3bfcd771ebcaffaefe84a66f3fa0b6a9fdb98373 Mon Sep 17 00:00:00 2001 From: s1kx Date: Wed, 24 Aug 2016 17:00:49 -0700 Subject: [PATCH] Fix compatibility issues with SSH_ASKPASS. Background: Previously, ssh-agent was run in an empty environment. This caused the agent to fail when a key was added with ssh-add -c and SSH_ASKPASS is set. When ssh-add was called with SSH_ASKPASS, the passphrase was still read from the terminal and the askpass program was not called. In this commit - ssh-ident detects if SSH_ASKPASS is set and invokes ssh-add with {0}".format(agentfile)]) - return agentfile + + # Pass only a subset of environment variables to ssh-agent. + env_filter = {'PATH', 'DISPLAY', 'XAUTHORITY', 'SSH_ASKPASS'} + agent_env = { k: v for k, v in os.environ.items() if k in env_filter } + + # Redirect shell instructions from stdout to agent-file and debug output to + # STDOUT if in DEBUG mode. + shell_args = "-c" + agent_flags = "" + agent_fork = "" + log_pipe = None + if ShouldPrint(config, LOG_DEBUG): + shell_args = "-xc" + agent_flags = "-d" + agent_fork = "&" + log_pipe = sys.stderr + + shell_command = "ssh-agent {0} 1>&{1} {2}".format( + agent_flags, agent_file, agent_fork) + command = ["/bin/sh", shell_args, shell_command] + + # Start ssh-agent with restricted environment variables. + p = subprocess.Popen(command, env=agent_env, stderr=log_pipe) + + # Wait until agent has forked. + p.wait() + + return agent_file @staticmethod def IsAgentFileValid(agentfile): @@ -766,21 +801,20 @@ class AgentManager(object): return True @staticmethod - def RunShellCommand(command): + def RunShellCommand(command, shell_args = None): """Runs a shell command, returns (status, stdout), (int, string).""" - command = ["/bin/sh", "-c", command] + if not shell_args: + shell_args = "-c" + command = ["/bin/sh", shell_args, command] process = subprocess.Popen(command, stdout=subprocess.PIPE) stdout, stderr = process.communicate() return process.wait(), stdout @staticmethod - def RunShellCommandInAgent(agentfile, command): + def RunShellCommandInAgent(agentfile, command, shell_args = None): """Runs a shell command with an agent configured in the environment.""" - command = ["/bin/sh", "-c", - ". {0} >/dev/null 2>/dev/null; {1}".format(agentfile, command)] - process = subprocess.Popen(command, stdout=subprocess.PIPE) - stdout, stderr = process.communicate() - return process.wait(), stdout + shell_command = ". {0} >/dev/null 2>/dev/null; {1}".format(agentfile, command) + return AgentManager.RunShellCommand(shell_command, shell_args) @staticmethod def EscapeShellArguments(argv): @@ -845,7 +879,7 @@ def AutodetectBinary(argv, config): # The logic here is pretty straightforward: # - Try to eliminate the path of ssh-ident from PATH. # - Search for a binary with the same name of ssh-ident to run. - # + # # If this fails, we may end up in some sort of loop, where ssh-ident # tries to run itself. This should normally be detected later on, # where the code checks for the next binary to run. @@ -897,7 +931,7 @@ def AutodetectBinary(argv, config): ssh-ident was invoked in place of the binary {0} (determined from argv[0]). Neither this binary nor 'ssh' could be found in $PATH. - PATH="{1}" + PATH="{1}" You need to adjust your setup for ssh-ident to work: consider setting BINARY_SSH or BINARY_DIR in your config, or running ssh-ident some @@ -956,8 +990,8 @@ def main(argv): message = textwrap.dedent("""\ ssh-ident found '{0}' as the next command to run. Based on argv[0] ({1}), it seems like this will create a - loop. - + loop. + Please use BINARY_SSH, BINARY_DIR, or change the way ssh-ident is invoked (eg, a different argv[0]) to make it work correctly.""")