URL: https://github.com/freeipa/freeipa/pull/428 Author: MartinBasti Title: #428: [WIP] [Py3] ipa-server-install Action: opened
PR body: """ This PR allows to install ipa server using PY3 (CA, no DNS, no KRA, no CA-less, no external CA) and uninstall it (ipa-server-install --uninstall) Functionality depends on #427 """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/428/head:pr428 git checkout pr428
From 2f86d65d64bf3034d2fd91623f4b7c3bdfdc00be Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Tue, 24 Jan 2017 17:49:06 +0100 Subject: [PATCH 01/17] py3: base64 encoding/decoding returns always bytes don't mix it Using unicode(bytes) call causes undesired side effect that is inserting `b` character to result. This obviously causes issues with binary base64 data https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/plugins/baseldap.py | 4 ++-- ipaserver/plugins/ca.py | 2 +- ipaserver/plugins/cert.py | 2 +- ipaserver/secrets/client.py | 6 ++++-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/ipaserver/plugins/baseldap.py b/ipaserver/plugins/baseldap.py index e7bf43c..2f7889b 100644 --- a/ipaserver/plugins/baseldap.py +++ b/ipaserver/plugins/baseldap.py @@ -1036,8 +1036,8 @@ def process_attr_options(self, entry_attrs, dn, keys, options): except ValueError: if isinstance(delval, bytes): # This is a Binary value, base64 encode it - delval = unicode(base64.b64encode(delval)) - raise errors.AttrValueNotFound(attr=attr, value=delval) + delval = base64.b64encode(delval).decode('ascii') + raise errors.AttrValueNotFound(attr=attr, value=delval) # normalize all values changedattrs = setattrs | addattrs | delattrs diff --git a/ipaserver/plugins/ca.py b/ipaserver/plugins/ca.py index 4f24278..ac9f68e 100644 --- a/ipaserver/plugins/ca.py +++ b/ipaserver/plugins/ca.py @@ -176,7 +176,7 @@ def set_certificate_attrs(entry, options, want_cert=True): with api.Backend.ra_lightweight_ca as ca_api: if want_cert or full: der = ca_api.read_ca_cert(ca_id) - entry['certificate'] = six.text_type(base64.b64encode(der)) + entry['certificate'] = base64.b64encode(der).decode('ascii') if want_chain or full: pkcs7_der = ca_api.read_ca_chain(ca_id) diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py index 5bf4cfb..6bf5c03 100644 --- a/ipaserver/plugins/cert.py +++ b/ipaserver/plugins/cert.py @@ -1260,7 +1260,7 @@ def _get_cert_key(self, cert): return (DN(cert_obj.issuer), cert_obj.serial) def _get_cert_obj(self, cert, all, raw, pkey_only): - obj = {'certificate': unicode(base64.b64encode(cert))} + obj = {'certificate': base64.b64encode(cert).decode('ascii')} full = not pkey_only and all if not raw: diff --git a/ipaserver/secrets/client.py b/ipaserver/secrets/client.py index a04b9a6..a945e01 100644 --- a/ipaserver/secrets/client.py +++ b/ipaserver/secrets/client.py @@ -70,7 +70,8 @@ def init_creds(self): name = gssapi.Name(self.client_service, gssapi.NameType.hostbased_service) store = {'client_keytab': self.keytab, - 'ccache': 'MEMORY:Custodia_%s' % b64encode(os.urandom(8))} + 'ccache': 'MEMORY:Custodia_%s' % b64encode( + os.urandom(8)).decode('ascii')} return gssapi.Credentials(name=name, store=store, usage='initiate') def _auth_header(self): @@ -78,7 +79,8 @@ def _auth_header(self): self.creds = self.init_creds() ctx = gssapi.SecurityContext(name=self.service_name, creds=self.creds) authtok = ctx.step() - return {'Authorization': 'Negotiate %s' % b64encode(authtok)} + return {'Authorization': 'Negotiate %s' % b64encode( + authtok).decode('ascii')} def fetch_key(self, keyname, store=True): From df975b68875628940ce50c5470d34f30cc716762 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Tue, 24 Jan 2017 18:31:50 +0100 Subject: [PATCH 02/17] py3: base64.b64encode requires bytes as param Decimal must be changed to string first and then encoded to bytes https://fedorahosted.org/freeipa/ticket/4985 --- ipalib/rpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipalib/rpc.py b/ipalib/rpc.py index fb739f8..a3642a6 100644 --- a/ipalib/rpc.py +++ b/ipalib/rpc.py @@ -308,7 +308,7 @@ def json_encode_binary(val, version): encoded = encoded.decode('ascii') return {'__base64__': encoded} elif isinstance(val, Decimal): - return {'__base64__': base64.b64encode(str(val))} + return {'__base64__': base64.b64encode(str(val).encode('ascii'))} elif isinstance(val, DN): return str(val) elif isinstance(val, datetime.datetime): From 6669afc9ccec975607fbe0da597f81ed1f6dd64d Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Wed, 25 Jan 2017 14:56:07 +0100 Subject: [PATCH 03/17] py3: remove_entry_from_group: attribute name must be string Do not encode attribute names https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/plugins/ldap2.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py index 71c095d..e671ecb 100644 --- a/ipaserver/plugins/ldap2.py +++ b/ipaserver/plugins/ldap2.py @@ -442,7 +442,7 @@ def remove_entry_from_group(self, dn, group_dn, member_attr='member'): # update group entry try: with self.error_handler(): - modlist = [(a, self.encode(b), self.encode(c)) + modlist = [(a, b, self.encode(c)) for a, b, c in modlist] self.conn.modify_s(str(group_dn), modlist) except errors.MidairCollision: From d02b38e92b0e48e70cfa7bd810636e5fa4944f58 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Wed, 25 Jan 2017 15:38:03 +0100 Subject: [PATCH 04/17] py3: _ptrrecord_precallaback: use bytes with labels DNS labels are bytes so bytes must be used for comparison https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/plugins/dns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipaserver/plugins/dns.py b/ipaserver/plugins/dns.py index 08f9c6d..0838161 100644 --- a/ipaserver/plugins/dns.py +++ b/ipaserver/plugins/dns.py @@ -3098,7 +3098,7 @@ def _ptrrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options): # Classless zones (0/25.0.0.10.in-addr.arpa.) -> skip check # zone has to be checked without reverse domain suffix (in-addr.arpa.) - for sign in ('/', '-'): + for sign in (b'/', b'-'): for name in (zone, addr): for label in name.labels: if sign in label: From ce2f44b848b0109cc1abb6ae7ccfc3081c8c9d52 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Thu, 26 Jan 2017 10:25:46 +0100 Subject: [PATCH 05/17] py3: DNS: get_record_entry_attrs: do not modify dict during iteration In py3 keys() doesn't return list but iterator so it must be transformed to tuple otherwise iterator will be broken. https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/plugins/dns.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipaserver/plugins/dns.py b/ipaserver/plugins/dns.py index 0838161..97f6527 100644 --- a/ipaserver/plugins/dns.py +++ b/ipaserver/plugins/dns.py @@ -3195,7 +3195,7 @@ def get_dns_masters(self): def get_record_entry_attrs(self, entry_attrs): entry_attrs = entry_attrs.copy() - for attr in entry_attrs.keys(): + for attr in tuple(entry_attrs.keys()): if attr not in self.params or self.params[attr].primary_key: del entry_attrs[attr] return entry_attrs From ac1a38a1ef3f16e761a78c0449b2a6f7acfd5eff Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Fri, 27 Jan 2017 10:48:32 +0100 Subject: [PATCH 06/17] py3: entry_to_dict: input can be both bytes and unicode https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/plugins/baseldap.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ipaserver/plugins/baseldap.py b/ipaserver/plugins/baseldap.py index 2f7889b..803c478 100644 --- a/ipaserver/plugins/baseldap.py +++ b/ipaserver/plugins/baseldap.py @@ -255,7 +255,8 @@ def entry_to_dict(entry, **options): value = list(entry.raw[attr]) for (i, v) in enumerate(value): try: - value[i] = v.decode('utf-8') + if isinstance(v, bytes): + value[i] = v.decode('utf-8') except UnicodeDecodeError: pass result[attr] = value From f14a85426c9c5ab5e4198b900f03b3b05d81bb26 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Fri, 27 Jan 2017 12:06:54 +0100 Subject: [PATCH 07/17] py3: _convert_to_idna: fix bytes/unicode mistmatch ToASCII() returns bytes, it must be decoded to unicode https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/plugins/dns.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ipaserver/plugins/dns.py b/ipaserver/plugins/dns.py index 97f6527..40c9b51 100644 --- a/ipaserver/plugins/dns.py +++ b/ipaserver/plugins/dns.py @@ -1620,8 +1620,9 @@ def _convert_to_idna(value): idna_val = encodings.idna.nameprep(idna_val) idna_val = re.split(r'(?<!\\)\.', idna_val) idna_val = u'%s%s%s' % (start_dot, - u'.'.join(encodings.idna.ToASCII(x) - for x in idna_val), + u'.'.join( + encodings.idna.ToASCII(x).decode('ascii') + for x in idna_val), end_dot) return idna_val except Exception: From 4a7754a499297e8a072eb136ed89873ad751166b Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Fri, 27 Jan 2017 17:00:42 +0100 Subject: [PATCH 08/17] py3: modify_s: attribute nmae must be str not bytes https://fedorahosted.org/freeipa/ticket/4985 --- ipapython/ipaldap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py index 497b947..2b8bfec 100644 --- a/ipapython/ipaldap.py +++ b/ipapython/ipaldap.py @@ -727,7 +727,7 @@ def modify_s(self, dn, modlist): # FIXME: for backwards compatibility only assert isinstance(dn, DN) dn = str(dn) - modlist = [(a, self.encode(b), self.encode(c)) for a, b, c in modlist] + modlist = [(a, b, self.encode(c)) for a, b, c in modlist] return self.conn.modify_s(dn, modlist) @property From a44c979e6045b4452e2e2bd9bfe7870221d3fa01 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Fri, 27 Jan 2017 17:33:44 +0100 Subject: [PATCH 09/17] py3: configparser: use raw keyword configparser.get() changed in python3 and `raw` is now a keyword attribute. Also it must be set to True, otherwise InterpolationSyntaxError is raised ''' InterpolationSyntaxError: '%' must be followed by '%' or '(', found: '%2fvar%2frun%2fslapd-EXAMPLE-COM.socket' ''' https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/secrets/kem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipaserver/secrets/kem.py b/ipaserver/secrets/kem.py index 143caaf..3577975 100644 --- a/ipaserver/secrets/kem.py +++ b/ipaserver/secrets/kem.py @@ -181,7 +181,7 @@ def __init__(self, config=None, ipaconf=paths.IPA_DEFAULT_CONF): self.realm = conf.get('global', 'realm') self.ldap_uri = config.get('ldap_uri', None) if self.ldap_uri is None: - self.ldap_uri = conf.get('global', 'ldap_uri', None) + self.ldap_uri = conf.get('global', 'ldap_uri', raw=True) self._server_keys = None def find_key(self, kid, usage): From 27e5c044908bb8cfb85dd75098249b5a43363dd0 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Fri, 27 Jan 2017 18:10:37 +0100 Subject: [PATCH 10/17] py3: custodia: basedn must be unicode basedn in custodia related modules has type bytes, that causes issues in Py3 when strings were concatenated with bytes ``` malformed RDN string = "cn=custodia,cn=ipa,cn=etc,b'dc=example,dc=com'" ``` https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/secrets/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipaserver/secrets/common.py b/ipaserver/secrets/common.py index 2b906b6..f3dc320 100644 --- a/ipaserver/secrets/common.py +++ b/ipaserver/secrets/common.py @@ -23,7 +23,7 @@ def basedn(self): if self._basedn is None: conn = self.connect() r = conn.search_s('', ldap.SCOPE_BASE) - self._basedn = r[0][1]['defaultnamingcontext'][0] + self._basedn = r[0][1]['defaultnamingcontext'][0].decode('utf-8') return self._basedn def connect(self): From c97a0810936a62611e5216de7f4bb401a5cdb38e Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Tue, 31 Jan 2017 18:11:42 +0100 Subject: [PATCH 11/17] py3: kem.py: user bytes with ldap values python ldap requires bytes as values https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/secrets/kem.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ipaserver/secrets/kem.py b/ipaserver/secrets/kem.py index 3577975..5d784b7 100644 --- a/ipaserver/secrets/kem.py +++ b/ipaserver/secrets/kem.py @@ -130,13 +130,13 @@ def set_key(self, usage, principal, key): service_rdn = ('cn', servicename) if servicename != 'host' else DN() dn = str(DN(('cn', name), service_rdn, self.keysbase)) try: - mods = [('objectClass', ['nsContainer', - 'ipaKeyPolicy', - 'ipaPublicKeyObject', - 'groupOfPrincipals']), - ('cn', name), - ('ipaKeyUsage', RFC5280_USAGE_MAP[usage]), - ('memberPrincipal', principal), + mods = [('objectClass', [b'nsContainer', + b'ipaKeyPolicy', + b'ipaPublicKeyObject', + b'groupOfPrincipals']), + ('cn', name.encode('utf-8')), + ('ipaKeyUsage', RFC5280_USAGE_MAP[usage].encode('utf-8')), + ('memberPrincipal', principal.encode('utf-8')), ('ipaPublicKey', public_key)] conn.add_s(dn, mods) except Exception: # pylint: disable=broad-except From fb74dc50787595e3967012904741fd753981cf21 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Tue, 31 Jan 2017 18:14:33 +0100 Subject: [PATCH 12/17] custodia: kem.set_keys: replace too-broad exception Exception is too brod and may hide various issues that show up later. If the code expects that entry may exist, then ldap.ALREADY_EXISTS exception should be used --- ipaserver/secrets/kem.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ipaserver/secrets/kem.py b/ipaserver/secrets/kem.py index 5d784b7..28fb4d3 100644 --- a/ipaserver/secrets/kem.py +++ b/ipaserver/secrets/kem.py @@ -139,8 +139,7 @@ def set_key(self, usage, principal, key): ('memberPrincipal', principal.encode('utf-8')), ('ipaPublicKey', public_key)] conn.add_s(dn, mods) - except Exception: # pylint: disable=broad-except - # This may fail if the entry already exists + except ldap.ALREADY_EXISTS: mods = [(ldap.MOD_REPLACE, 'ipaPublicKey', public_key)] conn.modify_s(dn, mods) From 015ab52f5a5ba75f8b9dc23a6268a988b86c4418 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Tue, 31 Jan 2017 18:36:24 +0100 Subject: [PATCH 13/17] py3: upgradeinstance: open dse.ldif in textual mode ldap ldif parser requires to have input file opened in textual mode https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/install/upgradeinstance.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ipaserver/install/upgradeinstance.py b/ipaserver/install/upgradeinstance.py index 8e28436..b244898 100644 --- a/ipaserver/install/upgradeinstance.py +++ b/ipaserver/install/upgradeinstance.py @@ -124,7 +124,7 @@ def create_instance(self): def __save_config(self): shutil.copy2(self.filename, self.savefilename) - with open(self.filename, "rb") as in_file: + with open(self.filename, "r") as in_file: parser = GetEntryFromLDIF(in_file, entries_dn=["cn=config"]) parser.parse() try: @@ -156,8 +156,8 @@ def __save_config(self): def __enable_ds_global_write_lock(self): ldif_outfile = "%s.modified.out" % self.filename - with open(ldif_outfile, "wb") as out_file: - with open(self.filename, "rb") as in_file: + with open(ldif_outfile, "w") as out_file: + with open(self.filename, "r") as in_file: parser = installutils.ModifyLDIF(in_file, out_file) parser.replace_value( @@ -172,8 +172,8 @@ def __restore_config(self): global_lock = self.restore_state('nsslapd-global-backend-lock') ldif_outfile = "%s.modified.out" % self.filename - with open(ldif_outfile, "wb") as out_file: - with open(self.filename, "rb") as in_file: + with open(ldif_outfile, "w") as out_file: + with open(self.filename, "r") as in_file: parser = installutils.ModifyLDIF(in_file, out_file) if port is not None: @@ -194,8 +194,8 @@ def __restore_config(self): def __disable_listeners(self): ldif_outfile = "%s.modified.out" % self.filename - with open(ldif_outfile, "wb") as out_file: - with open(self.filename, "rb") as in_file: + with open(ldif_outfile, "w") as out_file: + with open(self.filename, "r") as in_file: parser = installutils.ModifyLDIF(in_file, out_file) parser.replace_value("cn=config", "nsslapd-port", ["0"]) parser.replace_value("cn=config", "nsslapd-security", ["off"]) From b94dddf7086a08f5ae7cadc14131bc4fe88fbd50 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Tue, 31 Jan 2017 18:53:47 +0100 Subject: [PATCH 14/17] py3: upgradeinstance: decode data before storing them as backup... ...and vice versa backup requires string not bytes, but ldap provide bytes thus data must be decoded and encoded from restore https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/install/upgradeinstance.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ipaserver/install/upgradeinstance.py b/ipaserver/install/upgradeinstance.py index b244898..8e6c87d 100644 --- a/ipaserver/install/upgradeinstance.py +++ b/ipaserver/install/upgradeinstance.py @@ -134,21 +134,22 @@ def __save_config(self): self.filename) try: - port = config_entry['nsslapd-port'][0] + port = config_entry['nsslapd-port'][0].decode('utf-8') except KeyError: pass else: self.backup_state('nsslapd-port', port) try: - security = config_entry['nsslapd-security'][0] + security = config_entry['nsslapd-security'][0].decode('utf-8') except KeyError: pass else: self.backup_state('nsslapd-security', security) try: - global_lock = config_entry['nsslapd-global-backend-lock'][0] + global_lock = config_entry[ + 'nsslapd-global-backend-lock'][0].decode('utf-8') except KeyError: pass else: @@ -177,16 +178,17 @@ def __restore_config(self): parser = installutils.ModifyLDIF(in_file, out_file) if port is not None: - parser.replace_value("cn=config", "nsslapd-port", [port]) + parser.replace_value( + "cn=config", "nsslapd-port", [port.encode('utf-8')]) if security is not None: parser.replace_value("cn=config", "nsslapd-security", - [security]) + [security.encode('utf-8')]) # disable global lock by default parser.remove_value("cn=config", "nsslapd-global-backend-lock") if global_lock is not None: parser.add_value("cn=config", "nsslapd-global-backend-lock", - [global_lock]) + [global_lock.encode('utf-8')]) parser.parse() From 3bd4cee6eeaf5db1a1ac108d162fd6529cce3832 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Tue, 31 Jan 2017 19:23:39 +0100 Subject: [PATCH 15/17] py3: upgradeinstance: use bytes literals with LDIF operations python ldif support only bytes as values, literals must be bytes https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/install/upgradeinstance.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ipaserver/install/upgradeinstance.py b/ipaserver/install/upgradeinstance.py index 8e6c87d..fca4226 100644 --- a/ipaserver/install/upgradeinstance.py +++ b/ipaserver/install/upgradeinstance.py @@ -162,7 +162,7 @@ def __enable_ds_global_write_lock(self): parser = installutils.ModifyLDIF(in_file, out_file) parser.replace_value( - "cn=config", "nsslapd-global-backend-lock", ["on"]) + "cn=config", "nsslapd-global-backend-lock", [b"on"]) parser.parse() shutil.copy2(ldif_outfile, self.filename) @@ -199,8 +199,8 @@ def __disable_listeners(self): with open(ldif_outfile, "w") as out_file: with open(self.filename, "r") as in_file: parser = installutils.ModifyLDIF(in_file, out_file) - parser.replace_value("cn=config", "nsslapd-port", ["0"]) - parser.replace_value("cn=config", "nsslapd-security", ["off"]) + parser.replace_value("cn=config", "nsslapd-port", [b"0"]) + parser.replace_value("cn=config", "nsslapd-security", [b"off"]) parser.remove_value("cn=config", "nsslapd-ldapientrysearchbase") parser.parse() From 841e14477f72e428631b5e6114764f0801a90102 Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Tue, 31 Jan 2017 19:59:31 +0100 Subject: [PATCH 16/17] py3: create DNS zonefile: use textual mode Also code was rewritten to use NamedTemporaryFile with context https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/install/bindinstance.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py index e24249a..10a37b9 100644 --- a/ipaserver/install/bindinstance.py +++ b/ipaserver/install/bindinstance.py @@ -668,10 +668,13 @@ def create_file_with_system_records(self): system_records.get_base_records() ) ) - [fd, name] = tempfile.mkstemp(".db","ipa.system.records.") - os.write(fd, text) - os.close(fd) - print("Please add records in this file to your DNS system:", name) + with tempfile.NamedTemporaryFile( + mode="w", prefix="ipa.system.records.", + suffix=".db", delete=False + ) as f: + f.write(text) + print("Please add records in this file to your DNS system:", + f.name) def create_instance(self): From 0769eeef325b1777257bf5fa86b3d8d6a0daafbd Mon Sep 17 00:00:00 2001 From: Martin Basti <mba...@redhat.com> Date: Tue, 31 Jan 2017 20:27:11 +0100 Subject: [PATCH 17/17] py3: change_admin_password: use textual mode Convert function to NamedTemporaryFile with textual mode, because passwords are text. Using `with` and NamedTemporaryFile gives more security agains leaking password from tempfiles. https://fedorahosted.org/freeipa/ticket/4985 --- ipaserver/install/dsinstance.py | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index ceb7bf3..ceb3693 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -951,21 +951,19 @@ def add_hbac(self): def change_admin_password(self, password): root_logger.debug("Changing admin password") - dmpwdfile = "" - admpwdfile = "" - try: - (dmpwdfd, dmpwdfile) = tempfile.mkstemp(dir=paths.VAR_LIB_IPA) - os.write(dmpwdfd, self.dm_password) - os.close(dmpwdfd) + NTF = tempfile.NamedTemporaryFile + dir = paths.VAR_LIB_IPA + with NTF("w", dir=dir) as dmpwdfile, NTF("w", dir=dir) as admpwdfile: + dmpwdfile.write(self.dm_password) + dmpwdfile.flush() - (admpwdfd, admpwdfile) = tempfile.mkstemp(dir=paths.VAR_LIB_IPA) - os.write(admpwdfd, password) - os.close(admpwdfd) + admpwdfile.write(password) + admpwdfile.flush() args = [paths.LDAPPASSWD, "-h", self.fqdn, "-ZZ", "-x", "-D", str(DN(('cn', 'Directory Manager'))), - "-y", dmpwdfile, "-T", admpwdfile, + "-y", dmpwdfile.name, "-T", admpwdfile.name, str(DN(('uid', 'admin'), ('cn', 'users'), ('cn', 'accounts'), self.suffix))] try: env = {'LDAPTLS_CACERTDIR': os.path.dirname(paths.IPA_CA_CRT), @@ -976,12 +974,6 @@ def change_admin_password(self, password): print("Unable to set admin password", e) root_logger.debug("Unable to set admin password %s" % e) - finally: - if os.path.isfile(dmpwdfile): - os.remove(dmpwdfile) - if os.path.isfile(admpwdfile): - os.remove(admpwdfile) - def uninstall(self): if self.is_configured(): self.print_msg("Unconfiguring directory server")
-- Manage your subscription for the Freeipa-devel mailing list: https://www.redhat.com/mailman/listinfo/freeipa-devel Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code