summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Cholasta <jcholast@redhat.com>2014-09-18 16:28:59 +0200
committerMartin Kosek <mkosek@redhat.com>2014-09-30 10:01:38 +0200
commit231f57cedb4fea26d3317fe2b1f30d043c7d2524 (patch)
tree568ca28e1e09751d0d8296d1d4338af813002e59
parent2421b13a9b8bd79084e9cfe488690057445d7aa7 (diff)
downloadfreeipa-231f57cedb4fea26d3317fe2b1f30d043c7d2524.tar.gz
freeipa-231f57cedb4fea26d3317fe2b1f30d043c7d2524.tar.xz
freeipa-231f57cedb4fea26d3317fe2b1f30d043c7d2524.zip
Introduce NSS database /etc/ipa/nssdb
This is the new default NSS database for IPA. /etc/pki/nssdb is still maintained for backward compatibility. https://fedorahosted.org/freeipa/ticket/3259 Reviewed-By: Rob Crittenden <rcritten@redhat.com>
-rw-r--r--freeipa.spec.in17
-rwxr-xr-xipa-client/ipa-install/ipa-client-install159
-rw-r--r--ipa-client/ipaclient/ipa_certupdate.py9
-rw-r--r--ipalib/rpc.py2
-rw-r--r--ipaplatform/base/paths.py2
-rw-r--r--ipapython/certdb.py28
6 files changed, 153 insertions, 64 deletions
diff --git a/freeipa.spec.in b/freeipa.spec.in
index e3ffc0bad..6e9747fde 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -424,6 +424,7 @@ mkdir -p %{buildroot}/%{_localstatedir}/lib/ipa/backup
mkdir -p %{buildroot}%{_sysconfdir}/ipa/
/bin/touch %{buildroot}%{_sysconfdir}/ipa/default.conf
/bin/touch %{buildroot}%{_sysconfdir}/ipa/ca.crt
+mkdir -p %{buildroot}%{_sysconfdir}/ipa/nssdb
mkdir -p %{buildroot}/%{_localstatedir}/lib/ipa-client/sysrestore
mkdir -p %{buildroot}%{_sysconfdir}/bash_completion.d
install -pm 644 contrib/completion/ipa.bash_completion %{buildroot}%{_sysconfdir}/bash_completion.d/ipa
@@ -538,6 +539,17 @@ if [ $1 -gt 1 ] ; then
/bin/systemctl condrestart ntpd.service 2>&1 || :
fi
fi
+
+ if [ ! -f '/etc/ipa/nssdb/cert8.db' -a $restore -ge 2 ]; then
+ python2 -c 'from ipapython.certdb import create_ipa_nssdb; create_ipa_nssdb()' >/dev/null 2>&1
+ tempfile=$(mktemp)
+ if certutil -L -d /etc/pki/nssdb -n 'IPA CA' -a >"$tempfile" 2>/var/log/ipaupgrade.log; then
+ certutil -A -d /etc/ipa/nssdb -n 'IPA CA' -t CT,C,C -a -i "$tempfile" >/var/log/ipaupgrade.log 2>&1
+ elif certutil -L -d /etc/pki/nssdb -n 'External CA cert' -a >"$tempfile" 2>/var/log/ipaupgrade.log; then
+ certutil -A -d /etc/ipa/nssdb -n 'External CA cert' -t C,, -a -i "$tempfile" >/var/log/ipaupgrade.log 2>&1
+ fi
+ rm -f "$tempfile"
+ fi
fi
%triggerin -n freeipa-client -- openssh-server
@@ -798,6 +810,11 @@ fi
%dir %attr(0755,root,root) %{_sysconfdir}/ipa/
%ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/default.conf
%ghost %attr(0644,root,apache) %config(noreplace) %{_sysconfdir}/ipa/ca.crt
+%dir %attr(0755,root,root) %{_sysconfdir}/ipa/nssdb
+%ghost %config(noreplace) %{_sysconfdir}/ipa/nssdb/cert8.db
+%ghost %config(noreplace) %{_sysconfdir}/ipa/nssdb/key3.db
+%ghost %config(noreplace) %{_sysconfdir}/ipa/nssdb/secmod.db
+%ghost %config(noreplace) %{_sysconfdir}/ipa/nssdb/pwdfile.txt
%if ! %{ONLY_CLIENT}
%files tests -f tests-python.list
diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index 45e802207..ab40cd827 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -46,7 +46,7 @@ try:
from ipaplatform import services
from ipaplatform.paths import paths
from ipapython import ipautil, sysrestore, version, certmonger, ipaldap
- from ipapython import kernel_keyring
+ from ipapython import kernel_keyring, certdb
from ipapython.config import IPAOptionParser
from ipalib import api, errors
from ipalib import x509, certstore
@@ -550,6 +550,15 @@ def uninstall(options, env):
cmonger.service_name, str(e))
# Remove our host cert and CA cert
+ for filename in (os.path.join(paths.IPA_NSSDB_DIR, 'cert8.db'),
+ os.path.join(paths.IPA_NSSDB_DIR, 'key3.db'),
+ os.path.join(paths.IPA_NSSDB_DIR, 'secmod.db'),
+ os.path.join(paths.IPA_NSSDB_DIR, 'pwdfile.txt')):
+ try:
+ os.remove(filename)
+ except OSError, e:
+ root_logger.error("Failed to remove %s: %s", filename, e)
+
purge_ipa_certs({client_nss_nickname, 'IPA CA', 'External CA cert'})
try:
@@ -2524,62 +2533,69 @@ def install(options, env, fstore, statestore):
except ValueError:
pass
- # Add CA certs to a temporary NSS database
+ tmp_nss_dir = tempfile.mkdtemp()
try:
- os.mkdir(paths.IPA_NSSDB_DIR)
- pwd_file = ipautil.write_tmp_file(ipautil.ipa_generate_password())
- run([paths.CERTUTIL, '-N',
- '-d', paths.IPA_NSSDB_DIR,
- '-f', pwd_file.name])
-
- ca_certs = x509.load_certificate_list_from_file(CACERT)
- ca_certs = [cert.der_data for cert in ca_certs]
- for i, cert in enumerate(ca_certs):
- run([paths.CERTUTIL, '-A',
- '-d', paths.IPA_NSSDB_DIR,
- '-n', 'CA certificate %d' % (i + 1),
- '-t', 'C,,'],
- stdin=cert)
- except CalledProcessError, e:
- root_logger.info("Failed to add CA to temporary NSS database.")
- return CLIENT_INSTALL_ERROR
+ # Add CA certs to a temporary NSS database
+ try:
+ pwd_file = ipautil.write_tmp_file(ipautil.ipa_generate_password())
+ run([paths.CERTUTIL, '-N',
+ '-d', tmp_nss_dir,
+ '-f', pwd_file.name])
- # Now, let's try to connect to the server's XML-RPC interface
- connected = False
- try:
- api.Backend.rpcclient.connect(nss_dir=paths.IPA_NSSDB_DIR)
- connected = True
- root_logger.debug('Try RPC connection')
- api.Backend.rpcclient.forward('ping')
- except errors.KerberosError, e:
- if connected:
- api.Backend.rpcclient.disconnect()
- root_logger.info('Cannot connect to the server due to ' +
- 'Kerberos error: %s. Trying with delegate=True', str(e))
+ ca_certs = x509.load_certificate_list_from_file(CACERT)
+ ca_certs = [cert.der_data for cert in ca_certs]
+ for i, cert in enumerate(ca_certs):
+ run([paths.CERTUTIL, '-A',
+ '-d', tmp_nss_dir,
+ '-n', 'CA certificate %d' % (i + 1),
+ '-t', 'C,,'],
+ stdin=cert)
+ except CalledProcessError, e:
+ root_logger.info("Failed to add CA to temporary NSS database.")
+ return CLIENT_INSTALL_ERROR
+
+ # Now, let's try to connect to the server's RPC interface
+ connected = False
try:
- api.Backend.rpcclient.connect(delegate=True, nss_dir=paths.IPA_NSSDB_DIR)
- root_logger.debug('Try RPC connection')
+ api.Backend.rpcclient.connect(nss_dir=tmp_nss_dir)
+ connected = True
+ root_logger.debug("Try RPC connection")
api.Backend.rpcclient.forward('ping')
+ except errors.KerberosError, e:
+ if connected:
+ api.Backend.rpcclient.disconnect()
+ root_logger.info(
+ "Cannot connect to the server due to Kerberos error: %s. "
+ "Trying with delegate=True", e)
+ try:
+ api.Backend.rpcclient.connect(delegate=True,
+ nss_dir=tmp_nss_dir)
+ root_logger.debug("Try RPC connection")
+ api.Backend.rpcclient.forward('ping')
- root_logger.info('Connection with delegate=True successful')
+ root_logger.info("Connection with delegate=True successful")
- # The remote server is not capable of Kerberos S4U2Proxy delegation
- # This features is implemented in IPA server version 2.2 and higher
- root_logger.warning("Target IPA server has a lower version than " +
- "the enrolled client")
- root_logger.warning("Some capabilities including the ipa " +
- "command capability may not be available")
- except errors.PublicError, e2:
- root_logger.warning(
- 'Second connect with delegate=True also failed: %s', str(e2))
+ # The remote server is not capable of Kerberos S4U2Proxy
+ # delegation. This features is implemented in IPA server
+ # version 2.2 and higher
+ root_logger.warning(
+ "Target IPA server has a lower version than the enrolled "
+ "client")
+ root_logger.warning(
+ "Some capabilities including the ipa command capability "
+ "may not be available")
+ except errors.PublicError, e2:
+ root_logger.warning(
+ "Second connect with delegate=True also failed: %s", e2)
+ root_logger.error(
+ "Cannot connect to the IPA server RPC interface: %s", e2)
+ return CLIENT_INSTALL_ERROR
+ except errors.PublicError, e:
root_logger.error(
- "Cannot connect to the IPA server XML-RPC interface: %s",
- str(e2))
+ "Cannot connect to the server due to generic error: %s", e)
return CLIENT_INSTALL_ERROR
- except errors.PublicError, e:
- root_logger.error(
- 'Cannot connect to the server due to generic error: %s', str(e))
- return CLIENT_INSTALL_ERROR
+ finally:
+ shutil.rmtree(tmp_nss_dir)
# Use the RPC directly so older servers are supported
result = api.Backend.rpcclient.forward(
@@ -2591,14 +2607,38 @@ def install(options, env, fstore, statestore):
if not remote_env['enable_ra']:
disable_ra()
+ # Create IPA NSS database
+ try:
+ certdb.create_ipa_nssdb()
+ except ipautil.CalledProcessError, e:
+ root_logger.error("Failed to create IPA NSS database: %s", e)
+ return CLIENT_INSTALL_ERROR
+
# Get CA certificates from the certificate store
ca_certs = get_certs_from_ldap(cli_server[0], cli_basedn, cli_realm,
remote_env['enable_ra'])
+ ca_certs_trust = [(c, n, certstore.key_policy_to_trust_flags(t, True, u))
+ for (c, n, t, u) in ca_certs]
- # Add the CA to the platform-dependant systemwide CA store
+ # Add the CA certificates to the IPA NSS database
+ root_logger.debug("Adding CA certificates to the IPA NSS database.")
+ for cert, nickname, trust_flags in ca_certs_trust:
+ try:
+ run([paths.CERTUTIL,
+ "-A",
+ "-d", paths.IPA_NSSDB_DIR,
+ "-n", nickname,
+ "-t", trust_flags],
+ stdin=cert)
+ except CalledProcessError, e:
+ root_logger.error(
+ "Failed to add %s to the IPA NSS database.", nickname)
+ return CLIENT_INSTALL_ERROR
+
+ # Add the CA certificates to the platform-dependant systemwide CA store
tasks.insert_ca_certs_into_systemwide_ca_store(ca_certs)
- # Add the CA to the default NSS database and trust it
+ # Add the CA certificates to the default NSS database
if not purge_ipa_certs():
root_logger.info(
"Failed to remove old IPA certificates from the default NSS "
@@ -2611,12 +2651,10 @@ def install(options, env, fstore, statestore):
root_logger.error("Failed to open /etc/pki/nssdb/ipa.txt: %s", e)
return CLIENT_INSTALL_ERROR
- for cert, nickname, trusted, ext_key_usage in ca_certs:
+ root_logger.debug(
+ "Attempting to add CA certificates to the default NSS database.")
+ for cert, nickname, trust_flags in ca_certs_trust:
try:
- root_logger.debug("Attempting to add CA directly to the "
- "default NSS database.")
- trust_flags = certstore.key_policy_to_trust_flags(
- trusted, True, ext_key_usage)
run([paths.CERTUTIL,
"-A",
"-d", paths.NSS_DB_DIR,
@@ -2624,12 +2662,13 @@ def install(options, env, fstore, statestore):
"-t", trust_flags],
stdin=cert)
except CalledProcessError, e:
- root_logger.info("Failed to add CA to the default NSS database.")
+ root_logger.error(
+ "Failed to add %s to the default NSS database.", nickname)
list_file.close()
return CLIENT_INSTALL_ERROR
else:
- root_logger.info('Added the CA to the default NSS database.')
list_file.write(nickname + '\n')
+ root_logger.info("Added CA certificates to the default NSS database.")
list_file.close()
@@ -2855,7 +2894,3 @@ finally:
os.remove(CCACHE_FILE)
except Exception:
pass
- try:
- shutil.rmtree(paths.IPA_NSSDB_DIR)
- except Exception:
- pass
diff --git a/ipa-client/ipaclient/ipa_certupdate.py b/ipa-client/ipaclient/ipa_certupdate.py
index 8e7fe0470..57dbf200b 100644
--- a/ipa-client/ipaclient/ipa_certupdate.py
+++ b/ipa-client/ipaclient/ipa_certupdate.py
@@ -70,6 +70,15 @@ class CertUpdate(admintool.AdminTool):
def update_client(self, certs):
self.update_file(paths.IPA_CA_CRT, certs)
+ self.update_db(paths.IPA_NSSDB_DIR, certs)
+
+ for nickname in ('IPA CA', 'External CA cert'):
+ try:
+ ipautil.run([paths.CERTUTIL, '-D',
+ '-d', paths.NSS_DB_DIR,
+ '-n', nickname])
+ except ipautil.CalledProcessError, e:
+ pass
self.update_db(paths.NSS_DB_DIR, certs)
diff --git a/ipalib/rpc.py b/ipalib/rpc.py
index e7e60f414..5934f0c26 100644
--- a/ipalib/rpc.py
+++ b/ipalib/rpc.py
@@ -483,7 +483,7 @@ class SSLTransport(LanguageAwareTransport):
if self._connection and host == self._connection[0]:
return self._connection[1]
- dbdir = getattr(context, 'nss_dir', paths.NSS_DB_DIR)
+ dbdir = getattr(context, 'nss_dir', paths.IPA_NSSDB_DIR)
no_init = self.__nss_initialized(dbdir)
if sys.version_info < (2, 7):
conn = NSSHTTPS(host, 443, dbdir=dbdir, no_init=no_init)
diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
index 5093408e3..283aab682 100644
--- a/ipaplatform/base/paths.py
+++ b/ipaplatform/base/paths.py
@@ -63,7 +63,7 @@ class BasePathNamespace(object):
IPA_DNS_UPDATE_TXT = "/etc/ipa/.dns_update.txt"
IPA_CA_CRT = "/etc/ipa/ca.crt"
IPA_DEFAULT_CONF = "/etc/ipa/default.conf"
- IPA_NSSDB_DIR = "/etc/ipa/.nssdb"
+ IPA_NSSDB_DIR = "/etc/ipa/nssdb"
KRB5_CONF = "/etc/krb5.conf"
KRB5_KEYTAB = "/etc/krb5.keytab"
LDAP_CONF = "/etc/ldap.conf"
diff --git a/ipapython/certdb.py b/ipapython/certdb.py
index a85831380..426c80996 100644
--- a/ipapython/certdb.py
+++ b/ipapython/certdb.py
@@ -17,6 +17,34 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
+import os
+
+from ipaplatform.paths import paths
+from ipapython import ipautil
+
CA_NICKNAME_FMT = "%s IPA CA"
+
+
def get_ca_nickname(realm, format=CA_NICKNAME_FMT):
return format % realm
+
+
+def create_ipa_nssdb():
+ pwdfile = os.path.join(paths.IPA_NSSDB_DIR, 'pwdfile.txt')
+
+ ipautil.backup_file(pwdfile)
+ ipautil.backup_file(os.path.join(paths.IPA_NSSDB_DIR, 'cert8.db'))
+ ipautil.backup_file(os.path.join(paths.IPA_NSSDB_DIR, 'key3.db'))
+ ipautil.backup_file(os.path.join(paths.IPA_NSSDB_DIR, 'secmod.db'))
+
+ with open(pwdfile, 'w') as f:
+ f.write(ipautil.ipa_generate_password(pwd_len=40))
+ os.chmod(pwdfile, 0600)
+
+ ipautil.run([paths.CERTUTIL,
+ "-N",
+ "-d", paths.IPA_NSSDB_DIR,
+ "-f", pwdfile])
+ os.chmod(os.path.join(paths.IPA_NSSDB_DIR, 'cert8.db'), 0644)
+ os.chmod(os.path.join(paths.IPA_NSSDB_DIR, 'key3.db'), 0644)
+ os.chmod(os.path.join(paths.IPA_NSSDB_DIR, 'secmod.db'), 0644)