mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Fix ipa-server-install answer cache
Current Answer Cache storing mechanism is not ideal for storing non-trivial Python types like arrays, custom classes, etc. RawConfigParser just translates values to string, which are not correctly decoded when the Answer Cache is parsed and restored in the installer. This patch replaces RawConfigParser with Python's standard pickle module, which is a recommended way for serialization in Python. https://fedorahosted.org/freeipa/ticket/2054
This commit is contained in:
parent
9f07404fe3
commit
32a506cac8
@ -36,7 +36,7 @@ import signal
|
|||||||
import shutil
|
import shutil
|
||||||
import glob
|
import glob
|
||||||
import traceback
|
import traceback
|
||||||
from ConfigParser import RawConfigParser
|
import pickle
|
||||||
import random
|
import random
|
||||||
import tempfile
|
import tempfile
|
||||||
import nss.error
|
import nss.error
|
||||||
@ -302,45 +302,36 @@ ANSWER_CACHE = "/root/.ipa_cache"
|
|||||||
|
|
||||||
def read_cache(dm_password):
|
def read_cache(dm_password):
|
||||||
"""
|
"""
|
||||||
Returns a dict of cached answers or None if no cache file exists.
|
Returns a dict of cached answers or empty dict if no cache file exists.
|
||||||
"""
|
"""
|
||||||
if not ipautil.file_exists(ANSWER_CACHE):
|
if not ipautil.file_exists(ANSWER_CACHE):
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
top_dir = tempfile.mkdtemp("ipa")
|
top_dir = tempfile.mkdtemp("ipa")
|
||||||
|
fname = "%s/cache" % top_dir
|
||||||
try:
|
try:
|
||||||
clearfile = "%s/cache" % top_dir
|
decrypt_file(ANSWER_CACHE, fname, dm_password, top_dir)
|
||||||
decrypt_file(ANSWER_CACHE, clearfile, dm_password, top_dir)
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
shutil.rmtree(top_dir)
|
shutil.rmtree(top_dir)
|
||||||
raise RuntimeError("Problem decrypting answer cache in %s, check your password." % ANSWER_CACHE)
|
raise Exception("Decryption of answer cache in %s failed, please check your password." % ANSWER_CACHE)
|
||||||
|
|
||||||
optdict={}
|
|
||||||
parser = RawConfigParser()
|
|
||||||
try:
|
try:
|
||||||
fp = open(clearfile, "r")
|
with open(fname, 'rb') as f:
|
||||||
parser.readfp(fp)
|
try:
|
||||||
optlist = parser.items('options')
|
optdict = pickle.load(f)
|
||||||
fp.close()
|
except Exception, e:
|
||||||
|
raise Exception("Parse error in %s: %s" % (ANSWER_CACHE, str(e)))
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
raise RuntimeError("Error reading cache file %s: %s" % (ANSWER_CACHE, str(e)))
|
raise Exception("Read error in %s: %s" % (ANSWER_CACHE, str(e)))
|
||||||
finally:
|
finally:
|
||||||
shutil.rmtree(top_dir)
|
shutil.rmtree(top_dir)
|
||||||
|
|
||||||
for opt in optlist:
|
|
||||||
value = opt[1]
|
|
||||||
if value.lower() in ['true', 'false']:
|
|
||||||
value = value.lower() == 'true'
|
|
||||||
if value == 'None':
|
|
||||||
value = None
|
|
||||||
optdict[opt[0]] = value
|
|
||||||
|
|
||||||
# These are the only ones that may be overridden
|
# These are the only ones that may be overridden
|
||||||
if 'external_ca_file' in optdict:
|
for opt in ('external_ca_file', 'external_cert_file'):
|
||||||
del optdict['external_ca_file']
|
try:
|
||||||
if 'external_cert_file' in optdict:
|
del optdict[opt]
|
||||||
del optdict['external_cert_file']
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
return optdict
|
return optdict
|
||||||
|
|
||||||
@ -348,21 +339,14 @@ def write_cache(options):
|
|||||||
"""
|
"""
|
||||||
Takes a dict as input and writes a cached file of answers
|
Takes a dict as input and writes a cached file of answers
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# convert the options instance into a dict
|
|
||||||
optdict = eval(str(options))
|
|
||||||
parser = RawConfigParser()
|
|
||||||
top_dir = tempfile.mkdtemp("ipa")
|
top_dir = tempfile.mkdtemp("ipa")
|
||||||
|
fname = "%s/cache" % top_dir
|
||||||
try:
|
try:
|
||||||
fp = open("%s/cache" % top_dir, "w")
|
with open(fname, 'wb') as f:
|
||||||
parser.add_section('options')
|
pickle.dump(options, f)
|
||||||
for opt in optdict:
|
ipautil.encrypt_file(fname, ANSWER_CACHE, options['dm_password'], top_dir)
|
||||||
parser.set('options', opt, optdict[opt])
|
|
||||||
parser.write(fp)
|
|
||||||
fp.close()
|
|
||||||
ipautil.encrypt_file("%s/cache" % top_dir, ANSWER_CACHE, options.dm_password, top_dir);
|
|
||||||
except IOError, e:
|
except IOError, e:
|
||||||
raise RuntimeError("Unable to cache command-line options %s" % str(e))
|
raise Exception("Unable to cache command-line options %s" % str(e))
|
||||||
finally:
|
finally:
|
||||||
shutil.rmtree(top_dir)
|
shutil.rmtree(top_dir)
|
||||||
|
|
||||||
@ -636,7 +620,10 @@ def main():
|
|||||||
dm_password = read_password("Directory Manager", confirm=False)
|
dm_password = read_password("Directory Manager", confirm=False)
|
||||||
if dm_password is None:
|
if dm_password is None:
|
||||||
sys.exit("\nDirectory Manager password required")
|
sys.exit("\nDirectory Manager password required")
|
||||||
options._update_loose(read_cache(dm_password))
|
try:
|
||||||
|
options._update_loose(read_cache(dm_password))
|
||||||
|
except Exception, e:
|
||||||
|
sys.exit("Cannot process the cache file: %s" % str(e))
|
||||||
|
|
||||||
if options.external_cert_file:
|
if options.external_cert_file:
|
||||||
try:
|
try:
|
||||||
@ -964,7 +951,7 @@ def main():
|
|||||||
options.unattended = True
|
options.unattended = True
|
||||||
options.forwarders = dns_forwarders
|
options.forwarders = dns_forwarders
|
||||||
options.reverse_zone = reverse_zone
|
options.reverse_zone = reverse_zone
|
||||||
write_cache(options)
|
write_cache(vars(options))
|
||||||
ca.configure_instance(host_name, dm_password, dm_password,
|
ca.configure_instance(host_name, dm_password, dm_password,
|
||||||
csr_file="/root/ipa.csr",
|
csr_file="/root/ipa.csr",
|
||||||
subject_base=options.subject)
|
subject_base=options.subject)
|
||||||
|
Loading…
Reference in New Issue
Block a user