Add check for probes such as dictionary password attacks.

This commit is contained in:
Charles Haley 2012-08-04 12:41:03 +02:00
parent df2c0a2106
commit 81ed281c8e
3 changed files with 34 additions and 5 deletions

View File

@ -48,6 +48,9 @@ class OpenFeedback(DeviceError):
''' '''
raise NotImplementedError raise NotImplementedError
class InitialConnectionError(OpenFeedback):
""" Errors detected during connection after detection but before open """
class OpenFailed(ProtocolError): class OpenFailed(ProtocolError):
""" Raised when device cannot be opened this time. No retry is to be done. """ Raised when device cannot be opened this time. No retry is to be done.
The device should continue to be polled for future opens. If the The device should continue to be polled for future opens. If the

View File

@ -14,7 +14,8 @@ from functools import wraps
from calibre import prints from calibre import prints
from calibre.constants import numeric_version, DEBUG from calibre.constants import numeric_version, DEBUG
from calibre.devices.errors import OpenFailed, ControlError, TimeoutError from calibre.devices.errors import (OpenFailed, ControlError, TimeoutError,
InitialConnectionError)
from calibre.devices.interface import DevicePlugin from calibre.devices.interface import DevicePlugin
from calibre.devices.usbms.books import Book, BookList from calibre.devices.usbms.books import Book, BookList
from calibre.devices.usbms.deviceconfig import DeviceConfig from calibre.devices.usbms.deviceconfig import DeviceConfig
@ -82,6 +83,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
BASE_PACKET_LEN = 4096 BASE_PACKET_LEN = 4096
PROTOCOL_VERSION = 1 PROTOCOL_VERSION = 1
MAX_CLIENT_COMM_TIMEOUT = 60.0 # Wait at most N seconds for an answer MAX_CLIENT_COMM_TIMEOUT = 60.0 # Wait at most N seconds for an answer
MAX_UNSUCCESSFUL_CONNECTS = 5
opcodes = { opcodes = {
'NOOP' : 12, 'NOOP' : 12,
@ -490,6 +492,19 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
self.listen_socket.settimeout(None) self.listen_socket.settimeout(None)
self.device_socket.settimeout(None) self.device_socket.settimeout(None)
self.is_connected = True self.is_connected = True
try:
peer = self.device_socket.getpeername()[0]
attempts = self.connection_attempts.get(peer, 0)
if attempts >= self.MAX_UNSUCCESSFUL_CONNECTS:
self._debug('too many connection attempts from', peer)
self._close_device_socket()
raise InitialConnectionError(_('Too many connection attempts from %s')%peer)
else:
self.connection_attempts[peer] = attempts + 1
except InitialConnectionError:
raise
except:
pass
except socket.timeout: except socket.timeout:
self._close_device_socket() self._close_device_socket()
except socket.error: except socket.error:
@ -497,7 +512,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
self._debug('unexpected socket exception', x.args[0]) self._debug('unexpected socket exception', x.args[0])
self._close_device_socket() self._close_device_socket()
raise raise
return (True, self) return (self.is_connected, self)
return (False, None) return (False, None)
@synchronous('sync_lock') @synchronous('sync_lock')
@ -570,6 +585,11 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
# Don't bother with a message. The user will be informed on # Don't bother with a message. The user will be informed on
# the device. # the device.
raise OpenFailed('') raise OpenFailed('')
try:
peer = self.device_socket.getpeername()
self.connection_attempts[peer] = 0
except:
pass
return True return True
except socket.timeout: except socket.timeout:
self._close_device_socket() self._close_device_socket()
@ -807,6 +827,7 @@ class SMART_DEVICE_APP(DeviceConfig, DevicePlugin):
self.debug_start_time = time.time() self.debug_start_time = time.time()
self.max_book_packet_len = 0 self.max_book_packet_len = 0
self.noop_counter = 0 self.noop_counter = 0
self.connection_attempts = {}
try: try:
self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except: except:

View File

@ -13,7 +13,8 @@ from PyQt4.Qt import (QMenu, QAction, QActionGroup, QIcon, SIGNAL,
from calibre.customize.ui import (available_input_formats, available_output_formats, from calibre.customize.ui import (available_input_formats, available_output_formats,
device_plugins) device_plugins)
from calibre.devices.interface import DevicePlugin from calibre.devices.interface import DevicePlugin
from calibre.devices.errors import UserFeedback, OpenFeedback, OpenFailed from calibre.devices.errors import (UserFeedback, OpenFeedback, OpenFailed,
InitialConnectionError)
from calibre.gui2.dialogs.choose_format_device import ChooseFormatDeviceDialog from calibre.gui2.dialogs.choose_format_device import ChooseFormatDeviceDialog
from calibre.utils.ipc.job import BaseJob from calibre.utils.ipc.job import BaseJob
from calibre.devices.scanner import DeviceScanner from calibre.devices.scanner import DeviceScanner
@ -232,8 +233,12 @@ class DeviceManager(Thread): # {{{
for device in self.devices: for device in self.devices:
if device in self.ejected_devices: if device in self.ejected_devices:
continue continue
try:
possibly_connected, detected_device = \ possibly_connected, detected_device = \
self.scanner.is_device_connected(device) self.scanner.is_device_connected(device)
except InitialConnectionError as e:
self.open_feedback_msg(device.get_gui_name(), e)
continue
if possibly_connected: if possibly_connected:
possibly_connected_devices.append((device, detected_device)) possibly_connected_devices.append((device, detected_device))
if possibly_connected_devices: if possibly_connected_devices: