1
0

Trezor: session timeout improvements

Move session timeout from wallet to config
Prevent timeouts whenever a device operation is in progress
Move timeout job from each plugin to device manager
This commit is contained in:
Neil Booth
2016-02-10 21:51:22 +09:00
parent 7fcc881dd4
commit 5f28834bb2
8 changed files with 73 additions and 82 deletions

View File

@@ -1,4 +1,4 @@
from sys import stderr
import time
from electrum.i18n import _
from electrum.util import PrintError, UserCancelled
@@ -82,6 +82,7 @@ class TrezorClientBase(GuiMixin, PrintError):
self.tx_api = plugin
self.types = plugin.types
self.msg_code_override = None
self.used()
def __str__(self):
return "%s/%s" % (self.label(), self.features.device_id)
@@ -97,6 +98,20 @@ class TrezorClientBase(GuiMixin, PrintError):
def is_pairable(self):
return not self.features.bootloader_mode
def used(self):
self.print_error("used")
self.last_operation = time.time()
def prevent_timeouts(self):
self.print_error("prevent timeouts")
self.last_operation = float('inf')
def timeout(self, cutoff):
'''Time out the client if the last operation was before cutoff.'''
if self.last_operation < cutoff:
self.print_error("timed out")
self.clear_session()
@staticmethod
def expand_path(n):
'''Convert bip32 path to list of uint32 integers with prime flags
@@ -158,6 +173,7 @@ class TrezorClientBase(GuiMixin, PrintError):
'''Clear the session to force pin (and passphrase if enabled)
re-entry. Does not leak exceptions.'''
self.print_error("clear session:", self)
self.prevent_timeouts()
try:
super(TrezorClientBase, self).clear_session()
except BaseException as e:
@@ -185,8 +201,10 @@ class TrezorClientBase(GuiMixin, PrintError):
def wrapped(self, *args, **kwargs):
try:
self.prevent_timeouts()
return func(self, *args, **kwargs)
finally:
self.used()
self.handler.finished()
return wrapped

View File

@@ -1,7 +1,6 @@
import base64
import re
import threading
import time
from binascii import unhexlify
from functools import partial
@@ -136,8 +135,7 @@ class TrezorCompatiblePlugin(HW_PluginBase):
devmgr = self.device_manager()
client = devmgr.client_for_wallet(self, wallet, force_pair)
if client:
self.print_error("set last_operation")
wallet.last_operation = time.time()
client.used()
return client
@@ -147,9 +145,6 @@ class TrezorCompatiblePlugin(HW_PluginBase):
self.device_manager().unpair_wallet(wallet)
def initialize_device(self, wallet):
# Prevent timeouts during initialization
wallet.last_operation = self.prevent_timeout
# Initialization method
msg = _("Choose how you want to initialize your %s.\n\n"
"The first two methods are secure as no secret information "

View File

@@ -345,6 +345,7 @@ class SettingsDialog(WindowModalDialog):
self.setMaximumWidth(540)
devmgr = plugin.device_manager()
config = devmgr.config
handler = window.wallet.handler
thread = window.wallet.thread
# wallet can be None, needn't be window.wallet
@@ -459,8 +460,7 @@ class SettingsDialog(WindowModalDialog):
timeout_minutes.setText(_("%2d minutes") % mins)
def slider_released():
seconds = timeout_slider.sliderPosition() * 60
wallet.set_session_timeout(seconds)
config.set_session_timeout(timeout_slider.sliderPosition() * 60)
# Information tab
info_tab = QWidget()
@@ -549,29 +549,28 @@ class SettingsDialog(WindowModalDialog):
settings_glayout.addWidget(homescreen_msg, 5, 1, 1, -1)
# Settings tab - Session Timeout
if wallet:
timeout_label = QLabel(_("Session Timeout"))
timeout_minutes = QLabel()
timeout_slider = QSlider(Qt.Horizontal)
timeout_slider.setRange(1, 60)
timeout_slider.setSingleStep(1)
timeout_slider.setTickInterval(5)
timeout_slider.setTickPosition(QSlider.TicksBelow)
timeout_slider.setTracking(True)
timeout_msg = QLabel(
_("Clear the session after the specified period "
"of inactivity. Once a session has timed out, "
"your PIN and passphrase (if enabled) must be "
"re-entered to use the device."))
timeout_msg.setWordWrap(True)
timeout_slider.setSliderPosition(wallet.session_timeout // 60)
slider_moved()
timeout_slider.valueChanged.connect(slider_moved)
timeout_slider.sliderReleased.connect(slider_released)
settings_glayout.addWidget(timeout_label, 6, 0)
settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3)
settings_glayout.addWidget(timeout_minutes, 6, 4)
settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1)
timeout_label = QLabel(_("Session Timeout"))
timeout_minutes = QLabel()
timeout_slider = QSlider(Qt.Horizontal)
timeout_slider.setRange(1, 60)
timeout_slider.setSingleStep(1)
timeout_slider.setTickInterval(5)
timeout_slider.setTickPosition(QSlider.TicksBelow)
timeout_slider.setTracking(True)
timeout_msg = QLabel(
_("Clear the session after the specified period "
"of inactivity. Once a session has timed out, "
"your PIN and passphrase (if enabled) must be "
"re-entered to use the device."))
timeout_msg.setWordWrap(True)
timeout_slider.setSliderPosition(config.get_session_timeout() // 60)
slider_moved()
timeout_slider.valueChanged.connect(slider_moved)
timeout_slider.sliderReleased.connect(slider_released)
settings_glayout.addWidget(timeout_label, 6, 0)
settings_glayout.addWidget(timeout_slider, 6, 1, 1, 3)
settings_glayout.addWidget(timeout_minutes, 6, 4)
settings_glayout.addWidget(timeout_msg, 7, 1, 1, -1)
settings_layout.addLayout(settings_glayout)
settings_layout.addStretch(1)