Merge remote-tracking branch 'upstream/master' into doc-enhancements2

master
rendaw 6 years ago
commit 95e98d6eda

@ -5,7 +5,7 @@ and please let me [know](https://github.com/romanz/trezor-agent/issues/new) if s
work well for you. If possible: work well for you. If possible:
* record the session (e.g. using [asciinema](https://asciinema.org)) * record the session (e.g. using [asciinema](https://asciinema.org))
* attach the GPG agent log from `~/.gnupg/{trezor,ledger}/gpg-agent.log` * attach the GPG agent log from `~/.gnupg/{trezor,ledger}/gpg-agent.log` (can be [encrypted](https://keybase.io/romanz))
Thanks! Thanks!

@ -115,3 +115,55 @@ Note that your local SSH configuration may ignore `trezor-agent`, if it has `Ide
If you are failing to connect, try running: If you are failing to connect, try running:
$ trezor-agent -vv user@host -- ssh -vv -oIdentitiesOnly=no user@host $ trezor-agent -vv user@host -- ssh -vv -oIdentitiesOnly=no user@host
# Start the agent as a systemd unit
##### 1. Create these files in `~/.config/systemd/user`
Replace `trezor` with `keepkey` or `ledger` as required.
###### `trezor-ssh-agent.service`
````
[Unit]
Description=trezor-agent SSH agent
Requires=trezor-ssh-agent.socket
[Service]
Type=Simple
ExecStart=/usr/bin/trezor-agent --foreground --sock-path %t/trezor-agent/S.ssh IDENTITY
````
Replace `IDENTITY` with the identity you used when exporting the public key.
###### `trezor-ssh-agent.socket`
````
[Unit]
Description=trezor-agent SSH agent socket
[Socket]
ListenStream=%t/trezor-agent/S.ssh
FileDescriptorName=ssh
Service=trezor-ssh-agent.service
SocketMode=0600
DirectoryMode=0700
[Install]
WantedBy=sockets.target
````
##### 2. Run
```
systemctl --user start trezor-ssh-agent.service trezor-ssh-agent.socket
systemctl --user enable trezor-ssh-agent.socket
```
##### 3. Add this line to your `.bashrc` or equivalent file:
```bash
export SSH_AUTH_SOCK=$(systemctl show --user --property=Listen trezor-ssh-agent.socket | grep -o "/run.*")
```
##### 4. SSH will now automatically use your device key in all terminals.

@ -57,21 +57,25 @@ class Trezor(interface.Device):
cli_handler = conn.callback_PinMatrixRequest cli_handler = conn.callback_PinMatrixRequest
def new_handler(msg): def new_handler(msg):
if _is_open_tty(sys.stdin): try:
result = cli_handler(msg) # CLI-based PIN handler if _is_open_tty(sys.stdin):
else: result = cli_handler(msg) # CLI-based PIN handler
scrambled_pin = _message_box( else:
'Use the numeric keypad to describe number positions.\n' scrambled_pin = _message_box(
'The layout is:\n' 'Use the numeric keypad to describe number positions.\n'
' 7 8 9\n' 'The layout is:\n'
' 4 5 6\n' ' 7 8 9\n'
' 1 2 3\n' ' 4 5 6\n'
'Please enter PIN:') ' 1 2 3\n'
result = self._defs.PinMatrixAck(pin=scrambled_pin) 'Please enter PIN:')
if not set(result.pin).issubset('123456789'): result = self._defs.PinMatrixAck(pin=scrambled_pin)
raise self._defs.PinException( if not set(result.pin).issubset('123456789'):
None, 'Invalid scrambled PIN: {!r}'.format(result.pin)) raise self._defs.PinException(
return result None, 'Invalid scrambled PIN: {!r}'.format(result.pin))
return result
except: # noqa
conn.init_device()
raise
conn.callback_PinMatrixRequest = new_handler conn.callback_PinMatrixRequest = new_handler
@ -81,20 +85,24 @@ class Trezor(interface.Device):
cli_handler = conn.callback_PassphraseRequest cli_handler = conn.callback_PassphraseRequest
def new_handler(msg): def new_handler(msg):
if self.__class__.cached_passphrase_ack: try:
log.debug('re-using cached %s passphrase', self) if self.__class__.cached_passphrase_ack:
return self.__class__.cached_passphrase_ack log.debug('re-using cached %s passphrase', self)
return self.__class__.cached_passphrase_ack
if _is_open_tty(sys.stdin):
# use CLI-based PIN handler if _is_open_tty(sys.stdin):
ack = cli_handler(msg) # use CLI-based PIN handler
else: ack = cli_handler(msg)
passphrase = _message_box('Please enter passphrase:') else:
passphrase = mnemonic.Mnemonic.normalize_string(passphrase) passphrase = _message_box('Please enter passphrase:')
ack = self._defs.PassphraseAck(passphrase=passphrase) passphrase = mnemonic.Mnemonic.normalize_string(passphrase)
ack = self._defs.PassphraseAck(passphrase=passphrase)
self.__class__.cached_passphrase_ack = ack
return ack self.__class__.cached_passphrase_ack = ack
return ack
except: # noqa
conn.init_device()
raise
conn.callback_PassphraseRequest = new_handler conn.callback_PassphraseRequest = new_handler

@ -126,7 +126,11 @@ def run_init(device_type, args):
homedir = os.path.expanduser('~/.gnupg/{}'.format(device_name)) homedir = os.path.expanduser('~/.gnupg/{}'.format(device_name))
log.info('GPG home directory: %s', homedir) log.info('GPG home directory: %s', homedir)
check_call(['rm', '-rf', homedir]) if os.path.exists(homedir):
log.error('GPG home directory %s exists, '
'remove it manually if required', homedir)
sys.exit(1)
check_call(['mkdir', '-p', homedir]) check_call(['mkdir', '-p', homedir])
check_call(['chmod', '700', homedir]) check_call(['chmod', '700', homedir])

@ -88,6 +88,8 @@ def create_agent_parser(device_type):
g = p.add_mutually_exclusive_group() g = p.add_mutually_exclusive_group()
g.add_argument('-d', '--daemonize', default=False, action='store_true', g.add_argument('-d', '--daemonize', default=False, action='store_true',
help='Daemonize the agent and print its UNIX socket path') help='Daemonize the agent and print its UNIX socket path')
g.add_argument('-f', '--foreground', default=False, action='store_true',
help='Run agent in foreground with specified UNIX socket path')
g.add_argument('-s', '--shell', default=False, action='store_true', g.add_argument('-s', '--shell', default=False, action='store_true',
help=('run ${SHELL} as subprocess under SSH agent, allowing ' help=('run ${SHELL} as subprocess under SSH agent, allowing '
'regular SSH-based tools to be used in the shell')) 'regular SSH-based tools to be used in the shell'))
@ -211,6 +213,17 @@ def _dummy_context():
yield yield
def _get_sock_path(args):
sock_path = args.sock_path
if not sock_path:
if args.foreground:
log.error('running in foreground mode requires specifying UNIX socket path')
sys.exit(1)
else:
sock_path = tempfile.mktemp(prefix='trezor-ssh-agent-')
return sock_path
@handle_connection_error @handle_connection_error
def main(device_type): def main(device_type):
"""Run ssh-agent using given hardware client factory.""" """Run ssh-agent using given hardware client factory."""
@ -232,9 +245,7 @@ def main(device_type):
identity.identity_dict['proto'] = u'ssh' identity.identity_dict['proto'] = u'ssh'
log.info('identity #%d: %s', index, identity.to_string()) log.info('identity #%d: %s', index, identity.to_string())
sock_path = args.sock_path sock_path = _get_sock_path(args)
if not sock_path:
sock_path = tempfile.mktemp(prefix='trezor-ssh-agent-')
command = args.command command = args.command
context = _dummy_context() context = _dummy_context()
@ -248,6 +259,8 @@ def main(device_type):
sys.stdout.flush() sys.stdout.flush()
context = daemon.DaemonContext() context = daemon.DaemonContext()
log.info('running the agent as a daemon on %s', sock_path) log.info('running the agent as a daemon on %s', sock_path)
elif args.foreground:
log.info('running the agent on %s', sock_path)
use_shell = bool(args.shell) use_shell = bool(args.shell)
if use_shell: if use_shell:
@ -258,7 +271,7 @@ def main(device_type):
conn_factory=lambda: client.Client(device_type()), conn_factory=lambda: client.Client(device_type()),
identities=identities, public_keys=public_keys) identities=identities, public_keys=public_keys)
if command or args.daemonize: if command or args.daemonize or args.foreground:
with context: with context:
return run_server(conn=conn, command=command, sock_path=sock_path, return run_server(conn=conn, command=command, sock_path=sock_path,
debug=args.debug, timeout=args.timeout) debug=args.debug, timeout=args.timeout)

Loading…
Cancel
Save