summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEndi S. Dewata <edewata@redhat.com>2014-09-16 20:11:35 -0400
committerPetr Viktorin <pviktori@dhcp-31-13.brq.redhat.com>2014-11-11 09:09:19 +0100
commit80a8df3f193aa800740f1627a269e6973f57aa0a (patch)
tree82f6add398a2a56413c8b1f23213d2aca4928284
parent74e0a8cebca251bf89144597f521440407a469ba (diff)
downloadfreeipa-80a8df3f193aa800740f1627a269e6973f57aa0a.tar.gz
freeipa-80a8df3f193aa800740f1627a269e6973f57aa0a.tar.xz
freeipa-80a8df3f193aa800740f1627a269e6973f57aa0a.zip
Modififed NSSConnection not to shutdown existing database.
The NSSConnection class has been modified not to shutdown the existing NSS database if the database is already opened to establish an SSL connection, or is already opened by another code that uses an NSS database without establishing an SSL connection such as vault CLIs. https://fedorahosted.org/freeipa/ticket/4638 Reviewed-By: Jan Cholasta <jcholast@redhat.com>
-rw-r--r--ipalib/rpc.py34
-rw-r--r--ipapython/nsslib.py35
2 files changed, 42 insertions, 27 deletions
diff --git a/ipalib/rpc.py b/ipalib/rpc.py
index 5934f0c26..001b7f1ca 100644
--- a/ipalib/rpc.py
+++ b/ipalib/rpc.py
@@ -63,6 +63,7 @@ from ipaplatform.paths import paths
from ipapython.cookie import Cookie
from ipapython.dnsutil import DNSName
from ipalib.text import _
+import ipapython.nsslib
from ipapython.nsslib import NSSHTTPS, NSSConnection
from ipalib.krb_utils import KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, KRB5KRB_AP_ERR_TKT_EXPIRED, \
KRB5_FCC_PERM, KRB5_FCC_NOFILE, KRB5_CC_FORMAT, KRB5_REALM_CANT_RESOLVE
@@ -450,14 +451,10 @@ class LanguageAwareTransport(MultiProtocolTransport):
class SSLTransport(LanguageAwareTransport):
"""Handles an HTTPS transaction to an XML-RPC server."""
- def __nss_initialized(self, dbdir):
+ def get_connection_dbdir(self):
"""
- If there is another connections open it may have already
- initialized NSS. This is likely to lead to an NSS shutdown
- failure. One way to mitigate this is to tell NSS to not
- initialize if it has already been done in another open connection.
-
- Returns True if another connection is using the same db.
+ If there is a connections open it may have already initialized
+ NSS database. Return the database location used by the connection.
"""
for value in context.__dict__.values():
if not isinstance(value, Connection):
@@ -466,25 +463,32 @@ class SSLTransport(LanguageAwareTransport):
getattr(value.conn, '_ServerProxy__transport', None),
SSLTransport):
continue
- if hasattr(value.conn._ServerProxy__transport, 'dbdir') and \
- value.conn._ServerProxy__transport.dbdir == dbdir:
- return True
- return False
+ if hasattr(value.conn._ServerProxy__transport, 'dbdir'):
+ return value.conn._ServerProxy__transport.dbdir
+ return None
def make_connection(self, host):
host, self._extra_headers, x509 = self.get_host_info(host)
# Python 2.7 changed the internal class used in xmlrpclib from
# HTTP to HTTPConnection. We need to use the proper subclass
- # If we an existing connection exists using the same NSS database
- # there is no need to re-initialize. Pass thsi into the NSS
- # connection creator.
if sys.version_info >= (2, 7):
if self._connection and host == self._connection[0]:
return self._connection[1]
dbdir = getattr(context, 'nss_dir', paths.IPA_NSSDB_DIR)
- no_init = self.__nss_initialized(dbdir)
+ connection_dbdir = self.get_connection_dbdir()
+
+ if connection_dbdir:
+ # If an existing connection is already using the same NSS
+ # database there is no need to re-initialize.
+ no_init = dbdir == connection_dbdir
+
+ else:
+ # If the NSS database is already being used there is no
+ # need to re-initialize.
+ no_init = dbdir == ipapython.nsslib.current_dbdir
+
if sys.version_info < (2, 7):
conn = NSSHTTPS(host, 443, dbdir=dbdir, no_init=no_init)
else:
diff --git a/ipapython/nsslib.py b/ipapython/nsslib.py
index 93b0c56fc..1452a2a58 100644
--- a/ipapython/nsslib.py
+++ b/ipapython/nsslib.py
@@ -31,6 +31,9 @@ import nss.ssl as ssl
import nss.error as error
from ipaplatform.paths import paths
+# NSS database currently open
+current_dbdir = None
+
def auth_certificate_callback(sock, check_sig, is_server, certdb):
cert_is_valid = False
@@ -184,19 +187,27 @@ class NSSConnection(httplib.HTTPConnection, NSSAddressFamilyFallback):
httplib.HTTPConnection.__init__(self, host, port, strict)
NSSAddressFamilyFallback.__init__(self, family)
- if not dbdir:
- raise RuntimeError("dbdir is required")
-
root_logger.debug('%s init %s', self.__class__.__name__, host)
- if not no_init and nss.nss_is_initialized():
- # close any open NSS database and use the new one
- ssl.clear_session_cache()
- try:
- nss.nss_shutdown()
- except NSPRError, e:
- if e.errno != error.SEC_ERROR_NOT_INITIALIZED:
- raise e
- nss.nss_init(dbdir)
+
+ # If initialization is requested, initialize the new database.
+ if not no_init:
+
+ if nss.nss_is_initialized():
+ ssl.clear_session_cache()
+ try:
+ nss.nss_shutdown()
+ except NSPRError, e:
+ if e.errno != error.SEC_ERROR_NOT_INITIALIZED:
+ raise e
+
+ if not dbdir:
+ raise RuntimeError("dbdir is required")
+
+ nss.nss_init(dbdir)
+
+ global current_dbdir
+ current_dbdir = dbdir
+
ssl.set_domestic_policy()
nss.set_password_callback(self.password_callback)