Script for gpg-agent startup to enable ssh login

I first did invoke gpg-connect-agent automatically after Windows 10 boot as it is recommended officially here. However, a few times, I experienced that SSH login nevertheless failed. I researched the web and found out that gpg-connect-agent should start gpg-agent. I, furthermore, discovered that the gpg-agent sometimes may be affected by Windows sleep mode or other system events. So I changed the procedure and now run the gpg-connect-agent command manually immediately before I need it. This also has the advantage that the command window will not pop up on each Windows start up even if one does not intend to perform an ssl login.

For this purpose, I then programmed a litte Python script which also checks whether the gpg-agent is actually running afterwards. If gpg-agent is running already before, it is killed and started again which should prevent its malfunction.

Here follows the simple script:

# Start-up gpg-agent for ssh login by putty using Nitrokey.
# This script was tested under Windows 10 (June 14, 2020).
import os

# This standard windows shell command gives returncode 0 if TASK runs:
# tasklist /fi "imagename eq TASK" 2>NUL | find /I /N "TASK">NUL
def is_task_running(taskname: str, output=False) -> bool:
  command = 'tasklist /fi "imagename eq ' + taskname + \
            '" 2>NUL | find /I /N "' + taskname + '">NUL'
  it_runs = os.system(command) == 0
  if output:
    print('task', taskname, 'is running:', it_runs)
  return it_runs

# gpg-agent.exe: GnuPG's private key daemon
# scdaemon.exe : GnuPG's smartcard daemon
# gpg-connect-agent.exe: utility to communicate with a running gpg-agent
# Precondition to use Nitrokey with putty on Windows:
#   c:\Users\UserName\AppData\Roaming\gnupg\gpg-agent.conf
#   must contain: enable-putty-support
# "gpg-connect-agent.exe /bye" should start up gpg-agent.exe
#   The so-called "control command" /bye means:
#   Terminate the connection and gpg-connect-agent"
# If it works, the output would be:
#   gpg-connect-agent: Kein aktiver gpg-agent 
#                      - 'gpg-agent.exe' wird gestartet
#   gpg-connect-agent: Warte bis der agent bereit ist ... (5s)
#   gpg-connect-agent: Verbindung zum agent aufgebaut
# gpg-agent must be running, otherwise auth with Nitrokey will fail!
# scdaemon.exe automatically started after ssh login with putty attempted 

is_task_running('scdaemon.exe', True)
agent = 'gpg-agent.exe'
agent_runs = is_task_running(agent)

# Full path not necessary since gpg-connect-agent in search path.
# "C:\\Program Files (x86)\\GnuPG\\bin\\gpg-connect-agent.exe"
# In case of login problems after sleep or other events, try
#   os.system('gpg-connect-agent "KILLAGENT" /bye')
# before agent start-up.
if not agent_runs:
  print('gpg-agent down, trying to start...')
  os.system('gpg-connect-agent /bye')
  print('gpg-agent already running, restart...')
  os.system('gpg-connect-agent "KILLAGENT" /bye')
  os.system('gpg-connect-agent /bye')

if is_task_running(agent, True):
  print('Startup failed...')

1 Like

In case you want to extend it, you may have a look into scd-event which is fired, when the stick is (un)-plugged. with telling the gpg-connect-agent "SCD CHECKPIN " you would also be able to react different depending on the card … just an idea

1 Like