summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xinstall/tools/ipa-server-install5
-rwxr-xr-xipa-client/ipa-install/ipa-client-install19
-rw-r--r--ipa-client/man/ipa-client-install.12
-rw-r--r--ipapython/certmonger.py (renamed from ipaserver/install/certmonger.py)102
-rw-r--r--ipaserver/install/certs.py27
-rw-r--r--ipaserver/install/dsinstance.py4
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)