Managing an interactive process using PHP using the Symfony Process

I am trying to manage ssh-agent systems by adding new keys to it using ssh-add . For this, I use the Symfony Process component.

When I run this code from a website, it works fine, but when I run the same code in the shell / console, the ssh-add process hangs on Enter passphrase for <path to key>:

A simplified version of the code looks something like this:

 use Symfony\Component\Process\Process; $keyPath = '<path to key>'; $keyPassword = '<password for unlocking the key>'; $socketPath = '<path to ssh-agent socket>'; $sshAdd = new Process( "ssh-add {$keyPath}", null, [ 'SSH_AUTH_SOCK' => $socketPath ], $keyPassword ); $sshAdd->run(); 

As you can see in the above code, I make an ssh-add call, set SSH_AUTH_SOCK in the environment, so ssh-add can talk to the agent, and then sends the password to the login. As I said earlier, when I run this in a web context, it works, but it hangs in the shell / console context.

I did strace while working in the console, and the relevant parts look like this:

 open("<path to key>", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3 write(4, "<key password>", <length of password>) = 20 close(4) = 0 wait4(9650, 0x7fff00ab3554, WNOHANG|WSTOPPED, NULL) = 0 select(8, [5 7], [], [], {0, 0}) = 0 (Timeout) wait4(9650, 0x7fff00ab3554, WNOHANG|WSTOPPED, NULL) = 0 select(8, [5 7], [], [], {0, 0}) = 0 (Timeout) select(8, [5 7], [], [], {0, 200000}Enter passphrase for <path to key>:) = 0 (Timeout) select(8, [5 7], [], [], {0, 200000}) = 0 (Timeout) select(8, [5 7], [], [], {0, 200000}) = 0 (Timeout) select(8, [5 7], [], [], {0, 200000}) = 0 (Timeout) select(8, [5 7], [], [], {0, 200000}) = 0 (Timeout) ... 

As you can see, the entry seems to be ignored, and the ssh-add program begins to block waiting for input.

+6
source share
1 answer

Finally, I found a solution to this problem after reading the source for ssh-add and reading this very old article from Wez Furlong , where he talks about adding PTY support for PHP.

To quote an article:

What this does is like creating a channel for a process, but instead creates a master (for your script) and slave (for the process you are working on) pty descriptors using the / dev / ptmx interface of your OS. This allows you send and retrieve data from applications that open / dev / tty explicitly - and this is usually done with an interactive password request.

It turns out that Symfony Process also supports PTY, so the source code required only a couple of changes. First I need to indicate that I want to use PTY instead of pipes, calling setPty(true) . Then I need to simulate that the user pressed ENTER after entering the password, simply adding the feed line to the input.

The last code will look something like this (with comments on the modified lines)

 use Symfony\Component\Process\Process; $keyPath = '<path to key>'; $keyPassword = '<password for unlocking the key>'; $socketPath = '<path to ssh-agent socket>'; $sshAdd = new Process( "ssh-add {$keyPath}", null, [ 'SSH_AUTH_SOCK' => $socketPath ], $keyPassword . "\n" // Append a line feed to simulate pressing ENTER ); $sshAdd->setPty(true); // Use PTY instead of the default pipes $sshAdd->run(); 
+7
source

Source: https://habr.com/ru/post/978415/


All Articles