# Authors: # Alexander Bokovoy # # Copyright (C) 2012 Red Hat # see file 'COPYING' for use and warranty information # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . import logging from ipalib.install import certstore from ipaserver.install import certs, dsinstance from ipapython.ipaldap import realm_to_serverid from ipalib import Registry, errors from ipalib import Updater from ipapython import certdb from ipapython.dn import DN logger = logging.getLogger(__name__) register = Registry() @register() class update_upload_cacrt(Updater): """ Upload public CA certificate to LDAP """ def execute(self, **options): serverid = realm_to_serverid(self.api.env.realm) db = certs.CertDB(self.api.env.realm, nssdir=dsinstance.config_dirname(serverid)) ca_cert = None ca_enabled = self.api.Command.ca_is_enabled()['result'] if ca_enabled: ca_nickname = certdb.get_ca_nickname(self.api.env.realm) ca_subject = certstore.get_ca_subject( self.api.Backend.ldap2, self.api.env.container_ca, self.api.env.basedn) else: ca_nickname = None server_certs = db.find_server_certs() if server_certs: ca_chain = db.find_root_cert(server_certs[0][0])[:-1] if ca_chain: ca_nickname = ca_chain[-1] ldap = self.api.Backend.ldap2 for nickname, trust_flags in db.list_certs(): if trust_flags.has_key: continue cert = db.get_cert_from_db(nickname) subject = cert.subject if ca_enabled and subject == ca_subject: # When ca is enabled, we can have the IPA CA cert stored # in the nss db with a different nickname (for instance # when the server was installed with --subject to # customize the CA cert subject), but it must always be # stored in LDAP with the DN cn=$DOMAIN IPA CA # This is why we check the subject instead of the nickname here nickname = ca_nickname trust_flags = certdb.IPA_CA_TRUST_FLAGS trust, _ca, eku = certstore.trust_flags_to_key_policy(trust_flags) dn = DN(('cn', nickname), ('cn', 'certificates'), ('cn', 'ipa'), ('cn','etc'), self.api.env.basedn) entry = ldap.make_entry(dn) try: certstore.init_ca_entry(entry, cert, nickname, trust, eku) except Exception as e: logger.warning("Failed to create entry for %s: %s", nickname, e) continue if nickname == ca_nickname: ca_cert = cert config = entry.setdefault('ipaConfigString', []) if ca_enabled: config.append('ipaCa') config.append('compatCA') try: ldap.add_entry(entry) except errors.DuplicateEntry: if nickname == ca_nickname and ca_enabled: try: ldap.update_entry(entry) except errors.EmptyModlist: pass if ca_cert: dn = DN(('cn', 'CACert'), ('cn', 'ipa'), ('cn','etc'), self.api.env.basedn) try: entry = ldap.get_entry(dn) except errors.NotFound: entry = ldap.make_entry(dn) entry['objectclass'] = ['nsContainer', 'pkiCA'] entry.single_value['cn'] = 'CAcert' entry.single_value['cACertificate;binary'] = ca_cert ldap.add_entry(entry) else: force_write = False try: _cert_bin = entry['cACertificate;binary'] except ValueError: # BZ 1644874 # sometimes the cert is badly stored, twice encoded # force write to fix the value logger.debug('Fixing the value of cACertificate;binary ' 'in entry %s', entry.dn) force_write = True if force_write or b'' in entry['cACertificate;binary']: entry.single_value['cACertificate;binary'] = ca_cert ldap.update_entry(entry) return False, []