mirror of
https://github.com/openvswitch/ovs
synced 2025-08-31 06:15:47 +00:00
python: Replace pyOpenSSL with ssl.
Currently, pyOpenSSL is half-deprecated upstream and so it's removed on some distributions (for example on CentOS Stream 9, https://issues.redhat.com/browse/CS-336), but since OVS only supports Python 3 it's possible to replace pyOpenSSL with "import ssl" included in base Python 3. Stream recv and send had to be splitted as _recv and _send, since SSLError is a subclass of socket.error and so it was not possible to except for SSLWantReadError and SSLWantWriteError in recv and send of SSLStream. TCPstream._open cannot be used in SSLStream, since Python ssl module requires the SSL socket to be created before connecting it, so SSLStream._open needs to create the socket, create SSL socket and then connect the SSL socket. Reported-by: Timothy Redaelli <tredaelli@redhat.com> Reported-at: https://bugzilla.redhat.com/1988429 Signed-off-by: Timothy Redaelli <tredaelli@redhat.com> Acked-by: Terry Wilson <twilson@redhat.com> Tested-by: Terry Wilson <twilson@redhat.com> Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
This commit is contained in:
committed by
Ilya Maximets
parent
3f550fa538
commit
68543dd523
@@ -21,7 +21,7 @@ make -j4 HAVE_LLVM= HAVE_SQLITE= install
|
|||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
pip3 install --disable-pip-version-check --user \
|
pip3 install --disable-pip-version-check --user \
|
||||||
flake8 hacking sphinx pyOpenSSL wheel setuptools
|
flake8 hacking sphinx wheel setuptools
|
||||||
pip3 install --user 'meson==0.47.1'
|
pip3 install --user 'meson==0.47.1'
|
||||||
|
|
||||||
if [ "$M32" ]; then
|
if [ "$M32" ]; then
|
||||||
|
@@ -9,7 +9,7 @@ freebsd_build_task:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
DEPENDENCIES: automake libtool gmake gcc wget openssl python3
|
DEPENDENCIES: automake libtool gmake gcc wget openssl python3
|
||||||
PY_DEPS: sphinx|openssl
|
PY_DEPS: sphinx
|
||||||
matrix:
|
matrix:
|
||||||
COMPILER: gcc
|
COMPILER: gcc
|
||||||
COMPILER: clang
|
COMPILER: clang
|
||||||
|
@@ -17,7 +17,6 @@ addons:
|
|||||||
- libjemalloc-dev
|
- libjemalloc-dev
|
||||||
- libnuma-dev
|
- libnuma-dev
|
||||||
- libpcap-dev
|
- libpcap-dev
|
||||||
- python3-openssl
|
|
||||||
- python3-pip
|
- python3-pip
|
||||||
- python3-sphinx
|
- python3-sphinx
|
||||||
- libelf-dev
|
- libelf-dev
|
||||||
|
3
NEWS
3
NEWS
@@ -10,6 +10,9 @@ Post-v2.16.0
|
|||||||
limiting behavior.
|
limiting behavior.
|
||||||
* Add hardware offload support for matching IPv4/IPv6 frag types
|
* Add hardware offload support for matching IPv4/IPv6 frag types
|
||||||
(experimental).
|
(experimental).
|
||||||
|
- Python:
|
||||||
|
* For SSL support, the use of the pyOpenSSL library has been replaced
|
||||||
|
with the native 'ssl' module.
|
||||||
|
|
||||||
|
|
||||||
v2.16.0 - 16 Aug 2021
|
v2.16.0 - 16 Aug 2021
|
||||||
|
@@ -26,9 +26,9 @@ if sys.platform == "win32":
|
|||||||
import ovs.winutils as winutils
|
import ovs.winutils as winutils
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from OpenSSL import SSL
|
import ssl
|
||||||
except ImportError:
|
except ImportError:
|
||||||
SSL = None
|
ssl = None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from eventlet import patcher as eventlet_patcher
|
from eventlet import patcher as eventlet_patcher
|
||||||
@@ -73,7 +73,7 @@ class _SelectSelect(object):
|
|||||||
def register(self, fd, events):
|
def register(self, fd, events):
|
||||||
if isinstance(fd, socket.socket):
|
if isinstance(fd, socket.socket):
|
||||||
fd = fd.fileno()
|
fd = fd.fileno()
|
||||||
if SSL and isinstance(fd, SSL.Connection):
|
if ssl and isinstance(fd, ssl.SSLSocket):
|
||||||
fd = fd.fileno()
|
fd = fd.fileno()
|
||||||
|
|
||||||
if sys.platform != 'win32':
|
if sys.platform != 'win32':
|
||||||
|
@@ -22,9 +22,9 @@ import ovs.socket_util
|
|||||||
import ovs.vlog
|
import ovs.vlog
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from OpenSSL import SSL
|
import ssl
|
||||||
except ImportError:
|
except ImportError:
|
||||||
SSL = None
|
ssl = None
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
import ovs.winutils as winutils
|
import ovs.winutils as winutils
|
||||||
@@ -322,6 +322,12 @@ class Stream(object):
|
|||||||
The recv function will not block waiting for data to arrive. If no
|
The recv function will not block waiting for data to arrive. If no
|
||||||
data have been received, it returns (errno.EAGAIN, "") immediately."""
|
data have been received, it returns (errno.EAGAIN, "") immediately."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
return self._recv(n)
|
||||||
|
except socket.error as e:
|
||||||
|
return (ovs.socket_util.get_exception_errno(e), "")
|
||||||
|
|
||||||
|
def _recv(self, n):
|
||||||
retval = self.connect()
|
retval = self.connect()
|
||||||
if retval != 0:
|
if retval != 0:
|
||||||
return (retval, "")
|
return (retval, "")
|
||||||
@@ -331,10 +337,7 @@ class Stream(object):
|
|||||||
if sys.platform == 'win32' and self.socket is None:
|
if sys.platform == 'win32' and self.socket is None:
|
||||||
return self.__recv_windows(n)
|
return self.__recv_windows(n)
|
||||||
|
|
||||||
try:
|
return (0, self.socket.recv(n))
|
||||||
return (0, self.socket.recv(n))
|
|
||||||
except socket.error as e:
|
|
||||||
return (ovs.socket_util.get_exception_errno(e), "")
|
|
||||||
|
|
||||||
def __recv_windows(self, n):
|
def __recv_windows(self, n):
|
||||||
if self._read_pending:
|
if self._read_pending:
|
||||||
@@ -396,6 +399,12 @@ class Stream(object):
|
|||||||
Will not block. If no bytes can be immediately accepted for
|
Will not block. If no bytes can be immediately accepted for
|
||||||
transmission, returns -errno.EAGAIN immediately."""
|
transmission, returns -errno.EAGAIN immediately."""
|
||||||
|
|
||||||
|
try:
|
||||||
|
return self._send(buf)
|
||||||
|
except socket.error as e:
|
||||||
|
return -ovs.socket_util.get_exception_errno(e)
|
||||||
|
|
||||||
|
def _send(self, buf):
|
||||||
retval = self.connect()
|
retval = self.connect()
|
||||||
if retval != 0:
|
if retval != 0:
|
||||||
return -retval
|
return -retval
|
||||||
@@ -409,10 +418,7 @@ class Stream(object):
|
|||||||
if sys.platform == 'win32' and self.socket is None:
|
if sys.platform == 'win32' and self.socket is None:
|
||||||
return self.__send_windows(buf)
|
return self.__send_windows(buf)
|
||||||
|
|
||||||
try:
|
return self.socket.send(buf)
|
||||||
return self.socket.send(buf)
|
|
||||||
except socket.error as e:
|
|
||||||
return -ovs.socket_util.get_exception_errno(e)
|
|
||||||
|
|
||||||
def __send_windows(self, buf):
|
def __send_windows(self, buf):
|
||||||
if self._write_pending:
|
if self._write_pending:
|
||||||
@@ -769,35 +775,42 @@ class SSLStream(Stream):
|
|||||||
def check_connection_completion(sock):
|
def check_connection_completion(sock):
|
||||||
try:
|
try:
|
||||||
return Stream.check_connection_completion(sock)
|
return Stream.check_connection_completion(sock)
|
||||||
except SSL.SysCallError as e:
|
except ssl.SSLSyscallError as e:
|
||||||
return ovs.socket_util.get_exception_errno(e)
|
return ovs.socket_util.get_exception_errno(e)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def needs_probes():
|
def needs_probes():
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def verify_cb(conn, cert, errnum, depth, ok):
|
|
||||||
return ok
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _open(suffix, dscp):
|
def _open(suffix, dscp):
|
||||||
error, sock = TCPStream._open(suffix, dscp)
|
address = ovs.socket_util.inet_parse_active(suffix, 0)
|
||||||
if error:
|
family, sock = ovs.socket_util.inet_create_socket_active(
|
||||||
return error, None
|
socket.SOCK_STREAM, address)
|
||||||
|
if sock is None:
|
||||||
|
return family, sock
|
||||||
|
|
||||||
# Create an SSL context
|
# Create an SSL context
|
||||||
ctx = SSL.Context(SSL.SSLv23_METHOD)
|
ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
||||||
ctx.set_verify(SSL.VERIFY_PEER, SSLStream.verify_cb)
|
ctx.verify_mode = ssl.CERT_REQUIRED
|
||||||
ctx.set_options(SSL.OP_NO_SSLv2 | SSL.OP_NO_SSLv3)
|
ctx.options |= ssl.OP_NO_SSLv2
|
||||||
|
ctx.options |= ssl.OP_NO_SSLv3
|
||||||
# If the client has not set the SSL configuration files
|
# If the client has not set the SSL configuration files
|
||||||
# exception would be raised.
|
# exception would be raised.
|
||||||
ctx.use_privatekey_file(Stream._SSL_private_key_file)
|
|
||||||
ctx.use_certificate_file(Stream._SSL_certificate_file)
|
|
||||||
ctx.load_verify_locations(Stream._SSL_ca_cert_file)
|
ctx.load_verify_locations(Stream._SSL_ca_cert_file)
|
||||||
|
ctx.load_cert_chain(Stream._SSL_certificate_file,
|
||||||
|
Stream._SSL_private_key_file)
|
||||||
|
ssl_sock = ctx.wrap_socket(sock, do_handshake_on_connect=False)
|
||||||
|
|
||||||
ssl_sock = SSL.Connection(ctx, sock)
|
# Connect
|
||||||
ssl_sock.set_connect_state()
|
error = ovs.socket_util.inet_connect_active(ssl_sock, address, family,
|
||||||
|
dscp)
|
||||||
|
if not error:
|
||||||
|
try:
|
||||||
|
ssl_sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||||
|
except socket.error as e:
|
||||||
|
ssl_sock.close()
|
||||||
|
return ovs.socket_util.get_exception_errno(e), None
|
||||||
return error, ssl_sock
|
return error, ssl_sock
|
||||||
|
|
||||||
def connect(self):
|
def connect(self):
|
||||||
@@ -809,40 +822,44 @@ class SSLStream(Stream):
|
|||||||
# TCP Connection is successful. Now do the SSL handshake
|
# TCP Connection is successful. Now do the SSL handshake
|
||||||
try:
|
try:
|
||||||
self.socket.do_handshake()
|
self.socket.do_handshake()
|
||||||
except SSL.WantReadError:
|
except ssl.SSLWantReadError:
|
||||||
return errno.EAGAIN
|
return errno.EAGAIN
|
||||||
except SSL.SysCallError as e:
|
except ssl.SSLSyscallError as e:
|
||||||
return ovs.socket_util.get_exception_errno(e)
|
return ovs.socket_util.get_exception_errno(e)
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
def recv(self, n):
|
def recv(self, n):
|
||||||
try:
|
try:
|
||||||
return super(SSLStream, self).recv(n)
|
return super(SSLStream, self)._recv(n)
|
||||||
except SSL.WantReadError:
|
except ssl.SSLWantReadError:
|
||||||
return (errno.EAGAIN, "")
|
return (errno.EAGAIN, "")
|
||||||
except SSL.SysCallError as e:
|
except ssl.SSLSyscallError as e:
|
||||||
return (ovs.socket_util.get_exception_errno(e), "")
|
return (ovs.socket_util.get_exception_errno(e), "")
|
||||||
except SSL.ZeroReturnError:
|
except ssl.SSLZeroReturnError:
|
||||||
return (0, "")
|
return (0, "")
|
||||||
|
except socket.error as e:
|
||||||
|
return (ovs.socket_util.get_exception_errno(e), "")
|
||||||
|
|
||||||
def send(self, buf):
|
def send(self, buf):
|
||||||
try:
|
try:
|
||||||
return super(SSLStream, self).send(buf)
|
return super(SSLStream, self)._send(buf)
|
||||||
except SSL.WantWriteError:
|
except ssl.SSLWantWriteError:
|
||||||
return -errno.EAGAIN
|
return -errno.EAGAIN
|
||||||
except SSL.SysCallError as e:
|
except ssl.SSLSyscallError as e:
|
||||||
|
return -ovs.socket_util.get_exception_errno(e)
|
||||||
|
except socket.error as e:
|
||||||
return -ovs.socket_util.get_exception_errno(e)
|
return -ovs.socket_util.get_exception_errno(e)
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
if self.socket:
|
if self.socket:
|
||||||
try:
|
try:
|
||||||
self.socket.shutdown()
|
self.socket.shutdown(socket.SHUT_RDWR)
|
||||||
except SSL.Error:
|
except socket.error:
|
||||||
pass
|
pass
|
||||||
return super(SSLStream, self).close()
|
return super(SSLStream, self).close()
|
||||||
|
|
||||||
|
|
||||||
if SSL:
|
if ssl:
|
||||||
# Register SSL only if the OpenSSL module is available
|
# Register SSL only if the OpenSSL module is available
|
||||||
Stream.register_method("ssl", SSLStream)
|
Stream.register_method("ssl", SSLStream)
|
||||||
|
@@ -225,7 +225,7 @@ m4_define([OVSDB_CHECK_IDL_TCP6_MULTIPLE_REMOTES_PY],
|
|||||||
m4_define([OVSDB_CHECK_IDL_SSL_PY],
|
m4_define([OVSDB_CHECK_IDL_SSL_PY],
|
||||||
[AT_SETUP([$1 - Python3 - SSL])
|
[AT_SETUP([$1 - Python3 - SSL])
|
||||||
AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
|
AT_SKIP_IF([test "$HAVE_OPENSSL" = no])
|
||||||
$PYTHON3 -c "import OpenSSL.SSL"
|
$PYTHON3 -c "import ssl"
|
||||||
SSL_PRESENT=$?
|
SSL_PRESENT=$?
|
||||||
AT_SKIP_IF([test $SSL_PRESENT != 0])
|
AT_SKIP_IF([test $SSL_PRESENT != 0])
|
||||||
AT_KEYWORDS([ovsdb server idl positive Python with ssl socket $5])
|
AT_KEYWORDS([ovsdb server idl positive Python with ssl socket $5])
|
||||||
|
Reference in New Issue
Block a user