pinentry: specify device name at PIN/passphrase entry UI
This commit is contained in:
parent
870152a7af
commit
d0497b0137
@ -30,37 +30,36 @@ def _create_default_options_getter():
|
|||||||
class UI(object):
|
class UI(object):
|
||||||
"""UI for PIN/passphrase entry (for TREZOR devices)."""
|
"""UI for PIN/passphrase entry (for TREZOR devices)."""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, device_type, config):
|
||||||
"""C-tor."""
|
"""C-tor."""
|
||||||
|
default_pinentry = 'pinentry' # by default, use GnuPG pinentry tool
|
||||||
|
self.pin_entry_binary = config.get('pin_entry_binary',
|
||||||
|
default_pinentry)
|
||||||
|
self.passphrase_entry_binary = config.get('passphrase_entry_binary',
|
||||||
|
default_pinentry)
|
||||||
self.options_getter = _create_default_options_getter()
|
self.options_getter = _create_default_options_getter()
|
||||||
self.pin_entry_binary = 'pinentry'
|
self.device_name = device_type.__name__
|
||||||
self.passphrase_entry_binary = 'pinentry'
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_config_dict(cls, d):
|
|
||||||
"""Simple c-tor from configuration dictionary."""
|
|
||||||
obj = cls()
|
|
||||||
obj.pin_entry_binary = d.get('pin_entry_binary',
|
|
||||||
obj.pin_entry_binary)
|
|
||||||
obj.passphrase_entry_binary = d.get('passphrase_entry_binary',
|
|
||||||
obj.passphrase_entry_binary)
|
|
||||||
return obj
|
|
||||||
|
|
||||||
def get_pin(self):
|
def get_pin(self):
|
||||||
"""Ask the user for (scrambled) PIN."""
|
"""Ask the user for (scrambled) PIN."""
|
||||||
return pinentry.interact(
|
description = (
|
||||||
'Use the numeric keypad to describe number positions.\n'
|
'Use the numeric keypad to describe number positions.\n'
|
||||||
'The layout is:\n'
|
'The layout is:\n'
|
||||||
' 7 8 9\n'
|
' 7 8 9\n'
|
||||||
' 4 5 6\n'
|
' 4 5 6\n'
|
||||||
' 1 2 3\n'
|
' 1 2 3')
|
||||||
'Please enter PIN:',
|
return pinentry.interact(
|
||||||
|
title='{} PIN'.format(self.device_name),
|
||||||
|
prompt='PIN:',
|
||||||
|
description=description,
|
||||||
binary=self.pin_entry_binary,
|
binary=self.pin_entry_binary,
|
||||||
options=self.options_getter())
|
options=self.options_getter())
|
||||||
|
|
||||||
def get_passphrase(self):
|
def get_passphrase(self):
|
||||||
"""Ask the user for passphrase."""
|
"""Ask the user for passphrase."""
|
||||||
return pinentry.interact(
|
return pinentry.interact(
|
||||||
'Please enter passphrase:',
|
title='{} passphrase'.format(self.device_name),
|
||||||
|
prompt='Passphrase:',
|
||||||
|
description=None,
|
||||||
binary=self.passphrase_entry_binary,
|
binary=self.passphrase_entry_binary,
|
||||||
options=self.options_getter())
|
options=self.options_getter())
|
||||||
|
@ -26,7 +26,7 @@ def expect(p, prefixes):
|
|||||||
raise ValueError('Unexpected response: {}'.format(resp))
|
raise ValueError('Unexpected response: {}'.format(resp))
|
||||||
|
|
||||||
|
|
||||||
def interact(description, binary, options):
|
def interact(title, description, prompt, binary, options):
|
||||||
"""Use GPG pinentry program to interact with the user."""
|
"""Use GPG pinentry program to interact with the user."""
|
||||||
p = subprocess.Popen(args=[binary],
|
p = subprocess.Popen(args=[binary],
|
||||||
stdin=subprocess.PIPE,
|
stdin=subprocess.PIPE,
|
||||||
@ -34,10 +34,20 @@ def interact(description, binary, options):
|
|||||||
env=os.environ)
|
env=os.environ)
|
||||||
expect(p, [b'OK'])
|
expect(p, [b'OK'])
|
||||||
|
|
||||||
description = libagent.gpg.agent.serialize(description.encode('ascii'))
|
title = libagent.gpg.agent.serialize(title.encode('ascii'))
|
||||||
write(p, b'SETDESC ' + description + b'\n')
|
write(p, b'SETTITLE ' + title + b'\n')
|
||||||
expect(p, [b'OK'])
|
expect(p, [b'OK'])
|
||||||
|
|
||||||
|
if description:
|
||||||
|
description = libagent.gpg.agent.serialize(description.encode('ascii'))
|
||||||
|
write(p, b'SETDESC ' + description + b'\n')
|
||||||
|
expect(p, [b'OK'])
|
||||||
|
|
||||||
|
if prompt:
|
||||||
|
prompt = libagent.gpg.agent.serialize(prompt.encode('ascii'))
|
||||||
|
write(p, b'SETPROMPT ' + prompt + b'\n')
|
||||||
|
expect(p, [b'OK'])
|
||||||
|
|
||||||
log.debug('setting %d options', len(options))
|
log.debug('setting %d options', len(options))
|
||||||
for opt in options:
|
for opt in options:
|
||||||
write(p, b'OPTION ' + opt + b'\n')
|
write(p, b'OPTION ' + opt + b'\n')
|
||||||
|
@ -226,7 +226,8 @@ def run_agent(device_type):
|
|||||||
env = {'GNUPGHOME': args.homedir}
|
env = {'GNUPGHOME': args.homedir}
|
||||||
sock_path = keyring.get_agent_sock_path(env=env)
|
sock_path = keyring.get_agent_sock_path(env=env)
|
||||||
pubkey_bytes = keyring.export_public_keys(env=env)
|
pubkey_bytes = keyring.export_public_keys(env=env)
|
||||||
device_type.ui = device.ui.UI.from_config_dict(vars(args))
|
device_type.ui = device.ui.UI(device_type=device_type,
|
||||||
|
config=vars(args))
|
||||||
handler = agent.Handler(device=device_type(), pubkey_bytes=pubkey_bytes)
|
handler = agent.Handler(device=device_type(), pubkey_bytes=pubkey_bytes)
|
||||||
with server.unix_domain_socket_server(sock_path) as sock:
|
with server.unix_domain_socket_server(sock_path) as sock:
|
||||||
for conn in agent.yield_connections(sock):
|
for conn in agent.yield_connections(sock):
|
||||||
@ -279,6 +280,6 @@ def main(device_type):
|
|||||||
p.set_defaults(func=run_unlock)
|
p.set_defaults(func=run_unlock)
|
||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
device_type.ui = device.ui.UI.from_config_dict(vars(args))
|
device_type.ui = device.ui.UI(device_type=device_type, config=vars(args))
|
||||||
|
|
||||||
return args.func(device_type=device_type, args=args)
|
return args.func(device_type=device_type, args=args)
|
||||||
|
@ -273,7 +273,7 @@ def main(device_type):
|
|||||||
sys.stdin.close()
|
sys.stdin.close()
|
||||||
|
|
||||||
# override default PIN/passphrase entry tools (relevant for TREZOR/Keepkey):
|
# override default PIN/passphrase entry tools (relevant for TREZOR/Keepkey):
|
||||||
device_type.ui = device.ui.UI.from_config_dict(vars(args))
|
device_type.ui = device.ui.UI(device_type=device_type, config=vars(args))
|
||||||
|
|
||||||
conn = JustInTimeConnection(
|
conn = JustInTimeConnection(
|
||||||
conn_factory=lambda: client.Client(device_type()),
|
conn_factory=lambda: client.Client(device_type()),
|
||||||
|
Loading…
Reference in New Issue
Block a user