diff options
-rwxr-xr-x | install/tools/ipa-server-install | 5 | ||||
-rwxr-xr-x | ipa-client/ipa-install/ipa-client-install | 19 | ||||
-rw-r--r-- | ipa-client/man/ipa-client-install.1 | 2 | ||||
-rw-r--r-- | ipapython/certmonger.py (renamed from ipaserver/install/certmonger.py) | 102 | ||||
-rw-r--r-- | ipaserver/install/certs.py | 27 | ||||
-rw-r--r-- | ipaserver/install/dsinstance.py | 4 |
6 files changed, 131 insertions, 28 deletions
diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install index 89bb83e3d..a62f8af4e 100755 --- a/install/tools/ipa-server-install +++ b/install/tools/ipa-server-install @@ -381,11 +381,12 @@ def uninstall(dm_password=None): api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=dm_password) try: - run(["/usr/sbin/ipa-client-install", "--on-master", "--unattended", "--uninstall"]) + (stdout, stderr, rc) = run(["/usr/sbin/ipa-client-install", "--on-master", "--unattended", "--uninstall"], raiseonerr=False) + if rc != 2: + raise RuntimeError(stdout) except Exception, e: print "Uninstall of client side components failed!" print "ipa-client-install returned: " + str(e) - pass ntpinstance.NTPInstance(fstore).uninstall() if cainstance.CADSInstance().is_configured(): diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install index e0abfd67a..d8ce5c930 100755 --- a/ipa-client/ipa-install/ipa-client-install +++ b/ipa-client/ipa-install/ipa-client-install @@ -34,6 +34,7 @@ try: from ipapython.ipautil import run, user_input, CalledProcessError, file_exists from ipapython import sysrestore from ipapython import version + from ipapython import certmonger import SSSDConfig from ConfigParser import RawConfigParser except ImportError: @@ -174,7 +175,7 @@ def uninstall(options): if not fstore.has_files() and not options.force: print "IPA client is not configured on this system." - return 1 + return 2 # Remove our host cert and CA cert if nickname_exists("IPA CA"): @@ -183,19 +184,25 @@ def uninstall(options): except Exception, e: print "Failed to remove IPA CA from /etc/pki/nssdb: %s" % str(e) if nickname_exists("Server-Cert"): + # Always start certmonger. We can't untrack something if it isn't + # running + try: + service('certmonger', 'start') + except: + pass + try: + certmonger.stop_tracking('/etc/pki/nssdb', nickname='Server-Cert') + except (CalledProcessError, RuntimeError), e: + logging.error("certmonger failed to stop tracking certificate: %s" % str(e)) try: run(["/usr/bin/certutil", "-D", "-d", "/etc/pki/nssdb", "-n", "Server-Cert"]) except Exception, e: print "Failed to remove Server-Cert from /etc/pki/nssdb: %s" % str(e) - try: - run(["/usr/bin/ipa-getcert", "stop-tracking", "-d", "/etc/pki/nssdb", "-n", "Server-Cert"]) - except Exception, e: - print "Failed to stop tracking Server-Cert in certmonger: %s" % str(e) try: service('certmonger', 'stop') except: - print "Failed to stop the certmonger daemon" + pass try: chkconfig('certmonger', 'off') diff --git a/ipa-client/man/ipa-client-install.1 b/ipa-client/man/ipa-client-install.1 index 4a1fcb543..4cdc921d7 100644 --- a/ipa-client/man/ipa-client-install.1 +++ b/ipa-client/man/ipa-client-install.1 @@ -81,3 +81,5 @@ Remove the IPA client software and restore the configuration to the pre-IPA stat 0 if the installation was successful 1 if an error occurred + +2 if uninstalling and the client is not configured diff --git a/ipaserver/install/certmonger.py b/ipapython/certmonger.py index bb56c2ab3..667a70de6 100644 --- a/ipaserver/install/certmonger.py +++ b/ipapython/certmonger.py @@ -76,6 +76,36 @@ def get_request_value(request_id, directive): return None +def get_request_id(criteria): + """ + If you don't know the certmonger request_id then try to find it by looking + through all the request files. An alternative would be to parse the + ipa-getcert list output but this seems cleaner. + + criteria is a tuple of key/value pairs to search for. The more specific + the better. An error is raised if multiple request_ids are returned for + the same criteria. + + None is returned if none of the criteria match. + """ + assert type(criteria) is tuple + + reqid=None + fileList=os.listdir(REQUEST_DIR) + for file in fileList: + match = True + for (key, value) in criteria: + rv = find_request_value('%s/%s' % (REQUEST_DIR, file), key) + if rv is None or rv.rstrip() != value: + match = False + break + if match and reqid is not None: + raise RuntimeError('multiple certmonger requests match the criteria') + if match: + reqid = find_request_value('%s/%s' % (REQUEST_DIR, file), 'id').rstrip() + + return reqid + def add_request_value(request_id, directive, value): """ Add a new directive to a certmonger request file. @@ -133,18 +163,84 @@ def request_cert(nssdb, nickname, subject, principal, passwd_fname=None): request_id = m.group(1) return request_id -def stop_tracking(request_id): +def cert_exists(nickname, secdir): + """ + See if a nickname exists in an NSS database. + + Returns True/False + + This isn't very sophisticated in that it doesn't differentiate between + a database that doesn't exist and a nickname that doesn't exist within + the database. + """ + args = ["/usr/bin/certutil", "-L", + "-d", secdir, + "-n", nickname + ] + (stdout, stderr, rc) = ipautil.run(args, raiseonerr=False) + if rc == 0: + return True + else: + return False + +def start_tracking(nickname, secdir, password_file=None): """ - Stop tracking the current request. + Tell certmonger to track the given certificate nickname in NSS + database in secdir protected by optional password file password_file. + + Returns the stdout, stderr and returncode from running ipa-getcert + + This assumes that certmonger is already running. + """ + if not cert_exists(nickname, secdir): + raise RuntimeError('Nickname "%s" doesn\'t exist in NSS database "%s"' % (nickname, secdir)) + args = ["/usr/bin/ipa-getcert", "start-tracking", + "-d", secdir, + "-n", nickname] + if password_file: + args.append("-p") + args.append(password_file) + + (stdout, stderr, returncode) = ipautil.run(args) + + return (stdout, stderr, returncode) + +def stop_tracking(secdir, request_id=None, nickname=None): + """ + Stop tracking the current request using either the request_id or nickname. This assumes that the certmonger service is running. """ + if request_id is None and nickname is None: + raise RuntimeError('Both request_id and nickname are missing.') + if nickname: + # Using the nickname find the certmonger request_id + criteria = (('cert_storage_location','%s' % secdir),('cert_nickname', '%s' % nickname)) + try: + request_id = get_request_id(criteria) + if request_id is None: + return ('', '', 0) + except RuntimeError: + # This means that multiple requests matched, skip it for now + # Fall back to trying to stop tracking using nickname + pass + args = ['/usr/bin/ipa-getcert', 'stop-tracking', - '-i', request_id ] + if request_id: + args.append('-i') + args.append(request_id) + else: + args.append('-n') + args.append(nickname) + args.append('-d') + args.append(secdir) + (stdout, stderr, returncode) = ipautil.run(args) + return (stdout, stderr, returncode) + if __name__ == '__main__': request_id = request_cert("/etc/httpd/alias", "Test", "cn=tiger.example.com,O=IPA", "HTTP/tiger.example.com@EXAMPLE.COM") csr = get_request_value(request_id, 'csr') diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py index 7f246d11c..c8e1d17d5 100644 --- a/ipaserver/install/certs.py +++ b/ipaserver/install/certs.py @@ -32,10 +32,10 @@ from ipapython import nsslib from ipapython import dogtag from ipapython import sysrestore from ipapython import ipautil +from ipapython import certmonger from ipalib import pkcs10 from ConfigParser import RawConfigParser import service -import certmonger from ipalib import x509 from nss.error import NSPRError @@ -441,21 +441,19 @@ class CertDB(object): """ service.chkconfig_on("certmonger") service.start("certmonger") - args = ["/usr/bin/ipa-getcert", "start-tracking", - "-d", self.secdir, - "-n", nickname] - if password_file: - args.append("-p") - args.append(password_file) try: - (stdout, stderr, returncode) = ipautil.run(args) - except ipautil.CalledProcessError, e: - logging.error("tracking certificate failed: %s" % str(e)) + (stdout, stderr, rc) = certmonger.start_tracking(nickname, self.secdir, password_file) + except (ipautil.CalledProcessError, RuntimeError), e: + logging.error("certmonger failed starting to track certificate: %s" % str(e)) + return service.stop("certmonger") cert = self.get_cert_from_db(nickname) subject = str(x509.get_subject(cert)) m = re.match('New tracking request "(\d+)" added', stdout) + if not m: + logging.error('Didn\'t get new certmonger request, got %s' % stdout) + raise RuntimeError('certmonger did not issue new tracking request for \'%s\' in \'%s\'. Use \'ipa-getcert list\' to list existing certificates.' % (nickname, self.secdir)) request_id = m.group(1) certmonger.add_principal(request_id, principal) @@ -471,13 +469,10 @@ class CertDB(object): # Always start certmonger. We can't untrack something if it isn't # running service.start("certmonger") - args = ["/usr/bin/ipa-getcert", "stop-tracking", - "-d", self.secdir, - "-n", nickname] try: - (stdout, stderr, returncode) = ipautil.run(args) - except ipautil.CalledProcessError, e: - logging.error("untracking certificate failed: %s" % str(e)) + certmonger.stop_tracking(self.secdir, nickname=nickname) + except (ipautil.CalledProcessError, RuntimeError), e: + logging.error("certmonger failed to stop tracking certificate: %s" % str(e)) service.stop("certmonger") def create_server_cert(self, nickname, hostname, other_certdb=None, subject=None): diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index a53348456..4a36f1b98 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -493,7 +493,9 @@ class DsInstance(service.Service): serverid = self.restore_state("serverid") if not serverid is None: - dirname = config_dirname(serverid) + # drop the trailing / off the config_dirname so the directory + # will match what is in certmonger + dirname = config_dirname(serverid)[:-1] dsdb = certs.CertDB(dirname) dsdb.untrack_server_cert("Server-Cert") erase_ds_instance_data(serverid) |