Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 48 additions & 38 deletions riak/security.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,34 +16,25 @@
under the License.
"""

import ssl
import warnings
from six import PY2
from riak import RiakError
from riak.util import str_to_long

OPENSSL_VERSION_101G = 268439679
if PY2:
if hasattr(ssl, 'SSLContext'):
# For Python >= 2.7.9 and Python 3.x
USE_STDLIB_SSL = True
else:
# For Python 2.6 and <= 2.7.8
USE_STDLIB_SSL = False

if not USE_STDLIB_SSL:
import OpenSSL.SSL
from OpenSSL import crypto
sslver = OpenSSL.SSL.OPENSSL_VERSION_NUMBER
# Be sure to use at least OpenSSL 1.0.1g
if (sslver < OPENSSL_VERSION_101G) or \
not hasattr(OpenSSL.SSL, 'TLSv1_2_METHOD'):
verstring = OpenSSL.SSL.SSLeay_version(OpenSSL.SSL.SSLEAY_VERSION)
msg = "Found {0} version, but expected at least OpenSSL 1.0.1g. " \
"Security may not support TLS 1.2.".format(verstring)
warnings.warn(msg, UserWarning)
if hasattr(OpenSSL.SSL, 'TLSv1_2_METHOD'):
DEFAULT_TLS_VERSION = OpenSSL.SSL.TLSv1_2_METHOD
elif hasattr(OpenSSL.SSL, 'TLSv1_1_METHOD'):
DEFAULT_TLS_VERSION = OpenSSL.SSL.TLSv1_1_METHOD
elif hasattr(OpenSSL.SSL, 'TLSv1_METHOD'):
DEFAULT_TLS_VERSION = OpenSSL.SSL.TLSv1_METHOD
else:
DEFAULT_TLS_VERSION = OpenSSL.SSL.SSLv23_METHOD
else:
import ssl

OPENSSL_VERSION_101G = 268439679
if hasattr(ssl, 'OPENSSL_VERSION_NUMBER'):
# For Python 2.7 and Python 3.x
sslver = ssl.OPENSSL_VERSION_NUMBER
# Be sure to use at least OpenSSL 1.0.1g
if sslver < OPENSSL_VERSION_101G or \
Expand All @@ -61,6 +52,25 @@
else:
DEFAULT_TLS_VERSION = ssl.PROTOCOL_SSLv23

else:
# For Python 2.6
sslver = OpenSSL.SSL.OPENSSL_VERSION_NUMBER
# Be sure to use at least OpenSSL 1.0.1g
if (sslver < OPENSSL_VERSION_101G) or \
not hasattr(OpenSSL.SSL, 'TLSv1_2_METHOD'):
verstring = OpenSSL.SSL.SSLeay_version(OpenSSL.SSL.SSLEAY_VERSION)
msg = "Found {0} version, but expected at least OpenSSL 1.0.1g. " \
"Security may not support TLS 1.2.".format(verstring)
warnings.warn(msg, UserWarning)
if hasattr(OpenSSL.SSL, 'TLSv1_2_METHOD'):
DEFAULT_TLS_VERSION = OpenSSL.SSL.TLSv1_2_METHOD
elif hasattr(OpenSSL.SSL, 'TLSv1_1_METHOD'):
DEFAULT_TLS_VERSION = OpenSSL.SSL.TLSv1_1_METHOD
elif hasattr(OpenSSL.SSL, 'TLSv1_METHOD'):
DEFAULT_TLS_VERSION = OpenSSL.SSL.TLSv1_METHOD
else:
DEFAULT_TLS_VERSION = OpenSSL.SSL.SSLv23_METHOD


class SecurityError(RiakError):
"""
Expand Down Expand Up @@ -197,7 +207,7 @@ def ssl_version(self):
"""
return self._ssl_version

if PY2:
if not USE_STDLIB_SSL:
@property
def pkey(self):
"""
Expand Down Expand Up @@ -266,20 +276,20 @@ def _has_credential(self, key):
return (getattr(self, internal_key) is not None) or \
(getattr(self, internal_key + "_file") is not None)

def _check_revoked_cert(self, ssl_socket):
"""
Checks whether the server certificate on the passed socket has been
revoked by checking the CRL.
def _check_revoked_cert(self, ssl_socket):
"""
Checks whether the server certificate on the passed socket has been
revoked by checking the CRL.

