asyncssh icon indicating copy to clipboard operation
asyncssh copied to clipboard

Pageant still not used

Open pyhedgehog opened this issue 3 years ago • 2 comments

This issue is similiar to #215 and #331, but I still can't get it working. My setup is pageant-compatible agent (KeeAgent 0.12.1). Just to show, that my environment is working:

C:\>set SSH_AUTH_SOCK
Environment variable SSH_AUTH_SOCK not defined

C:\>C:\WINDOWS\System32\OpenSSH\ssh-add.exe -l|wc -l
2

C:\>C:\WINDOWS\System32\OpenSSH\ssh.exe 127.0.0.1 uptime
 01:43:33 up 4 days, 10:06,  0 users,  load average: 1.35, 1.42, 1.43

C:\>plink -ssh -batch %USERNAME%@127.0.0.1 uptime
 01:45:11 up 4 days, 10:08,  0 users,  load average: 1.37, 1.41, 1.43

But with asyncssh everything not so pretty:

C:\>py -3.8 -c "from unsync import unsync;import asyncssh;print(asyncssh.__name__, asyncssh.__version__);exec('@unsync\n
async def f(func,*args,**opts):\n  return await func(*args,**opts)\n');print(f(asyncssh.connect, '127.0.0.1', login_time
out=10).result())"
asyncssh 2.11.0
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\tools\python38\lib\site-packages\unsync\unsync.py", line 144, in result
    return self.concurrent_future.result(*args, **kwargs)
  File "C:\tools\python38\lib\concurrent\futures\_base.py", line 439, in result
    return self.__get_result()
  File "C:\tools\python38\lib\concurrent\futures\_base.py", line 388, in __get_result
    raise self._exception
  File "<string>", line 3, in f
  File "C:\tools\python38\lib\site-packages\asyncssh\connection.py", line 7713, in connect
    return await asyncio.wait_for(
  File "C:\tools\python38\lib\asyncio\tasks.py", line 455, in wait_for
    return await fut
  File "C:\tools\python38\lib\site-packages\asyncssh\connection.py", line 440, in _connect
    await options.waiter
asyncssh.misc.PermissionDenied: Permission denied

My question is: How should I call asyncssh.connect() to use agent?

PS: I'm using unsync here only to construct one-liner and minimize demo code.

pyhedgehog avatar Jun 28 '22 00:06 pyhedgehog

I'm not quite sure I'm following the tests you're running here.

In my experience, OpenSSH (including ssh-add) doesn't work with Pageant, and so I'd only expect your calls to ssh-add.exe to work if you did had an OpenSSH-compatible agent running.

When I try running ssh-add here on a system with Pageant running but not ssh-agent, I get the error "Error connection to agent: No such file or directory". If I start the ssh-agent service manually by running "ssh-agent" (after setting the service's StartupType to "Manual"), I'm then able to run "ssh-add", but that doesn't involve Pageant in any way.

To test Pageant, I usually use PuTTY. Whether or not I have an ssh-agent running, PuTTY will attempt to access keys loaded in Pageant when it is running.

By default, AsyncSSH should look at SSH_AUTH_SOCK to try and find the path to a running ssh-agent if it is set, but should automatically fall back to Pageant if SSH_AUTH_SOCK is not set. If it can't access Pageant, it will then fall back to trying to access ssh-agent using the default OpenSSH path, which is a pipe named "OpenSSH-ssh-agent".

That said, I just did some testing here, and I think I found a problem. It looks like everything works fine when agent_path is set to a string, but in the case where it is set to its default value and there's no SSH_AUTH_SOCK set, it ends up being treated as if it were set to None, completely disabling the agent rather than letting it use Pageant or the default Windows SSH agent path.

I think the following change should fix this:

diff --git a/asyncssh/connection.py b/asyncssh/connection.py
index 6246811..2e551bd 100644
--- a/asyncssh/connection.py
+++ b/asyncssh/connection.py
@@ -7018,9 +7018,9 @@ class SSHClientConnectionOptions(SSHConnectionOptions):

         if agent_path == ():
             agent_path = \
-                cast(DefTuple[str], os.environ.get('SSH_AUTH_SOCK', None))
+                cast(DefTuple[str], os.environ.get('SSH_AUTH_SOCK', ''))

-        agent_path = str(Path(agent_path).expanduser()) if agent_path else None
+        agent_path = str(Path(agent_path).expanduser()) if agent_path else ''

         if pkcs11_provider == ():
             pkcs11_provider = \

I'll get this into the develop branch after I do a bit more testing on it, but so far this looks good here. If it doesn't work for you, please let me know!

ronf avatar Jun 28 '22 04:06 ronf

The change above plus some improvements that should hopefully reduce the chance of this happening again is now available in commit 82ad31a in the "develop" branch.

ronf avatar Jun 29 '22 03:06 ronf

These changes are now available in AsyncSSH 2.12.0.

ronf avatar Aug 11 '22 05:08 ronf