otptoken: use ipapython.nsslib instead of Python's ssl module

The otptoken plugin is the only module in FreeIPA that uses Python's ssl
module instead of NSS. The patch replaces ssl with NSSConnection. It
uses the default NSS database to lookup trust anchors. NSSConnection
uses NSS for hostname matching. The package
python-backports-ssl_match_hostname is no longer required.

https://fedorahosted.org/freeipa/ticket/5068

Reviewed-By: Martin Basti <mbasti@redhat.com>
This commit is contained in:
Christian Heimes 2015-07-07 15:10:28 +02:00 committed by Martin Basti
parent 2596adb312
commit 3c974c157f
2 changed files with 8 additions and 30 deletions

View File

@ -95,7 +95,6 @@ BuildRequires: systemd
BuildRequires: libunistring-devel BuildRequires: libunistring-devel
BuildRequires: python-lesscpy BuildRequires: python-lesscpy
BuildRequires: python-yubico >= 1.2.3 BuildRequires: python-yubico >= 1.2.3
BuildRequires: python-backports-ssl_match_hostname
BuildRequires: softhsm-devel >= 2.0.0rc1-1 BuildRequires: softhsm-devel >= 2.0.0rc1-1
BuildRequires: openssl-devel BuildRequires: openssl-devel
BuildRequires: p11-kit-devel BuildRequires: p11-kit-devel
@ -272,7 +271,6 @@ Requires: libsss_autofs
Requires: autofs Requires: autofs
Requires: libnfsidmap Requires: libnfsidmap
Requires: nfs-utils Requires: nfs-utils
Requires: python-backports-ssl_match_hostname
Requires(post): policycoreutils Requires(post): policycoreutils
Conflicts: %{alt_name}-client Conflicts: %{alt_name}-client

View File

@ -24,8 +24,9 @@ from ipalib.plugable import Registry
from ipalib.errors import PasswordMismatch, ConversionError, LastMemberError, NotFound, ValidationError from ipalib.errors import PasswordMismatch, ConversionError, LastMemberError, NotFound, ValidationError
from ipalib.request import context from ipalib.request import context
from ipalib.frontend import Local from ipalib.frontend import Local
from ipaplatform.paths import paths
from ipapython.nsslib import NSSConnection
from backports.ssl_match_hostname import match_hostname
import base64 import base64
import uuid import uuid
import urllib import urllib
@ -34,7 +35,6 @@ import httplib
import urlparse import urlparse
import qrcode import qrcode
import os import os
import ssl
__doc__ = _(""" __doc__ = _("""
OTP Tokens OTP Tokens
@ -471,28 +471,6 @@ class otptoken_remove_managedby(LDAPRemoveMember):
member_attributes = ['managedby'] member_attributes = ['managedby']
class HTTPSConnection(httplib.HTTPConnection):
"Generates an SSL HTTP connection that performs hostname validation."
ssl_kwargs = ssl.wrap_socket.func_code.co_varnames[1:ssl.wrap_socket.func_code.co_argcount] #pylint: disable=E1101
default_port = httplib.HTTPS_PORT
def __init__(self, host, **kwargs):
# Strip out arguments we want to pass to ssl.wrap_socket()
self.__kwargs = {k: v for k, v in kwargs.items() if k in self.ssl_kwargs}
for k in self.__kwargs:
del kwargs[k]
# Can't use super() because the parent is an old-style class.
httplib.HTTPConnection.__init__(self, host, **kwargs)
def connect(self):
# Create the raw socket and wrap it in ssl.
httplib.HTTPConnection.connect(self)
self.sock = ssl.wrap_socket(self.sock, **self.__kwargs)
# Verify the remote hostname.
match_hostname(self.sock.getpeercert(), self.host.split(':', 1)[0])
class HTTPSHandler(urllib2.HTTPSHandler): class HTTPSHandler(urllib2.HTTPSHandler):
"Opens SSL HTTPS connections that perform hostname validation." "Opens SSL HTTPS connections that perform hostname validation."
@ -506,7 +484,9 @@ class HTTPSHandler(urllib2.HTTPSHandler):
def __inner(self, host, **kwargs): def __inner(self, host, **kwargs):
tmp = self.__kwargs.copy() tmp = self.__kwargs.copy()
tmp.update(kwargs) tmp.update(kwargs)
return HTTPSConnection(host, **tmp) # NSSConnection doesn't support timeout argument
tmp.pop('timeout', None)
return NSSConnection(host, **tmp)
def https_open(self, req): def https_open(self, req):
return self.do_open(self.__inner, req) return self.do_open(self.__inner, req)
@ -548,9 +528,9 @@ class otptoken_sync(Local):
# Sync the token. # Sync the token.
# pylint: disable=E1101 # pylint: disable=E1101
handler = HTTPSHandler(ca_certs=os.path.join(self.api.env.confdir, 'ca.crt'), handler = HTTPSHandler(dbdir=paths.IPA_NSSDB_DIR,
cert_reqs=ssl.CERT_REQUIRED, tls_version_min=api.env.tls_version_min,
ssl_version=ssl.PROTOCOL_TLSv1) tls_version_max=api.env.tls_version_max)
rsp = urllib2.build_opener(handler).open(sync_uri, query) rsp = urllib2.build_opener(handler).open(sync_uri, query)
if rsp.getcode() == 200: if rsp.getcode() == 200:
status['result'][self.header] = rsp.info().get(self.header, 'unknown') status['result'][self.header] = rsp.info().get(self.header, 'unknown')