summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2009-04-17 17:17:31 -0400
committerRob Crittenden <rcritten@redhat.com>2009-05-04 16:54:42 -0400
commitdfe9db55484339a8a9f2ce3bd057bd9702bb9579 (patch)
treefb99b81da54e189d6ea08c47348b4e044990ecbc
parent36c239cda44c3e816a3ffd95957f2d49f434f62b (diff)
downloadfreeipa-dfe9db55484339a8a9f2ce3bd057bd9702bb9579.zip
freeipa-dfe9db55484339a8a9f2ce3bd057bd9702bb9579.tar.gz
freeipa-dfe9db55484339a8a9f2ce3bd057bd9702bb9579.tar.xz
Add signing profile to CA installation so we can sign the firefox jar file.
Use the requestId we get back from the CA when requesting the RA agent cert and use that to issue the certificate rather than hardcoding 7. This also adds some clean-up of file permissions and leaking fds
-rw-r--r--install/share/Makefile.am1
-rw-r--r--install/share/caJarSigningCert.cfg.template88
-rw-r--r--ipaserver/install/cainstance.py40
-rw-r--r--ipaserver/install/certs.py149
-rw-r--r--ipaserver/install/httpinstance.py9
-rw-r--r--ipaserver/install/installutils.py29
6 files changed, 259 insertions, 57 deletions
diff --git a/install/share/Makefile.am b/install/share/Makefile.am
index 6ef43ba..3a2ef87 100644
--- a/install/share/Makefile.am
+++ b/install/share/Makefile.am
@@ -10,6 +10,7 @@ app_DATA = \
60basev2.ldif \
60policyv2.ldif \
bootstrap-template.ldif \
+ caJarSigningCert.cfg.template \
default-aci.ldif \
default-keytypes.ldif \
kerberos.ldif \
diff --git a/install/share/caJarSigningCert.cfg.template b/install/share/caJarSigningCert.cfg.template
new file mode 100644
index 0000000..9f01855
--- /dev/null
+++ b/install/share/caJarSigningCert.cfg.template
@@ -0,0 +1,88 @@
+desc=Jar Signing certificate to auto-configure Firefox
+enable=true
+enableBy=admin
+lastModified=1239836280692
+name=Manual Jar Signing Certificate Enrollment
+visible=true
+auth.class_id=
+auth.instance_id=raCertAuth
+input.list=i1,i2
+input.i1.class_id=certReqInputImpl
+input.i2.class_id=submitterInfoInputImpl
+output.list=o1
+output.o1.class_id=certOutputImpl
+policyset.list=caJarSigningSet
+policyset.caJarSigningSet.list=1,2,3,6,7,9
+policyset.caJarSigningSet.1.constraint.class_id=subjectNameConstraintImpl
+policyset.caJarSigningSet.1.constraint.name=Subject Name Constraint
+policyset.caJarSigningSet.1.constraint.params.accept=true
+policyset.caJarSigningSet.1.constraint.params.pattern=.*
+policyset.caJarSigningSet.1.default.class_id=userSubjectNameDefaultImpl
+policyset.caJarSigningSet.1.default.name=Subject Name Default
+policyset.caJarSigningSet.1.default.params.name=
+policyset.caJarSigningSet.2.constraint.class_id=validityConstraintImpl
+policyset.caJarSigningSet.2.constraint.name=Validity Constraint
+policyset.caJarSigningSet.2.constraint.params.notAfterCheck=false
+policyset.caJarSigningSet.2.constraint.params.notBeforeCheck=false
+policyset.caJarSigningSet.2.constraint.params.range=2922
+policyset.caJarSigningSet.2.default.class_id=validityDefaultImpl
+policyset.caJarSigningSet.2.default.name=Validity Default
+policyset.caJarSigningSet.2.default.params.range=1461
+policyset.caJarSigningSet.2.default.params.startTime=60
+policyset.caJarSigningSet.3.constraint.class_id=keyConstraintImpl
+policyset.caJarSigningSet.3.constraint.name=Key Constraint
+policyset.caJarSigningSet.3.constraint.params.keyMaxLength=4096
+policyset.caJarSigningSet.3.constraint.params.keyMinLength=1024
+policyset.caJarSigningSet.3.constraint.params.keyType=-
+policyset.caJarSigningSet.3.default.class_id=userKeyDefaultImpl
+policyset.caJarSigningSet.3.default.name=Key Default
+policyset.caJarSigningSet.6.constraint.class_id=keyUsageExtConstraintImpl
+policyset.caJarSigningSet.6.constraint.name=Key Usage Extension Constraint
+policyset.caJarSigningSet.6.constraint.params.keyUsageCritical=-
+policyset.caJarSigningSet.6.constraint.params.keyUsageCrlSign=-
+policyset.caJarSigningSet.6.constraint.params.keyUsageDataEncipherment=-
+policyset.caJarSigningSet.6.constraint.params.keyUsageDecipherOnly=-
+policyset.caJarSigningSet.6.constraint.params.keyUsageDigitalSignature=-
+policyset.caJarSigningSet.6.constraint.params.keyUsageEncipherOnly=-
+policyset.caJarSigningSet.6.constraint.params.keyUsageKeyAgreement=-
+policyset.caJarSigningSet.6.constraint.params.keyUsageKeyCertSign=-
+policyset.caJarSigningSet.6.constraint.params.keyUsageKeyEncipherment=-
+policyset.caJarSigningSet.6.constraint.params.keyUsageNonRepudiation=-
+policyset.caJarSigningSet.6.default.class_id=keyUsageExtDefaultImpl
+policyset.caJarSigningSet.6.default.name=Key Usage Default
+policyset.caJarSigningSet.6.default.params.keyUsageCritical=true
+policyset.caJarSigningSet.6.default.params.keyUsageCrlSign=false
+policyset.caJarSigningSet.6.default.params.keyUsageDataEncipherment=false
+policyset.caJarSigningSet.6.default.params.keyUsageDecipherOnly=false
+policyset.caJarSigningSet.6.default.params.keyUsageDigitalSignature=true
+policyset.caJarSigningSet.6.default.params.keyUsageEncipherOnly=false
+policyset.caJarSigningSet.6.default.params.keyUsageKeyAgreement=false
+policyset.caJarSigningSet.6.default.params.keyUsageKeyCertSign=true
+policyset.caJarSigningSet.6.default.params.keyUsageKeyEncipherment=false
+policyset.caJarSigningSet.6.default.params.keyUsageNonRepudiation=false
+policyset.caJarSigningSet.7.constraint.class_id=nsCertTypeExtConstraintImpl
+policyset.caJarSigningSet.7.constraint.name=Netscape Certificate Type Extension Constraint
+policyset.caJarSigningSet.7.constraint.params.nsCertCritical=-
+policyset.caJarSigningSet.7.constraint.params.nsCertEmail=-
+policyset.caJarSigningSet.7.constraint.params.nsCertEmailCA=-
+policyset.caJarSigningSet.7.constraint.params.nsCertObjectSigning=-
+policyset.caJarSigningSet.7.constraint.params.nsCertObjectSigningCA=-
+policyset.caJarSigningSet.7.constraint.params.nsCertSSLCA=-
+policyset.caJarSigningSet.7.constraint.params.nsCertSSLClient=-
+policyset.caJarSigningSet.7.constraint.params.nsCertSSLServer=-
+policyset.caJarSigningSet.7.default.class_id=nsCertTypeExtDefaultImpl
+policyset.caJarSigningSet.7.default.name=Netscape Certificate Type Extension Default
+policyset.caJarSigningSet.7.default.params.nsCertCritical=false
+policyset.caJarSigningSet.7.default.params.nsCertEmail=false
+policyset.caJarSigningSet.7.default.params.nsCertEmailCA=false
+policyset.caJarSigningSet.7.default.params.nsCertObjectSigning=true
+policyset.caJarSigningSet.7.default.params.nsCertObjectSigningCA=false
+policyset.caJarSigningSet.7.default.params.nsCertSSLCA=false
+policyset.caJarSigningSet.7.default.params.nsCertSSLClient=false
+policyset.caJarSigningSet.7.default.params.nsCertSSLServer=false
+policyset.caJarSigningSet.9.constraint.class_id=signingAlgConstraintImpl
+policyset.caJarSigningSet.9.constraint.name=No Constraint
+policyset.caJarSigningSet.9.constraint.params.signingAlgsAllowed=MD5withRSA,MD2withRSA,SHA1withRSA,SHA256withRSA,SHA512withRSA,SHA1withDSA,SHA1withEC
+policyset.caJarSigningSet.9.default.class_id=signingAlgDefaultImpl
+policyset.caJarSigningSet.9.default.name=Signing Alg
+policyset.caJarSigningSet.9.default.params.signingAlg=-
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 088744a..d33901d 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -34,6 +34,7 @@ import shutil
import httplib
import urllib
import xml.dom.minidom
+import stat
from nss.error import NSPRError
import nss.nss as nss
@@ -44,7 +45,6 @@ from ipapython import nsslib
from ipaserver.install import service
from ipaserver.install import installutils
from ipaserver import ipaldap
-from ipaserver.install import ldapupdate
from ipaserver.install import dsinstance
from ipalib import util
@@ -368,6 +368,7 @@ class CAInstance(service.Service):
self.server_root = "/var/lib"
self.secure_port = 9444
self.ra_cert = None
+ self.requestId = None
def __del__(self):
shutil.rmtree(self.ca_agent_db, ignore_errors=True)
@@ -390,6 +391,7 @@ class CAInstance(service.Service):
self.step("issuing RA agent certificate", self.__issue_ra_cert)
self.step("adding RA agent as a trusted user", self.__configure_ra)
self.step("fixing RA database permissions", self.__fix_ra_perms)
+ self.step("setting up signing cert profile", self.__setup_sign_profile)
self.step("configuring certificate server to start on boot", self.__enable)
self.step("restarting certificate server", self.__restart_instance)
@@ -540,7 +542,7 @@ class CAInstance(service.Service):
def __restart_instance(self):
try:
self.restart()
- except Exception:
+ except Exception, e:
# TODO: roll back here?
logging.critical("Failed to restart the certificate server. See the installation log for details.")
@@ -577,9 +579,10 @@ class CAInstance(service.Service):
'-n', 'ipa-ca-agent',
'-p', self.admin_password,
'-d', self.ca_agent_db,
- '-r', '/ca/agent/ca/profileReview?requestId=7',
+ '-r', '/ca/agent/ca/profileReview?requestId=%s' % self.requestId,
'%s:%d' % (self.host_name, 9443),
]
+ logging.debug("running sslget %s" % args)
(stdout, stderr) = ipautil.run(args)
data = stdout.split('\r\n')
@@ -589,6 +592,8 @@ class CAInstance(service.Service):
params['submit'] = 'submit'
params['requestNotes'] = ''
params = urllib.urlencode(params)
+ headers = {"Content-type": "application/x-www-form-urlencoded",
+ "Accept": "text/plain"}
# Now issue the RA certificate.
args = [
@@ -600,6 +605,7 @@ class CAInstance(service.Service):
'-r', '/ca/agent/ca/profileProcess',
'%s:%d' % (self.host_name, 9443),
]
+ logging.debug("running sslget %s" % args)
(stdout, stderr) = ipautil.run(args)
data = stdout.split('\r\n')
@@ -679,6 +685,7 @@ class CAInstance(service.Service):
f = os.open(self.ra_agent_pwd, os.O_CREAT | os.O_RDWR)
os.write(f, hex_str)
os.close(f)
+ os.chmod(self.ra_agent_pwd, stat.S_IRUSR)
stdout, stderr = self.__run_certutil(["-N"])
@@ -758,11 +765,14 @@ class CAInstance(service.Service):
res = conn.getresponse()
if res.status == 200:
data = res.read()
- # FIXME: pull the requestId out so of the response so it isn't
- # later hard-coded at 7
-# print data
-
conn.close()
+ doc = xml.dom.minidom.parseString(data)
+ item_node = doc.getElementsByTagName("RequestId")
+ self.requestId = item_node[0].childNodes[0].data
+ doc.unlink()
+ self.requestId = self.requestId.strip()
+ if self.requestId is None:
+ raise RuntimeError("Unable to determine RA certificate requestId")
else:
conn.close()
raise RuntimeError("Unable to submit RA cert request")
@@ -778,6 +788,22 @@ class CAInstance(service.Service):
os.chown(self.ra_agent_db + "/secmod.db", 0, pent.pw_gid )
os.chown(self.ra_agent_pwd, 0, pent.pw_gid)
+ def __setup_sign_profile(self):
+ caconfig = "/var/lib/pki-ca/conf/CS.cfg"
+
+ if not ipautil.file_exists('/var/lib/pki-ca/profiles/ca/caJarSigningCert.cfg'):
+ profile = ipautil.template_file(ipautil.SHARE_DIR + "caJarSigningCert.cfg.template", {})
+ fd = open("/var/lib/pki-ca/profiles/ca/caJarSigningCert.cfg", "w")
+ fd.write(profile)
+ fd.close()
+
+ profilelist = installutils.get_directive(caconfig, "profile.list", separator="=")
+ if profilelist.find('caJarSigningCert') < 0:
+ profilelist = profilelist + ',caJarSigningCert'
+ installutils.set_directive(caconfig, 'profile.list', profilelist, quotes=False, separator='=')
+ installutils.set_directive(caconfig, 'profile.caJarSigningCert.class_id', 'caEnrollImpl', quotes=False, separator='=')
+ installutils.set_directive(caconfig, 'profile.caJarSigningCert.config', '/var/lib/pki-ca/profiles/ca/caJarSigningCert.cfg', quotes=False, separator='=')
+
def uninstall(self):
try:
ipautil.run(["/usr/bin/pkiremove", "-pki_instance_root=/var/lib",
diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
index 45958f2..bad9a1e 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -23,8 +23,10 @@ import errno
import tempfile
import shutil
import logging
+import httplib
import urllib
import xml.dom.minidom
+import pwd
from ipapython import nsslib
from ipapython import sysrestore
@@ -165,8 +167,12 @@ class CertDB(object):
return str(self.cur_serial)
- def set_perms(self, fname, write=False):
- os.chown(fname, self.uid, self.gid)
+ def set_perms(self, fname, write=False, uid=None):
+ if uid:
+ pent = pwd.getpwnam(uid)
+ os.chown(fname, pent.pw_uid, pent.pw_gid)
+ else:
+ os.chown(fname, self.uid, self.gid)
perms = stat.S_IRUSR
if write:
perms |= stat.S_IWUSR
@@ -181,7 +187,13 @@ class CertDB(object):
return ipautil.run(new_args, stdin)
def run_signtool(self, args, stdin=None):
- new_args = ["/usr/bin/signtool", "-d", self.secdir]
+ if not self.self_signed_ca:
+ f = open(self.passwd_fname, "r")
+ password = f.readline()
+ f.close()
+ new_args = ["/usr/bin/signtool", "-d", self.secdir, "-p", password]
+ else:
+ new_args = ["/usr/bin/signtool", "-d", self.secdir]
new_args = new_args + args
ipautil.run(new_args, stdin)
@@ -233,7 +245,7 @@ class CertDB(object):
self.run_certutil(["-L", "-n", nickname,
"-a",
"-o", self.cacert_fname])
- self.set_perms(self.cacert_fname)
+ os.chmod(self.cacert_fname, stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
if create_pkcs12:
ipautil.backup_file(self.pk12_fname)
ipautil.run(["/usr/bin/pk12util", "-d", self.secdir,
@@ -286,11 +298,11 @@ class CertDB(object):
os.unlink(self.certreq_fname)
os.unlink(self.certder_fname)
- def create_signing_cert(self, nickname, name, other_certdb=None):
+ def create_signing_cert(self, nickname, subject, other_certdb=None):
cdb = other_certdb
if not cdb:
cdb = self
- self.request_cert(name)
+ self.request_cert(subject)
cdb.issue_signing_cert(self.certreq_fname, self.certder_fname)
self.add_cert(self.certder_fname, nickname)
os.unlink(self.certreq_fname)
@@ -365,8 +377,8 @@ class CertDB(object):
headers = {"Content-type": "application/x-www-form-urlencoded",
"Accept": "text/plain"}
- # Send the CSR request to the CA
- f = open(self.passwd_fname)
+ # Send the request to the CA
+ f = open(self.passwd_fname, "r")
password = f.readline()
f.close()
conn = nsslib.NSSConnection(self.host_name, 9444, dbdir=self.secdir)
@@ -385,6 +397,7 @@ class CertDB(object):
item_node = doc.getElementsByTagName("b64")
cert = item_node[0].childNodes[0].data
doc.unlink()
+ conn.close()
# Write the certificate to a file. It will be imported in a later
# step.
@@ -395,34 +408,87 @@ class CertDB(object):
return
def issue_signing_cert(self, certreq_fname, cert_fname):
- p = subprocess.Popen(["/usr/bin/certutil",
- "-d", self.secdir,
- "-C", "-c", self.cacert_name,
- "-i", certreq_fname,
- "-o", cert_fname,
- "-m", self.next_serial(),
- "-v", self.valid_months,
- "-f", self.passwd_fname,
- "-1", "-5"],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE)
-
- # Bah - this sucks, but I guess it isn't possible to fully
- # control this with command line arguments.
- #
- # What this is requesting is:
- # -1 (Create key usage extension)
- # 0 - Digital Signature
- # 5 - Cert signing key
- # 9 - done
- # n - not critical
- #
- # -5 (Create netscape cert type extension)
- # 3 - Object Signing
- # 9 - done
- # n - not critical
- p.stdin.write("0\n5\n9\nn\n3\n9\nn\n")
- p.wait()
+ if self.self_signed_ca:
+ p = subprocess.Popen(["/usr/bin/certutil",
+ "-d", self.secdir,
+ "-C", "-c", self.cacert_name,
+ "-i", certreq_fname,
+ "-o", cert_fname,
+ "-m", self.next_serial(),
+ "-v", self.valid_months,
+ "-f", self.passwd_fname,
+ "-1", "-5"],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+
+ # Bah - this sucks, but I guess it isn't possible to fully
+ # control this with command line arguments.
+ #
+ # What this is requesting is:
+ # -1 (Create key usage extension)
+ # 0 - Digital Signature
+ # 5 - Cert signing key
+ # 9 - done
+ # n - not critical
+ #
+ # -5 (Create netscape cert type extension)
+ # 3 - Object Signing
+ # 9 - done
+ # n - not critical
+ p.stdin.write("0\n5\n9\nn\n3\n9\nn\n")
+ p.wait()
+ else:
+ if self.host_name is None:
+ raise RuntimeError("CA Host is not set.")
+
+ f = open(certreq_fname, "r")
+ csr = f.readlines()
+ f.close()
+ csr = "".join(csr)
+
+ # We just want the CSR bits, make sure there is no thing else
+ s = csr.find("-----BEGIN NEW CERTIFICATE REQUEST-----")
+ e = csr.find("-----END NEW CERTIFICATE REQUEST-----")
+ if e > 0:
+ e = e + 37
+ if s >= 0:
+ csr = csr[s:]
+
+ params = urllib.urlencode({'profileId': 'caJarSigningCert',
+ 'cert_request_type': 'pkcs10',
+ 'requestor_name': 'IPA Installer',
+ 'cert_request': csr,
+ 'xmlOutput': 'true'})
+ headers = {"Content-type": "application/x-www-form-urlencoded",
+ "Accept": "text/plain"}
+
+ # Send the request to the CA
+ f = open(self.passwd_fname, "r")
+ password = f.readline()
+ f.close()
+ conn = nsslib.NSSConnection(self.host_name, 9444, dbdir=self.secdir)
+ conn.sslsock.set_client_auth_data_callback(client_auth_data_callback, "ipaCert", password, nss.get_default_certdb())
+ conn.set_debuglevel(0)
+
+ conn.request("POST", "/ca/ee/ca/profileSubmit", params, headers)
+ res = conn.getresponse()
+ data = res.read()
+ conn.close()
+ if res.status != 200:
+ raise RuntimeError("Unable to submit cert request")
+
+ # The result is an XML blob. Pull the certificate out of that
+ doc = xml.dom.minidom.parseString(data)
+ item_node = doc.getElementsByTagName("b64")
+ cert = item_node[0].childNodes[0].data
+ doc.unlink()
+ conn.close()
+
+ f = open(cert_fname, "w")
+ f.write(cert)
+ f.close()
+
+ return
def add_cert(self, cert_fname, nickname):
args = ["-A", "-n", nickname,
@@ -440,9 +506,10 @@ class CertDB(object):
ipautil.backup_file(self.pin_fname)
f = open(self.pin_fname, "w")
f.write("Internal (Software) Token:")
- pwd = open(self.passwd_fname)
- f.write(pwd.read())
+ pwdfile = open(self.passwd_fname)
+ f.write(pwdfile.read())
f.close()
+ pwdfile.close()
self.set_perms(self.pin_fname)
def create_password_conf(self):
@@ -452,9 +519,11 @@ class CertDB(object):
ipautil.backup_file(self.pwd_conf)
f = open(self.pwd_conf, "w")
f.write("internal:")
- pwd = open(self.passwd_fname)
- f.write(pwd.read())
+ pwdfile = open(self.passwd_fname)
+ f.write(pwdfile.read())
f.close()
+ pwdfile.close()
+ self.set_perms(self.pwd_conf, uid="apache")
def find_root_cert(self, nickname):
p = subprocess.Popen(["/usr/bin/certutil", "-d", self.secdir,
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
index 0637e3f..1bd9ffd 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -183,6 +183,7 @@ class HTTPInstance(service.Service):
db.create_signing_cert("Signing-Cert", "cn=%s,ou=Signing Certificate,o=Identity Policy Audit" % self.fqdn, ca_db)
else:
db.create_server_cert("Server-Cert", "CN=%s,OU=ipa-pki,O=IPA" % self.fqdn, ca_db)
+ db.create_signing_cert("Signing-Cert", "CN=Object Signing Cert,OU=ipa-pki,O=IPA", ca_db)
db.create_password_conf()
# Fix the database permissions
@@ -196,20 +197,12 @@ class HTTPInstance(service.Service):
os.chown(NSS_DIR + "/secmod.db", 0, pent.pw_gid )
def __setup_autoconfig(self):
- # FIXME. Need to issue the self-signed cert from the CA as well.
- # A special profile is needed from the CS team to do this.
- if not self.self_signed_ca:
- return
prefs_txt = ipautil.template_file(ipautil.SHARE_DIR + "preferences.html.template", self.sub_dict)
prefs_fd = open("/usr/share/ipa/html/preferences.html", "w")
prefs_fd.write(prefs_txt)
prefs_fd.close()
# The signing cert is generated in __setup_ssl
- if self.self_signed_ca:
- ca_db = certs.CertDB(dsinstance.config_dirname(dsinstance.realm_to_serverid(self.realm)))
- else:
- ca_db = certs.CertDB(NSS_DIR)
db = certs.CertDB(NSS_DIR)
tmpdir = tempfile.mkdtemp(prefix = "tmp-")
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index f5e0463..c120237 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -210,24 +210,49 @@ def update_file(filename, orig, subst):
print "File %s doesn't exist." % filename
return 1
-def set_directive(filename, directive, value):
+def set_directive(filename, directive, value, quotes=True, separator=' '):
"""Set a name/value pair directive in a configuration file.
This has only been tested with nss.conf
"""
+ valueset = False
fd = open(filename)
file = []
for line in fd:
if directive in line:
- file.append('%s "%s"\n' % (directive, value))
+ valueset = True
+ if quotes:
+ file.append('%s%s"%s"\n' % (directive, separator, value))
+ else:
+ file.append('%s%s%s\n' % (directive, separator, value))
else:
file.append(line)
fd.close()
+ if not valueset:
+ if quotes:
+ file.append('%s%s"%s"\n' % (directive, separator, value))
+ else:
+ file.append('%s%s%s\n' % (directive, separator, value))
fd = open(filename, "w")
fd.write("".join(file))
fd.close()
+def get_directive(filename, directive, strip_quotes=True, separator=' '):
+ """
+ A rather inefficient way to get a configuration directive.
+ """
+ fd = open(filename, "r")
+ for line in fd:
+ if directive in line:
+ line = line.strip()
+ result = line.split(separator, 1)[1]
+ result = result.strip('"')
+ fd.close()
+ return result
+ fd.close()
+ return None
+
def kadmin(command):
ipautil.run(["/usr/kerberos/sbin/kadmin.local", "-q", command])