Fix a denial-of-service bug by setting the server socket timeout

This change fixes a potential denial-of-service bug with the
server, setting a default timeout for all server sockets. This
allows the server to drop hung connections without blocking
forever. The interrupt triggered during accept calls is expected
and is now handled appropriately. Server unit tests have been
updated to reflect this change.

Closes #430
This commit is contained in:
Peter Hamilton 2018-04-24 21:57:20 -04:00
parent 1f172ee08d
commit 3a7b880bdf
2 changed files with 11 additions and 1 deletions

View File

@ -267,6 +267,7 @@ class KmipServer(object):
self._logger.info("Starting server socket handler.")
# Create a TCP stream socket and configure it for immediate reuse.
socket.setdefaulttimeout(10)
self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@ -407,6 +408,11 @@ class KmipServer(object):
while self._is_serving:
try:
connection, address = self._socket.accept()
except socket.timeout:
# Setting the default socket timeout to break hung connections
# will cause accept to periodically raise socket.timeout. This
# is expected behavior, so ignore it and retry accept.
pass
except socket.error as e:
self._logger.warning(
"Error detected while establishing new connection."

View File

@ -485,7 +485,11 @@ class TestKmipServer(testtools.TestCase):
# Test the expected behavior for a normal server/interrupt sequence
s._socket.accept = mock.MagicMock(
side_effect=[('connection', 'address'), expected_error]
side_effect=[
('connection', 'address'),
socket.timeout,
expected_error
]
)
s.serve()