:param ssl_socket: the SSL/TLS socket
:rtype: bool
:raises SecurityError: when the certificate has been revoked
"""
if not self._has_credential('crl'):
return True

servcert = ssl_socket.get_peer_certificate()
servserial = servcert.get_serial_number()
for rev in self.crl.get_revoked():
if servserial == str_to_long(rev.get_serial(), 16):
raise SecurityError("Server certificate has been revoked")
:param ssl_socket: the SSL/TLS socket
:rtype: bool
:raises SecurityError: when the certificate has been revoked
"""
if not self._has_credential('crl'):
return True

servcert = ssl_socket.get_peer_certificate()
servserial = servcert.get_serial_number()
for rev in self.crl.get_revoked():
if servserial == str_to_long(rev.get_serial(), 16):
raise SecurityError("Server certificate has been revoked")
11 changes: 5 additions & 6 deletions riak/tests/test_security.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,15 @@
under the License.
"""

import platform
if platform.python_version() < '2.7':
import sys
if sys.version_info < (2, 7):
unittest = __import__('unittest2')
else:
import unittest
from riak.tests import RUN_SECURITY, SECURITY_USER, SECURITY_PASSWD, \
SECURITY_CACERT, SECURITY_KEY, SECURITY_CERT, SECURITY_REVOKED, \
SECURITY_CERT_USER, SECURITY_CERT_PASSWD, SECURITY_BAD_CERT
from riak.security import SecurityCreds
from six import PY3


class SecurityTests(object):
Expand Down Expand Up @@ -110,9 +109,9 @@ def test_security_revoked_cert(self):
creds = SecurityCreds(username=SECURITY_USER, password=SECURITY_PASSWD,
cacert_file=SECURITY_CACERT,
crl_file=SECURITY_REVOKED)
# Curenly Python 3.x native CRL doesn't seem to work
# as advertised
if PY3:
# Currently Python >= 2.7.9 and Python 3.x native CRL doesn't seem to
# work as advertised
if sys.version_info >= (2, 7, 9):
return
client = self.create_client(credentials=creds)
with self.assertRaises(Exception):
Expand Down
16 changes: 9 additions & 7 deletions riak/transports/http/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,27 +19,29 @@
import socket
import select
from six import PY2
if PY2:
from riak.security import SecurityError, USE_STDLIB_SSL
if USE_STDLIB_SSL:
import ssl
from riak.transports.security import configure_ssl_context
else:
import OpenSSL.SSL
from riak.transports.security import RiakWrappedSocket,\
configure_pyopenssl_context
if PY2:
from httplib import HTTPConnection, \
NotConnected, \
IncompleteRead, \
ImproperConnectionState, \
BadStatusLine, \
HTTPSConnection
from riak.transports.security import RiakWrappedSocket,\
configure_pyopenssl_context
else:
from http.client import HTTPConnection, \
HTTPSConnection, \
NotConnected, \
IncompleteRead, \
ImproperConnectionState, \
BadStatusLine
import ssl
from riak.transports.security import configure_ssl_context

from riak.security import SecurityError
from riak.transports.pool import Pool
from riak.transports.http.transport import RiakHttpTransport

Expand Down Expand Up @@ -106,7 +108,7 @@ def connect(self):
Connect to a host on a given (SSL) port using PyOpenSSL.
"""
sock = socket.create_connection((self.host, self.port), self.timeout)
if PY2:
if not USE_STDLIB_SSL:
ssl_ctx = configure_pyopenssl_context(self.credentials)

# attempt to upgrade the socket to TLS
Expand Down
6 changes: 3 additions & 3 deletions riak/transports/pbc/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import socket
import struct
import riak_pb
from riak.security import SecurityError
from riak.security import SecurityError, USE_STDLIB_SSL
from riak import RiakError
from riak_pb.messages import (
MESSAGE_CLASSES,
Expand All @@ -30,7 +30,7 @@
)
from riak.util import bytes_to_str, str_to_bytes
from six import PY2
if PY2:
if not USE_STDLIB_SSL:
from OpenSSL.SSL import Connection
from riak.transports.security import configure_pyopenssl_context
else:
Expand Down Expand Up @@ -113,7 +113,7 @@ def _auth(self):
else:
return False

if PY2:
if not USE_STDLIB_SSL:
def _ssl_handshake(self):
"""
Perform an SSL handshake w/ the server.
Expand Down
Loading