diff --git a/.gitignore b/.gitignore index bcfe5f9..e66632a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -SOURCES/freeipa-4.2.0.tar.gz +SOURCES/freeipa-4.4.0.tar.gz SOURCES/header-logo.png SOURCES/login-screen-background.jpg SOURCES/login-screen-logo.png diff --git a/.ipa.metadata b/.ipa.metadata index 3f16db3..97596a6 100644 --- a/.ipa.metadata +++ b/.ipa.metadata @@ -1,4 +1,4 @@ -40a1587de7d78f4e01bfb3775ab3f4e264c56e4c SOURCES/freeipa-4.2.0.tar.gz +441ef8cb2b0ac103723d03b0478da641d697e104 SOURCES/freeipa-4.4.0.tar.gz 77c318cf1f4fc25cf847de0692a77859a767c0e3 SOURCES/header-logo.png 8727245558422bf966d60677568925f081b8e299 SOURCES/login-screen-background.jpg 24a29d79efbd0906777be4639957abda111fca4b SOURCES/login-screen-logo.png diff --git a/SOURCES/0001-Fix-incorrect-check-for-principal-type-when-evaluati.patch b/SOURCES/0001-Fix-incorrect-check-for-principal-type-when-evaluati.patch new file mode 100644 index 0000000..46921fd --- /dev/null +++ b/SOURCES/0001-Fix-incorrect-check-for-principal-type-when-evaluati.patch @@ -0,0 +1,34 @@ +From 808772d7426dae6924c62ca327116c3152729a8e Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Fri, 1 Jul 2016 11:55:47 +0200 +Subject: [PATCH] Fix incorrect check for principal type when evaluating CA + ACLs + +This error prevented hosts to request certificates for themselves. + +https://fedorahosted.org/freeipa/ticket/3864 + +Reviewed-By: Petr Spacek +--- + ipaserver/plugins/caacl.py | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/ipaserver/plugins/caacl.py b/ipaserver/plugins/caacl.py +index 3f813a7efb9e554abcb8dd2946eea73065c93414..9a60f7e27809c4f41b160647efafde94dbe90bf0 100644 +--- a/ipaserver/plugins/caacl.py ++++ b/ipaserver/plugins/caacl.py +@@ -64,8 +64,10 @@ def _acl_make_request(principal_type, principal, ca_id, profile_id): + req = pyhbac.HbacRequest() + req.targethost.name = ca_id + req.service.name = profile_id +- if principal_type == 'user' or principal_type == 'host': ++ if principal_type == 'user': + req.user.name = principal.username ++ elif principal_type == 'host': ++ req.user.name = principal.hostname + elif principal_type == 'service': + req.user.name = unicode(principal) + groups = [] +-- +2.9.0 + diff --git a/SOURCES/0001-Start-dirsrv-for-kdcproxy-upgrade.patch b/SOURCES/0001-Start-dirsrv-for-kdcproxy-upgrade.patch deleted file mode 100644 index 305ea1a..0000000 --- a/SOURCES/0001-Start-dirsrv-for-kdcproxy-upgrade.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 5e1ff6ef5fa35715a5b9995388c6d7b16375ac23 Mon Sep 17 00:00:00 2001 -From: Christian Heimes -Date: Fri, 10 Jul 2015 18:18:29 +0200 -Subject: [PATCH] Start dirsrv for kdcproxy upgrade - -The kdcproxy upgrade step in ipa-server-upgrade needs a running dirsrv -instance. Under some circumstances the dirsrv isn't running. The patch -rearranges some upgrade steps and starts DS before enable_kdcproxy(). - -https://fedorahosted.org/freeipa/ticket/5113 - -Reviewed-By: Martin Basti ---- - ipaserver/install/server/upgrade.py | 35 +++++++++++++++++++---------------- - 1 file changed, 19 insertions(+), 16 deletions(-) - -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index 84a5b06accb10663eaa4d995f66796366040e9c8..f295655dc2aa592e0215f15017c9b65af49eef80 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -1396,22 +1396,6 @@ def upgrade_configuration(): - http.change_mod_nss_port_from_http() - http.configure_certmonger_renewal_guard() - -- if not http.is_kdcproxy_configured(): -- root_logger.info('[Enabling KDC Proxy]') -- if http.admin_conn is None: -- http.ldapi = True -- http.fqdn = fqdn -- http.realm = api.env.realm -- http.suffix = ipautil.realm_to_suffix(api.env.realm) -- http.ldap_connect() -- http.create_kdcproxy_conf() -- http.enable_kdcproxy() -- -- http.stop() -- update_mod_nss_protocol(http) -- fix_trust_flags() -- http.start() -- - ds = dsinstance.DsInstance() - ds.configure_dirsrv_ccache() - -@@ -1433,6 +1417,25 @@ def upgrade_configuration(): - ds.suffix = ipautil.realm_to_suffix(api.env.realm) - ds_enable_sidgen_extdom_plugins(ds) - -+ # Now 389-ds is available, run the remaining http tasks -+ if not http.is_kdcproxy_configured(): -+ root_logger.info('[Enabling KDC Proxy]') -+ if http.admin_conn is None: -+ # 389-ds needs to be running -+ ds.start() -+ http.ldapi = True -+ http.fqdn = fqdn -+ http.realm = api.env.realm -+ http.suffix = ipautil.realm_to_suffix(api.env.realm) -+ http.ldap_connect() -+ http.create_kdcproxy_conf() -+ http.enable_kdcproxy() -+ -+ http.stop() -+ update_mod_nss_protocol(http) -+ fix_trust_flags() -+ http.start() -+ - uninstall_selfsign(ds, http) - - simple_service_list = ( --- -2.1.0 - diff --git a/SOURCES/0002-Fix-DNS-records-installation-for-replicas.patch b/SOURCES/0002-Fix-DNS-records-installation-for-replicas.patch deleted file mode 100644 index 1fa91fa..0000000 --- a/SOURCES/0002-Fix-DNS-records-installation-for-replicas.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 8610ddbee7025286881c1b470e13f0a5ff6a4452 Mon Sep 17 00:00:00 2001 -From: Simo Sorce -Date: Fri, 10 Jul 2015 12:58:19 -0400 -Subject: [PATCH] Fix DNS records installation for replicas - -Ticket: https:/fedorahosted.org/freeipa/ticket/5116 - -Signed-off-by: Simo Sorce -Reviewed-By: Martin Basti ---- - ipaserver/install/server/replicainstall.py | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py -index a78eeb331c1f3f4f2233abb9e65bdde79eee4000..1ad291a1eada080361031a5723a0ea61679fc72e 100644 ---- a/ipaserver/install/server/replicainstall.py -+++ b/ipaserver/install/server/replicainstall.py -@@ -503,9 +503,9 @@ def install_check(installer): - if options.setup_dns: - dns.install_check(False, True, options, config.host_name) - else: -- installutils.get_server_ip_address(config.host_name, fstore, -- not installer.interactive, False, -- options.ip_addresses) -+ config.ips = installutils.get_server_ip_address( -+ config.host_name, fstore, not installer.interactive, False, -+ options.ip_addresses) - - # check connection - if not options.skip_conncheck: --- -2.1.0 - diff --git a/SOURCES/0002-uninstall-untrack-lightweight-CA-certs.patch b/SOURCES/0002-uninstall-untrack-lightweight-CA-certs.patch new file mode 100644 index 0000000..21fa9ec --- /dev/null +++ b/SOURCES/0002-uninstall-untrack-lightweight-CA-certs.patch @@ -0,0 +1,31 @@ +From 8235b85d6960356fd49affca40b1b609f3cae827 Mon Sep 17 00:00:00 2001 +From: Fraser Tweedale +Date: Mon, 4 Jul 2016 13:05:28 +1000 +Subject: [PATCH] uninstall: untrack lightweight CA certs + +Fixes: https://fedorahosted.org/freeipa/ticket/6020 +Reviewed-By: Martin Babinsky +--- + ipaserver/install/cainstance.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py +index 5e3e8c7f9a1845b82d23de589f804aa065387b38..070498fe8a394802ea55f848a268e2b6563ec472 100644 +--- a/ipaserver/install/cainstance.py ++++ b/ipaserver/install/cainstance.py +@@ -1127,6 +1127,12 @@ class CAInstance(DogtagInstance): + """ + super(CAInstance, self).stop_tracking_certificates(False) + ++ # stop tracking lightweight CA signing certs ++ for request_id in certmonger.get_requests_for_dir(self.nss_db): ++ nickname = certmonger.get_request_value(request_id, 'key-nickname') ++ if nickname.startswith('caSigningCert cert-pki-ca '): ++ certmonger.stop_tracking(self.nss_db, nickname=nickname) ++ + try: + certmonger.stop_tracking(paths.HTTPD_ALIAS_DIR, nickname='ipaCert') + except RuntimeError as e: +-- +2.4.3 + diff --git a/SOURCES/0003-Prevent-to-rename-certprofile-profile-id.patch b/SOURCES/0003-Prevent-to-rename-certprofile-profile-id.patch deleted file mode 100644 index 5127951..0000000 --- a/SOURCES/0003-Prevent-to-rename-certprofile-profile-id.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 51f03f45f6cdab9da0479f48093951ccdd7cdab0 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Thu, 9 Jul 2015 17:17:21 +0200 -Subject: [PATCH] Prevent to rename certprofile profile id - -https://fedorahosted.org/freeipa/ticket/5074 - -Reviewed-By: Jan Cholasta ---- - ipalib/plugins/certprofile.py | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/ipalib/plugins/certprofile.py b/ipalib/plugins/certprofile.py -index 6f9a41875b2a276b521219156e630817a9c41fdc..5550ed942521dbab2e783fba1570520268f9b378 100644 ---- a/ipalib/plugins/certprofile.py -+++ b/ipalib/plugins/certprofile.py -@@ -291,6 +291,9 @@ class certprofile_mod(LDAPUpdate): - - def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): - ca_enabled_check() -+ # Once a profile id is set it cannot be changed -+ if 'cn' in entry_attrs: -+ raise errors.ACIError(info=_('cn is immutable')) - if 'file' in options: - with self.api.Backend.ra_certprofile as profile_api: - profile_api.disable_profile(keys[0]) --- -2.1.0 - diff --git a/SOURCES/0003-ipa-nis-manage-Use-server-API-to-retrieve-plugin-sta.patch b/SOURCES/0003-ipa-nis-manage-Use-server-API-to-retrieve-plugin-sta.patch new file mode 100644 index 0000000..b0e8ae3 --- /dev/null +++ b/SOURCES/0003-ipa-nis-manage-Use-server-API-to-retrieve-plugin-sta.patch @@ -0,0 +1,28 @@ +From db7950c119f71df018ae1759933c0a8dca1072df Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Mon, 4 Jul 2016 13:33:10 +0200 +Subject: [PATCH] ipa-nis-manage: Use server API to retrieve plugin status + +https://fedorahosted.org/freeipa/ticket/6027 + +Reviewed-By: Florence Blanc-Renaud +--- + install/tools/ipa-nis-manage | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/install/tools/ipa-nis-manage b/install/tools/ipa-nis-manage +index f70961309c34e48ea1b4c1b144c9c0df5860f667..64de9e848ff7c382ddaea0729352da2584be6031 100755 +--- a/install/tools/ipa-nis-manage ++++ b/install/tools/ipa-nis-manage +@@ -116,7 +116,7 @@ def main(): + if not dirman_password: + sys.exit("No password supplied") + +- api.bootstrap(context='cli', debug=options.debug) ++ api.bootstrap(context='cli', debug=options.debug, in_server=True) + api.finalize() + + conn = None +-- +2.4.3 + diff --git a/SOURCES/0004-Stageusedr-activate-show-username-instead-of-DN.patch b/SOURCES/0004-Stageusedr-activate-show-username-instead-of-DN.patch deleted file mode 100644 index 4d29df8..0000000 --- a/SOURCES/0004-Stageusedr-activate-show-username-instead-of-DN.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 5fb2c0f8c7237214f870d341cc10a2ccda48d117 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Fri, 10 Jul 2015 14:47:59 +0200 -Subject: [PATCH] Stageusedr-activate: show username instead of DN - -If activate user already exists, show name of this user in error message -instead of user DN. -Error message reworder to keep the same format as stageuser-add, -user-add. - -https://fedorahosted.org/freeipa/ticket/5038 - -Reviewed-By: David Kupka ---- - ipalib/plugins/stageuser.py | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/ipalib/plugins/stageuser.py b/ipalib/plugins/stageuser.py -index 35e636ded4474b00ad635c60340aaf66e6b41752..6cbc8f4ab07f2c1172f2b2c45bfe8f30a74938b3 100644 ---- a/ipalib/plugins/stageuser.py -+++ b/ipalib/plugins/stageuser.py -@@ -682,8 +682,9 @@ class stageuser_activate(LDAPQuery): - active_dn, ['dn'] - ) - assert isinstance(staging_dn, DN) -- raise errors.DuplicateEntry(message=_('Active user %(user)s already exists') % dict( -- user=test_entry_attrs.dn)) -+ raise errors.DuplicateEntry( -+ message=_('active user with name "%(user)s" already exists') % -+ dict(user=args[-1])) - except errors.NotFound: - pass - --- -2.1.0 - diff --git a/SOURCES/0004-ipa-compat-manage-use-server-API-to-retrieve-plugin-.patch b/SOURCES/0004-ipa-compat-manage-use-server-API-to-retrieve-plugin-.patch new file mode 100644 index 0000000..a74f4d0 --- /dev/null +++ b/SOURCES/0004-ipa-compat-manage-use-server-API-to-retrieve-plugin-.patch @@ -0,0 +1,28 @@ +From 5d699a0bff0c42220d68fac54d08fbcdd2daae67 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Mon, 11 Jul 2016 10:46:34 +0200 +Subject: [PATCH] ipa-compat-manage: use server API to retrieve plugin status + +https://fedorahosted.org/freeipa/ticket/6033 + +Reviewed-By: Stanislav Laznicka +--- + install/tools/ipa-compat-manage | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/install/tools/ipa-compat-manage b/install/tools/ipa-compat-manage +index 2b13c4a68531c7b6261465399b59225db094aba2..178cef9792c703f868fa3639a3a570b963dc7ed6 100755 +--- a/install/tools/ipa-compat-manage ++++ b/install/tools/ipa-compat-manage +@@ -103,7 +103,7 @@ def main(): + if dirman_password is None: + sys.exit("Directory Manager password required") + +- api.bootstrap(context='cli', debug=options.debug) ++ api.bootstrap(context='cli', in_server=True, debug=options.debug) + api.finalize() + + conn = None +-- +2.4.3 + diff --git a/SOURCES/0005-copy-schema-to-ca-allow-to-overwrite-schema-files.patch b/SOURCES/0005-copy-schema-to-ca-allow-to-overwrite-schema-files.patch deleted file mode 100644 index 2181d76..0000000 --- a/SOURCES/0005-copy-schema-to-ca-allow-to-overwrite-schema-files.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 7919e3c6b245adb0f6d6743edaf03da704259b5d Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Fri, 10 Jul 2015 14:17:02 +0200 -Subject: [PATCH] copy-schema-to-ca: allow to overwrite schema files - -If content of source and target file differs, the script will ask user -for permission to overwrite target file. - -https://fedorahosted.org/freeipa/ticket/5034 - -Reviewed-By: David Kupka ---- - install/share/copy-schema-to-ca.py | 29 ++++++++++++++++++++++++++--- - 1 file changed, 26 insertions(+), 3 deletions(-) - -diff --git a/install/share/copy-schema-to-ca.py b/install/share/copy-schema-to-ca.py -index 1614e11636c2f52e231ea2ff40d882209194c60a..ff6c3568586f9f4b3fac7f848869e74d0db0df34 100755 ---- a/install/share/copy-schema-to-ca.py -+++ b/install/share/copy-schema-to-ca.py -@@ -15,6 +15,8 @@ import sys - import pwd - import shutil - -+from hashlib import sha1 -+ - from ipapython import ipautil, dogtag - from ipapython.ipa_log_manager import root_logger, standard_logging_setup - from ipaserver.install.dsinstance import DS_USER, schema_dirname -@@ -42,6 +44,11 @@ SCHEMA_FILENAMES = ( - ) - - -+def _sha1_file(filename): -+ with open(filename, 'rb') as f: -+ return sha1(f.read()).hexdigest() -+ -+ - def add_ca_schema(): - """Copy IPA schema files into the CA DS instance - """ -@@ -54,9 +61,25 @@ def add_ca_schema(): - root_logger.debug('File does not exist: %s', source_fname) - continue - if os.path.exists(target_fname): -- root_logger.info( -- 'Target exists, not overwriting: %s', target_fname) -- continue -+ target_sha1 = _sha1_file(target_fname) -+ source_sha1 = _sha1_file(source_fname) -+ if target_sha1 != source_sha1: -+ target_size = os.stat(target_fname).st_size -+ source_size = os.stat(source_fname).st_size -+ root_logger.info('Target file %s exists but the content is ' -+ 'different', target_fname) -+ root_logger.info('\tTarget file: sha1: %s, size: %s B', -+ target_sha1, target_size) -+ root_logger.info('\tSource file: sha1: %s, size: %s B', -+ source_sha1, source_size) -+ if not ipautil.user_input("Do you want replace %s file?" % -+ target_fname, True): -+ continue -+ -+ else: -+ root_logger.info( -+ 'Target exists, not overwriting: %s', target_fname) -+ continue - try: - shutil.copyfile(source_fname, target_fname) - except IOError, e: --- -2.1.0 - diff --git a/SOURCES/0005-ipa-advise-correct-handling-of-plugin-namespace-iter.patch b/SOURCES/0005-ipa-advise-correct-handling-of-plugin-namespace-iter.patch new file mode 100644 index 0000000..e55904e --- /dev/null +++ b/SOURCES/0005-ipa-advise-correct-handling-of-plugin-namespace-iter.patch @@ -0,0 +1,40 @@ +From c4d5331ec5361a5f607eca7bb576d5d387bf3824 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Mon, 11 Jul 2016 14:03:36 +0200 +Subject: [PATCH] ipa-advise: correct handling of plugin namespace iteration + +The API object namespace iterators now yield plugin classes themselves +instead of their names as strings. The method enumerating through available +plugins needs to be made aware of this change. + +https://fedorahosted.org/freeipa/ticket/6044 + +Reviewed-By: Stanislav Laznicka +--- + ipaserver/advise/base.py | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/ipaserver/advise/base.py b/ipaserver/advise/base.py +index d083a3c506074f0adbb49e7a6d9935b8d338e941..a2dc9ccee93811da415c1e1eb0b57f47ac817a3f 100644 +--- a/ipaserver/advise/base.py ++++ b/ipaserver/advise/base.py +@@ -167,12 +167,12 @@ class IpaAdvise(admintool.AdminTool): + def print_config_list(self): + self.print_header('List of available advices') + +- max_keyword_len = max((len(keyword) for keyword in advise_api.Advice)) ++ max_keyword_len = max( ++ (len(advice.__name__) for advice in advise_api.Advice)) + +- for keyword in advise_api.Advice: +- advice = getattr(advise_api.Advice, keyword, '') ++ for advice in advise_api.Advice: + description = getattr(advice, 'description', '') +- keyword = keyword.replace('_', '-') ++ keyword = advice.__name__.replace('_', '-') + + # Compute the number of spaces needed for the table to be aligned + offset = max_keyword_len - len(keyword) +-- +2.4.3 + diff --git a/SOURCES/0006-kdb-check-for-local-realm-in-enterprise-principals.patch b/SOURCES/0006-kdb-check-for-local-realm-in-enterprise-principals.patch new file mode 100644 index 0000000..fd02aa9 --- /dev/null +++ b/SOURCES/0006-kdb-check-for-local-realm-in-enterprise-principals.patch @@ -0,0 +1,89 @@ +From ed178aad6751ea7673d8e730bd5a6709921a1ff0 Mon Sep 17 00:00:00 2001 +From: Sumit Bose +Date: Wed, 6 Jul 2016 17:29:37 +0200 +Subject: [PATCH] kdb: check for local realm in enterprise principals + +Reviewed-By: Martin Babinsky +Reviewed-By: Jakub Hrozek +--- + daemons/ipa-kdb/ipa_kdb_principals.c | 52 +++++++++++++++++++++++++++--------- + 1 file changed, 40 insertions(+), 12 deletions(-) + +diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c +index 6cdfa909452a4b55912b2a5a74648abd2053482a..5b80909475565d6bb4fa8cba67629094daf51eb3 100644 +--- a/daemons/ipa-kdb/ipa_kdb_principals.c ++++ b/daemons/ipa-kdb/ipa_kdb_principals.c +@@ -1198,30 +1198,58 @@ krb5_error_code ipadb_get_principal(krb5_context kcontext, + /* skip '@' and use part after '@' as an enterprise realm for comparison */ + realm++; + +- kerr = ipadb_is_princ_from_trusted_realm(kcontext, +- realm, +- upn->length - (realm - upn->data), +- &trusted_realm); +- if (kerr == 0) { +- kentry = calloc(1, sizeof(krb5_db_entry)); +- if (!kentry) { ++ /* check for our realm */ ++ if (strncasecmp(ipactx->realm, realm, ++ upn->length - (realm - upn->data)) == 0) { ++ /* it looks like it is ok to use malloc'ed strings as principal */ ++ krb5_free_unparsed_name(kcontext, principal); ++ principal = strndup((const char *) upn->data, upn->length); ++ if (principal == NULL) { + kerr = ENOMEM; + goto done; + } +- kerr = krb5_parse_name(kcontext, principal, +- &kentry->princ); ++ ++ ldap_msgfree(res); ++ res = NULL; ++ kerr = ipadb_fetch_principals(ipactx, flags, principal, &res); + if (kerr != 0) { + goto done; + } + +- kerr = krb5_set_principal_realm(kcontext, kentry->princ, trusted_realm); ++ kerr = ipadb_find_principal(kcontext, flags, res, &principal, ++ &lentry); + if (kerr != 0) { + goto done; + } +- *entry = kentry; ++ } else { ++ ++ kerr = ipadb_is_princ_from_trusted_realm(kcontext, ++ realm, ++ upn->length - (realm - upn->data), ++ &trusted_realm); ++ if (kerr == 0) { ++ kentry = calloc(1, sizeof(krb5_db_entry)); ++ if (!kentry) { ++ kerr = ENOMEM; ++ goto done; ++ } ++ kerr = krb5_parse_name(kcontext, principal, ++ &kentry->princ); ++ if (kerr != 0) { ++ goto done; ++ } ++ ++ kerr = krb5_set_principal_realm(kcontext, kentry->princ, trusted_realm); ++ if (kerr != 0) { ++ goto done; ++ } ++ *entry = kentry; ++ } ++ goto done; + } ++ } else { ++ goto done; + } +- goto done; + } + + kerr = ipadb_parse_ldap_entry(kcontext, principal, lentry, entry, &pol); +-- +2.4.3 + diff --git a/SOURCES/0006-spec-file-Update-minimum-required-version-of-krb5.patch b/SOURCES/0006-spec-file-Update-minimum-required-version-of-krb5.patch deleted file mode 100644 index 8bf286e..0000000 --- a/SOURCES/0006-spec-file-Update-minimum-required-version-of-krb5.patch +++ /dev/null @@ -1,48 +0,0 @@ -From 6bc5c6e1d7af6229e8c6f547951b0b3314ca5f12 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Wed, 15 Jul 2015 08:45:53 +0000 -Subject: [PATCH] spec file: Update minimum required version of krb5 - -Automatically require the krb5 version used at build time. - -https://fedorahosted.org/freeipa/ticket/5132 - -Reviewed-By: Alexander Bokovoy ---- - freeipa.spec.in | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/freeipa.spec.in b/freeipa.spec.in -index e78ad1a0851186c7fdb5ab0a4649b64b2b1e010f..a819710b2bad16a5c17b77670cdb29cb4b09ad8f 100644 ---- a/freeipa.spec.in -+++ b/freeipa.spec.in -@@ -11,6 +11,8 @@ - %global selinux_policy_version 3.12.1-179 - %endif - -+%define krb5_base_version %(LC_ALL=C rpm -q --qf '%%{VERSION}' krb5-devel | grep -Eo '^[^.]+\.[^.]+') -+ - %global plugin_dir %{_libdir}/dirsrv/plugins - %global etc_systemd_dir %{_sysconfdir}/systemd/system - %global gettext_domain ipa -@@ -52,7 +54,7 @@ BuildRequires: nspr-devel - BuildRequires: nss-devel - BuildRequires: openssl-devel - BuildRequires: openldap-devel --BuildRequires: krb5-devel >= 1.11 -+BuildRequires: krb5-devel >= 1.13 - BuildRequires: krb5-workstation - BuildRequires: libuuid-devel - BuildRequires: libcurl-devel >= 7.21.7-2 -@@ -119,7 +121,7 @@ Requires: 389-ds-base >= 1.3.4.0 - Requires: openldap-clients > 2.4.35-4 - Requires: nss >= 3.14.3-12.0 - Requires: nss-tools >= 3.14.3-12.0 --Requires: krb5-server >= 1.11.5-5 -+Requires(post): krb5-server >= %{krb5_base_version}, krb5-server < %{krb5_base_version}.100 - Requires: krb5-pkinit-openssl - Requires: cyrus-sasl-gssapi%{?_isa} - Requires: ntp --- -2.1.0 - diff --git a/SOURCES/0007-Enable-vault-commands-on-client.patch b/SOURCES/0007-Enable-vault-commands-on-client.patch new file mode 100644 index 0000000..59fd755 --- /dev/null +++ b/SOURCES/0007-Enable-vault-commands-on-client.patch @@ -0,0 +1,70 @@ +From 0d3f6f147382625fc326a6f84bb6a950dd4386b1 Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Fri, 8 Jul 2016 15:53:25 +0200 +Subject: [PATCH] Enable vault-* commands on client + +Client plugins fot vault commands were disabled by NO_CLI=True, +inherited from vault_add_interal, that is always NO_CLI=True. +Introduced by this commit 8278da6967dbe425b4e0c6cf37dc1c53052525b2 + +Removed NO_CLI=True from client side plugins for vault. + +https://fedorahosted.org/freeipa/ticket/6035 + +Reviewed-By: Martin Babinsky +Reviewed-By: Alexander Bokovoy +--- + ipaclient/plugins/vault.py | 16 ---------------- + 1 file changed, 16 deletions(-) + +diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py +index 11210d6e1339f42598b39bcf599d3e6eacb5b9d8..bf0242fc4290bb94f29faf9c787dd7454a8921bf 100644 +--- a/ipaclient/plugins/vault.py ++++ b/ipaclient/plugins/vault.py +@@ -202,10 +202,6 @@ class vault_add(Local): + ), + ) + +- @property +- def NO_CLI(self): +- return self.api.Command.vault_add_internal.NO_CLI +- + def get_args(self): + for arg in self.api.Command.vault_add_internal.args(): + yield arg +@@ -394,10 +390,6 @@ class vault_mod(Local): + ), + ) + +- @property +- def NO_CLI(self): +- return self.api.Command.vault_mod_internal.NO_CLI +- + def get_args(self): + for arg in self.api.Command.vault_mod_internal.args(): + yield arg +@@ -572,10 +564,6 @@ class vault_archive(Local): + ), + ) + +- @property +- def NO_CLI(self): +- return self.api.Command.vault_archive_internal.NO_CLI +- + def get_args(self): + for arg in self.api.Command.vault_archive_internal.args(): + yield arg +@@ -820,10 +808,6 @@ class vault_retrieve(Local): + ), + ) + +- @property +- def NO_CLI(self): +- return self.api.Command.vault_retrieve_internal.NO_CLI +- + def get_args(self): + for arg in self.api.Command.vault_retrieve_internal.args(): + yield arg +-- +2.4.3 + diff --git a/SOURCES/0007-do-not-import-memcache-on-client.patch b/SOURCES/0007-do-not-import-memcache-on-client.patch deleted file mode 100644 index cbdcfb0..0000000 --- a/SOURCES/0007-do-not-import-memcache-on-client.patch +++ /dev/null @@ -1,41 +0,0 @@ -From 0def5f5e160f6ebdf766d956721b70c26372a0b6 Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Thu, 16 Jul 2015 10:17:26 +0200 -Subject: [PATCH] do not import memcache on client - -Fixes regression caused by cd3ca94ff2ef738cb3a9eae502193413058f976d. - -Which caused: -* client installation failure (missing memcache) -* invalid warning in CLI on server - -https://fedorahosted.org/freeipa/ticket/5133 - -Reviewed-By: Tomas Babej ---- - ipalib/plugins/session.py | 6 ++++-- - 1 file changed, 4 insertions(+), 2 deletions(-) - -diff --git a/ipalib/plugins/session.py b/ipalib/plugins/session.py -index 3fd566d3224a13b5fbaa4450f02855329a13bc4c..b03b6b41032ab7f00ff9b75e23b5f998353a7ea5 100644 ---- a/ipalib/plugins/session.py -+++ b/ipalib/plugins/session.py -@@ -2,11 +2,13 @@ - # Copyright (C) 2015 FreeIPA Contributors see COPYING for license - # - --from ipalib import Command -+from ipalib import api, Command - from ipalib.request import context --from ipalib.session import session_mgr - from ipalib.plugable import Registry - -+if api.env.in_server: -+ from ipalib.session import session_mgr -+ - register = Registry() - - --- -2.4.3 - diff --git a/SOURCES/0008-selinux-enable-httpd_run_ipa-to-allow-communicating-.patch b/SOURCES/0008-selinux-enable-httpd_run_ipa-to-allow-communicating-.patch deleted file mode 100644 index c36d10a..0000000 --- a/SOURCES/0008-selinux-enable-httpd_run_ipa-to-allow-communicating-.patch +++ /dev/null @@ -1,49 +0,0 @@ -From aad359de280a0c28e9a9305fd93b48cd40ddddd8 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Tue, 14 Jul 2015 11:11:36 +0000 -Subject: [PATCH] selinux: enable httpd_run_ipa to allow communicating with - oddjobd services - -A new SELinux policy allows communication between IPA framework running -under Apache with oddjobd-based services via DBus. - -This communication is crucial for one-way trust support and also is required -for any out of band tools which may be executed by IPA framework. - -Details of out of band communication and SELinux policy can be found in a bug -https://bugzilla.redhat.com/show_bug.cgi?id=1238165 - -Reviewed-By: Tomas Babej ---- - freeipa.spec.in | 2 +- - ipaserver/install/httpinstance.py | 1 + - 2 files changed, 2 insertions(+), 1 deletion(-) - -diff --git a/freeipa.spec.in b/freeipa.spec.in -index a819710b2bad16a5c17b77670cdb29cb4b09ad8f..5790f7941d2117ed95d3c99556f1579c27917270 100644 ---- a/freeipa.spec.in -+++ b/freeipa.spec.in -@@ -8,7 +8,7 @@ - %global selinux_policy_version 3.12.1-153 - %else - %global samba_version 2:4.0.5-1 --%global selinux_policy_version 3.12.1-179 -+%global selinux_policy_version 3.13.1-128.6 - %endif - - %define krb5_base_version %(LC_ALL=C rpm -q --qf '%%{VERSION}' krb5-devel | grep -Eo '^[^.]+\.[^.]+') -diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py -index f5f2a86fca3a1ff3e9123d08052a7e57b50a94fe..792825621f68844a2b0b1265eeeb37e4247d66f8 100644 ---- a/ipaserver/install/httpinstance.py -+++ b/ipaserver/install/httpinstance.py -@@ -46,6 +46,7 @@ from ipaplatform import services - SELINUX_BOOLEAN_SETTINGS = dict( - httpd_can_network_connect='on', - httpd_manage_ipa='on', -+ httpd_run_ipa='on', - ) - - --- -2.4.3 - diff --git a/SOURCES/0008-vault-add-set-the-default-vault-type-on-the-client-s.patch b/SOURCES/0008-vault-add-set-the-default-vault-type-on-the-client-s.patch new file mode 100644 index 0000000..5045dea --- /dev/null +++ b/SOURCES/0008-vault-add-set-the-default-vault-type-on-the-client-s.patch @@ -0,0 +1,38 @@ +From 5754f00a924bd74079fbf8dc386437ef671547b0 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Tue, 12 Jul 2016 13:44:49 +0200 +Subject: [PATCH] vault-add: set the default vault type on the client side if + none was given + +`vault-add` commands does much processing depending on the vault type even +before the request is forwarded to remote server. Since default values for +parameters are now filled only on server side, the client-side logic would +fail if the vault type was not explicitly given. In this case we have to +retrieve and use the default vault type from schema. + +https://fedorahosted.org/freeipa/ticket/6047 + +Reviewed-By: Stanislav Laznicka +--- + ipaclient/plugins/vault.py | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py +index bf0242fc4290bb94f29faf9c787dd7454a8921bf..a3ce6fecbfd38b342f826d8d27940d991d821e90 100644 +--- a/ipaclient/plugins/vault.py ++++ b/ipaclient/plugins/vault.py +@@ -221,6 +221,11 @@ class vault_add(Local): + def forward(self, *args, **options): + + vault_type = options.get('ipavaulttype') ++ ++ if vault_type is None: ++ internal_cmd = self.api.Command.vault_add_internal ++ vault_type = internal_cmd.params.ipavaulttype.default ++ + password = options.get('password') + password_file = options.get('password_file') + public_key = options.get('ipavaultpublickey') +-- +2.4.3 + diff --git a/SOURCES/0009-caacl-expand-plugin-documentation.patch b/SOURCES/0009-caacl-expand-plugin-documentation.patch new file mode 100644 index 0000000..3b5a6c2 --- /dev/null +++ b/SOURCES/0009-caacl-expand-plugin-documentation.patch @@ -0,0 +1,66 @@ +From 39fdccd9216c7a58ba48ed2226a5588a4f19da51 Mon Sep 17 00:00:00 2001 +From: Fraser Tweedale +Date: Tue, 12 Jul 2016 15:11:11 +1000 +Subject: [PATCH] caacl: expand plugin documentation + +Expand the 'caacl' plugin documentation to explain some common +confusions including the fact that CA ACLs apply to the target +subject principal (not necessarily the principal requesting the +cert), and the fact that CA-less CA ACL implies the 'ipa' CA. + +Fixes: https://fedorahosted.org/freeipa/ticket/6002 +Reviewed-By: Alexander Bokovoy +--- + ipaserver/plugins/caacl.py | 34 ++++++++++++++++++++++++++++------ + 1 file changed, 28 insertions(+), 6 deletions(-) + +diff --git a/ipaserver/plugins/caacl.py b/ipaserver/plugins/caacl.py +index 3f813a7efb9e554abcb8dd2946eea73065c93414..1461c4814727e5774219ac206bab3d078f2daa7d 100644 +--- a/ipaserver/plugins/caacl.py ++++ b/ipaserver/plugins/caacl.py +@@ -23,14 +23,36 @@ if six.PY3: + __doc__ = _(""" + Manage CA ACL rules. + +-This plugin is used to define rules governing which principals are +-permitted to have certificates issued using a given certificate +-profile. ++This plugin is used to define rules governing which CAs and profiles ++may be used to issue certificates to particular principals or groups ++of principals. + +-PROFILE ID SYNTAX: ++SUBJECT PRINCIPAL SCOPE: + +-A Profile ID is a string without spaces or punctuation starting with a letter +-and followed by a sequence of letters, digits or underscore ("_"). ++For a certificate request to be allowed, the principal(s) that are ++the subject of a certificate request (not necessarily the principal ++actually requesting the certificate) must be included in the scope ++of a CA ACL that also includes the target CA and profile. ++ ++Users can be included by name, group or the "all users" category. ++Hosts can be included by name, hostgroup or the "all hosts" ++category. Services can be included by service name or the "all ++services" category. CA ACLs may be associated with a single type of ++principal, or multiple types. ++ ++CERTIFICATE AUTHORITY SCOPE: ++ ++A CA ACL can be associated with one or more CAs by name, or by the ++"all CAs" category. For compatibility reasons, a CA ACL with no CA ++association implies an association with the 'ipa' CA (and only this ++CA). ++ ++PROFILE SCOPE: ++ ++A CA ACL can be associated with one or more profiles by Profile ID. ++The Profile ID is a string without spaces or punctuation starting ++with a letter and followed by a sequence of letters, digits or ++underscore ("_"). + + EXAMPLES: + +-- +2.4.3 + diff --git a/SOURCES/0009-oddjob-avoid-chown-keytab-to-sssd-if-sssd-user-does-.patch b/SOURCES/0009-oddjob-avoid-chown-keytab-to-sssd-if-sssd-user-does-.patch deleted file mode 100644 index 34ece69..0000000 --- a/SOURCES/0009-oddjob-avoid-chown-keytab-to-sssd-if-sssd-user-does-.patch +++ /dev/null @@ -1,50 +0,0 @@ -From cc4f00b7fcbd01dcdfd920feda39cdd0344e7cd7 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Thu, 16 Jul 2015 14:11:26 +0300 -Subject: [PATCH] oddjob: avoid chown keytab to sssd if sssd user does not - exist - -If sssd user does not exist, it means SSSD does not run as sssd user. - -Currently SSSD has too tight check for keytab permissions and ownership. -It assumes the keytab has to be owned by the same user it runs under -and has to have 0600 permissions. ipa-getkeytab creates the file with -right permissions and 'root:root' ownership. - -Jakub Hrozek promised to enhance SSSD keytab permissions check so that -both sssd:sssd and root:root ownership is possible and then when SSSD -switches to 'sssd' user, the former becomes the default. Since right now -SSSD 1.13 is capable to run as 'sssd' user but doesn't create 'sssd' -user in Fedora 22 / RHEL 7 environments, we can use its presence as a -version trigger. - -https://fedorahosted.org/freeipa/ticket/5136 - -Reviewed-By: Tomas Babej ---- - install/oddjob/com.redhat.idm.trust-fetch-domains | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - -diff --git a/install/oddjob/com.redhat.idm.trust-fetch-domains b/install/oddjob/com.redhat.idm.trust-fetch-domains -index 85e3cc993b28f983f7e7ae068d9f9f135bab876e..e50c81e50e73b258bf08737c2d9a13a8832eb69f 100755 ---- a/install/oddjob/com.redhat.idm.trust-fetch-domains -+++ b/install/oddjob/com.redhat.idm.trust-fetch-domains -@@ -45,8 +45,13 @@ def retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal): - env={'KRB5CCNAME': ccache_name, 'LANG': 'C'}, - raiseonerr=False) - # Make sure SSSD is able to read the keytab -- sssd = pwd.getpwnam('sssd') -- os.chown(oneway_keytab_name, sssd[2], sssd[3]) -+ try: -+ sssd = pwd.getpwnam('sssd') -+ os.chown(oneway_keytab_name, sssd[2], sssd[3]) -+ except KeyError as e: -+ # If user 'sssd' does not exist, we don't need to chown from root to sssd -+ # because it means SSSD does not run as sssd user -+ pass - - - def parse_options(): --- -2.4.3 - diff --git a/SOURCES/0010-host-find-do-not-show-SSH-key-by-default.patch b/SOURCES/0010-host-find-do-not-show-SSH-key-by-default.patch new file mode 100644 index 0000000..387dc4d --- /dev/null +++ b/SOURCES/0010-host-find-do-not-show-SSH-key-by-default.patch @@ -0,0 +1,30 @@ +From 058e260ac530f09f5fb5566a14a87614c4bdff63 Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Fri, 8 Jul 2016 13:40:02 +0200 +Subject: [PATCH] host-find: do not show SSH key by default + +Only function 'remove_sshpubkey_from_output_list_post' should be used in +postcallbacks of *-find, otherwise only one entry will be cleaned up + +https://fedorahosted.org/freeipa/ticket/6043 + +Reviewed-By: Stanislav Laznicka +--- + ipaserver/plugins/host.py | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/ipaserver/plugins/host.py b/ipaserver/plugins/host.py +index 2c5cf48cb80c6a49b6577836231a19cd13d824e2..f342b05c87b936ab7b99009cfb0f6d3acde4ef93 100644 +--- a/ipaserver/plugins/host.py ++++ b/ipaserver/plugins/host.py +@@ -1077,7 +1077,6 @@ class host_find(LDAPSearch): + entry_attrs['managing'] = self.obj.get_managed_hosts(entry_attrs.dn) + + convert_sshpubkey_post(entry_attrs) +- remove_sshpubkey_from_output_post(self.context, entry_attrs) + convert_ipaassignedidview_post(entry_attrs, options) + + remove_sshpubkey_from_output_list_post(self.context, entries) +-- +2.4.3 + diff --git a/SOURCES/0010-webui-fix-user-reset-password-dialog.patch b/SOURCES/0010-webui-fix-user-reset-password-dialog.patch deleted file mode 100644 index a94134f..0000000 --- a/SOURCES/0010-webui-fix-user-reset-password-dialog.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 29bc4045aebbe06c9c4dc6985749b809b12d785e Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Tue, 14 Jul 2015 17:55:48 +0200 -Subject: [PATCH] webui: fix user reset password dialog - -Could not open user password dialog. - -regression introduced in ed78dcfa3acde7aeb1f381f49988c6911c5277ee - -https://fedorahosted.org/freeipa/ticket/5131 - -Reviewed-By: Martin Basti ---- - install/ui/src/freeipa/dialogs/password.js | 1 - - install/ui/src/freeipa/user.js | 5 +++-- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/install/ui/src/freeipa/dialogs/password.js b/install/ui/src/freeipa/dialogs/password.js -index f25f7ac60477b1c85b5a6ede23cd93724a89e642..aa9bf44fc49b890fb5393119335b13c622f48879 100644 ---- a/install/ui/src/freeipa/dialogs/password.js -+++ b/install/ui/src/freeipa/dialogs/password.js -@@ -48,7 +48,6 @@ dialogs.password.default_fields_pre_op = function(spec) { - - spec.title = spec.title || '@i18n:password.reset_password'; - spec.width = spec.width || 400; -- spec.method = spec.method || 'mod'; - spec.success_message = spec.success_message || '@i18n:password.password_change_complete'; - spec.confirm_button_label = spec.confirm_button_label || '@i18n:password.reset_password'; - spec.sections = spec.sections || [ -diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js -index e30311bbf0763d9efbc38fdb19e80e114e7636c9..0e828c16b999ffd58504bc4e53d2748bcd16b042 100644 ---- a/install/ui/src/freeipa/user.js -+++ b/install/ui/src/freeipa/user.js -@@ -29,13 +29,14 @@ define([ - './reg', - './rpc', - './text', -+ './dialog', - './dialogs/password', - './details', - './search', - './association', - './entity', - './certificate'], -- function(builder, IPA, $, phases, reg, rpc, text, password_dialog) { -+ function(builder, IPA, $, phases, reg, rpc, text, dialogs) { - - /** - * User module -@@ -638,7 +639,7 @@ IPA.user.password_dialog_pre_op = function(spec) { - - IPA.user.password_dialog = function(spec) { - -- var that = password_dialog.dialog(spec); -+ var that = dialogs.command_dialog(spec); - - that.is_self_service = function() { - var self_service = that.args[0] === IPA.whoami.uid[0]; --- -2.4.3 - diff --git a/SOURCES/0011-Removed-unused-method-parameter-from-migrate-ds.patch b/SOURCES/0011-Removed-unused-method-parameter-from-migrate-ds.patch new file mode 100644 index 0000000..97510ab --- /dev/null +++ b/SOURCES/0011-Removed-unused-method-parameter-from-migrate-ds.patch @@ -0,0 +1,31 @@ +From 4132b63a5e02b019826053a07b2be79c879c1f6e Mon Sep 17 00:00:00 2001 +From: Stanislav Laznicka +Date: Mon, 11 Jul 2016 12:31:39 +0200 +Subject: [PATCH] Removed unused method parameter from migrate-ds + +An extra parameter on client side command override of migrate-ds output +was causing errors. + +https://fedorahosted.org/freeipa/ticket/6034 + +Reviewed-By: Martin Babinsky +--- + ipaclient/plugins/migration.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipaclient/plugins/migration.py b/ipaclient/plugins/migration.py +index 8ac5f66bf1440b245c1268cd97d5a3e0dc2e6226..cf8d461bfa144f1287ef36a231f553fd9cd102b3 100644 +--- a/ipaclient/plugins/migration.py ++++ b/ipaclient/plugins/migration.py +@@ -50,7 +50,7 @@ can use their Kerberos accounts.''') + option = option.clone_retype(option.name, File) + yield option + +- def output_for_cli(self, textui, result, ldapuri, bindpw, **options): ++ def output_for_cli(self, textui, result, ldapuri, **options): + textui.print_name(self.name) + if not result['enabled']: + textui.print_plain(self.migration_disabled_msg) +-- +2.4.3 + diff --git a/SOURCES/0011-fix-hbac-rule-search-for-non-admin-users.patch b/SOURCES/0011-fix-hbac-rule-search-for-non-admin-users.patch deleted file mode 100644 index a71a9ae..0000000 --- a/SOURCES/0011-fix-hbac-rule-search-for-non-admin-users.patch +++ /dev/null @@ -1,35 +0,0 @@ -From f8a4727b7e77e377e4c63c0ebd98a67f4f84bdb4 Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Tue, 14 Jul 2015 18:04:33 +0200 -Subject: [PATCH] fix hbac rule search for non-admin users - -hbacrule has it default attributes (which are used in search) attribute -'memberhostgroup'. This attr is not in ACI nor in schema. If the search -contains an attribute which can't be read then the search won't return -anything. - -Therefore all searches with filter set fail. - -https://fedorahosted.org/freeipa/ticket/5130 - -Reviewed-By: Martin Basti ---- - ipalib/plugins/hbacrule.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipalib/plugins/hbacrule.py b/ipalib/plugins/hbacrule.py -index 34bdc9bdfe03f01662851bd5aea9daf9e28823d0..82a52bd80f58ede43249264db69acd193233448d 100644 ---- a/ipalib/plugins/hbacrule.py -+++ b/ipalib/plugins/hbacrule.py -@@ -124,7 +124,7 @@ class hbacrule(LDAPObject): - 'description', 'usercategory', 'hostcategory', - 'servicecategory', 'ipaenabledflag', - 'memberuser', 'sourcehost', 'memberhost', 'memberservice', -- 'memberhostgroup', 'externalhost', -+ 'externalhost', - ] - uuid_attribute = 'ipauniqueid' - rdn_attribute = 'ipauniqueid' --- -2.4.3 - diff --git a/SOURCES/0012-Preserve-user-principal-aliases-during-rename-operat.patch b/SOURCES/0012-Preserve-user-principal-aliases-during-rename-operat.patch new file mode 100644 index 0000000..b897bc3 --- /dev/null +++ b/SOURCES/0012-Preserve-user-principal-aliases-during-rename-operat.patch @@ -0,0 +1,92 @@ +From 07ff43d198055bc5b95a0acdf516216d00a85cc3 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Fri, 1 Jul 2016 18:09:04 +0200 +Subject: [PATCH] Preserve user principal aliases during rename operation + +When a MODRDN is performed on the user entry, the MODRDN plugin resets both +krbPrincipalName and krbCanonicalName to the value constructed from uid. In +doing so, hovewer, any principal aliases added to the krbPrincipalName are +wiped clean. In this patch old aliases are fetched before the MODRDN operation +takes place and inserted back after it is performed. + +This also preserves previous user logins which can be used further for +authentication as aliases. + +https://fedorahosted.org/freeipa/ticket/6028 + +Reviewed-By: Alexander Bokovoy +Reviewed-By: Simo Sorce +--- + ipaserver/plugins/baseuser.py | 46 +++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 46 insertions(+) + +diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py +index 0052e718afe639bcc1c0a698ded39ea8407a0551..e4288a5a131157815ffb2452692a7edb342f6ac3 100644 +--- a/ipaserver/plugins/baseuser.py ++++ b/ipaserver/plugins/baseuser.py +@@ -498,6 +498,50 @@ class baseuser_mod(LDAPUpdate): + len = int(config.get('ipamaxusernamelength')[0]) + ) + ) ++ ++ def preserve_krbprincipalname_pre(self, ldap, entry_attrs, *keys, **options): ++ """ ++ preserve user principal aliases during rename operation. This is the ++ pre-callback part of this. Another method called during post-callback ++ shall insert the principals back ++ """ ++ if options.get('rename', None) is None: ++ return ++ ++ try: ++ old_entry = ldap.get_entry( ++ entry_attrs.dn, attrs_list=( ++ 'krbprincipalname', 'krbcanonicalname')) ++ ++ if 'krbcanonicalname' not in old_entry: ++ return ++ except errors.NotFound: ++ self.obj.handle_not_found(*keys) ++ ++ self.context.krbprincipalname = old_entry.get( ++ 'krbprincipalname', []) ++ ++ def preserve_krbprincipalname_post(self, ldap, entry_attrs, **options): ++ """ ++ Insert the preserved aliases back to the user entry during rename ++ operation ++ """ ++ if options.get('rename', None) is None or not hasattr( ++ self.context, 'krbprincipalname'): ++ return ++ ++ obj_pkey = self.obj.get_primary_key_from_dn(entry_attrs.dn) ++ canonical_name = entry_attrs['krbcanonicalname'][0] ++ ++ principals_to_add = tuple(p for p in self.context.krbprincipalname if ++ p != canonical_name) ++ ++ if principals_to_add: ++ result = self.api.Command.user_add_principal( ++ obj_pkey, principals_to_add)['result'] ++ ++ entry_attrs['krbprincipalname'] = result.get('krbprincipalname', []) ++ + def check_mail(self, entry_attrs): + if 'mail' in entry_attrs: + entry_attrs['mail'] = self.obj.normalize_and_validate_email(entry_attrs['mail']) +@@ -557,9 +601,11 @@ class baseuser_mod(LDAPUpdate): + + self.check_objectclass(ldap, dn, entry_attrs) + self.obj.convert_usercertificate_pre(entry_attrs) ++ self.preserve_krbprincipalname_pre(ldap, entry_attrs, *keys, **options) + + def post_common_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) ++ self.preserve_krbprincipalname_post(ldap, entry_attrs, **options) + if options.get('random', False): + try: + entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword')) +-- +2.7.4 + diff --git a/SOURCES/0012-fix-selinuxusermap-search-for-non-admin-users.patch b/SOURCES/0012-fix-selinuxusermap-search-for-non-admin-users.patch deleted file mode 100644 index e108873..0000000 --- a/SOURCES/0012-fix-selinuxusermap-search-for-non-admin-users.patch +++ /dev/null @@ -1,30 +0,0 @@ -From d234274f7e99a7eeff89e4039cf176a4b15147ec Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Thu, 16 Jul 2015 15:07:05 +0200 -Subject: [PATCH] fix selinuxusermap search for non-admin users - -Remove nonexistent attribute 'hostmembergroup' that is not in ACI nor schema. - -Related to https://fedorahosted.org/freeipa/ticket/5130 - -Reviewed-By: Petr Vobornik ---- - ipalib/plugins/selinuxusermap.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipalib/plugins/selinuxusermap.py b/ipalib/plugins/selinuxusermap.py -index 76668b4692d4374fd09a83d6c28cb6cb2b20c958..e1a16af5004a5f4fd01166230ddd586068b6b556 100644 ---- a/ipalib/plugins/selinuxusermap.py -+++ b/ipalib/plugins/selinuxusermap.py -@@ -143,7 +143,7 @@ class selinuxusermap(LDAPObject): - 'cn', 'ipaenabledflag', - 'description', 'usercategory', 'hostcategory', - 'ipaenabledflag', 'memberuser', 'memberhost', -- 'memberhostgroup', 'seealso', 'ipaselinuxuser', -+ 'seealso', 'ipaselinuxuser', - ] - uuid_attribute = 'ipauniqueid' - rdn_attribute = 'ipauniqueid' --- -2.4.3 - diff --git a/SOURCES/0013-Validate-adding-privilege-to-a-permission.patch b/SOURCES/0013-Validate-adding-privilege-to-a-permission.patch deleted file mode 100644 index 69f0992..0000000 --- a/SOURCES/0013-Validate-adding-privilege-to-a-permission.patch +++ /dev/null @@ -1,113 +0,0 @@ -From 8ad2b5d6b81986235d0da6aa9349cfefaec06fcb Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Thu, 9 Jul 2015 16:48:36 +0200 -Subject: [PATCH] Validate adding privilege to a permission - -Adding priviledge to a permission via webUI allowed to avoid check and to add permission -with improper type. - -https://fedorahosted.org/freeipa/ticket/5075 - -Reviewed-By: Jan Cholasta ---- - ipalib/plugins/permission.py | 7 ++++++ - ipalib/plugins/privilege.py | 51 ++++++++++++++++++++++---------------------- - 2 files changed, 33 insertions(+), 25 deletions(-) - -diff --git a/ipalib/plugins/permission.py b/ipalib/plugins/permission.py -index f2e896935cc777801ec3a70262372f296b1ea2b8..7d2a4dd156693d9d9b7d6f042488856274fb3f64 100644 ---- a/ipalib/plugins/permission.py -+++ b/ipalib/plugins/permission.py -@@ -21,6 +21,7 @@ import re - import traceback - - from ipalib.plugins import baseldap -+from ipalib.plugins.privilege import validate_permission_to_privilege - from ipalib import errors - from ipalib.parameters import Str, StrEnum, DNParam, Flag - from ipalib import api, _, ngettext -@@ -1377,6 +1378,12 @@ class permission_add_member(baseldap.LDAPAddMember): - """Add members to a permission.""" - NO_CLI = True - -+ def pre_callback(self, ldap, dn, member_dns, failed, *keys, **options): -+ # We can only add permissions with bind rule type set to -+ # "permission" (or old-style permissions) -+ validate_permission_to_privilege(self.api, keys[-1]) -+ return dn -+ - - @register() - class permission_remove_member(baseldap.LDAPRemoveMember): -diff --git a/ipalib/plugins/privilege.py b/ipalib/plugins/privilege.py -index 867544359f76fdcb44cd3015f7466a46ba492bec..ffb903e03dbfaafbe2bb7135038494ae49a7d8a8 100644 ---- a/ipalib/plugins/privilege.py -+++ b/ipalib/plugins/privilege.py -@@ -45,6 +45,31 @@ See role and permission for additional information. - register = Registry() - - -+def validate_permission_to_privilege(api, permission): -+ ldap = api.Backend.ldap2 -+ ldapfilter = ldap.combine_filters(rules='&', filters=[ -+ '(objectClass=ipaPermissionV2)', '(!(ipaPermBindRuleType=permission))', -+ ldap.make_filter_from_attr('cn', permission, rules='|')]) -+ try: -+ entries, truncated = ldap.find_entries( -+ filter=ldapfilter, -+ attrs_list=['cn', 'ipapermbindruletype'], -+ base_dn=DN(api.env.container_permission, api.env.basedn), -+ size_limit=1) -+ except errors.NotFound: -+ pass -+ else: -+ entry = entries[0] -+ message = _('cannot add permission "%(perm)s" with bindtype ' -+ '"%(bindtype)s" to a privilege') -+ raise errors.ValidationError( -+ name='permission', -+ error=message % { -+ 'perm': entry.single_value['cn'], -+ 'bindtype': entry.single_value.get( -+ 'ipapermbindruletype', 'permission')}) -+ -+ - @register() - class privilege(LDAPObject): - """ -@@ -185,31 +210,7 @@ class privilege_add_permission(LDAPAddReverseMember): - if options.get('permission'): - # We can only add permissions with bind rule type set to - # "permission" (or old-style permissions) -- ldapfilter = ldap.combine_filters(rules='&', filters=[ -- '(objectClass=ipaPermissionV2)', -- '(!(ipaPermBindRuleType=permission))', -- ldap.make_filter_from_attr('cn', options['permission'], -- rules='|'), -- ]) -- try: -- entries, truncated = ldap.find_entries( -- filter=ldapfilter, -- attrs_list=['cn', 'ipapermbindruletype'], -- base_dn=DN(self.api.env.container_permission, -- self.api.env.basedn), -- size_limit=1) -- except errors.NotFound: -- pass -- else: -- entry = entries[0] -- message = _('cannot add permission "%(perm)s" with bindtype ' -- '"%(bindtype)s" to a privilege') -- raise errors.ValidationError( -- name='permission', -- error=message % { -- 'perm': entry.single_value['cn'], -- 'bindtype': entry.single_value.get( -- 'ipapermbindruletype', 'permission')}) -+ validate_permission_to_privilege(self.api, options['permission']) - return dn - - --- -2.4.3 - diff --git a/SOURCES/0013-messages-specify-message-type-for-ResultFormattingEr.patch b/SOURCES/0013-messages-specify-message-type-for-ResultFormattingEr.patch new file mode 100644 index 0000000..3f77ffa --- /dev/null +++ b/SOURCES/0013-messages-specify-message-type-for-ResultFormattingEr.patch @@ -0,0 +1,31 @@ +From 0d5962e52aa9418ec0285f202aa786083aec67c3 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Wed, 13 Jul 2016 18:22:04 +0200 +Subject: [PATCH] messages: specify message type for ResultFormattingError + +the ResultFormattingError message class was missing a `type` member which +could cause `otptoken-add` command to crash during QR image rendering using +suboptimal TTY settings + +https://fedorahosted.org/freeipa/ticket/6081 + +Reviewed-By: Alexander Bokovoy +--- + ipalib/messages.py | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/ipalib/messages.py b/ipalib/messages.py +index 7288606f6ac923c2c87fadba5f2a6a2d9dadb7f5..6abad64a8259a8e164db60f63e75bbb9c230e7bf 100644 +--- a/ipalib/messages.py ++++ b/ipalib/messages.py +@@ -363,6 +363,7 @@ class ResultFormattingError(PublicMessage): + """ + **13019** Unable to correctly format some part of the result + """ ++ type = "warning" + errno = 13019 + + +-- +2.7.4 + diff --git a/SOURCES/0014-migration-Use-api.env-variables.patch b/SOURCES/0014-migration-Use-api.env-variables.patch deleted file mode 100644 index 420edaa..0000000 --- a/SOURCES/0014-migration-Use-api.env-variables.patch +++ /dev/null @@ -1,85 +0,0 @@ -From c626fcb564404d41cd06db83a299e97959fa3c4e Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Thu, 16 Jul 2015 10:15:36 +0200 -Subject: [PATCH] migration: Use api.env variables. - -Use api.env.basedn instead of anonymously accessing LDAP to get base DN. -Use api.env.basedn instead of searching filesystem for ldapi socket. - -https://fedorahosted.org/freeipa/ticket/4953 - -Reviewed-By: Jan Cholasta -Reviewed-By: Petr Vobornik -Reviewed-By: Alexander Bokovoy ---- - install/migration/migration.py | 33 +++++---------------------------- - 1 file changed, 5 insertions(+), 28 deletions(-) - -diff --git a/install/migration/migration.py b/install/migration/migration.py -index b629b1c9ff7bd58f1ea64e4c2b2433428a939f28..8c440175a0358b01acba227ea3179318af50fa32 100644 ---- a/install/migration/migration.py -+++ b/install/migration/migration.py -@@ -22,14 +22,13 @@ Password migration script - - import cgi - import errno --import glob - from wsgiref.util import request_uri - - from ipapython.ipa_log_manager import root_logger - from ipapython.ipautil import get_ipa_basedn - from ipapython.dn import DN - from ipapython.ipaldap import IPAdmin --from ipalib import errors -+from ipalib import errors, create_api - from ipaplatform.paths import paths - - -@@ -45,23 +44,6 @@ def get_ui_url(environ): - return full_url[:index] + "/ipa/ui" - - --def get_base_dn(ldap_uri): -- """ -- Retrieve LDAP server base DN. -- """ -- try: -- conn = IPAdmin(ldap_uri=ldap_uri) -- conn.do_simple_bind(DN(), '') -- base_dn = get_ipa_basedn(conn) -- except Exception, e: -- root_logger.error('migration context search failed: %s' % e) -- return '' -- finally: -- conn.unbind() -- -- return base_dn -- -- - def bind(ldap_uri, base_dn, username, password): - if not base_dn: - root_logger.error('migration unable to get base dn') -@@ -90,16 +72,11 @@ def application(environ, start_response): - if not form_data.has_key('username') or not form_data.has_key('password'): - return wsgi_redirect(start_response, 'invalid.html') - -- slapd_sockets = glob.glob(paths.ALL_SLAPD_INSTANCE_SOCKETS) -- if slapd_sockets: -- ldap_uri = 'ldapi://%s' % slapd_sockets[0].replace('/', '%2f') -- else: -- ldap_uri = 'ldaps://localhost:636' -- -- base_dn = get_base_dn(ldap_uri) -- -+ # API object only for configuration, finalize() not needed -+ api = create_api(mode=None) -+ api.bootstrap(context='server', in_server=True) - try: -- bind(ldap_uri, base_dn, -+ bind(api.env.ldap_uri, api.env.basedn, - form_data['username'].value, form_data['password'].value) - except IOError as err: - if err.errno == errno.EPERM: --- -2.4.3 - diff --git a/SOURCES/0014-schema-Fix-subtopic-topic-mapping.patch b/SOURCES/0014-schema-Fix-subtopic-topic-mapping.patch new file mode 100644 index 0000000..2f95e8a --- /dev/null +++ b/SOURCES/0014-schema-Fix-subtopic-topic-mapping.patch @@ -0,0 +1,29 @@ +From a48b8aa5e4d45b238551c122f88dfc8151314c93 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Thu, 14 Jul 2016 10:15:59 +0200 +Subject: [PATCH] schema: Fix subtopic -> topic mapping + +https://fedorahosted.org/freeipa/ticket/6069 + +Reviewed-By: Martin Babinsky +--- + ipaserver/plugins/schema.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ipaserver/plugins/schema.py b/ipaserver/plugins/schema.py +index a82b357899a483fd3b3dc9f7407bd26a4c03aada..8fd7c6ba1c4ed8cd6e27cb8b1b04f48694a4f1ff 100644 +--- a/ipaserver/plugins/schema.py ++++ b/ipaserver/plugins/schema.py +@@ -399,7 +399,8 @@ class topic_(MetaObject): + continue + if topic_value is not None: + topic_name = unicode(topic_value) +- topic['topic_topic'] = topic_full_name ++ topic['topic_topic'] = '{}/{}'.format(topic_name, ++ topic_version) + else: + topic.pop('topic_topic', None) + +-- +2.7.4 + diff --git a/SOURCES/0015-DNS-install-Ensure-that-DNS-servers-container-exists.patch b/SOURCES/0015-DNS-install-Ensure-that-DNS-servers-container-exists.patch new file mode 100644 index 0000000..b0dd7fc --- /dev/null +++ b/SOURCES/0015-DNS-install-Ensure-that-DNS-servers-container-exists.patch @@ -0,0 +1,93 @@ +From caceb3a08644dae0ecae05a5b1f18b91a522356d Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Thu, 14 Jul 2016 17:14:59 +0200 +Subject: [PATCH] DNS install: Ensure that DNS servers container exists + +during DNS installation it is assumed that the cn=servers,cn=dns container is +always present in LDAP backend when migrating DNS server info to LDAP. + +This may not always be the case (e.g. when a new replica is set up against +older master) so the code must take additional steps to ensure this container +is present. + +https://fedorahosted.org/freeipa/ticket/6083 + +Reviewed-By: Stanislav Laznicka +--- + ipaserver/install/bindinstance.py | 21 +++++++++++++++++++++ + ipaserver/install/plugins/dns.py | 13 ++----------- + 2 files changed, 23 insertions(+), 11 deletions(-) + +diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py +index f4ed63141cf25dfcfdc72d37d6ff4563e4acccf1..844fb04a9d9feca936211964b75a0b3468ba663b 100644 +--- a/ipaserver/install/bindinstance.py ++++ b/ipaserver/install/bindinstance.py +@@ -546,6 +546,26 @@ def remove_master_dns_records(hostname, realm): + bind.remove_server_ns_records(hostname) + + ++def ensure_dnsserver_container_exists(ldap, api_instance, logger=None): ++ """ ++ Create cn=servers,cn=dns,$SUFFIX container. If logger is not None, emit a ++ message that the container already exists when DuplicateEntry is raised ++ """ ++ ++ entry = ldap.make_entry( ++ DN(api_instance.env.container_dnsservers, api_instance.env.basedn), ++ { ++ u'objectclass': [u'top', u'nsContainer'], ++ u'cn': [u'servers'] ++ } ++ ) ++ try: ++ ldap.add_entry(entry) ++ except errors.DuplicateEntry: ++ if logger is not None: ++ logger.debug('cn=servers,cn=dns container already exists') ++ ++ + class DnsBackup(object): + def __init__(self, service): + self.service = service +@@ -942,6 +962,7 @@ class BindInstance(service.Service): + ) + + def __setup_server_configuration(self): ++ ensure_dnsserver_container_exists(self.admin_conn, self.api) + try: + self.api.Command.dnsserver_add( + self.fqdn, idnssoamname=DNSName(self.fqdn).make_absolute(), +diff --git a/ipaserver/install/plugins/dns.py b/ipaserver/install/plugins/dns.py +index 4fa30661e40748cd32cb25c232168191db20c461..32247eedbac7fc7e00c7277ef0bc593a74cd22e4 100644 +--- a/ipaserver/install/plugins/dns.py ++++ b/ipaserver/install/plugins/dns.py +@@ -29,6 +29,7 @@ from ipapython.dn import DN + from ipapython import dnsutil + from ipapython.ipa_log_manager import root_logger + from ipaserver.install import sysupgrade ++from ipaserver.install.bindinstance import ensure_dnsserver_container_exists + from ipaserver.plugins.dns import dns_container_exists + + register = Registry() +@@ -521,17 +522,7 @@ class update_dnsserver_configuration_into_ldap(DNSUpdater): + return False, [] + + # create container first, if doesn't exist +- entry = ldap.make_entry( +- DN(self.api.env.container_dnsservers, self.api.env.basedn), +- { +- u'objectclass': [u'top', u'nsContainer'], +- u'cn': [u'servers'] +- } +- ) +- try: +- ldap.add_entry(entry) +- except errors.DuplicateEntry: +- self.log.debug('cn=dnsservers container already exists') ++ ensure_dnsserver_container_exists(ldap, self.api, logger=self.log) + + try: + self.api.Command.dnsserver_add(self.api.env.host) +-- +2.7.4 + diff --git a/SOURCES/0015-sysrestore-copy-files-instead-of-moving-them-to-avoi.patch b/SOURCES/0015-sysrestore-copy-files-instead-of-moving-them-to-avoi.patch deleted file mode 100644 index 330d314..0000000 --- a/SOURCES/0015-sysrestore-copy-files-instead-of-moving-them-to-avoi.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 630a9b60995e2d6eb02281a3dd176f0252f632db Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Wed, 15 Jul 2015 16:20:59 +0200 -Subject: [PATCH] sysrestore: copy files instead of moving them to avoind - SELinux issues - -Copying files restores SELinux context. - -https://fedorahosted.org/freeipa/ticket/4923 - -Reviewed-By: Alexander Bokovoy ---- - ipapython/sysrestore.py | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/ipapython/sysrestore.py b/ipapython/sysrestore.py -index 580df9a4fd6d0fae35602dad1f81d498fa8f0173..1a111258bc0f6dd503673028d3a990821f077fef 100644 ---- a/ipapython/sysrestore.py -+++ b/ipapython/sysrestore.py -@@ -187,7 +187,9 @@ class FileStore: - if new_path is not None: - path = new_path - -- shutil.move(backup_path, path) -+ shutil.copy(backup_path, path) # SELinux needs copy -+ os.remove(backup_path) -+ - os.chown(path, int(uid), int(gid)) - os.chmod(path, int(mode)) - -@@ -218,7 +220,9 @@ class FileStore: - root_logger.debug(" -> Not restoring - '%s' doesn't exist", backup_path) - continue - -- shutil.move(backup_path, path) -+ shutil.copy(backup_path, path) # SELinux needs copy -+ os.remove(backup_path) -+ - os.chown(path, int(uid), int(gid)) - os.chmod(path, int(mode)) - --- -2.4.3 - diff --git a/SOURCES/0016-Allow-value-no-for-replica-certify-all-attr-in-abort.patch b/SOURCES/0016-Allow-value-no-for-replica-certify-all-attr-in-abort.patch deleted file mode 100644 index f241c55..0000000 --- a/SOURCES/0016-Allow-value-no-for-replica-certify-all-attr-in-abort.patch +++ /dev/null @@ -1,68 +0,0 @@ -From c2b5f7b164268ec8d15916031260c87dc6c9ffd5 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Thu, 16 Jul 2015 16:26:55 +0200 -Subject: [PATCH] Allow value 'no' for replica-certify-all attr in - abort-clean-ruv subcommand - ---force option set replica-certify-all to 'no' during abort-clean-ruv -subcommand - -https://fedorahosted.org/freeipa/ticket/4988 - -Reviewed-By: Petr Vobornik ---- - install/tools/ipa-replica-manage | 2 +- - install/tools/man/ipa-replica-manage.1 | 2 +- - ipaserver/install/replication.py | 3 ++- - 3 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage -index e525a02f4c60350b7a943abab4b4aedd957e984a..50a57f70ec452c0df5bf2ea55d2a136e8149aa41 100755 ---- a/install/tools/ipa-replica-manage -+++ b/install/tools/ipa-replica-manage -@@ -470,7 +470,7 @@ def abort_clean_ruv(realm, ruv, options): - print - thisrepl = replication.ReplicationManager(realm, options.host, - options.dirman_passwd) -- thisrepl.abortcleanallruv(ruv) -+ thisrepl.abortcleanallruv(ruv, options.force) - - print "Cleanup task stopped" - -diff --git a/install/tools/man/ipa-replica-manage.1 b/install/tools/man/ipa-replica-manage.1 -index 8a7c78f39eeb6c7902ed99e7bed37e32eb0e92dc..c09ed362f3143e6e38716e1b3a96e90001a64674 100644 ---- a/install/tools/man/ipa-replica-manage.1 -+++ b/install/tools/man/ipa-replica-manage.1 -@@ -49,7 +49,7 @@ Manages the replication agreements of an IPA server. The available commands are: - \- Run the CLEANALLRUV task to remove a replication ID. - .TP - \fBabort\-clean\-ruv\fR [REPLICATION_ID] --\- Abort a running CLEANALLRUV task. -+\- Abort a running CLEANALLRUV task. With \-\-force option the task does not wait for all the replica servers to have been sent the abort task, or be online, before completing. - .TP - \fBlist\-clean\-ruv\fR - \- List all running CLEANALLRUV and abort CLEANALLRUV tasks. -diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py -index 0f420106e093e8a7a277016857d27aaa48daa4dc..e9af88dc4356d4fd5495f4fea399ab09c75db953 100644 ---- a/ipaserver/install/replication.py -+++ b/ipaserver/install/replication.py -@@ -1451,7 +1451,7 @@ class ReplicationManager(object): - - wait_for_task(self.conn, dn) - -- def abortcleanallruv(self, replicaId): -+ def abortcleanallruv(self, replicaId, force=False): - """ - Create a task to abort a CLEANALLRUV operation. - """ -@@ -1465,6 +1465,7 @@ class ReplicationManager(object): - 'replica-id': [replicaId], - 'objectclass': ['top', 'extensibleObject'], - 'cn': ['abort %d' % replicaId], -+ 'replica-certify-all': ['no'] if force else ['yes'], - } - ) - try: --- -2.4.3 - diff --git a/SOURCES/0016-Heap-corruption-in-ipapwd-plugin.patch b/SOURCES/0016-Heap-corruption-in-ipapwd-plugin.patch new file mode 100644 index 0000000..59d2c6e --- /dev/null +++ b/SOURCES/0016-Heap-corruption-in-ipapwd-plugin.patch @@ -0,0 +1,41 @@ +From 98bdf4755d5c0256d26ba6a6aed6b9e649adf941 Mon Sep 17 00:00:00 2001 +From: Thierry Bordaz +Date: Mon, 18 Jul 2016 15:00:02 +0200 +Subject: [PATCH] Heap corruption in ipapwd plugin + +ipapwd_encrypt_encode_key allocates 'kset' on the heap but +with num_keys and keys not being initialized. +Then ipa_krb5_generate_key_data initializes them with the +generated keys. +If ipa_krb5_generate_key_data fails (here EINVAL meaning no +principal->realm.data), num_keys and keys are left uninitialized. +Upon failure, ipapwd_keyset_free is called to free 'kset' +that contains random num_keys and keys. + +allocates kset with calloc so that kset->num_keys==0 and +kset->keys==NULL + +https://fedorahosted.org/freeipa/ticket/6030 + +Reviewed-By: Simo Sorce +Reviewed-By: Lukas Slebodnik +--- + daemons/ipa-slapi-plugins/ipa-pwd-extop/encoding.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/daemons/ipa-slapi-plugins/ipa-pwd-extop/encoding.c b/daemons/ipa-slapi-plugins/ipa-pwd-extop/encoding.c +index 9c62f0560aa999b2179a7767040047dfa89288e0..7b2f341229b4f3bf48105c3856c0d6778da154a5 100644 +--- a/daemons/ipa-slapi-plugins/ipa-pwd-extop/encoding.c ++++ b/daemons/ipa-slapi-plugins/ipa-pwd-extop/encoding.c +@@ -157,7 +157,7 @@ Slapi_Value **ipapwd_encrypt_encode_key(struct ipapwd_krbcfg *krbcfg, + pwd.length = strlen(data->password); + } + +- kset = malloc(sizeof(struct ipapwd_keyset)); ++ kset = (struct ipapwd_keyset *) calloc(1, sizeof(struct ipapwd_keyset)); + if (!kset) { + LOG_OOM(); + goto enc_error; +-- +2.7.4 + diff --git a/SOURCES/0017-Use-server-API-in-com.redhat.idm.trust-fetch-domains.patch b/SOURCES/0017-Use-server-API-in-com.redhat.idm.trust-fetch-domains.patch new file mode 100644 index 0000000..52f2eae --- /dev/null +++ b/SOURCES/0017-Use-server-API-in-com.redhat.idm.trust-fetch-domains.patch @@ -0,0 +1,29 @@ +From c5f48cd10b9aa3f0dd226aacab8abd8af996c861 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Thu, 14 Jul 2016 09:31:22 +0200 +Subject: [PATCH] Use server API in com.redhat.idm.trust-fetch-domains oddjob + helper + +https://fedorahosted.org/freeipa/ticket/6082 + +Reviewed-By: Alexander Bokovoy +--- + install/oddjob/com.redhat.idm.trust-fetch-domains | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/install/oddjob/com.redhat.idm.trust-fetch-domains b/install/oddjob/com.redhat.idm.trust-fetch-domains +index a6b87cde917cfa5bfedf28442a6d1b2b512706f9..7c948fd53bd54bf3638ef3cc4407576b9011f4fb 100755 +--- a/install/oddjob/com.redhat.idm.trust-fetch-domains ++++ b/install/oddjob/com.redhat.idm.trust-fetch-domains +@@ -76,7 +76,7 @@ env._bootstrap(debug=options.debug, log=None) + env._finalize_core(**dict(DEFAULT_CONFIG)) + + # Initialize the API with the proper debug level +-api.bootstrap(debug=env.debug, log=None) ++api.bootstrap(in_server=True, debug=env.debug, log=None) + api.finalize() + + # Only import trust plugin after api is initialized or internal imports +-- +2.7.4 + diff --git a/SOURCES/0017-trusts-Check-for-AD-root-domain-among-our-trusted-do.patch b/SOURCES/0017-trusts-Check-for-AD-root-domain-among-our-trusted-do.patch deleted file mode 100644 index b0593e2..0000000 --- a/SOURCES/0017-trusts-Check-for-AD-root-domain-among-our-trusted-do.patch +++ /dev/null @@ -1,68 +0,0 @@ -From eb8651626099df8df14e12b905aace0be5c37ded Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Wed, 15 Jul 2015 14:22:48 +0200 -Subject: [PATCH] trusts: Check for AD root domain among our trusted domains - -Check for the presence of the forest root DNS domain of the AD realm -among the IPA realm domains prior to esablishing the trust. - -This prevents creation of a failing setup, as trusts would not work -properly in this case. - -https://fedorahosted.org/freeipa/ticket/4799 - -Reviewed-By: Petr Vobornik -Reviewed-By: Alexander Bokovoy ---- - ipalib/plugins/trust.py | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) - -diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py -index 196df5926e7965dc1f0165f301bd5ac11528d1cd..6232e4fe9d3d5e957d22a3557cdcf4bb12cec0ea 100644 ---- a/ipalib/plugins/trust.py -+++ b/ipalib/plugins/trust.py -@@ -640,6 +640,8 @@ sides. - self.params['realm_passwd'].label, confirm=False) - - def validate_options(self, *keys, **options): -+ trusted_realm_domain = keys[-1] -+ - if not _bindings_installed: - raise errors.NotFound( - name=_('AD Trust setup'), -@@ -692,6 +694,23 @@ sides. - ) - ) - -+ # Obtain a list of IPA realm domains -+ result = self.api.Command.realmdomains_show()['result'] -+ realm_domains = result['associateddomain'] -+ -+ # Do not allow the AD's trusted realm domain in the list -+ # of our realm domains -+ if trusted_realm_domain.lower() in realm_domains: -+ raise errors.ValidationError( -+ name=_('AD Trust setup'), -+ error=_( -+ 'Trusted domain %(domain)s is included among ' -+ 'IPA realm domains. It needs to be removed ' -+ 'prior to establishing the trust. See the ' -+ '"ipa realmdomains-mod --del-domain" command.' -+ ) % dict(domain=trusted_realm_domain) -+ ) -+ - self.realm_server = options.get('realm_server') - self.realm_admin = options.get('realm_admin') - self.realm_passwd = options.get('realm_passwd') -@@ -702,7 +721,7 @@ sides. - if len(names) > 1: - # realm admin name is in UPN format, user@realm, check that - # realm is the same as the one that we are attempting to trust -- if keys[-1].lower() != names[-1].lower(): -+ if trusted_realm_domain.lower() != names[-1].lower(): - raise errors.ValidationError( - name=_('AD Trust setup'), - error=_( --- -2.4.3 - diff --git a/SOURCES/0018-enable-debugging-of-ntpd-during-client-installation.patch b/SOURCES/0018-enable-debugging-of-ntpd-during-client-installation.patch deleted file mode 100644 index 5dce4b2..0000000 --- a/SOURCES/0018-enable-debugging-of-ntpd-during-client-installation.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 941941733a9a2af27ae4fd73714a87a08931e76a Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Mon, 30 Mar 2015 12:29:04 +0200 -Subject: [PATCH] enable debugging of ntpd during client installation - -When installing IPA client in debug mode, the ntpd command spawned during -initial time-sync with master KDC will also run in debug mode. - -https://fedorahosted.org/freeipa/ticket/4931 - -Reviewed-By: Jan Cholasta -Reviewed-By: Martin Basti ---- - ipa-client/ipa-install/ipa-client-install | 5 +++-- - ipa-client/ipaclient/ntpconf.py | 7 +++++-- - 2 files changed, 8 insertions(+), 4 deletions(-) - -diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install -index a1564583ca2d461413da7ea5929b91851cd3f3e1..96b30b486585bc60b0882263cff58292a3538df9 100755 ---- a/ipa-client/ipa-install/ipa-client-install -+++ b/ipa-client/ipa-install/ipa-client-install -@@ -2388,12 +2388,13 @@ def install(options, env, fstore, statestore): - ntp_servers = options.ntp_servers - - for s in ntp_servers: -- synced_ntp = ipaclient.ntpconf.synconce_ntp(s) -+ synced_ntp = ipaclient.ntpconf.synconce_ntp(s, options.debug) - if synced_ntp: - break - - if not synced_ntp and not options.ntp_servers: -- synced_ntp = ipaclient.ntpconf.synconce_ntp(cli_server[0]) -+ synced_ntp = ipaclient.ntpconf.synconce_ntp(cli_server[0], -+ options.debug) - if not synced_ntp: - root_logger.warning("Unable to sync time with NTP " + - "server, assuming the time is in sync. Please check " + -diff --git a/ipa-client/ipaclient/ntpconf.py b/ipa-client/ipaclient/ntpconf.py -index c22fba401d33009b3b95d1418dc7c8a03328d569..9a7db6544b54288569dc7699e67ddc865bb88db4 100644 ---- a/ipa-client/ipaclient/ntpconf.py -+++ b/ipa-client/ipaclient/ntpconf.py -@@ -137,7 +137,7 @@ def config_ntp(ntp_servers, fstore = None, sysstore = None): - services.knownservices.ntpd.restart() - - --def synconce_ntp(server_fqdn): -+def synconce_ntp(server_fqdn, debug=False): - """ - Syncs time with specified server using ntpd. - Primarily designed to be used before Kerberos setup -@@ -150,13 +150,16 @@ def synconce_ntp(server_fqdn): - return False - - tmp_ntp_conf = ipautil.write_tmp_file('server %s' % server_fqdn) -+ args = [ntpd, '-qgc', tmp_ntp_conf.name] -+ if debug: -+ args.append('-d') - try: - # The ntpd command will never exit if it is unable to reach the - # server, so timeout after 15 seconds. - timeout = 15 - root_logger.info('Attempting to sync time using ntpd. ' - 'Will timeout after %d seconds' % timeout) -- ipautil.run([ntpd, '-qgc', tmp_ntp_conf.name], timeout=timeout) -+ ipautil.run(args, timeout=timeout) - return True - except ipautil.CalledProcessError: - return False --- -2.4.3 - diff --git a/SOURCES/0018-frontend-copy-command-arguments-to-output-params-on-.patch b/SOURCES/0018-frontend-copy-command-arguments-to-output-params-on-.patch new file mode 100644 index 0000000..64f030e --- /dev/null +++ b/SOURCES/0018-frontend-copy-command-arguments-to-output-params-on-.patch @@ -0,0 +1,39 @@ +From 1297d5f1ba731e81b03a2fca997487813a2e962a Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Mon, 18 Jul 2016 07:37:31 +0200 +Subject: [PATCH] frontend: copy command arguments to output params on client + +In commit f554078291d682d59956998af97f7d3066fbe7e7 we stopped copying +command arguments to output params in order to remove redundancies and +reduce API schema in size. Since then, output params were removed from +API schema completely and are reconstructed on the client. + +Not including arguments in output params hides failed members from member +commands' CLI output. To fix this, copy arguments to output params again, +but only on the client side. + +https://fedorahosted.org/freeipa/ticket/6026 + +Reviewed-By: Florence Blanc-Renaud +--- + ipaclient/frontend.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/ipaclient/frontend.py b/ipaclient/frontend.py +index e8eacc068f4bec5ccdb21228b32a88aea24424df..1525c88b3dfeadccd8115cb4b6ba149caef22103 100644 +--- a/ipaclient/frontend.py ++++ b/ipaclient/frontend.py +@@ -95,6 +95,10 @@ class ClientMethod(ClientCommand, Method): + + def get_output_params(self): + seen = set() ++ for param in self.params(): ++ if param.name not in self.obj.params: ++ seen.add(param.name) ++ yield param + for output_param in super(ClientMethod, self).get_output_params(): + seen.add(output_param.name) + yield output_param +-- +2.7.4 + diff --git a/SOURCES/0019-Show-full-error-message-for-selinuxusermap-add-hostg.patch b/SOURCES/0019-Show-full-error-message-for-selinuxusermap-add-hostg.patch new file mode 100644 index 0000000..ea161af --- /dev/null +++ b/SOURCES/0019-Show-full-error-message-for-selinuxusermap-add-hostg.patch @@ -0,0 +1,152 @@ +From b79d70c9977a9b5026f8976e172122bf78885dd8 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Wed, 20 Jul 2016 11:02:30 +0200 +Subject: [PATCH] Show full error message for selinuxusermap-add-hostgroup + +While investigating the issue for selinuxusermap-add-hostgroup, +we discovered that other commands were missing output. +A first patch fixes most of the issues: +freeipa-jcholast-677-frontend-copy-command-arguments-to-output-params-on-.patch + +This patch fixes servicedelegation CLI, where +servicedelegation.takes_params was missing +ipaallowedtarget_servicedelegationtarget, ipaallowedtoimpersonate and +memberprincipal + +https://fedorahosted.org/freeipa/ticket/6026 + +Reviewed-By: Jan Cholasta +--- + ipaserver/plugins/servicedelegation.py | 53 ++++++++++------------------------ + 1 file changed, 15 insertions(+), 38 deletions(-) + +diff --git a/ipaserver/plugins/servicedelegation.py b/ipaserver/plugins/servicedelegation.py +index 958c3b739a2dd465c2b685672c3deb1af8c36e4e..6f38c36a30363755c80081d02bf4c86d829eae34 100644 +--- a/ipaserver/plugins/servicedelegation.py ++++ b/ipaserver/plugins/servicedelegation.py +@@ -96,30 +96,6 @@ PROTECTED_CONSTRAINT_TARGETS = ( + ) + + +-output_params = ( +- Str( +- 'ipaallowedtarget_servicedelegationtarget', +- label=_('Allowed Target'), +- ), +- Str( +- 'ipaallowedtoimpersonate', +- label=_('Allowed to Impersonate'), +- ), +- Str( +- 'memberprincipal', +- label=_('Member principals'), +- ), +- Str( +- 'failed_memberprincipal', +- label=_('Failed members'), +- ), +- Str( +- 'ipaallowedtarget', +- label=_('Failed targets'), +- ), +-) +- +- + class servicedelegation(LDAPObject): + """ + Service Constrained Delegation base object. +@@ -175,6 +151,21 @@ class servicedelegation(LDAPObject): + label=_('Delegation name'), + primary_key=True, + ), ++ Str( ++ 'ipaallowedtarget_servicedelegationtarget', ++ label=_('Allowed Target'), ++ flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'}, ++ ), ++ Str( ++ 'ipaallowedtoimpersonate', ++ label=_('Allowed to Impersonate'), ++ flags={'no_create', 'no_update', 'no_search'}, ++ ), ++ Str( ++ 'memberprincipal', ++ label=_('Member principals'), ++ flags={'no_create', 'no_update', 'no_search'}, ++ ), + ) + + +@@ -186,8 +177,6 @@ class servicedelegation_add_member(LDAPAddMember): + principal_attr = 'memberprincipal' + principal_failedattr = 'failed_memberprincipal' + +- has_output_params = LDAPAddMember.has_output_params + output_params +- + def get_options(self): + for option in super(servicedelegation_add_member, self).get_options(): + yield option +@@ -268,8 +257,6 @@ class servicedelegation_remove_member(LDAPRemoveMember): + principal_attr = 'memberprincipal' + principal_failedattr = 'failed_memberprincipal' + +- has_output_params = LDAPRemoveMember.has_output_params + output_params +- + def get_options(self): + for option in super( + servicedelegation_remove_member, self).get_options(): +@@ -397,8 +384,6 @@ class servicedelegationrule_del(LDAPDelete): + class servicedelegationrule_find(LDAPSearch): + __doc__ = _('Search for service delegations rule.') + +- has_output_params = LDAPSearch.has_output_params + output_params +- + msg_summary = ngettext( + '%(count)d service delegation rule matched', + '%(count)d service delegation rules matched', 0 +@@ -409,8 +394,6 @@ class servicedelegationrule_find(LDAPSearch): + class servicedelegationrule_show(LDAPRetrieve): + __doc__ = _('Display information about a named service delegation rule.') + +- has_output_params = LDAPRetrieve.has_output_params + output_params +- + + @register() + class servicedelegationrule_add_member(servicedelegation_add_member): +@@ -437,7 +420,6 @@ class servicedelegationrule_add_target(LDAPAddMember): + attribute_members = { + 'ipaallowedtarget': ['servicedelegationtarget'], + } +- has_output_params = LDAPAddMember.has_output_params + output_params + + + @register() +@@ -447,7 +429,6 @@ class servicedelegationrule_remove_target(LDAPRemoveMember): + attribute_members = { + 'ipaallowedtarget': ['servicedelegationtarget'], + } +- has_output_params = LDAPRemoveMember.has_output_params + output_params + + + @register() +@@ -492,8 +473,6 @@ class servicedelegationtarget_del(LDAPDelete): + class servicedelegationtarget_find(LDAPSearch): + __doc__ = _('Search for service delegation target.') + +- has_output_params = LDAPSearch.has_output_params + output_params +- + msg_summary = ngettext( + '%(count)d service delegation target matched', + '%(count)d service delegation targets matched', 0 +@@ -530,8 +509,6 @@ class servicedelegationtarget_find(LDAPSearch): + class servicedelegationtarget_show(LDAPRetrieve): + __doc__ = _('Display information about a named service delegation target.') + +- has_output_params = LDAPRetrieve.has_output_params + output_params +- + + @register() + class servicedelegationtarget_add_member(servicedelegation_add_member): +-- +2.7.4 + diff --git a/SOURCES/0019-cermonger-Use-private-unix-socket-when-DBus-SystemBu.patch b/SOURCES/0019-cermonger-Use-private-unix-socket-when-DBus-SystemBu.patch deleted file mode 100644 index 364e464..0000000 --- a/SOURCES/0019-cermonger-Use-private-unix-socket-when-DBus-SystemBu.patch +++ /dev/null @@ -1,288 +0,0 @@ -From 3cec31570b04fa9ece1f3d02768a676c6c2f35ff Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Tue, 7 Jul 2015 15:49:27 +0200 -Subject: [PATCH] cermonger: Use private unix socket when DBus SystemBus is not - available. - -https://fedorahosted.org/freeipa/ticket/5095 - -Reviewed-By: Jan Cholasta ---- - ipaplatform/base/paths.py | 4 ++ - ipapython/certmonger.py | 137 +++++++++++++++++++++++++++++++--------------- - 2 files changed, 98 insertions(+), 43 deletions(-) - -diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py -index 9fef3e7a1351dd42895fe560bb3c1bc5a1c852b4..5756040172126438d42275b734f4d766d53048fe 100644 ---- a/ipaplatform/base/paths.py -+++ b/ipaplatform/base/paths.py -@@ -348,3 +348,7 @@ class BasePathNamespace(object): - BAK2DB = '/usr/sbin/bak2db' - DB2BAK = '/usr/sbin/db2bak' - KDCPROXY_CONFIG = '/etc/ipa/kdcproxy/kdcproxy.conf' -+ CERTMONGER = '/usr/sbin/certmonger' -+ -+ -+path_namespace = BasePathNamespace -diff --git a/ipapython/certmonger.py b/ipapython/certmonger.py -index 4baaaa85da08bb943d6b9f0091a1d2acc36b18d6..b37676872a8b983636c7b2dc5590e83c8b08ea98 100644 ---- a/ipapython/certmonger.py -+++ b/ipapython/certmonger.py -@@ -27,6 +27,8 @@ import sys - import time - import dbus - import shlex -+import subprocess -+import tempfile - from ipapython import ipautil - from ipapython import dogtag - from ipapython.ipa_log_manager import * -@@ -35,6 +37,7 @@ from ipaplatform import services - - DBUS_CM_PATH = '/org/fedorahosted/certmonger' - DBUS_CM_IF = 'org.fedorahosted.certmonger' -+DBUS_CM_NAME = 'org.fedorahosted.certmonger' - DBUS_CM_REQUEST_IF = 'org.fedorahosted.certmonger.request' - DBUS_CM_CA_IF = 'org.fedorahosted.certmonger.ca' - DBUS_PROPERTY_IF = 'org.freedesktop.DBus.Properties' -@@ -44,7 +47,7 @@ class _cm_dbus_object(object): - """ - Auxiliary class for convenient DBus object handling. - """ -- def __init__(self, bus, object_path, object_dbus_interface, -+ def __init__(self, bus, parent, object_path, object_dbus_interface, - parent_dbus_interface=None, property_interface=False): - """ - bus - DBus bus object, result of dbus.SystemBus() or dbus.SessionBus() -@@ -60,6 +63,7 @@ class _cm_dbus_object(object): - if parent_dbus_interface is None: - parent_dbus_interface = object_dbus_interface - self.bus = bus -+ self.parent = parent - self.path = object_path - self.obj_dbus_if = object_dbus_interface - self.parent_dbus_if = parent_dbus_interface -@@ -69,36 +73,83 @@ class _cm_dbus_object(object): - self.prop_if = dbus.Interface(self.obj, DBUS_PROPERTY_IF) - - --def _start_certmonger(): -- """ -- Start certmonger daemon. If it's already running systemctl just ignores -- the command. -- """ -- if not services.knownservices.certmonger.is_running(): -+class _certmonger(_cm_dbus_object): -+ """ -+ Create a connection to certmonger. -+ By default use SystemBus. When not available use private connection -+ over Unix socket. -+ This solution is really ugly and should be removed as soon as DBus -+ SystemBus is available at system install time. -+ """ -+ timeout = 300 -+ -+ def _start_private_conn(self): -+ sock_filename = os.path.join(tempfile.mkdtemp(), 'certmonger') -+ self._proc = subprocess.Popen([paths.CERTMONGER, '-n', '-L', '-P', -+ sock_filename]) -+ for t in range(0, self.timeout, 5): -+ if os.path.exists(sock_filename): -+ return "unix:path=%s" % sock_filename -+ time.sleep(5) -+ self._stop_private_conn() -+ raise RuntimeError("Failed to start certmonger: Timed out") -+ -+ def _stop_private_conn(self): -+ if self._proc: -+ retcode = self._proc.poll() -+ if retcode is not None: -+ return -+ self._proc.terminate() -+ for t in range(0, self.timeout, 5): -+ retcode = self._proc.poll() -+ if retcode is not None: -+ return -+ time.sleep(5) -+ root_logger.error("Failed to stop certmonger.") -+ -+ def __del__(self): -+ self._stop_private_conn() -+ -+ def __init__(self): -+ self._proc = None -+ self._bus = None - try: -- services.knownservices.certmonger.start() -- except Exception, e: -- root_logger.error('Failed to start certmonger: %s' % e) -- raise -- -- --def _connect_to_certmonger(): -- """ -- Start certmonger daemon and connect to it via DBus. -- """ -- try: -- _start_certmonger() -- except (KeyboardInterrupt, OSError), e: -- root_logger.error('Failed to start certmonger: %s' % e) -- raise -- -- try: -- bus = dbus.SystemBus() -- cm = _cm_dbus_object(bus, DBUS_CM_PATH, DBUS_CM_IF) -- except dbus.DBusException, e: -- root_logger.error("Failed to access certmonger over DBus: %s", e) -- raise -- return cm -+ self._bus = dbus.SystemBus() -+ except dbus.DBusException as e: -+ err_name = e.get_dbus_name() -+ if err_name not in ['org.freedesktop.DBus.Error.NoServer', -+ 'org.freedesktop.DBus.Error.FileNotFound']: -+ root_logger.error("Failed to connect to certmonger over " -+ "SystemBus: %s" % e) -+ raise -+ try: -+ self._private_sock = self._start_private_conn() -+ self._bus = dbus.connection.Connection(self._private_sock) -+ except dbus.DBusException as e: -+ root_logger.error("Failed to connect to certmonger over " -+ "private socket: %s" % e) -+ raise -+ else: -+ try: -+ self._bus.get_name_owner(DBUS_CM_NAME) -+ except dbus.DBusException: -+ try: -+ services.knownservices.certmonger.start() -+ except Exception as e: -+ root_logger.error("Failed to start certmonger: %s" % e) -+ raise -+ -+ for t in range(0, self.timeout, 5): -+ try: -+ self._bus.get_name_owner(DBUS_CM_NAME) -+ break -+ except dbus.DBusException: -+ pass -+ time.sleep(5) -+ raise RuntimeError('Failed to start certmonger') -+ -+ super(_certmonger, self).__init__(self._bus, None, DBUS_CM_PATH, -+ DBUS_CM_IF) - - - def _get_requests(criteria=dict()): -@@ -108,7 +159,7 @@ def _get_requests(criteria=dict()): - if not isinstance(criteria, dict): - raise TypeError('"criteria" must be dict.') - -- cm = _connect_to_certmonger() -+ cm = _certmonger() - requests = [] - requests_paths = [] - if 'nickname' in criteria: -@@ -119,12 +170,12 @@ def _get_requests(criteria=dict()): - requests_paths = cm.obj_if.get_requests() - - for request_path in requests_paths: -- request = _cm_dbus_object(cm.bus, request_path, DBUS_CM_REQUEST_IF, -+ request = _cm_dbus_object(cm.bus, cm, request_path, DBUS_CM_REQUEST_IF, - DBUS_CM_IF, True) - for criterion in criteria: - if criterion == 'ca-name': - ca_path = request.obj_if.get_ca() -- ca = _cm_dbus_object(cm.bus, ca_path, DBUS_CM_CA_IF, -+ ca = _cm_dbus_object(cm.bus, cm, ca_path, DBUS_CM_CA_IF, - DBUS_CM_IF) - value = ca.obj_if.get_nickname() - else: -@@ -133,6 +184,7 @@ def _get_requests(criteria=dict()): - break - else: - requests.append(request) -+ - return requests - - -@@ -166,7 +218,7 @@ def get_request_value(request_id, directive): - if request: - if directive == 'ca-name': - ca_path = request.obj_if.get_ca() -- ca = _cm_dbus_object(request.bus, ca_path, DBUS_CM_CA_IF, -+ ca = _cm_dbus_object(request.bus, request, ca_path, DBUS_CM_CA_IF, - DBUS_CM_IF) - return ca.obj_if.get_nickname() - else: -@@ -250,7 +302,7 @@ def request_cert(nssdb, nickname, subject, principal, passwd_fname=None): - """ - Execute certmonger to request a server certificate. - """ -- cm = _connect_to_certmonger() -+ cm = _certmonger() - ca_path = cm.obj_if.find_ca_by_nickname('IPA') - if not ca_path: - raise RuntimeError('IPA CA not found') -@@ -264,7 +316,7 @@ def request_cert(nssdb, nickname, subject, principal, passwd_fname=None): - result = cm.obj_if.add_request(request_parameters) - try: - if result[0]: -- request = _cm_dbus_object(cm.bus, result[1], DBUS_CM_REQUEST_IF, -+ request = _cm_dbus_object(cm.bus, cm, result[1], DBUS_CM_REQUEST_IF, - DBUS_CM_IF, True) - except TypeError: - root_logger.error('Failed to get create new request.') -@@ -283,7 +335,7 @@ def start_tracking(nickname, secdir, password_file=None, command=None): - - Returns certificate nickname. - """ -- cm = _connect_to_certmonger() -+ cm = _certmonger() - params = {'TRACK': True} - params['cert-nickname'] = nickname - params['cert-database'] = os.path.abspath(secdir) -@@ -302,7 +354,7 @@ def start_tracking(nickname, secdir, password_file=None, command=None): - result = cm.obj_if.add_request(params) - try: - if result[0]: -- request = _cm_dbus_object(cm.bus, result[1], DBUS_CM_REQUEST_IF, -+ request = _cm_dbus_object(cm.bus, cm, result[1], DBUS_CM_REQUEST_IF, - DBUS_CM_IF, True) - except TypeError, e: - root_logger.error('Failed to add new request.') -@@ -330,8 +382,7 @@ def stop_tracking(secdir, request_id=None, nickname=None): - root_logger.error('Failed to get request: %s' % e) - raise - if request: -- cm = _connect_to_certmonger() -- cm.obj_if.remove_request(request.path) -+ request.parent.obj_if.remove_request(request.path) - - - def modify(request_id, profile=None): -@@ -357,9 +408,9 @@ def _find_IPA_ca(): - We can use find_request_value because the ca files have the - same file format. - """ -- cm = _connect_to_certmonger() -+ cm = _certmonger() - ca_path = cm.obj_if.find_ca_by_nickname('IPA') -- return _cm_dbus_object(cm.bus, ca_path, DBUS_CM_CA_IF, DBUS_CM_IF, True) -+ return _cm_dbus_object(cm.bus, cm, ca_path, DBUS_CM_CA_IF, DBUS_CM_IF, True) - - - def add_principal_to_cas(principal): -@@ -423,7 +474,7 @@ def dogtag_start_tracking(ca, nickname, pin, pinfile, secdir, pre_command, - Both commands can be None. - """ - -- cm = _connect_to_certmonger() -+ cm = _certmonger() - certmonger_cmd_template = paths.CERTMONGER_COMMAND_TEMPLATE - - params = {'TRACK': True} --- -2.4.3 - diff --git a/SOURCES/0020-allow-value-output-param-in-commands-without-primary.patch b/SOURCES/0020-allow-value-output-param-in-commands-without-primary.patch new file mode 100644 index 0000000..6c91a7f --- /dev/null +++ b/SOURCES/0020-allow-value-output-param-in-commands-without-primary.patch @@ -0,0 +1,157 @@ +From 829e708bf22e80373f1af167fbfb3e6b6bf8655e Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Mon, 18 Jul 2016 13:18:44 +0200 +Subject: [PATCH] allow 'value' output param in commands without primary key + +`PrimaryKey` output param works only for API objects that have primary keys, +otherwise it expects None (nothing is associated with this param). Since the +validation of command output was tightened durng thin client effort, some +commands not honoring this contract began to fail output validation. + +A custom output was implemented for them to restore their functionality. It +should however be considered as a fix for broken commands and not used +further. + +https://fedorahosted.org/freeipa/ticket/6037 +https://fedorahosted.org/freeipa/ticket/6061 + +Reviewed-By: Alexander Bokovoy +Reviewed-By: Jan Cholasta +--- + API.txt | 10 +++++----- + VERSION | 4 ++-- + ipalib/output.py | 10 ++++++++++ + ipaserver/plugins/automember.py | 3 +++ + ipaserver/plugins/trust.py | 2 ++ + 5 files changed, 22 insertions(+), 7 deletions(-) + +diff --git a/API.txt b/API.txt +index eb33c1fb7f94f5af45ec0b38fc7e45e484a1044e..535d8ec9a4990395207e2455a09a8c1bdef5529a 100644 +--- a/API.txt ++++ b/API.txt +@@ -144,7 +144,7 @@ option: StrEnum('type', values=[u'group', u'hostgroup']) + option: Str('version?') + output: Entry('result') + output: Output('summary', type=[, ]) +-output: PrimaryKey('value') ++output: Output('value', type=[]) + command: automember_default_group_set/1 + args: 0,6,3 + option: Flag('all', autofill=True, cli_name='all', default=False) +@@ -155,7 +155,7 @@ option: StrEnum('type', values=[u'group', u'hostgroup']) + option: Str('version?') + output: Entry('result') + output: Output('summary', type=[, ]) +-output: PrimaryKey('value') ++output: Output('value', type=[]) + command: automember_default_group_show/1 + args: 0,4,3 + option: Flag('all', autofill=True, cli_name='all', default=False) +@@ -164,7 +164,7 @@ option: StrEnum('type', values=[u'group', u'hostgroup']) + option: Str('version?') + output: Entry('result') + output: Output('summary', type=[, ]) +-output: PrimaryKey('value') ++output: Output('value', type=[]) + command: automember_del/1 + args: 1,2,3 + arg: Str('cn+', cli_name='automember_rule') +@@ -5574,7 +5574,7 @@ option: StrEnum('trust_type', autofill=True, cli_name='type', default=u'ad', val + option: Str('version?') + output: Entry('result') + output: Output('summary', type=[, ]) +-output: PrimaryKey('value') ++output: Output('value', type=[]) + command: trustconfig_show/1 + args: 0,5,3 + option: Flag('all', autofill=True, cli_name='all', default=False) +@@ -5584,7 +5584,7 @@ option: StrEnum('trust_type', autofill=True, cli_name='type', default=u'ad', val + option: Str('version?') + output: Entry('result') + output: Output('summary', type=[, ]) +-output: PrimaryKey('value') ++output: Output('value', type=[]) + command: trustdomain_add/1 + args: 2,8,3 + arg: Str('trustcn', cli_name='trust') +diff --git a/VERSION b/VERSION +index 0559741451a858dd0adfa99a8bf653261d771601..ca489965050f32d2d8987dfd251ec2b2a0ba1768 100644 +--- a/VERSION ++++ b/VERSION +@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 + # # + ######################################################## + IPA_API_VERSION_MAJOR=2 +-IPA_API_VERSION_MINOR=210 +-# Last change: Add --ca option to cert-status ++IPA_API_VERSION_MINOR=211 ++# Last change: mbabinsk: allow 'value' output param in commands without primary key +diff --git a/ipalib/output.py b/ipalib/output.py +index 19dd9adadeb8521caf9f0dc52981ce57a7f0c8b6..b104584631629f33280164dd1d23922d21ddea49 100644 +--- a/ipalib/output.py ++++ b/ipalib/output.py +@@ -217,3 +217,13 @@ simple_value = ( + Output('result', bool, _('True means the operation was successful')), + Output('value', unicode, flags=['no_display']), + ) ++ ++# custom shim for commands like `trustconfig-show`, ++# `automember-default-group-*` which put stuff into output['value'] despite not ++# having primary key themselves. Designing commands like this is not a very ++# good practice, so please do not use this for new code. ++simple_entry = ( ++ summary, ++ Entry('result'), ++ Output('value', unicode, flags=['no_display']), ++) +diff --git a/ipaserver/plugins/automember.py b/ipaserver/plugins/automember.py +index dfa8498a6bd44352d854bff7f8eedaba8f731eef..8e9356a9d30c98b7c72735ffb9ac05c672546a0d 100644 +--- a/ipaserver/plugins/automember.py ++++ b/ipaserver/plugins/automember.py +@@ -586,6 +586,7 @@ class automember_default_group_set(LDAPUpdate): + ), + ) + group_type + msg_summary = _('Set default (fallback) group for automember "%(value)s"') ++ has_output = output.simple_entry + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + dn = DN(('cn', options['type']), api.env.container_automember, +@@ -609,6 +610,7 @@ class automember_default_group_remove(LDAPUpdate): + + takes_options = group_type + msg_summary = _('Removed default (fallback) group for automember "%(value)s"') ++ has_output = output.simple_entry + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + dn = DN(('cn', options['type']), api.env.container_automember, +@@ -644,6 +646,7 @@ class automember_default_group_show(LDAPRetrieve): + obj_name = 'automember_default_group' + + takes_options = group_type ++ has_output = output.simple_entry + + def pre_callback(self, ldap, dn, attrs_list, *keys, **options): + dn = DN(('cn', options['type']), api.env.container_automember, +diff --git a/ipaserver/plugins/trust.py b/ipaserver/plugins/trust.py +index 8536202b9b785507bd27b3c7b1896b721f8c5927..d4676bd57054043edd07da5ec3321d755babf35c 100644 +--- a/ipaserver/plugins/trust.py ++++ b/ipaserver/plugins/trust.py +@@ -1288,6 +1288,7 @@ class trustconfig_mod(LDAPUpdate): + + takes_options = LDAPUpdate.takes_options + (_trust_type_option,) + msg_summary = _('Modified "%(value)s" trust configuration') ++ has_output = output.simple_entry + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + self.obj._normalize_groupdn(entry_attrs) +@@ -1310,6 +1311,7 @@ class trustconfig_show(LDAPRetrieve): + __doc__ = _('Show global trust configuration.') + + takes_options = LDAPRetrieve.takes_options + (_trust_type_option,) ++ has_output = output.simple_entry + + def execute(self, *keys, **options): + result = super(trustconfig_show, self).execute(*keys, **options) +-- +2.7.4 + diff --git a/SOURCES/0020-ipa-client-install-Do-not-re-start-certmonger-and-DB.patch b/SOURCES/0020-ipa-client-install-Do-not-re-start-certmonger-and-DB.patch deleted file mode 100644 index 5e5ef43..0000000 --- a/SOURCES/0020-ipa-client-install-Do-not-re-start-certmonger-and-DB.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 42353682a3d9e92f4053877d66f54e44f516bb53 Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Tue, 7 Jul 2015 15:49:51 +0200 -Subject: [PATCH] ipa-client-install: Do not (re)start certmonger and DBus - daemons. - -When DBus is present in the system it is always running. - -Starting of certmomger is handled in ipapython/certmonger.py module if -necessary. Restarting is no longer needed since freeipa is not changing -certmonger's files. - -https://fedorahosted.org/freeipa/ticket/5095 - -Reviewed-By: Jan Cholasta ---- - ipa-client/ipa-install/ipa-client-install | 71 +++++++------------------------ - 1 file changed, 15 insertions(+), 56 deletions(-) - -diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install -index 96b30b486585bc60b0882263cff58292a3538df9..91323ae115a27d221bcbc43fee887c56d99c8635 100755 ---- a/ipa-client/ipa-install/ipa-client-install -+++ b/ipa-client/ipa-install/ipa-client-install -@@ -522,20 +522,7 @@ def uninstall(options, env): - ipa_db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR) - sys_db = certdb.NSSDatabase(paths.NSS_DB_DIR) - -- # Always start certmonger. We can't untrack something if it isn't -- # running -- messagebus = services.knownservices.messagebus -- try: -- messagebus.start() -- except Exception, e: -- log_service_error(messagebus.service_name, 'start', e) -- - cmonger = services.knownservices.certmonger -- try: -- cmonger.start() -- except Exception, e: -- log_service_error(cmonger.service_name, 'start', e) -- - if ipa_db.has_nickname('Local IPA host'): - try: - certmonger.stop_tracking(paths.IPA_NSSDB_DIR, -@@ -576,14 +563,14 @@ def uninstall(options, env): - nickname, sys_db.secdir, e) - break - -+ # Remove any special principal names we added to the IPA CA helper -+ certmonger.remove_principal_from_cas() -+ - try: - cmonger.stop() - except Exception, e: - log_service_error(cmonger.service_name, 'stop', e) - -- # Remove any special principal names we added to the IPA CA helper -- certmonger.remove_principal_from_cas() -- - try: - cmonger.disable() - except Exception, e: -@@ -1138,41 +1125,14 @@ def configure_certmonger(fstore, subject_base, cli_realm, hostname, options, - "Not requesting host certificate.") - return - -- started = True - principal = 'host/%s@%s' % (hostname, cli_realm) - -- messagebus = services.knownservices.messagebus -- try: -- messagebus.start() -- except Exception, e: -- log_service_error(messagebus.service_name, 'start', e) -- -- # Ensure that certmonger has been started at least once to generate the -- # cas files in /var/lib/certmonger/cas. -- cmonger = services.knownservices.certmonger -- try: -- cmonger.restart() -- except Exception, e: -- log_service_error(cmonger.service_name, 'restart', e) -- - if options.hostname: -- # It needs to be stopped if we touch them -- try: -- cmonger.stop() -- except Exception, e: -- log_service_error(cmonger.service_name, 'stop', e) - # If the hostname is explicitly set then we need to tell certmonger - # which principal name to use when requesting certs. - certmonger.add_principal_to_cas(principal) - -- try: -- cmonger.restart() -- except Exception, e: -- log_service_error(cmonger.service_name, 'restart', e) -- root_logger.warning( -- "Automatic certificate management will not be available") -- started = False -- -+ cmonger = services.knownservices.certmonger - try: - cmonger.enable() - except Exception, e: -@@ -1183,18 +1143,17 @@ def configure_certmonger(fstore, subject_base, cli_realm, hostname, options, - "Automatic certificate management will not be available") - - # Request our host cert -- if started: -- subject = str(DN(('CN', hostname), subject_base)) -- passwd_fname = os.path.join(paths.IPA_NSSDB_DIR, 'pwdfile.txt') -- try: -- certmonger.request_cert(nssdb=paths.IPA_NSSDB_DIR, -- nickname='Local IPA host', -- subject=subject, -- principal=principal, -- passwd_fname=passwd_fname) -- except Exception: -- root_logger.error("%s request for host certificate failed", -- cmonger.service_name) -+ subject = str(DN(('CN', hostname), subject_base)) -+ passwd_fname = os.path.join(paths.IPA_NSSDB_DIR, 'pwdfile.txt') -+ try: -+ certmonger.request_cert(nssdb=paths.IPA_NSSDB_DIR, -+ nickname='Local IPA host', -+ subject=subject, -+ principal=principal, -+ passwd_fname=passwd_fname) -+ except Exception: -+ root_logger.error("%s request for host certificate failed", -+ cmonger.service_name) - - def configure_sssd_conf(fstore, cli_realm, cli_domain, cli_server, options, client_domain, client_hostname): - try: --- -2.4.3 - diff --git a/SOURCES/0021-DNS-Consolidate-DNS-RR-types-in-API-and-schema.patch b/SOURCES/0021-DNS-Consolidate-DNS-RR-types-in-API-and-schema.patch deleted file mode 100644 index 5aa37bd..0000000 --- a/SOURCES/0021-DNS-Consolidate-DNS-RR-types-in-API-and-schema.patch +++ /dev/null @@ -1,503 +0,0 @@ -From eeec6dd88ea1e6f2c24ee87d70a8d6aa98cbd0e4 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Wed, 15 Jul 2015 09:44:07 +0200 -Subject: [PATCH] DNS: Consolidate DNS RR types in API and schema - -* Remove NSEC3, DNSKEY, TSIG, TKEY, TA records from API: - These records never worked, they dont have attributes in schema. - TSIG and TKEY are meta-RR should not be in LDAP - TA is not supported by BIND - NSEC3, DNSKEY are DNSSEC records generated by BIND, should not be - in LDAP. - *! SIG, NSEC are already defined in schema, must stay in API. - -* Add HINFO, MINFO, MD, NXT records to API as unsupported records - These records are already defined in LDAP schema - -* Add schema for RP, APL, IPSEC, DHCID, HIP, SPF records - These records were defined in IPA API as unsupported, but schema definition was - missing. This causes that ACI cannot be created for these records - and dnszone-find failed. (#5055) - -https://fedorahosted.org/freeipa/ticket/4934 -https://fedorahosted.org/freeipa/ticket/5055 - -Reviewed-By: Martin Babinsky -Reviewed-By: Petr Spacek ---- - ACI.txt | 4 +- - API.txt | 28 ++---------- - VERSION | 4 +- - install/share/60ipadns.ldif | 8 +++- - install/share/dns.ldif | 2 +- - install/updates/40-dns.update | 4 +- - ipalib/plugins/dns.py | 101 ++++++++++++++++++++++-------------------- - 7 files changed, 71 insertions(+), 80 deletions(-) - -diff --git a/ACI.txt b/ACI.txt -index 76a7ff70e27c032bdd8fa26e076271e02b23d3b3..60607b98deb74d0b7f45d24ee9359b0cf8162b0d 100644 ---- a/ACI.txt -+++ b/ACI.txt -@@ -61,13 +61,13 @@ aci: (targetattr = "ipaprivatekey || ipapublickey || ipasecretkey || ipasecretke - dn: dc=ipa,dc=example - aci: (targetattr = "cn || idnssecalgorithm || idnsseckeyactivate || idnsseckeycreated || idnsseckeydelete || idnsseckeyinactive || idnsseckeypublish || idnsseckeyref || idnsseckeyrevoke || idnsseckeysep || idnsseckeyzone || objectclass")(target = "ldap:///cn=dns,dc=ipa,dc=example")(targetfilter = "(objectclass=idnsSecKey)")(version 3.0;acl "permission:System: Manage DNSSEC metadata";allow (all) groupdn = "ldap:///cn=System: Manage DNSSEC metadata,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: dc=ipa,dc=example --aci: (targetattr = "a6record || aaaarecord || afsdbrecord || arecord || certrecord || cn || cnamerecord || createtimestamp || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || entryusn || hinforecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || modifytimestamp || mxrecord || naptrrecord || nsec3paramrecord || nsecrecord || nsrecord || nxtrecord || objectclass || ptrrecord || rrsigrecord || sigrecord || srvrecord || sshfprecord || tlsarecord || txtrecord || unknownrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example")(version 3.0;acl "permission:System: Read DNS Entries";allow (compare,read,search) groupdn = "ldap:///cn=System: Read DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+aci: (targetattr = "a6record || aaaarecord || afsdbrecord || aplrecord || arecord || certrecord || cn || cnamerecord || createtimestamp || dhcidrecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || entryusn || hinforecord || hiprecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || ipseckeyrecord || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || modifytimestamp || mxrecord || naptrrecord || nsec3paramrecord || nsecrecord || nsrecord || nxtrecord || objectclass || ptrrecord || rprecord || rrsigrecord || sigrecord || spfrecord || srvrecord || sshfprecord || tlsarecord || txtrecord || unknownrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example")(version 3.0;acl "permission:System: Read DNS Entries";allow (compare,read,search) groupdn = "ldap:///cn=System: Read DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: dc=ipa,dc=example - aci: (targetattr = "cn || createtimestamp || entryusn || idnssecalgorithm || idnsseckeyactivate || idnsseckeycreated || idnsseckeydelete || idnsseckeyinactive || idnsseckeypublish || idnsseckeyref || idnsseckeyrevoke || idnsseckeysep || idnsseckeyzone || modifytimestamp || objectclass")(target = "ldap:///cn=dns,dc=ipa,dc=example")(targetfilter = "(objectclass=idnsSecKey)")(version 3.0;acl "permission:System: Read DNSSEC metadata";allow (compare,read,search) groupdn = "ldap:///cn=System: Read DNSSEC metadata,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: dc=ipa,dc=example - aci: (target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example")(version 3.0;acl "permission:System: Remove DNS Entries";allow (delete) groupdn = "ldap:///cn=System: Remove DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: dc=ipa,dc=example --aci: (targetattr = "a6record || aaaarecord || afsdbrecord || arecord || certrecord || cn || cnamerecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || mxrecord || naptrrecord || nsec3paramrecord || nsecrecord || nsrecord || nxtrecord || ptrrecord || rrsigrecord || sigrecord || srvrecord || sshfprecord || tlsarecord || txtrecord || unknownrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example")(version 3.0;acl "permission:System: Update DNS Entries";allow (write) groupdn = "ldap:///cn=System: Update DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+aci: (targetattr = "a6record || aaaarecord || afsdbrecord || aplrecord || arecord || certrecord || cn || cnamerecord || dhcidrecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || hiprecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || ipseckeyrecord || keyrecord || kxrecord || locrecord || managedby || mdrecord || minforecord || mxrecord || naptrrecord || nsec3paramrecord || nsecrecord || nsrecord || nxtrecord || ptrrecord || rprecord || rrsigrecord || sigrecord || spfrecord || srvrecord || sshfprecord || tlsarecord || txtrecord || unknownrecord")(target = "ldap:///idnsname=*,cn=dns,dc=ipa,dc=example")(version 3.0;acl "permission:System: Update DNS Entries";allow (write) groupdn = "ldap:///cn=System: Update DNS Entries,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: cn=groups,cn=accounts,dc=ipa,dc=example - aci: (targetfilter = "(|(objectclass=ipausergroup)(objectclass=posixgroup))")(version 3.0;acl "permission:System: Add Groups";allow (add) groupdn = "ldap:///cn=System: Add Groups,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: cn=groups,cn=accounts,dc=ipa,dc=example -diff --git a/API.txt b/API.txt -index c68bee94e3a9ed6182f6bd2152070222e32c7532..6ab30ddab41715fdbccb4f37aa1852621bca62b4 100644 ---- a/API.txt -+++ b/API.txt -@@ -1054,7 +1054,7 @@ output: Entry('result', , Gettext('A dictionary representing an LDA - output: Output('summary', (, ), None) - output: PrimaryKey('value', None, None) - command: dnsrecord_add --args: 2,100,3 -+args: 2,95,3 - arg: DNSNameParam('dnszoneidnsname', cli_name='dnszone', multivalue=False, only_absolute=True, primary_key=True, query=True, required=True) - arg: DNSNameParam('idnsname', attribute=True, cli_name='name', multivalue=False, primary_key=True, required=True) - option: Str('a6_part_data', attribute=False, cli_name='a6_data', multivalue=False, option_group=u'A6 Record', required=False) -@@ -1087,7 +1087,6 @@ option: DLVRecord('dlvrecord', attribute=True, cli_name='dlv_rec', csv=True, mul - option: DNSNameParam('dname_part_target', attribute=False, cli_name='dname_target', multivalue=False, option_group=u'DNAME Record', required=False) - option: DNAMERecord('dnamerecord', attribute=True, cli_name='dname_rec', csv=True, multivalue=True, option_group=u'DNAME Record', required=False) - option: StrEnum('dnsclass', attribute=True, cli_name='class', multivalue=False, required=False, values=(u'IN', u'CS', u'CH', u'HS')) --option: DNSKEYRecord('dnskeyrecord', attribute=True, cli_name='dnskey_rec', csv=True, multivalue=True, option_group=u'DNSKEY Record', required=False) - option: Int('dnsttl', attribute=True, cli_name='ttl', multivalue=False, required=False) - option: Int('ds_part_algorithm', attribute=False, cli_name='ds_algorithm', maxvalue=255, minvalue=0, multivalue=False, option_group=u'DS Record', required=False) - option: Str('ds_part_digest', attribute=False, cli_name='ds_digest', multivalue=False, option_group=u'DS Record', pattern='^[0-9a-fA-F]+$', required=False) -@@ -1125,7 +1124,6 @@ option: Str('naptr_part_replacement', attribute=False, cli_name='naptr_replaceme - option: Str('naptr_part_service', attribute=False, cli_name='naptr_service', multivalue=False, option_group=u'NAPTR Record', required=False) - option: NAPTRRecord('naptrrecord', attribute=True, cli_name='naptr_rec', csv=True, multivalue=True, option_group=u'NAPTR Record', required=False) - option: DNSNameParam('ns_part_hostname', attribute=False, cli_name='ns_hostname', multivalue=False, option_group=u'NS Record', required=False) --option: NSEC3Record('nsec3record', attribute=True, cli_name='nsec3_rec', csv=True, multivalue=True, option_group=u'NSEC3 Record', required=False) - option: NSECRecord('nsecrecord', attribute=True, cli_name='nsec_rec', csv=True, multivalue=True, option_group=u'NSEC Record', required=False) - option: NSRecord('nsrecord', attribute=True, cli_name='ns_rec', csv=True, multivalue=True, option_group=u'NS Record', required=False) - option: DNSNameParam('ptr_part_hostname', attribute=False, cli_name='ptr_hostname', multivalue=False, option_group=u'PTR Record', required=False) -@@ -1146,14 +1144,11 @@ option: Str('sshfp_part_fingerprint', attribute=False, cli_name='sshfp_fingerpri - option: Int('sshfp_part_fp_type', attribute=False, cli_name='sshfp_fp_type', maxvalue=255, minvalue=0, multivalue=False, option_group=u'SSHFP Record', required=False) - option: SSHFPRecord('sshfprecord', attribute=True, cli_name='sshfp_rec', csv=True, multivalue=True, option_group=u'SSHFP Record', required=False) - option: Flag('structured', autofill=True, default=False) --option: TARecord('tarecord', attribute=True, cli_name='ta_rec', csv=True, multivalue=True, option_group=u'TA Record', required=False) --option: TKEYRecord('tkeyrecord', attribute=True, cli_name='tkey_rec', csv=True, multivalue=True, option_group=u'TKEY Record', required=False) - option: Str('tlsa_part_cert_association_data', attribute=False, cli_name='tlsa_cert_association_data', multivalue=False, option_group=u'TLSA Record', required=False) - option: Int('tlsa_part_cert_usage', attribute=False, cli_name='tlsa_cert_usage', maxvalue=255, minvalue=0, multivalue=False, option_group=u'TLSA Record', required=False) - option: Int('tlsa_part_matching_type', attribute=False, cli_name='tlsa_matching_type', maxvalue=255, minvalue=0, multivalue=False, option_group=u'TLSA Record', required=False) - option: Int('tlsa_part_selector', attribute=False, cli_name='tlsa_selector', maxvalue=255, minvalue=0, multivalue=False, option_group=u'TLSA Record', required=False) - option: TLSARecord('tlsarecord', attribute=True, cli_name='tlsa_rec', csv=True, multivalue=True, option_group=u'TLSA Record', required=False) --option: TSIGRecord('tsigrecord', attribute=True, cli_name='tsig_rec', csv=True, multivalue=True, option_group=u'TSIG Record', required=False) - option: Str('txt_part_data', attribute=False, cli_name='txt_data', multivalue=False, option_group=u'TXT Record', required=False) - option: TXTRecord('txtrecord', attribute=True, cli_name='txt_rec', csv=True, multivalue=True, option_group=u'TXT Record', required=False) - option: Str('version?', exclude='webui') -@@ -1161,7 +1156,7 @@ output: Entry('result', , Gettext('A dictionary representing an LDA - output: Output('summary', (, ), None) - output: PrimaryKey('value', None, None) - command: dnsrecord_del --args: 2,39,3 -+args: 2,34,3 - arg: DNSNameParam('dnszoneidnsname', cli_name='dnszone', multivalue=False, only_absolute=True, primary_key=True, query=True, required=True) - arg: DNSNameParam('idnsname', attribute=True, cli_name='name', multivalue=False, primary_key=True, query=True, required=True) - option: A6Record('a6record', attribute=True, autofill=False, cli_name='a6_rec', csv=True, multivalue=True, option_group=None, required=False) -@@ -1176,7 +1171,6 @@ option: DHCIDRecord('dhcidrecord', attribute=True, autofill=False, cli_name='dhc - option: DLVRecord('dlvrecord', attribute=True, autofill=False, cli_name='dlv_rec', csv=True, multivalue=True, option_group=None, required=False) - option: DNAMERecord('dnamerecord', attribute=True, autofill=False, cli_name='dname_rec', csv=True, multivalue=True, option_group=None, required=False) - option: StrEnum('dnsclass', attribute=True, autofill=False, cli_name='class', multivalue=False, required=False, values=(u'IN', u'CS', u'CH', u'HS')) --option: DNSKEYRecord('dnskeyrecord', attribute=True, autofill=False, cli_name='dnskey_rec', csv=True, multivalue=True, option_group=None, required=False) - option: Int('dnsttl', attribute=True, autofill=False, cli_name='ttl', multivalue=False, required=False) - option: DSRecord('dsrecord', attribute=True, autofill=False, cli_name='ds_rec', csv=True, multivalue=True, option_group=None, required=False) - option: HIPRecord('hiprecord', attribute=True, autofill=False, cli_name='hip_rec', csv=True, multivalue=True, option_group=None, required=False) -@@ -1186,7 +1180,6 @@ option: KXRecord('kxrecord', attribute=True, autofill=False, cli_name='kx_rec', - option: LOCRecord('locrecord', attribute=True, autofill=False, cli_name='loc_rec', csv=True, multivalue=True, option_group=None, required=False) - option: MXRecord('mxrecord', attribute=True, autofill=False, cli_name='mx_rec', csv=True, multivalue=True, option_group=None, required=False) - option: NAPTRRecord('naptrrecord', attribute=True, autofill=False, cli_name='naptr_rec', csv=True, multivalue=True, option_group=None, required=False) --option: NSEC3Record('nsec3record', attribute=True, autofill=False, cli_name='nsec3_rec', csv=True, multivalue=True, option_group=None, required=False) - option: NSECRecord('nsecrecord', attribute=True, autofill=False, cli_name='nsec_rec', csv=True, multivalue=True, option_group=None, required=False) - option: NSRecord('nsrecord', attribute=True, autofill=False, cli_name='ns_rec', csv=True, multivalue=True, option_group=None, required=False) - option: PTRRecord('ptrrecord', attribute=True, autofill=False, cli_name='ptr_rec', csv=True, multivalue=True, option_group=None, required=False) -@@ -1197,10 +1190,7 @@ option: SPFRecord('spfrecord', attribute=True, autofill=False, cli_name='spf_rec - option: SRVRecord('srvrecord', attribute=True, autofill=False, cli_name='srv_rec', csv=True, multivalue=True, option_group=None, required=False) - option: SSHFPRecord('sshfprecord', attribute=True, autofill=False, cli_name='sshfp_rec', csv=True, multivalue=True, option_group=None, required=False) - option: Flag('structured', autofill=True, default=False) --option: TARecord('tarecord', attribute=True, autofill=False, cli_name='ta_rec', csv=True, multivalue=True, option_group=None, required=False) --option: TKEYRecord('tkeyrecord', attribute=True, autofill=False, cli_name='tkey_rec', csv=True, multivalue=True, option_group=None, required=False) - option: TLSARecord('tlsarecord', attribute=True, autofill=False, cli_name='tlsa_rec', csv=True, multivalue=True, option_group=None, required=False) --option: TSIGRecord('tsigrecord', attribute=True, autofill=False, cli_name='tsig_rec', csv=True, multivalue=True, option_group=None, required=False) - option: TXTRecord('txtrecord', attribute=True, autofill=False, cli_name='txt_rec', csv=True, multivalue=True, option_group=None, required=False) - option: Str('version?', exclude='webui') - output: Output('result', , None) -@@ -1216,7 +1206,7 @@ output: Output('result', , None) - output: Output('summary', (, ), None) - output: ListOfPrimaryKeys('value', None, None) - command: dnsrecord_find --args: 2,44,4 -+args: 2,39,4 - arg: DNSNameParam('dnszoneidnsname', cli_name='dnszone', multivalue=False, only_absolute=True, primary_key=True, query=True, required=True) - arg: Str('criteria?', noextrawhitespace=False) - option: A6Record('a6record', attribute=True, autofill=False, cli_name='a6_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) -@@ -1231,7 +1221,6 @@ option: DHCIDRecord('dhcidrecord', attribute=True, autofill=False, cli_name='dhc - option: DLVRecord('dlvrecord', attribute=True, autofill=False, cli_name='dlv_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: DNAMERecord('dnamerecord', attribute=True, autofill=False, cli_name='dname_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: StrEnum('dnsclass', attribute=True, autofill=False, cli_name='class', multivalue=False, query=True, required=False, values=(u'IN', u'CS', u'CH', u'HS')) --option: DNSKEYRecord('dnskeyrecord', attribute=True, autofill=False, cli_name='dnskey_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: Int('dnsttl', attribute=True, autofill=False, cli_name='ttl', multivalue=False, query=True, required=False) - option: DSRecord('dsrecord', attribute=True, autofill=False, cli_name='ds_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: HIPRecord('hiprecord', attribute=True, autofill=False, cli_name='hip_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) -@@ -1242,7 +1231,6 @@ option: KXRecord('kxrecord', attribute=True, autofill=False, cli_name='kx_rec', - option: LOCRecord('locrecord', attribute=True, autofill=False, cli_name='loc_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: MXRecord('mxrecord', attribute=True, autofill=False, cli_name='mx_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: NAPTRRecord('naptrrecord', attribute=True, autofill=False, cli_name='naptr_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) --option: NSEC3Record('nsec3record', attribute=True, autofill=False, cli_name='nsec3_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: NSECRecord('nsecrecord', attribute=True, autofill=False, cli_name='nsec_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: NSRecord('nsrecord', attribute=True, autofill=False, cli_name='ns_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: Flag('pkey_only?', autofill=True, default=False) -@@ -1256,11 +1244,8 @@ option: SPFRecord('spfrecord', attribute=True, autofill=False, cli_name='spf_rec - option: SRVRecord('srvrecord', attribute=True, autofill=False, cli_name='srv_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: SSHFPRecord('sshfprecord', attribute=True, autofill=False, cli_name='sshfp_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: Flag('structured', autofill=True, default=False) --option: TARecord('tarecord', attribute=True, autofill=False, cli_name='ta_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: Int('timelimit?', autofill=False, minvalue=0) --option: TKEYRecord('tkeyrecord', attribute=True, autofill=False, cli_name='tkey_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: TLSARecord('tlsarecord', attribute=True, autofill=False, cli_name='tlsa_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) --option: TSIGRecord('tsigrecord', attribute=True, autofill=False, cli_name='tsig_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: TXTRecord('txtrecord', attribute=True, autofill=False, cli_name='txt_rec', csv=True, multivalue=True, option_group=None, query=True, required=False) - option: Str('version?', exclude='webui') - output: Output('count', , None) -@@ -1268,7 +1253,7 @@ output: ListOfEntries('result', (, ), Gettext('A list - output: Output('summary', (, ), None) - output: Output('truncated', , None) - command: dnsrecord_mod --args: 2,100,3 -+args: 2,95,3 - arg: DNSNameParam('dnszoneidnsname', cli_name='dnszone', multivalue=False, only_absolute=True, primary_key=True, query=True, required=True) - arg: DNSNameParam('idnsname', attribute=True, cli_name='name', multivalue=False, primary_key=True, query=True, required=True) - option: Str('a6_part_data', attribute=False, autofill=False, cli_name='a6_data', multivalue=False, option_group=u'A6 Record', required=False) -@@ -1300,7 +1285,6 @@ option: DLVRecord('dlvrecord', attribute=True, autofill=False, cli_name='dlv_rec - option: DNSNameParam('dname_part_target', attribute=False, autofill=False, cli_name='dname_target', multivalue=False, option_group=u'DNAME Record', required=False) - option: DNAMERecord('dnamerecord', attribute=True, autofill=False, cli_name='dname_rec', csv=True, multivalue=True, option_group=u'DNAME Record', required=False) - option: StrEnum('dnsclass', attribute=True, autofill=False, cli_name='class', multivalue=False, required=False, values=(u'IN', u'CS', u'CH', u'HS')) --option: DNSKEYRecord('dnskeyrecord', attribute=True, autofill=False, cli_name='dnskey_rec', csv=True, multivalue=True, option_group=u'DNSKEY Record', required=False) - option: Int('dnsttl', attribute=True, autofill=False, cli_name='ttl', multivalue=False, required=False) - option: Int('ds_part_algorithm', attribute=False, autofill=False, cli_name='ds_algorithm', maxvalue=255, minvalue=0, multivalue=False, option_group=u'DS Record', required=False) - option: Str('ds_part_digest', attribute=False, autofill=False, cli_name='ds_digest', multivalue=False, option_group=u'DS Record', pattern='^[0-9a-fA-F]+$', required=False) -@@ -1337,7 +1321,6 @@ option: Str('naptr_part_replacement', attribute=False, autofill=False, cli_name= - option: Str('naptr_part_service', attribute=False, autofill=False, cli_name='naptr_service', multivalue=False, option_group=u'NAPTR Record', required=False) - option: NAPTRRecord('naptrrecord', attribute=True, autofill=False, cli_name='naptr_rec', csv=True, multivalue=True, option_group=u'NAPTR Record', required=False) - option: DNSNameParam('ns_part_hostname', attribute=False, autofill=False, cli_name='ns_hostname', multivalue=False, option_group=u'NS Record', required=False) --option: NSEC3Record('nsec3record', attribute=True, autofill=False, cli_name='nsec3_rec', csv=True, multivalue=True, option_group=u'NSEC3 Record', required=False) - option: NSECRecord('nsecrecord', attribute=True, autofill=False, cli_name='nsec_rec', csv=True, multivalue=True, option_group=u'NSEC Record', required=False) - option: NSRecord('nsrecord', attribute=True, autofill=False, cli_name='ns_rec', csv=True, multivalue=True, option_group=u'NS Record', required=False) - option: DNSNameParam('ptr_part_hostname', attribute=False, autofill=False, cli_name='ptr_hostname', multivalue=False, option_group=u'PTR Record', required=False) -@@ -1360,14 +1343,11 @@ option: Str('sshfp_part_fingerprint', attribute=False, autofill=False, cli_name= - option: Int('sshfp_part_fp_type', attribute=False, autofill=False, cli_name='sshfp_fp_type', maxvalue=255, minvalue=0, multivalue=False, option_group=u'SSHFP Record', required=False) - option: SSHFPRecord('sshfprecord', attribute=True, autofill=False, cli_name='sshfp_rec', csv=True, multivalue=True, option_group=u'SSHFP Record', required=False) - option: Flag('structured', autofill=True, default=False) --option: TARecord('tarecord', attribute=True, autofill=False, cli_name='ta_rec', csv=True, multivalue=True, option_group=u'TA Record', required=False) --option: TKEYRecord('tkeyrecord', attribute=True, autofill=False, cli_name='tkey_rec', csv=True, multivalue=True, option_group=u'TKEY Record', required=False) - option: Str('tlsa_part_cert_association_data', attribute=False, autofill=False, cli_name='tlsa_cert_association_data', multivalue=False, option_group=u'TLSA Record', required=False) - option: Int('tlsa_part_cert_usage', attribute=False, autofill=False, cli_name='tlsa_cert_usage', maxvalue=255, minvalue=0, multivalue=False, option_group=u'TLSA Record', required=False) - option: Int('tlsa_part_matching_type', attribute=False, autofill=False, cli_name='tlsa_matching_type', maxvalue=255, minvalue=0, multivalue=False, option_group=u'TLSA Record', required=False) - option: Int('tlsa_part_selector', attribute=False, autofill=False, cli_name='tlsa_selector', maxvalue=255, minvalue=0, multivalue=False, option_group=u'TLSA Record', required=False) - option: TLSARecord('tlsarecord', attribute=True, autofill=False, cli_name='tlsa_rec', csv=True, multivalue=True, option_group=u'TLSA Record', required=False) --option: TSIGRecord('tsigrecord', attribute=True, autofill=False, cli_name='tsig_rec', csv=True, multivalue=True, option_group=u'TSIG Record', required=False) - option: Str('txt_part_data', attribute=False, autofill=False, cli_name='txt_data', multivalue=False, option_group=u'TXT Record', required=False) - option: TXTRecord('txtrecord', attribute=True, autofill=False, cli_name='txt_rec', csv=True, multivalue=True, option_group=u'TXT Record', required=False) - option: Str('version?', exclude='webui') -diff --git a/VERSION b/VERSION -index b2f7a9a3e73b5f38741f7266054e3429803d7036..678d1f8a7e588d480b16441e12e4d527d9c1cd98 100644 ---- a/VERSION -+++ b/VERSION -@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 - # # - ######################################################## - IPA_API_VERSION_MAJOR=2 --IPA_API_VERSION_MINOR=146 --# Last change: pvoborni - move session_logout to ipalib/plugins -+IPA_API_VERSION_MINOR=147 -+# Last change: mbasti - Consolidate DNS RR in API and schema -diff --git a/install/share/60ipadns.ldif b/install/share/60ipadns.ldif -index 9e5b7feb2ee1809fb67b23cb2017a536d1bacb0a..e0ed0ab869cea0478d9640bb509c6267abed1a01 100644 ---- a/install/share/60ipadns.ldif -+++ b/install/share/60ipadns.ldif -@@ -10,6 +10,7 @@ attributeTypes: (1.3.6.1.4.1.2428.20.1.12 NAME 'pTRRecord' DESC 'domain name poi - attributeTypes: (1.3.6.1.4.1.2428.20.1.13 NAME 'hInfoRecord' DESC 'host information, RFC 1035' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.14 NAME 'mInfoRecord' DESC 'mailbox or mail list information, RFC 1035' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.16 NAME 'tXTRecord' DESC 'text string, RFC 1035' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -+attributeTypes: (1.3.6.1.4.1.2428.20.1.17 NAME 'RPRecord' DESC 'Responsible Person, RFC 1183' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.18 NAME 'aFSDBRecord' DESC 'for AFS Data Base location, RFC 1183' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.24 NAME 'SigRecord' DESC 'Signature, RFC 2535' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.25 NAME 'KeyRecord' DESC 'Key, RFC 2535' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -@@ -22,12 +23,17 @@ attributeTypes: (1.3.6.1.4.1.2428.20.1.36 NAME 'kXRecord' DESC 'Key Exchange Del - attributeTypes: (1.3.6.1.4.1.2428.20.1.37 NAME 'certRecord' DESC 'certificate, RFC 2538' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.38 NAME 'a6Record' DESC 'A6 Record Type, RFC 2874' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.39 NAME 'dNameRecord' DESC 'Non-Terminal DNS Name Redirection, RFC 2672' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) -+attributeTypes: (1.3.6.1.4.1.2428.20.1.42 NAME 'APLRecord' DESC 'Lists of Address Prefixes, RFC 3132' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.43 NAME 'dSRecord' DESC 'Delegation Signer, RFC 3658' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.44 NAME 'sSHFPRecord' DESC 'SSH Key Fingerprint, draft-ietf-secsh-dns-05.txt' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -+attributeTypes: (1.3.6.1.4.1.2428.20.1.45 NAME 'IPSECKEYRecord' DESC 'IPSECKEY, RFC 4025' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.46 NAME 'rRSIGRecord' DESC 'RRSIG, RFC 3755' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.47 NAME 'nSECRecord' DESC 'NSEC, RFC 3755' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -+attributeTypes: (1.3.6.1.4.1.2428.20.1.49 NAME 'DHCIDRecord' DESC 'Dynamic Host Configuration Protocol (DHCP) Information, RFC 4701' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.51 NAME 'nSEC3PARAMRecord' DESC 'RFC 5155' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.52 NAME 'TLSARecord' DESC 'DNS-Based Authentication of Named Entities - Transport Layer Security Protocol, RFC 6698' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -+attributeTypes: (1.3.6.1.4.1.2428.20.1.55 NAME 'HIPRecord' DESC 'Host Identity Protocol (HIP) Domain Name System (DNS) Extension, RFC 5205' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -+attributeTypes: (1.3.6.1.4.1.2428.20.1.99 NAME 'SPFRecord' DESC 'Sender Policy Framework (SPF) for Authorizing Use of Domains in Email, RFC 7208' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.1.32769 NAME 'DLVRecord' DESC 'DNSSEC Lookaside Validation, RFC 4431' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) - attributeTypes: (1.3.6.1.4.1.2428.20.4 NAME 'UnknownRecord' DESC 'unknown DNS record, RFC 3597' SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch ) - attributeTypes: (0.9.2342.19200300.100.1.26 NAME 'aRecord' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -@@ -64,7 +70,7 @@ attributeTypes: ( 2.16.840.1.113730.3.8.5.25 NAME 'idnsSecKeyRevoke' DESC 'DNSKE - attributeTypes: ( 2.16.840.1.113730.3.8.5.26 NAME 'idnsSecKeySep' DESC 'DNSKEY SEP flag (equivalent to bit 15): RFC 4035' EQUALITY booleanMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 SINGLE-VALUE X-ORIGIN 'IPA v4.1' ) - attributeTypes: ( 2.16.840.1.113730.3.8.5.27 NAME 'idnsSecAlgorithm' DESC 'DNSKEY algorithm: string used as mnemonic' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'IPA v4.1' ) - attributeTypes: ( 2.16.840.1.113730.3.8.5.28 NAME 'idnsSecKeyRef' DESC 'PKCS#11 URI of the key' EQUALITY caseExactMatch SINGLE-VALUE SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v4.1' ) --objectClasses: ( 2.16.840.1.113730.3.8.6.0 NAME 'idnsRecord' DESC 'dns Record, usually a host' SUP top STRUCTURAL MUST idnsName MAY ( cn $ idnsAllowDynUpdate $ dNSTTL $ dNSClass $ aRecord $ aAAARecord $ a6Record $ nSRecord $ cNAMERecord $ pTRRecord $ sRVRecord $ tXTRecord $ mXRecord $ mDRecord $ hInfoRecord $ mInfoRecord $ aFSDBRecord $ SigRecord $ KeyRecord $ LocRecord $ nXTRecord $ nAPTRRecord $ kXRecord $ certRecord $ dNameRecord $ dSRecord $ sSHFPRecord $ rRSIGRecord $ nSECRecord $ DLVRecord $ TLSARecord $ UnknownRecord ) ) -+objectClasses: ( 2.16.840.1.113730.3.8.6.0 NAME 'idnsRecord' DESC 'dns Record, usually a host' SUP top STRUCTURAL MUST idnsName MAY ( cn $ idnsAllowDynUpdate $ dNSTTL $ dNSClass $ aRecord $ aAAARecord $ a6Record $ nSRecord $ cNAMERecord $ pTRRecord $ sRVRecord $ tXTRecord $ mXRecord $ mDRecord $ hInfoRecord $ mInfoRecord $ aFSDBRecord $ SigRecord $ KeyRecord $ LocRecord $ nXTRecord $ nAPTRRecord $ kXRecord $ certRecord $ dNameRecord $ dSRecord $ sSHFPRecord $ rRSIGRecord $ nSECRecord $ DLVRecord $ TLSARecord $ UnknownRecord $ RPRecord $ APLRecord $ IPSECKEYRecord $ DHCIDRecord $ HIPRecord $ SPFRecord ) ) - objectClasses: ( 2.16.840.1.113730.3.8.6.1 NAME 'idnsZone' DESC 'Zone class' SUP idnsRecord STRUCTURAL MUST ( idnsZoneActive $ idnsSOAmName $ idnsSOArName $ idnsSOAserial $ idnsSOArefresh $ idnsSOAretry $ idnsSOAexpire $ idnsSOAminimum ) MAY ( idnsUpdatePolicy $ idnsAllowQuery $ idnsAllowTransfer $ idnsAllowSyncPTR $ idnsForwardPolicy $ idnsForwarders $ idnsSecInlineSigning $ nSEC3PARAMRecord ) ) - objectClasses: ( 2.16.840.1.113730.3.8.6.2 NAME 'idnsConfigObject' DESC 'DNS global config options' STRUCTURAL MAY ( idnsForwardPolicy $ idnsForwarders $ idnsAllowSyncPTR $ idnsZoneRefresh $ idnsPersistentSearch ) ) - objectClasses: ( 2.16.840.1.113730.3.8.12.18 NAME 'ipaDNSZone' SUP top AUXILIARY MUST idnsName MAY managedBy X-ORIGIN 'IPA v3' ) -diff --git a/install/share/dns.ldif b/install/share/dns.ldif -index c9e368677006b55d0e748f54d297d83bdd69e205..42b41a8d706a8a3fd826320aff6c9333264128fc 100644 ---- a/install/share/dns.ldif -+++ b/install/share/dns.ldif -@@ -9,7 +9,7 @@ ipaConfigString: DNSVersion 1 - aci: (targetattr = "*")(version 3.0; acl "Allow read access"; allow (read,search,compare) groupdn = "ldap:///cn=Read DNS Entries,cn=permissions,cn=pbac,$SUFFIX" or userattr = "parent[0,1].managedby#GROUPDN";) - aci: (target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Add DNS entries in a zone";allow (add) userattr = "parent[1].managedby#GROUPDN";) - aci: (target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Remove DNS entries from a zone";allow (delete) userattr = "parent[1].managedby#GROUPDN";) --aci: (targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders || dlvrecord || idnssecinlinesigning || nsec3paramrecord || tlsarecord || unknownrecord ")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";) -+aci: (targetattr = "a6record || aaaarecord || afsdbrecord || aplrecord || arecord || certrecord || cn || cnamerecord || dhcidrecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || hiprecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || ipseckeyrecord || keyrecord || kxrecord || locrecord || mdrecord || minforecord || mxrecord || naptrrecord || nsecrecord || nsec3paramrecord || nsrecord || nxtrecord || ptrrecord || rprecord || rrsigrecord || sigrecord || spfrecord || srvrecord || sshfprecord || tlsarecord || txtrecord || unknownrecord ")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";) - - dn: cn=DNS Administrators,cn=privileges,cn=pbac,$SUFFIX - changetype: add -diff --git a/install/updates/40-dns.update b/install/updates/40-dns.update -index c06d8158d85fd811be0253ac0f1146a623fae2b2..9f64a2f707db5cb0e3503259a0e64d9831ae92f2 100644 ---- a/install/updates/40-dns.update -+++ b/install/updates/40-dns.update -@@ -5,7 +5,8 @@ addifexist: objectClass: idnsConfigObject - addifexist: objectClass: ipaConfigObject - addifexist: aci:(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Add DNS entries in a zone";allow (add) userattr = "parent[1].managedby#GROUPDN";) - addifexist: aci:(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Remove DNS entries from a zone";allow (delete) userattr = "parent[1].managedby#GROUPDN";) --addifexist: aci:(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders || dlvrecord || idnssecinlinesigning || nsec3paramrecord || tlsarecord || unknownrecord ")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";) -+addifexist: aci:(targetattr = "a6record || aaaarecord || afsdbrecord || aplrecord || arecord || certrecord || cn || cnamerecord || dhcidrecord || dlvrecord || dnamerecord || dnsclass || dnsttl || dsrecord || hinforecord || hiprecord || idnsallowdynupdate || idnsallowquery || idnsallowsyncptr || idnsallowtransfer || idnsforwarders || idnsforwardpolicy || idnsname || idnssecinlinesigning || idnssoaexpire || idnssoaminimum || idnssoamname || idnssoarefresh || idnssoaretry || idnssoarname || idnssoaserial || idnsupdatepolicy || idnszoneactive || ipseckeyrecord || keyrecord || kxrecord || locrecord || mdrecord || minforecord || mxrecord || naptrrecord || nsecrecord || nsec3paramrecord || nsrecord || nxtrecord || ptrrecord || rprecord || rrsigrecord || sigrecord || spfrecord || srvrecord || sshfprecord || tlsarecord || txtrecord || unknownrecord ")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";) -+ - - # replace DNS tree deny rule with managedBy enhanced allow rule - dn: cn=dns, $SUFFIX -@@ -16,6 +17,7 @@ replace:aci:(targetattr = "*")(version 3.0; acl "Allow read access"; allow (read - dn: cn=dns, $SUFFIX - remove:aci:(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";) - remove:aci:(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders || dlvrecord || idnssecinlinesigning || nsec3paramrecord || tlsarecord ")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";) -+remove:aci:(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy || idnsallowquery || idnsallowtransfer || idnsallowsyncptr || idnsforwardpolicy || idnsforwarders || dlvrecord || idnssecinlinesigning || nsec3paramrecord || tlsarecord || unknownrecord ")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "Update DNS entries in a zone";allow (write) userattr = "parent[0,1].managedby#GROUPDN";) - - # add DNS plugin - dn: cn=IPA DNS,cn=plugins,cn=config -diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py -index a7a4100db6de1956b8d0468e03214abc227386d5..512a653c3cc8ee641debec0d20f58e17eff08266 100644 ---- a/ipalib/plugins/dns.py -+++ b/ipalib/plugins/dns.py -@@ -281,10 +281,9 @@ register = Registry() - # supported resource record types - _record_types = ( - u'A', u'AAAA', u'A6', u'AFSDB', u'APL', u'CERT', u'CNAME', u'DHCID', u'DLV', -- u'DNAME', u'DNSKEY', u'DS', u'HIP', u'IPSECKEY', u'KEY', u'KX', u'LOC', -- u'MX', u'NAPTR', u'NS', u'NSEC', u'NSEC3', u'PTR', -- u'RRSIG', u'RP', u'SIG', u'SPF', u'SRV', u'SSHFP', u'TA', u'TKEY', -- u'TLSA', u'TSIG', u'TXT', -+ u'DNAME', u'DS', u'HIP', u'HINFO', u'IPSECKEY', u'KEY', u'KX', u'LOC', -+ u'MD', u'MINFO', u'MX', u'NAPTR', u'NS', u'NSEC', u'NXT', u'PTR', u'RRSIG', -+ u'RP', u'SIG', u'SPF', u'SRV', u'SSHFP', u'TLSA', u'TXT', - ) - - # DNS zone record identificator -@@ -1092,9 +1091,6 @@ class DNAMERecord(DNSRecord): - ), - ) - --class DNSKEYRecord(UnsupportedDNSRecord): -- rrtype = 'DNSKEY' -- rfc = 4034 - - class DSRecord(DNSRecord): - rrtype = 'DS' -@@ -1129,6 +1125,11 @@ class DLVRecord(DSRecord): - rfc = 4431 - - -+class HINFORecord(UnsupportedDNSRecord): -+ rrtype = 'HINFO' -+ rfc = 1035 -+ -+ - class HIPRecord(UnsupportedDNSRecord): - rrtype = 'HIP' - rfc = 5205 -@@ -1287,6 +1288,18 @@ class LOCRecord(DNSRecord): - name=target_cli_name) - raise errors.ValidationError(name=self.name, error=error) - -+ -+class MDRecord(UnsupportedDNSRecord): -+ # obsoleted, use MX instead -+ rrtype = 'MD' -+ rfc = 1035 -+ -+ -+class MINFORecord(UnsupportedDNSRecord): -+ rrtype = 'MINFO' -+ rfc = 1035 -+ -+ - class MXRecord(DNSRecord): - rrtype = 'MX' - rfc = 1035 -@@ -1318,9 +1331,6 @@ class NSECRecord(UnsupportedDNSRecord): - rrtype = 'NSEC' - rfc = 4034 - --class NSEC3Record(UnsupportedDNSRecord): -- rrtype = 'NSEC3' -- rfc = 5155 - - def _validate_naptr_flags(ugettext, flags): - allowed_flags = u'SAUP' -@@ -1361,6 +1371,12 @@ class NAPTRRecord(DNSRecord): - ), - ) - -+ -+class NXTRecord(UnsupportedDNSRecord): -+ rrtype = 'NXT' -+ rfc = 2535 -+ -+ - class PTRRecord(DNSRecord): - rrtype = 'PTR' - rfc = 1035 -@@ -1450,10 +1466,6 @@ class SSHFPRecord(DNSRecord): - return tuple(values) - - --class TARecord(UnsupportedDNSRecord): -- rrtype = 'TA' -- -- - class TLSARecord(DNSRecord): - rrtype = 'TLSA' - rfc = 6698 -@@ -1479,12 +1491,6 @@ class TLSARecord(DNSRecord): - ) - - --class TKEYRecord(UnsupportedDNSRecord): -- rrtype = 'TKEY' -- --class TSIGRecord(UnsupportedDNSRecord): -- rrtype = 'TSIG' -- - class TXTRecord(DNSRecord): - rrtype = 'TXT' - rfc = 1035 -@@ -1509,7 +1515,6 @@ _dns_records = ( - DHCIDRecord(), - DLVRecord(), - DNAMERecord(), -- DNSKEYRecord(), - DSRecord(), - HIPRecord(), - IPSECKEYRecord(), -@@ -1520,7 +1525,6 @@ _dns_records = ( - NAPTRRecord(), - NSRecord(), - NSECRecord(), -- NSEC3Record(), - PTRRecord(), - RRSIGRecord(), - RPRecord(), -@@ -1528,10 +1532,7 @@ _dns_records = ( - SPFRecord(), - SRVRecord(), - SSHFPRecord(), -- TARecord(), - TLSARecord(), -- TKEYRecord(), -- TSIGRecord(), - TXTRecord(), - ) - -@@ -2500,20 +2501,21 @@ class dnszone(DNSZoneBase): - 'ipapermtarget': DN('idnsname=*', 'cn=dns', api.env.basedn), - 'ipapermdefaultattr': { - 'objectclass', -- 'a6record', 'aaaarecord', 'afsdbrecord', 'arecord', -- 'certrecord', 'cn', 'cnamerecord', 'dlvrecord', 'dnamerecord', -- 'dnsclass', 'dnsttl', 'dsrecord', 'hinforecord', -- 'idnsallowdynupdate', 'idnsallowquery', 'idnsallowsyncptr', -- 'idnsallowtransfer', 'idnsforwarders', 'idnsforwardpolicy', -- 'idnsname', 'idnssecinlinesigning', 'idnssoaexpire', -- 'idnssoaminimum', 'idnssoamname', 'idnssoarefresh', -- 'idnssoaretry', 'idnssoarname', 'idnssoaserial', -- 'idnsupdatepolicy', 'idnszoneactive', 'keyrecord', 'kxrecord', -+ 'a6record', 'aaaarecord', 'afsdbrecord', 'aplrecord', 'arecord', -+ 'certrecord', 'cn', 'cnamerecord', 'dhcidrecord', 'dlvrecord', -+ 'dnamerecord', 'dnsclass', 'dnsttl', 'dsrecord', -+ 'hinforecord', 'hiprecord', 'idnsallowdynupdate', -+ 'idnsallowquery', 'idnsallowsyncptr', 'idnsallowtransfer', -+ 'idnsforwarders', 'idnsforwardpolicy', 'idnsname', -+ 'idnssecinlinesigning', 'idnssoaexpire', 'idnssoaminimum', -+ 'idnssoamname', 'idnssoarefresh', 'idnssoaretry', -+ 'idnssoarname', 'idnssoaserial', 'idnsupdatepolicy', -+ 'idnszoneactive', 'ipseckeyrecord','keyrecord', 'kxrecord', - 'locrecord', 'managedby', 'mdrecord', 'minforecord', - 'mxrecord', 'naptrrecord', 'nsecrecord', 'nsec3paramrecord', -- 'nsrecord', 'nxtrecord', 'ptrrecord', 'rrsigrecord', -- 'sigrecord', 'srvrecord', 'sshfprecord', 'tlsarecord', -- 'txtrecord', 'unknownrecord', -+ 'nsrecord', 'nxtrecord', 'ptrrecord', 'rprecord', 'rrsigrecord', -+ 'sigrecord', 'spfrecord', 'srvrecord', 'sshfprecord', -+ 'tlsarecord', 'txtrecord', 'unknownrecord', - }, - 'replaces_system': ['Read DNS Entries'], - 'default_privileges': {'DNS Administrators', 'DNS Servers'}, -@@ -2534,20 +2536,21 @@ class dnszone(DNSZoneBase): - 'ipapermlocation': api.env.basedn, - 'ipapermtarget': DN('idnsname=*', 'cn=dns', api.env.basedn), - 'ipapermdefaultattr': { -- 'a6record', 'aaaarecord', 'afsdbrecord', 'arecord', -- 'certrecord', 'cn', 'cnamerecord', 'dlvrecord', 'dnamerecord', -- 'dnsclass', 'dnsttl', 'dsrecord', 'hinforecord', -- 'idnsallowdynupdate', 'idnsallowquery', 'idnsallowsyncptr', -- 'idnsallowtransfer', 'idnsforwarders', 'idnsforwardpolicy', -- 'idnsname', 'idnssecinlinesigning', 'idnssoaexpire', -- 'idnssoaminimum', 'idnssoamname', 'idnssoarefresh', -- 'idnssoaretry', 'idnssoarname', 'idnssoaserial', -- 'idnsupdatepolicy', 'idnszoneactive', 'keyrecord', 'kxrecord', -+ 'a6record', 'aaaarecord', 'afsdbrecord', 'aplrecord', 'arecord', -+ 'certrecord', 'cn', 'cnamerecord', 'dhcidrecord', 'dlvrecord', -+ 'dnamerecord', 'dnsclass', 'dnsttl', 'dsrecord', -+ 'hinforecord', 'hiprecord', 'idnsallowdynupdate', -+ 'idnsallowquery', 'idnsallowsyncptr', 'idnsallowtransfer', -+ 'idnsforwarders', 'idnsforwardpolicy', 'idnsname', -+ 'idnssecinlinesigning', 'idnssoaexpire', 'idnssoaminimum', -+ 'idnssoamname', 'idnssoarefresh', 'idnssoaretry', -+ 'idnssoarname', 'idnssoaserial', 'idnsupdatepolicy', -+ 'idnszoneactive', 'ipseckeyrecord','keyrecord', 'kxrecord', - 'locrecord', 'managedby', 'mdrecord', 'minforecord', - 'mxrecord', 'naptrrecord', 'nsecrecord', 'nsec3paramrecord', -- 'nsrecord', 'nxtrecord', 'ptrrecord', 'rrsigrecord', -- 'sigrecord', 'srvrecord', 'sshfprecord', 'tlsarecord', -- 'txtrecord', 'unknownrecord', -+ 'nsrecord', 'nxtrecord', 'ptrrecord', 'rprecord', 'rrsigrecord', -+ 'sigrecord', 'spfrecord', 'srvrecord', 'sshfprecord', -+ 'tlsarecord', 'txtrecord', 'unknownrecord', - }, - 'replaces': [ - '(targetattr = "idnsname || cn || idnsallowdynupdate || dnsttl || dnsclass || arecord || aaaarecord || a6record || nsrecord || cnamerecord || ptrrecord || srvrecord || txtrecord || mxrecord || mdrecord || hinforecord || minforecord || afsdbrecord || sigrecord || keyrecord || locrecord || nxtrecord || naptrrecord || kxrecord || certrecord || dnamerecord || dsrecord || sshfprecord || rrsigrecord || nsecrecord || idnsname || idnszoneactive || idnssoamname || idnssoarname || idnssoaserial || idnssoarefresh || idnssoaretry || idnssoaexpire || idnssoaminimum || idnsupdatepolicy")(target = "ldap:///idnsname=*,cn=dns,$SUFFIX")(version 3.0;acl "permission:update dns entries";allow (write) groupdn = "ldap:///cn=update dns entries,cn=permissions,cn=pbac,$SUFFIX";)', --- -2.4.3 - diff --git a/SOURCES/0021-server-uninstall-fails-to-remove-krb-principals.patch b/SOURCES/0021-server-uninstall-fails-to-remove-krb-principals.patch new file mode 100644 index 0000000..cdcb725 --- /dev/null +++ b/SOURCES/0021-server-uninstall-fails-to-remove-krb-principals.patch @@ -0,0 +1,51 @@ +From 028ae66827085960cdfa9861c413a7aeccea5221 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Mon, 11 Jul 2016 09:00:44 +0200 +Subject: [PATCH] server uninstall fails to remove krb principals + +This patch fixes the 3rd issue of ticket 6012: +ipa-server-install --uninstall -U +complains while removing Kerberos service principals from /etc/krb5.keytab +---- +Failed to remove Kerberos service principals: Command '/usr/sbin/ipa-rmkeytab -k /etc/krb5.keytab -r DOM-221.ABC.IDM.LAB.ENG.BRQ.REDHAT.COM' returned non-zero exit status 5 +---- + +This happens because the uninstaller performs the following sequence: +1/ restore pre-install files, including /etc/krb5.keytab +At this point /etc/krb5.keytab does not contain any principal for +IPA domain +2/ call ipa-client-install --uninstall, which in turns runs +ipa-rmkeytab -k /etc/krb5.keytab -r +to remove the principals. + +The fix ignores ipa-rmkeytab's exit code 5 (Principal name or realm not +found in keytab) + +https://fedorahosted.org/freeipa/ticket/6012 + +Reviewed-By: Martin Basti +--- + client/ipa-client-install | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/client/ipa-client-install b/client/ipa-client-install +index cee202f89e0f40f4b7ee77e5c38a2c7d50e0dee9..45185d44feb43a8b8d30e412a26dd63121be4ad1 100755 +--- a/client/ipa-client-install ++++ b/client/ipa-client-install +@@ -614,6 +614,13 @@ def uninstall(options, env): + fp.close() + realm = parser.get('global', 'realm') + run([paths.IPA_RMKEYTAB, "-k", paths.KRB5_KEYTAB, "-r", realm]) ++ except CalledProcessError as err: ++ if err.returncode != 5: ++ # 5 means Principal name or realm not found in keytab ++ # and can be ignored ++ root_logger.error( ++ "Failed to remove Kerberos service principals: %s", ++ str(err)) + except Exception as e: + root_logger.error( + "Failed to remove Kerberos service principals: %s", str(e)) +-- +2.7.4 + diff --git a/SOURCES/0022-expose-secret-option-in-radiusproxy-commands.patch b/SOURCES/0022-expose-secret-option-in-radiusproxy-commands.patch new file mode 100644 index 0000000..dd10fc1 --- /dev/null +++ b/SOURCES/0022-expose-secret-option-in-radiusproxy-commands.patch @@ -0,0 +1,32 @@ +From a9914cc13e0b04fbe8637214970c99b2328a2dfa Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Mon, 18 Jul 2016 10:45:48 +0200 +Subject: [PATCH] expose `--secret` option in radiusproxy-* commands + +Option `--secret` was hidden from radiusproxy CLI preventing setting a secret +on existing server or searching by secret. Since thin client implementation it +was also not recognized by the interactive prompt code in CLI frontend since +it never got there. + +https://fedorahosted.org/freeipa/ticket/6078 + +Reviewed-By: Jan Cholasta +--- + ipaserver/plugins/radiusproxy.py | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/ipaserver/plugins/radiusproxy.py b/ipaserver/plugins/radiusproxy.py +index 44d87b9ae1337278bb6237d471f64693b0eac3db..5657e002c1ce66335b7697b98f95a49207c61d87 100644 +--- a/ipaserver/plugins/radiusproxy.py ++++ b/ipaserver/plugins/radiusproxy.py +@@ -126,7 +126,6 @@ class radiusproxy(LDAPObject): + label=_('Secret'), + doc=_('The secret used to encrypt data'), + confirm=True, +- flags=['no_option'], + ), + Int('ipatokenradiustimeout?', + cli_name='timeout', +-- +2.7.4 + diff --git a/SOURCES/0022-ipaplatform-Add-constants-submodule.patch b/SOURCES/0022-ipaplatform-Add-constants-submodule.patch deleted file mode 100644 index 418c4f2..0000000 --- a/SOURCES/0022-ipaplatform-Add-constants-submodule.patch +++ /dev/null @@ -1,147 +0,0 @@ -From 9e5c97ffdc7a42f6f76affbc9a791496ba245557 Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Thu, 2 Jul 2015 12:38:43 +0200 -Subject: [PATCH] ipaplatform: Add constants submodule - -Introduce a ipaplatform/constants.py file to store platform related -constants, which are not paths. - -Reviewed-By: Martin Basti -Reviewed-By: Petr Spacek ---- - Makefile | 3 ++- - freeipa.spec.in | 2 ++ - ipaplatform/base/constants.py | 11 +++++++++++ - ipaplatform/fedora/constants.py | 16 ++++++++++++++++ - ipaplatform/redhat/constants.py | 17 +++++++++++++++++ - ipaplatform/rhel/constants.py | 16 ++++++++++++++++ - 6 files changed, 64 insertions(+), 1 deletion(-) - create mode 100644 ipaplatform/base/constants.py - create mode 100644 ipaplatform/fedora/constants.py - create mode 100644 ipaplatform/redhat/constants.py - create mode 100644 ipaplatform/rhel/constants.py - -diff --git a/Makefile b/Makefile -index abf58382960099a54b8920dd0e741b9fda17682f..3c81466d3728022c1d9cf5bb216990f14a59b7e5 100644 ---- a/Makefile -+++ b/Makefile -@@ -159,10 +159,11 @@ version-update: release-update - if [ "$(SUPPORTED_PLATFORM)" != "" ]; then \ - sed -e s/__PLATFORM__/$(SUPPORTED_PLATFORM)/ \ - ipaplatform/__init__.py.in > ipaplatform/__init__.py; \ -- rm -f ipaplatform/paths.py ipaplatform/services.py ipaplatform/tasks.py; \ -+ rm -f ipaplatform/paths.py ipaplatform/services.py ipaplatform/tasks.py ipaplatform/constants.py; \ - ln -s $(SUPPORTED_PLATFORM)/paths.py ipaplatform/paths.py; \ - ln -s $(SUPPORTED_PLATFORM)/services.py ipaplatform/services.py; \ - ln -s $(SUPPORTED_PLATFORM)/tasks.py ipaplatform/tasks.py; \ -+ ln -s $(SUPPORTED_PLATFORM)/constants.py ipaplatform/constants.py; \ - fi - - if [ "$(SKIP_API_VERSION_CHECK)" != "yes" ]; then \ -diff --git a/freeipa.spec.in b/freeipa.spec.in -index 5790f7941d2117ed95d3c99556f1579c27917270..e9ba596fec1f8d179d4f834485e35a4814db898d 100644 ---- a/freeipa.spec.in -+++ b/freeipa.spec.in -@@ -363,6 +363,7 @@ rm -f ipapython/version.py - rm -f ipaplatform/services.py - rm -f ipaplatform/tasks.py - rm -f ipaplatform/paths.py -+rm -f ipaplatform/constants.py - make version-update - cd ipa-client; ../autogen.sh --prefix=%{_usr} --sysconfdir=%{_sysconfdir} --localstatedir=%{_localstatedir} --libdir=%{_libdir} --mandir=%{_mandir}; cd .. - %if ! %{ONLY_CLIENT} -@@ -385,6 +386,7 @@ rm -f ipapython/version.py - rm -f ipaplatform/services.py - rm -f ipaplatform/tasks.py - rm -f ipaplatform/paths.py -+rm -f ipaplatform/constants.py - make version-update - %if ! %{ONLY_CLIENT} - make install DESTDIR=%{buildroot} -diff --git a/ipaplatform/base/constants.py b/ipaplatform/base/constants.py -new file mode 100644 -index 0000000000000000000000000000000000000000..70485055fa5a12fac878ace3dea11ea442ebe6be ---- /dev/null -+++ b/ipaplatform/base/constants.py -@@ -0,0 +1,11 @@ -+# -+# Copyright (C) 2015 FreeIPA Contributors see COPYING for license -+# -+ -+''' -+This base platform module exports platform dependant constants. -+''' -+ -+ -+class BaseConstantsNamespace(object): -+ pass -diff --git a/ipaplatform/fedora/constants.py b/ipaplatform/fedora/constants.py -new file mode 100644 -index 0000000000000000000000000000000000000000..ce03f58cf95be1a72a9ce3da65e6d21ef193cefe ---- /dev/null -+++ b/ipaplatform/fedora/constants.py -@@ -0,0 +1,16 @@ -+# -+# Copyright (C) 2015 FreeIPA Contributors see COPYING for license -+# -+ -+''' -+This Fedora base platform module exports platform related constants. -+''' -+ -+# Fallback to default constant definitions -+from ipaplatform.redhat.constants import RedHatConstantsNamespace -+ -+ -+class FedoraConstantsNamespace(RedHatConstantsNamespace): -+ pass -+ -+constants = FedoraConstantsNamespace() -diff --git a/ipaplatform/redhat/constants.py b/ipaplatform/redhat/constants.py -new file mode 100644 -index 0000000000000000000000000000000000000000..7209947f8afbd688b02c8b134d33185e497befe0 ---- /dev/null -+++ b/ipaplatform/redhat/constants.py -@@ -0,0 +1,17 @@ -+# -+# Copyright (C) 2015 FreeIPA Contributors see COPYING for license -+# -+ -+''' -+This Red Hat OS family base platform module exports default platform -+related constants for the Red Hat OS family-based systems. -+''' -+ -+# Fallback to default path definitions -+from ipaplatform.base.constants import BaseConstantsNamespace -+ -+ -+class RedHatConstantsNamespace(BaseConstantsNamespace): -+ pass -+ -+constants = RedHatConstantsNamespace() -diff --git a/ipaplatform/rhel/constants.py b/ipaplatform/rhel/constants.py -new file mode 100644 -index 0000000000000000000000000000000000000000..eaca48030fa28804c70c161b07228646a95fc1a3 ---- /dev/null -+++ b/ipaplatform/rhel/constants.py -@@ -0,0 +1,16 @@ -+# -+# Copyright (C) 2015 FreeIPA Contributors see COPYING for license -+# -+ -+''' -+This RHEL base platform module exports platform related constants. -+''' -+ -+# Fallback to default constant definitions -+from ipaplatform.redhat.constants import RedHatConstantsNamespace -+ -+ -+class RHELConstantsNamespace(RedHatConstantsNamespace): -+ pass -+ -+constants = RHELConstantsNamespace() --- -2.4.3 - diff --git a/SOURCES/0023-DNS-check-if-DNS-package-is-installed.patch b/SOURCES/0023-DNS-check-if-DNS-package-is-installed.patch deleted file mode 100644 index cd483f2..0000000 --- a/SOURCES/0023-DNS-check-if-DNS-package-is-installed.patch +++ /dev/null @@ -1,170 +0,0 @@ -From 9bf3e3efe51ccda418afd2340a113f39144851c3 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Wed, 1 Jul 2015 15:05:45 +0200 -Subject: [PATCH] DNS: check if DNS package is installed - -Instead of separate checking of DNS required packages, we need just -check if IPA DNS package is installed. - -https://fedorahosted.org/freeipa/ticket/4058 - -Reviewed-By: Martin Babinsky -Reviewed-By: Petr Spacek -Reviewed-By: Tomas Babej ---- - ipaplatform/base/constants.py | 2 +- - ipaplatform/base/paths.py | 1 + - ipaplatform/rhel/constants.py | 2 +- - ipaserver/install/bindinstance.py | 19 +------------------ - ipaserver/install/dns.py | 11 ++++++----- - ipaserver/install/dnskeysyncinstance.py | 6 ------ - ipaserver/install/opendnssecinstance.py | 8 -------- - 7 files changed, 10 insertions(+), 39 deletions(-) - -diff --git a/ipaplatform/base/constants.py b/ipaplatform/base/constants.py -index 70485055fa5a12fac878ace3dea11ea442ebe6be..cef829e2d3886db00ae6d0299ddcf325d1add80e 100644 ---- a/ipaplatform/base/constants.py -+++ b/ipaplatform/base/constants.py -@@ -8,4 +8,4 @@ This base platform module exports platform dependant constants. - - - class BaseConstantsNamespace(object): -- pass -+ IPA_DNS_PACKAGE_NAME = "freeipa-server-dns" -diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py -index 5756040172126438d42275b734f4d766d53048fe..4c93c1f7162b0aeb4f798ef84e1ac8db4573518b 100644 ---- a/ipaplatform/base/paths.py -+++ b/ipaplatform/base/paths.py -@@ -218,6 +218,7 @@ class BasePathNamespace(object): - GROUPADD = "/usr/sbin/groupadd" - HTTPD = "/usr/sbin/httpd" - IPA_CLIENT_INSTALL = "/usr/sbin/ipa-client-install" -+ IPA_DNS_INSTALL = "/usr/sbin/ipa-dns-install" - SBIN_IPA_JOIN = "/usr/sbin/ipa-join" - IPA_REPLICA_CONNCHECK = "/usr/sbin/ipa-replica-conncheck" - IPA_RMKEYTAB = "/usr/sbin/ipa-rmkeytab" -diff --git a/ipaplatform/rhel/constants.py b/ipaplatform/rhel/constants.py -index eaca48030fa28804c70c161b07228646a95fc1a3..17abde1f861778bec83067cb01e9a1faae325527 100644 ---- a/ipaplatform/rhel/constants.py -+++ b/ipaplatform/rhel/constants.py -@@ -11,6 +11,6 @@ from ipaplatform.redhat.constants import RedHatConstantsNamespace - - - class RHELConstantsNamespace(RedHatConstantsNamespace): -- pass -+ IPA_DNS_PACKAGE_NAME = "ipa-server-dns" - - constants = RHELConstantsNamespace() -diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py -index 2228342dc40ee415d1adf2687a7ae91a5963d3c7..9705e845a76191a252bfa963b54d9c31d83ad18e 100644 ---- a/ipaserver/install/bindinstance.py -+++ b/ipaserver/install/bindinstance.py -@@ -62,25 +62,8 @@ named_conf_arg_options_template_nonstr = "%(indent)s%(name)s %(value)s;\n" - named_conf_include_re = re.compile(r'\s*include\s+"(?P)"\s*;') - named_conf_include_template = "include \"%(path)s\";\n" - --def check_inst(unattended): -- has_bind = True -- named = services.knownservices.named -- if not os.path.exists(named.get_binary_path()): -- print "BIND was not found on this system" -- print ("Please install the '%s' package and start the installation again" -- % named.get_package_name()) -- has_bind = False -- -- # Also check for the LDAP BIND plug-in -- if not os.path.exists(paths.BIND_LDAP_SO) and \ -- not os.path.exists(paths.BIND_LDAP_SO_64): -- print "The BIND LDAP plug-in was not found on this system" -- print "Please install the 'bind-dyndb-ldap' package and start the installation again" -- has_bind = False -- -- if not has_bind: -- return False - -+def check_inst(unattended): - if not unattended and os.path.exists(NAMED_CONF): - msg = "Existing BIND configuration detected, overwrite?" - return ipautil.user_input(msg, False) -diff --git a/ipaserver/install/dns.py b/ipaserver/install/dns.py -index d22bce7a7cd2e0e8a7ffe0ab4aa496634465903b..9430d189978b0984b0b71d7d754516a4135053fb 100644 ---- a/ipaserver/install/dns.py -+++ b/ipaserver/install/dns.py -@@ -9,6 +9,7 @@ from subprocess import CalledProcessError - from ipalib import api - from ipalib import errors - from ipaplatform.paths import paths -+from ipaplatform.constants import constants - from ipaplatform import services - from ipapython import ipautil - from ipapython import sysrestore -@@ -96,6 +97,10 @@ def install_check(standalone, replica, options, hostname): - global reverse_zones - fstore = sysrestore.FileStore(paths.SYSRESTORE) - -+ if not ipautil.file_exists(paths.IPA_DNS_INSTALL): -+ raise RuntimeError("Integrated DNS requires '%s' package" % -+ constants.IPA_DNS_PACKAGE_NAME) -+ - if standalone: - print "==============================================================================" - print "This program will setup DNS for the FreeIPA Server." -@@ -141,8 +146,7 @@ def install_check(standalone, replica, options, hostname): - sys.exit("Aborted") - - # Check bind packages are installed -- if not (bindinstance.check_inst(options.unattended) and -- dnskeysyncinstance.check_inst()): -+ if not bindinstance.check_inst(options.unattended): - sys.exit("Aborting installation.") - - if options.disable_dnssec_master: -@@ -177,9 +181,6 @@ def install_check(standalone, replica, options, hostname): - sys.exit("Only one DNSSEC key master is supported in current " - "version.") - -- # check opendnssec packages are installed -- if not opendnssecinstance.check_inst(): -- sys.exit("Aborting installation") - if options.kasp_db_file: - dnskeysyncd = services.service('ipa-dnskeysyncd') - -diff --git a/ipaserver/install/dnskeysyncinstance.py b/ipaserver/install/dnskeysyncinstance.py -index eb6d07f014bce296a5b094f499194286c31c2489..7d1351ccc57a5dbd7d537741545ad44d0dcd5eb1 100644 ---- a/ipaserver/install/dnskeysyncinstance.py -+++ b/ipaserver/install/dnskeysyncinstance.py -@@ -30,12 +30,6 @@ softhsm_token_label = u'ipaDNSSEC' - softhsm_slot = 0 - replica_keylabel_template = u"dnssec-replica:%s" - --def check_inst(): -- if not os.path.exists(paths.DNSSEC_KEYFROMLABEL): -- print ("Please install the 'bind-pkcs11-utils' package and start " -- "the installation again") -- return False -- return True - - def dnssec_container_exists(fqdn, suffix, dm_password=None, ldapi=False, - realm=None, autobind=ipaldap.AUTOBIND_DISABLED): -diff --git a/ipaserver/install/opendnssecinstance.py b/ipaserver/install/opendnssecinstance.py -index d68691fa32f135c7527ce28ed771757eadab4831..0f1af828ea245046330fdfab77db130ca14faba3 100644 ---- a/ipaserver/install/opendnssecinstance.py -+++ b/ipaserver/install/opendnssecinstance.py -@@ -55,14 +55,6 @@ def get_dnssec_key_masters(conn): - return keymasters_list - - --def check_inst(): -- if not os.path.exists(paths.ODS_KSMUTIL): -- print ("Please install the 'opendnssec' package and start " -- "the installation again") -- return False -- return True -- -- - class OpenDNSSECInstance(service.Service): - def __init__(self, fstore=None, dm_password=None, ldapi=False, - start_tls=False, autobind=ipaldap.AUTOBIND_ENABLED): --- -2.4.3 - diff --git a/SOURCES/0023-prevent-search-for-RADIUS-proxy-servers-by-secret.patch b/SOURCES/0023-prevent-search-for-RADIUS-proxy-servers-by-secret.patch new file mode 100644 index 0000000..915e307 --- /dev/null +++ b/SOURCES/0023-prevent-search-for-RADIUS-proxy-servers-by-secret.patch @@ -0,0 +1,37 @@ +From 57e8d1c6ff58bc58d50d0b1d501820f55a6f2837 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Thu, 21 Jul 2016 09:42:01 +0200 +Subject: [PATCH] prevent search for RADIUS proxy servers by secret + +radiusproxy-find should not allow search by proxy secret even for privileged +users so we should hide it from CLI. + +https://fedorahosted.org/freeipa/ticket/6078 + +Reviewed-By: Jan Cholasta +--- + ipaserver/plugins/radiusproxy.py | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/ipaserver/plugins/radiusproxy.py b/ipaserver/plugins/radiusproxy.py +index 5657e002c1ce66335b7697b98f95a49207c61d87..3391b8aed77205fb1a586d5472d8cfdbc9fd1cd5 100644 +--- a/ipaserver/plugins/radiusproxy.py ++++ b/ipaserver/plugins/radiusproxy.py +@@ -169,6 +169,14 @@ class radiusproxy_find(LDAPSearch): + '%(count)d RADIUS proxy server matched', '%(count)d RADIUS proxy servers matched', 0 + ) + ++ def get_options(self): ++ for option in super(radiusproxy_find, self).get_options(): ++ if option.name == 'ipatokenradiussecret': ++ option = option.clone(flags={'no_option'}) ++ ++ yield option ++ ++ + @register() + class radiusproxy_show(LDAPRetrieve): + __doc__ = _('Display information about a RADIUS proxy server.') +-- +2.7.4 + diff --git a/SOURCES/0024-dcerpc-Expand-explanation-for-WERR_ACCESS_DENIED.patch b/SOURCES/0024-dcerpc-Expand-explanation-for-WERR_ACCESS_DENIED.patch deleted file mode 100644 index b400a03..0000000 --- a/SOURCES/0024-dcerpc-Expand-explanation-for-WERR_ACCESS_DENIED.patch +++ /dev/null @@ -1,76 +0,0 @@ -From c4859813a5fd89082c9c05a3808f9b6cb97ca5d0 Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Wed, 15 Jul 2015 15:38:50 +0200 -Subject: [PATCH] dcerpc: Expand explanation for WERR_ACCESS_DENIED - -It's possible for AD to contact a wrong IPA server in case the DNS -SRV records on the AD sides are not properly configured. - -Mention this case in the error message as well. - -https://fedorahosted.org/freeipa/ticket/5013 - -Reviewed-By: Petr Vobornik ---- - ipaserver/dcerpc.py | 36 +++++++++++++++++++++++++++++------- - 1 file changed, 29 insertions(+), 7 deletions(-) - -diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py -index a1da0a641064f59a79639d97489ff73181787a4a..97f6c1694c20f26af0861b86a1ae1adf7a970a59 100644 ---- a/ipaserver/dcerpc.py -+++ b/ipaserver/dcerpc.py -@@ -1084,22 +1084,44 @@ class TrustDomainInstance(object): - result = retrieve_netlogon_info_2(None, self, - netlogon.NETLOGON_CONTROL_TC_VERIFY, - another_domain.info['dns_domain']) -- if (result and (result.flags and netlogon.NETLOGON_VERIFY_STATUS_RETURNED)): -- if (result.pdc_connection_status[0] != 0) and (result.tc_connection_status[0] != 0): -+ -+ if result and result.flags and netlogon.NETLOGON_VERIFY_STATUS_RETURNED: -+ if result.pdc_connection_status[0] != 0 and result.tc_connection_status[0] != 0: - if result.pdc_connection_status[1] == "WERR_ACCESS_DENIED": - # Most likely AD DC hit another IPA replica which yet has no trust secret replicated -+ - # Sleep and repeat again - self.validation_attempts += 1 - if self.validation_attempts < 10: - sleep(5) - return self.verify_trust(another_domain) -- raise errors.ACIError( -- info=_('IPA master denied trust validation requests from AD DC ' -- '%(count)d times. Most likely AD DC contacted a replica ' -- 'that has no trust information replicated yet.') -- % dict(count=self.validation_attempts)) -+ -+ # If we get here, we already failed 10 times -+ srv_record_templates = ( -+ '_ldap._tcp.%s', -+ '_ldap._tcp.Default-First-Site-Name._sites.dc._msdcs.%s' -+ ) -+ -+ srv_records = ', '.join( -+ [srv_record % api.env.domain -+ for srv_record in srv_record_templates] -+ ) -+ -+ error_message = _( -+ 'IPA master denied trust validation requests from AD ' -+ 'DC %(count)d times. Most likely AD DC contacted a ' -+ 'replica that has no trust information replicated ' -+ 'yet. Additionally, please check that AD DNS is able ' -+ 'to resolve %(records)s SRV records to the correct ' -+ 'IPA server.') % dict(count=self.validation_attempts, -+ records=srv_records) -+ -+ raise errors.ACIError(info=error_message) -+ - raise assess_dcerpc_exception(*result.pdc_connection_status) -+ - return True -+ - return False - - --- -2.4.3 - diff --git a/SOURCES/0024-trust-add-handle-all-raw-options-properly.patch b/SOURCES/0024-trust-add-handle-all-raw-options-properly.patch new file mode 100644 index 0000000..dd90e03 --- /dev/null +++ b/SOURCES/0024-trust-add-handle-all-raw-options-properly.patch @@ -0,0 +1,89 @@ +From b18c50fb6f596896b35b80178368762d8b9d4a56 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Fri, 15 Jul 2016 12:38:00 +0200 +Subject: [PATCH] trust-add: handle `--all/--raw` options properly + +`trust-add` command did not handle these options correctly often resulting in +internal errors or mangled output. This patch implements a behavior which is +more in-line with the rest of the API commands. + +https://fedorahosted.org/freeipa/ticket/6059 + +Reviewed-By: Jan Cholasta +--- + ipaserver/plugins/trust.py | 41 +++++++++++++++++++++++++++-------------- + 1 file changed, 27 insertions(+), 14 deletions(-) + +diff --git a/ipaserver/plugins/trust.py b/ipaserver/plugins/trust.py +index d4676bd57054043edd07da5ec3321d755babf35c..f2e0b1ee4b261ddc4f29477f46b7f4027af18892 100644 +--- a/ipaserver/plugins/trust.py ++++ b/ipaserver/plugins/trust.py +@@ -710,6 +710,25 @@ sides. + msg_summary = _('Added Active Directory trust for realm "%(value)s"') + msg_summary_existing = _('Re-established trust to domain "%(value)s"') + ++ def _format_trust_attrs(self, result, **options): ++ ++ # Format the output into human-readable values ++ attributes = int(result['result'].get('ipanttrustattributes', [0])[0]) ++ ++ if not options.get('raw', False): ++ result['result']['trusttype'] = [trust_type_string( ++ result['result']['ipanttrusttype'][0], attributes)] ++ result['result']['trustdirection'] = [trust_direction_string( ++ result['result']['ipanttrustdirection'][0])] ++ result['result']['truststatus'] = [trust_status_string( ++ result['verified'])] ++ ++ if attributes: ++ result['result'].pop('ipanttrustattributes', None) ++ ++ result['result'].pop('ipanttrustauthoutgoing', None) ++ result['result'].pop('ipanttrustauthincoming', None) ++ + def execute(self, *keys, **options): + ldap = self.obj.backend + +@@ -729,10 +748,15 @@ sides. + else: + created_range_type = old_range['result']['iparangetype'][0] + ++ attrs_list = self.obj.default_attributes ++ if options.get('all', False): ++ attrs_list.append('*') ++ + trust_filter = "cn=%s" % result['value'] + (trusts, truncated) = ldap.find_entries( + base_dn=DN(self.api.env.container_trusts, self.api.env.basedn), +- filter=trust_filter) ++ filter=trust_filter, ++ attrs_list=attrs_list) + + result['result'] = entry_to_dict(trusts[0], **options) + +@@ -761,20 +785,9 @@ sides. + # add_new_domains_from_trust() on its own. + fetch_trusted_domains_over_dbus(self.api, self.log, result['value']) + +- # Format the output into human-readable values +- attributes = int(result['result'].get('ipanttrustattributes', [0])[0]) +- result['result']['trusttype'] = [trust_type_string( +- result['result']['ipanttrusttype'][0], attributes)] +- result['result']['trustdirection'] = [trust_direction_string( +- result['result']['ipanttrustdirection'][0])] +- result['result']['truststatus'] = [trust_status_string( +- result['verified'])] +- if attributes: +- result['result'].pop('ipanttrustattributes', None) +- ++ # Format the output into human-readable values unless `--raw` is given ++ self._format_trust_attrs(result, **options) + del result['verified'] +- result['result'].pop('ipanttrustauthoutgoing', None) +- result['result'].pop('ipanttrustauthincoming', None) + + return result + +-- +2.7.4 + diff --git a/SOURCES/0025-dcerpc-Fix-UnboundLocalError-for-ccache_name.patch b/SOURCES/0025-dcerpc-Fix-UnboundLocalError-for-ccache_name.patch deleted file mode 100644 index 27e23ca..0000000 --- a/SOURCES/0025-dcerpc-Fix-UnboundLocalError-for-ccache_name.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 45cbe4b94e59bcfa3d8968595a780bdb9f3af2f2 Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Wed, 22 Jul 2015 14:29:35 +0200 -Subject: [PATCH] dcerpc: Fix UnboundLocalError for ccache_name - -Reviewed-By: Alexander Bokovoy ---- - ipaserver/dcerpc.py | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py -index 97f6c1694c20f26af0861b86a1ae1adf7a970a59..c0aa322c5d59e7d17a4ceb90448b397613284e38 100644 ---- a/ipaserver/dcerpc.py -+++ b/ipaserver/dcerpc.py -@@ -644,6 +644,8 @@ class DomainValidator(object): - Returns LDAP result or None. - """ - -+ ccache_name = None -+ - if self._admin_creds: - (ccache_name, principal) = self.kinit_as_administrator(info['dns_domain']) - --- -2.4.3 - diff --git a/SOURCES/0025-unite-log-file-name-of-ipa-ca-install.patch b/SOURCES/0025-unite-log-file-name-of-ipa-ca-install.patch new file mode 100644 index 0000000..0e10ba9 --- /dev/null +++ b/SOURCES/0025-unite-log-file-name-of-ipa-ca-install.patch @@ -0,0 +1,54 @@ +From 41b85da8629e69efcc9acf65ba81ab79d38dc609 Mon Sep 17 00:00:00 2001 +From: Petr Vobornik +Date: Fri, 15 Jul 2016 16:25:36 +0200 +Subject: [PATCH] unite log file name of ipa-ca-install + +ipa-ca-install said that it used + /var/log/ipareplica-ca-install.log +but in fact it used + /var/log/ipaserver-ca-install.log + +This patch unites it to ipareplica-ca-install.log + +It was chosen because of backwards compatibility - ipareplica-ca-install +was more commonly used. ipaserver-ca-install.log was used only in rare +CA less -> CA installation. + +https://fedorahosted.org/freeipa/ticket/6086 + +Reviewed-By: Martin Babinsky +Reviewed-By: Jan Cholasta +Reviewed-By: Florence Blanc-Renaud +--- + install/tools/ipa-ca-install | 2 +- + ipaplatform/base/paths.py | 1 - + 2 files changed, 1 insertion(+), 2 deletions(-) + +diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install +index ed685920cbadb9cd3fc80865afb1610ca42f8b13..985e7413aa06900976934c329757ce45da5ff12d 100755 +--- a/install/tools/ipa-ca-install ++++ b/install/tools/ipa-ca-install +@@ -285,7 +285,7 @@ def main(): + cainstance.is_ca_installed_locally()): + sys.exit("CA is already installed on this host.") + +- standard_logging_setup(paths.IPASERVER_CA_INSTALL_LOG, debug=options.debug) ++ standard_logging_setup(log_file_name, debug=options.debug) + root_logger.debug("%s was invoked with options: %s,%s", + sys.argv[0], safe_options, filename) + root_logger.debug("IPA version %s", version.VENDOR_VERSION) +diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py +index d6fbe32f6839a5db40148777132ba1454cbc3382..1507ac36da5b40447c951ee608053a09b2db2fc3 100644 +--- a/ipaplatform/base/paths.py ++++ b/ipaplatform/base/paths.py +@@ -307,7 +307,6 @@ class BasePathNamespace(object): + IPAREPLICA_CONNCHECK_LOG = "/var/log/ipareplica-conncheck.log" + IPAREPLICA_INSTALL_LOG = "/var/log/ipareplica-install.log" + IPARESTORE_LOG = "/var/log/iparestore.log" +- IPASERVER_CA_INSTALL_LOG = "/var/log/ipaserver-ca-install.log" + IPASERVER_INSTALL_LOG = "/var/log/ipaserver-install.log" + IPASERVER_KRA_INSTALL_LOG = "/var/log/ipaserver-kra-install.log" + IPASERVER_KRA_UNINSTALL_LOG = "/var/log/ipaserver-kra-uninstall.log" +-- +2.7.4 + diff --git a/SOURCES/0026-Host-del-fix-behavior-of-updatedns-and-PTR-records.patch b/SOURCES/0026-Host-del-fix-behavior-of-updatedns-and-PTR-records.patch new file mode 100644 index 0000000..0f2f5ff --- /dev/null +++ b/SOURCES/0026-Host-del-fix-behavior-of-updatedns-and-PTR-records.patch @@ -0,0 +1,95 @@ +From 57b757807a53400b8addb19d323f5691122c3ebb Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Thu, 21 Jul 2016 13:18:34 +0200 +Subject: [PATCH] Host-del: fix behavior of --updatedns and PTR records + +* target for ptr record must be absolute domain name +* zone is detected using DNS system instead of random splitting of +hostname + +https://fedorahosted.org/freeipa/ticket/6060 + +Reviewed-By: Petr Spacek +--- + ipaserver/plugins/host.py | 26 +++++++++++++++----------- + 1 file changed, 15 insertions(+), 11 deletions(-) + +diff --git a/ipaserver/plugins/host.py b/ipaserver/plugins/host.py +index f342b05c87b936ab7b99009cfb0f6d3acde4ef93..413dcf15e0423170d8334902b9dcf8fb5aa14de6 100644 +--- a/ipaserver/plugins/host.py ++++ b/ipaserver/plugins/host.py +@@ -18,6 +18,9 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + ++from __future__ import absolute_import ++ ++import dns.resolver + import string + + import six +@@ -134,7 +137,7 @@ register = Registry() + host_pwd_chars = string.digits + string.ascii_letters + '_,.@+-=' + + +-def remove_ptr_rec(ipaddr, host, domain): ++def remove_ptr_rec(ipaddr, fqdn): + """ + Remove PTR record of IP address (ipaddr) + :return: True if PTR record was removed, False if record was not found +@@ -143,13 +146,12 @@ def remove_ptr_rec(ipaddr, host, domain): + try: + revzone, revname = get_reverse_zone(ipaddr) + +- # in case domain is in FQDN form with a trailing dot, we needn't add +- # another one, in case it has no trailing dot, dnsrecord-del will +- # normalize the entry +- delkw = {'ptrrecord': "%s.%s" % (host, domain)} ++ # assume that target in PTR record is absolute name (otherwise it is ++ # non-standard configuration) ++ delkw = {'ptrrecord': u"%s" % fqdn.make_absolute()} + + api.Command['dnsrecord_del'](revzone, revname, **delkw) +- except errors.NotFound: ++ except (errors.NotFound, errors.AttrValueNotFound): + api.log.debug('PTR record of ipaddr %s not found', ipaddr) + return False + +@@ -794,13 +796,15 @@ class host_del(LDAPDelete): + + if updatedns: + # Remove A, AAAA, SSHFP and PTR records of the host +- parts = fqdn.split('.') +- domain = unicode('.'.join(parts[1:])) ++ fqdn_dnsname = DNSName(fqdn).make_absolute() ++ zone = DNSName(dns.resolver.zone_for_name(fqdn_dnsname)) ++ relative_hostname = fqdn_dnsname.relativize(zone) ++ + # Get all resources for this host + rec_removed = False + try: + record = api.Command['dnsrecord_show']( +- domain, parts[0])['result'] ++ zone, relative_hostname)['result'] + except errors.NotFound: + pass + else: +@@ -808,13 +812,13 @@ class host_del(LDAPDelete): + for attr in ('arecord', 'aaaarecord'): + for val in record.get(attr, []): + rec_removed = ( +- remove_ptr_rec(val, parts[0], domain) or ++ remove_ptr_rec(val, fqdn_dnsname) or + rec_removed + ) + try: + # remove all A, AAAA, SSHFP records of the host + api.Command['dnsrecord_mod']( +- domain, ++ zone, + record['idnsname'][0], + arecord=[], + aaaarecord=[], +-- +2.7.4 + diff --git a/SOURCES/0026-fix-broken-search-for-users-by-their-manager.patch b/SOURCES/0026-fix-broken-search-for-users-by-their-manager.patch deleted file mode 100644 index be8fffb..0000000 --- a/SOURCES/0026-fix-broken-search-for-users-by-their-manager.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 29d63aa08fc648c3dfbc9ae4cc74991eba2fb7a0 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Thu, 23 Jul 2015 10:44:08 +0200 -Subject: [PATCH] fix broken search for users by their manager - -The patch fixes incorrect construction of search filter when using `ipa -user-find` with '--manager' option. - -https://fedorahosted.org/freeipa/ticket/5146 - -Reviewed-By: Tomas Babej ---- - ipalib/plugins/baseuser.py | 8 ++++++++ - ipalib/plugins/stageuser.py | 7 ------- - ipalib/plugins/user.py | 4 ---- - 3 files changed, 8 insertions(+), 11 deletions(-) - -diff --git a/ipalib/plugins/baseuser.py b/ipalib/plugins/baseuser.py -index 9068ef0fd266a4460697ee45f29c80b74662fab2..bd66cf5a3e3a4e6c18d1a54408f969668c834fab 100644 ---- a/ipalib/plugins/baseuser.py -+++ b/ipalib/plugins/baseuser.py -@@ -561,6 +561,14 @@ class baseuser_find(LDAPSearch): - """ - Prototype command plugin to be implemented by real plugin - """ -+ def args_options_2_entry(self, *args, **options): -+ newoptions = {} -+ self.common_enhance_options(newoptions, **options) -+ options.update(newoptions) -+ -+ return super(baseuser_find, self).args_options_2_entry( -+ *args, **options) -+ - def common_enhance_options(self, newoptions, **options): - # assure the manager attr is a dn, not just a bare uid - manager = options.get('manager') -diff --git a/ipalib/plugins/stageuser.py b/ipalib/plugins/stageuser.py -index 6cbc8f4ab07f2c1172f2b2c45bfe8f30a74938b3..49a762a922b21bd6d0824787d9305417f5e47ee6 100644 ---- a/ipalib/plugins/stageuser.py -+++ b/ipalib/plugins/stageuser.py -@@ -449,13 +449,6 @@ class stageuser_find(baseuser_find): - member_attributes = ['memberof'] - has_output_params = baseuser_find.has_output_params + stageuser_output_params - -- def execute(self, *args, **options): -- newoptions = {} -- self.common_enhance_options(newoptions, **options) -- options.update(newoptions) -- -- return super(stageuser_find, self).execute(self, *args, **options) -- - def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *keys, **options): - assert isinstance(base_dn, DN) - -diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py -index 9bd7bf7e5242234ead4c39a6346e57865b2e2124..206b380efb6472fb040dde33ac80e3f66c00c138 100644 ---- a/ipalib/plugins/user.py -+++ b/ipalib/plugins/user.py -@@ -730,10 +730,6 @@ class user_find(baseuser_find): - return ("(&(objectclass=posixaccount)(krbprincipalname=%s))"%\ - getattr(context, 'principal'), base_dn, scope) - -- newoptions = {} -- self.common_enhance_options(newoptions, **options) -- options.update(newoptions) -- - preserved = options.get('preserved', False) - if preserved is None: - base_dn = self.api.env.basedn --- -2.4.3 - diff --git a/SOURCES/0027-dcerpc-Add-get_trusted_domain_object_type-method.patch b/SOURCES/0027-dcerpc-Add-get_trusted_domain_object_type-method.patch deleted file mode 100644 index d9aaad1..0000000 --- a/SOURCES/0027-dcerpc-Add-get_trusted_domain_object_type-method.patch +++ /dev/null @@ -1,62 +0,0 @@ -From c21bb52f339a38aaf7d5b4285447e5a166fb4fcf Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Wed, 22 Jul 2015 14:00:37 +0200 -Subject: [PATCH] dcerpc: Add get_trusted_domain_object_type method - -https://fedorahosted.org/freeipa/ticket/5029 - -Reviewed-By: Alexander Bokovoy ---- - ipaserver/dcerpc.py | 29 +++++++++++++++++++++++++++++ - 1 file changed, 29 insertions(+) - -diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py -index c0aa322c5d59e7d17a4ceb90448b397613284e38..c604fa3eae4cf94d719190a5a3e3de15d3841d24 100644 ---- a/ipaserver/dcerpc.py -+++ b/ipaserver/dcerpc.py -@@ -107,6 +107,14 @@ dcerpc_error_messages = { - errors.RequirementError(name=_('At least the domain or IP address should be specified')), - } - -+pysss_type_key_translation_dict = { -+ pysss_nss_idmap.ID_USER: 'user', -+ pysss_nss_idmap.ID_GROUP: 'group', -+ # Used for users with magic private groups -+ pysss_nss_idmap.ID_BOTH: 'both', -+} -+ -+ - def assess_dcerpc_exception(num=None,message=None): - """ - Takes error returned by Samba bindings and converts it into -@@ -368,6 +376,27 @@ class DomainValidator(object): - raise errors.ValidationError(name=_('trusted domain object'), - error= _('Trusted domain did not return a valid SID for the object')) - -+ def get_trusted_domain_object_type(self, name_or_sid): -+ """ -+ Return the type of the object corresponding to the given name in -+ the trusted domain, which is either 'user', 'group' or 'both'. -+ The 'both' types is used for users with magic private groups. -+ """ -+ -+ object_type = None -+ -+ if is_sid_valid(name_or_sid): -+ result = pysss_nss_idmap.getnamebysid(name_or_sid) -+ else: -+ result = pysss_nss_idmap.getsidbyname(name_or_sid) -+ -+ if name_or_sid in result: -+ object_type = result[name_or_sid].get(pysss_nss_idmap.TYPE_KEY) -+ -+ # Do the translation to hide pysss_nss_idmap constants -+ # from higher-level code -+ return pysss_type_key_translation_dict.get(object_type) -+ - def get_trusted_domain_object_from_sid(self, sid): - root_logger.debug("Converting SID to object name: %s" % sid) - --- -2.4.3 - diff --git a/SOURCES/0027-help-Add-dnsserver-commands-to-help-topic-dns.patch b/SOURCES/0027-help-Add-dnsserver-commands-to-help-topic-dns.patch new file mode 100644 index 0000000..a0b00c8 --- /dev/null +++ b/SOURCES/0027-help-Add-dnsserver-commands-to-help-topic-dns.patch @@ -0,0 +1,67 @@ +From a7c1e25d3d1c065d0a56e63741c8e5b05ee880a6 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Fri, 15 Jul 2016 11:55:19 +0200 +Subject: [PATCH] help: Add dnsserver commands to help topic 'dns' + +https://fedorahosted.org/freeipa/ticket/6069 + +Reviewed-By: Petr Spacek +--- + ipaserver/plugins/dnsserver.py | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/ipaserver/plugins/dnsserver.py b/ipaserver/plugins/dnsserver.py +index beddec04230d810479fff9612721cf12260bbb3a..d635722a6b6aaea942d49456a04f5d0480d344c9 100644 +--- a/ipaserver/plugins/dnsserver.py ++++ b/ipaserver/plugins/dnsserver.py +@@ -48,6 +48,8 @@ EXAMPLES: + + register = Registry() + ++topic = None ++ + dnsserver_object_class = ['top', 'idnsServerConfigObject'] + + @register() +@@ -149,6 +151,7 @@ class dnsserver(LDAPObject): + @register() + class dnsserver_mod(LDAPUpdate): + __doc__ = _('Modify DNS server configuration') ++ topic = 'dns' + + msg_summary = _('Modified DNS server "%(value)s"') + +@@ -156,6 +159,7 @@ class dnsserver_mod(LDAPUpdate): + @register() + class dnsserver_find(LDAPSearch): + __doc__ = _('Search for DNS servers.') ++ topic = 'dns' + + msg_summary = ngettext( + '%(count)d DNS server matched', +@@ -166,6 +170,7 @@ class dnsserver_find(LDAPSearch): + @register() + class dnsserver_show(LDAPRetrieve): + __doc__=_('Display configuration of a DNS server.') ++ topic = 'dns' + + + @register() +@@ -175,6 +180,7 @@ class dnsserver_add(LDAPCreate, Local): + Be careful in future this will be transformed to public API call + """ + __doc__ = _('Add a new DNS server.') ++ topic = 'dns' + + msg_summary = _('Added new DNS server "%(value)s"') + +@@ -186,5 +192,6 @@ class dnsserver_del(LDAPDelete, Local): + Be careful in future this will be transformed to public API call + """ + __doc__ = _('Delete a DNS server') ++ topic = 'dns' + + msg_summary = _('Deleted DNS server "%(value)s"') +-- +2.7.4 + diff --git a/SOURCES/0028-DNS-Locations-fix-update-system-records-unpacking-er.patch b/SOURCES/0028-DNS-Locations-fix-update-system-records-unpacking-er.patch new file mode 100644 index 0000000..dc26a25 --- /dev/null +++ b/SOURCES/0028-DNS-Locations-fix-update-system-records-unpacking-er.patch @@ -0,0 +1,35 @@ +From 0f655b619eae8320757cd6d18f9f1dda6ab2c6ed Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Fri, 22 Jul 2016 13:32:31 +0200 +Subject: [PATCH] DNS Locations: fix update-system-records unpacking error + +Method IPASystemRecords.records_list_from_node returns only list +consists only from record names not tuple, which caused unpacking error + +https://fedorahosted.org/freeipa/ticket/6117 + +Reviewed-By: Nikhil Dehadrai +--- + ipaserver/install/bindinstance.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py +index 844fb04a9d9feca936211964b75a0b3468ba663b..7538e145cbe37dfc21963d97dea0e835e3bd5072 100644 +--- a/ipaserver/install/bindinstance.py ++++ b/ipaserver/install/bindinstance.py +@@ -1139,10 +1139,10 @@ class BindInstance(service.Service): + root_logger.error("Update of following records failed:") + for attr in (failed_ipa_rec, failed_loc_rec): + for rname, node, error in attr: +- for record, e in IPASystemRecords.records_list_from_node( ++ for record in IPASystemRecords.records_list_from_node( + rname, node + ): +- root_logger.error("%s (%s)", record, e) ++ root_logger.error("%s (%s)", record, error) + + def check_global_configuration(self): + """ +-- +2.7.4 + diff --git a/SOURCES/0028-idviews-Restrict-anchor-to-name-and-name-to-anchor-c.patch b/SOURCES/0028-idviews-Restrict-anchor-to-name-and-name-to-anchor-c.patch deleted file mode 100644 index 21dea02..0000000 --- a/SOURCES/0028-idviews-Restrict-anchor-to-name-and-name-to-anchor-c.patch +++ /dev/null @@ -1,98 +0,0 @@ -From 964bce5fd60bbb52be1dcc67e628a6c1ab62e356 Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Thu, 23 Jul 2015 12:36:53 +0200 -Subject: [PATCH] idviews: Restrict anchor to name and name to anchor - conversions - -When converting the ID override anchor from AD SID representation to -the object name, we need to properly restrict the type of the object -that is being resolved. - -The same restriction applies for the opposite direction, when -converting the object name to it's SID. - -https://fedorahosted.org/freeipa/ticket/5029 - -Reviewed-By: Alexander Bokovoy ---- - ipalib/plugins/idviews.py | 50 +++++++++++++++++++++++++++++++++++++++++++---- - 1 file changed, 46 insertions(+), 4 deletions(-) - -diff --git a/ipalib/plugins/idviews.py b/ipalib/plugins/idviews.py -index 67f52f886f0e19288a829616603c7aef6768f8db..c4f748132642f8702dcd12d38367dc36f4bc4a3c 100644 ---- a/ipalib/plugins/idviews.py -+++ b/ipalib/plugins/idviews.py -@@ -432,6 +432,36 @@ class idview_unapply(baseidview_apply): - - - # ID overrides helper methods -+def verify_trusted_domain_object_type(validator, desired_type, name_or_sid): -+ -+ object_type = validator.get_trusted_domain_object_type(name_or_sid) -+ -+ if object_type == desired_type: -+ # In case SSSD returns the same type as the type being -+ # searched, no problems here. -+ return True -+ -+ elif desired_type == 'user' and object_type == 'both': -+ # Type both denotes users with magic private groups. -+ # Overriding attributes for such users is OK. -+ return True -+ -+ elif desired_type == 'group' and object_type == 'both': -+ # However, overriding attributes for magic private groups -+ # does not make sense. One should override the GID of -+ # the user itself. -+ -+ raise errors.ConversionError( -+ name='identifier', -+ error=_('You are trying to reference a magic private group ' -+ 'which is not allowed to be overriden. ' -+ 'Try overriding the GID attribute of the ' -+ 'corresponding user instead.') -+ ) -+ -+ return False -+ -+ - def resolve_object_to_anchor(ldap, obj_type, obj, fallback_to_ldap): - """ - Resolves the user/group name to the anchor uuid: -@@ -482,9 +512,15 @@ def resolve_object_to_anchor(ldap, obj_type, obj, fallback_to_ldap): - sid = domain_validator.get_trusted_domain_object_sid(obj, - fallback_to_ldap=fallback_to_ldap) - -- # There is no domain prefix since SID contains information -- # about the domain -- return SID_ANCHOR_PREFIX + sid -+ # We need to verify that the object type is correct -+ type_correct = verify_trusted_domain_object_type( -+ domain_validator, obj_type, sid) -+ -+ if type_correct: -+ # There is no domain prefix since SID contains information -+ # about the domain -+ return SID_ANCHOR_PREFIX + sid -+ - except errors.ValidationError: - # Domain validator raises Validation Error if object name does not - # contain domain part (either NETBIOS\ prefix or @domain.name suffix) -@@ -539,7 +575,13 @@ def resolve_anchor_to_object_name(ldap, obj_type, anchor): - domain_validator = ipaserver.dcerpc.DomainValidator(api) - if domain_validator.is_configured(): - name = domain_validator.get_trusted_domain_object_from_sid(sid) -- return name -+ -+ # We need to verify that the object type is correct -+ type_correct = verify_trusted_domain_object_type( -+ domain_validator, obj_type, name) -+ -+ if type_correct: -+ return name - - # No acceptable object was found - raise errors.NotFound( --- -2.4.3 - diff --git a/SOURCES/0029-Fix-session-cookies.patch b/SOURCES/0029-Fix-session-cookies.patch new file mode 100644 index 0000000..dc2dd2c --- /dev/null +++ b/SOURCES/0029-Fix-session-cookies.patch @@ -0,0 +1,136 @@ +From 059ced75270c681144462dba3772812901495054 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Thu, 21 Jul 2016 16:54:43 +0200 +Subject: [PATCH] Fix session cookies + +The CLI was not using session cookies for communication with IPA API. +The kernel_keyring code was expecting the keyname to be a string, but +in python 2 a unicode was supplied (the key is built using +ipa_session_cookie:%principal and principal is a unicode). + +The patch fixes the assertions, allowing to store and retrieve the cookie. +It also adds a test with unicode key name. + +https://fedorahosted.org/freeipa/ticket/5984 + +Reviewed-By: Petr Spacek +--- + ipapython/kernel_keyring.py | 15 ++++++++------- + ipatests/test_ipapython/test_keyring.py | 15 +++++++++++++++ + 2 files changed, 23 insertions(+), 7 deletions(-) + +diff --git a/ipapython/kernel_keyring.py b/ipapython/kernel_keyring.py +index ed4868a9d8eaffdae6f717928663296bd20c762e..651fd708667420d1769e3601a8fa0b6c52604a10 100644 +--- a/ipapython/kernel_keyring.py ++++ b/ipapython/kernel_keyring.py +@@ -18,6 +18,7 @@ + # + + import os ++import six + + from ipapython.ipautil import run + +@@ -45,7 +46,7 @@ def get_real_key(key): + One cannot request a key based on the description it was created with + so find the one we're looking for. + """ +- assert isinstance(key, str) ++ assert isinstance(key, six.string_types) + result = run(['keyctl', 'search', KEYRING, KEYTYPE, key], + raiseonerr=False, capture_output=True) + if result.returncode: +@@ -53,7 +54,7 @@ def get_real_key(key): + return result.raw_output.rstrip() + + def get_persistent_key(key): +- assert isinstance(key, str) ++ assert isinstance(key, six.string_types) + result = run(['keyctl', 'get_persistent', KEYRING, key], + raiseonerr=False, capture_output=True) + if result.returncode: +@@ -73,7 +74,7 @@ def has_key(key): + """ + Returns True/False whether the key exists in the keyring. + """ +- assert isinstance(key, str) ++ assert isinstance(key, six.string_types) + try: + get_real_key(key) + return True +@@ -86,7 +87,7 @@ def read_key(key): + + Use pipe instead of print here to ensure we always get the raw data. + """ +- assert isinstance(key, str) ++ assert isinstance(key, six.string_types) + real_key = get_real_key(key) + result = run(['keyctl', 'pipe', real_key], raiseonerr=False, + capture_output=True) +@@ -99,7 +100,7 @@ def update_key(key, value): + """ + Update the keyring data. If they key doesn't exist it is created. + """ +- assert isinstance(key, str) ++ assert isinstance(key, six.string_types) + assert isinstance(value, bytes) + if has_key(key): + real_key = get_real_key(key) +@@ -114,7 +115,7 @@ def add_key(key, value): + """ + Add a key to the kernel keyring. + """ +- assert isinstance(key, str) ++ assert isinstance(key, six.string_types) + assert isinstance(value, bytes) + if has_key(key): + raise ValueError('key %s already exists' % key) +@@ -127,7 +128,7 @@ def del_key(key): + """ + Remove a key from the keyring + """ +- assert isinstance(key, str) ++ assert isinstance(key, six.string_types) + real_key = get_real_key(key) + result = run(['keyctl', 'unlink', real_key, KEYRING], + raiseonerr=False) +diff --git a/ipatests/test_ipapython/test_keyring.py b/ipatests/test_ipapython/test_keyring.py +index e22841c8f5d229d17cdd05ab9c4248eeffaab249..c81e6d95f7ebdf585ee37ecf71151c01e0001912 100644 +--- a/ipatests/test_ipapython/test_keyring.py ++++ b/ipatests/test_ipapython/test_keyring.py +@@ -28,6 +28,7 @@ import pytest + pytestmark = pytest.mark.tier0 + + TEST_KEY = 'ipa_test' ++TEST_UNICODEKEY = u'ipa_unicode' + TEST_VALUE = b'abc123' + UPDATE_VALUE = b'123abc' + +@@ -49,6 +50,10 @@ class test_keyring(object): + kernel_keyring.del_key(SIZE_256) + except ValueError: + pass ++ try: ++ kernel_keyring.del_key(TEST_UNICODEKEY) ++ except ValueError: ++ pass + + def test_01(self): + """ +@@ -150,3 +155,13 @@ class test_keyring(object): + assert(result == SIZE_1024.encode('ascii')) + + kernel_keyring.del_key(TEST_KEY) ++ ++ def test_10(self): ++ """ ++ Test a unicode key ++ """ ++ kernel_keyring.add_key(TEST_UNICODEKEY, TEST_VALUE) ++ result = kernel_keyring.read_key(TEST_UNICODEKEY) ++ assert(result == TEST_VALUE) ++ ++ kernel_keyring.del_key(TEST_UNICODEKEY) +-- +2.7.4 + diff --git a/SOURCES/0029-idviews-Enforce-objectclass-check-in-idoverride-del.patch b/SOURCES/0029-idviews-Enforce-objectclass-check-in-idoverride-del.patch deleted file mode 100644 index be14df0..0000000 --- a/SOURCES/0029-idviews-Enforce-objectclass-check-in-idoverride-del.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 9fedf58eb1282560957edc1f36356602b55a736d Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Thu, 23 Jul 2015 14:00:06 +0200 -Subject: [PATCH] idviews: Enforce objectclass check in idoverride*-del - -Even with anchor to sid type checking, it would be still -possible to delete a user ID override by specifying a group -raw anchor and vice versa. - -This patch introduces a objectclass check in idoverride*-del -commands to prevent that. - -https://fedorahosted.org/freeipa/ticket/5029 - -Reviewed-By: Alexander Bokovoy ---- - ipalib/plugins/idviews.py | 19 +++++++++++++++++++ - 1 file changed, 19 insertions(+) - -diff --git a/ipalib/plugins/idviews.py b/ipalib/plugins/idviews.py -index c4f748132642f8702dcd12d38367dc36f4bc4a3c..2e6e84510d3caa3636d3f0c08c56403866ff54f9 100644 ---- a/ipalib/plugins/idviews.py -+++ b/ipalib/plugins/idviews.py -@@ -716,6 +716,25 @@ class baseidoverride_del(LDAPDelete): - - takes_options = LDAPDelete.takes_options + (fallback_to_ldap_option,) - -+ def pre_callback(self, ldap, dn, *keys, **options): -+ assert isinstance(dn, DN) -+ -+ # Make sure the entry we're deleting has all the objectclasses -+ # this object requires -+ try: -+ entry = ldap.get_entry(dn, ['objectclass']) -+ except errors.NotFound: -+ self.obj.handle_not_found(*keys) -+ -+ required_object_classes = set(self.obj.object_class) -+ actual_object_classes = set(entry['objectclass']) -+ -+ # If not, treat it as a failed search -+ if not required_object_classes.issubset(actual_object_classes): -+ self.obj.handle_not_found(*keys) -+ -+ return dn -+ - - class baseidoverride_mod(LDAPUpdate): - __doc__ = _('Modify an ID override.') --- -2.4.3 - diff --git a/SOURCES/0030-Use-copy-when-replacing-files-to-keep-SELinux-contex.patch b/SOURCES/0030-Use-copy-when-replacing-files-to-keep-SELinux-contex.patch new file mode 100644 index 0000000..ac00108 --- /dev/null +++ b/SOURCES/0030-Use-copy-when-replacing-files-to-keep-SELinux-contex.patch @@ -0,0 +1,38 @@ +From 602d1c5190cfb879f81ced19e60d1eb08bd559f0 Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Thu, 21 Jul 2016 18:49:57 +0200 +Subject: [PATCH] Use copy when replacing files to keep SELinux context + +When installer replaces any file with newer, it must use 'copy' instead of +'mv' to keep SELinux context valid. + +https://fedorahosted.org/freeipa/ticket/6111 + +Reviewed-By: Petr Spacek +--- + ipapython/ipautil.py | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py +index 763a99c117e22a4ac49d8d34b38230f3da7c8435..9964fba4f694b57242b3bd3065a418917d977533 100644 +--- a/ipapython/ipautil.py ++++ b/ipapython/ipautil.py +@@ -528,10 +528,14 @@ def dir_exists(filename): + except Exception: + return False + ++ + def install_file(fname, dest): ++ # SELinux: use copy to keep the right context + if file_exists(dest): + os.rename(dest, dest + ".orig") +- shutil.move(fname, dest) ++ shutil.copy(fname, dest) ++ os.remove(fname) ++ + + def backup_file(fname): + if file_exists(fname): +-- +2.7.4 + diff --git a/SOURCES/0030-idviews-Check-for-the-Default-Trust-View-only-if-app.patch b/SOURCES/0030-idviews-Check-for-the-Default-Trust-View-only-if-app.patch deleted file mode 100644 index 2f74590..0000000 --- a/SOURCES/0030-idviews-Check-for-the-Default-Trust-View-only-if-app.patch +++ /dev/null @@ -1,50 +0,0 @@ -From f12e0e81f1cc6af2034c535866c3bfeddce8321d Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Tue, 21 Jul 2015 12:44:37 +0200 -Subject: [PATCH] idviews: Check for the Default Trust View only if applying - the view - -Currently, the code wrongly validates the idview-unapply command. Move -check for the forbidden application of the Default Trust View into -the correct logical branch. - -https://fedorahosted.org/freeipa/ticket/4969 - -Reviewed-By: Martin Basti ---- - ipalib/plugins/idviews.py | 14 ++++++++------ - 1 file changed, 8 insertions(+), 6 deletions(-) - -diff --git a/ipalib/plugins/idviews.py b/ipalib/plugins/idviews.py -index 2e6e84510d3caa3636d3f0c08c56403866ff54f9..ceb277020d1325bfd1607bcd4b05f4069ae9508d 100644 ---- a/ipalib/plugins/idviews.py -+++ b/ipalib/plugins/idviews.py -@@ -256,17 +256,19 @@ class baseidview_apply(LDAPQuery): - if not options.get('clear_view', False): - view_dn = self.api.Object['idview'].get_dn_if_exists(view) - assert isinstance(view_dn, DN) -+ -+ # Check that we're not applying the Default Trust View -+ if view.lower() == DEFAULT_TRUST_VIEW_NAME: -+ raise errors.ValidationError( -+ name=_('ID View'), -+ error=_('Default Trust View cannot be applied on hosts') -+ ) -+ - else: - # In case we are removing assigned view, we modify the host setting - # the ipaAssignedIDView to None - view_dn = None - -- if view.lower() == DEFAULT_TRUST_VIEW_NAME: -- raise errors.ValidationError( -- name=_('ID View'), -- error=_('Default Trust View cannot be applied on hosts') -- ) -- - completed = 0 - succeeded = {'host': []} - failed = { --- -2.4.3 - diff --git a/SOURCES/0031-baseldap-Fix-MidairCollision-instantiation-during-en.patch b/SOURCES/0031-baseldap-Fix-MidairCollision-instantiation-during-en.patch new file mode 100644 index 0000000..9b87f51 --- /dev/null +++ b/SOURCES/0031-baseldap-Fix-MidairCollision-instantiation-during-en.patch @@ -0,0 +1,38 @@ +From 25b1fb956cc8029d5030d93cf48faed823778c5e Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Mon, 25 Jul 2016 14:05:08 +0200 +Subject: [PATCH] baseldap: Fix MidairCollision instantiation during entry + modification + +https://fedorahosted.org/freeipa/ticket/6097 + +Reviewed-By: Alexander Bokovoy +--- + ipaserver/plugins/baseldap.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ipaserver/plugins/baseldap.py b/ipaserver/plugins/baseldap.py +index 6107e43a6ee17d9b9a63d9dc109664d8b232069f..f7844e3e7c59c259b9c8367d135b2dbefc3f0016 100644 +--- a/ipaserver/plugins/baseldap.py ++++ b/ipaserver/plugins/baseldap.py +@@ -1466,7 +1466,7 @@ class LDAPUpdate(LDAPQuery, crud.Update): + entry_attrs.dn, attrs_list) + except errors.NotFound: + raise errors.MidairCollision( +- format=_('the entry was deleted while being modified') ++ message=_('the entry was deleted while being modified') + ) + + self.obj.get_indirect_members(entry_attrs, attrs_list) +@@ -2344,7 +2344,7 @@ class BaseLDAPModAttribute(LDAPQuery): + entry_attrs.dn, attrs_list) + except errors.NotFound: + raise errors.MidairCollision( +- format=_('the entry was deleted while being modified') ++ message=_('the entry was deleted while being modified') + ) + + for callback in self.get_callbacks('post'): +-- +2.7.4 + diff --git a/SOURCES/0031-replication-Fix-incorrect-exception-invocation.patch b/SOURCES/0031-replication-Fix-incorrect-exception-invocation.patch deleted file mode 100644 index 8ae1032..0000000 --- a/SOURCES/0031-replication-Fix-incorrect-exception-invocation.patch +++ /dev/null @@ -1,26 +0,0 @@ -From e3925cac13a3daca4880e789a139bad265c21798 Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Fri, 24 Jul 2015 11:26:33 +0200 -Subject: [PATCH] replication: Fix incorrect exception invocation - -Reviewed-By: Tomas Babej ---- - ipaserver/install/replication.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py -index e9af88dc4356d4fd5495f4fea399ab09c75db953..2b36a5eb9287bf1789009a3198e540e333869e98 100644 ---- a/ipaserver/install/replication.py -+++ b/ipaserver/install/replication.py -@@ -1171,7 +1171,7 @@ class ReplicationManager(object): - entry = self.get_replication_agreement(hostname) - if not entry: - raise errors.NotFound( -- "Replication agreement for %s not found" % hostname) -+ reason="Replication agreement for %s not found" % hostname) - objectclass = entry.get("objectclass") - - for o in objectclass: --- -2.4.3 - diff --git a/SOURCES/0032-Create-indexes-for-krbCanonicalName-attribute.patch b/SOURCES/0032-Create-indexes-for-krbCanonicalName-attribute.patch new file mode 100644 index 0000000..7a008f3 --- /dev/null +++ b/SOURCES/0032-Create-indexes-for-krbCanonicalName-attribute.patch @@ -0,0 +1,54 @@ +From 1eed28c173336da828ac60b64b09a8b01d79fab4 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Fri, 22 Jul 2016 13:02:38 +0200 +Subject: [PATCH] Create indexes for krbCanonicalName attribute + +krbCanonicalName is for a long time among the attributes guarded by uniqueness +plugins, but there was never an index for it. Now that the attribute is really +used to store canonical principal names we need to add index for it to avoid +performance regressions. + +https://fedorahosted.org/freeipa/ticket/6100 + +Reviewed-By: Thierry Bordaz +--- + install/share/indices.ldif | 9 +++++++++ + install/updates/20-indices.update | 8 ++++++++ + 2 files changed, 17 insertions(+) + +diff --git a/install/share/indices.ldif b/install/share/indices.ldif +index 642c2f7aee78b684b3e451c2595e4f18950e449e..d853266025ae350dd7de83e11e463c6bb1ab9429 100644 +--- a/install/share/indices.ldif ++++ b/install/share/indices.ldif +@@ -269,3 +269,12 @@ ObjectClass: nsIndex + nsSystemIndex: false + nsIndexType: eq + nsIndexType: pres ++ ++dn: cn=krbCanonicalName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config ++changetype: add ++cn: krbCanonicalName ++objectClass: top ++objectClass: nsIndex ++nsSystemIndex: false ++nsIndexType: eq ++nsIndexType: sub +diff --git a/install/updates/20-indices.update b/install/updates/20-indices.update +index 445eda5ab6939f21654335ea4dd50d7b2cab008f..74961d77875515d680f34af739c984a6533eb252 100644 +--- a/install/updates/20-indices.update ++++ b/install/updates/20-indices.update +@@ -251,3 +251,11 @@ only: nsMatchingRule: caseIgnoreIA5Match + only: nsMatchingRule: caseExactIA5Match + only:nsIndexType: eq + only:nsIndexType: sub ++ ++dn: cn=krbCanonicalName,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config ++default: cn: krbCanonicalName ++default: objectClass: top ++default: objectClass: nsIndex ++only: nsSystemIndex: false ++only: nsIndexType: eq ++only: nsIndexType: sub +-- +2.7.4 + diff --git a/SOURCES/0032-webui-add-Kerberos-configuration-instructions-for-Ch.patch b/SOURCES/0032-webui-add-Kerberos-configuration-instructions-for-Ch.patch deleted file mode 100644 index 4693fb7..0000000 --- a/SOURCES/0032-webui-add-Kerberos-configuration-instructions-for-Ch.patch +++ /dev/null @@ -1,149 +0,0 @@ -From dc0d09f6e6a5681fa4c4146e6df6872dccc40b68 Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Fri, 17 Jul 2015 15:57:30 +0200 -Subject: [PATCH] webui: add Kerberos configuration instructions for Chrome - -* IE section moved at the end -* Chrome section added -* FF and IE icons removed - -https://fedorahosted.org/freeipa/ticket/823 - -Reviewed-By: Martin Basti ---- - install/html/ssbrowser.html | 111 +++++++++++++++++++++++++++++++------------- - 1 file changed, 80 insertions(+), 31 deletions(-) - -diff --git a/install/html/ssbrowser.html b/install/html/ssbrowser.html -index d90103228150a60bd49e91ea8c64891d53d75d7b..685800e16e6e77c70adf905acfca2996513d1e1d 100644 ---- a/install/html/ssbrowser.html -+++ b/install/html/ssbrowser.html -@@ -54,38 +54,8 @@ -
-
-

Browser Kerberos Setup

--

Internet ExplorerInternet Explorer Configuration

--

-- Once you are able to log into the workstation with your kerberos key you are now able to use that ticket in Internet Explorer. --

--

-- Login to the Windows machine using an account of your Kerberos realm (administrative domain) --

--

-- In Internet Explorer, click Tools, and then click Internet Options. --

--
--
    --
  1. Click the Security tab
  2. --
  3. Click Local intranet
  4. --
  5. Click Sites
  6. --
  7. Click Advanced
  8. --
  9. Add your domain to the list
  10. --
--
    --
  1. Click the Security tab
  2. --
  3. Click Local intranet
  4. --
  5. Click Custom Level
  6. --
  7. Select Automatic logon only in Intranet zone
  8. --
-- --
    --
  1. Visit a kerberized web site using IE (You must use the fully-qualified Domain Name in the URL)
  2. --
  3. You are all set.
  4. --
--
- --

FirefoxFirefox Configuration

-+

Firefox

- -

- You can configure Firefox to use Kerberos for Single Sign-on. The following instructions will guide you in configuring your web browser to send your Kerberos credentials to the appropriate Key Distribution Center which enables Single Sign-on. -@@ -117,6 +87,85 @@ - - - -+

Chrome

-+ -+

-+ You can configure Chrome to use Kerberos for Single Sign-on. The following instructions will guide you in configuring your web browser to send your Kerberos credentials to the appropriate Key Distribution Center which enables Single Sign-on. -+

-+ -+

Import CA Certificate

-+
    -+
  1. -+ Download the CA certificate. Alternatively, if the host is also an IdM client, you can find the certificate in /etc/ipa/ca.crt. -+
  2. -+
  3. -+ Click the menu button with the Customize and control Google Chrome tooltip, which is by default in the top right-hand corner of Chrome, and click Settings. -+
  4. -+
  5. -+ Click Show advanced settings to display more options, and then click the Manage certificates button located under the HTTPS/SSL heading. -+
  6. -+
  7. -+ In the Authorities tab, click the Import button at the bottom. -+
  8. -+
  9. Select the CA certificate file that you downloaded in the first step.
  10. -+
-+ -+

-+ Enable SPNEGO (Simple and Protected GSSAPI Negotiation Mechanism) to Use Kerberos Authentication -+ in Chrome -+

-+
    -+
  1. -+ Make sure you have the necessary directory created by running: -+
    -+ [root@client]# mkdir -p /etc/opt/chrome/policies/managed/ -+
    -+
  2. -+
  3. -+ Create a new /etc/opt/chrome/policies/managed/mydomain.json file with write privileges limited to the system administrator or root, and include the following line: -+
    -+ { "AuthServerWhitelist": "*.example.com." } -+
    -+
    -+ You can do this by running: -+
    -+
    -+ [root@server]# echo '{ "AuthServerWhitelist": "*.example.com." }' > /etc/opt/chrome/policies/managed/mydomain.json -+
    -+
  4. -+
-+ -+

Internet Explorer

-+

-+ Once you are able to log into the workstation with your kerberos key you are now able to use that ticket in Internet Explorer. -+

-+

-+ Login to the Windows machine using an account of your Kerberos realm (administrative domain) -+

-+

-+ In Internet Explorer, click Tools, and then click Internet Options. -+

-+
-+
    -+
  1. Click the Security tab
  2. -+
  3. Click Local intranet
  4. -+
  5. Click Sites
  6. -+
  7. Click Advanced
  8. -+
  9. Add your domain to the list
  10. -+
-+
    -+
  1. Click the Security tab
  2. -+
  3. Click Local intranet
  4. -+
  5. Click Custom Level
  6. -+
  7. Select Automatic logon only in Intranet zone
  8. -+
-+ -+
    -+
  1. Visit a kerberized web site using IE (You must use the fully-qualified Domain Name in the URL)
  2. -+
  3. You are all set.
  4. -+
-+
-+ -
-
- --- -2.4.3 - diff --git a/SOURCES/0033-Remove-ico-files-from-Makefile.patch b/SOURCES/0033-Remove-ico-files-from-Makefile.patch deleted file mode 100644 index 620acff..0000000 --- a/SOURCES/0033-Remove-ico-files-from-Makefile.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 56cdac487c35623b89881df4dd39713fdd36cb7c Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Mon, 27 Jul 2015 16:06:39 +0200 -Subject: [PATCH] Remove ico files from Makefile - -Icons were removed in a4be844809179ff0a05286606df1487d81a70022 but still -persist in Makefile. This patch fixes Makefile. - -https://fedorahosted.org/freeipa/ticket/823 - -Reviewed-By: Martin Babinsky ---- - install/ui/images/Makefile.am | 2 -- - 1 file changed, 2 deletions(-) - -diff --git a/install/ui/images/Makefile.am b/install/ui/images/Makefile.am -index e74d747b79ad14ef2f5b9e539c348670796fec8a..7d85d7e8203ca54f5b8fddeb55d86e106f077140 100644 ---- a/install/ui/images/Makefile.am -+++ b/install/ui/images/Makefile.am -@@ -4,9 +4,7 @@ appdir = $(IPA_DATA_DIR)/ui/images - app_DATA = \ - facet-tab-off.png \ - facet-tab-on.png \ -- firefox-icon.png \ - header-logo.png \ -- ie-icon.png \ - login-screen-background.jpg \ - login-screen-logo.png \ - product-name.png \ --- -2.4.3 - diff --git a/SOURCES/0033-harden-the-check-for-trust-namespace-overlap-in-new-.patch b/SOURCES/0033-harden-the-check-for-trust-namespace-overlap-in-new-.patch new file mode 100644 index 0000000..8bf5ee6 --- /dev/null +++ b/SOURCES/0033-harden-the-check-for-trust-namespace-overlap-in-new-.patch @@ -0,0 +1,43 @@ +From 843d21620c118f283f53db77b1114d15d26dc176 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Wed, 20 Jul 2016 15:46:22 +0200 +Subject: [PATCH] harden the check for trust namespace overlap in new + principals + +This check must handle the possibility of optional attributes +(ipantadditionalsuffixes and ipantflatname) missing in the trusted domain +entry. + +https://fedorahosted.org/freeipa/ticket/6099 + +Reviewed-By: David Kupka +--- + ipalib/util.py | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/ipalib/util.py b/ipalib/util.py +index d101514cad4f35fd9a09d84b549ffa86de432f70..e0fc178c4af2056d04ad88a3923daa7d127fe307 100644 +--- a/ipalib/util.py ++++ b/ipalib/util.py +@@ -968,11 +968,15 @@ def check_principal_realm_in_trust_namespace(api_instance, *keys): + trust_suffix_namespace = set() + + for obj in trust_objects: +- trust_suffix_namespace.update( +- set(upn.lower() for upn in obj['ipantadditionalsuffixes'])) ++ nt_suffixes = obj.get('ipantadditionalsuffixes', []) + + trust_suffix_namespace.update( +- set((obj['cn'][0].lower(), obj['ipantflatname'][0].lower()))) ++ set(upn.lower() for upn in nt_suffixes)) ++ ++ if 'ipantflatname' in obj: ++ trust_suffix_namespace.add(obj['ipantflatname'][0].lower()) ++ ++ trust_suffix_namespace.add(obj['cn'][0].lower()) + + for principal in keys[-1]: + realm = principal.realm +-- +2.7.4 + diff --git a/SOURCES/0034-ACI-plugin-correctly-parse-bind-rules-enclosed-in-pa.patch b/SOURCES/0034-ACI-plugin-correctly-parse-bind-rules-enclosed-in-pa.patch deleted file mode 100644 index 2268504..0000000 --- a/SOURCES/0034-ACI-plugin-correctly-parse-bind-rules-enclosed-in-pa.patch +++ /dev/null @@ -1,47 +0,0 @@ -From c00b3fac15439828ce0ecffa181d1b263ad505a7 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Thu, 23 Jul 2015 15:45:35 +0200 -Subject: [PATCH] ACI plugin: correctly parse bind rules enclosed in - parentheses - -Since bind rule such as `(userdn = "ldap:///anyone")` is also a valid -statement, the ipalib ACI parser was updated to handle this case. - -https://fedorahosted.org/freeipa/ticket/5037 - -Reviewed-By: Martin Basti ---- - ipalib/aci.py | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/ipalib/aci.py b/ipalib/aci.py -index a55732bf19e58d8a4b36fa18bee2725d5b6584da..f78c5327dbe659240f046ae15622e798c8552829 100755 ---- a/ipalib/aci.py -+++ b/ipalib/aci.py -@@ -26,10 +26,11 @@ import re - ACIPat = re.compile(r'\(version\s+3.0\s*;\s*ac[li]\s+\"([^\"]*)\"\s*;\s*([^;]*);\s*\)', re.UNICODE) - - # Break the permissions/bind_rules out --PermPat = re.compile(r'(\w+)\s*\((.*)\)\s+(.*)', re.UNICODE) -+PermPat = re.compile(r'(\w+)\s*\(([^()]*)\)\s*(.*)', re.UNICODE) - - # Break the bind rule out --BindPat = re.compile(r'([a-zA-Z0-9;\.]+)\s*(\!?=)\s*(.*)', re.UNICODE) -+BindPat = re.compile(r'\(?([a-zA-Z0-9;\.]+)\s*(\!?=)\s*\"(.*)\"\)?', -+ re.UNICODE) - - ACTIONS = ["allow", "deny"] - -@@ -193,6 +194,9 @@ class ACI: - self.target['target']['operator'] = operator - - def set_bindrule(self, bindrule): -+ if bindrule.startswith('(') != bindrule.endswith(')'): -+ raise SyntaxError("non-matching parentheses in bindrule") -+ - match = BindPat.match(bindrule) - if not match or len(match.groups()) < 3: - raise SyntaxError, "malformed bind rule" --- -2.4.3 - diff --git a/SOURCES/0034-Revert-Enable-vault-commands-on-client.patch b/SOURCES/0034-Revert-Enable-vault-commands-on-client.patch new file mode 100644 index 0000000..9b74d02 --- /dev/null +++ b/SOURCES/0034-Revert-Enable-vault-commands-on-client.patch @@ -0,0 +1,65 @@ +From 872e67c0121250dd41e2d6953810582f1e5dda27 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Mon, 25 Jul 2016 14:00:08 +0200 +Subject: [PATCH] Revert "Enable vault-* commands on client" + +This reverts commit 9feeaca9fb552229638ce98086aa75905a45b48d. + +https://fedorahosted.org/freeipa/ticket/6089 + +Reviewed-By: Florence Blanc-Renaud +--- + ipaclient/plugins/vault.py | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py +index a3ce6fecbfd38b342f826d8d27940d991d821e90..b7e0cfffb2fff62fdbbf438964d124fc2dd8ac36 100644 +--- a/ipaclient/plugins/vault.py ++++ b/ipaclient/plugins/vault.py +@@ -202,6 +202,10 @@ class vault_add(Local): + ), + ) + ++ @property ++ def NO_CLI(self): ++ return self.api.Command.vault_add_internal.NO_CLI ++ + def get_args(self): + for arg in self.api.Command.vault_add_internal.args(): + yield arg +@@ -395,6 +399,10 @@ class vault_mod(Local): + ), + ) + ++ @property ++ def NO_CLI(self): ++ return self.api.Command.vault_mod_internal.NO_CLI ++ + def get_args(self): + for arg in self.api.Command.vault_mod_internal.args(): + yield arg +@@ -569,6 +577,10 @@ class vault_archive(Local): + ), + ) + ++ @property ++ def NO_CLI(self): ++ return self.api.Command.vault_archive_internal.NO_CLI ++ + def get_args(self): + for arg in self.api.Command.vault_archive_internal.args(): + yield arg +@@ -813,6 +825,10 @@ class vault_retrieve(Local): + ), + ) + ++ @property ++ def NO_CLI(self): ++ return self.api.Command.vault_retrieve_internal.NO_CLI ++ + def get_args(self): + for arg in self.api.Command.vault_retrieve_internal.args(): + yield arg +-- +2.7.4 + diff --git a/SOURCES/0035-ULC-Fix-stageused-add-from-delete-command.patch b/SOURCES/0035-ULC-Fix-stageused-add-from-delete-command.patch deleted file mode 100644 index 5927ccb..0000000 --- a/SOURCES/0035-ULC-Fix-stageused-add-from-delete-command.patch +++ /dev/null @@ -1,46 +0,0 @@ -From c899fa3f5b404e9e28a149cc55684591482344f9 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Thu, 23 Jul 2015 10:52:54 +0200 -Subject: [PATCH] ULC: Fix stageused-add --from-delete command - -Nonexistent method was used to move deleted user to staged area. -Minor fixes added: - * handle not found error - * return new DN - -https://fedorahosted.org/freeipa/ticket/5145 - -Reviewed-By: David Kupka ---- - ipalib/plugins/stageuser.py | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/ipalib/plugins/stageuser.py b/ipalib/plugins/stageuser.py -index 49a762a922b21bd6d0824787d9305417f5e47ee6..41844712042c4456fc515afd316af60b612f164f 100644 ---- a/ipalib/plugins/stageuser.py -+++ b/ipalib/plugins/stageuser.py -@@ -377,16 +377,17 @@ class stageuser_add(baseuser_add): - - staging_dn = self.obj.get_dn(*keys, **options) - delete_dn = DN(staging_dn[0], self.obj.delete_container_dn, api.env.basedn) -- -+ new_dn = DN(staging_dn[0], self.obj.stage_container_dn, api.env.basedn) - # Check that this value is a Active user - try: - entry_attrs = self._exc_wrapper(keys, options, ldap.get_entry)(delete_dn, ['dn']) - except errors.NotFound: -- raise -- self._exc_wrapper(keys, options, ldap.move_entry_newsuperior)(delete_dn, str(DN(self.obj.stage_container_dn, api.env.basedn))) -+ self.obj.handle_not_found(*keys) - -+ self._exc_wrapper(keys, options, ldap.move_entry)( -+ delete_dn, new_dn) - entry_attrs = entry_to_dict(entry_attrs, **options) -- entry_attrs['dn'] = delete_dn -+ entry_attrs['dn'] = new_dn - - if self.obj.primary_key and keys[-1] is not None: - return dict(result=entry_attrs, value=keys[-1]) --- -2.4.3 - diff --git a/SOURCES/0035-client-fix-hiding-of-commands-which-lack-server-supp.patch b/SOURCES/0035-client-fix-hiding-of-commands-which-lack-server-supp.patch new file mode 100644 index 0000000..6b2b1cd --- /dev/null +++ b/SOURCES/0035-client-fix-hiding-of-commands-which-lack-server-supp.patch @@ -0,0 +1,93 @@ +From a23b8fd488ca33f3e6ffa42530debd6d5d3430ac Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Mon, 18 Jul 2016 09:37:24 +0200 +Subject: [PATCH] client: fix hiding of commands which lack server support + +Rather than checking the server counterpart's NO_CLI, which may be False +even for commands supported on the server, check wheter the server +counterpart is a command defined on the server or a local placeholder. + +https://fedorahosted.org/freeipa/ticket/6089 + +Reviewed-By: Florence Blanc-Renaud +--- + ipaclient/plugins/automount.py | 3 ++- + ipaclient/plugins/otptoken_yubikey.py | 3 ++- + ipaclient/plugins/vault.py | 12 ++++++++---- + 3 files changed, 12 insertions(+), 6 deletions(-) + +diff --git a/ipaclient/plugins/automount.py b/ipaclient/plugins/automount.py +index 8405f9f4fe283d9c068d51e10717fb1396fa44bf..c6537bc6c24b905a8e1f7fb6a7e2c931b95374c7 100644 +--- a/ipaclient/plugins/automount.py ++++ b/ipaclient/plugins/automount.py +@@ -54,7 +54,8 @@ class _fake_automountlocation_show(Method): + class automountlocation_tofiles(MethodOverride): + @property + def NO_CLI(self): +- return self.api.Command.automountlocation_show.NO_CLI ++ return isinstance(self.api.Command.automountlocation_show, ++ _fake_automountlocation_show) + + def output_for_cli(self, textui, result, *keys, **options): + maps = result['result']['maps'] +diff --git a/ipaclient/plugins/otptoken_yubikey.py b/ipaclient/plugins/otptoken_yubikey.py +index 5e0d994628ab997853a80d1f1118ba8ada9993d9..423b670de15dd7f803db1dcbb759bd0254827072 100644 +--- a/ipaclient/plugins/otptoken_yubikey.py ++++ b/ipaclient/plugins/otptoken_yubikey.py +@@ -76,7 +76,8 @@ class otptoken_add_yubikey(Command): + + @property + def NO_CLI(self): +- return self.api.Command.otptoken_add.NO_CLI ++ return isinstance(self.api.Command.otptoken_add, ++ _fake_otptoken_add) + + def get_args(self): + for arg in self.api.Command.otptoken_add.args(): +diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py +index b7e0cfffb2fff62fdbbf438964d124fc2dd8ac36..e3a1ae3a0ad767bcee843b7fa3743a934e02d18b 100644 +--- a/ipaclient/plugins/vault.py ++++ b/ipaclient/plugins/vault.py +@@ -204,7 +204,8 @@ class vault_add(Local): + + @property + def NO_CLI(self): +- return self.api.Command.vault_add_internal.NO_CLI ++ return isinstance(self.api.Command.vault_add_internal, ++ _fake_vault_add_internal) + + def get_args(self): + for arg in self.api.Command.vault_add_internal.args(): +@@ -401,7 +402,8 @@ class vault_mod(Local): + + @property + def NO_CLI(self): +- return self.api.Command.vault_mod_internal.NO_CLI ++ return isinstance(self.api.Command.vault_mod_internal, ++ _fake_vault_mod_internal) + + def get_args(self): + for arg in self.api.Command.vault_mod_internal.args(): +@@ -579,7 +581,8 @@ class vault_archive(Local): + + @property + def NO_CLI(self): +- return self.api.Command.vault_archive_internal.NO_CLI ++ return isinstance(self.api.Command.vault_archive_internal, ++ _fake_vault_archive_internal) + + def get_args(self): + for arg in self.api.Command.vault_archive_internal.args(): +@@ -827,7 +830,8 @@ class vault_retrieve(Local): + + @property + def NO_CLI(self): +- return self.api.Command.vault_retrieve_internal.NO_CLI ++ return isinstance(self.api.Command.vault_retrieve_internal, ++ _fake_vault_retrieve_internal) + + def get_args(self): + for arg in self.api.Command.vault_retrieve_internal.args(): +-- +2.7.4 + diff --git a/SOURCES/0036-Minor-fix-in-ipa-replica-manage-MAN-page.patch b/SOURCES/0036-Minor-fix-in-ipa-replica-manage-MAN-page.patch new file mode 100644 index 0000000..76b1fca --- /dev/null +++ b/SOURCES/0036-Minor-fix-in-ipa-replica-manage-MAN-page.patch @@ -0,0 +1,51 @@ +From 1087492c74ed4f823c49314454b9db8bddf29ed2 Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Tue, 12 Jul 2016 17:08:06 +0530 +Subject: [PATCH] Minor fix in ipa-replica-manage MAN page + +Fixes: https://fedorahosted.org/freeipa/ticket/6058 + +Signed-off-by: Abhijeet Kasurde +Reviewed-By: Florence Blanc-Renaud +--- + install/tools/man/ipa-replica-manage.1 | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/install/tools/man/ipa-replica-manage.1 b/install/tools/man/ipa-replica-manage.1 +index 68be0232fae9309b108e69f9144501be3277f503..34cd314a517ae2f74da7bc87d6336e62d7b57118 100644 +--- a/install/tools/man/ipa-replica-manage.1 ++++ b/install/tools/man/ipa-replica-manage.1 +@@ -16,7 +16,7 @@ + .\" + .\" Author: Rob Crittenden + .\" +-.TH "ipa-replica-manage" "1" "Mar 1 2013" "FreeIPA" "FreeIPA Manual Pages" ++.TH "ipa-replica-manage" "1" "Jul 12 2016" "FreeIPA" "FreeIPA Manual Pages" + .SH "NAME" + ipa\-replica\-manage \- Manage an IPA replica + .SH "SYNOPSIS" +@@ -163,15 +163,15 @@ Performing range changes as a delegated administrator (e.g. not using the Direct + .TP + List all masters: + # ipa\-replica\-manage list +- srv1.example.com +- srv2.example.com +- srv3.example.com +- srv4.example.com ++ srv1.example.com: master ++ srv2.example.com: master ++ srv3.example.com: master ++ srv4.example.com: master + .TP + List a server's replication agreements. + # ipa\-replica\-manage list srv1.example.com +- srv2.example.com +- srv3.example.com ++ srv2.example.com: replica ++ srv3.example.com: replica + .TP + Re\-initialize a replica: + # ipa\-replica\-manage re\-initialize \-\-from srv2.example.com +-- +2.7.4 + diff --git a/SOURCES/0036-webui-fix-regressions-failed-auth-messages.patch b/SOURCES/0036-webui-fix-regressions-failed-auth-messages.patch deleted file mode 100644 index ea69c48..0000000 --- a/SOURCES/0036-webui-fix-regressions-failed-auth-messages.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 4c1b511fbcdca211c913a4db409c66469cdc3a4f Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Tue, 28 Jul 2015 14:01:34 +0200 -Subject: [PATCH] webui: fix regressions failed auth messages - -1. after logout, krb auth no longer shows "session expired" but correct -"Authentication with Kerberos failed". - -2. "The password or username you entered is incorrect." is showed on -failed forms-based auth. - -https://fedorahosted.org/freeipa/ticket/5163 - -Reviewed-By: Martin Basti ---- - install/ui/src/freeipa/ipa.js | 8 ++++---- - install/ui/src/freeipa/widgets/LoginScreen.js | 2 +- - 2 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/install/ui/src/freeipa/ipa.js b/install/ui/src/freeipa/ipa.js -index 75dd73c379815a0e0e1dc2c4d786fdcf3be7c1b0..eaaaaf7fcfaee873d97d96630b72365ecffe6b08 100644 ---- a/install/ui/src/freeipa/ipa.js -+++ b/install/ui/src/freeipa/ipa.js -@@ -32,6 +32,7 @@ define([ - './json2', - './_base/i18n', - './auth', -+ './config', - './datetime', - './metadata', - './builder', -@@ -41,7 +42,8 @@ define([ - './util', - 'exports' - ], function(declare, Deferred, Evented, keys, topic, $, JSON, i18n, auth, -- datetime, metadata_provider, builder, reg, rpc, text, util, exports) { -+ config, datetime, metadata_provider, builder, reg, rpc, text, -+ util, exports) { - - /** - * @class -@@ -127,11 +129,9 @@ var IPA = function () { - // if current path matches live server path, use live data - if (that.url && window.location.pathname.substring(0, that.url.length) === that.url) { - that.json_url = params.url || '/ipa/session/json'; -- that.login_url = params.url || '/ipa/session/login_kerberos'; - - } else { // otherwise use fixtures - that.json_path = params.url || "test/data"; -- // that.login_url is not needed for fixtures - } - - $.ajaxSetup(that.ajax_options); -@@ -377,7 +377,7 @@ IPA.get_credentials = function() { - } - - var request = { -- url: IPA.login_url, -+ url: config.krb_login_url, - cache: false, - type: "GET", - success: success_handler, -diff --git a/install/ui/src/freeipa/widgets/LoginScreen.js b/install/ui/src/freeipa/widgets/LoginScreen.js -index fb7ccccc6c34d9c1c7115dd95809f3a39de488eb..eb95b9161f05eeac1ec9aed286c9730dada85d59 100644 ---- a/install/ui/src/freeipa/widgets/LoginScreen.js -+++ b/install/ui/src/freeipa/widgets/LoginScreen.js -@@ -232,8 +232,8 @@ define(['dojo/_base/declare', - this.set('view', 'reset'); - val_summary.add_info('login', this.password_expired); - } else { -- val_summary.add_error('login', this.form_auth_failed); - password_f.set_value(''); -+ val_summary.add_error('login', this.form_auth_failed); - } - })); - }, --- -2.4.3 - diff --git a/SOURCES/0037-Validate-vault-s-file-parameters.patch b/SOURCES/0037-Validate-vault-s-file-parameters.patch deleted file mode 100644 index c6b18d3..0000000 --- a/SOURCES/0037-Validate-vault-s-file-parameters.patch +++ /dev/null @@ -1,139 +0,0 @@ -From f5cf88337d6f775df4a311469b869921bbc90f05 Mon Sep 17 00:00:00 2001 -From: Christian Heimes -Date: Thu, 30 Jul 2015 15:48:40 +0200 -Subject: [PATCH] Validate vault's file parameters - -A user can pass file names for password, public and private key files to -the vault plugin. The plugin attempts to read from these files. If any -file can't be, an internal error was raised. The patch wraps all reads -and turns any IOError and UnicodeError into a ValidationError. - -https://fedorahosted.org/freeipa/ticket/5155 - -Reviewed-By: Martin Basti ---- - ipalib/plugins/vault.py | 59 +++++++++++++++++++++++++++++++++++++++---------- - 1 file changed, 47 insertions(+), 12 deletions(-) - -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index 37a32282e7a4e87889eea90d987b737f98fd82c3..fe4eec325dde4a9ecd8a7ce5af1a124fc5c6a9ae 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -19,6 +19,7 @@ - - import base64 - import getpass -+import io - import json - import os - import sys -@@ -210,6 +211,33 @@ EXAMPLES: - ipa vault-remove-member --users - """) - -+ -+def validated_read(argname, filename, mode='r', encoding=None): -+ """Read file and catch errors -+ -+ IOError and UnicodeError (for text files) are turned into a -+ ValidationError -+ """ -+ try: -+ with io.open(filename, mode=mode, encoding=encoding) as f: -+ data = f.read() -+ except IOError as exc: -+ raise errors.ValidationError( -+ name=argname, -+ error=_("Cannot read file '%(filename)s': %(exc)s") % { -+ 'filename': filename, 'exc': exc[1] -+ } -+ ) -+ except UnicodeError as exc: -+ raise errors.ValidationError( -+ name=argname, -+ error=_("Cannot decode file '%(filename)s': %(exc)s") % { -+ 'filename': filename, 'exc': exc -+ } -+ ) -+ return data -+ -+ - register = Registry() - - -@@ -591,8 +619,10 @@ class vault_add(PKQuery, Local): - pass - - elif password_file: -- with open(password_file, 'rb') as f: -- password = f.read().rstrip('\n').decode('utf-8') -+ password = validated_read('password-file', -+ password_file, -+ encoding='utf-8') -+ password = password.rstrip('\n') - - else: - password = self.obj.get_new_password() -@@ -611,8 +641,9 @@ class vault_add(PKQuery, Local): - pass - - elif public_key_file: -- with open(public_key_file, 'rb') as f: -- public_key = f.read() -+ public_key = validated_read('public-key-file', -+ public_key_file, -+ mode='rb') - - # store vault public key - options['ipavaultpublickey'] = public_key -@@ -904,8 +935,7 @@ class vault_archive(PKQuery, Local): - reason=_('Input data specified multiple times')) - - elif input_file: -- with open(input_file, 'rb') as f: -- data = f.read() -+ data = validated_read('in', input_file, mode='rb') - - elif not data: - data = '' -@@ -937,8 +967,10 @@ class vault_archive(PKQuery, Local): - pass - - elif password_file: -- with open(password_file) as f: -- password = f.read().rstrip('\n').decode('utf-8') -+ password = validated_read('password-file', -+ password_file, -+ encoding='utf-8') -+ password = password.rstrip('\n') - - else: - password = self.obj.get_existing_password() -@@ -1254,8 +1286,10 @@ class vault_retrieve(PKQuery, Local): - pass - - elif password_file: -- with open(password_file) as f: -- password = f.read().rstrip('\n').decode('utf-8') -+ password = validated_read('password-file', -+ password_file, -+ encoding='utf-8') -+ password = password.rstrip('\n') - - else: - password = self.obj.get_existing_password() -@@ -1277,8 +1311,9 @@ class vault_retrieve(PKQuery, Local): - pass - - elif private_key_file: -- with open(private_key_file, 'rb') as f: -- private_key = f.read() -+ private_key = validated_read('private-key-file', -+ private_key_file, -+ mode='rb') - - else: - raise errors.ValidationError( --- -2.4.3 - diff --git a/SOURCES/0037-compat-fix-ping-call.patch b/SOURCES/0037-compat-fix-ping-call.patch new file mode 100644 index 0000000..ce000c1 --- /dev/null +++ b/SOURCES/0037-compat-fix-ping-call.patch @@ -0,0 +1,31 @@ +From f557f7487d9aae0c901a740b9a446568677b8bb3 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Mon, 25 Jul 2016 15:58:20 +0200 +Subject: [PATCH] compat: fix ping call + +Copy & paste accident caused the ping command to be called with an unwanted +argument, which results in an exception. + +Remove the argument to fix it. + +https://fedorahosted.org/freeipa/ticket/6129 +--- + ipaclient/remote_plugins/compat.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipaclient/remote_plugins/compat.py b/ipaclient/remote_plugins/compat.py +index 40521af450aafca83f33d1723b4fd9e27ef8d96f..aef5718fcaade157487c0e65562c3bc8a11ad7de 100644 +--- a/ipaclient/remote_plugins/compat.py ++++ b/ipaclient/remote_plugins/compat.py +@@ -39,7 +39,7 @@ def get_package(api, client): + try: + server_version = env['result']['api_version'] + except KeyError: +- ping = client.forward(u'ping', u'api_version', version=u'2.0') ++ ping = client.forward(u'ping', version=u'2.0') + try: + match = re.search(u'API version (2\.[0-9]+)', ping['summary']) + except KeyError: +-- +2.7.4 + diff --git a/SOURCES/0038-certprofile-import-do-not-require-profileId-in-profi.patch b/SOURCES/0038-certprofile-import-do-not-require-profileId-in-profi.patch deleted file mode 100644 index 57f8aa1..0000000 --- a/SOURCES/0038-certprofile-import-do-not-require-profileId-in-profi.patch +++ /dev/null @@ -1,58 +0,0 @@ -From ae5939600d367172a1e830c87254d2fc1bb56fe8 Mon Sep 17 00:00:00 2001 -From: Christian Heimes -Date: Thu, 23 Jul 2015 17:48:56 +0200 -Subject: [PATCH] certprofile-import: do not require profileId in profile data - -certprofile-import no longer requires profileId in profile data. Instead -the profile ID from the command line is taken and added to the profile -data internally. - -If profileId is set in the profile, then it still has to match the CLI -option. - -https://fedorahosted.org/freeipa/ticket/5090 - -Reviewed-By: Martin Basti ---- - ipalib/plugins/certprofile.py | 8 +++++--- - 1 file changed, 5 insertions(+), 3 deletions(-) - -diff --git a/ipalib/plugins/certprofile.py b/ipalib/plugins/certprofile.py -index 5550ed942521dbab2e783fba1570520268f9b378..b0b76ca8e78f2482b5c08dad21d9161fd4c2c2d0 100644 ---- a/ipalib/plugins/certprofile.py -+++ b/ipalib/plugins/certprofile.py -@@ -11,6 +11,7 @@ from ipalib.plugins.virtual import VirtualCommand - from ipalib.plugins.baseldap import ( - LDAPObject, LDAPSearch, LDAPCreate, - LDAPDelete, LDAPUpdate, LDAPRetrieve) -+from ipalib.request import context - from ipalib import ngettext - from ipalib.text import _ - from ipapython.version import API_VERSION -@@ -230,11 +231,12 @@ class certprofile_import(LDAPCreate): - - def pre_callback(self, ldap, dn, entry, entry_attrs, *keys, **options): - ca_enabled_check() -+ context.profile = options['file'] - - match = self.PROFILE_ID_PATTERN.search(options['file']) - if match is None: -- raise errors.ValidationError(name='file', -- error=_("Profile ID is not present in profile data")) -+ # no profileId found, use CLI value as profileId. -+ context.profile = u'profileId=%s\n%s' % (keys[0], context.profile) - elif keys[0] != match.group(1): - raise errors.ValidationError(name='file', - error=_("Profile ID '%(cli_value)s' does not match profile data '%(file_value)s'") -@@ -250,7 +252,7 @@ class certprofile_import(LDAPCreate): - """ - try: - with self.api.Backend.ra_certprofile as profile_api: -- profile_api.create_profile(options['file']) -+ profile_api.create_profile(context.profile) - profile_api.enable_profile(keys[0]) - except: - # something went wrong ; delete entry --- -2.4.3 - diff --git a/SOURCES/0038-replica-install-Fix-domain.patch b/SOURCES/0038-replica-install-Fix-domain.patch new file mode 100644 index 0000000..20d2325 --- /dev/null +++ b/SOURCES/0038-replica-install-Fix-domain.patch @@ -0,0 +1,71 @@ +From 42c09751aedf6289f983d4238ae1ff3b44b5f572 Mon Sep 17 00:00:00 2001 +From: Petr Spacek +Date: Mon, 25 Jul 2016 15:54:43 +0200 +Subject: [PATCH] replica-install: Fix --domain + +Replica installation must not check existence of --domain - the domain +must (logically) exist. + +https://fedorahosted.org/freeipa/ticket/6130 + +Reviewed-By: Jan Cholasta +--- + ipaserver/install/server/common.py | 5 ----- + ipaserver/install/server/install.py | 14 +++++++++++--- + 2 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/ipaserver/install/server/common.py b/ipaserver/install/server/common.py +index 45fb2dc17976a08acab16783584524721411fb4e..e6093d15cd1067a83ed89945c4a9c983c66ec06f 100644 +--- a/ipaserver/install/server/common.py ++++ b/ipaserver/install/server/common.py +@@ -284,11 +284,6 @@ class BaseServer(common.Installable, common.Interactive, core.Composite): + @domain_name.validator + def domain_name(self, value): + validate_domain_name(value) +- if (self.setup_dns and +- not self.dns.allow_zone_overlap): # pylint: disable=no-member +- print("Checking DNS domain %s, please wait ..." % value) +- check_zone_overlap(value, False) +- + + dm_password = Knob( + str, None, +diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py +index c0c676b870b481696ae75742c7bf88074b0ecf9c..65f9318201e648b30a3c13626e807ac6f3a9416d 100644 +--- a/ipaserver/install/server/install.py ++++ b/ipaserver/install/server/install.py +@@ -17,6 +17,7 @@ import six + + from ipapython import certmonger, ipaldap, ipautil, sysrestore + from ipapython.dn import DN ++from ipapython.dnsutil import check_zone_overlap + from ipapython.install import core + from ipapython.install.common import step + from ipapython.install.core import Knob +@@ -1199,13 +1200,20 @@ class ServerCA(BaseServerCA): + + + class Server(BaseServer): +- realm_name = Knob(BaseServer.realm_name) +- domain_name = Knob(BaseServer.domain_name) +- + setup_ca = None + setup_kra = None + setup_dns = Knob(BaseServer.setup_dns) + ++ realm_name = Knob(BaseServer.realm_name) ++ domain_name = Knob(BaseServer.domain_name) ++ ++ @domain_name.validator ++ def domain_name(self, value): ++ if (self.setup_dns and ++ not self.dns.allow_zone_overlap): # pylint: disable=no-member ++ print("Checking DNS domain %s, please wait ..." % value) ++ check_zone_overlap(value, False) ++ + dm_password = Knob( + BaseServer.dm_password, + description="Directory Manager password", +-- +2.7.4 + diff --git a/SOURCES/0039-idrange-fix-unassigned-global-variable.patch b/SOURCES/0039-idrange-fix-unassigned-global-variable.patch new file mode 100644 index 0000000..731295d --- /dev/null +++ b/SOURCES/0039-idrange-fix-unassigned-global-variable.patch @@ -0,0 +1,33 @@ +From 89bfc7c0a4b08c873e5c8b8dfad54cf895b742cd Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Fri, 29 Jul 2016 16:46:09 +0200 +Subject: [PATCH] idrange: fix unassigned global variable + +Global variable '_dcerpc_bindings_installed' is in some cases used +before assigment. This patch ensures that _dcerpc_bindings_installed is +always initialized. + +https://fedorahosted.org/freeipa/ticket/6082 + +Reviewed-By: Alexander Bokovoy +--- + ipaserver/plugins/idrange.py | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/ipaserver/plugins/idrange.py b/ipaserver/plugins/idrange.py +index ccd67995e5b42634387e1064e7c819b711f3ef99..3e9db0b6b734513547423901a8b3212b3cee9147 100644 +--- a/ipaserver/plugins/idrange.py ++++ b/ipaserver/plugins/idrange.py +@@ -35,6 +35,9 @@ if api.env.in_server and api.env.context in ['lite', 'server']: + _dcerpc_bindings_installed = True + except ImportError: + _dcerpc_bindings_installed = False ++else: ++ _dcerpc_bindings_installed = False ++ + + ID_RANGE_VS_DNA_WARNING = """======= + WARNING: +-- +2.7.4 + diff --git a/SOURCES/0039-user-show-add-out-option-to-save-certificates-to-fil.patch b/SOURCES/0039-user-show-add-out-option-to-save-certificates-to-fil.patch deleted file mode 100644 index 94d2fb8..0000000 --- a/SOURCES/0039-user-show-add-out-option-to-save-certificates-to-fil.patch +++ /dev/null @@ -1,109 +0,0 @@ -From 52ddaafcac7ace012535ac7044b301ad3a7d7b9a Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Fri, 24 Jul 2015 09:31:26 -0400 -Subject: [PATCH] user-show: add --out option to save certificates to file - -Add the --out option to user-show, bringing it into line with -host-show and service-show with the ability to save the user's -certificate(s) to a file. - -https://fedorahosted.org/freeipa/ticket/5171 - -Reviewed-By: Martin Basti ---- - API.txt | 3 ++- - VERSION | 4 ++-- - ipalib/plugins/user.py | 27 ++++++++++++++++++++++++++- - 3 files changed, 30 insertions(+), 4 deletions(-) - -diff --git a/API.txt b/API.txt -index 6ab30ddab41715fdbccb4f37aa1852621bca62b4..2e19d6b2f1e16cc1c89d71ed7d443145426a28e3 100644 ---- a/API.txt -+++ b/API.txt -@@ -5360,10 +5360,11 @@ output: Entry('result', , Gettext('A dictionary representing an LDA - output: Output('summary', (, ), None) - output: PrimaryKey('value', None, None) - command: user_show --args: 1,5,3 -+args: 1,6,3 - arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=True) - option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') - option: Flag('no_members', autofill=True, default=False, exclude='webui') -+option: Str('out?') - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') - option: Flag('rights', autofill=True, default=False) - option: Str('version?', exclude='webui') -diff --git a/VERSION b/VERSION -index 678d1f8a7e588d480b16441e12e4d527d9c1cd98..ca43f3e0c06880d355c068514134187c5edda175 100644 ---- a/VERSION -+++ b/VERSION -@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 - # # - ######################################################## - IPA_API_VERSION_MAJOR=2 --IPA_API_VERSION_MINOR=147 --# Last change: mbasti - Consolidate DNS RR in API and schema -+IPA_API_VERSION_MINOR=148 -+# Last change: ftweedal - add --out option to user-show -diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py -index 206b380efb6472fb040dde33ac80e3f66c00c138..0209b29b130f2377c04f497f95c8ad39e98f2587 100644 ---- a/ipalib/plugins/user.py -+++ b/ipalib/plugins/user.py -@@ -23,7 +23,7 @@ import string - import posixpath - import os - --from ipalib import api, errors -+from ipalib import api, errors, util - from ipalib import Flag, Int, Password, Str, Bool, StrEnum, DateTime - from ipalib.plugins.baseuser import baseuser, baseuser_add, baseuser_del, \ - baseuser_mod, baseuser_find, baseuser_show, \ -@@ -38,6 +38,7 @@ from ipalib.plugins import baseldap - from ipalib.request import context - from ipalib import _, ngettext - from ipalib import output -+from ipalib import x509 - from ipaplatform.paths import paths - from ipapython.ipautil import ipa_generate_password - from ipapython.ipavalidate import Email -@@ -765,6 +766,11 @@ class user_show(baseuser_show): - __doc__ = _('Display information about a user.') - - has_output_params = baseuser_show.has_output_params + user_output_params -+ takes_options = baseuser_show.takes_options + ( -+ Str('out?', -+ doc=_('file to store certificate in'), -+ ), -+ ) - - def post_callback(self, ldap, dn, entry_attrs, *keys, **options): - convert_nsaccountlock(entry_attrs) -@@ -772,6 +778,25 @@ class user_show(baseuser_show): - self.obj.get_preserved_attribute(entry_attrs, options) - return dn - -+ def forward(self, *keys, **options): -+ if 'out' in options: -+ util.check_writable_file(options['out']) -+ result = super(user_show, self).forward(*keys, **options) -+ if 'usercertificate' in result['result']: -+ x509.write_certificate_list( -+ result['result']['usercertificate'], -+ options['out'] -+ ) -+ result['summary'] = ( -+ _('Certificate(s) stored in file \'%(file)s\'') -+ % dict(file=options['out']) -+ ) -+ return result -+ else: -+ raise errors.NoCertificateError(entry=keys[-1]) -+ else: -+ return super(user_show, self).forward(*keys, **options) -+ - @register() - class user_undel(LDAPQuery): - __doc__ = _('Undelete a delete user account.') --- -2.4.3 - diff --git a/SOURCES/0040-re-set-canonical-principal-name-on-migrated-users.patch b/SOURCES/0040-re-set-canonical-principal-name-on-migrated-users.patch new file mode 100644 index 0000000..bc6f486 --- /dev/null +++ b/SOURCES/0040-re-set-canonical-principal-name-on-migrated-users.patch @@ -0,0 +1,86 @@ +From 1dfba16f6d46a2811d0230f28abf0ea4621bfde2 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Thu, 28 Jul 2016 10:42:58 +0200 +Subject: [PATCH] re-set canonical principal name on migrated users + +The migration procedure has been updated to re-set `krbcanonicalname` +attribute on migrated users as well as `krbprincipalname` so that migration +from FreeIPA versions supporting principal aliases does not break subsequent +authentication of migrated users. + +https://fedorahosted.org/freeipa/ticket/6101 + +Reviewed-By: Florence Blanc-Renaud +--- + ipaserver/plugins/migration.py | 41 ++++++++++++++++++++++++++++------------- + 1 file changed, 28 insertions(+), 13 deletions(-) + +diff --git a/ipaserver/plugins/migration.py b/ipaserver/plugins/migration.py +index 7f634a7ccf8c49a4c8e0cc3fe2b2dce84b5cadff..404c4aeb08ff2ee018799af3a9224bec93c26f82 100644 +--- a/ipaserver/plugins/migration.py ++++ b/ipaserver/plugins/migration.py +@@ -36,6 +36,7 @@ if api.env.in_server and api.env.context in ['lite', 'server']: + from ipalib import _ + from ipapython.dn import DN + from ipapython.ipautil import write_tmp_file ++from ipapython.kerberos import Principal + import datetime + from ipaplatform.paths import paths + +@@ -152,6 +153,32 @@ _supported_scopes = {u'base': SCOPE_BASE, u'onelevel': SCOPE_ONELEVEL, u'subtree + _default_scope = u'onelevel' + + ++def _create_kerberos_principals(ldap, pkey, entry_attrs, failed): ++ """ ++ Create 'krbprincipalname' and 'krbcanonicalname' attributes for incoming ++ user entry or skip it if there already is a user with such principal name. ++ The code does not search for `krbcanonicalname` since we assume that the ++ canonical principal name is always contained among values of ++ `krbprincipalname` attribute.Both `krbprincipalname` and `krbcanonicalname` ++ are set to default value generated from uid and realm. ++ ++ Note: the migration does not currently preserve principal aliases ++ """ ++ principal = Principal((pkey,), realm=api.env.realm) ++ try: ++ ldap.find_entry_by_attr( ++ 'krbprincipalname', principal, 'krbprincipalaux', [''], ++ DN(api.env.container_user, api.env.basedn) ++ ) ++ except errors.NotFound: ++ entry_attrs['krbprincipalname'] = principal ++ entry_attrs['krbcanonicalname'] = principal ++ except errors.LimitsExceeded: ++ failed[pkey] = unicode(_krb_failed_msg % unicode(principal)) ++ else: ++ failed[pkey] = unicode(_krb_err_msg % unicode(principal)) ++ ++ + def _pre_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs): + assert isinstance(dn, DN) + attr_blacklist = ['krbprincipalkey','memberofindirect','memberindirect'] +@@ -217,19 +244,7 @@ def _pre_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs + except ValueError: # object class not present + pass + +- # generate a principal name and check if it isn't already taken +- principal = u'%s@%s' % (pkey, api.env.realm) +- try: +- ldap.find_entry_by_attr( +- 'krbprincipalname', principal, 'krbprincipalaux', [''], +- DN(api.env.container_user, api.env.basedn) +- ) +- except errors.NotFound: +- entry_attrs['krbprincipalname'] = principal +- except errors.LimitsExceeded: +- failed[pkey] = unicode(_krb_failed_msg % principal) +- else: +- failed[pkey] = unicode(_krb_err_msg % principal) ++ _create_kerberos_principals(ldap, pkey, entry_attrs, failed) + + # Fix any attributes with DN syntax that point to entries in the old + # tree +-- +2.7.4 + diff --git a/SOURCES/0040-store-certificates-issued-for-user-entries-as-userCe.patch b/SOURCES/0040-store-certificates-issued-for-user-entries-as-userCe.patch deleted file mode 100644 index c284618..0000000 --- a/SOURCES/0040-store-certificates-issued-for-user-entries-as-userCe.patch +++ /dev/null @@ -1,158 +0,0 @@ -From 180f571e60aaedaacdaa272d2a34719ce0ce0565 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Mon, 3 Aug 2015 13:36:29 +0200 -Subject: [PATCH] store certificates issued for user entries as - userCertificate;binary - -This patch forces the user management CLI command to store certificates as -userCertificate;binary attribute. The code to retrieve of user information was -modified to enable outputting of userCertificate;binary attribute to the -command line. - -The modification also fixes https://fedorahosted.org/freeipa/ticket/5173 - -Reviewed-By: Jan Cholasta ---- - ipalib/plugins/baseuser.py | 23 ++++++++++++++++++++++- - ipalib/plugins/user.py | 21 +++++++++------------ - 2 files changed, 31 insertions(+), 13 deletions(-) - -diff --git a/ipalib/plugins/baseuser.py b/ipalib/plugins/baseuser.py -index bd66cf5a3e3a4e6c18d1a54408f969668c834fab..5eede7a98e7e6d9bf31a6d553b0ce60c7cf3527c 100644 ---- a/ipalib/plugins/baseuser.py -+++ b/ipalib/plugins/baseuser.py -@@ -187,7 +187,7 @@ class baseuser(LDAPObject): - 'telephonenumber', 'title', 'memberof', 'nsaccountlock', - 'memberofindirect', 'ipauserauthtype', 'userclass', - 'ipatokenradiusconfiglink', 'ipatokenradiususername', -- 'krbprincipalexpiration', 'usercertificate', -+ 'krbprincipalexpiration', 'usercertificate;binary', - ] - search_display_attributes = [ - 'uid', 'givenname', 'sn', 'homedirectory', 'loginshell', -@@ -465,10 +465,27 @@ class baseuser(LDAPObject): - assert isinstance(user, DN) - return self._user_status(user, DN(self.delete_container_dn, api.env.basedn)) - -+ def convert_usercertificate_pre(self, entry_attrs): -+ if 'usercertificate' in entry_attrs: -+ entry_attrs['usercertificate;binary'] = entry_attrs.pop( -+ 'usercertificate') -+ -+ def convert_usercertificate_post(self, entry_attrs, **options): -+ if 'usercertificate;binary' in entry_attrs: -+ entry_attrs['usercertificate'] = entry_attrs.pop( -+ 'usercertificate;binary') -+ - class baseuser_add(LDAPCreate): - """ - Prototype command plugin to be implemented by real plugin - """ -+ def pre_common_callback(self, ldap, dn, entry_attrs, **options): -+ assert isinstance(dn, DN) -+ self.obj.convert_usercertificate_pre(entry_attrs) -+ -+ def post_common_callback(self, ldap, dn, entry_attrs, **options): -+ assert isinstance(dn, DN) -+ self.obj.convert_usercertificate_post(entry_attrs, **options) - - class baseuser_del(LDAPDelete): - """ -@@ -542,6 +559,7 @@ class baseuser_mod(LDAPUpdate): - self.check_userpassword(entry_attrs, **options) - - self.check_objectclass(ldap, dn, entry_attrs) -+ self.obj.convert_usercertificate_pre(entry_attrs) - - def post_common_callback(self, ldap, dn, entry_attrs, **options): - assert isinstance(dn, DN) -@@ -554,6 +572,7 @@ class baseuser_mod(LDAPUpdate): - convert_nsaccountlock(entry_attrs) - self.obj.convert_manager(entry_attrs, **options) - self.obj.get_password_attributes(ldap, dn, entry_attrs) -+ self.obj.convert_usercertificate_post(entry_attrs, **options) - convert_sshpubkey_post(ldap, dn, entry_attrs) - radius_dn2pk(self.api, entry_attrs) - -@@ -584,6 +603,7 @@ class baseuser_find(LDAPSearch): - for attrs in entries: - self.obj.convert_manager(attrs, **options) - self.obj.get_password_attributes(ldap, attrs.dn, attrs) -+ self.obj.convert_usercertificate_post(attrs, **options) - if (lockout): - attrs['nsaccountlock'] = True - else: -@@ -598,5 +618,6 @@ class baseuser_show(LDAPRetrieve): - assert isinstance(dn, DN) - self.obj.convert_manager(entry_attrs, **options) - self.obj.get_password_attributes(ldap, dn, entry_attrs) -+ self.obj.convert_usercertificate_post(entry_attrs, **options) - convert_sshpubkey_post(ldap, dn, entry_attrs) - radius_dn2pk(self.api, entry_attrs) -diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py -index 0209b29b130f2377c04f497f95c8ad39e98f2587..859939205f903fa4832524c8d2601141f3674bb5 100644 ---- a/ipalib/plugins/user.py -+++ b/ipalib/plugins/user.py -@@ -510,6 +510,8 @@ class user_add(baseuser_add): - answer = self.api.Object['radiusproxy'].get_dn_if_exists(rcl) - entry_attrs['ipatokenradiusconfiglink'] = answer - -+ self.pre_common_callback(ldap, dn, entry_attrs, **options) -+ - return dn - - def post_callback(self, ldap, dn, entry_attrs, *keys, **options): -@@ -557,6 +559,9 @@ class user_add(baseuser_add): - convert_sshpubkey_post(ldap, dn, entry_attrs) - radius_dn2pk(self.api, entry_attrs) - self.obj.get_preserved_attribute(entry_attrs, options) -+ -+ self.post_common_callback(ldap, dn, entry_attrs, **options) -+ - return dn - - -@@ -1034,18 +1039,14 @@ class user_add_cert(LDAPAddAttribute): - **options): - assert isinstance(dn, DN) - -- new_attr_name = '%s;binary' % self.attribute -- if self.attribute in entry_attrs: -- entry_attrs[new_attr_name] = entry_attrs.pop(self.attribute) -+ self.obj.convert_usercertificate_pre(entry_attrs) - - return dn - - def post_callback(self, ldap, dn, entry_attrs, *keys, **options): - assert isinstance(dn, DN) - -- old_attr_name = '%s;binary' % self.attribute -- if old_attr_name in entry_attrs: -- entry_attrs[self.attribute] = entry_attrs.pop(old_attr_name) -+ self.obj.convert_usercertificate_post(entry_attrs, **options) - - return dn - -@@ -1060,17 +1061,13 @@ class user_remove_cert(LDAPRemoveAttribute): - **options): - assert isinstance(dn, DN) - -- new_attr_name = '%s;binary' % self.attribute -- if self.attribute in entry_attrs: -- entry_attrs[new_attr_name] = entry_attrs.pop(self.attribute) -+ self.obj.convert_usercertificate_pre(entry_attrs) - - return dn - - def post_callback(self, ldap, dn, entry_attrs, *keys, **options): - assert isinstance(dn, DN) - -- old_attr_name = '%s;binary' % self.attribute -- if old_attr_name in entry_attrs: -- entry_attrs[self.attribute] = entry_attrs.pop(old_attr_name) -+ self.obj.convert_usercertificate_post(entry_attrs, **options) - - return dn --- -2.4.3 - diff --git a/SOURCES/0041-Do-not-initialize-API-in-ipa-client-automount-uninst.patch b/SOURCES/0041-Do-not-initialize-API-in-ipa-client-automount-uninst.patch new file mode 100644 index 0000000..8d2cb7f --- /dev/null +++ b/SOURCES/0041-Do-not-initialize-API-in-ipa-client-automount-uninst.patch @@ -0,0 +1,41 @@ +From c92d242a215c7fb312aaeb07dd02f5783aec1817 Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Thu, 28 Jul 2016 09:47:39 +0200 +Subject: [PATCH] Do not initialize API in ipa-client-automount uninstall + +API is not needed in uninstallation, it may only produce errors. + +https://fedorahosted.org/freeipa/ticket/6072 + +Reviewed-By: Florence Blanc-Renaud +--- + client/ipa-client-automount | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/client/ipa-client-automount b/client/ipa-client-automount +index f06aa7f8d53ba2528bc2c023792771d5fd341e7c..08209c849f155a8394acddc6bb961be8fa68073c 100755 +--- a/client/ipa-client-automount ++++ b/client/ipa-client-automount +@@ -378,6 +378,9 @@ def main(): + paths.IPACLIENT_INSTALL_LOG, verbose=False, debug=options.debug, + filemode='a', console_format='%(message)s') + ++ if options.uninstall: ++ return uninstall(fstore, statestore) ++ + cfg = dict( + context='cli_installer', + in_server=False, +@@ -392,9 +395,6 @@ def main(): + if os.path.exists(paths.IPA_CA_CRT): + ca_cert_path = paths.IPA_CA_CRT + +- if options.uninstall: +- return uninstall(fstore, statestore) +- + if statestore.has_state('autofs'): + sys.exit('automount is already configured on this system.\n') + +-- +2.7.4 + diff --git a/SOURCES/0041-Fix-incorrect-type-comparison-in-trust-fetch-domains.patch b/SOURCES/0041-Fix-incorrect-type-comparison-in-trust-fetch-domains.patch deleted file mode 100644 index 3e06394..0000000 --- a/SOURCES/0041-Fix-incorrect-type-comparison-in-trust-fetch-domains.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 8233849dd703e964f6abb70d2a4f37377d5bb7f0 Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Wed, 5 Aug 2015 17:31:47 +0200 -Subject: [PATCH] Fix incorrect type comparison in trust-fetch-domains - -Value needs to be unpacked from the list and converted before comparison. - -https://fedorahosted.org/freeipa/ticket/5182 - -Reviewed-By: Alexander Bokovoy ---- - ipalib/plugins/trust.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py -index 6232e4fe9d3d5e957d22a3557cdcf4bb12cec0ea..0bb5e6558b680ac1acad44461d78a571098c7b25 100644 ---- a/ipalib/plugins/trust.py -+++ b/ipalib/plugins/trust.py -@@ -1487,7 +1487,7 @@ class trust_fetch_domains(LDAPRetrieve): - result['truncated'] = False - - # For one-way trust fetch over DBus. we don't get the list in this case. -- if trust['ipanttrustdirection'] & TRUST_BIDIRECTIONAL != TRUST_BIDIRECTIONAL: -+ if int(trust['ipanttrustdirection'][0]) != TRUST_BIDIRECTIONAL: - fetch_trusted_domains_over_dbus(self.api, self.log, keys[0]) - result['summary'] = unicode(_('List of trust domains successfully refreshed. Use trustdomain-find command to list them.')) - return result --- -2.4.3 - diff --git a/SOURCES/0042-Correct-path-to-HTTPD-s-systemd-service-directory.patch b/SOURCES/0042-Correct-path-to-HTTPD-s-systemd-service-directory.patch new file mode 100644 index 0000000..1f2a798 --- /dev/null +++ b/SOURCES/0042-Correct-path-to-HTTPD-s-systemd-service-directory.patch @@ -0,0 +1,37 @@ +From 0a0f32622b06234deb64a01376b0706a03650681 Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Tue, 2 Aug 2016 16:58:07 +0200 +Subject: [PATCH] Correct path to HTTPD's systemd service directory + +Ticket #5681 and commit 586fee293f42388510fa5436af19460bbe1fdec5 changed +the location of the ipa.conf for Apache HTTPD. The variables +SYSTEMD_SYSTEM_HTTPD_D_DIR and SYSTEMD_SYSTEM_HTTPD_IPA_CONF point to +the wrong directory /etc/systemd/system/httpd.d/. The path is corrected +to /etc/systemd/system/httpd.service.d/. + +https://fedorahosted.org/freeipa/ticket/6158 +https://bugzilla.redhat.com/show_bug.cgi?id=1362537 +Signed-off-by: Christian Heimes +Reviewed-By: Abhijeet Kasurde +--- + ipaplatform/base/paths.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py +index 1507ac36da5b40447c951ee608053a09b2db2fc3..9c8eaf951df89d373796be3f354bd3c51a329902 100644 +--- a/ipaplatform/base/paths.py ++++ b/ipaplatform/base/paths.py +@@ -126,8 +126,8 @@ class BasePathNamespace(object): + SYSCONFIG_PKI_TOMCAT = "/etc/sysconfig/pki-tomcat" + SYSCONFIG_PKI_TOMCAT_PKI_TOMCAT_DIR = "/etc/sysconfig/pki/tomcat/pki-tomcat" + ETC_SYSTEMD_SYSTEM_DIR = "/etc/systemd/system/" +- SYSTEMD_SYSTEM_HTTPD_D_DIR = "/etc/systemd/system/httpd.d/" +- SYSTEMD_SYSTEM_HTTPD_IPA_CONF = "/etc/systemd/system/httpd.d/ipa.conf" ++ SYSTEMD_SYSTEM_HTTPD_D_DIR = "/etc/systemd/system/httpd.service.d/" ++ SYSTEMD_SYSTEM_HTTPD_IPA_CONF = "/etc/systemd/system/httpd.service.d/ipa.conf" + SYSTEMD_CERTMONGER_SERVICE = "/etc/systemd/system/multi-user.target.wants/certmonger.service" + SYSTEMD_IPA_SERVICE = "/etc/systemd/system/multi-user.target.wants/ipa.service" + SYSTEMD_SSSD_SERVICE = "/etc/systemd/system/multi-user.target.wants/sssd.service" +-- +2.7.4 + diff --git a/SOURCES/0042-Fix-selector-of-protocol-for-LSA-RPC-binding-string.patch b/SOURCES/0042-Fix-selector-of-protocol-for-LSA-RPC-binding-string.patch deleted file mode 100644 index 42548b9..0000000 --- a/SOURCES/0042-Fix-selector-of-protocol-for-LSA-RPC-binding-string.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 2585d6d6455d7c9257a8bbc65cc489d4a424a08e Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Wed, 5 Aug 2015 21:33:45 +0300 -Subject: [PATCH] Fix selector of protocol for LSA RPC binding string - -For Windows Server 2012R2 and others which force SMB2 protocol use -we have to specify right DCE RPC binding options. - -For using SMB1 protocol we have to omit specifying SMB2 protocol and -anything else or otherwise SMB1 would be considered a pipe to connect -to. This is by design of a binding string format. - -https://fedorahosted.org/freeipa/ticket/5183 - -Reviewed-By: Tomas Babej ---- - ipaserver/dcerpc.py | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py -index c604fa3eae4cf94d719190a5a3e3de15d3841d24..74b4743d4bfb9c4950f441f1aa3561fc7a81391c 100644 ---- a/ipaserver/dcerpc.py -+++ b/ipaserver/dcerpc.py -@@ -854,8 +854,8 @@ class TrustDomainInstance(object): - We try NCACN_NP before NCACN_IP_TCP and use SMB2 before SMB1 or defaults. - """ - transports = (u'ncacn_np', u'ncacn_ip_tcp') -- options = ( u'smb2', u'smb1', u'') -- binding_template=lambda x,y,z: u'%s:%s[%s,print]' % (x, y, z) -+ options = ( u'smb2,print', u'print') -+ binding_template=lambda x,y,z: u'%s:%s[%s]' % (x, y, z) - return [binding_template(t, remote_host, o) for t in transports for o in options] - - def retrieve_anonymously(self, remote_host, discover_srv=False, search_pdc=False): --- -2.4.3 - diff --git a/SOURCES/0043-dcerpc-Simplify-generation-of-LSA-RPC-binding-string.patch b/SOURCES/0043-dcerpc-Simplify-generation-of-LSA-RPC-binding-string.patch deleted file mode 100644 index 1edd83d..0000000 --- a/SOURCES/0043-dcerpc-Simplify-generation-of-LSA-RPC-binding-string.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 47e9c9cacdc189ac87983ed1596db3d48f45e089 Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Fri, 7 Aug 2015 18:03:48 +0200 -Subject: [PATCH] dcerpc: Simplify generation of LSA-RPC binding strings - -https://fedorahosted.org/freeipa/ticket/5183 - -Reviewed-By: Tomas Babej ---- - ipaserver/dcerpc.py | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py -index 74b4743d4bfb9c4950f441f1aa3561fc7a81391c..71106b6a804b8445e5c266a92a30ac7557dcf853 100644 ---- a/ipaserver/dcerpc.py -+++ b/ipaserver/dcerpc.py -@@ -855,8 +855,7 @@ class TrustDomainInstance(object): - """ - transports = (u'ncacn_np', u'ncacn_ip_tcp') - options = ( u'smb2,print', u'print') -- binding_template=lambda x,y,z: u'%s:%s[%s]' % (x, y, z) -- return [binding_template(t, remote_host, o) for t in transports for o in options] -+ return [u'%s:%s[%s]' % (t, remote_host, o) for t in transports for o in options] - - def retrieve_anonymously(self, remote_host, discover_srv=False, search_pdc=False): - """ --- -2.4.3 - diff --git a/SOURCES/0043-vault-Catch-correct-exception-in-decrypt.patch b/SOURCES/0043-vault-Catch-correct-exception-in-decrypt.patch new file mode 100644 index 0000000..25eb903 --- /dev/null +++ b/SOURCES/0043-vault-Catch-correct-exception-in-decrypt.patch @@ -0,0 +1,30 @@ +From cc92fe8badfe32f4c55abfa8b249dc1f94936d7c Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Wed, 3 Aug 2016 10:35:40 +0200 +Subject: [PATCH] vault: Catch correct exception in decrypt + +ValueError is raised when decryption fails. + +https://fedorahosted.org/freeipa/ticket/6160 + +Reviewed-By: David Kupka +--- + ipaclient/plugins/vault.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py +index e3a1ae3a0ad767bcee843b7fa3743a934e02d18b..73ad09b38316d55b466b7973dbeffefc1b7bb528 100644 +--- a/ipaclient/plugins/vault.py ++++ b/ipaclient/plugins/vault.py +@@ -164,7 +164,7 @@ def decrypt(data, symmetric_key=None, private_key=None): + label=None + ) + ) +- except AssertionError: ++ except ValueError: + raise errors.AuthenticationError( + message=_('Invalid credentials')) + +-- +2.7.4 + diff --git a/SOURCES/0044-Fixed-missing-KRA-agent-cert-on-replica.patch b/SOURCES/0044-Fixed-missing-KRA-agent-cert-on-replica.patch deleted file mode 100644 index 826d8b5..0000000 --- a/SOURCES/0044-Fixed-missing-KRA-agent-cert-on-replica.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 9d1657b3527e423e489a25fd7ee31692181f9f5b Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Sat, 1 Aug 2015 02:46:26 +0200 -Subject: [PATCH] Fixed missing KRA agent cert on replica. - -The code that exports the KRA agent certificate has been moved -such that it will be executed both on master and replica. - -https://fedorahosted.org/freeipa/ticket/5174 - -Reviewed-By: Jan Cholasta ---- - ipaserver/install/krainstance.py | 17 +++++++++-------- - 1 file changed, 9 insertions(+), 8 deletions(-) - -diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py -index 50ab424b0e59becfea9e7af4b8d43a32ccbdc823..fa50c3dec897d63b9d3522d196054163f7b3369a 100644 ---- a/ipaserver/install/krainstance.py -+++ b/ipaserver/install/krainstance.py -@@ -256,6 +256,15 @@ class KRAInstance(DogtagInstance): - os.remove(cfg_file) - - shutil.move(paths.KRA_BACKUP_KEYS_P12, paths.KRACERT_P12) -+ -+ # export ipaCert with private key for client authentication -+ args = ["/usr/bin/pki", -+ "-d", paths.HTTPD_ALIAS_DIR, -+ "-C", paths.ALIAS_PWDFILE_TXT, -+ "client-cert-show", "ipaCert", -+ "--client-cert", paths.KRA_AGENT_PEM] -+ ipautil.run(args) -+ - self.log.debug("completed creating KRA instance") - - def __add_ra_user_to_agent_group(self): -@@ -330,14 +339,6 @@ class KRAInstance(DogtagInstance): - finally: - os.remove(filename) - -- # export ipaCert with private key for client authentication -- args = ["/usr/bin/pki", -- "-d", paths.HTTPD_ALIAS_DIR, -- "-C", paths.ALIAS_PWDFILE_TXT, -- "client-cert-show", "ipaCert", -- "--client-cert", paths.KRA_AGENT_PEM] -- ipautil.run(args) -- - def __add_vault_container(self): - sub_dict = { - 'SUFFIX': self.suffix, --- -2.4.3 - diff --git a/SOURCES/0044-Increase-default-length-of-auto-generated-passwords.patch b/SOURCES/0044-Increase-default-length-of-auto-generated-passwords.patch new file mode 100644 index 0000000..1814e3c --- /dev/null +++ b/SOURCES/0044-Increase-default-length-of-auto-generated-passwords.patch @@ -0,0 +1,138 @@ +From 0d2e4dae80eb4140ea605ca88d9130b8bf3ec269 Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Fri, 22 Jul 2016 16:41:29 +0200 +Subject: [PATCH] Increase default length of auto generated passwords + +Installer/IPA generates passwords for warious purpose: +* KRA +* kerberos master key +* NSSDB password +* temporary passwords during installation + +Length of passwords should be increased to 22, ~128bits of entropy, to +be safe nowadays. + +https://fedorahosted.org/freeipa/ticket/6116 + +Reviewed-By: Alexander Bokovoy +--- + ipapython/ipautil.py | 3 ++- + ipaserver/plugins/baseuser.py | 5 +++-- + ipaserver/plugins/host.py | 9 +++++++-- + ipaserver/plugins/stageuser.py | 5 +++-- + ipaserver/plugins/user.py | 5 +++-- + 5 files changed, 18 insertions(+), 9 deletions(-) + +diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py +index 9964fba4f694b57242b3bd3065a418917d977533..fdfebb65ecb8b62108852f6517b5ffb22fd7eedc 100644 +--- a/ipapython/ipautil.py ++++ b/ipapython/ipautil.py +@@ -57,7 +57,8 @@ from ipapython.dn import DN + SHARE_DIR = paths.USR_SHARE_IPA_DIR + PLUGINS_SHARE_DIR = paths.IPA_PLUGINS + +-GEN_PWD_LEN = 12 ++GEN_PWD_LEN = 22 ++GEN_TMP_PWD_LEN = 12 # only for OTP password that is manually retyped by user + + # Having this in krb_utils would cause circular import + KRB5_KDC_UNREACH = 2529639068 # Cannot contact any KDC for requested realm +diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py +index e4288a5a131157815ffb2452692a7edb342f6ac3..5e36a6620295351d4745bfc035f24349f8fb8295 100644 +--- a/ipaserver/plugins/baseuser.py ++++ b/ipaserver/plugins/baseuser.py +@@ -34,7 +34,7 @@ from ipaserver.plugins.service import ( + from ipalib.request import context + from ipalib import _ + from ipapython import kerberos +-from ipapython.ipautil import ipa_generate_password ++from ipapython.ipautil import ipa_generate_password, GEN_TMP_PWD_LEN + from ipapython.ipavalidate import Email + from ipalib.util import ( + normalize_sshpubkey, +@@ -552,7 +552,8 @@ class baseuser_mod(LDAPUpdate): + + def check_userpassword(self, entry_attrs, **options): + if 'userpassword' not in entry_attrs and options.get('random'): +- entry_attrs['userpassword'] = ipa_generate_password(baseuser_pwdchars) ++ entry_attrs['userpassword'] = ipa_generate_password( ++ baseuser_pwdchars, pwd_len=GEN_TMP_PWD_LEN) + # save the password so it can be displayed in post_callback + setattr(context, 'randompassword', entry_attrs['userpassword']) + +diff --git a/ipaserver/plugins/host.py b/ipaserver/plugins/host.py +index 413dcf15e0423170d8334902b9dcf8fb5aa14de6..03c64c637cbba0aee1b6569f3b5dbe200953bff8 100644 +--- a/ipaserver/plugins/host.py ++++ b/ipaserver/plugins/host.py +@@ -59,7 +59,11 @@ from ipalib.util import (normalize_sshpubkey, validate_sshpubkey_no_options, + hostname_validator, + set_krbcanonicalname + ) +-from ipapython.ipautil import ipa_generate_password, CheckedIPAddress ++from ipapython.ipautil import ( ++ ipa_generate_password, ++ CheckedIPAddress, ++ GEN_TMP_PWD_LEN ++) + from ipapython.dnsutil import DNSName + from ipapython.ssh import SSHPublicKey + from ipapython.dn import DN +@@ -683,7 +687,8 @@ class host_add(LDAPCreate): + if 'krbprincipal' in entry_attrs['objectclass']: + entry_attrs['objectclass'].remove('krbprincipal') + if options.get('random'): +- entry_attrs['userpassword'] = ipa_generate_password(characters=host_pwd_chars) ++ entry_attrs['userpassword'] = ipa_generate_password( ++ characters=host_pwd_chars, pwd_len=GEN_TMP_PWD_LEN) + # save the password so it can be displayed in post_callback + setattr(context, 'randompassword', entry_attrs['userpassword']) + certs = options.get('usercertificate', []) +diff --git a/ipaserver/plugins/stageuser.py b/ipaserver/plugins/stageuser.py +index 3b9388f6020b9a6c40caedd36f3640a05a13da65..a219e3dace6da5e9c036122e9710b2acaaa42ebf 100644 +--- a/ipaserver/plugins/stageuser.py ++++ b/ipaserver/plugins/stageuser.py +@@ -47,7 +47,7 @@ from ipalib.util import set_krbcanonicalname + from ipalib import _, ngettext + from ipalib import output + from ipaplatform.paths import paths +-from ipapython.ipautil import ipa_generate_password ++from ipapython.ipautil import ipa_generate_password, GEN_TMP_PWD_LEN + from ipalib.capabilities import client_has_capability + + if six.PY3: +@@ -339,7 +339,8 @@ class stageuser_add(baseuser_add): + + # If requested, generate a userpassword + if 'userpassword' not in entry_attrs and options.get('random'): +- entry_attrs['userpassword'] = ipa_generate_password(baseuser_pwdchars) ++ entry_attrs['userpassword'] = ipa_generate_password( ++ baseuser_pwdchars, pwd_len=GEN_TMP_PWD_LEN) + # save the password so it can be displayed in post_callback + setattr(context, 'randompassword', entry_attrs['userpassword']) + +diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py +index b3ae7646fdcfa1dce10d90063dae2a24c091e8ee..935ea892cde9e2cb5b21f4714fd93e73c3fa53d5 100644 +--- a/ipaserver/plugins/user.py ++++ b/ipaserver/plugins/user.py +@@ -63,7 +63,7 @@ from ipalib import _, ngettext + from ipalib import output + from ipaplatform.paths import paths + from ipapython.dn import DN +-from ipapython.ipautil import ipa_generate_password ++from ipapython.ipautil import ipa_generate_password, GEN_TMP_PWD_LEN + from ipalib.capabilities import client_has_capability + + if api.env.in_server: +@@ -517,7 +517,8 @@ class user_add(baseuser_add): + entry_attrs['gidnumber'] = group_attrs['gidnumber'] + + if 'userpassword' not in entry_attrs and options.get('random'): +- entry_attrs['userpassword'] = ipa_generate_password(baseuser_pwdchars) ++ entry_attrs['userpassword'] = ipa_generate_password( ++ baseuser_pwdchars, pwd_len=GEN_TMP_PWD_LEN) + # save the password so it can be displayed in post_callback + setattr(context, 'randompassword', entry_attrs['userpassword']) + +-- +2.7.4 + diff --git a/SOURCES/0045-vault-add-missing-salt-option-to-vault_mod.patch b/SOURCES/0045-vault-add-missing-salt-option-to-vault_mod.patch new file mode 100644 index 0000000..802353a --- /dev/null +++ b/SOURCES/0045-vault-add-missing-salt-option-to-vault_mod.patch @@ -0,0 +1,31 @@ +From 001abcdca2026d0e1f51ca4e4e9d2cff052eadd7 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Thu, 4 Aug 2016 14:14:15 +0200 +Subject: [PATCH] vault: add missing salt option to vault_mod + +The option was accidentally removed in commit +4b119e21a2f93ca16c5edf3d1058552b44feeaf8. + +https://fedorahosted.org/freeipa/ticket/6154 + +Reviewed-By: Jan Cholasta +--- + ipaclient/plugins/vault.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py +index 73ad09b38316d55b466b7973dbeffefc1b7bb528..9026cbb0829a7557584df27a4262dfde640b4f28 100644 +--- a/ipaclient/plugins/vault.py ++++ b/ipaclient/plugins/vault.py +@@ -413,7 +413,7 @@ class vault_mod(Local): + + def get_options(self): + for option in self.api.Command.vault_mod_internal.options(): +- if option.name not in ('ipavaultsalt', 'version'): ++ if option.name != 'version': + yield option + for option in super(vault_mod, self).get_options(): + yield option +-- +2.7.4 + diff --git a/SOURCES/0045-webui-add-LDAP-vs-Kerberos-behavior-description-to-u.patch b/SOURCES/0045-webui-add-LDAP-vs-Kerberos-behavior-description-to-u.patch deleted file mode 100644 index 0457ec3..0000000 --- a/SOURCES/0045-webui-add-LDAP-vs-Kerberos-behavior-description-to-u.patch +++ /dev/null @@ -1,89 +0,0 @@ -From f169531c4b4fec3485015a9673e5b0d3b76e30d6 Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Mon, 10 Aug 2015 12:58:14 +0200 -Subject: [PATCH] webui: add LDAP vs Kerberos behavior description to user auth - types - -https://fedorahosted.org/freeipa/ticket/4935 - -Reviewed-By: David Kupka ---- - install/ui/src/freeipa/serverconfig.js | 5 ++++- - install/ui/src/freeipa/user.js | 5 ++++- - install/ui/test/data/ipa_init.json | 4 ++-- - ipalib/plugins/internal.py | 4 ++-- - 4 files changed, 12 insertions(+), 6 deletions(-) - -diff --git a/install/ui/src/freeipa/serverconfig.js b/install/ui/src/freeipa/serverconfig.js -index efe1805698372b45afae38d1f9dd883034ee03c6..70bb9574b8368d6a294dc171fdea2d03dfe56cab 100644 ---- a/install/ui/src/freeipa/serverconfig.js -+++ b/install/ui/src/freeipa/serverconfig.js -@@ -83,7 +83,10 @@ return { - { label: '@i18n:authtype.type_radius', value: 'radius' }, - { label: '@i18n:authtype.type_otp', value: 'otp' } - ], -- tooltip: '@i18n:authtype.config_tooltip' -+ tooltip: { -+ title: '@i18n:authtype.config_tooltip', -+ html: true -+ } - }, - { - $type: 'checkbox', -diff --git a/install/ui/src/freeipa/user.js b/install/ui/src/freeipa/user.js -index 0e828c16b999ffd58504bc4e53d2748bcd16b042..a920e088aacd02585cd131dce725272f47e4cf1c 100644 ---- a/install/ui/src/freeipa/user.js -+++ b/install/ui/src/freeipa/user.js -@@ -188,7 +188,10 @@ return { - { label: '@i18n:authtype.type_radius', value: 'radius' }, - { label: '@i18n:authtype.type_otp', value: 'otp' } - ], -- tooltip: '@i18n:authtype.user_tooltip' -+ tooltip: { -+ title: '@i18n:authtype.user_tooltip', -+ html: true -+ } - }, - { - $type: 'entity_select', -diff --git a/install/ui/test/data/ipa_init.json b/install/ui/test/data/ipa_init.json -index ef172950527512e71c28916274153036f17212fe..b80e44ffe8ead3d0b29196ca3af18e00d72a9f04 100644 ---- a/install/ui/test/data/ipa_init.json -+++ b/install/ui/test/data/ipa_init.json -@@ -49,12 +49,12 @@ - "show_results": "Show Results" - }, - "authtype": { -- "config_tooltip": "Implicit method (password) will be used if no method is chosen.", -+ "config_tooltip": "

Implicit method (password) will be used if no method is chosen.

Password + Two-factor: LDAP and Kerberos allow authentication with either one of the authentication types but Kerberos uses pre-authentication method which requires to use armor ccache.

RADIUS with another type: Kerberos always use RADIUS, but LDAP never does. LDAP only recognize the password and two-factor authentication options.

", - "type_otp": "Two factor authentication (password + OTP)", - "type_password": "Password", - "type_radius": "Radius", - "type_disabled": "Disable per-user override", -- "user_tooltip": "Per-user setting, overwrites the global setting if any option is checked." -+ "user_tooltip": "

Per-user setting, overwrites the global setting if any option is checked.

Password + Two-factor: LDAP and Kerberos allow authentication with either one of the authentication types but Kerberos uses pre-authentication method which requires to use armor ccache.

RADIUS with another type: Kerberos always use RADIUS, but LDAP never does. LDAP only recognize the password and two-factor authentication options.

", - }, - "buttons": { - "about": "About", -diff --git a/ipalib/plugins/internal.py b/ipalib/plugins/internal.py -index f97885ceae8f3c0913a16c281c2faa8a918541e7..e1904d2d3d1e1523895554b8d8e58b1dfd070366 100644 ---- a/ipalib/plugins/internal.py -+++ b/ipalib/plugins/internal.py -@@ -191,12 +191,12 @@ class i18n_messages(Command): - "show_results": _("Show Results"), - }, - "authtype": { -- "config_tooltip": _("Implicit method (password) will be used if no method is chosen."), -+ "config_tooltip": _("

Implicit method (password) will be used if no method is chosen.

Password + Two-factor: LDAP and Kerberos allow authentication with either one of the authentication types but Kerberos uses pre-authentication method which requires to use armor ccache.

RADIUS with another type: Kerberos always use RADIUS, but LDAP never does. LDAP only recognize the password and two-factor authentication options.

"), - "type_otp": _("Two factor authentication (password + OTP)"), - "type_password": _("Password"), - "type_radius": _("Radius"), - "type_disabled": _("Disable per-user override"), -- "user_tooltip": _("Per-user setting, overwrites the global setting if any option is checked."), -+ "user_tooltip": _("

Per-user setting, overwrites the global setting if any option is checked.

Password + Two-factor: LDAP and Kerberos allow authentication with either one of the authentication types but Kerberos uses pre-authentication method which requires to use armor ccache.

RADIUS with another type: Kerberos always use RADIUS, but LDAP never does. LDAP only recognize the password and two-factor authentication options.

"), - }, - "buttons": { - "about": _("About"), --- -2.4.3 - diff --git a/SOURCES/0046-Fix-ipa-hbactest-output.patch b/SOURCES/0046-Fix-ipa-hbactest-output.patch new file mode 100644 index 0000000..252279e --- /dev/null +++ b/SOURCES/0046-Fix-ipa-hbactest-output.patch @@ -0,0 +1,46 @@ +From 56f6fe1df44bc9d3f434b0bccd44bc11cda89999 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Tue, 2 Aug 2016 10:40:54 +0200 +Subject: [PATCH] Fix ipa hbactest output + +ipa hbactest command produces a Traceback (TypeError: cannot concatenate +'str' and 'bool' objects) +This happens because hbactest overrides output_for_cli but does not +properly handle the output for 'value' field. 'value' contains a boolean +but it should not be displayed (refer to ipalib/frontend.py, +Command.output_for_cli()). + +Note that the issue did not appear before because the 'value' field +had a flag no_display. + +https://fedorahosted.org/freeipa/ticket/6157 + +Reviewed-By: Martin Basti +--- + ipaclient/plugins/hbactest.py | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/ipaclient/plugins/hbactest.py b/ipaclient/plugins/hbactest.py +index 2518719522c4eddff2e6bc341ee9a7c34b431938..1b54530b236cf654bc8ece7ab4e329850f5a6815 100644 +--- a/ipaclient/plugins/hbactest.py ++++ b/ipaclient/plugins/hbactest.py +@@ -39,13 +39,15 @@ class hbactest(CommandOverride): + # to be printed as our execute() method will return None for corresponding + # entries and None entries will be skipped. + for o in self.output: ++ if o == 'value': ++ continue + outp = self.output[o] + if 'no_display' in outp.flags: + continue + result = output[o] + if isinstance(result, (list, tuple)): + textui.print_attribute(unicode(outp.doc), result, '%s: %s', 1, True) +- elif isinstance(result, (unicode, bool)): ++ elif isinstance(result, unicode): + if o == 'summary': + textui.print_summary(result) + else: +-- +2.7.4 + diff --git a/SOURCES/0046-Fix-upgrade-of-sidgen-and-extdom-plugins.patch b/SOURCES/0046-Fix-upgrade-of-sidgen-and-extdom-plugins.patch deleted file mode 100644 index c16440a..0000000 --- a/SOURCES/0046-Fix-upgrade-of-sidgen-and-extdom-plugins.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 0df0907537d53f731e5ffc833a7c8d2e2d1a51f7 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Mon, 10 Aug 2015 10:53:28 +0200 -Subject: [PATCH] Fix upgrade of sidgen and extdom plugins - -If configuration entries already exist, upgrade will not add them -again. - -https://fedorahosted.org/freeipa/ticket/5151 - -Reviewed-By: Martin Babinsky ---- - ipaserver/install/dsinstance.py | 28 +++++++++++++++++++++++++--- - ipaserver/install/server/upgrade.py | 9 ++++++--- - 2 files changed, 31 insertions(+), 6 deletions(-) - -diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py -index b2558024f0b345700bc544757e0eecd8b1052a1d..f33a9e03a4148dde69fc61441c878f5126f8e455 100644 ---- a/ipaserver/install/dsinstance.py -+++ b/ipaserver/install/dsinstance.py -@@ -925,20 +925,42 @@ class DsInstance(service.Service): - def __add_range_check_plugin(self): - self._ldap_mod("range-check-conf.ldif", self.sub_dict) - -- # These two methods are not local, they are also called from the upgrade code - def _add_sidgen_plugin(self): - """ - Add sidgen directory server plugin configuration if it does not already exist. - """ - self._ldap_mod('ipa-sidgen-conf.ldif', self.sub_dict) - -+ def add_sidgen_plugin(self): -+ """ -+ Add sidgen plugin configuration only if it does not already exist. -+ """ -+ dn = DN('cn=IPA SIDGEN,cn=plugins,cn=config') -+ try: -+ self.admin_conn.get_entry(dn) -+ except errors.NotFound: -+ self._add_sidgen_plugin() -+ else: -+ root_logger.debug("sidgen plugin is already configured") -+ - def _add_extdom_plugin(self): - """ -- Add directory server configuration for the extdom extended operation -- if it does not already exist. -+ Add directory server configuration for the extdom extended operation. - """ - self._ldap_mod('ipa-extdom-extop-conf.ldif', self.sub_dict) - -+ def add_extdom_plugin(self): -+ """ -+ Add extdom configuration if it does not already exist. -+ """ -+ dn = DN('cn=ipa_extdom_extop,cn=plugins,cn=config') -+ try: -+ self.admin_conn.get_entry(dn) -+ except errors.NotFound: -+ self._add_extdom_plugin() -+ else: -+ root_logger.debug("extdom plugin is already configured") -+ - def replica_populate(self): - self.ldap_connect() - -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index f295655dc2aa592e0215f15017c9b65af49eef80..037127918cb4c205c5049446989bfdaa674967a4 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -1261,11 +1261,11 @@ def ds_enable_sidgen_extdom_plugins(ds): - root_logger.info('[Enable sidgen and extdom plugins by default]') - - if sysupgrade.get_upgrade_state('ds', 'enable_ds_sidgen_extdom_plugins'): -- root_logger.info('sidgen and extdom plugins are enabled already') -+ root_logger.debug('sidgen and extdom plugins are enabled already') - return - -- ds._add_sidgen_plugin() -- ds._add_extdom_plugin() -+ ds.add_sidgen_plugin() -+ ds.add_extdom_plugin() - sysupgrade.set_upgrade_state('ds', 'enable_ds_sidgen_extdom_plugins', True) - - def ca_upgrade_schema(ca): -@@ -1415,7 +1415,10 @@ def upgrade_configuration(): - ds.fqdn = fqdn - ds.realm = api.env.realm - ds.suffix = ipautil.realm_to_suffix(api.env.realm) -+ -+ ds.ldap_connect() - ds_enable_sidgen_extdom_plugins(ds) -+ ds.ldap_disconnect() - - # Now 389-ds is available, run the remaining http tasks - if not http.is_kdcproxy_configured(): --- -2.4.3 - diff --git a/SOURCES/0047-Give-more-info-on-virtual-command-access-denial.patch b/SOURCES/0047-Give-more-info-on-virtual-command-access-denial.patch deleted file mode 100644 index 8c25117..0000000 --- a/SOURCES/0047-Give-more-info-on-virtual-command-access-denial.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 7416358e95e69a517424319ac31dfcc68bda2878 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Sun, 9 Aug 2015 01:54:41 -0400 -Subject: [PATCH] Give more info on virtual command access denial - -The current error message upon a virutal command access denial does -not give any information about the virtual operation that was -prohibited. Add more information to the ACIError message. - -Reviewed-By: Martin Babinsky ---- - ipalib/plugins/virtual.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipalib/plugins/virtual.py b/ipalib/plugins/virtual.py -index 414de4c0011b4ae49083d7820a3cb3708e3e16b1..3bbe32e538ab108d7abc71785e27664fea5ea248 100644 ---- a/ipalib/plugins/virtual.py -+++ b/ipalib/plugins/virtual.py -@@ -62,7 +62,7 @@ class VirtualCommand(Command): - try: - if not ldap.can_write(operationdn, "objectclass"): - raise errors.ACIError( -- info=_('not allowed to perform this command')) -+ info=_('not allowed to perform operation: %s') % operation) - except errors.NotFound: - raise errors.ACIError(info=_('No such virtual command')) - --- -2.4.3 - diff --git a/SOURCES/0047-install-fix-external-CA-cert-validation.patch b/SOURCES/0047-install-fix-external-CA-cert-validation.patch new file mode 100644 index 0000000..0e6980c --- /dev/null +++ b/SOURCES/0047-install-fix-external-CA-cert-validation.patch @@ -0,0 +1,31 @@ +From fdcaf9f8437fcd12220af125a4fe0871c6d33f47 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Thu, 4 Aug 2016 09:58:38 +0200 +Subject: [PATCH] install: fix external CA cert validation + +The code which loads the external CA cert chain was never executed because +of an incorrect usage of an iterator (iterating over it twice). + +https://fedorahosted.org/freeipa/ticket/6166 + +Reviewed-By: Jan Cholasta +--- + ipaserver/install/installutils.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py +index 25f48aed1eeaa03353465bc40abf3484ec19bf3b..66ba33326adcdb47c2ba77c573ba9b66a82b365e 100644 +--- a/ipaserver/install/installutils.py ++++ b/ipaserver/install/installutils.py +@@ -1038,7 +1038,7 @@ def load_external_cert(files, subject_base): + raise ScriptError( + "IPA CA certificate not found in %s" % (", ".join(files))) + +- trust_chain = reversed(nssdb.get_trust_chain(ca_nickname)) ++ trust_chain = list(reversed(nssdb.get_trust_chain(ca_nickname))) + ca_cert_chain = [] + for nickname in trust_chain: + cert, subject, issuer = cache[nickname] +-- +2.7.4 + diff --git a/SOURCES/0048-Allow-SAN-extension-for-cert-request-self-service.patch b/SOURCES/0048-Allow-SAN-extension-for-cert-request-self-service.patch deleted file mode 100644 index 5de2f41..0000000 --- a/SOURCES/0048-Allow-SAN-extension-for-cert-request-self-service.patch +++ /dev/null @@ -1,33 +0,0 @@ -From a7532af44e518994b8124b09e32fb3f494150ba6 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Sun, 9 Aug 2015 03:25:58 -0400 -Subject: [PATCH] Allow SAN extension for cert-request self-service - -Users cannot self-issue a certificate with a subjectAltName -extension (e.g. with rfc822Name altNames). Suppress the -cert-request "request certificate with subjectaltname" permission -check when the bind principal is the target principal (i.e. -cert-request self-service). - -Fixes: https://fedorahosted.org/freeipa/ticket/5190 -Reviewed-By: Martin Babinsky ---- - ipalib/plugins/cert.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipalib/plugins/cert.py b/ipalib/plugins/cert.py -index 341bdd01766d50ba18ce7147d4408851e6f95487..d612e9d38da44e4fd4768d286f930e51c71a1031 100644 ---- a/ipalib/plugins/cert.py -+++ b/ipalib/plugins/cert.py -@@ -369,7 +369,7 @@ class cert_request(VirtualCommand): - error=_("Failure decoding Certificate Signing Request: %s") % e) - - # host principals may bypass allowed ext check -- if bind_principal_type != HOST: -+ if bind_principal != principal and bind_principal_type != HOST: - for ext in extensions: - operation = self._allowed_extensions.get(ext) - if operation: --- -2.4.3 - diff --git a/SOURCES/0048-caacl-fix-regression-in-rule-instantiation.patch b/SOURCES/0048-caacl-fix-regression-in-rule-instantiation.patch new file mode 100644 index 0000000..beeb795 --- /dev/null +++ b/SOURCES/0048-caacl-fix-regression-in-rule-instantiation.patch @@ -0,0 +1,52 @@ +From c27595371bfe1f4fe12125e053cb7ec3ad08ebf6 Mon Sep 17 00:00:00 2001 +From: Fraser Tweedale +Date: Thu, 28 Jul 2016 10:55:45 +1000 +Subject: [PATCH] caacl: fix regression in rule instantiation + +The Principal refactor causes service collections +('memberservice_service' attribute) to return Principal objects +where previously it returned strings, but the HBAC machinery used +for CA ACL enforcement only handles strings. Update the code to +stringify service Principal objects when adding them to HBAC rules. + +Fixes: https://fedorahosted.org/freeipa/ticket/6146 +Reviewed-By: Martin Basti +--- + ipaserver/plugins/caacl.py | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +diff --git a/ipaserver/plugins/caacl.py b/ipaserver/plugins/caacl.py +index d316cc7c48cf2997d6be6b052dc1efa6d6fcdb6a..a7817c4cf64f070c74557f52e9f26c9013a4963c 100644 +--- a/ipaserver/plugins/caacl.py ++++ b/ipaserver/plugins/caacl.py +@@ -132,16 +132,21 @@ def _acl_make_rule(principal_type, obj): + rule.services.names = obj.get(attr, []) + + # add principals and principal's groups +- m = {'user': 'group', 'host': 'hostgroup', 'service': None} + category_attr = '{}category'.format(principal_type) + if category_attr in obj and obj[category_attr][0].lower() == 'all': + rule.users.category = {pyhbac.HBAC_CATEGORY_ALL} + else: +- principal_attr = 'member{}_{}'.format(principal_type, principal_type) +- rule.users.names = obj.get(principal_attr, []) +- if m[principal_type] is not None: +- group_attr = 'member{}_{}'.format(principal_type, m[principal_type]) +- rule.users.groups = obj.get(group_attr, []) ++ if principal_type == 'user': ++ rule.users.names = obj.get('memberuser_user', []) ++ rule.users.groups = obj.get('memberuser_group', []) ++ elif principal_type == 'host': ++ rule.users.names = obj.get('memberhost_host', []) ++ rule.users.groups = obj.get('memberhost_hostgroup', []) ++ elif principal_type == 'service': ++ rule.users.names = [ ++ unicode(principal) ++ for principal in obj.get('memberservice_service', []) ++ ] + + return rule + +-- +2.7.4 + diff --git a/SOURCES/0049-Add-profile-for-DNP3-IEC-62351-8-certificates.patch b/SOURCES/0049-Add-profile-for-DNP3-IEC-62351-8-certificates.patch deleted file mode 100644 index 89d69ff..0000000 --- a/SOURCES/0049-Add-profile-for-DNP3-IEC-62351-8-certificates.patch +++ /dev/null @@ -1,180 +0,0 @@ -From cfd3cbe627870f6a575e1fbdc52896c22bce4dcd Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Fri, 24 Jul 2015 09:32:51 -0400 -Subject: [PATCH] Add profile for DNP3 / IEC 62351-8 certificates - -The DNP3 smart-grid standard uses certificate with the IEC 62351-8 -IECUserRoles extension. Add a profile for DNP3 certificates which -copies the IECUserRoles extension from the CSR, if present. - -Also update cert-request to accept CSRs containing this extension. - -Fixes: https://fedorahosted.org/freeipa/ticket/4752 -Reviewed-By: Martin Babinsky ---- - install/share/profiles/IECUserRoles.cfg | 114 ++++++++++++++++++++++++++++++++ - install/share/profiles/Makefile.am | 1 + - ipalib/plugins/cert.py | 1 + - ipapython/dogtag.py | 1 + - 4 files changed, 117 insertions(+) - create mode 100644 install/share/profiles/IECUserRoles.cfg - -diff --git a/install/share/profiles/IECUserRoles.cfg b/install/share/profiles/IECUserRoles.cfg -new file mode 100644 -index 0000000000000000000000000000000000000000..9d2b4bb7932db42f6fc1f4e8edbc2bb741d8d8b6 ---- /dev/null -+++ b/install/share/profiles/IECUserRoles.cfg -@@ -0,0 +1,114 @@ -+profileId=IECUserRoles -+classId=caEnrollImpl -+desc=Enroll user certificates with IECUserRoles extension via IPA-RA agent authentication. -+visible=false -+enable=true -+enableBy=admin -+auth.instance_id=raCertAuth -+name=IPA-RA Agent-Authenticated Server Certificate Enrollment -+input.list=i1,i2 -+input.i1.class_id=certReqInputImpl -+input.i2.class_id=submitterInfoInputImpl -+output.list=o1 -+output.o1.class_id=certOutputImpl -+policyset.list=serverCertSet -+policyset.serverCertSet.list=1,2,3,4,5,6,7,8,9,10,11,12 -+policyset.serverCertSet.1.constraint.class_id=subjectNameConstraintImpl -+policyset.serverCertSet.1.constraint.name=Subject Name Constraint -+policyset.serverCertSet.1.constraint.params.pattern=CN=[^,]+,.+ -+policyset.serverCertSet.1.constraint.params.accept=true -+policyset.serverCertSet.1.default.class_id=subjectNameDefaultImpl -+policyset.serverCertSet.1.default.name=Subject Name Default -+policyset.serverCertSet.1.default.params.name=CN=$$request.req_subject_name.cn$$, $SUBJECT_DN_O -+policyset.serverCertSet.2.constraint.class_id=validityConstraintImpl -+policyset.serverCertSet.2.constraint.name=Validity Constraint -+policyset.serverCertSet.2.constraint.params.range=740 -+policyset.serverCertSet.2.constraint.params.notBeforeCheck=false -+policyset.serverCertSet.2.constraint.params.notAfterCheck=false -+policyset.serverCertSet.2.default.class_id=validityDefaultImpl -+policyset.serverCertSet.2.default.name=Validity Default -+policyset.serverCertSet.2.default.params.range=731 -+policyset.serverCertSet.2.default.params.startTime=0 -+policyset.serverCertSet.3.constraint.class_id=keyConstraintImpl -+policyset.serverCertSet.3.constraint.name=Key Constraint -+policyset.serverCertSet.3.constraint.params.keyType=RSA -+policyset.serverCertSet.3.constraint.params.keyParameters=1024,2048,3072,4096 -+policyset.serverCertSet.3.default.class_id=userKeyDefaultImpl -+policyset.serverCertSet.3.default.name=Key Default -+policyset.serverCertSet.4.constraint.class_id=noConstraintImpl -+policyset.serverCertSet.4.constraint.name=No Constraint -+policyset.serverCertSet.4.default.class_id=authorityKeyIdentifierExtDefaultImpl -+policyset.serverCertSet.4.default.name=Authority Key Identifier Default -+policyset.serverCertSet.5.constraint.class_id=noConstraintImpl -+policyset.serverCertSet.5.constraint.name=No Constraint -+policyset.serverCertSet.5.default.class_id=authInfoAccessExtDefaultImpl -+policyset.serverCertSet.5.default.name=AIA Extension Default -+policyset.serverCertSet.5.default.params.authInfoAccessADEnable_0=true -+policyset.serverCertSet.5.default.params.authInfoAccessADLocationType_0=URIName -+policyset.serverCertSet.5.default.params.authInfoAccessADLocation_0=http://$IPA_CA_RECORD.$DOMAIN/ca/ocsp -+policyset.serverCertSet.5.default.params.authInfoAccessADMethod_0=1.3.6.1.5.5.7.48.1 -+policyset.serverCertSet.5.default.params.authInfoAccessCritical=false -+policyset.serverCertSet.5.default.params.authInfoAccessNumADs=1 -+policyset.serverCertSet.6.constraint.class_id=keyUsageExtConstraintImpl -+policyset.serverCertSet.6.constraint.name=Key Usage Extension Constraint -+policyset.serverCertSet.6.constraint.params.keyUsageCritical=true -+policyset.serverCertSet.6.constraint.params.keyUsageDigitalSignature=true -+policyset.serverCertSet.6.constraint.params.keyUsageNonRepudiation=true -+policyset.serverCertSet.6.constraint.params.keyUsageDataEncipherment=true -+policyset.serverCertSet.6.constraint.params.keyUsageKeyEncipherment=true -+policyset.serverCertSet.6.constraint.params.keyUsageKeyAgreement=false -+policyset.serverCertSet.6.constraint.params.keyUsageKeyCertSign=false -+policyset.serverCertSet.6.constraint.params.keyUsageCrlSign=false -+policyset.serverCertSet.6.constraint.params.keyUsageEncipherOnly=false -+policyset.serverCertSet.6.constraint.params.keyUsageDecipherOnly=false -+policyset.serverCertSet.6.default.class_id=keyUsageExtDefaultImpl -+policyset.serverCertSet.6.default.name=Key Usage Default -+policyset.serverCertSet.6.default.params.keyUsageCritical=true -+policyset.serverCertSet.6.default.params.keyUsageDigitalSignature=true -+policyset.serverCertSet.6.default.params.keyUsageNonRepudiation=true -+policyset.serverCertSet.6.default.params.keyUsageDataEncipherment=true -+policyset.serverCertSet.6.default.params.keyUsageKeyEncipherment=true -+policyset.serverCertSet.6.default.params.keyUsageKeyAgreement=false -+policyset.serverCertSet.6.default.params.keyUsageKeyCertSign=false -+policyset.serverCertSet.6.default.params.keyUsageCrlSign=false -+policyset.serverCertSet.6.default.params.keyUsageEncipherOnly=false -+policyset.serverCertSet.6.default.params.keyUsageDecipherOnly=false -+policyset.serverCertSet.7.constraint.class_id=noConstraintImpl -+policyset.serverCertSet.7.constraint.name=No Constraint -+policyset.serverCertSet.7.default.class_id=extendedKeyUsageExtDefaultImpl -+policyset.serverCertSet.7.default.name=Extended Key Usage Extension Default -+policyset.serverCertSet.7.default.params.exKeyUsageCritical=false -+policyset.serverCertSet.7.default.params.exKeyUsageOIDs=1.3.6.1.5.5.7.3.1,1.3.6.1.5.5.7.3.2 -+policyset.serverCertSet.8.constraint.class_id=signingAlgConstraintImpl -+policyset.serverCertSet.8.constraint.name=No Constraint -+policyset.serverCertSet.8.constraint.params.signingAlgsAllowed=SHA1withRSA,SHA256withRSA,SHA512withRSA,MD5withRSA,MD2withRSA,SHA1withDSA,SHA1withEC,SHA256withEC,SHA384withEC,SHA512withEC -+policyset.serverCertSet.8.default.class_id=signingAlgDefaultImpl -+policyset.serverCertSet.8.default.name=Signing Alg -+policyset.serverCertSet.8.default.params.signingAlg=- -+policyset.serverCertSet.9.constraint.class_id=noConstraintImpl -+policyset.serverCertSet.9.constraint.name=No Constraint -+policyset.serverCertSet.9.default.class_id=crlDistributionPointsExtDefaultImpl -+policyset.serverCertSet.9.default.name=CRL Distribution Points Extension Default -+policyset.serverCertSet.9.default.params.crlDistPointsCritical=false -+policyset.serverCertSet.9.default.params.crlDistPointsNum=1 -+policyset.serverCertSet.9.default.params.crlDistPointsEnable_0=true -+policyset.serverCertSet.9.default.params.crlDistPointsIssuerName_0=$CRL_ISSUER -+policyset.serverCertSet.9.default.params.crlDistPointsIssuerType_0=DirectoryName -+policyset.serverCertSet.9.default.params.crlDistPointsPointName_0=http://$IPA_CA_RECORD.$DOMAIN/ipa/crl/MasterCRL.bin -+policyset.serverCertSet.9.default.params.crlDistPointsPointType_0=URIName -+policyset.serverCertSet.9.default.params.crlDistPointsReasons_0= -+policyset.serverCertSet.10.constraint.class_id=noConstraintImpl -+policyset.serverCertSet.10.constraint.name=No Constraint -+policyset.serverCertSet.10.default.class_id=subjectKeyIdentifierExtDefaultImpl -+policyset.serverCertSet.10.default.name=Subject Key Identifier Extension Default -+policyset.serverCertSet.10.default.params.critical=false -+policyset.serverCertSet.11.constraint.class_id=noConstraintImpl -+policyset.serverCertSet.11.constraint.name=No Constraint -+policyset.serverCertSet.11.default.class_id=userExtensionDefaultImpl -+policyset.serverCertSet.11.default.name=User Supplied Extension Default -+policyset.serverCertSet.11.default.params.userExtOID=2.5.29.17 -+policyset.serverCertSet.12.constraint.class_id=noConstraintImpl -+policyset.serverCertSet.12.constraint.name=No Constraint -+policyset.serverCertSet.12.default.class_id=userExtensionDefaultImpl -+policyset.serverCertSet.12.default.name=IECUserRoles Extension Default -+policyset.serverCertSet.12.default.params.userExtOID=1.2.840.10070.8.1 -diff --git a/install/share/profiles/Makefile.am b/install/share/profiles/Makefile.am -index 4e6cf975a0f51d02ec29bd07ac8cb9ccc8320818..b5ccb6e9317a93c040b7de0e0bc1ca5cb88c33fc 100644 ---- a/install/share/profiles/Makefile.am -+++ b/install/share/profiles/Makefile.am -@@ -3,6 +3,7 @@ NULL = - appdir = $(IPA_DATA_DIR)/profiles - app_DATA = \ - caIPAserviceCert.cfg \ -+ IECUserRoles.cfg \ - $(NULL) - - EXTRA_DIST = \ -diff --git a/ipalib/plugins/cert.py b/ipalib/plugins/cert.py -index d612e9d38da44e4fd4768d286f930e51c71a1031..b6e6d7981846778896eabce1a29a88fdf9a639e1 100644 ---- a/ipalib/plugins/cert.py -+++ b/ipalib/plugins/cert.py -@@ -312,6 +312,7 @@ class cert_request(VirtualCommand): - '2.5.29.17': 'request certificate with subjectaltname', - '2.5.29.19': None, # Basic Constraints - '2.5.29.37': None, # Extended Key Usage -+ '1.2.840.10070.8.1': None, # IECUserRoles (DNP3 / IEC 62351-8) - } - - def execute(self, csr, **kw): -diff --git a/ipapython/dogtag.py b/ipapython/dogtag.py -index 53085f7762fc828ed9fc6621fbf3a0c67ec6a656..0782d360ccf2ce2c90c4e9cfa66b5159e437e77c 100644 ---- a/ipapython/dogtag.py -+++ b/ipapython/dogtag.py -@@ -45,6 +45,7 @@ from ipapython.ipa_log_manager import * - INCLUDED_PROFILES = { - # ( profile_id , description , store_issued) - (u'caIPAserviceCert', u'Standard profile for network services', True), -+ (u'IECUserRoles', u'User profile that includes IECUserRoles extension from request', True), - } - - DEFAULT_PROFILE = u'caIPAserviceCert' --- -2.4.3 - diff --git a/SOURCES/0049-Update-ipa-replica-install-documentation.patch b/SOURCES/0049-Update-ipa-replica-install-documentation.patch new file mode 100644 index 0000000..eb68a96 --- /dev/null +++ b/SOURCES/0049-Update-ipa-replica-install-documentation.patch @@ -0,0 +1,45 @@ +From 2c82ea7bd562c34fd6ea9476b3b9b25f399bb0f1 Mon Sep 17 00:00:00 2001 +From: Tomas Krizek +Date: Fri, 5 Aug 2016 09:25:05 +0200 +Subject: [PATCH] Update ipa-replica-install documentation + +Update the ipa-replica-install man page and help to reflect that replica_file +is optional instead of mandatory. + +https://fedorahosted.org/freeipa/ticket/6164 + +Reviewed-By: Martin Basti +--- + install/tools/ipa-replica-install | 2 +- + install/tools/man/ipa-replica-install.1 | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install +index 17fc957a583739bbda386676f44209e196282a9a..b3f0361c6577cb693dcc0d81d8ca95b0c220679e 100755 +--- a/install/tools/ipa-replica-install ++++ b/install/tools/ipa-replica-install +@@ -27,7 +27,7 @@ ReplicaInstall = cli.install_tool( + Replica, + command_name='ipa-replica-install', + positional_arguments=['replica_file'], +- usage='%prog [options] REPLICA_FILE', ++ usage='%prog [options] [REPLICA_FILE]', + log_file_name=paths.IPAREPLICA_INSTALL_LOG, + debug_option=True, + ) +diff --git a/install/tools/man/ipa-replica-install.1 b/install/tools/man/ipa-replica-install.1 +index 55bae2cb77e1a1c520e0598983b8939a919a9ee9..af37b07956691aeb676bb8e41e90f6ce783a5270 100644 +--- a/install/tools/man/ipa-replica-install.1 ++++ b/install/tools/man/ipa-replica-install.1 +@@ -22,7 +22,7 @@ ipa\-replica\-install \- Create an IPA replica + .SH "SYNOPSIS" + .SS "DOMAIN LEVEL 0" + .TP +-ipa\-replica\-install [\fIOPTION\fR]... replica_file ++ipa\-replica\-install [\fIOPTION\fR]... [replica_file] + .SS "DOMAIN LEVEL 1" + .TP + ipa\-replica\-install [\fIOPTION\fR]... +-- +2.7.4 + diff --git a/SOURCES/0050-Work-around-python-nss-bug-on-unrecognised-OIDs.patch b/SOURCES/0050-Work-around-python-nss-bug-on-unrecognised-OIDs.patch deleted file mode 100644 index afa5653..0000000 --- a/SOURCES/0050-Work-around-python-nss-bug-on-unrecognised-OIDs.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 688660a0545f5a29b6f4f2f06bbef23d3dbef688 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Fri, 24 Jul 2015 09:23:07 -0400 -Subject: [PATCH] Work around python-nss bug on unrecognised OIDs - -A bug in python-nss causes an error to be thrown when converting an -unrecognised OID to a string. If cert-request receives a PKCS #10 -CSR with an unknown extension, the error is thrown. - -Work around this error by first checking if the OID is recognised -and, if it is not, using a different method to obtain its string -representation. - -Once the python-nss bug is fixed, this workaround should be -reverted. https://bugzilla.redhat.com/show_bug.cgi?id=1246729 - -Reviewed-By: Martin Babinsky ---- - ipalib/pkcs10.py | 15 ++++++++++++++- - 1 file changed, 14 insertions(+), 1 deletion(-) - -diff --git a/ipalib/pkcs10.py b/ipalib/pkcs10.py -index 6299dfea43b7a3f4104f0b0ec78c4f105d9daf62..64670835127e96f1d724c5f32ed7a939d37b7f16 100644 ---- a/ipalib/pkcs10.py -+++ b/ipalib/pkcs10.py -@@ -53,7 +53,20 @@ def get_extensions(csr, datatype=PEM): - The return value is a tuple of strings - """ - request = load_certificate_request(csr, datatype) -- return tuple(nss.oid_dotted_decimal(ext.oid_tag)[4:] -+ -+ # Work around a bug in python-nss where nss.oid_dotted_decimal -+ # errors on unrecognised OIDs -+ # -+ # https://bugzilla.redhat.com/show_bug.cgi?id=1246729 -+ # -+ def get_prefixed_oid_str(ext): -+ """Returns a string like 'OID.1.2...'.""" -+ if ext.oid_tag == 0: -+ return repr(ext) -+ else: -+ return nss.oid_dotted_decimal(ext.oid) -+ -+ return tuple(get_prefixed_oid_str(ext)[4:] - for ext in request.extensions) - - class _PrincipalName(univ.Sequence): --- -2.4.3 - diff --git a/SOURCES/0050-ipa-kdb-Fix-unit-test-after-packaging-changes-in-krb.patch b/SOURCES/0050-ipa-kdb-Fix-unit-test-after-packaging-changes-in-krb.patch new file mode 100644 index 0000000..28a3b5d --- /dev/null +++ b/SOURCES/0050-ipa-kdb-Fix-unit-test-after-packaging-changes-in-krb.patch @@ -0,0 +1,29 @@ +From 92c1f960cd31417d898230f9cb538dc2336ba590 Mon Sep 17 00:00:00 2001 +From: Lukas Slebodnik +Date: Fri, 5 Aug 2016 08:34:23 +0200 +Subject: [PATCH] ipa-kdb: Fix unit test after packaging changes in krb5 + +Resolves: +https://fedorahosted.org/freeipa/ticket/6173 + +Reviewed-By: Alexander Bokovoy +--- + freeipa.spec.in | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/freeipa.spec.in b/freeipa.spec.in +index ff27a32eebcc640cdbc8895f47732f06a90c4a1b..e1d98a44d04804a6bb2d4b17206aa7c280d64eb9 100644 +--- a/freeipa.spec.in ++++ b/freeipa.spec.in +@@ -108,6 +108,8 @@ BuildRequires: python-netifaces >= 0.10.4 + # Build dependencies for unit tests + BuildRequires: libcmocka-devel + BuildRequires: nss_wrapper ++# Required by ipa_kdb_tests ++BuildRequires: %{_libdir}/krb5/plugins/kdb/db2.so + + %if 0%{?with_python3} + BuildRequires: python3-devel +-- +2.7.4 + diff --git a/SOURCES/0051-Improvements-for-the-ipa-cacert-manage-man-and-help.patch b/SOURCES/0051-Improvements-for-the-ipa-cacert-manage-man-and-help.patch new file mode 100644 index 0000000..9945b12 --- /dev/null +++ b/SOURCES/0051-Improvements-for-the-ipa-cacert-manage-man-and-help.patch @@ -0,0 +1,117 @@ +From 57f643fa5ba0382bbe8a35bd3cc6fe7bec721064 Mon Sep 17 00:00:00 2001 +From: Stanislav Laznicka +Date: Fri, 15 Jul 2016 14:04:59 +0200 +Subject: [PATCH] Improvements for the ipa-cacert-manage man and help + +The man page for ipa-cacert-manage didn't mention that some +options are only applicable to the install some to the renew +subcommand. + +Also fixed a few missing articles. + +https://fedorahosted.org/freeipa/ticket/6013 + +Reviewed-By: Florence Blanc-Renaud +--- + install/tools/man/ipa-cacert-manage.1 | 38 ++++++++++++++++++++++------------ + ipaserver/install/ipa_cacert_manage.py | 2 +- + 2 files changed, 26 insertions(+), 14 deletions(-) + +diff --git a/install/tools/man/ipa-cacert-manage.1 b/install/tools/man/ipa-cacert-manage.1 +index 1f37788336048e412eee71757f236c9944860514..f0a1033ab372c2f923a883b385c0e3304b98f56f 100644 +--- a/install/tools/man/ipa-cacert-manage.1 ++++ b/install/tools/man/ipa-cacert-manage.1 +@@ -20,7 +20,9 @@ + .SH "NAME" + ipa\-cacert\-manage \- Manage CA certificates in IPA + .SH "SYNOPSIS" +-\fBipa\-cacert\-manage\fR [\fIOPTIONS\fR...] \fICOMMAND\fR ++\fBipa\-cacert\-manage\fR [\fIOPTIONS\fR...] renew ++.RE ++\fBipa\-cacert\-manage\fR [\fIOPTIONS\fR...] install \fICERTFILE\fR + .SH "DESCRIPTION" + \fBipa\-cacert\-manage\fR can be used to manage CA certificates in IPA. + .SH "COMMANDS" +@@ -29,7 +31,7 @@ ipa\-cacert\-manage \- Manage CA certificates in IPA + \- Renew the IPA CA certificate + .sp + .RS +-This command can be used to manually renew CA certificate of the IPA CA. ++This command can be used to manually renew the CA certificate of the IPA CA. + .sp + When the IPA CA is the root CA (the default), it is not usually necessary to manually renew the CA certificate, as it will be renewed automatically when it is about to expire, but you can do so if you wish. + .sp +@@ -42,13 +44,30 @@ When the IPA CA is not configured, this command is not available. + \- Install a CA certificate + .sp + .RS +-This command can be used to install new CA certificate to IPA. ++This command can be used to install the certificate contained in \fICERTFILE\fR as a new CA certificate to IPA. + .RE +-.SH "OPTIONS" ++.SH "COMMON OPTIONS" ++.TP ++\fB\-\-version\fR ++Show the program's version and exit. ++.TP ++\fB\-h\fR, \fB\-\-help\fR ++Show the help for this program. + .TP + \fB\-p\fR \fIDM_PASSWORD\fR, \fB\-\-password\fR=\fIDM_PASSWORD\fR + The Directory Manager password to use for authentication. + .TP ++\fB\-v\fR, \fB\-\-verbose\fR ++Print debugging information. ++.TP ++\fB\-q\fR, \fB\-\-quiet\fR ++Output only errors. ++.TP ++\fB\-\-log\-file\fR=\fIFILE\fR ++Log to the given file. ++.RE ++.SH "RENEW OPTIONS" ++.TP + \fB\-\-self\-signed\fR + Sign the renewed certificate by itself. + .TP +@@ -57,6 +76,8 @@ Sign the renewed certificate by external CA. + .TP + \fB\-\-external\-cert\-file\fR=\fIFILE\fR + File containing the IPA CA certificate and the external CA certificate chain. The file is accepted in PEM and DER certificate and PKCS#7 certificate chain formats. This option may be used multiple times. ++.RE ++.SH "INSTALL OPTIONS" + .TP + \fB\-n\fR \fINICKNAME\fR, \fB\-\-nickname\fR=\fINICKNAME\fR + Nickname for the certificate. +@@ -73,15 +94,6 @@ T \- CA trusted to issue client certificates + .IP + p \- not trusted + .RE +-.TP +-\fB\-v\fR, \fB\-\-verbose\fR +-Print debugging information. +-.TP +-\fB\-q\fR, \fB\-\-quiet\fR +-Output only errors. +-.TP +-\fB\-\-log\-file\fR=\fIFILE\fR +-Log to the given file. + .SH "EXIT STATUS" + 0 if the command was successful + +diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py +index de13ad39397ae5e9b924b0621521e5fc6016c8e6..32ef25c7aac3e57d27955b6a2608adb6a1626019 100644 +--- a/ipaserver/install/ipa_cacert_manage.py ++++ b/ipaserver/install/ipa_cacert_manage.py +@@ -35,7 +35,7 @@ from ipaserver.install import certs, cainstance, installutils + class CACertManage(admintool.AdminTool): + command_name = 'ipa-cacert-manage' + +- usage = "%prog {renew|install} [options]" ++ usage = "%prog renew [options]\n%prog install [options] CERTFILE" + + description = "Manage CA certificates." + +-- +2.7.4 + diff --git a/SOURCES/0051-adtrust-install-Correctly-determine-4.2-FreeIPA-serv.patch b/SOURCES/0051-adtrust-install-Correctly-determine-4.2-FreeIPA-serv.patch deleted file mode 100644 index 6c46e62..0000000 --- a/SOURCES/0051-adtrust-install-Correctly-determine-4.2-FreeIPA-serv.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 6cc7d00a8d6966b4be24fa9b3df12dcba094b6ef Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Tue, 11 Aug 2015 16:05:32 +0200 -Subject: [PATCH] adtrust-install: Correctly determine 4.2 FreeIPA servers - -We need to detect a list of FreeIPA 4.2 (and above) servers, since -only there is the required version of SSSD present. - -Since the maximum domain level for 4.2 is 0 (and not 1), we can filter -for any value of ipaMaxDomainLevel / ipaMinDomainLevel attributes -to generate the list. - -https://fedorahosted.org/freeipa/ticket/5199 - -Reviewed-By: Alexander Bokovoy ---- - install/tools/ipa-adtrust-install | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/install/tools/ipa-adtrust-install b/install/tools/ipa-adtrust-install -index 5340c31d16ed78da0cb39725d9ae93c76470b698..21e58dd9f25e82429ce8d0c776d1b512c2661809 100755 ---- a/install/tools/ipa-adtrust-install -+++ b/install/tools/ipa-adtrust-install -@@ -396,7 +396,7 @@ def main(): - # Search only masters which have support for domain levels - # because only these masters will have SSSD recent enough to support AD trust agents - (entries_m, truncated) = smb.admin_conn.find_entries( -- filter="(&(objectclass=ipaSupportedDomainLevelConfig)(!(ipaMaxDomainLevel=0)))", -+ filter="(&(objectclass=ipaSupportedDomainLevelConfig)(ipaMaxDomainLevel=*)(ipaMinDomainLevel=*))", - base_dn=masters_dn, attrs_list=['cn'], scope=ldap.SCOPE_ONELEVEL) - except errors.NotFound: - pass --- -2.4.3 - diff --git a/SOURCES/0052-Revert-spec-add-conflict-with-bind-chroot-to-freeipa.patch b/SOURCES/0052-Revert-spec-add-conflict-with-bind-chroot-to-freeipa.patch new file mode 100644 index 0000000..98c97b7 --- /dev/null +++ b/SOURCES/0052-Revert-spec-add-conflict-with-bind-chroot-to-freeipa.patch @@ -0,0 +1,35 @@ +From 61746b75a7b10115633df2f9dce075c0bbdf161e Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Tue, 9 Aug 2016 14:12:50 +0200 +Subject: [PATCH] Revert "spec: add conflict with bind-chroot to + freeipa-server-dns" + +Remove the conflict, as bind-chroot caused issue only on systems with older +bind and bind-chroot - e.g. RHEL 6. + +This reverts commit 3ab63fa6ba60947b1452c2108c4cf7637f4aacdb. + +https://fedorahosted.org/freeipa/ticket/5696 + +Reviewed-By: Petr Spacek +--- + freeipa.spec.in | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/freeipa.spec.in b/freeipa.spec.in +index e1d98a44d04804a6bb2d4b17206aa7c280d64eb9..77fca24ef0e1e244e53d203a228931b4a444fb5a 100644 +--- a/freeipa.spec.in ++++ b/freeipa.spec.in +@@ -274,9 +274,6 @@ Obsoletes: %{alt_name}-server-dns < %{version} + # upgrade path from monolithic -server to -server + -server-dns + Obsoletes: %{name}-server <= 4.2.0 + +-# FreeIPA does not support running integrated BIND in chroot jail +-Conflicts: bind-chroot +- + %description server-dns + IPA integrated DNS server with support for automatic DNSSEC signing. + Integrated DNS server is BIND 9. OpenDNSSEC provides key management. +-- +2.7.4 + diff --git a/SOURCES/0052-certprofile-import-improve-profile-format-documentat.patch b/SOURCES/0052-certprofile-import-improve-profile-format-documentat.patch deleted file mode 100644 index e5e3287..0000000 --- a/SOURCES/0052-certprofile-import-improve-profile-format-documentat.patch +++ /dev/null @@ -1,31 +0,0 @@ -From c6c3ee0658fcda223bd98fed8d696bdb26add4ac Mon Sep 17 00:00:00 2001 -From: Christian Heimes -Date: Thu, 23 Jul 2015 18:22:19 +0200 -Subject: [PATCH] certprofile-import: improve profile format documentation - -The certprofile-import plugin expects a raw Dogtag config file. The XML -format is not supported. --help gives a hint about the correct file format. - -https://fedorahosted.org/freeipa/ticket/5089 - -Reviewed-By: Fraser Tweedale ---- - ipalib/plugins/certprofile.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipalib/plugins/certprofile.py b/ipalib/plugins/certprofile.py -index b0b76ca8e78f2482b5c08dad21d9161fd4c2c2d0..658fbca3b4eb851eb5a22190c443044f6ceb8491 100644 ---- a/ipalib/plugins/certprofile.py -+++ b/ipalib/plugins/certprofile.py -@@ -221,7 +221,7 @@ class certprofile_import(LDAPCreate): - msg_summary = _('Imported profile "%(value)s"') - takes_options = ( - File('file', -- label=_('Filename'), -+ label=_('Filename of a raw profile. The XML format is not supported.'), - cli_name='file', - flags=('virtual_attribute',), - ), --- -2.4.3 - diff --git a/SOURCES/0053-Fix-default-CA-ACL-added-during-upgrade.patch b/SOURCES/0053-Fix-default-CA-ACL-added-during-upgrade.patch deleted file mode 100644 index 7aa2975..0000000 --- a/SOURCES/0053-Fix-default-CA-ACL-added-during-upgrade.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 3e8d1d09e5a1b19c64a0356d2b19dac74c20ad73 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Fri, 7 Aug 2015 03:21:43 -0400 -Subject: [PATCH] Fix default CA ACL added during upgrade - -The upgrade script is adding the default CA ACL with incorrect -attributes - usercategory=all instead of servicecategory=all. Fix -it to create the correct object. - -Fixes: https://fedorahosted.org/freeipa/ticket/5185 -Reviewed-By: Martin Babinsky ---- - ipaserver/install/server/upgrade.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index 037127918cb4c205c5049446989bfdaa674967a4..692d0c77e0683f4ad35ebbc14d5a34decc098deb 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -1306,7 +1306,7 @@ def add_default_caacl(ca): - - if not api.Command.caacl_find()['result']: - api.Command.caacl_add(u'hosts_services_caIPAserviceCert', -- hostcategory=u'all', usercategory=u'all') -+ hostcategory=u'all', servicecategory=u'all') - api.Command.caacl_add_profile(u'hosts_services_caIPAserviceCert', - certprofile=(u'caIPAserviceCert',)) - --- -2.4.3 - diff --git a/SOURCES/0053-Fix-unicode-characters-in-ca-and-domain-adders.patch b/SOURCES/0053-Fix-unicode-characters-in-ca-and-domain-adders.patch new file mode 100644 index 0000000..f32cb64 --- /dev/null +++ b/SOURCES/0053-Fix-unicode-characters-in-ca-and-domain-adders.patch @@ -0,0 +1,41 @@ +From 8163981ec3296c6768cacad2ac7382ae2c706853 Mon Sep 17 00:00:00 2001 +From: Pavel Vomacka +Date: Fri, 5 Aug 2016 14:04:03 +0200 +Subject: [PATCH] Fix unicode characters in ca and domain adders + +Topology graph didn't show plus icons correctly. + +There is a problem with uglifying of javascript code. It does not leave unicode character +written in hexadecimal format unchanged. Therefore this workaround which inserts +needed character using Javascript function and uglifiyng does not affect it. + +https://fedorahosted.org/freeipa/ticket/6175 + +Reviewed-By: Martin Basti +--- + install/ui/src/freeipa/topology_graph.js | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/install/ui/src/freeipa/topology_graph.js b/install/ui/src/freeipa/topology_graph.js +index ce2ebeaff611987ae27f2655b5da80bdcd1b4f8a..4bc3668647979c77719efa78b7a663d0e899216e 100644 +--- a/install/ui/src/freeipa/topology_graph.js ++++ b/install/ui/src/freeipa/topology_graph.js +@@ -530,12 +530,14 @@ topology_graph.TopoGraph = declare([Evented], { + + function add_labels(type, color, adder_group) { + var label_radius = 3; ++ var decimal_plus = parseInt('f067', 16); // Converts hexadecimal ++ // code of plus icon to decimal. + + var plus = adder_group + .append('text') + .classed('plus', true) + .classed(type + '_plus', true) +- .text('\uf067'); ++ .text(String.fromCharCode(decimal_plus)); + + var label = adder_group.append('path') + .attr('id', type + '_label'); +-- +2.7.4 + diff --git a/SOURCES/0054-Fix-KRB5PrincipalName-UPN-SAN-comparison.patch b/SOURCES/0054-Fix-KRB5PrincipalName-UPN-SAN-comparison.patch deleted file mode 100644 index c17d7cf..0000000 --- a/SOURCES/0054-Fix-KRB5PrincipalName-UPN-SAN-comparison.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 34be9a7cd6eb4f379f09fd40d723fa83317f2b61 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Sun, 9 Aug 2015 05:55:04 -0400 -Subject: [PATCH] Fix KRB5PrincipalName / UPN SAN comparison - -Depending on how the target principal name is conveyed to the -command (i.e. with / without realm), the KRB5PrincipalName / UPN -subjectAltName validation could be comparing unequal strings and -erroneously rejecting a valid request. - -Normalise both side of the comparison to ensure that the principal -names contain realm information. - -Fixes: https://fedorahosted.org/freeipa/ticket/5191 -Reviewed-By: Martin Babinsky ---- - ipalib/plugins/cert.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipalib/plugins/cert.py b/ipalib/plugins/cert.py -index b6e6d7981846778896eabce1a29a88fdf9a639e1..610f2149363eaa74180e9de5c9ee1439446ef409 100644 ---- a/ipalib/plugins/cert.py -+++ b/ipalib/plugins/cert.py -@@ -474,7 +474,7 @@ class cert_request(VirtualCommand): - principal_type, alt_principal_string, ca, profile_id) - elif name_type in (pkcs10.SAN_OTHERNAME_KRB5PRINCIPALNAME, - pkcs10.SAN_OTHERNAME_UPN): -- if name != principal_string: -+ if split_any_principal(name) != principal: - raise errors.ACIError( - info=_("Principal '%s' in subject alt name does not " - "match requested principal") % name) --- -2.4.3 - diff --git a/SOURCES/0054-ipa-backup-backup-etc-tmpfiles.d-dirsrv-instance-.co.patch b/SOURCES/0054-ipa-backup-backup-etc-tmpfiles.d-dirsrv-instance-.co.patch new file mode 100644 index 0000000..f54e563 --- /dev/null +++ b/SOURCES/0054-ipa-backup-backup-etc-tmpfiles.d-dirsrv-instance-.co.patch @@ -0,0 +1,52 @@ +From 7422ad189f90d596fcda93da97ae1cd152df4df3 Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Fri, 5 Aug 2016 17:35:49 +0200 +Subject: [PATCH] ipa-backup: backup /etc/tmpfiles.d/dirsrv-.conf + +This file allows daemon tmpfiles.d to re-create the dirs in volatile +directories like /var/run or /var/lock. Without this file Dirsrv will +not start. + +https://fedorahosted.org/freeipa/ticket/6165 + +Reviewed-By: Petr Spacek +--- + ipaplatform/base/paths.py | 1 + + ipaserver/install/ipa_backup.py | 9 ++++++--- + 2 files changed, 7 insertions(+), 3 deletions(-) + +diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py +index 9c8eaf951df89d373796be3f354bd3c51a329902..5ffe689950792a40c179533c8baf2794c2388696 100644 +--- a/ipaplatform/base/paths.py ++++ b/ipaplatform/base/paths.py +@@ -132,6 +132,7 @@ class BasePathNamespace(object): + SYSTEMD_IPA_SERVICE = "/etc/systemd/system/multi-user.target.wants/ipa.service" + SYSTEMD_SSSD_SERVICE = "/etc/systemd/system/multi-user.target.wants/sssd.service" + SYSTEMD_PKI_TOMCAT_SERVICE = "/etc/systemd/system/pki-tomcatd.target.wants/pki-tomcatd@pki-tomcat.service" ++ ETC_TMPFILESD_DIRSRV = "/etc/tmpfiles.d/dirsrv-%s.conf" + DNSSEC_TRUSTED_KEY = "/etc/trusted-key.key" + HOME_DIR = "/home" + PROC_FIPS_ENABLED = "/proc/sys/crypto/fips_enabled" +diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py +index 18a60ecd13c7e7f5381b61ec70ea308a1931b7ec..9b09f4293028c3e560337ba082164b528cf76d80 100644 +--- a/ipaserver/install/ipa_backup.py ++++ b/ipaserver/install/ipa_backup.py +@@ -337,9 +337,12 @@ class Backup(admintool.AdminTool): + if os.path.exists(dir): + self.dirs.append(dir) + +- file = paths.SYSCONFIG_DIRSRV_INSTANCE % serverid +- if os.path.exists(file): +- self.files.append(file) ++ for file in ( ++ paths.SYSCONFIG_DIRSRV_INSTANCE % serverid, ++ paths.ETC_TMPFILESD_DIRSRV % serverid, ++ ): ++ if os.path.exists(file): ++ self.files.append(file) + + self.logs.append(paths.VAR_LOG_DIRSRV_INSTANCE_TEMPLATE % serverid) + +-- +2.7.4 + diff --git a/SOURCES/0055-adjust-search-so-that-it-works-for-non-admin-users.patch b/SOURCES/0055-adjust-search-so-that-it-works-for-non-admin-users.patch deleted file mode 100644 index 26d1181..0000000 --- a/SOURCES/0055-adjust-search-so-that-it-works-for-non-admin-users.patch +++ /dev/null @@ -1,95 +0,0 @@ -From 6c1ae29831a5fdea5a81412042ea73cc5df9f397 Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Wed, 12 Aug 2015 10:35:38 +0200 -Subject: [PATCH] adjust search so that it works for non-admin users - -Non-admin user can now search for: -- hosts -- hostgroups -- netgroups -- servers -- services - -(Fixes ACI issue where search returns nothing when user does't have -read rights for an attribute in search_attributes. - -https://fedorahosted.org/freeipa/ticket/5167 - -Reviewed-By: Tomas Babej ---- - ipalib/plugins/host.py | 2 +- - ipalib/plugins/hostgroup.py | 1 + - ipalib/plugins/netgroup.py | 4 ++++ - ipalib/plugins/server.py | 1 + - ipalib/plugins/service.py | 3 +-- - 5 files changed, 8 insertions(+), 3 deletions(-) - -diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py -index 410b4bd120743a6ad5787fbd2a55534b4f108601..3e882aefd210df73b7ffd15b5a4c1d2fc4173536 100644 ---- a/ipalib/plugins/host.py -+++ b/ipalib/plugins/host.py -@@ -292,7 +292,7 @@ class host(LDAPObject): - # object_class_config = 'ipahostobjectclasses' - search_attributes = [ - 'fqdn', 'description', 'l', 'nshostlocation', 'krbprincipalname', -- 'nshardwareplatform', 'nsosversion', 'managedby', 'ipaallowedtoperform' -+ 'nshardwareplatform', 'nsosversion', 'managedby', - ] - default_attributes = [ - 'fqdn', 'description', 'l', 'nshostlocation', 'krbprincipalname', -diff --git a/ipalib/plugins/hostgroup.py b/ipalib/plugins/hostgroup.py -index fafe40ad9a8d1693505b7d90e5d8fd12202a894b..30d474d80905f02c4f88742a2677220c150b3c7f 100644 ---- a/ipalib/plugins/hostgroup.py -+++ b/ipalib/plugins/hostgroup.py -@@ -78,6 +78,7 @@ class hostgroup(LDAPObject): - object_name_plural = _('host groups') - object_class = ['ipaobject', 'ipahostgroup'] - permission_filter_objectclasses = ['ipahostgroup'] -+ search_attributes = ['cn', 'description', 'member', 'memberof'] - default_attributes = ['cn', 'description', 'member', 'memberof', - 'memberindirect', 'memberofindirect', - ] -diff --git a/ipalib/plugins/netgroup.py b/ipalib/plugins/netgroup.py -index d535b383e048fd12d08bde9247f158d183a5bcad..e69aaf94a035d0c4af28585f84b4b1f8105b3fc3 100644 ---- a/ipalib/plugins/netgroup.py -+++ b/ipalib/plugins/netgroup.py -@@ -86,6 +86,10 @@ class netgroup(LDAPObject): - object_name_plural = _('netgroups') - object_class = ['ipaobject', 'ipaassociation', 'ipanisnetgroup'] - permission_filter_objectclasses = ['ipanisnetgroup'] -+ search_attributes = [ -+ 'cn', 'description', 'memberof', 'externalhost', 'nisdomainname', -+ 'memberuser', 'memberhost', 'member', 'usercategory', 'hostcategory', -+ ] - default_attributes = [ - 'cn', 'description', 'memberof', 'externalhost', 'nisdomainname', - 'memberuser', 'memberhost', 'member', 'memberindirect', -diff --git a/ipalib/plugins/server.py b/ipalib/plugins/server.py -index 7fc44197343dbb651782fbf79993cbbe8818efed..5808c9c5ea78fce4a15cd2e49740fbe20bca8358 100644 ---- a/ipalib/plugins/server.py -+++ b/ipalib/plugins/server.py -@@ -38,6 +38,7 @@ class server(LDAPObject): - object_name = _('server') - object_name_plural = _('servers') - object_class = ['top'] -+ search_attributes = ['cn'] - default_attributes = [ - 'cn', 'iparepltopomanagedsuffix', 'ipamindomainlevel', - 'ipamaxdomainlevel' -diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py -index a5e10921beac8b232f6b74640ef17713f7297a3d..a21d004c8a70d50385c94b12447d5fd5bc0851b4 100644 ---- a/ipalib/plugins/service.py -+++ b/ipalib/plugins/service.py -@@ -391,8 +391,7 @@ class service(LDAPObject): - ] - possible_objectclasses = ['ipakrbprincipal', 'ipaallowedoperations'] - permission_filter_objectclasses = ['ipaservice'] -- search_attributes = ['krbprincipalname', 'managedby', 'ipakrbauthzdata', -- 'ipaallowedtoperform'] -+ search_attributes = ['krbprincipalname', 'managedby', 'ipakrbauthzdata'] - default_attributes = ['krbprincipalname', 'usercertificate', 'managedby', - 'ipakrbauthzdata', 'memberof', 'ipaallowedtoperform'] - uuid_attribute = 'ipauniqueid' --- -2.4.3 - diff --git a/SOURCES/0055-client-RPM-require-initscripts-to-get-domainname.ser.patch b/SOURCES/0055-client-RPM-require-initscripts-to-get-domainname.ser.patch new file mode 100644 index 0000000..a60ff94 --- /dev/null +++ b/SOURCES/0055-client-RPM-require-initscripts-to-get-domainname.ser.patch @@ -0,0 +1,28 @@ +From 99105177385dbed1082db8676a1ff052e99e1eda Mon Sep 17 00:00:00 2001 +From: Petr Spacek +Date: Mon, 8 Aug 2016 13:13:18 +0200 +Subject: [PATCH] client: RPM require initscripts to get *-domainname.service + +https://fedorahosted.org/freeipa/ticket/4831 + +Reviewed-By: Jan Cholasta +--- + freeipa.spec.in | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/freeipa.spec.in b/freeipa.spec.in +index 77fca24ef0e1e244e53d203a228931b4a444fb5a..29b63c9300b73d82aea88dbcf50f2f6ab5f9e9bd 100644 +--- a/freeipa.spec.in ++++ b/freeipa.spec.in +@@ -324,6 +324,8 @@ Requires: krb5-workstation + Requires: authconfig + Requires: pam_krb5 + Requires: curl ++# NIS domain name config: /usr/lib/systemd/system/*-domainname.service ++Requires: initscripts + Requires: libcurl >= 7.21.7-2 + Requires: xmlrpc-c >= 1.27.4 + Requires: sssd >= 1.14.0 +-- +2.7.4 + diff --git a/SOURCES/0056-parameters-move-the-confirm-kwarg-to-Param.patch b/SOURCES/0056-parameters-move-the-confirm-kwarg-to-Param.patch new file mode 100644 index 0000000..bc1a5cc --- /dev/null +++ b/SOURCES/0056-parameters-move-the-confirm-kwarg-to-Param.patch @@ -0,0 +1,89 @@ +From c7b4c108ddd76d5ac02e2242a7eccb3acf3efce5 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Mon, 8 Aug 2016 13:09:39 +0200 +Subject: [PATCH] parameters: move the `confirm` kwarg to Param + +Whether a parameter is treated like password is determined by the +`password` class attribute defined in the Param class. Whether the CLI will +asks for confirmation of a password parameter depends on the value of the +`confirm` kwarg of the Password class. + +Move the `confirm` kwarg from the Password class to the Param class, so +that it can be used by any Param subclass which has the `password` class +attribute set to True. + +This fixes confirmation of the --key option of otptoken-add, which is a +Bytes subclass with `password` set to True. + +https://fedorahosted.org/freeipa/ticket/6174 + +Reviewed-By: Martin Basti +Reviewed-By: David Kupka +--- + ipaclient/remote_plugins/schema.py | 2 +- + ipalib/parameters.py | 6 ++---- + ipaserver/plugins/otptoken.py | 4 ---- + 3 files changed, 3 insertions(+), 9 deletions(-) + +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index cd1d5d607978899254325f634ccec91d2c92f59b..0301e54127dc236ebc14e1409484626f1427800d 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -155,7 +155,7 @@ class _SchemaPlugin(object): + elif key in ('cli_metavar', + 'cli_name'): + kwargs[key] = str(value) +- elif key == 'confirm' and issubclass(cls, Password): ++ elif key == 'confirm': + kwargs[key] = value + elif key == 'default': + default = value +diff --git a/ipalib/parameters.py b/ipalib/parameters.py +index 1581b7dcac5259e5c4a127e2a38e13335002b204..6917c8d4fc117b47bddc11fbf3ea379e3c537ea4 100644 +--- a/ipalib/parameters.py ++++ b/ipalib/parameters.py +@@ -377,6 +377,7 @@ class Param(ReadOnly): + parameter is not `required` + - sortorder: used to sort a list of parameters for Command. See + `Command.finalize()` for further information ++ - confirm: if password, ask for confirmation + """ + + # This is a dummy type so that most of the functionality of Param can be +@@ -418,6 +419,7 @@ class Param(ReadOnly): + ('cli_metavar', str, None), + ('no_convert', bool, False), + ('deprecated', bool, False), ++ ('confirm', bool, True), + + # The 'default' kwarg gets appended in Param.__init__(): + # ('default', self.type, None), +@@ -1511,10 +1513,6 @@ class Password(Str): + + password = True + +- kwargs = Str.kwargs + ( +- ('confirm', bool, True), +- ) +- + def _convert_scalar(self, value, index=None): + if isinstance(value, (tuple, list)) and len(value) == 2: + (p1, p2) = value +diff --git a/ipaserver/plugins/otptoken.py b/ipaserver/plugins/otptoken.py +index 56b8c911b3492de9342946cd3e47681e99a5abef..39012e2f9106c33c520e19f14331fc440333015a 100644 +--- a/ipaserver/plugins/otptoken.py ++++ b/ipaserver/plugins/otptoken.py +@@ -79,10 +79,6 @@ class OTPTokenKey(Bytes): + + password = True + +- kwargs = Bytes.kwargs + ( +- ('confirm', bool, True), +- ) +- + def _convert_scalar(self, value, index=None): + if isinstance(value, (tuple, list)) and len(value) == 2: + (p1, p2) = value +-- +2.7.4 + diff --git a/SOURCES/0056-validate-mutually-exclusive-options-in-vault-add.patch b/SOURCES/0056-validate-mutually-exclusive-options-in-vault-add.patch deleted file mode 100644 index 11907c5..0000000 --- a/SOURCES/0056-validate-mutually-exclusive-options-in-vault-add.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 97f52ad53a6284b20e275e8ae28c599d96fc0b30 Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Wed, 12 Aug 2015 11:07:22 +0200 -Subject: [PATCH] validate mutually exclusive options in vault-add - -https://fedorahosted.org/freeipa/ticket/5195 - -Reviewed-By: Tomas Babej ---- - ipalib/plugins/vault.py | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index fe4eec325dde4a9ecd8a7ce5af1a124fc5c6a9ae..055e8d00f1616c15b217e7570eeedd46efba7c81 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -597,6 +597,18 @@ class vault_add(PKQuery, Local): - if 'public_key_file' in options: - del options['public_key_file'] - -+ if vault_type != u'symmetric' and (password or password_file): -+ raise errors.MutuallyExclusiveError( -+ reason=_('Password can be specified only for ' -+ 'symmetric vault') -+ ) -+ -+ if vault_type != u'asymmetric' and (public_key or public_key_file): -+ raise errors.MutuallyExclusiveError( -+ reason=_('Public key can be specified only for ' -+ 'asymmetric vault') -+ ) -+ - if self.api.env.in_server: - backend = self.api.Backend.ldap2 - else: --- -2.4.3 - diff --git a/SOURCES/0057-client-add-missing-output-params-to-client-side-comm.patch b/SOURCES/0057-client-add-missing-output-params-to-client-side-comm.patch new file mode 100644 index 0000000..c1bd136 --- /dev/null +++ b/SOURCES/0057-client-add-missing-output-params-to-client-side-comm.patch @@ -0,0 +1,95 @@ +From b654999d25de81e2c63b0765b6f16df2ff880144 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Wed, 10 Aug 2016 09:02:47 +0200 +Subject: [PATCH] client: add missing output params to client-side commands + +Add output params for the otptoken-add-yubikey, vault-add, vault-mod, +vault-archive and vault-retrieve commands. + +This fixes the commands not having any output in CLI. + +https://fedorahosted.org/freeipa/ticket/6182 + +Reviewed-By: Alexander Bokovoy +Reviewed-By: David Kupka +--- + ipaclient/plugins/otptoken_yubikey.py | 6 ++++++ + ipaclient/plugins/vault.py | 24 ++++++++++++++++++++++++ + 2 files changed, 30 insertions(+) + +diff --git a/ipaclient/plugins/otptoken_yubikey.py b/ipaclient/plugins/otptoken_yubikey.py +index 423b670de15dd7f803db1dcbb759bd0254827072..3c310eacbaeef654e43049db78437c8c29f52279 100644 +--- a/ipaclient/plugins/otptoken_yubikey.py ++++ b/ipaclient/plugins/otptoken_yubikey.py +@@ -103,6 +103,12 @@ class otptoken_add_yubikey(Command): + for option in super(otptoken_add_yubikey, self).get_options(): + yield option + ++ def get_output_params(self): ++ for param in self.api.Command.otptoken_add.output_params(): ++ yield param ++ for param in super(otptoken_add_yubikey, self).get_output_params(): ++ yield param ++ + def _iter_output(self): + return self.api.Command.otptoken_add.output() + +diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py +index 9026cbb0829a7557584df27a4262dfde640b4f28..3e116bbad54fea419b571d1f09c1b00280e94991 100644 +--- a/ipaclient/plugins/vault.py ++++ b/ipaclient/plugins/vault.py +@@ -220,6 +220,12 @@ class vault_add(Local): + for option in super(vault_add, self).get_options(): + yield option + ++ def get_output_params(self): ++ for param in self.api.Command.vault_add_internal.output_params(): ++ yield param ++ for param in super(vault_add, self).get_output_params(): ++ yield param ++ + def _iter_output(self): + return self.api.Command.vault_add_internal.output() + +@@ -418,6 +424,12 @@ class vault_mod(Local): + for option in super(vault_mod, self).get_options(): + yield option + ++ def get_output_params(self): ++ for param in self.api.Command.vault_mod_internal.output_params(): ++ yield param ++ for param in super(vault_mod, self).get_output_params(): ++ yield param ++ + def _iter_output(self): + return self.api.Command.vault_mod_internal.output() + +@@ -600,6 +612,12 @@ class vault_archive(Local): + for option in super(vault_archive, self).get_options(): + yield option + ++ def get_output_params(self): ++ for param in self.api.Command.vault_archive_internal.output_params(): ++ yield param ++ for param in super(vault_archive, self).get_output_params(): ++ yield param ++ + def _iter_output(self): + return self.api.Command.vault_archive_internal.output() + +@@ -846,6 +864,12 @@ class vault_retrieve(Local): + for option in super(vault_retrieve, self).get_options(): + yield option + ++ def get_output_params(self): ++ for param in self.api.Command.vault_retrieve_internal.output_params(): ++ yield param ++ for param in super(vault_retrieve, self).get_output_params(): ++ yield param ++ + def _iter_output(self): + return self.api.Command.vault_retrieve_internal.output() + +-- +2.7.4 + diff --git a/SOURCES/0057-idranges-raise-an-error-when-local-IPA-ID-range-is-b.patch b/SOURCES/0057-idranges-raise-an-error-when-local-IPA-ID-range-is-b.patch deleted file mode 100644 index 1387dc3..0000000 --- a/SOURCES/0057-idranges-raise-an-error-when-local-IPA-ID-range-is-b.patch +++ /dev/null @@ -1,110 +0,0 @@ -From 887bd5f84d862dfb923c72a60b4491374be34d5f Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Fri, 7 Aug 2015 15:44:57 +0200 -Subject: [PATCH] idranges: raise an error when local IPA ID range is being - modified - -also show the message about the way UID/GID ranges are managed in FreeIPA in -the idrange-mod's help message - -https://fedorahosted.org/freeipa/ticket/4826 - -Reviewed-By: Tomas Babej ---- - ipalib/plugins/idrange.py | 52 ++++++++++++++++++++++++++--------------------- - 1 file changed, 29 insertions(+), 23 deletions(-) - -diff --git a/ipalib/plugins/idrange.py b/ipalib/plugins/idrange.py -index fb198d79d4c14ffd5f7dc633c9f01a1465ff01d7..2cec05bd8f837fb27803b869bf33fe389126506c 100644 ---- a/ipalib/plugins/idrange.py -+++ b/ipalib/plugins/idrange.py -@@ -31,6 +31,20 @@ if api.env.in_server and api.env.context in ['lite', 'server']: - except ImportError: - _dcerpc_bindings_installed = False - -+ID_RANGE_VS_DNA_WARNING = """======= -+WARNING: -+ -+DNA plugin in 389-ds will allocate IDs based on the ranges configured for the -+local domain. Currently the DNA plugin *cannot* be reconfigured itself based -+on the local ranges set via this family of commands. -+ -+Manual configuration change has to be done in the DNA plugin configuration for -+the new local range. Specifically, The dnaNextRange attribute of 'cn=Posix -+IDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config' has to be -+modified to match the new range. -+======= -+""" -+ - __doc__ = _(""" - ID ranges - -@@ -139,17 +153,8 @@ this domain has the SID S-1-5-21-123-456-789-1010 then 1010 id the RID of the - user. RIDs are unique in a domain, 32bit values and are used for users and - groups. - --WARNING: -- --DNA plugin in 389-ds will allocate IDs based on the ranges configured for the --local domain. Currently the DNA plugin *cannot* be reconfigured itself based --on the local ranges set via this family of commands. -- --Manual configuration change has to be done in the DNA plugin configuration for --the new local range. Specifically, The dnaNextRange attribute of 'cn=Posix --IDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config' has to be --modified to match the new range. --""") -+{0} -+""".format(ID_RANGE_VS_DNA_WARNING)) - - register = Registry() - -@@ -386,17 +391,8 @@ class idrange_add(LDAPCreate): - - must be given to add a new range for a trusted AD domain. - -- WARNING: -- -- DNA plugin in 389-ds will allocate IDs based on the ranges configured for the -- local domain. Currently the DNA plugin *cannot* be reconfigured itself based -- on the local ranges set via this family of commands. -- -- Manual configuration change has to be done in the DNA plugin configuration for -- the new local range. Specifically, The dnaNextRange attribute of 'cn=Posix -- IDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config' has to be -- modified to match the new range. -- """) -+{0} -+""".format(ID_RANGE_VS_DNA_WARNING)) - - msg_summary = _('Added ID range "%(value)s"') - -@@ -670,7 +666,10 @@ class idrange_show(LDAPRetrieve): - - @register() - class idrange_mod(LDAPUpdate): -- __doc__ = _('Modify ID range.') -+ __doc__ = _("""Modify ID range. -+ -+{0} -+""".format(ID_RANGE_VS_DNA_WARNING)) - - msg_summary = _('Modified ID range "%(value)s"') - -@@ -688,6 +687,13 @@ class idrange_mod(LDAPUpdate): - except errors.NotFound: - self.obj.handle_not_found(*keys) - -+ if old_attrs['iparangetype'][0] == 'ipa-local': -+ raise errors.ExecutionError( -+ message=_('This command can not be used to change ID ' -+ 'allocation for local IPA domain. Run ' -+ '`ipa help idrange` for more information') -+ ) -+ - is_set = lambda x: (x in entry_attrs) and (entry_attrs[x] is not None) - in_updated_attrs = lambda x:\ - (x in entry_attrs and entry_attrs[x] is not None) or\ --- -2.4.3 - diff --git a/SOURCES/0058-install-Fix-server-and-replica-install-options.patch b/SOURCES/0058-install-Fix-server-and-replica-install-options.patch deleted file mode 100644 index 8c915c0..0000000 --- a/SOURCES/0058-install-Fix-server-and-replica-install-options.patch +++ /dev/null @@ -1,211 +0,0 @@ -From 8fd313b624e3da699280f81da1f88ef7149e6123 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Wed, 12 Aug 2015 07:49:53 +0200 -Subject: [PATCH] install: Fix server and replica install options - -https://fedorahosted.org/freeipa/ticket/5184 - -Reviewed-By: Martin Babinsky ---- - ipaserver/install/server/install.py | 55 ++++++------------------------ - ipaserver/install/server/replicainstall.py | 36 ++++--------------- - 2 files changed, 17 insertions(+), 74 deletions(-) - -diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py -index b9bf3f34bdb7c32115e5c6a7038f11f901ab06b8..ff517513473a458a84f63c5c1308a8cc0b8699f8 100644 ---- a/ipaserver/install/server/install.py -+++ b/ipaserver/install/server/install.py -@@ -1137,18 +1137,6 @@ def uninstall(installer): - class ServerCA(common.Installable, core.Group, core.Composite): - description = "certificate system" - -- setup_ca = Knob( -- bool, False, -- initializable=False, -- description="configure a dogtag CA", -- ) -- -- setup_kra = Knob( -- bool, False, -- initializable=False, -- description="configure a dogtag KRA", -- ) -- - external_ca = Knob( - bool, False, - description=("Generate a CSR for the IPA CA certificate to be signed " -@@ -1163,7 +1151,7 @@ class ServerCA(common.Installable, core.Group, core.Composite): - external_cert_files = Knob( - (list, str), None, - description=("File containing the IPA CA certificate and the external " -- "CA certificate chain (can be specified multiple times)"), -+ "CA certificate chain"), - cli_name='external-cert-file', - cli_aliases=['external_cert_file', 'external_ca_file'], - cli_metavar='FILE', -@@ -1308,6 +1296,7 @@ class ServerDNS(common.Installable, core.Group, core.Composite): - description=("The reverse DNS zone to use. This option can be used " - "multiple times"), - cli_name='reverse-zone', -+ cli_metavar='REVERSE_ZONE', - ) - - no_reverse = Knob( -@@ -1320,31 +1309,6 @@ class ServerDNS(common.Installable, core.Group, core.Composite): - description="Disable DNSSEC validation", - ) - -- dnssec_master = Knob( -- bool, False, -- initializable=False, -- description="Setup server to be DNSSEC key master", -- ) -- -- disable_dnssec_master = Knob( -- bool, False, -- initializable=False, -- description="Disable the DNSSEC master on this server", -- ) -- -- kasp_db_file = Knob( -- str, None, -- initializable=False, -- description="Copy OpenDNSSEC metadata from the specified file (will " -- "not create a new kasp.db file)", -- ) -- -- force = Knob( -- bool, False, -- initializable=False, -- description="Force install", -- ) -- - zonemgr = Knob( - str, None, - description=("DNS zone manager e-mail address. Defaults to " -@@ -1416,7 +1380,6 @@ class Server(common.Installable, common.Interactive, core.Composite): - master_password = Knob( - str, None, - sensitive=True, -- deprecated=True, - description="kerberos master password (normally autogenerated)", - cli_short_name='P', - ) -@@ -1466,11 +1429,13 @@ class Server(common.Installable, common.Interactive, core.Composite): - description=("Master Server IP Address. This option can be used " - "multiple times"), - cli_name='ip-address', -+ cli_metavar='IP_ADDRESS', - ) - - no_ntp = Knob( - bool, False, - description="do not configure ntp", -+ cli_short_name='N', - ) - - idstart = Knob( -@@ -1615,8 +1580,8 @@ class Server(common.Installable, common.Interactive, core.Composite): - # Automatically disable pkinit w/ dogtag until that is supported - self.ca.no_pkinit = True - -- self.setup_ca = self.ca.setup_ca -- self.setup_kra = self.ca.setup_kra -+ self.setup_ca = False -+ self.setup_kra = False - self.external_ca = self.ca.external_ca - self.external_ca_type = self.ca.external_ca_type - self.external_cert_files = self.ca.external_cert_files -@@ -1639,10 +1604,10 @@ class Server(common.Installable, common.Interactive, core.Composite): - self.reverse_zones = self.dns.reverse_zones - self.no_reverse = self.dns.no_reverse - self.no_dnssec_validation = self.dns.no_dnssec_validation -- self.dnssec_master = self.dns.dnssec_master -- self.disable_dnssec_master = self.dns.disable_dnssec_master -- self.kasp_db_file = self.dns.kasp_db_file -- self.force = self.dns.force -+ self.dnssec_master = False -+ self.disable_dnssec_master = False -+ self.kasp_db_file = None -+ self.force = False - self.zonemgr = self.dns.zonemgr - self.no_host_dns = self.dns.no_host_dns - self.no_dns_sshfp = self.dns.no_dns_sshfp -diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py -index 1ad291a1eada080361031a5723a0ea61679fc72e..dd8bc0d4bb7d8d9835a3e3e4dc24d1f67199d28f 100644 ---- a/ipaserver/install/server/replicainstall.py -+++ b/ipaserver/install/server/replicainstall.py -@@ -679,6 +679,7 @@ class ReplicaDNS(common.Installable, core.Group, core.Composite): - description=("The reverse DNS zone to use. This option can be used " - "multiple times"), - cli_name='reverse-zone', -+ cli_metavar='REVERSE_ZONE', - ) - - no_reverse = Knob( -@@ -691,31 +692,6 @@ class ReplicaDNS(common.Installable, core.Group, core.Composite): - description="Disable DNSSEC validation", - ) - -- dnssec_master = Knob( -- bool, False, -- initializable=False, -- description="Setup server to be DNSSEC key master", -- ) -- -- disable_dnssec_master = Knob( -- bool, False, -- initializable=False, -- description="Disable the DNSSEC master on this server", -- ) -- -- force = Knob( -- bool, False, -- initializable=False, -- description="Force install", -- ) -- -- kasp_db_file = Knob( -- str, None, -- initializable=False, -- description="Copy OpenDNSSEC metadata from the specified file (will " -- "not create a new kasp.db file)", -- ) -- - no_host_dns = Knob( - bool, False, - description="Do not use DNS for hostname lookup during installation", -@@ -750,6 +726,7 @@ class Replica(common.Installable, common.Interactive, core.Composite): - description=("Replica server IP Address. This option can be used " - "multiple times"), - cli_name='ip-address', -+ cli_metavar='IP_ADDRESS', - ) - - password = Knob( -@@ -774,6 +751,7 @@ class Replica(common.Installable, common.Interactive, core.Composite): - no_ntp = Knob( - bool, False, - description="do not configure ntp", -+ cli_short_name='N', - ) - - no_ui_redirect = Knob( -@@ -864,10 +842,10 @@ class Replica(common.Installable, common.Interactive, core.Composite): - self.reverse_zones = self.dns.reverse_zones - self.no_reverse = self.dns.no_reverse - self.no_dnssec_validation = self.dns.no_dnssec_validation -- self.dnssec_master = self.dns.dnssec_master -- self.disable_dnssec_master = self.dns.disable_dnssec_master -- self.kasp_db_file = self.dns.kasp_db_file -- self.force = self.dns.force -+ self.dnssec_master = False -+ self.disable_dnssec_master = False -+ self.kasp_db_file = None -+ self.force = False - self.zonemgr = None - self.no_host_dns = self.dns.no_host_dns - self.no_dns_sshfp = self.dns.no_dns_sshfp --- -2.4.3 - diff --git a/SOURCES/0058-server-install-Fix-hostname-option-to-always-overrid.patch b/SOURCES/0058-server-install-Fix-hostname-option-to-always-overrid.patch new file mode 100644 index 0000000..4267f9f --- /dev/null +++ b/SOURCES/0058-server-install-Fix-hostname-option-to-always-overrid.patch @@ -0,0 +1,52 @@ +From 09b5f9fc0e75886917aae014c2bb0c5bd67d3c4c Mon Sep 17 00:00:00 2001 +From: Petr Spacek +Date: Tue, 12 Jul 2016 17:42:40 +0200 +Subject: [PATCH] server-install: Fix --hostname option to always override + api.env values + +Attempts to compare local hostname with user-provided values are error +prone as we found out in #5794. This patch removes comparison and makes +the env values deterministic. + +https://fedorahosted.org/freeipa/ticket/6071 + +Reviewed-By: Jan Cholasta +--- + ipaserver/install/server/install.py | 13 +++++-------- + 1 file changed, 5 insertions(+), 8 deletions(-) + +diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py +index 65f9318201e648b30a3c13626e807ac6f3a9416d..1e925595b93ff95a98b3e6c3d0c357b1766dc1dc 100644 +--- a/ipaserver/install/server/install.py ++++ b/ipaserver/install/server/install.py +@@ -560,7 +560,12 @@ def install_check(installer): + cfg = dict( + context='installer', + in_server=True, ++ # make sure host name specified by user is used instead of default ++ host=host_name, + ) ++ if setup_ca: ++ # we have an IPA-integrated CA ++ cfg['ca_host'] = host_name + + # Create the management framework config file and finalize api + target_fname = paths.IPA_DEFAULT_CONF +@@ -586,14 +591,6 @@ def install_check(installer): + # Must be readable for everyone + os.chmod(target_fname, 0o644) + +- system_hostname = get_fqdn() +- if host_name != system_hostname: +- root_logger.debug("Chosen hostname (%s) differs from system hostname " +- "(%s) - change it" % (host_name, system_hostname)) +- # update `api.env.ca_host` to correct hostname +- # https://fedorahosted.org/freeipa/ticket/4936 +- api.env.ca_host = host_name +- + api.bootstrap(**cfg) + api.finalize() + +-- +2.7.4 + diff --git a/SOURCES/0059-certprofile-add-profile-format-explanation.patch b/SOURCES/0059-certprofile-add-profile-format-explanation.patch deleted file mode 100644 index fac47d7..0000000 --- a/SOURCES/0059-certprofile-add-profile-format-explanation.patch +++ /dev/null @@ -1,49 +0,0 @@ -From 056d185b4b2bfd7de423da7ff7a80f764c043810 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Thu, 23 Jul 2015 23:07:10 -0400 -Subject: [PATCH] certprofile: add profile format explanation - -Part of: https://fedorahosted.org/freeipa/ticket/5089 - -Reviewed-By: Tomas Babej ---- - ipalib/plugins/certprofile.py | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/ipalib/plugins/certprofile.py b/ipalib/plugins/certprofile.py -index 658fbca3b4eb851eb5a22190c443044f6ceb8491..1dd4f403ee4461b83c053eb36019a8896506bb81 100644 ---- a/ipalib/plugins/certprofile.py -+++ b/ipalib/plugins/certprofile.py -@@ -47,9 +47,29 @@ EXAMPLES: - Show information about a profile: - ipa certprofile-show ShortLivedUserCert - -+ Save profile configuration to a file: -+ ipa certprofile-show caIPAserviceCert --out caIPAserviceCert.cfg -+ - Search for profiles that do not store certificates: - ipa certprofile-find --store=false - -+PROFILE CONFIGURATION FORMAT: -+ -+The profile configuration format is the raw property-list format -+used by Dogtag Certificate System. The XML format is not supported. -+ -+The following restrictions apply to profiles managed by FreeIPA: -+ -+- When importing a profile the "profileId" field, if present, must -+ match the ID given on the command line. -+ -+- The "classId" field must be set to "caEnrollImpl" -+ -+- The "auth.instance_id" field must be set to "raCertAuth" -+ -+- The "certReqInputImpl" input class and "certOutputImpl" output -+ class must be used. -+ - """) - - --- -2.4.3 - diff --git a/SOURCES/0059-install-Call-hostnamectl-set-hostname-only-if-hostna.patch b/SOURCES/0059-install-Call-hostnamectl-set-hostname-only-if-hostna.patch new file mode 100644 index 0000000..2154c99 --- /dev/null +++ b/SOURCES/0059-install-Call-hostnamectl-set-hostname-only-if-hostna.patch @@ -0,0 +1,148 @@ +From fa252eac5db87020c7f4ecd3646a25bb7cafd27c Mon Sep 17 00:00:00 2001 +From: Petr Spacek +Date: Thu, 28 Jul 2016 16:13:55 +0200 +Subject: [PATCH] install: Call hostnamectl set-hostname only if --hostname + option is used + +This commit also splits hostname backup and configuration into two separate +functions. This allows us to backup hostname without setting it at the +same time. + +https://fedorahosted.org/freeipa/ticket/6071 + +Reviewed-By: Jan Cholasta +--- + client/ipa-client-install | 3 ++- + doc/guide/guide.org | 10 +++++----- + ipaplatform/base/tasks.py | 7 ++----- + ipaplatform/redhat/tasks.py | 13 ++----------- + ipaserver/install/server/install.py | 10 +++++----- + 5 files changed, 16 insertions(+), 27 deletions(-) + +diff --git a/client/ipa-client-install b/client/ipa-client-install +index 45185d44feb43a8b8d30e412a26dd63121be4ad1..db2037b8372644f997de498dcf3b99edcf3abb56 100755 +--- a/client/ipa-client-install ++++ b/client/ipa-client-install +@@ -2525,7 +2525,8 @@ def install(options, env, fstore, statestore): + if options.hostname and not options.on_master: + # skip this step when run by ipa-server-install as it always configures + # hostname +- tasks.backup_and_replace_hostname(fstore, statestore, options.hostname) ++ tasks.backup_hostname(fstore, statestore) ++ tasks.set_hostname(options.hostname) + + ntp_srv_servers = [] + if not options.on_master and options.conf_ntp: +diff --git a/doc/guide/guide.org b/doc/guide/guide.org +index 6d181559f0af90e7be7089aa94ab4900fa4e90b5..2e852a964991781ef5dd7b93ac481891897e1ed0 100644 +--- a/doc/guide/guide.org ++++ b/doc/guide/guide.org +@@ -1039,14 +1039,14 @@ def restore_context_default(filepath): + # version in platform services + restore_context = restore_context_default + +-# Default implementation of backup and replace hostname that does nothing +-def backup_and_replace_hostname_default(fstore, statestore, hostname): ++# Default implementation of backup hostname that does nothing ++def backup_hostname_default(fstore, statestore): + return + +-# Backup and replace system's hostname +-# Since many platforms have their own way how to store system's hostname, this method must be ++# Backup system's hostname ++# Since many platforms have their own way of handling system's hostname, this method must be + # implemented in platform services +-backup_and_replace_hostname = backup_and_replace_hostname_default ++backup_hostname = backup_hostname_default + + from ipapython.platform.SUPPORTED_PLATFORM import * + #+END_SRC +diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py +index c6860ce47ad3d043f1561a690c401537f5e2fdb7..1e687b6181fcff20303b50ac18bfde66280f8bfd 100644 +--- a/ipaplatform/base/tasks.py ++++ b/ipaplatform/base/tasks.py +@@ -45,14 +45,11 @@ class BaseTaskNamespace(object): + + raise NotImplementedError() + +- def backup_and_replace_hostname(self, fstore, statestore, hostname): ++ def backup_hostname(self, fstore, statestore): + """ + Backs up the current hostname in the statestore (so that it can be + restored by the restore_hostname platform task). + +- Makes sure that new hostname (passed via hostname argument) is set +- as a new pemanent hostname for this host. +- + No return value expected. + """ + +@@ -109,7 +106,7 @@ class BaseTaskNamespace(object): + def restore_hostname(self, fstore, statestore): + """ + Restores the original hostname as backed up in the +- backup_and_replace_hostname platform task. ++ backup_hostname platform task. + """ + + raise NotImplementedError() +diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py +index 8ac88511e94d640f077c7a0e202bc545ec8bcbbe..dbe005abb0ecbcb398368789fee52895c6d6e980 100644 +--- a/ipaplatform/redhat/tasks.py ++++ b/ipaplatform/redhat/tasks.py +@@ -332,22 +332,13 @@ class RedHatTaskNamespace(BaseTaskNamespace): + + return result + +- def backup_and_replace_hostname(self, fstore, statestore, hostname): +- old_hostname = socket.gethostname() +- try: +- self.set_hostname(hostname) +- except ipautil.CalledProcessError as e: +- root_logger.debug(traceback.format_exc()) +- root_logger.error( +- "Failed to set this machine hostname to %s (%s).", +- old_hostname, e +- ) +- ++ def backup_hostname(self, fstore, statestore): + filepath = paths.ETC_HOSTNAME + if os.path.exists(filepath): + fstore.backup_file(filepath) + + # store old hostname ++ old_hostname = socket.gethostname() + statestore.backup_state('network', 'hostname', old_hostname) + + def restore_hostname(self, fstore, statestore): +diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py +index 1e925595b93ff95a98b3e6c3d0c357b1766dc1dc..94698898934844350488d5fc52d6e1e567624502 100644 +--- a/ipaserver/install/server/install.py ++++ b/ipaserver/install/server/install.py +@@ -651,6 +651,7 @@ def install_check(installer): + options.dm_password = dm_password + options.master_password = master_password + options.admin_password = admin_password ++ options._host_name_overridden = bool(options.host_name) + options.host_name = host_name + options.ip_addresses = ip_addresses + +@@ -702,11 +703,10 @@ def install(installer): + print("Please wait until the prompt is returned.") + print("") + +- # configure /etc/sysconfig/network to contain the custom hostname +- tasks.backup_and_replace_hostname(fstore, sstore, host_name) +- +- # set hostname (we need both transient and static) +- tasks.set_hostname(host_name) ++ # set hostname (transient and static) if user instructed us to do so ++ if options._host_name_overridden: ++ tasks.backup_hostname(fstore, sstore) ++ tasks.set_hostname(host_name) + + if installer._update_hosts_file: + update_hosts_file(ip_addresses, host_name, fstore) +-- +2.7.4 + diff --git a/SOURCES/0060-ULC-Prevent-preserved-users-from-being-assigned-memb.patch b/SOURCES/0060-ULC-Prevent-preserved-users-from-being-assigned-memb.patch deleted file mode 100644 index d8dbffa..0000000 --- a/SOURCES/0060-ULC-Prevent-preserved-users-from-being-assigned-memb.patch +++ /dev/null @@ -1,155 +0,0 @@ -From 6087dd789833738e99040d031473c76ed9d8723c Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Wed, 12 Aug 2015 11:03:40 +0200 -Subject: [PATCH] ULC: Prevent preserved users from being assigned membership - -https://fedorahosted.org/freeipa/ticket/5170 - -Reviewed-By: David Kupka ---- - ipalib/plugins/user.py | 31 ++++++++++++++++++------------- - 1 file changed, 18 insertions(+), 13 deletions(-) - -diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py -index 859939205f903fa4832524c8d2601141f3674bb5..4ea770ede7525149780f1486b5e4eb44699c8533 100644 ---- a/ipalib/plugins/user.py -+++ b/ipalib/plugins/user.py -@@ -342,7 +342,7 @@ class user(baseuser): - ), - ) - -- def get_dn(self, *keys, **options): -+ def get_either_dn(self, *keys, **options): - ''' - Returns the DN of a user - The user can be active (active container) or delete (delete container) -@@ -351,7 +351,7 @@ class user(baseuser): - ldap = self.backend - # Check that this value is a Active user - try: -- active_dn = super(user, self).get_dn(*keys, **options) -+ active_dn = self.get_dn(*keys, **options) - ldap.get_entry(active_dn, ['dn']) - - # The Active user exists -@@ -402,7 +402,7 @@ class user_add(baseuser_add): - ) - - def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): -- assert isinstance(dn, DN) -+ dn = self.obj.get_either_dn(*keys, **options) - if not options.get('noprivate', False): - try: - # The Managed Entries plugin will allow a user to be created -@@ -599,7 +599,7 @@ class user_del(baseuser_del): - return super(user_del, self).forward(*keys, **options) - - def pre_callback(self, ldap, dn, *keys, **options): -- assert isinstance(dn, DN) -+ dn = self.obj.get_either_dn(*keys, **options) - - # For User life Cycle: user-del is a common plugin - # command to delete active user (active container) and -@@ -625,7 +625,7 @@ class user_del(baseuser_del): - - def execute(self, *keys, **options): - -- dn = self.obj.get_dn(*keys, **options) -+ dn = self.obj.get_either_dn(*keys, **options) - - # We are going to permanent delete or the user is already in the delete container. - delete_container = DN(self.obj.delete_container_dn, self.api.env.basedn) -@@ -644,7 +644,7 @@ class user_del(baseuser_del): - ldap = self.obj.backend - - # need to handle multiple keys (e.g. keys[-1]=(u'tb8', u'tb9').. -- active_dn = self.obj.get_dn(*keys, **options) -+ active_dn = self.obj.get_either_dn(*keys, **options) - superior_dn = DN(self.obj.delete_container_dn, api.env.basedn) - delete_dn = DN(active_dn[0], self.obj.delete_container_dn, api.env.basedn) - self.log.debug("preserve move %s -> %s" % (active_dn, delete_dn)) -@@ -701,6 +701,7 @@ class user_mod(baseuser_mod): - has_output_params = baseuser_mod.has_output_params + user_output_params - - def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): -+ dn = self.obj.get_either_dn(*keys, **options) - self.pre_common_callback(ldap, dn, entry_attrs, **options) - validate_nsaccountlock(entry_attrs) - return dn -@@ -777,6 +778,10 @@ class user_show(baseuser_show): - ), - ) - -+ def pre_callback(self, ldap, dn, attrs_list, *keys, **options): -+ dn = self.obj.get_either_dn(*keys, **options) -+ return dn -+ - def post_callback(self, ldap, dn, entry_attrs, *keys, **options): - convert_nsaccountlock(entry_attrs) - self.post_common_callback(ldap, dn, entry_attrs, **options) -@@ -813,7 +818,7 @@ class user_undel(LDAPQuery): - ldap = self.obj.backend - - # First check that the user exists and is a delete one -- delete_dn = self.obj.get_dn(*keys, **options) -+ delete_dn = self.obj.get_either_dn(*keys, **options) - if delete_dn.endswith(DN(self.obj.active_container_dn, api.env.basedn)): - raise errors.ValidationError( - name=self.obj.primary_key.cli_name, -@@ -860,7 +865,7 @@ class user_disable(LDAPQuery): - - check_protected_member(keys[-1]) - -- dn = self.obj.get_dn(*keys, **options) -+ dn = self.obj.get_either_dn(*keys, **options) - ldap.deactivate_entry(dn) - - return dict( -@@ -880,7 +885,7 @@ class user_enable(LDAPQuery): - def execute(self, *keys, **options): - ldap = self.obj.backend - -- dn = self.obj.get_dn(*keys, **options) -+ dn = self.obj.get_either_dn(*keys, **options) - - ldap.activate_entry(dn) - -@@ -904,7 +909,7 @@ class user_unlock(LDAPQuery): - msg_summary = _('Unlocked account "%(value)s"') - - def execute(self, *keys, **options): -- dn = self.obj.get_dn(*keys, **options) -+ dn = self.obj.get_either_dn(*keys, **options) - entry = self.obj.backend.get_entry( - dn, ['krbLastAdminUnlock', 'krbLoginFailedCount']) - -@@ -948,7 +953,7 @@ class user_status(LDAPQuery): - - def execute(self, *keys, **options): - ldap = self.obj.backend -- dn = self.obj.get_dn(*keys, **options) -+ dn = self.obj.get_either_dn(*keys, **options) - attr_list = ['krbloginfailedcount', 'krblastsuccessfulauth', 'krblastfailedauth', 'nsaccountlock'] - - disabled = False -@@ -1037,7 +1042,7 @@ class user_add_cert(LDAPAddAttribute): - - def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, - **options): -- assert isinstance(dn, DN) -+ dn = self.obj.get_either_dn(*keys, **options) - - self.obj.convert_usercertificate_pre(entry_attrs) - -@@ -1059,7 +1064,7 @@ class user_remove_cert(LDAPRemoveAttribute): - - def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, - **options): -- assert isinstance(dn, DN) -+ dn = self.obj.get_either_dn(*keys, **options) - - self.obj.convert_usercertificate_pre(entry_attrs) - --- -2.4.3 - diff --git a/SOURCES/0060-schema-Speed-up-schema-cache.patch b/SOURCES/0060-schema-Speed-up-schema-cache.patch new file mode 100644 index 0000000..7c7d189 --- /dev/null +++ b/SOURCES/0060-schema-Speed-up-schema-cache.patch @@ -0,0 +1,415 @@ +From beff42632d1db674802c817afd49a3ac8bcd8fb6 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Wed, 27 Jul 2016 10:46:40 +0200 +Subject: [PATCH] schema: Speed up schema cache + +Check presence of schema in cache (and download it if necessary) on +__init__ instead of with each __getitem__ call. Prefill internal +dictionary with empty record for each command to be able to quickly +determine if requested command exist in schema or not. Rest of schema +data are read from cache on first attempt to retrive them. + +https://fedorahosted.org/freeipa/ticket/6048 +https://fedorahosted.org/freeipa/ticket/6069 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/schema.py | 301 ++++++++++++++++++++++--------------- + 1 file changed, 177 insertions(+), 124 deletions(-) + +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index 0301e54127dc236ebc14e1409484626f1427800d..d039fb41991c26a9c7b7f76f6959668efb677586 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -5,10 +5,8 @@ + import collections + import errno + import fcntl +-import glob + import json + import os +-import re + import sys + import time + import types +@@ -65,8 +63,6 @@ USER_CACHE_PATH = ( + '.cache' + ) + ) +-SCHEMA_DIR = os.path.join(USER_CACHE_PATH, 'ipa', 'schema') +-SERVERS_DIR = os.path.join(USER_CACHE_PATH, 'ipa', 'servers') + + logger = log_mgr.get_logger(__name__) + +@@ -274,15 +270,6 @@ class _SchemaObjectPlugin(_SchemaPlugin): + schema_key = 'classes' + + +-def _ensure_dir_created(d): +- try: +- os.makedirs(d) +- except OSError as e: +- if e.errno != errno.EEXIST: +- raise RuntimeError("Unable to create cache directory: {}" +- "".format(e)) +- +- + class _LockedZipFile(zipfile.ZipFile): + """ Add locking to zipfile.ZipFile + Shared lock is used with read mode, exclusive with write mode. +@@ -308,7 +295,10 @@ class _SchemaNameSpace(collections.Mapping): + self._schema = schema + + def __getitem__(self, key): +- return self._schema.read_namespace_member(self.name, key) ++ try: ++ return self._schema.read_namespace_member(self.name, key) ++ except KeyError: ++ raise KeyError(key) + + def __iter__(self): + for key in self._schema.iter_namespace(self.name): +@@ -322,6 +312,62 @@ class NotAvailable(Exception): + pass + + ++class ServerInfo(collections.MutableMapping): ++ _DIR = os.path.join(USER_CACHE_PATH, 'ipa', 'servers') ++ ++ def __init__(self, api): ++ hostname = DNSName(api.env.server).ToASCII() ++ self._path = os.path.join(self._DIR, hostname) ++ self._dict = {} ++ self._dirty = False ++ ++ self._read() ++ ++ def __enter__(self): ++ return self ++ ++ def __exit__(self, *_exc_info): ++ if self._dirty: ++ self._write() ++ ++ def _read(self): ++ try: ++ with open(self._path, 'r') as sc: ++ self._dict = json.load(sc) ++ except EnvironmentError as e: ++ if e.errno != errno.ENOENT: ++ logger.warning('Failed to read server info: {}'.format(e)) ++ ++ def _write(self): ++ try: ++ try: ++ os.makedirs(self._DIR) ++ except EnvironmentError as e: ++ if e.errno != errno.EEXIST: ++ raise ++ with open(self._path, 'w') as sc: ++ json.dump(self._dict, sc) ++ except EnvironmentError as e: ++ logger.warning('Failed to write server info: {}'.format(e)) ++ ++ def __getitem__(self, key): ++ return self._dict[key] ++ ++ def __setitem__(self, key, value): ++ self._dirty = key not in self._dict or self._dict[key] != value ++ self._dict[key] = value ++ ++ def __delitem__(self, key): ++ del self._dict[key] ++ self._dirty = True ++ ++ def __iter__(self): ++ return iter(self._dict) ++ ++ def __len__(self): ++ return len(self._dict) ++ ++ + class Schema(object): + """ + Store and provide schema for commands and topics +@@ -342,38 +388,76 @@ class Schema(object): + u'Ping the remote IPA server to ...' + + """ +- schema_path_template = os.path.join(SCHEMA_DIR, '{}') +- servers_path_template = os.path.join(SERVERS_DIR, '{}') +- ns_member_pattern_template = '^{}/(?P.+)$' +- ns_member_path_template = '{}/{}' + namespaces = {'classes', 'commands', 'topics'} + schema_info_path = 'schema' ++ _DIR = os.path.join(USER_CACHE_PATH, 'ipa', 'schema') + +- @classmethod +- def _list(cls): +- for f in glob.glob(cls.schema_path_template.format('*')): +- yield os.path.splitext(os.path.basename(f))[0] ++ def __init__(self, api, server_info, client): ++ self._dict = {} ++ self._namespaces = {} ++ self._help = None + +- @classmethod +- def _in_cache(cls, fingeprint): +- return os.path.exists(cls.schema_path_template.format(fingeprint)) ++ for ns in self.namespaces: ++ self._dict[ns] = {} ++ self._namespaces[ns] = _SchemaNameSpace(self, ns) + +- def __init__(self, api, client): +- self._api = api +- self._client = client +- self._dict = {} ++ is_known = False ++ if not api.env.force_schema_check: ++ try: ++ self._fingerprint = server_info['fingerprint'] ++ self._expiration = server_info['expiration'] ++ except KeyError: ++ pass ++ else: ++ is_known = True ++ ++ if is_known: ++ try: ++ self._read_schema() ++ except Exception: ++ pass ++ else: ++ return + +- def _open_server_info(self, hostname, mode): +- encoded_hostname = DNSName(hostname).ToASCII() +- path = self.servers_path_template.format(encoded_hostname) +- return open(path, mode) ++ try: ++ self._fetch(client) ++ except NotAvailable: ++ raise ++ else: ++ self._write_schema() ++ finally: ++ try: ++ server_info['fingerprint'] = self._fingerprint ++ server_info['expiration'] = self._expiration ++ except AttributeError: ++ pass + +- def _get_schema(self): +- client = self._client ++ def _open_schema(self, filename, mode): ++ path = os.path.join(self._DIR, filename) ++ return _LockedZipFile(path, mode) ++ ++ def _get_schema_fingerprint(self, schema): ++ schema_info = json.loads(schema.read(self.schema_info_path)) ++ return schema_info['fingerprint'] ++ ++ def _fetch(self, client): + if not client.isconnected(): + client.connect(verbose=False) + +- fps = [unicode(f) for f in Schema._list()] ++ fps = [] ++ try: ++ files = os.listdir(self._DIR) ++ except EnvironmentError: ++ pass ++ else: ++ for filename in files: ++ try: ++ with self._open_schema(filename, 'r') as schema: ++ fps.append( ++ unicode(self._get_schema_fingerprint(schema))) ++ except Exception: ++ continue ++ + kwargs = {u'version': u'2.170'} + if fps: + kwargs[u'known_fingerprints'] = fps +@@ -386,110 +470,80 @@ class Schema(object): + ttl = e.ttl + else: + fp = schema['fingerprint'] +- ttl = schema['ttl'] +- self._store(fp, schema) +- finally: +- client.disconnect() ++ ttl = schema.pop('ttl', 0) + +- exp = ttl + time.time() +- return (fp, exp) ++ for key, value in schema.items(): ++ if key in self.namespaces: ++ value = {m['full_name']: m for m in value} ++ self._dict[key] = value + +- def _ensure_cached(self): +- no_info = False +- try: +- # pylint: disable=access-member-before-definition +- fp = self._server_schema_fingerprint +- exp = self._server_schema_expiration +- except AttributeError: +- try: +- with self._open_server_info(self._api.env.server, 'r') as sc: +- si = json.load(sc) +- +- fp = si['fingerprint'] +- exp = si['expiration'] +- except Exception as e: +- no_info = True +- if not (isinstance(e, EnvironmentError) and +- e.errno == errno.ENOENT): # pylint: disable=no-member +- logger.warning('Failed to load server properties: {}' +- ''.format(e)) +- +- force_check = ((not getattr(self, '_schema_checked', False)) and +- self._api.env.force_schema_check) +- +- if (force_check or +- no_info or exp < time.time() or not Schema._in_cache(fp)): +- (fp, exp) = self._get_schema() +- self._schema_checked = True +- _ensure_dir_created(SERVERS_DIR) +- try: +- with self._open_server_info(self._api.env.server, 'w') as sc: +- json.dump(dict(fingerprint=fp, expiration=exp), sc) +- except Exception as e: +- logger.warning('Failed to store server properties: {}' +- ''.format(e)) +- +- if not self._dict: +- self._dict['fingerprint'] = fp +- schema_info = self._read(self.schema_info_path) ++ self._fingerprint = fp ++ self._expiration = ttl + time.time() ++ ++ def _read_schema(self): ++ with self._open_schema(self._fingerprint, 'r') as schema: ++ self._dict['fingerprint'] = self._get_schema_fingerprint(schema) ++ schema_info = json.loads(schema.read(self.schema_info_path)) + self._dict['version'] = schema_info['version'] +- for ns in self.namespaces: +- self._dict[ns] = _SchemaNameSpace(self, ns) + +- self._server_schema_fingerprintr = fp +- self._server_schema_expiration = exp ++ for name in schema.namelist(): ++ ns, _slash, key = name.partition('/') ++ if ns in self.namespaces: ++ self._dict[ns][key] = {} + + def __getitem__(self, key): +- self._ensure_cached() +- return self._dict[key] ++ try: ++ return self._namespaces[key] ++ except KeyError: ++ return self._dict[key] + +- def _open_archive(self, mode, fp=None): +- if not fp: +- fp = self['fingerprint'] +- arch_path = self.schema_path_template.format(fp) +- return _LockedZipFile(arch_path, mode) +- +- def _store(self, fingerprint, schema={}): +- _ensure_dir_created(SCHEMA_DIR) +- +- schema_info = dict(version=schema['version'], +- fingerprint=schema['fingerprint']) +- +- with self._open_archive('w', fingerprint) as zf: +- # store schema information +- zf.writestr(self.schema_info_path, json.dumps(schema_info)) +- # store namespaces +- for namespace in self.namespaces: +- for member in schema[namespace]: +- path = self.ns_member_path_template.format( +- namespace, +- member['full_name'] +- ) +- zf.writestr(path, json.dumps(member)) ++ def _write_schema(self): ++ try: ++ os.makedirs(self._DIR) ++ except EnvironmentError as e: ++ if e.errno != errno.EEXIST: ++ logger.warning("Failed ti write schema: {}".format(e)) ++ return ++ ++ with self._open_schema(self._fingerprint, 'w') as schema: ++ schema_info = {} ++ for key, value in self._dict.items(): ++ if key in self.namespaces: ++ ns = value ++ for member in ns: ++ path = '{}/{}'.format(key, member) ++ schema.writestr(path, json.dumps(ns[member])) ++ else: ++ schema_info[key] = value ++ ++ schema.writestr(self.schema_info_path, json.dumps(schema_info)) + + def _read(self, path): +- with self._open_archive('r') as zf: ++ with self._open_schema(self._fingerprint, 'r') as zf: + return json.loads(zf.read(path)) + + def read_namespace_member(self, namespace, member): +- path = self.ns_member_path_template.format(namespace, member) +- return self._read(path) ++ value = self._dict[namespace][member] ++ ++ if (not value) or ('full_name' not in value): ++ path = '{}/{}'.format(namespace, member) ++ value = self._dict[namespace].setdefault( ++ member, {} ++ ).update(self._read(path)) ++ ++ return value + + def iter_namespace(self, namespace): +- pattern = self.ns_member_pattern_template.format(namespace) +- with self._open_archive('r') as zf: +- for name in zf.namelist(): +- r = re.match(pattern, name) +- if r: +- yield r.groups('name')[0] ++ return iter(self._dict[namespace]) + + + def get_package(api, client): + try: + schema = api._schema + except AttributeError: +- schema = Schema(api, client) +- object.__setattr__(api, '_schema', schema) ++ with ServerInfo(api.env.hostname) as server_info: ++ schema = Schema(api, server_info, client) ++ object.__setattr__(api, '_schema', schema) + + fingerprint = str(schema['fingerprint']) + package_name = '{}${}'.format(__name__, fingerprint) +@@ -509,10 +563,9 @@ def get_package(api, client): + module = types.ModuleType(module_name) + module.__file__ = os.path.join(package_dir, 'plugins.py') + module.register = plugable.Registry() +- for key, plugin_cls in (('commands', _SchemaCommandPlugin), +- ('classes', _SchemaObjectPlugin)): +- for full_name in schema[key]: +- plugin = plugin_cls(full_name) ++ for plugin_cls in (_SchemaCommandPlugin, _SchemaObjectPlugin): ++ for full_name in schema[plugin_cls.schema_key]: ++ plugin = plugin_cls(str(full_name)) + plugin = module.register()(plugin) + sys.modules[module_name] = module + +-- +2.7.4 + diff --git a/SOURCES/0061-Asymmetric-vault-validate-public-key-in-client.patch b/SOURCES/0061-Asymmetric-vault-validate-public-key-in-client.patch deleted file mode 100644 index 8a5948a..0000000 --- a/SOURCES/0061-Asymmetric-vault-validate-public-key-in-client.patch +++ /dev/null @@ -1,45 +0,0 @@ -From 9eae8d891a8b5d5320cb38b8e697681802cbf573 Mon Sep 17 00:00:00 2001 -From: Christian Heimes -Date: Thu, 23 Jul 2015 20:30:21 +0200 -Subject: [PATCH] Asymmetric vault: validate public key in client - -The ipa vault commands now load and validate the public key for -asymmetric encryption, before sending it to the server. This prevents -invalid vaults and prohibits accidental exposure of private key -material. - -https://fedorahosted.org/freeipa/ticket/5142 -https://fedorahosted.org/freeipa/ticket/5143 - -Reviewed-By: Petr Vobornik ---- - ipalib/plugins/vault.py | 13 +++++++++++++ - 1 file changed, 13 insertions(+) - -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index 055e8d00f1616c15b217e7570eeedd46efba7c81..ac608f5c7e2779da138c75a0f02bd5546f4aeffd 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -665,6 +665,19 @@ class vault_add(PKQuery, Local): - name='ipavaultpublickey', - error=_('Missing vault public key')) - -+ # validate public key and prevent users from accidentally -+ # sending a private key to the server. -+ try: -+ load_pem_public_key( -+ data=public_key, -+ backend=default_backend() -+ ) -+ except ValueError as e: -+ raise errors.ValidationError( -+ name='ipavaultpublickey', -+ error=_('Invalid or unsupported vault public key: %s') % e, -+ ) -+ - # create vault - response = self.api.Command.vault_add_internal(*args, **options) - --- -2.4.3 - diff --git a/SOURCES/0061-frontend-Change-doc-summary-topic-and-NO_CLI-to-clas.patch b/SOURCES/0061-frontend-Change-doc-summary-topic-and-NO_CLI-to-clas.patch new file mode 100644 index 0000000..f27bd62 --- /dev/null +++ b/SOURCES/0061-frontend-Change-doc-summary-topic-and-NO_CLI-to-clas.patch @@ -0,0 +1,378 @@ +From 8293d36c504b59a6dac46187baf51719ab355fd2 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Wed, 20 Jul 2016 13:23:33 +0200 +Subject: [PATCH] frontend: Change doc, summary, topic and NO_CLI to class + properties + +Avoid need to instantiate all commands just to get information for +displaying help. + +https://fedorahosted.org/freeipa/ticket/6048 + +Reviewed-By: Jan Cholasta +--- + ipaclient/frontend.py | 32 ++++++++++++++------- + ipaclient/plugins/automount.py | 9 ++++-- + ipaclient/plugins/otptoken_yubikey.py | 11 +++++--- + ipaclient/plugins/vault.py | 35 ++++++++++++++--------- + ipaclient/remote_plugins/schema.py | 53 +++++++++++++++++++++++++++++++---- + ipalib/frontend.py | 10 ++++--- + ipalib/plugable.py | 17 ++++++----- + 7 files changed, 120 insertions(+), 47 deletions(-) + +diff --git a/ipaclient/frontend.py b/ipaclient/frontend.py +index 1525c88b3dfeadccd8115cb4b6ba149caef22103..aeaed550771d3c6af04a9b34fcae414faacb47d7 100644 +--- a/ipaclient/frontend.py ++++ b/ipaclient/frontend.py +@@ -2,9 +2,11 @@ + # Copyright (C) 2016 FreeIPA Contributors see COPYING for license + # + ++from ipalib import api + from ipalib.frontend import Command, Method + from ipalib.parameters import Str + from ipalib.text import _ ++from ipalib.util import classproperty + + + class ClientCommand(Command): +@@ -111,20 +113,30 @@ class CommandOverride(Command): + def __init__(self, api): + super(CommandOverride, self).__init__(api) + +- next_class = api.get_plugin_next(type(self)) ++ next_class = self.__get_next() + self.next = next_class(api) + +- @property +- def doc(self): +- return self.next.doc ++ @classmethod ++ def __get_next(cls): ++ return api.get_plugin_next(cls) + +- @property +- def NO_CLI(self): +- return self.next.NO_CLI ++ @classmethod ++ def __doc_getter(cls): ++ return cls.__get_next().doc + +- @property +- def topic(self): +- return self.next.topic ++ doc = classproperty(__doc_getter) ++ ++ @classmethod ++ def __NO_CLI_getter(cls): ++ return cls.__get_next().NO_CLI ++ ++ NO_CLI = classproperty(__NO_CLI_getter) ++ ++ @classmethod ++ def __topic_getter(cls): ++ return cls.__get_next().topic ++ ++ topic = classproperty(__topic_getter) + + @property + def forwarded_name(self): +diff --git a/ipaclient/plugins/automount.py b/ipaclient/plugins/automount.py +index c6537bc6c24b905a8e1f7fb6a7e2c931b95374c7..925b635ff27411fc7e2f8c3dae17c747216d7fb6 100644 +--- a/ipaclient/plugins/automount.py ++++ b/ipaclient/plugins/automount.py +@@ -27,6 +27,7 @@ from ipalib import api, errors + from ipalib import Flag, Str + from ipalib.frontend import Command, Method, Object + from ipalib.plugable import Registry ++from ipalib.util import classproperty + from ipalib import _ + from ipapython.dn import DN + +@@ -52,11 +53,13 @@ class _fake_automountlocation_show(Method): + + @register(override=True, no_fail=True) + class automountlocation_tofiles(MethodOverride): +- @property +- def NO_CLI(self): +- return isinstance(self.api.Command.automountlocation_show, ++ @classmethod ++ def __NO_CLI_getter(cls): ++ return isinstance(api.Command.automountlocation_show, + _fake_automountlocation_show) + ++ NO_CLI = classproperty(__NO_CLI_getter) ++ + def output_for_cli(self, textui, result, *keys, **options): + maps = result['result']['maps'] + keys = result['result']['keys'] +diff --git a/ipaclient/plugins/otptoken_yubikey.py b/ipaclient/plugins/otptoken_yubikey.py +index 3c310eacbaeef654e43049db78437c8c29f52279..549376a0ff65d44c5698666a84608849152368b2 100644 +--- a/ipaclient/plugins/otptoken_yubikey.py ++++ b/ipaclient/plugins/otptoken_yubikey.py +@@ -23,10 +23,11 @@ import six + import usb.core + import yubico + +-from ipalib import _, IntEnum ++from ipalib import _, api, IntEnum + from ipalib.errors import NotFound + from ipalib.frontend import Command, Method, Object + from ipalib.plugable import Registry ++from ipalib.util import classproperty + + if six.PY3: + unicode = str +@@ -74,11 +75,13 @@ class otptoken_add_yubikey(Command): + ) + has_output_params = takes_options + +- @property +- def NO_CLI(self): +- return isinstance(self.api.Command.otptoken_add, ++ @classmethod ++ def __NO_CLI_getter(cls): ++ return isinstance(api.Command.otptoken_add, + _fake_otptoken_add) + ++ NO_CLI = classproperty(__NO_CLI_getter) ++ + def get_args(self): + for arg in self.api.Command.otptoken_add.args(): + yield arg +diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py +index 3e116bbad54fea419b571d1f09c1b00280e94991..c0ded21d515fe41bde5fb0e547087cb7789aa6a3 100644 +--- a/ipaclient/plugins/vault.py ++++ b/ipaclient/plugins/vault.py +@@ -38,7 +38,8 @@ import nss.nss as nss + + from ipaclient.frontend import MethodOverride + from ipalib.frontend import Local, Method, Object +-from ipalib import errors ++from ipalib.util import classproperty ++from ipalib import api, errors + from ipalib import Bytes, Flag, Str + from ipalib.plugable import Registry + from ipalib import _ +@@ -202,11 +203,13 @@ class vault_add(Local): + ), + ) + +- @property +- def NO_CLI(self): +- return isinstance(self.api.Command.vault_add_internal, ++ @classmethod ++ def __NO_CLI_getter(cls): ++ return isinstance(api.Command.vault_add_internal, + _fake_vault_add_internal) + ++ NO_CLI = classproperty(__NO_CLI_getter) ++ + def get_args(self): + for arg in self.api.Command.vault_add_internal.args(): + yield arg +@@ -406,11 +409,13 @@ class vault_mod(Local): + ), + ) + +- @property +- def NO_CLI(self): +- return isinstance(self.api.Command.vault_mod_internal, ++ @classmethod ++ def __NO_CLI_getter(cls): ++ return isinstance(api.Command.vault_mod_internal, + _fake_vault_mod_internal) + ++ NO_CLI = classproperty(__NO_CLI_getter) ++ + def get_args(self): + for arg in self.api.Command.vault_mod_internal.args(): + yield arg +@@ -591,11 +596,13 @@ class vault_archive(Local): + ), + ) + +- @property +- def NO_CLI(self): +- return isinstance(self.api.Command.vault_archive_internal, ++ @classmethod ++ def __NO_CLI_getter(cls): ++ return isinstance(api.Command.vault_archive_internal, + _fake_vault_archive_internal) + ++ NO_CLI = classproperty(__NO_CLI_getter) ++ + def get_args(self): + for arg in self.api.Command.vault_archive_internal.args(): + yield arg +@@ -846,11 +853,13 @@ class vault_retrieve(Local): + ), + ) + +- @property +- def NO_CLI(self): +- return isinstance(self.api.Command.vault_retrieve_internal, ++ @classmethod ++ def __NO_CLI_getter(cls): ++ return isinstance(api.Command.vault_retrieve_internal, + _fake_vault_retrieve_internal) + ++ NO_CLI = classproperty(__NO_CLI_getter) ++ + def get_args(self): + for arg in self.api.Command.vault_retrieve_internal.args(): + yield arg +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index d039fb41991c26a9c7b7f76f6959668efb677586..f165736cde6f08d6d22c17070d570da261799e4b 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -89,10 +89,32 @@ class _SchemaPlugin(object): + bases = None + schema_key = None + +- def __init__(self, full_name): ++ def __init__(self, schema, full_name): + self.name, _slash, self.version = full_name.partition('/') + self.full_name = full_name +- self.__class = None ++ self._schema = schema ++ self._class = None ++ ++ @property ++ def doc(self): ++ if self._class is not None: ++ return self._class.doc ++ else: ++ schema = self._schema[self.schema_key][self.full_name] ++ try: ++ return schema['doc'] ++ except KeyError: ++ return None ++ ++ @property ++ def summary(self): ++ if self._class is not None: ++ return self._class.summary ++ else: ++ if self.doc is not None: ++ return self.doc.split('\n\n', 1)[0].strip() ++ else: ++ return u'<%s>' % self.full_name + + def _create_default_from(self, api, name, keys): + cmd_name = self.full_name +@@ -200,18 +222,37 @@ class _SchemaPlugin(object): + return self.name, self.bases, class_dict + + def __call__(self, api): +- if self.__class is None: ++ if self._class is None: + schema = api._schema[self.schema_key][self.full_name] + name, bases, class_dict = self._create_class(api, schema) +- self.__class = type(name, bases, class_dict) ++ self._class = type(name, bases, class_dict) + +- return self.__class(api) ++ return self._class(api) + + + class _SchemaCommandPlugin(_SchemaPlugin): + bases = (_SchemaCommand,) + schema_key = 'commands' + ++ @property ++ def topic(self): ++ if self._class is not None: ++ return self._class.topic ++ else: ++ schema = self._schema[self.schema_key][self.full_name] ++ try: ++ return str(schema['topic_topic']).partition('/')[0] ++ except KeyError: ++ return None ++ ++ @property ++ def NO_CLI(self): ++ if self._class is not None: ++ return self._class.NO_CLI ++ else: ++ schema = self._schema[self.schema_key][self.full_name] ++ return 'cli' in schema.get('exclude', []) ++ + def _create_output(self, api, schema): + if schema.get('multivalue', False): + type_type = (tuple, list) +@@ -565,7 +606,7 @@ def get_package(api, client): + module.register = plugable.Registry() + for plugin_cls in (_SchemaCommandPlugin, _SchemaObjectPlugin): + for full_name in schema[plugin_cls.schema_key]: +- plugin = plugin_cls(str(full_name)) ++ plugin = plugin_cls(schema, str(full_name)) + plugin = module.register()(plugin) + sys.modules[module_name] = module + +diff --git a/ipalib/frontend.py b/ipalib/frontend.py +index cb00841f21bd5a3e3b4095dcd17a8816ca24400f..455b222d4d7fcbb65b43c4d8e1ffbbaf3e131d22 100644 +--- a/ipalib/frontend.py ++++ b/ipalib/frontend.py +@@ -38,7 +38,7 @@ from ipalib.errors import (ZeroArgumentError, MaxArgumentError, OverlapError, + ValidationError, ConversionError) + from ipalib import errors, messages + from ipalib.request import context, context_frame +-from ipalib.util import json_serialize ++from ipalib.util import classproperty, json_serialize + + if six.PY3: + unicode = str +@@ -426,9 +426,11 @@ class Command(HasParam): + + api_version = API_VERSION + +- @property +- def topic(self): +- return type(self).__module__.rpartition('.')[2] ++ @classmethod ++ def __topic_getter(cls): ++ return cls.__module__.rpartition('.')[2] ++ ++ topic = classproperty(__topic_getter) + + @property + def forwarded_name(self): +diff --git a/ipalib/plugable.py b/ipalib/plugable.py +index 26fbeaa26d7986f2e184f0974ef396bd323d6bf5..073ad05d7aee5e83cae5c6e20bac8f9439505198 100644 +--- a/ipalib/plugable.py ++++ b/ipalib/plugable.py +@@ -155,19 +155,22 @@ class Plugin(ReadOnly): + + bases = classproperty(__bases_getter) + +- @property +- def doc(self): +- return type(self).__doc__ ++ @classmethod ++ def __doc_getter(cls): ++ return cls.__doc__ + +- @property +- def summary(self): +- doc = self.doc ++ doc = classproperty(__doc_getter) ++ ++ @classmethod ++ def __summary_getter(cls): ++ doc = cls.doc + if not _(doc).msg: +- cls = type(self) + return u'<%s.%s>' % (cls.__module__, cls.__name__) + else: + return unicode(doc).split('\n\n', 1)[0].strip() + ++ summary = classproperty(__summary_getter) ++ + @property + def api(self): + """ +-- +2.7.4 + diff --git a/SOURCES/0062-add-permission-System-Manage-User-Certificates.patch b/SOURCES/0062-add-permission-System-Manage-User-Certificates.patch deleted file mode 100644 index 8d0495e..0000000 --- a/SOURCES/0062-add-permission-System-Manage-User-Certificates.patch +++ /dev/null @@ -1,64 +0,0 @@ -From 159fe81f0f45f83f90037ba3315a3558d0ab94cf Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Wed, 12 Aug 2015 14:48:09 +0200 -Subject: [PATCH] add permission: System: Manage User Certificates - -usercertificate attr was moved from "System Modify Users" to this -new permission. - -https://fedorahosted.org/freeipa/ticket/5177 - -Reviewed-By: Fraser Tweedale ---- - ACI.txt | 4 +++- - ipalib/plugins/user.py | 10 +++++++++- - 2 files changed, 12 insertions(+), 2 deletions(-) - -diff --git a/ACI.txt b/ACI.txt -index 60607b98deb74d0b7f45d24ee9359b0cf8162b0d..99099275e1383f16aca122e05e34b2330f4d06a3 100644 ---- a/ACI.txt -+++ b/ACI.txt -@@ -309,9 +309,11 @@ aci: (targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:S - dn: cn=users,cn=accounts,dc=ipa,dc=example - aci: (targetattr = "krbprincipalkey || passwordhistory || sambalmpassword || sambantpassword || userpassword")(targetfilter = "(&(!(memberOf=cn=admins,cn=groups,cn=accounts,dc=ipa,dc=example))(objectclass=posixaccount))")(version 3.0;acl "permission:System: Change User password";allow (write) groupdn = "ldap:///cn=System: Change User password,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: cn=users,cn=accounts,dc=ipa,dc=example -+aci: (targetattr = "usercertificate")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Manage User Certificates";allow (write) groupdn = "ldap:///cn=System: Manage User Certificates,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+dn: cn=users,cn=accounts,dc=ipa,dc=example - aci: (targetattr = "ipasshpubkey")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Manage User SSH Public Keys";allow (write) groupdn = "ldap:///cn=System: Manage User SSH Public Keys,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: cn=users,cn=accounts,dc=ipa,dc=example --aci: (targetattr = "businesscategory || carlicense || cn || description || displayname || employeetype || facsimiletelephonenumber || gecos || givenname || homephone || inetuserhttpurl || initials || l || labeleduri || loginshell || manager || mepmanagedentry || mobile || objectclass || ou || pager || postalcode || preferredlanguage || roomnumber || secretary || seealso || sn || st || street || telephonenumber || title || usercertificate || userclass")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Modify Users";allow (write) groupdn = "ldap:///cn=System: Modify Users,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+aci: (targetattr = "businesscategory || carlicense || cn || description || displayname || employeetype || facsimiletelephonenumber || gecos || givenname || homephone || inetuserhttpurl || initials || l || labeleduri || loginshell || manager || mepmanagedentry || mobile || objectclass || ou || pager || postalcode || preferredlanguage || roomnumber || secretary || seealso || sn || st || street || telephonenumber || title || userclass")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Modify Users";allow (write) groupdn = "ldap:///cn=System: Modify Users,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: cn=UPG Definition,cn=Definitions,cn=Managed Entries,cn=etc,dc=ipa,dc=example - aci: (targetattr = "*")(target = "ldap:///cn=UPG Definition,cn=Definitions,cn=Managed Entries,cn=etc,dc=ipa,dc=example")(version 3.0;acl "permission:System: Read UPG Definition";allow (compare,read,search) groupdn = "ldap:///cn=System: Read UPG Definition,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: cn=users,cn=accounts,dc=ipa,dc=example -diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py -index 4ea770ede7525149780f1486b5e4eb44699c8533..90ae7260abf935abf92b49da04c11bc76e836e49 100644 ---- a/ipalib/plugins/user.py -+++ b/ipalib/plugins/user.py -@@ -259,6 +259,14 @@ class user(baseuser): - ], - 'default_privileges': {'User Administrators'}, - }, -+ 'System: Manage User Certificates': { -+ 'ipapermright': {'write'}, -+ 'ipapermdefaultattr': {'usercertificate'}, -+ 'default_privileges': { -+ 'User Administrators', -+ 'Modify Users and Reset passwords', -+ }, -+ }, - 'System: Modify Users': { - 'ipapermright': {'write'}, - 'ipapermdefaultattr': { -@@ -269,7 +277,7 @@ class user(baseuser): - 'mepmanagedentry', 'mobile', 'objectclass', 'ou', 'pager', - 'postalcode', 'roomnumber', 'secretary', 'seealso', 'sn', 'st', - 'street', 'telephonenumber', 'title', 'userclass', -- 'preferredlanguage', 'usercertificate', -+ 'preferredlanguage', - }, - 'replaces': [ - '(targetattr = "givenname || sn || cn || displayname || title || initials || loginshell || gecos || homephone || mobile || pager || facsimiletelephonenumber || telephonenumber || street || roomnumber || l || st || postalcode || manager || secretary || description || carlicense || labeleduri || inetuserhttpurl || seealso || employeetype || businesscategory || ou || mepmanagedentry || objectclass")(target = "ldap:///uid=*,cn=users,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Modify Users";allow (write) groupdn = "ldap:///cn=Modify Users,cn=permissions,cn=pbac,$SUFFIX";)', --- -2.4.3 - diff --git a/SOURCES/0062-schema-Introduce-schema-cache-format.patch b/SOURCES/0062-schema-Introduce-schema-cache-format.patch new file mode 100644 index 0000000..1e6d14f --- /dev/null +++ b/SOURCES/0062-schema-Introduce-schema-cache-format.patch @@ -0,0 +1,48 @@ +From 1242b26266b5f1222924dc06479e19d0914a0703 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Wed, 27 Jul 2016 10:54:16 +0200 +Subject: [PATCH] schema: Introduce schema cache format + +Information about schema cache format is stored in every cache item. +When schema cache format changes in incompatible way format will be +increased. When format stored in cache doesn't match currently used +format the entry in cache is ignored. + +https://fedorahosted.org/freeipa/ticket/6048 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/schema.py | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index f165736cde6f08d6d22c17070d570da261799e4b..d7c018e3de1cc79ffc086e3576542ce993ebc87a 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -23,6 +23,8 @@ from ipapython.dn import DN + from ipapython.dnsutil import DNSName + from ipapython.ipa_log_manager import log_mgr + ++FORMAT = '0' ++ + if six.PY3: + unicode = str + +@@ -478,6 +480,14 @@ class Schema(object): + return _LockedZipFile(path, mode) + + def _get_schema_fingerprint(self, schema): ++ try: ++ fmt = json.loads(schema.read('format')) ++ except KeyError: ++ fmt = '0' ++ ++ if fmt != FORMAT: ++ raise RuntimeError('invalid format') ++ + schema_info = json.loads(schema.read(self.schema_info_path)) + return schema_info['fingerprint'] + +-- +2.7.4 + diff --git a/SOURCES/0063-Add-permission-for-bypassing-CA-ACL-enforcement.patch b/SOURCES/0063-Add-permission-for-bypassing-CA-ACL-enforcement.patch deleted file mode 100644 index 480d85b..0000000 --- a/SOURCES/0063-Add-permission-for-bypassing-CA-ACL-enforcement.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 61487ce8cbcad43a711931e92c3c2ef9b160cc02 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Tue, 4 Aug 2015 01:13:09 -0400 -Subject: [PATCH] Add permission for bypassing CA ACL enforcement - -Add the "Request Certificate ignoring CA ACLs" permission and -associated ACI, initially assigned to "Certificate Administrators" -privilege. - -Update cert-request command to skip CA ACL enforcement when the bind -principal has this permission. - -Fixes: https://fedorahosted.org/freeipa/ticket/5099 -Reviewed-By: Martin Babinsky ---- - install/updates/40-delegation.update | 15 +++++++++++++++ - ipalib/plugins/cert.py | 13 ++++++++++--- - 2 files changed, 25 insertions(+), 3 deletions(-) - -diff --git a/install/updates/40-delegation.update b/install/updates/40-delegation.update -index bc0736c5b6c07747586a56c2cbde9596c7522d1c..8d4f6296cbed7fcc968c2193022cb50b488c8561 100644 ---- a/install/updates/40-delegation.update -+++ b/install/updates/40-delegation.update -@@ -144,6 +144,21 @@ default:member: cn=Certificate Administrators,cn=privileges,cn=pbac,$SUFFIX - dn: $SUFFIX - add:aci:(targetattr = "objectclass")(target = "ldap:///cn=request certificate with subjectaltname,cn=virtual operations,cn=etc,$SUFFIX" )(version 3.0; acl "permission:Request Certificate with SubjectAltName"; allow (write) groupdn = "ldap:///cn=Request Certificate with SubjectAltName,cn=permissions,cn=pbac,$SUFFIX";) - -+dn: cn=request certificate ignore caacl,cn=virtual operations,cn=etc,$SUFFIX -+default:objectClass: top -+default:objectClass: nsContainer -+default:cn: request certificate ignore caacl -+ -+dn: cn=Request Certificate ignoring CA ACLs,cn=permissions,cn=pbac,$SUFFIX -+default:objectClass: top -+default:objectClass: groupofnames -+default:objectClass: ipapermission -+default:cn: Request Certificate ignoring CA ACLs -+default:member: cn=Certificate Administrators,cn=privileges,cn=pbac,$SUFFIX -+ -+dn: $SUFFIX -+add:aci:(targetattr = "objectclass")(target = "ldap:///cn=request certificate ignore caacl,cn=virtual operations,cn=etc,$SUFFIX" )(version 3.0; acl "permission:Request Certificate ignoring CA ACLs"; allow (write) groupdn = "ldap:///cn=Request Certificate ignoring CA ACLs,cn=permissions,cn=pbac,$SUFFIX";) -+ - - # Read privileges - dn: cn=RBAC Readers,cn=privileges,cn=pbac,$SUFFIX -diff --git a/ipalib/plugins/cert.py b/ipalib/plugins/cert.py -index 610f2149363eaa74180e9de5c9ee1439446ef409..daa698b54f2cc1b645245d312fae0f0500239ea2 100644 ---- a/ipalib/plugins/cert.py -+++ b/ipalib/plugins/cert.py -@@ -345,8 +345,6 @@ class cert_request(VirtualCommand): - else: - principal_type = SERVICE - -- caacl_check(principal_type, principal_string, ca, profile_id) -- - bind_principal = split_any_principal(getattr(context, 'principal')) - bind_service, bind_name, bind_realm = bind_principal - -@@ -362,6 +360,15 @@ class cert_request(VirtualCommand): - self.check_access() - - try: -+ self.check_access("request certificate ignore caacl") -+ bypass_caacl = True -+ except errors.ACIError: -+ bypass_caacl = False -+ -+ if not bypass_caacl: -+ caacl_check(principal_type, principal_string, ca, profile_id) -+ -+ try: - subject = pkcs10.get_subject(csr) - extensions = pkcs10.get_extensions(csr) - subjectaltname = pkcs10.get_subjectaltname(csr) or () -@@ -469,7 +476,7 @@ class cert_request(VirtualCommand): - raise errors.ACIError(info=_( - "Insufficient privilege to create a certificate " - "with subject alt name '%s'.") % name) -- if alt_principal_string is not None: -+ if alt_principal_string is not None and not bypass_caacl: - caacl_check( - principal_type, alt_principal_string, ca, profile_id) - elif name_type in (pkcs10.SAN_OTHERNAME_KRB5PRINCIPALNAME, --- -2.4.3 - diff --git a/SOURCES/0063-schema-Generate-bits-for-help-load-them-on-request.patch b/SOURCES/0063-schema-Generate-bits-for-help-load-them-on-request.patch new file mode 100644 index 0000000..2a0ba33 --- /dev/null +++ b/SOURCES/0063-schema-Generate-bits-for-help-load-them-on-request.patch @@ -0,0 +1,162 @@ +From 5386802ebc96ef0c2bc4a3bfa260ee83a6d7fe5f Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Tue, 2 Aug 2016 08:16:30 +0200 +Subject: [PATCH] schema: Generate bits for help load them on request + +Store name, summary, topic_topic and exclude in single entry in cache +for all commands. These data are needed for help and storing and +loading them together allows fast help response. + +https://fedorahosted.org/freeipa/ticket/6048 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/schema.py | 54 +++++++++++++++++++++++++++++--------- + 1 file changed, 42 insertions(+), 12 deletions(-) + +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index d7c018e3de1cc79ffc086e3576542ce993ebc87a..5264d4cc177ba457c517f93f203e0baca7b0ac01 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -23,7 +23,7 @@ from ipapython.dn import DN + from ipapython.dnsutil import DNSName + from ipapython.ipa_log_manager import log_mgr + +-FORMAT = '0' ++FORMAT = '1' + + if six.PY3: + unicode = str +@@ -113,9 +113,11 @@ class _SchemaPlugin(object): + if self._class is not None: + return self._class.summary + else: +- if self.doc is not None: +- return self.doc.split('\n\n', 1)[0].strip() +- else: ++ self._schema.load_help() ++ schema = self._schema[self.schema_key][self.full_name] ++ try: ++ return schema['summary'] ++ except KeyError: + return u'<%s>' % self.full_name + + def _create_default_from(self, api, name, keys): +@@ -241,6 +243,7 @@ class _SchemaCommandPlugin(_SchemaPlugin): + if self._class is not None: + return self._class.topic + else: ++ self._schema.load_help() + schema = self._schema[self.schema_key][self.full_name] + try: + return str(schema['topic_topic']).partition('/')[0] +@@ -252,6 +255,7 @@ class _SchemaCommandPlugin(_SchemaPlugin): + if self._class is not None: + return self._class.NO_CLI + else: ++ self._schema.load_help() + schema = self._schema[self.schema_key][self.full_name] + return 'cli' in schema.get('exclude', []) + +@@ -432,7 +436,6 @@ class Schema(object): + + """ + namespaces = {'classes', 'commands', 'topics'} +- schema_info_path = 'schema' + _DIR = os.path.join(USER_CACHE_PATH, 'ipa', 'schema') + + def __init__(self, api, server_info, client): +@@ -488,8 +491,7 @@ class Schema(object): + if fmt != FORMAT: + raise RuntimeError('invalid format') + +- schema_info = json.loads(schema.read(self.schema_info_path)) +- return schema_info['fingerprint'] ++ return json.loads(schema.read('fingerprint')) + + def _fetch(self, client): + if not client.isconnected(): +@@ -522,6 +524,7 @@ class Schema(object): + else: + fp = schema['fingerprint'] + ttl = schema.pop('ttl', 0) ++ schema.pop('version', None) + + for key, value in schema.items(): + if key in self.namespaces: +@@ -534,8 +537,6 @@ class Schema(object): + def _read_schema(self): + with self._open_schema(self._fingerprint, 'r') as schema: + self._dict['fingerprint'] = self._get_schema_fingerprint(schema) +- schema_info = json.loads(schema.read(self.schema_info_path)) +- self._dict['version'] = schema_info['version'] + + for name in schema.namelist(): + ns, _slash, key = name.partition('/') +@@ -548,6 +549,27 @@ class Schema(object): + except KeyError: + return self._dict[key] + ++ def _generate_help(self, schema): ++ halp = {} ++ ++ for namespace in ('commands', 'topics'): ++ halp[namespace] = {} ++ ++ for member_schema in schema[namespace].values(): ++ member_full_name = member_schema['full_name'] ++ ++ topic = halp[namespace].setdefault(member_full_name, {}) ++ topic['name'] = member_schema['name'] ++ if 'doc' in member_schema: ++ topic['summary'] = ( ++ member_schema['doc'].split('\n\n', 1)[0].strip()) ++ if 'topic_topic' in member_schema: ++ topic['topic_topic'] = member_schema['topic_topic'] ++ if 'exclude' in member_schema: ++ topic['exclude'] = member_schema['exclude'] ++ ++ return halp ++ + def _write_schema(self): + try: + os.makedirs(self._DIR) +@@ -557,7 +579,6 @@ class Schema(object): + return + + with self._open_schema(self._fingerprint, 'w') as schema: +- schema_info = {} + for key, value in self._dict.items(): + if key in self.namespaces: + ns = value +@@ -565,9 +586,10 @@ class Schema(object): + path = '{}/{}'.format(key, member) + schema.writestr(path, json.dumps(ns[member])) + else: +- schema_info[key] = value ++ schema.writestr(key, json.dumps(value)) + +- schema.writestr(self.schema_info_path, json.dumps(schema_info)) ++ schema.writestr('_help', ++ json.dumps(self._generate_help(self._dict))) + + def _read(self, path): + with self._open_schema(self._fingerprint, 'r') as zf: +@@ -587,6 +609,14 @@ class Schema(object): + def iter_namespace(self, namespace): + return iter(self._dict[namespace]) + ++ def load_help(self): ++ if not self._help: ++ self._help = self._read('_help') ++ ++ for ns in self._help: ++ for member in self._help[ns]: ++ self._dict[ns][member].update(self._help[ns][member]) ++ + + def get_package(api, client): + try: +-- +2.7.4 + diff --git a/SOURCES/0064-Added-CLI-param-and-ACL-for-vault-service-operations.patch b/SOURCES/0064-Added-CLI-param-and-ACL-for-vault-service-operations.patch deleted file mode 100644 index 278ea95..0000000 --- a/SOURCES/0064-Added-CLI-param-and-ACL-for-vault-service-operations.patch +++ /dev/null @@ -1,383 +0,0 @@ -From 366a208f9d7bbbf637d192d1dfcab4482f69c441 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Tue, 11 Aug 2015 08:19:59 +0200 -Subject: [PATCH] Added CLI param and ACL for vault service operations. - -The CLIs to manage vault owners and members have been modified -to accept services with a new parameter. - -A new ACL has been added to allow a service to create its own -service container. - -https://fedorahosted.org/freeipa/ticket/5172 - -Reviewed-By: Jan Cholasta -Reviewed-By: Martin Kosek ---- - API.txt | 12 ++- - VERSION | 4 +- - install/share/vault.update | 1 + - ipalib/plugins/vault.py | 177 +++++++++++++++++++++------------------------ - 4 files changed, 94 insertions(+), 100 deletions(-) - -diff --git a/API.txt b/API.txt -index 2e19d6b2f1e16cc1c89d71ed7d443145426a28e3..71df3a56595a012e6382414ad4453d30ede8155b 100644 ---- a/API.txt -+++ b/API.txt -@@ -5434,13 +5434,14 @@ output: Entry('result', , Gettext('A dictionary representing an LDA - output: Output('summary', (, ), None) - output: PrimaryKey('value', None, None) - command: vault_add_member --args: 1,9,3 -+args: 1,10,3 - arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True) - option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') - option: Str('group*', alwaysask=True, cli_name='groups', csv=True) - option: Flag('no_members', autofill=True, default=False, exclude='webui') - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') - option: Str('service?') -+option: Str('services', alwaysask=True, cli_name='services', csv=True, multivalue=True, required=False) - option: Flag('shared?', autofill=True, default=False) - option: Str('user*', alwaysask=True, cli_name='users', csv=True) - option: Str('username?', cli_name='user') -@@ -5449,13 +5450,14 @@ output: Output('completed', , None) - output: Output('failed', , None) - output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) - command: vault_add_owner --args: 1,9,3 -+args: 1,10,3 - arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True) - option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') - option: Str('group*', alwaysask=True, cli_name='groups', csv=True) - option: Flag('no_members', autofill=True, default=False, exclude='webui') - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') - option: Str('service?') -+option: Str('services', alwaysask=True, cli_name='services', csv=True, multivalue=True, required=False) - option: Flag('shared?', autofill=True, default=False) - option: Str('user*', alwaysask=True, cli_name='users', csv=True) - option: Str('username?', cli_name='user') -@@ -5547,13 +5549,14 @@ output: Entry('result', , Gettext('A dictionary representing an LDA - output: Output('summary', (, ), None) - output: PrimaryKey('value', None, None) - command: vault_remove_member --args: 1,9,3 -+args: 1,10,3 - arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True) - option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') - option: Str('group*', alwaysask=True, cli_name='groups', csv=True) - option: Flag('no_members', autofill=True, default=False, exclude='webui') - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') - option: Str('service?') -+option: Str('services', alwaysask=True, cli_name='services', csv=True, multivalue=True, required=False) - option: Flag('shared?', autofill=True, default=False) - option: Str('user*', alwaysask=True, cli_name='users', csv=True) - option: Str('username?', cli_name='user') -@@ -5562,13 +5565,14 @@ output: Output('completed', , None) - output: Output('failed', , None) - output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) - command: vault_remove_owner --args: 1,9,3 -+args: 1,10,3 - arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True) - option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') - option: Str('group*', alwaysask=True, cli_name='groups', csv=True) - option: Flag('no_members', autofill=True, default=False, exclude='webui') - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') - option: Str('service?') -+option: Str('services', alwaysask=True, cli_name='services', csv=True, multivalue=True, required=False) - option: Flag('shared?', autofill=True, default=False) - option: Str('user*', alwaysask=True, cli_name='users', csv=True) - option: Str('username?', cli_name='user') -diff --git a/VERSION b/VERSION -index ca43f3e0c06880d355c068514134187c5edda175..69351a8fa8e27c884c130ab49d3fab541cd09ff9 100644 ---- a/VERSION -+++ b/VERSION -@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 - # # - ######################################################## - IPA_API_VERSION_MAJOR=2 --IPA_API_VERSION_MINOR=148 --# Last change: ftweedal - add --out option to user-show -+IPA_API_VERSION_MINOR=149 -+# Last change: edewata - Added CLI param and ACL for vault service operations -diff --git a/install/share/vault.update b/install/share/vault.update -index 61a8940b544fbc839b931f337389ac35dc2d1ffa..14421b5189efe9b3d9491e845e74debca6e18941 100644 ---- a/install/share/vault.update -+++ b/install/share/vault.update -@@ -8,6 +8,7 @@ default: objectClass: top - default: objectClass: ipaVaultContainer - default: cn: vaults - default: aci: (target="ldap:///cn=*,cn=users,cn=vaults,cn=kra,$SUFFIX")(version 3.0; acl "Allow users to create private container"; allow (add) userdn = "ldap:///uid=($$attr.cn),cn=users,cn=accounts,$SUFFIX";) -+default: aci: (target="ldap:///cn=*,cn=services,cn=vaults,cn=kra,$SUFFIX")(version 3.0; acl "Allow services to create private container"; allow (add) userdn = "ldap:///krbprincipalname=($$attr.cn)@$REALM,cn=services,cn=accounts,$SUFFIX";) - default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Container owners can manage vaults in the container"; allow(read, search, compare, add, delete) userattr="parent[1].owner#USERDN";) - default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Indirect container owners can manage vaults in the container"; allow(read, search, compare, add, delete) userattr="parent[1].owner#GROUPDN";) - default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Vault members can access the vault"; allow(read, search, compare) userattr="member#USERDN";) -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index ac608f5c7e2779da138c75a0f02bd5546f4aeffd..01c6096335d47b337253d4f2d1e0571200383c7a 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -44,7 +44,7 @@ from ipalib.crud import PKQuery, Retrieve, Update - from ipalib.plugable import Registry - from ipalib.plugins.baseldap import LDAPObject, LDAPCreate, LDAPDelete,\ - LDAPSearch, LDAPUpdate, LDAPRetrieve, LDAPAddMember, LDAPRemoveMember,\ -- pkey_to_value -+ LDAPModMember, pkey_to_value - from ipalib.request import context - from ipalib.plugins.user import split_principal - from ipalib import _, ngettext -@@ -93,122 +93,91 @@ The secret can only be retrieved using the private key. - """) + _(""" - EXAMPLES: - """) + _(""" -- List private vaults: -+ List vaults: - ipa vault-find -+ [--user |--service |--shared] - """) + _(""" -- List service vaults: -- ipa vault-find --service --""") + _(""" -- List shared vaults: -- ipa vault-find --shared --""") + _(""" -- List user vaults: -- ipa vault-find --user --""") + _(""" -- Add a private vault: -+ Add a standard vault: - ipa vault-add --""") + _(""" -- Add a service vault: -- ipa vault-add --service --""") + _(""" -- Add a shared vault: -- ipa vault-add --shared --""") + _(""" -- Add a user vault: -- ipa vault-add --user -+ [--user |--service |--shared] - """) + _(""" - Add a symmetric vault: -- ipa vault-add --type symmetric --password-file password.txt -+ ipa vault-add -+ [--user |--service |--shared] -+ --type symmetric --password-file password.txt - """) + _(""" - Add an asymmetric vault: -- ipa vault-add --type asymmetric --public-key-file public.pem -+ ipa vault-add -+ [--user |--service |--shared] -+ --type asymmetric --public-key-file public.pem - """) + _(""" -- Show a private vault: -+ Show a vault: - ipa vault-show -+ [--user |--service |--shared] - """) + _(""" -- Show a service vault: -- ipa vault-show --service -+ Modify a vault: -+ ipa vault-mod -+ [--user |--service |--shared] -+ --desc - """) + _(""" -- Show a shared vault: -- ipa vault-show --shared --""") + _(""" -- Show a user vault: -- ipa vault-show --user --""") + _(""" -- Modify a private vault: -- ipa vault-mod --desc --""") + _(""" -- Modify a service vault: -- ipa vault-mod --service --desc --""") + _(""" -- Modify a shared vault: -- ipa vault-mod --shared --desc --""") + _(""" -- Modify a user vault: -- ipa vault-mod --user --desc --""") + _(""" -- Delete a private vault: -+ Delete a vault: - ipa vault-del --""") + _(""" -- Delete a service vault: -- ipa vault-del --service --""") + _(""" -- Delete a shared vault: -- ipa vault-del --shared --""") + _(""" -- Delete a user vault: -- ipa vault-del --user -+ [--user |--service |--shared] - """) + _(""" - Display vault configuration: - ipa vaultconfig-show - """) + _(""" -- Archive data into private vault: -- ipa vault-archive --in --""") + _(""" -- Archive data into service vault: -- ipa vault-archive --service --in --""") + _(""" -- Archive data into shared vault: -- ipa vault-archive --shared --in --""") + _(""" -- Archive data into user vault: -- ipa vault-archive --user --in -+ Archive data into standard vault: -+ ipa vault-archive -+ [--user |--service |--shared] -+ --in - """) + _(""" - Archive data into symmetric vault: -- ipa vault-archive --in -+ ipa vault-archive -+ [--user |--service |--shared] -+ --in -+ --password-file password.txt - """) + _(""" - Archive data into asymmetric vault: -- ipa vault-archive --in --""") + _(""" -- Retrieve data from private vault: -- ipa vault-retrieve --out --""") + _(""" -- Retrieve data from service vault: -- ipa vault-retrieve --service --out --""") + _(""" -- Retrieve data from shared vault: -- ipa vault-retrieve --shared --out -+ ipa vault-archive -+ [--user |--service |--shared] -+ --in - """) + _(""" -- Retrieve data from user vault: -- ipa vault-retrieve --user --out -+ Retrieve data from standard vault: -+ ipa vault-retrieve -+ [--user |--service |--shared] -+ --out - """) + _(""" - Retrieve data from symmetric vault: -- ipa vault-retrieve --out data.bin -+ ipa vault-retrieve -+ [--user |--service |--shared] -+ --out -+ --password-file password.txt - """) + _(""" - Retrieve data from asymmetric vault: -- ipa vault-retrieve --out data.bin --private-key-file private.pem -+ ipa vault-retrieve -+ [--user |--service |--shared] -+ --out --private-key-file private.pem - """) + _(""" -- Add a vault owner: -- ipa vault-add-owner --users -+ Add vault owners: -+ ipa vault-add-owner -+ [--user |--service |--shared] -+ [--users ] [--groups ] [--services ] - """) + _(""" -- Delete a vault owner: -- ipa vault-remove-owner --users -+ Delete vault owners: -+ ipa vault-remove-owner -+ [--user |--service |--shared] -+ [--users ] [--groups ] [--services ] - """) + _(""" -- Add a vault member: -- ipa vault-add-member --users -+ Add vault members: -+ ipa vault-add-member -+ [--user |--service |--shared] -+ [--users ] [--groups ] [--services ] - """) + _(""" -- Delete a vault member: -- ipa vault-remove-member --users -+ Delete vault members: -+ ipa vault-remove-member -+ [--user |--service |--shared] -+ [--users ] [--groups ] [--services ] - """) - - -@@ -285,8 +254,8 @@ class vault(LDAPObject): - 'ipavaulttype', - ] - attribute_members = { -- 'owner': ['user', 'group'], -- 'member': ['user', 'group'], -+ 'owner': ['user', 'group', 'service'], -+ 'member': ['user', 'group', 'service'], - } - - label = _('Vaults') -@@ -340,6 +309,11 @@ class vault(LDAPObject): - label=_('Owner groups'), - flags=['no_create', 'no_update', 'no_search'], - ), -+ Str( -+ 'owner_service?', -+ label=_('Owner services'), -+ flags=['no_create', 'no_update', 'no_search'], -+ ), - ) - - def get_dn(self, *keys, **options): -@@ -1432,8 +1406,23 @@ class vault_retrieve_internal(PKQuery): - return response - - -+class VaultModMember(LDAPModMember): -+ def get_options(self): -+ for param in super(VaultModMember, self).get_options(): -+ if param.name == 'service' and param not in vault_options: -+ param = param.clone_rename('services') -+ yield param -+ -+ def get_member_dns(self, **options): -+ if 'services' in options: -+ options['service'] = options.pop('services') -+ else: -+ options.pop('service', None) -+ return super(VaultModMember, self).get_member_dns(**options) -+ -+ - @register() --class vault_add_owner(LDAPAddMember): -+class vault_add_owner(VaultModMember, LDAPAddMember): - __doc__ = _('Add owners to a vault.') - - takes_options = LDAPAddMember.takes_options + vault_options -@@ -1457,7 +1446,7 @@ class vault_add_owner(LDAPAddMember): - - - @register() --class vault_remove_owner(LDAPRemoveMember): -+class vault_remove_owner(VaultModMember, LDAPRemoveMember): - __doc__ = _('Remove owners from a vault.') - - takes_options = LDAPRemoveMember.takes_options + vault_options -@@ -1481,14 +1470,14 @@ class vault_remove_owner(LDAPRemoveMember): - - - @register() --class vault_add_member(LDAPAddMember): -+class vault_add_member(VaultModMember, LDAPAddMember): - __doc__ = _('Add members to a vault.') - - takes_options = LDAPAddMember.takes_options + vault_options - - - @register() --class vault_remove_member(LDAPRemoveMember): -+class vault_remove_member(VaultModMember, LDAPRemoveMember): - __doc__ = _('Remove members from a vault.') - - takes_options = LDAPRemoveMember.takes_options + vault_options --- -2.4.3 - diff --git a/SOURCES/0064-help-Do-not-create-instances-to-get-information-abou.patch b/SOURCES/0064-help-Do-not-create-instances-to-get-information-abou.patch new file mode 100644 index 0000000..62dca09 --- /dev/null +++ b/SOURCES/0064-help-Do-not-create-instances-to-get-information-abou.patch @@ -0,0 +1,77 @@ +From 0ae77ea176190307ef74598179fc8be83169628a Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Wed, 20 Jul 2016 13:24:03 +0200 +Subject: [PATCH] help: Do not create instances to get information about + commands and topics + +Creating instance requires that complete schema for the command is +read from schema cache and passed to constructor. This operation takes +a lot of time. Utilizing class properties and pregenerated help bits +allows to get the necessary information directly from classes reducing +time it takes significantly. + +https://fedorahosted.org/freeipa/ticket/6048 + +Reviewed-By: Jan Cholasta +--- + ipalib/cli.py | 15 ++++++++------- + ipalib/plugable.py | 7 +++++-- + 2 files changed, 13 insertions(+), 9 deletions(-) + +diff --git a/ipalib/cli.py b/ipalib/cli.py +index 1faf8285c47d950d5fd311154b6936c8371d746c..d89a5320853ecf575c7ba710b2db2e62e1003141 100644 +--- a/ipalib/cli.py ++++ b/ipalib/cli.py +@@ -727,8 +727,8 @@ class help(frontend.Local): + self._builtins = [] + + # build help topics +- for c in self.api.Command(): +- if c is not self.api.Command[c.name]: ++ for c in self.api.Command: ++ if c is not self.api.Command.get_plugin(c.name): + continue + if c.NO_CLI: + continue +@@ -793,13 +793,14 @@ class help(frontend.Local): + self.print_commands(name, outfile) + elif name == "commands": + mcl = 0 +- for cmd in self.Command(): +- if cmd is not self.Command[cmd.name]: ++ for cmd_plugin in self.Command: ++ if cmd_plugin is not self.Command.get_plugin(cmd_plugin.name): + continue +- if cmd.NO_CLI: ++ if cmd_plugin.NO_CLI: + continue +- mcl = max(mcl, len(cmd.name)) +- writer('%s %s' % (to_cli(cmd.name).ljust(mcl), cmd.summary)) ++ mcl = max(mcl, len(cmd_plugin.name)) ++ writer('%s %s' % (to_cli(cmd_plugin.name).ljust(mcl), ++ cmd_plugin.summary)) + else: + raise HelpError(topic=name) + +diff --git a/ipalib/plugable.py b/ipalib/plugable.py +index 073ad05d7aee5e83cae5c6e20bac8f9439505198..af35f5bae27a17230267d5b10b5fdc4f784a4760 100644 +--- a/ipalib/plugable.py ++++ b/ipalib/plugable.py +@@ -318,9 +318,12 @@ class APINameSpace(collections.Mapping): + self.__enumerate() + return iter(self.__plugins) + +- def __getitem__(self, key): ++ def get_plugin(self, key): + self.__enumerate() +- plugin = self.__plugins_by_key[key] ++ return self.__plugins_by_key[key] ++ ++ def __getitem__(self, key): ++ plugin = self.get_plugin(key) + return self.__api._get(plugin) + + def __call__(self): +-- +2.7.4 + diff --git a/SOURCES/0065-Fix-ipa-caalc-add-service-error-message.patch b/SOURCES/0065-Fix-ipa-caalc-add-service-error-message.patch new file mode 100644 index 0000000..5435828 --- /dev/null +++ b/SOURCES/0065-Fix-ipa-caalc-add-service-error-message.patch @@ -0,0 +1,31 @@ +From 69a3d8a8abffe7a785efda8e6e2012718521783f Mon Sep 17 00:00:00 2001 +From: Tomas Krizek +Date: Tue, 9 Aug 2016 14:09:24 +0200 +Subject: [PATCH] Fix ipa-caalc-add-service error message + +When service is not found in ipa-caalc-add-service command, return the +entire principal name of the service instead of the first character. + +https://fedorahosted.org/freeipa/ticket/6171 + +Reviewed-By: Petr Spacek +--- + ipaserver/plugins/service.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipaserver/plugins/service.py b/ipaserver/plugins/service.py +index 28ea364e9aca8c997a86e27c529fc49d8410115b..a44dcaa5e348d3deedda6c0b4f55760ad873cf49 100644 +--- a/ipaserver/plugins/service.py ++++ b/ipaserver/plugins/service.py +@@ -575,7 +575,7 @@ class service(LDAPObject): + pass + + try: +- return dn['krbprincipalname'][0] ++ return dn['krbprincipalname'] + except KeyError: + return unicode(dn) + +-- +2.7.4 + diff --git a/SOURCES/0065-trusts-Detect-missing-Samba-instance.patch b/SOURCES/0065-trusts-Detect-missing-Samba-instance.patch deleted file mode 100644 index 50f4de4..0000000 --- a/SOURCES/0065-trusts-Detect-missing-Samba-instance.patch +++ /dev/null @@ -1,189 +0,0 @@ -From df641e93d2f88f642f476ad8c5b7313bdfce8d9e Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Thu, 6 Aug 2015 10:10:04 +0200 -Subject: [PATCH] trusts: Detect missing Samba instance - -In the event of invocation of trust related commands, IPA server needs to -contact local Samba instance. This is not possible on servers that -merely act as AD trust agents, since they do not have Samba instance -running. - -Properly detect the absence of the Samba instance and output -user-friendly -message which includes list of servers that are capable of running -the command, if such exist. - -List of commands affected: -* ipa trust-add -* ipa trust-fetch-domains -* all of the trustdomain commands available via CLI - -https://fedorahosted.org/freeipa/ticket/5165 - -Reviewed-By: Martin Babinsky ---- - ipalib/plugins/trust.py | 99 +++++++++++++++++++++++++++++++++++++++---------- - 1 file changed, 79 insertions(+), 20 deletions(-) - -diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py -index 0bb5e6558b680ac1acad44461d78a571098c7b25..c7546692bdd8dd827ee9772b72a758042d97aa71 100644 ---- a/ipalib/plugins/trust.py -+++ b/ipalib/plugins/trust.py -@@ -199,6 +199,73 @@ def make_trust_dn(env, trust_type, dn): - return DN(dn, container_dn) - return dn - -+def find_adtrust_masters(ldap, api): -+ """ -+ Returns a list of names of IPA servers with ADTRUST component configured. -+ """ -+ -+ try: -+ entries, truncated = ldap.find_entries( -+ "cn=ADTRUST", -+ base_dn=api.env.container_masters + api.env.basedn -+ ) -+ except errors.NotFound: -+ entries = [] -+ -+ return [entry.dn[1].value for entry in entries] -+ -+def verify_samba_component_presence(ldap, api): -+ """ -+ Verifies that Samba is installed and configured on this particular master. -+ If Samba is not available, provide a heplful hint with the list of masters -+ capable of running the commands. -+ """ -+ -+ adtrust_present = api.Command['adtrust_is_enabled']()['result'] -+ -+ hint = _( -+ ' Alternatively, following servers are capable of running this ' -+ 'command: %(masters)s' -+ ) -+ -+ def raise_missing_component_error(message): -+ masters_with_adtrust = find_adtrust_masters(ldap, api) -+ -+ # If there are any masters capable of running Samba requiring commands -+ # let's advertise them directly -+ if masters_with_adtrust: -+ message += hint % dict(masters=', '.join(masters_with_adtrust)) -+ -+ raise errors.NotFound( -+ name=_('AD Trust setup'), -+ reason=message, -+ ) -+ -+ # We're ok in this case, bail out -+ if adtrust_present and _bindings_installed: -+ return -+ -+ # First check for packages missing -+ elif not _bindings_installed: -+ error_message=_( -+ 'Cannot perform the selected command without Samba 4 support ' -+ 'installed. Make sure you have installed server-trust-ad ' -+ 'sub-package of IPA.' -+ ) -+ -+ raise_missing_component_error(error_message) -+ -+ # Packages present, but ADTRUST instance is not configured -+ elif not adtrust_present: -+ error_message=_( -+ 'Cannot perform the selected command without Samba 4 instance ' -+ 'configured on this machine. Make sure you have run ' -+ 'ipa-adtrust-install on this server.' -+ ) -+ -+ raise_missing_component_error(error_message) -+ -+ - def generate_creds(trustinstance, style, **options): - """ - Generate string representing credentials using trust instance -@@ -554,6 +621,10 @@ sides. - has_output_params = LDAPCreate.has_output_params + trust_output_params - - def execute(self, *keys, **options): -+ ldap = self.obj.backend -+ -+ verify_samba_component_presence(ldap, self.api) -+ - full_join = self.validate_options(*keys, **options) - old_range, range_name, dom_sid = self.validate_range(*keys, **options) - result = self.execute_ad(full_join, *keys, **options) -@@ -569,7 +640,6 @@ sides. - created_range_type = old_range['result']['iparangetype'][0] - - trust_filter = "cn=%s" % result['value'] -- ldap = self.obj.backend - (trusts, truncated) = ldap.find_entries( - base_dn=DN(self.api.env.container_trusts, self.api.env.basedn), - filter=trust_filter) -@@ -642,16 +712,6 @@ sides. - def validate_options(self, *keys, **options): - trusted_realm_domain = keys[-1] - -- if not _bindings_installed: -- raise errors.NotFound( -- name=_('AD Trust setup'), -- reason=_( -- 'Cannot perform join operation without Samba 4 support ' -- 'installed. Make sure you have installed server-trust-ad ' -- 'sub-package of IPA' -- ) -- ) -- - if not _murmur_installed and 'base_id' not in options: - raise errors.ValidationError( - name=_('missing base_id'), -@@ -1398,6 +1458,9 @@ class trustdomain_del(LDAPDelete): - msg_summary = _('Removed information about the trusted domain "%(value)s"') - - def execute(self, *keys, **options): -+ ldap = self.api.Backend.ldap2 -+ verify_samba_component_presence(ldap, self.api) -+ - # Note that pre-/post- callback handling for LDAPDelete is causing pre_callback - # to always receive empty keys. We need to catch the case when root domain is being deleted - -@@ -1470,15 +1533,9 @@ class trust_fetch_domains(LDAPRetrieve): - ) - - def execute(self, *keys, **options): -- if not _bindings_installed: -- raise errors.NotFound( -- name=_('AD Trust setup'), -- reason=_( -- 'Cannot perform join operation without Samba 4 support ' -- 'installed. Make sure you have installed server-trust-ad ' -- 'sub-package of IPA' -- ) -- ) -+ ldap = self.api.Backend.ldap2 -+ verify_samba_component_presence(ldap, self.api) -+ - trust = self.api.Command.trust_show(keys[0], raw=True)['result'] - - result = dict() -@@ -1524,6 +1581,7 @@ class trustdomain_enable(LDAPQuery): - - def execute(self, *keys, **options): - ldap = self.api.Backend.ldap2 -+ verify_samba_component_presence(ldap, self.api) - - if keys[0].lower() == keys[1].lower(): - raise errors.ValidationError(name='domain', -@@ -1564,6 +1622,7 @@ class trustdomain_disable(LDAPQuery): - - def execute(self, *keys, **options): - ldap = self.api.Backend.ldap2 -+ verify_samba_component_presence(ldap, self.api) - - if keys[0].lower() == keys[1].lower(): - raise errors.ValidationError(name='domain', --- -2.4.3 - diff --git a/SOURCES/0066-Don-t-show-force-ntpd-option-in-replica-install.patch b/SOURCES/0066-Don-t-show-force-ntpd-option-in-replica-install.patch new file mode 100644 index 0000000..96e2a22 --- /dev/null +++ b/SOURCES/0066-Don-t-show-force-ntpd-option-in-replica-install.patch @@ -0,0 +1,42 @@ +From a1b1518f02e0237fb8080851d0722f866b127918 Mon Sep 17 00:00:00 2001 +From: Stanislav Laznicka +Date: Tue, 9 Aug 2016 15:22:33 +0200 +Subject: [PATCH] Don't show --force-ntpd option in replica install + +Always run the client installation script with --no-ntp +option so that it does not show the message about --force-ntpd +option that does not exist in ipa-replica-install. The time +synchronization is done elsewhere anyway. + +https://fedorahosted.org/freeipa/ticket/6046 + +Reviewed-By: Martin Basti +--- + ipaserver/install/server/replicainstall.py | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py +index 9d05a0be5a2679d825b4ee6bc2ea55ed358e8ff9..f54ff7da06c57b9c8251429cbdacc5c300805f84 100644 +--- a/ipaserver/install/server/replicainstall.py ++++ b/ipaserver/install/server/replicainstall.py +@@ -881,7 +881,7 @@ def install(installer): + try: + args = [paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended", + "--domain", config.domain_name, "--server", config.host_name, +- "--realm", config.realm_name] ++ "--realm", config.realm_name, "--no-ntp"] + if options.no_dns_sshfp: + args.append("--no-dns-sshfp") + if options.ssh_trust_dns: +@@ -918,7 +918,7 @@ def ensure_enrolled(installer): + try: + installer._enrollment_performed = True + +- args = [paths.IPA_CLIENT_INSTALL, "--unattended"] ++ args = [paths.IPA_CLIENT_INSTALL, "--unattended", "--no-ntp"] + stdin = None + + if installer.domain_name: +-- +2.7.4 + diff --git a/SOURCES/0066-winsync-migrate-Add-warning-about-passsync.patch b/SOURCES/0066-winsync-migrate-Add-warning-about-passsync.patch deleted file mode 100644 index d3917e2..0000000 --- a/SOURCES/0066-winsync-migrate-Add-warning-about-passsync.patch +++ /dev/null @@ -1,38 +0,0 @@ -From cdbf2fcc214bf8a4f94e3b25b6a742ea1fc9f75c Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Mon, 17 Aug 2015 08:46:52 +0200 -Subject: [PATCH] winsync-migrate: Add warning about passsync - -https://fedorahosted.org/freeipa/ticket/5162 - -Reviewed-By: Martin Babinsky ---- - ipaserver/install/ipa_winsync_migrate.py | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/ipaserver/install/ipa_winsync_migrate.py b/ipaserver/install/ipa_winsync_migrate.py -index cbe068458cc0b6853573c9d23d4cb6386a816bb3..c327e502e6bfb6e402931e1962fe2410570b2bc2 100644 ---- a/ipaserver/install/ipa_winsync_migrate.py -+++ b/ipaserver/install/ipa_winsync_migrate.py -@@ -302,6 +302,12 @@ class WinsyncMigrate(admintool.AdminTool): - object_container_dn=DN(api.env.container_selinux, api.env.basedn), - ) - -+ def warn_passsync(self): -+ self.log.warning("Migration completed. Please note that if PassSync " -+ "was configured on the given Active Directory server, " -+ "it needs to be manually removed, otherwise it may try " -+ "to reset password for accounts that are no longer existent.") -+ - @classmethod - def main(cls, argv): - """ -@@ -343,3 +349,5 @@ class WinsyncMigrate(admintool.AdminTool): - self.migrate_hbac_memberships(entry) - self.migrate_selinux_memberships(entry) - self.ldap.delete_entry(entry) -+ -+ self.warn_passsync() --- -2.4.3 - diff --git a/SOURCES/0067-DNS-server-upgrade-do-not-fail-when-DNS-server-did-n.patch b/SOURCES/0067-DNS-server-upgrade-do-not-fail-when-DNS-server-did-n.patch new file mode 100644 index 0000000..dce696d --- /dev/null +++ b/SOURCES/0067-DNS-server-upgrade-do-not-fail-when-DNS-server-did-n.patch @@ -0,0 +1,62 @@ +From 78ef6581483190fc60fc928fb2263f5520a5edfa Mon Sep 17 00:00:00 2001 +From: Petr Spacek +Date: Thu, 11 Aug 2016 13:44:29 +0200 +Subject: [PATCH] DNS server upgrade: do not fail when DNS server did not + respond + +Previously, update_dnsforward_emptyzones failed with an exeception if +DNS query failed for some reason. Now the error is logged and upgrade +continues. + +I assume that this is okay because the DNS query is used as heuristics +of last resort in the upgrade logic and failure to do so should not have +catastrophics consequences: In the worst case, the admin needs to +manually change forwarding policy from 'first' to 'only'. + +In the end I have decided not to auto-start BIND because BIND depends on +GSSAPI for authentication, which in turn depends on KDC ... Alternative +like reconfiguring BIND to use LDAPI+EXTERNAL and reconfiguring DS to +accept LDAP external bind from named user are too complicated. + +https://fedorahosted.org/freeipa/ticket/6205 + +Reviewed-By: Martin Basti +--- + ipaserver/install/plugins/dns.py | 14 ++++++++++++-- + 1 file changed, 12 insertions(+), 2 deletions(-) + +diff --git a/ipaserver/install/plugins/dns.py b/ipaserver/install/plugins/dns.py +index 32247eedbac7fc7e00c7277ef0bc593a74cd22e4..7b06a5c0d3a59e5825af75fae87c9739a53d9913 100644 +--- a/ipaserver/install/plugins/dns.py ++++ b/ipaserver/install/plugins/dns.py +@@ -17,6 +17,9 @@ + # You should have received a copy of the GNU General Public License + # along with this program. If not, see . + ++from __future__ import absolute_import ++ ++import dns.exception + import re + import traceback + import time +@@ -489,8 +492,15 @@ class update_dnsforward_emptyzones(DNSUpdater): + self.api.Command['dnsconfig_mod'](ipadnsversion=2) + + self.update_zones() +- if dnsutil.has_empty_zone_addresses(self.api.env.host): +- self.update_global_ldap_forwarder() ++ try: ++ if dnsutil.has_empty_zone_addresses(self.api.env.host): ++ self.update_global_ldap_forwarder() ++ except dns.exception.DNSException as ex: ++ self.log.error('Skipping update of global DNS forwarder in LDAP: ' ++ 'Unable to determine if local server is using an ' ++ 'IP address belonging to an automatic empty zone. ' ++ 'Consider changing forwarding policy to "only". ' ++ 'DNS exception: %s', ex) + + return False, [] + +-- +2.7.4 + diff --git a/SOURCES/0067-winsync-migrate-Expand-the-man-page.patch b/SOURCES/0067-winsync-migrate-Expand-the-man-page.patch deleted file mode 100644 index 500fe82..0000000 --- a/SOURCES/0067-winsync-migrate-Expand-the-man-page.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 6e006377d043155590024235d770cb37eb801652 Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Mon, 17 Aug 2015 08:46:20 +0200 -Subject: [PATCH] winsync-migrate: Expand the man page - -https://fedorahosted.org/freeipa/ticket/5162 - -Reviewed-By: Martin Babinsky ---- - install/tools/man/ipa-winsync-migrate.1 | 27 ++++++++++++++++++++++++++- - 1 file changed, 26 insertions(+), 1 deletion(-) - -diff --git a/install/tools/man/ipa-winsync-migrate.1 b/install/tools/man/ipa-winsync-migrate.1 -index a1e01c83da6017d5cbe10297dbe84a4dd1741ec7..88702bad6fca66206dcbc1a90fce495eb33598fb 100644 ---- a/install/tools/man/ipa-winsync-migrate.1 -+++ b/install/tools/man/ipa-winsync-migrate.1 -@@ -16,7 +16,7 @@ - .\" - .\" Author: Tomas Babej - .\" --.TH "ipa-advise" "1" "Mar 10 2015" "FreeIPA" "FreeIPA Manual Pages" -+.TH "ipa-winsync-migrate" "1" "Mar 10 2015" "FreeIPA" "FreeIPA Manual Pages" - .SH "NAME" - ipa\-winsync\-migrate \- Seamless migration of AD users created by winsync to native AD users. - .SH "SYNOPSIS" -@@ -25,3 +25,28 @@ ipa\-winsync\-migrate - Migrates AD users created by winsync agreement to ID overrides in - the Default Trust View, thus preserving the actual POSIX attributes - already established. -+ -+Prior to the actual migration, the winsync replication agreement -+will be removed to protect the removal of the user accounts -+on the Active Directory side. -+ -+During the migration, group, assigned roles, HBAC rules and SELinux -+memberships of the synced users will be preserved. Any local copies -+(created by winsync) of the migrated users will be removed. -+ -+.SH "WARNINGS" -+After the migration, any PassSync agreements need to be removed -+from Active Directory Domain Controllers, otherwise they might -+attempt to update passwords for accounts that no longer exist -+on the IPA server. -+ -+.SH "OPTIONS" -+.TP -+\fB\-\-realm\fR -+The Active Directory realm the winsynced users belong to. -+.TP -+\fB\-\-server\fR -+The hostname of Active Directory Domain Controller the winsync replication agreement is established with. -+.TP -+\fB\-\-unattended\fR -+Never prompts for user input. --- -2.4.3 - diff --git a/SOURCES/0068-DNS-allow-to-add-forward-zone-to-already-broken-sub-.patch b/SOURCES/0068-DNS-allow-to-add-forward-zone-to-already-broken-sub-.patch new file mode 100644 index 0000000..567a26c --- /dev/null +++ b/SOURCES/0068-DNS-allow-to-add-forward-zone-to-already-broken-sub-.patch @@ -0,0 +1,32 @@ +From 9b4153fdc1af86344da9f4cf6fa139a8dcb18c8c Mon Sep 17 00:00:00 2001 +From: Petr Spacek +Date: Fri, 12 Aug 2016 17:08:30 +0200 +Subject: [PATCH] DNS: allow to add forward zone to already broken sub-domain + +Errors during DNS resolution might indicate that forwarder is the +necessary configuration which is missing. Now we disallow adding a +forwarder only if the zone is normally resolvable without the forwarder. + +https://fedorahosted.org/freeipa/ticket/6062 + +Reviewed-By: Martin Basti +--- + 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 585b28c15daf00df2918a67585f7fb6e99462f1e..6f1bd716d202bd85dfc46b5eb94f73e85683b917 100644 +--- a/ipaserver/plugins/dns.py ++++ b/ipaserver/plugins/dns.py +@@ -2097,7 +2097,7 @@ class DNSZoneBase_add(LDAPCreate): + + if not options['skip_overlap_check']: + try: +- check_zone_overlap(keys[-1]) ++ check_zone_overlap(keys[-1], raise_on_error=False) + except ValueError as e: + raise errors.InvocationError(e.message) + +-- +2.7.4 + diff --git a/SOURCES/0068-fix-typo-in-BasePathNamespace-member-pointing-to-ods.patch b/SOURCES/0068-fix-typo-in-BasePathNamespace-member-pointing-to-ods.patch deleted file mode 100644 index f5bf21a..0000000 --- a/SOURCES/0068-fix-typo-in-BasePathNamespace-member-pointing-to-ods.patch +++ /dev/null @@ -1,55 +0,0 @@ -From e106329ac5dbbbcf1e303d1311cd0d742f5d8803 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Thu, 13 Aug 2015 15:03:05 +0200 -Subject: [PATCH] fix typo in BasePathNamespace member pointing to ods exporter - config - -Reviewed-By: Martin Basti ---- - ipaplatform/base/paths.py | 2 +- - ipaserver/install/ipa_backup.py | 2 +- - ipaserver/install/odsexporterinstance.py | 2 +- - 3 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py -index 4c93c1f7162b0aeb4f798ef84e1ac8db4573518b..0dd3c7fda3020264a1ace8f2d13557cfddf18c2d 100644 ---- a/ipaplatform/base/paths.py -+++ b/ipaplatform/base/paths.py -@@ -119,7 +119,7 @@ class BasePathNamespace(object): - SYSCONFIG_DIRSRV_PKI_IPA_DIR = "/etc/sysconfig/dirsrv-PKI-IPA" - SYSCONFIG_DIRSRV_SYSTEMD = "/etc/sysconfig/dirsrv.systemd" - SYSCONFIG_IPA_DNSKEYSYNCD = "/etc/sysconfig/ipa-dnskeysyncd" -- SYSOCNFIG_IPA_ODS_EXPORTER = "/etc/sysconfig/ipa-ods-exporter" -+ SYSCONFIG_IPA_ODS_EXPORTER = "/etc/sysconfig/ipa-ods-exporter" - SYSCONFIG_HTTPD = "/etc/sysconfig/httpd" - SYSCONFIG_KRB5KDC_DIR = "/etc/sysconfig/krb5kdc" - SYSCONFIG_NAMED = "/etc/sysconfig/named" -diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py -index f7e032ae572f404f84ce48c1a5d72e78c31b4766..1bb6f810b16c8344ab957dd6259983189a88e89f 100644 ---- a/ipaserver/install/ipa_backup.py -+++ b/ipaserver/install/ipa_backup.py -@@ -132,7 +132,7 @@ class Backup(admintool.AdminTool): - paths.SYSCONFIG_KRB5KDC_DIR, - paths.SYSCONFIG_PKI_CA_PKI_CA_DIR, - paths.SYSCONFIG_IPA_DNSKEYSYNCD, -- paths.SYSOCNFIG_IPA_ODS_EXPORTER, -+ paths.SYSCONFIG_IPA_ODS_EXPORTER, - paths.SYSCONFIG_NAMED, - paths.SYSCONFIG_ODS, - paths.ETC_SYSCONFIG_AUTHCONFIG, -diff --git a/ipaserver/install/odsexporterinstance.py b/ipaserver/install/odsexporterinstance.py -index c37095cfc3bba8c6724f45d23293bdf6f4a200ee..248943d6c0ca4b71815bcf7526d575842f6ce426 100644 ---- a/ipaserver/install/odsexporterinstance.py -+++ b/ipaserver/install/odsexporterinstance.py -@@ -86,7 +86,7 @@ class ODSExporterInstance(service.Service): - root_logger.error("DNSKeyExporter service already exists") - - def __setup_key_exporter(self): -- installutils.set_directive(paths.SYSOCNFIG_IPA_ODS_EXPORTER, -+ installutils.set_directive(paths.SYSCONFIG_IPA_ODS_EXPORTER, - 'SOFTHSM2_CONF', - paths.DNSSEC_SOFTHSM2_CONF, - quotes=False, separator='=') --- -2.4.3 - diff --git a/SOURCES/0069-cert-speed-up-cert-find.patch b/SOURCES/0069-cert-speed-up-cert-find.patch new file mode 100644 index 0000000..ecd9d83 --- /dev/null +++ b/SOURCES/0069-cert-speed-up-cert-find.patch @@ -0,0 +1,479 @@ +From be32fd1d727fc8398dd51fa0fd3f404ef451281a Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Mon, 1 Aug 2016 09:53:39 +0200 +Subject: [PATCH] cert: speed up cert-find + +Use issuer+serial rather than raw DER blob to identify certificates in +cert-find's intermediate result. + +Restructure the code to make it (hopefully) easier to follow. + +https://fedorahosted.org/freeipa/ticket/6098 + +Reviewed-By: Martin Basti +Reviewed-By: Pavel Vomacka +--- + ipaserver/plugins/cert.py | 398 +++++++++++++++++++++++++--------------------- + 1 file changed, 216 insertions(+), 182 deletions(-) + +diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py +index 06041d3083565e8d093b610473d6083111d406d2..47dccf15a4010f2766642aedd2cc16e0a1eb1dd4 100644 +--- a/ipaserver/plugins/cert.py ++++ b/ipaserver/plugins/cert.py +@@ -21,6 +21,7 @@ + + import base64 + import binascii ++import collections + import datetime + import os + +@@ -295,18 +296,24 @@ class BaseCertObject(Object): + ), + ) + +- def _parse(self, obj): +- cert = x509.load_certificate(obj['certificate']) +- obj['subject'] = DN(unicode(cert.subject)) +- obj['issuer'] = DN(unicode(cert.issuer)) +- obj['valid_not_before'] = unicode(cert.valid_not_before_str) +- obj['valid_not_after'] = unicode(cert.valid_not_after_str) +- obj['md5_fingerprint'] = unicode( +- nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0]) +- obj['sha1_fingerprint'] = unicode( +- nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0]) +- obj['serial_number'] = cert.serial_number +- obj['serial_number_hex'] = u'0x%X' % cert.serial_number ++ def _parse(self, obj, full=True): ++ cert = obj.get('certificate') ++ if cert is not None: ++ cert = x509.load_certificate(cert) ++ obj['subject'] = DN(unicode(cert.subject)) ++ obj['issuer'] = DN(unicode(cert.issuer)) ++ obj['serial_number'] = cert.serial_number ++ if full: ++ obj['valid_not_before'] = unicode(cert.valid_not_before_str) ++ obj['valid_not_after'] = unicode(cert.valid_not_after_str) ++ obj['md5_fingerprint'] = unicode( ++ nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0]) ++ obj['sha1_fingerprint'] = unicode( ++ nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0]) ++ ++ serial_number = obj.get('serial_number') ++ if serial_number is not None: ++ obj['serial_number_hex'] = u'0x%X' % serial_number + + + class BaseCertMethod(Method): +@@ -691,10 +698,14 @@ class cert(BaseCertObject): + yield self.api.Object[name] + + def _fill_owners(self, obj): ++ dns = obj.pop('owner', None) ++ if dns is None: ++ return ++ + for owner in self._owners(): + container_dn = DN(owner.container_dn, self.api.env.basedn) + name = 'owner_' + owner.name +- for dn in obj['owner']: ++ for dn in dns: + if dn.endswith(container_dn, 1): + value = owner.get_primary_key_from_dn(dn) + obj.setdefault(name, []).append(value) +@@ -776,9 +787,7 @@ class cert_show(Retrieve, CertMethod, VirtualCommand): + result['certificate'] = result['certificate'].replace('\r\n', '') + self.obj._parse(result) + result['revoked'] = ('revocation_reason' in result) +- if 'owner' in result: +- self.obj._fill_owners(result) +- del result['owner'] ++ self.obj._fill_owners(result) + + if hostname: + # If we have a hostname we want to verify that the subject +@@ -984,36 +993,171 @@ class cert_find(Search, CertMethod): + label=owner.object_name, + ) + +- def execute(self, criteria=None, all=False, raw=False, pkey_only=False, +- no_members=True, timelimit=None, sizelimit=None, **options): +- ca_options = {'cacn', +- 'revocation_reason', +- 'issuer', +- 'subject', +- 'min_serial_number', 'max_serial_number', +- 'exactly', +- 'validnotafter_from', 'validnotafter_to', +- 'validnotbefore_from', 'validnotbefore_to', +- 'issuedon_from', 'issuedon_to', +- 'revokedon_from', 'revokedon_to'} +- ldap_options = {prefix + owner.name +- for owner in self.obj._owners() +- for prefix in ('', 'no_')} +- has_ca_options = ( +- any(name in options for name in ca_options - {'exactly'}) or +- options['exactly']) +- has_ldap_options = any(name in options for name in ldap_options) +- has_cert_option = 'certificate' in options ++ def _get_cert_key(self, cert): ++ nss_cert = x509.load_certificate(cert, x509.DER) ++ ++ return (DN(unicode(nss_cert.issuer)), nss_cert.serial_number) ++ ++ def _get_cert_obj(self, cert, all, raw, pkey_only): ++ obj = {'certificate': unicode(base64.b64encode(cert))} ++ ++ full = not pkey_only and all ++ if not raw: ++ self.obj._parse(obj, full) ++ if not full: ++ del obj['certificate'] ++ ++ return obj ++ ++ def _cert_search(self, all, raw, pkey_only, **options): ++ result = collections.OrderedDict() ++ ++ try: ++ cert = options['certificate'] ++ except KeyError: ++ return result, False, False ++ ++ key = self._get_cert_key(cert) ++ ++ result[key] = self._get_cert_obj(cert, all, raw, pkey_only) ++ ++ return result, False, True ++ ++ def _ca_search(self, all, raw, pkey_only, sizelimit, exactly, **options): ++ ra_options = {} ++ for name in ('revocation_reason', ++ 'issuer', ++ 'subject', ++ 'min_serial_number', 'max_serial_number', ++ 'validnotafter_from', 'validnotafter_to', ++ 'validnotbefore_from', 'validnotbefore_to', ++ 'issuedon_from', 'issuedon_to', ++ 'revokedon_from', 'revokedon_to'): ++ try: ++ value = options[name] ++ except KeyError: ++ continue ++ if isinstance(value, datetime.datetime): ++ value = value.strftime(PKIDATE_FORMAT) ++ elif isinstance(value, DN): ++ value = unicode(value) ++ ra_options[name] = value ++ if sizelimit: ++ ra_options['sizelimit'] = sizelimit ++ if exactly: ++ ra_options['exactly'] = True ++ ++ result = collections.OrderedDict() ++ complete = bool(ra_options) + + try: + ca_enabled_check() + except errors.NotFound: +- if has_ca_options: ++ if ra_options: + raise +- ca_enabled = False ++ return result, False, complete ++ ++ ra = self.api.Backend.ra ++ for ra_obj in ra.find(ra_options): ++ issuer = DN(ra_obj['issuer']) ++ serial_number = ra_obj['serial_number'] ++ ++ if pkey_only: ++ obj = {'serial_number': serial_number} ++ else: ++ obj = ra_obj ++ obj['issuer'] = issuer ++ obj['subject'] = DN(ra_obj['subject']) ++ del obj['serial_number_hex'] ++ ++ if all: ++ ra_obj = ra.get_certificate(str(serial_number)) ++ if not raw: ++ obj['certificate'] = ( ++ ra_obj['certificate'].replace('\r\n', '')) ++ self.obj._parse(obj) ++ ++ result[issuer, serial_number] = obj ++ ++ return result, False, complete ++ ++ def _ldap_search(self, all, raw, pkey_only, no_members, timelimit, ++ sizelimit, **options): ++ ldap = self.api.Backend.ldap2 ++ ++ filters = [] ++ for owner in self.obj._owners(): ++ for prefix, rule in (('', ldap.MATCH_ALL), ++ ('no_', ldap.MATCH_NONE)): ++ try: ++ value = options[prefix + owner.name] ++ except KeyError: ++ continue ++ ++ filter = ldap.make_filter_from_attr( ++ 'objectclass', ++ owner.object_class, ++ ldap.MATCH_ALL) ++ if filter not in filters: ++ filters.append(filter) ++ ++ filter = ldap.make_filter_from_attr( ++ owner.primary_key.name, ++ value, ++ rule) ++ filters.append(filter) ++ ++ cert = options.get('certificate') ++ if cert is not None: ++ filter = ldap.make_filter_from_attr('usercertificate', cert) ++ filters.append(filter) ++ ++ result = collections.OrderedDict() ++ complete = bool(filters) ++ ++ if cert is None: ++ filter = '(usercertificate=*)' ++ filters.append(filter) ++ ++ filter = ldap.combine_filters(filters, ldap.MATCH_ALL) ++ try: ++ entries, truncated = ldap.find_entries( ++ base_dn=self.api.env.basedn, ++ filter=filter, ++ attrs_list=['usercertificate'], ++ time_limit=timelimit, ++ size_limit=sizelimit, ++ ) ++ except errors.EmptyResult: ++ entries = [] ++ truncated = False + else: +- ca_enabled = True ++ truncated = bool(truncated) ++ ++ for entry in entries: ++ for attr in ('usercertificate', 'usercertificate;binary'): ++ for cert in entry.get(attr, []): ++ key = self._get_cert_key(cert) ++ ++ try: ++ obj = result[key] ++ except KeyError: ++ obj = self._get_cert_obj(cert, all, raw, pkey_only) ++ result[key] = obj + ++ if not pkey_only and (all or not no_members): ++ owners = obj.setdefault('owner', []) ++ if entry.dn not in owners: ++ owners.append(entry.dn) ++ ++ if not raw: ++ for obj in six.itervalues(result): ++ self.obj._fill_owners(obj) ++ ++ return result, truncated, complete ++ ++ def execute(self, criteria=None, all=False, raw=False, pkey_only=False, ++ no_members=True, timelimit=None, sizelimit=None, **options): + if 'cacn' in options: + ca_obj = api.Command.ca_show(options['cacn'])['result'] + ca_sdn = unicode(ca_obj['ipacasubjectdn'][0]) +@@ -1028,153 +1172,43 @@ class cert_find(Search, CertMethod): + if criteria is not None: + return dict(result=[], count=0, truncated=False) + +- obj_seq = [] +- obj_dict = {} ++ result = collections.OrderedDict() + truncated = False +- +- if has_cert_option: +- cert = options['certificate'] +- obj = {'certificate': unicode(base64.b64encode(cert))} +- obj_seq.append(obj) +- obj_dict[cert] = obj +- +- if ca_enabled: +- ra_options = {} +- for name, value in options.items(): +- if name not in ca_options: +- continue +- if isinstance(value, datetime.datetime): +- value = value.strftime(PKIDATE_FORMAT) +- elif isinstance(value, DN): +- value = unicode(value) +- ra_options[name] = value +- if sizelimit is not None: +- if sizelimit != 0: +- ra_options['sizelimit'] = sizelimit +- sizelimit = 0 +- has_ca_options = True +- +- for ra_obj in self.Backend.ra.find(ra_options): +- obj = {} +- if ((not pkey_only and all) or +- not no_members or +- not has_ca_options or +- has_ldap_options or +- has_cert_option): +- ra_obj.update( +- self.Backend.ra.get_certificate( +- str(ra_obj['serial_number']))) +- cert = base64.b64decode(ra_obj['certificate']) +- try: +- obj = obj_dict[cert] +- except KeyError: +- if has_cert_option: +- continue +- obj = {} +- obj_seq.append(obj) +- obj_dict[cert] = obj ++ complete = False ++ ++ for sub_search in (self._cert_search, ++ self._ca_search, ++ self._ldap_search): ++ sub_result, sub_truncated, sub_complete = sub_search( ++ all=all, ++ raw=raw, ++ pkey_only=pkey_only, ++ no_members=no_members, ++ timelimit=timelimit, ++ sizelimit=sizelimit, ++ **options) ++ ++ if sub_complete: ++ sizelimit = None ++ ++ for key in tuple(result): ++ if key not in sub_result: ++ del result[key] ++ ++ for key, sub_obj in six.iteritems(sub_result): ++ try: ++ obj = result[key] ++ except KeyError: ++ if complete: ++ continue ++ result[key] = sub_obj + else: +- obj_seq.append(obj) +- obj.update(ra_obj) +- +- if ((not pkey_only and all) or +- not no_members or +- not has_ca_options or +- has_ldap_options or +- has_cert_option): +- ldap = self.api.Backend.ldap2 ++ obj.update(sub_obj) + +- filters = [] +- if 'certificate' in options: +- cert_filter = ldap.make_filter_from_attr( +- 'usercertificate', options['certificate']) +- else: +- cert_filter = '(usercertificate=*)' +- filters.append(cert_filter) +- for owner in self.obj._owners(): +- oc_filter = ldap.make_filter_from_attr( +- 'objectclass', owner.object_class, ldap.MATCH_ALL) +- for prefix, rule in (('', ldap.MATCH_ALL), +- ('no_', ldap.MATCH_NONE)): +- value = options.get(prefix + owner.name) +- if value is None: +- continue +- pkey_filter = ldap.make_filter_from_attr( +- owner.primary_key.name, value, rule) +- filters.append(oc_filter) +- filters.append(pkey_filter) +- filter = ldap.combine_filters(filters, ldap.MATCH_ALL) ++ truncated = truncated or sub_truncated ++ complete = complete or sub_complete + +- try: +- entries, truncated = ldap.find_entries( +- base_dn=self.api.env.basedn, +- filter=filter, +- attrs_list=['usercertificate'], +- time_limit=timelimit, +- size_limit=sizelimit, +- ) +- except errors.EmptyResult: +- entries, truncated = [], False +- for entry in entries: +- seen = set() +- for attr in ('usercertificate', 'usercertificate;binary'): +- for cert in entry.get(attr, []): +- if cert in seen: +- continue +- seen.add(cert) +- try: +- obj = obj_dict[cert] +- except KeyError: +- if has_ca_options or has_cert_option: +- continue +- obj = { +- 'certificate': unicode(base64.b64encode(cert))} +- obj_seq.append(obj) +- obj_dict[cert] = obj +- obj.setdefault('owner', []).append(entry.dn) +- +- result = [] +- for obj in obj_seq: +- if has_ldap_options and 'owner' not in obj: +- continue +- if not pkey_only: +- if not raw: +- if 'certificate' in obj: +- obj['certificate'] = ( +- obj['certificate'].replace('\r\n', '')) +- self.obj._parse(obj) +- if not all: +- del obj['certificate'] +- del obj['valid_not_before'] +- del obj['valid_not_after'] +- del obj['md5_fingerprint'] +- del obj['sha1_fingerprint'] +- if 'subject' in obj: +- obj['subject'] = DN(obj['subject']) +- if 'issuer' in obj: +- obj['issuer'] = DN(obj['issuer']) +- if 'status' in obj: +- obj['revoked'] = ( +- obj['status'] in (u'REVOKED', u'REVOKED_EXPIRED')) +- if 'owner' in obj: +- if all or not no_members: +- self.obj._fill_owners(obj) +- del obj['owner'] +- else: +- if 'certificate' in obj: +- if not all: +- del obj['certificate'] +- if 'owner' in obj: +- if not all and no_members: +- del obj['owner'] +- else: +- if 'serial_number' in obj: +- serial_number = obj['serial_number'] +- obj.clear() +- obj['serial_number'] = serial_number +- else: +- obj.clear() +- result.append(obj) ++ result = list(six.itervalues(result)) + + ret = dict( + result=result +-- +2.7.4 + diff --git a/SOURCES/0069-ipa-backup-archive-DNSSEC-zone-file-and-kasp.db.patch b/SOURCES/0069-ipa-backup-archive-DNSSEC-zone-file-and-kasp.db.patch deleted file mode 100644 index f63f3b5..0000000 --- a/SOURCES/0069-ipa-backup-archive-DNSSEC-zone-file-and-kasp.db.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 4d2932189ca9426492b2a69809e27c7aaca5e618 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Thu, 13 Aug 2015 15:05:36 +0200 -Subject: [PATCH] ipa-backup: archive DNSSEC zone file and kasp.db - -https://fedorahosted.org/freeipa/ticket/5159 - -Reviewed-By: Martin Basti ---- - ipaserver/install/ipa_backup.py | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py -index 1bb6f810b16c8344ab957dd6259983189a88e89f..d7afb3654b09e88321f1ce9f279749b19c2f6414 100644 ---- a/ipaserver/install/ipa_backup.py -+++ b/ipaserver/install/ipa_backup.py -@@ -171,6 +171,8 @@ class Backup(admintool.AdminTool): - paths.SVC_LIST_FILE, - paths.OPENDNSSEC_CONF_FILE, - paths.OPENDNSSEC_KASP_FILE, -+ paths.OPENDNSSEC_ZONELIST_FILE, -+ paths.OPENDNSSEC_KASP_DB, - paths.DNSSEC_SOFTHSM2_CONF, - paths.DNSSEC_SOFTHSM_PIN_SO, - paths.IPA_ODS_EXPORTER_KEYTAB, --- -2.4.3 - diff --git a/SOURCES/0070-baseldap-Allow-overriding-member-param-label-in-LDAP.patch b/SOURCES/0070-baseldap-Allow-overriding-member-param-label-in-LDAP.patch deleted file mode 100644 index 87b97f6..0000000 --- a/SOURCES/0070-baseldap-Allow-overriding-member-param-label-in-LDAP.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 1dfdb32cbd73a3b1144645c0208fee88b3530172 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Mon, 17 Aug 2015 09:39:21 +0200 -Subject: [PATCH] baseldap: Allow overriding member param label in - LDAPModMember - -https://fedorahosted.org/freeipa/ticket/5214 - -Reviewed-By: Petr Vobornik ---- - ipalib/plugins/baseldap.py | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py -index 36a5d5f4918828a97b0b30d4613819f777722de8..31f38946afcbb51638bcab68a6e74ec309eba0e4 100644 ---- a/ipalib/plugins/baseldap.py -+++ b/ipalib/plugins/baseldap.py -@@ -1652,6 +1652,7 @@ class LDAPModMember(LDAPQuery): - """ - member_attributes = ['member'] - member_param_doc = _('%s') -+ member_param_label = _('member %s') - member_count_out = ('%i member processed.', '%i members processed.') - - def get_options(self): -@@ -1662,9 +1663,9 @@ class LDAPModMember(LDAPQuery): - ldap_obj = self.api.Object[ldap_obj_name] - name = to_cli(ldap_obj_name) - doc = self.member_param_doc % ldap_obj.object_name_plural -+ label = self.member_param_label % ldap_obj.object_name - yield Str('%s*' % name, cli_name='%ss' % name, doc=doc, -- label=_('member %s') % ldap_obj.object_name, -- csv=True, alwaysask=True) -+ label=label, csv=True, alwaysask=True) - - def get_member_dns(self, **options): - dns = {} --- -2.4.3 - diff --git a/SOURCES/0070-cert-do-not-crash-on-invalid-data-in-cert-find.patch b/SOURCES/0070-cert-do-not-crash-on-invalid-data-in-cert-find.patch new file mode 100644 index 0000000..d1dba4e --- /dev/null +++ b/SOURCES/0070-cert-do-not-crash-on-invalid-data-in-cert-find.patch @@ -0,0 +1,81 @@ +From adb6802b1b4dec30f19c3bf76089b6bc60ac0454 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Mon, 1 Aug 2016 09:55:58 +0200 +Subject: [PATCH] cert: do not crash on invalid data in cert-find + +https://fedorahosted.org/freeipa/ticket/6150 + +Reviewed-By: Martin Basti +Reviewed-By: Pavel Vomacka +--- + ipaserver/plugins/cert.py | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py +index 47dccf15a4010f2766642aedd2cc16e0a1eb1dd4..b8df074a186ca91daa8e8f5e725724ea7bc5a663 100644 +--- a/ipaserver/plugins/cert.py ++++ b/ipaserver/plugins/cert.py +@@ -32,7 +32,7 @@ import six + + from ipalib import Command, Str, Int, Flag + from ipalib import api +-from ipalib import errors ++from ipalib import errors, messages + from ipalib import pkcs10 + from ipalib import x509 + from ipalib import ngettext +@@ -994,7 +994,15 @@ class cert_find(Search, CertMethod): + ) + + def _get_cert_key(self, cert): +- nss_cert = x509.load_certificate(cert, x509.DER) ++ try: ++ nss_cert = x509.load_certificate(cert, x509.DER) ++ except NSPRError as e: ++ message = messages.SearchResultTruncated( ++ reason=_("failed to load certificate: %s") % e, ++ ) ++ self.add_message(message) ++ ++ raise ValueError("failed to load certificate") + + return (DN(unicode(nss_cert.issuer)), nss_cert.serial_number) + +@@ -1017,7 +1025,10 @@ class cert_find(Search, CertMethod): + except KeyError: + return result, False, False + +- key = self._get_cert_key(cert) ++ try: ++ key = self._get_cert_key(cert) ++ except ValueError: ++ return result, True, True + + result[key] = self._get_cert_obj(cert, all, raw, pkey_only) + +@@ -1132,12 +1143,21 @@ class cert_find(Search, CertMethod): + entries = [] + truncated = False + else: ++ try: ++ ldap.handle_truncated_result(truncated) ++ except errors.LimitsExceeded as e: ++ self.add_message(messages.SearchResultTruncated(reason=e)) ++ + truncated = bool(truncated) + + for entry in entries: + for attr in ('usercertificate', 'usercertificate;binary'): + for cert in entry.get(attr, []): +- key = self._get_cert_key(cert) ++ try: ++ key = self._get_cert_key(cert) ++ except ValueError: ++ truncated = True ++ continue + + try: + obj = result[key] +-- +2.7.4 + diff --git a/SOURCES/0071-Add-warning-about-only-one-existing-CA-server.patch b/SOURCES/0071-Add-warning-about-only-one-existing-CA-server.patch new file mode 100644 index 0000000..2526f30 --- /dev/null +++ b/SOURCES/0071-Add-warning-about-only-one-existing-CA-server.patch @@ -0,0 +1,151 @@ +From 7767a6befe2cc461cd6b8aadff1626108e3101b0 Mon Sep 17 00:00:00 2001 +From: Pavel Vomacka +Date: Tue, 16 Aug 2016 10:03:36 +0200 +Subject: [PATCH] Add warning about only one existing CA server + +It is not safe to have only one CA server in topology. Therefore there is a check +and in case that there is only one CA server a warning is shown. The warning is +shown after each refreshing of servers facet. + +https://fedorahosted.org/freeipa/ticket/5828 + +Reviewed-By: Tomas Krizek +--- + install/ui/src/freeipa/topology.js | 73 +++++++++++++++++++++++++++++++++++++- + install/ui/test/data/ipa_init.json | 2 ++ + ipaserver/plugins/internal.py | 2 ++ + 3 files changed, 76 insertions(+), 1 deletion(-) + +diff --git a/install/ui/src/freeipa/topology.js b/install/ui/src/freeipa/topology.js +index 7e501eb3506587ea653497d2806938890066e4f0..c33adba9a3c704b66b85689dd18e927ab975d2fe 100644 +--- a/install/ui/src/freeipa/topology.js ++++ b/install/ui/src/freeipa/topology.js +@@ -28,13 +28,14 @@ define([ + './facets/Facet', + './topology_graph', + './navigation', ++ './widget', + // plain imports + './search', + './entity'], + function(lang, declare, Evented, Stateful, Deferred, on, all, when, + builder, IPA, $, menu, metadata_provider, phases, reg, rpc, + text, mod_details, mod_facet, mod_field, ActionMixin, +- HeaderMixin, Facet, topology_graph, navigation) { ++ HeaderMixin, Facet, topology_graph, navigation, widget_mod) { + /** + * Topology module + * @class +@@ -206,6 +207,7 @@ return { + facets: [ + { + $type: 'search', ++ $factory: topology.servers_search_facet, + no_update: true, + disable_facet_tabs: false, + tabs_in_sidebar: true, +@@ -483,6 +485,75 @@ topology.location_adapter = declare([mod_field.Adapter], { + } + }); + ++topology.servers_search_facet = function(spec, no_init) { ++ spec = spec || {}; ++ ++ var that = IPA.search_facet(spec); ++ ++ that.create_get_records_command = function(pkeys, on_success, on_error) { ++ ++ var on_success_extended = function(data, text_status, xhr) { ++ // Call original on_success handler ++ on_success(data, text_status, xhr); ++ ++ var result = data.result.results; ++ var counter = 0; ++ ++ for (var i=0, l=result.length; i -Date: Mon, 17 Aug 2015 09:39:48 +0200 -Subject: [PATCH] vault: Fix param labels in output of vault owner commands - -https://fedorahosted.org/freeipa/ticket/5214 - -Reviewed-By: Petr Vobornik ---- - ipalib/plugins/vault.py | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index 01c6096335d47b337253d4f2d1e0571200383c7a..b5a12d5c3da599d7f5afaed90f579ad3a23c27cd 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -314,6 +314,11 @@ class vault(LDAPObject): - label=_('Owner services'), - flags=['no_create', 'no_update', 'no_search'], - ), -+ Str( -+ 'owner?', -+ label=_('Failed owners'), -+ flags=['no_create', 'no_update', 'no_search'], -+ ), - ) - - def get_dn(self, *keys, **options): -@@ -1420,6 +1425,11 @@ class VaultModMember(LDAPModMember): - options.pop('service', None) - return super(VaultModMember, self).get_member_dns(**options) - -+ def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): -+ for fail in failed.itervalues(): -+ fail['services'] = fail.pop('service', []) -+ return completed, dn -+ - - @register() - class vault_add_owner(VaultModMember, LDAPAddMember): -@@ -1428,6 +1438,7 @@ class vault_add_owner(VaultModMember, LDAPAddMember): - takes_options = LDAPAddMember.takes_options + vault_options - - member_attributes = ['owner'] -+ member_param_label = _('owner %s') - member_count_out = ('%i owner added.', '%i owners added.') - - has_output = ( -@@ -1452,6 +1463,7 @@ class vault_remove_owner(VaultModMember, LDAPRemoveMember): - takes_options = LDAPRemoveMember.takes_options + vault_options - - member_attributes = ['owner'] -+ member_param_label = _('owner %s') - member_count_out = ('%i owner removed.', '%i owners removed.') - - has_output = ( --- -2.4.3 - diff --git a/SOURCES/0072-Fixed-vault-container-ownership.patch b/SOURCES/0072-Fixed-vault-container-ownership.patch deleted file mode 100644 index 284f9ac..0000000 --- a/SOURCES/0072-Fixed-vault-container-ownership.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 82738f7ef90586668761a4f1215a734ab8c25f5a Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Mon, 10 Aug 2015 20:57:58 +0200 -Subject: [PATCH] Fixed vault container ownership. - -The vault-add command has been fixed such that if the user/service -private vault container does not exist yet it will be created and -owned by the user/service instead of the vault creator. - -https://fedorahosted.org/freeipa/ticket/5194 - -Reviewed-By: Petr Vobornik ---- - ipalib/plugins/vault.py | 27 ++++++++++++++++++++++++--- - 1 file changed, 24 insertions(+), 3 deletions(-) - -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index b5a12d5c3da599d7f5afaed90f579ad3a23c27cd..88c63071f04462aa240a70d3a3eeac2d04e66062 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -704,12 +704,33 @@ class vault_add_internal(LDAPCreate): - else: - owner_dn = self.api.Object.user.get_dn(name) - -+ parent_dn = DN(*dn[1:]) -+ -+ container_dn = DN(self.api.Object.vault.container_dn, -+ self.api.env.basedn) -+ -+ services_dn = DN(('cn', 'services'), container_dn) -+ users_dn = DN(('cn', 'users'), container_dn) -+ -+ if dn.endswith(services_dn): -+ # service container should be owned by the service -+ service = parent_dn[0]['cn'] -+ parent_owner_dn = self.api.Object.service.get_dn(service) -+ -+ elif dn.endswith(users_dn): -+ # user container should be owned by the user -+ user = parent_dn[0]['cn'] -+ parent_owner_dn = self.api.Object.user.get_dn(user) -+ -+ else: -+ parent_owner_dn = owner_dn -+ - try: -- parent_dn = DN(*dn[1:]) -- self.obj.create_container(parent_dn, owner_dn) -- except errors.DuplicateEntry, e: -+ self.obj.create_container(parent_dn, parent_owner_dn) -+ except errors.DuplicateEntry as e: - pass - -+ # vault should be owned by the creator - entry_attrs['owner'] = owner_dn - - return dn --- -2.4.3 - diff --git a/SOURCES/0072-Set-servers-list-as-default-facet-in-topology-facet-.patch b/SOURCES/0072-Set-servers-list-as-default-facet-in-topology-facet-.patch new file mode 100644 index 0000000..a19800c --- /dev/null +++ b/SOURCES/0072-Set-servers-list-as-default-facet-in-topology-facet-.patch @@ -0,0 +1,32 @@ +From 9f684d883f21747ba413bf456cca114e67c1e53a Mon Sep 17 00:00:00 2001 +From: Pavel Vomacka +Date: Tue, 16 Aug 2016 10:06:28 +0200 +Subject: [PATCH] Set servers list as default facet in topology facet group + +Since there is a new warning about only one CA server, the default facet +of topology facet group is set to servers list where the warning is. +So the warning will be shown right after clicking on Topology section. + +Part of: https://fedorahosted.org/freeipa/ticket/5828 + +Reviewed-By: Tomas Krizek +--- + install/ui/src/freeipa/navigation/menu_spec.js | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/install/ui/src/freeipa/navigation/menu_spec.js b/install/ui/src/freeipa/navigation/menu_spec.js +index 108f4577f7e1326b9c9bc495c54f6e1f12a0cce6..1abd7204f9d7cc2f6e9f840eb026ea78841ce438 100644 +--- a/install/ui/src/freeipa/navigation/menu_spec.js ++++ b/install/ui/src/freeipa/navigation/menu_spec.js +@@ -212,7 +212,7 @@ var nav = {}; + ] + }, + { +- entity: 'topologysuffix', ++ entity: 'server', + label: '@i18n:tabs.topology', + facet: 'search', + children: [ +-- +2.7.4 + diff --git a/SOURCES/0073-schema-cache-Do-not-reset-ServerInfo-dirty-flag.patch b/SOURCES/0073-schema-cache-Do-not-reset-ServerInfo-dirty-flag.patch new file mode 100644 index 0000000..e283fb8 --- /dev/null +++ b/SOURCES/0073-schema-cache-Do-not-reset-ServerInfo-dirty-flag.patch @@ -0,0 +1,32 @@ +From 2ee7cd65c678f310154775d69bc0d044b8ad881a Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Thu, 4 Aug 2016 16:02:24 +0200 +Subject: [PATCH] schema cache: Do not reset ServerInfo dirty flag + +Once dirty flag is set to True it must not be set back to False. +Otherwise changes are not written back to file. + +https://fedorahosted.org/freeipa/ticket/6048 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/schema.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index 5264d4cc177ba457c517f93f203e0baca7b0ac01..b49ccbb7f7905e2561598d66beca6d8b1d5ed48e 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -401,7 +401,8 @@ class ServerInfo(collections.MutableMapping): + return self._dict[key] + + def __setitem__(self, key, value): +- self._dirty = key not in self._dict or self._dict[key] != value ++ if key not in self._dict or self._dict[key] != value: ++ self._dirty = True + self._dict[key] = value + + def __delitem__(self, key): +-- +2.7.4 + diff --git a/SOURCES/0073-vault-normalize-service-principal-in-service-vault-o.patch b/SOURCES/0073-vault-normalize-service-principal-in-service-vault-o.patch deleted file mode 100644 index 328a3da..0000000 --- a/SOURCES/0073-vault-normalize-service-principal-in-service-vault-o.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 9e930edf8b3b4e65bf39043e7b033f0b5537b7e3 Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Tue, 18 Aug 2015 12:14:36 +0200 -Subject: [PATCH] vault: normalize service principal in service vault - operations - -https://fedorahosted.org/freeipa/ticket/5233 - -Reviewed-By: Jan Cholasta ---- - ipalib/plugins/vault.py | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index 88c63071f04462aa240a70d3a3eeac2d04e66062..a1508b63b8c8aa506eadad415ecf7fa4942c74fc 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -47,6 +47,7 @@ from ipalib.plugins.baseldap import LDAPObject, LDAPCreate, LDAPDelete,\ - LDAPModMember, pkey_to_value - from ipalib.request import context - from ipalib.plugins.user import split_principal -+from ipalib.plugins.service import normalize_principal - from ipalib import _, ngettext - from ipaplatform.paths import paths - from ipapython.dn import DN -@@ -214,6 +215,7 @@ vault_options = ( - Str( - 'service?', - doc=_('Service name of the service vault'), -+ normalizer=normalize_principal, - ), - Flag( - 'shared?', --- -2.4.3 - diff --git a/SOURCES/0074-schema-cache-Do-not-read-fingerprint-and-format-from.patch b/SOURCES/0074-schema-cache-Do-not-read-fingerprint-and-format-from.patch new file mode 100644 index 0000000..e7bc841 --- /dev/null +++ b/SOURCES/0074-schema-cache-Do-not-read-fingerprint-and-format-from.patch @@ -0,0 +1,86 @@ +From 5138ff563b1ac870ecc77485c200d839e17622a8 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Thu, 4 Aug 2016 16:07:08 +0200 +Subject: [PATCH] schema cache: Do not read fingerprint and format from cache + +Fingerprint can be obtained from schema filename of from ServerInfo +instance. Use FORMAT in path to avoid openening schema just to read its +format. + +https://fedorahosted.org/freeipa/ticket/6048 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/schema.py | 29 +++++------------------------ + 1 file changed, 5 insertions(+), 24 deletions(-) + +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index b49ccbb7f7905e2561598d66beca6d8b1d5ed48e..c62b74408b448faf794ed9e2b315b03fc1a5a315 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -19,6 +19,7 @@ from ipalib import errors, parameters, plugable + from ipalib.frontend import Object + from ipalib.output import Output + from ipalib.parameters import DefaultFrom, Flag, Password, Str ++from ipapython.ipautil import fsdecode + from ipapython.dn import DN + from ipapython.dnsutil import DNSName + from ipapython.ipa_log_manager import log_mgr +@@ -437,7 +438,7 @@ class Schema(object): + + """ + namespaces = {'classes', 'commands', 'topics'} +- _DIR = os.path.join(USER_CACHE_PATH, 'ipa', 'schema') ++ _DIR = os.path.join(USER_CACHE_PATH, 'ipa', 'schema', FORMAT) + + def __init__(self, api, server_info, client): + self._dict = {} +@@ -483,34 +484,14 @@ class Schema(object): + path = os.path.join(self._DIR, filename) + return _LockedZipFile(path, mode) + +- def _get_schema_fingerprint(self, schema): +- try: +- fmt = json.loads(schema.read('format')) +- except KeyError: +- fmt = '0' +- +- if fmt != FORMAT: +- raise RuntimeError('invalid format') +- +- return json.loads(schema.read('fingerprint')) +- + def _fetch(self, client): + if not client.isconnected(): + client.connect(verbose=False) + +- fps = [] + try: +- files = os.listdir(self._DIR) ++ fps = [fsdecode(f) for f in os.listdir(self._DIR)] + except EnvironmentError: +- pass +- else: +- for filename in files: +- try: +- with self._open_schema(filename, 'r') as schema: +- fps.append( +- unicode(self._get_schema_fingerprint(schema))) +- except Exception: +- continue ++ fps = [] + + kwargs = {u'version': u'2.170'} + if fps: +@@ -537,7 +518,7 @@ class Schema(object): + + def _read_schema(self): + with self._open_schema(self._fingerprint, 'r') as schema: +- self._dict['fingerprint'] = self._get_schema_fingerprint(schema) ++ self._dict['fingerprint'] = self._fingerprint + + for name in schema.namelist(): + ns, _slash, key = name.partition('/') +-- +2.7.4 + diff --git a/SOURCES/0074-vault-validate-vault-type.patch b/SOURCES/0074-vault-validate-vault-type.patch deleted file mode 100644 index 5440f69..0000000 --- a/SOURCES/0074-vault-validate-vault-type.patch +++ /dev/null @@ -1,87 +0,0 @@ -From fc704bf5248ae3b224ce5066231bb826008f375d Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Tue, 18 Aug 2015 12:50:54 +0200 -Subject: [PATCH] vault: validate vault type - -https://fedorahosted.org/freeipa/ticket/5211 - -Reviewed-By: Jan Cholasta ---- - API.txt | 6 +++--- - VERSION | 4 ++-- - ipalib/plugins/vault.py | 5 +++-- - 3 files changed, 8 insertions(+), 7 deletions(-) - -diff --git a/API.txt b/API.txt -index 71df3a56595a012e6382414ad4453d30ede8155b..a39b22b602e0baf5d283732d18d83b2a25d5cf50 100644 ---- a/API.txt -+++ b/API.txt -@@ -5423,7 +5423,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui - option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=False) - option: Bytes('ipavaultpublickey', attribute=True, cli_name='public_key', multivalue=False, required=False) - option: Bytes('ipavaultsalt', attribute=True, cli_name='salt', multivalue=False, required=False) --option: Str('ipavaulttype', attribute=True, autofill=True, cli_name='type', default=u'standard', multivalue=False, required=False) -+option: StrEnum('ipavaulttype', attribute=True, autofill=True, cli_name='type', default=u'standard', multivalue=False, required=False, values=(u'standard', u'symmetric', u'asymmetric')) - option: Flag('no_members', autofill=True, default=False, exclude='webui') - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') - option: Str('service?') -@@ -5513,7 +5513,7 @@ arg: Str('criteria?', noextrawhitespace=False) - option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') - option: Str('cn', attribute=True, autofill=False, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=False) - option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False) --option: Str('ipavaulttype', attribute=True, autofill=False, cli_name='type', default=u'standard', multivalue=False, query=True, required=False) -+option: StrEnum('ipavaulttype', attribute=True, autofill=False, cli_name='type', default=u'standard', multivalue=False, query=True, required=False, values=(u'standard', u'symmetric', u'asymmetric')) - option: Flag('no_members', autofill=True, default=False, exclude='webui') - option: Flag('pkey_only?', autofill=True, default=False) - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') -@@ -5536,7 +5536,7 @@ option: Str('delattr*', cli_name='delattr', exclude='webui') - option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, required=False) - option: Bytes('ipavaultpublickey', attribute=True, autofill=False, cli_name='public_key', multivalue=False, required=False) - option: Bytes('ipavaultsalt', attribute=True, autofill=False, cli_name='salt', multivalue=False, required=False) --option: Str('ipavaulttype', attribute=True, autofill=False, cli_name='type', default=u'standard', multivalue=False, required=False) -+option: StrEnum('ipavaulttype', attribute=True, autofill=False, cli_name='type', default=u'standard', multivalue=False, required=False, values=(u'standard', u'symmetric', u'asymmetric')) - option: Flag('no_members', autofill=True, default=False, exclude='webui') - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') - option: Flag('rights', autofill=True, default=False) -diff --git a/VERSION b/VERSION -index 69351a8fa8e27c884c130ab49d3fab541cd09ff9..6569eeb70fa4e8065b5abb9dc89bd4cc6d42bd15 100644 ---- a/VERSION -+++ b/VERSION -@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 - # # - ######################################################## - IPA_API_VERSION_MAJOR=2 --IPA_API_VERSION_MINOR=149 --# Last change: edewata - Added CLI param and ACL for vault service operations -+IPA_API_VERSION_MINOR=150 -+# Last change: pvoborni - change type of vault type option to StrEnum -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index a1508b63b8c8aa506eadad415ecf7fa4942c74fc..4d430ee88658e7ba7f2863ca4ef1e8672e298923 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -38,7 +38,7 @@ import krbV - - from ipalib.frontend import Command, Object, Local - from ipalib import api, errors --from ipalib import Bytes, Str, Flag -+from ipalib import Bytes, Flag, Str, StrEnum - from ipalib import output - from ipalib.crud import PKQuery, Retrieve, Update - from ipalib.plugable import Registry -@@ -279,11 +279,12 @@ class vault(LDAPObject): - label=_('Description'), - doc=_('Vault description'), - ), -- Str( -+ StrEnum( - 'ipavaulttype?', - cli_name='type', - label=_('Type'), - doc=_('Vault type'), -+ values=(u'standard', u'symmetric', u'asymmetric', ), - default=u'standard', - autofill=True, - ), --- -2.4.3 - diff --git a/SOURCES/0075-Access-data-for-help-separately.patch b/SOURCES/0075-Access-data-for-help-separately.patch new file mode 100644 index 0000000..182c526 --- /dev/null +++ b/SOURCES/0075-Access-data-for-help-separately.patch @@ -0,0 +1,121 @@ +From e91392536994ce3167a1f025e819926ba6de299f Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Thu, 4 Aug 2016 16:14:33 +0200 +Subject: [PATCH] Access data for help separately + +To avoid the need to read all data for a plugin from cache and actualy +use the separately stored help data it must be requested and returned +separately. + +https://fedorahosted.org/freeipa/ticket/6048 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/schema.py | 37 ++++++++++++++++++------------------- + 1 file changed, 18 insertions(+), 19 deletions(-) + +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index c62b74408b448faf794ed9e2b315b03fc1a5a315..c72109ac3bb9b7a71f9cbc056eaf3a4d8371d035 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -114,10 +114,9 @@ class _SchemaPlugin(object): + if self._class is not None: + return self._class.summary + else: +- self._schema.load_help() +- schema = self._schema[self.schema_key][self.full_name] ++ halp = self._schema[self.schema_key].get_help(self.full_name) + try: +- return schema['summary'] ++ return halp['summary'] + except KeyError: + return u'<%s>' % self.full_name + +@@ -244,10 +243,9 @@ class _SchemaCommandPlugin(_SchemaPlugin): + if self._class is not None: + return self._class.topic + else: +- self._schema.load_help() +- schema = self._schema[self.schema_key][self.full_name] ++ halp = self._schema[self.schema_key].get_help(self.full_name) + try: +- return str(schema['topic_topic']).partition('/')[0] ++ return str(halp['topic_topic']).partition('/')[0] + except KeyError: + return None + +@@ -256,9 +254,8 @@ class _SchemaCommandPlugin(_SchemaPlugin): + if self._class is not None: + return self._class.NO_CLI + else: +- self._schema.load_help() +- schema = self._schema[self.schema_key][self.full_name] +- return 'cli' in schema.get('exclude', []) ++ halp = self._schema[self.schema_key].get_help(self.full_name) ++ return 'cli' in halp.get('exclude', []) + + def _create_output(self, api, schema): + if schema.get('multivalue', False): +@@ -355,6 +352,12 @@ class _SchemaNameSpace(collections.Mapping): + def __len__(self): + return len(list(self._schema.iter_namespace(self.name))) + ++ def get_help(self, key): ++ try: ++ return self._schema.get_help(self.name, key) ++ except KeyError: ++ raise KeyError(key) ++ + + class NotAvailable(Exception): + pass +@@ -523,7 +526,7 @@ class Schema(object): + for name in schema.namelist(): + ns, _slash, key = name.partition('/') + if ns in self.namespaces: +- self._dict[ns][key] = {} ++ self._dict[ns][key] = None + + def __getitem__(self, key): + try: +@@ -557,7 +560,7 @@ class Schema(object): + os.makedirs(self._DIR) + except EnvironmentError as e: + if e.errno != errno.EEXIST: +- logger.warning("Failed ti write schema: {}".format(e)) ++ logger.warning("Failed to write schema: {}".format(e)) + return + + with self._open_schema(self._fingerprint, 'w') as schema: +@@ -580,24 +583,20 @@ class Schema(object): + def read_namespace_member(self, namespace, member): + value = self._dict[namespace][member] + +- if (not value) or ('full_name' not in value): ++ if value is None: + path = '{}/{}'.format(namespace, member) +- value = self._dict[namespace].setdefault( +- member, {} +- ).update(self._read(path)) ++ value = self._dict[namespace][member] = self._read(path) + + return value + + def iter_namespace(self, namespace): + return iter(self._dict[namespace]) + +- def load_help(self): ++ def get_help(self, namespace, member): + if not self._help: + self._help = self._read('_help') + +- for ns in self._help: +- for member in self._help[ns]: +- self._dict[ns][member].update(self._help[ns][member]) ++ return self._help[namespace][member] + + + def get_package(api, client): +-- +2.7.4 + diff --git a/SOURCES/0075-install-Fix-replica-install-with-custom-certificates.patch b/SOURCES/0075-install-Fix-replica-install-with-custom-certificates.patch deleted file mode 100644 index 6753e81..0000000 --- a/SOURCES/0075-install-Fix-replica-install-with-custom-certificates.patch +++ /dev/null @@ -1,43 +0,0 @@ -From c2a1e876492bc630d3d5f74a2482cf9c94be763d Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Tue, 18 Aug 2015 12:51:26 +0200 -Subject: [PATCH] install: Fix replica install with custom certificates - -https://fedorahosted.org/freeipa/ticket/5226 - -Reviewed-By: Martin Babinsky ---- - ipaserver/install/server/replicainstall.py | 17 +++++++++-------- - 1 file changed, 9 insertions(+), 8 deletions(-) - -diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py -index dd8bc0d4bb7d8d9835a3e3e4dc24d1f67199d28f..0725c7763e505ca0cc5a8892414a3c36c557cf1d 100644 ---- a/ipaserver/install/server/replicainstall.py -+++ b/ipaserver/install/server/replicainstall.py -@@ -573,14 +573,15 @@ def install(installer): - otpd.create_instance('OTPD', config.host_name, config.dirman_password, - ipautil.realm_to_suffix(config.realm_name)) - -- CA = cainstance.CAInstance( -- config.realm_name, certs.NSS_DIR, -- dogtag_constants=dogtag_constants) -- CA.dm_password = config.dirman_password -- -- CA.configure_certmonger_renewal() -- CA.import_ra_cert(config.dir + "/ra.p12") -- CA.fix_ra_perms() -+ if ipautil.file_exists(config.dir + "/cacert.p12"): -+ CA = cainstance.CAInstance( -+ config.realm_name, certs.NSS_DIR, -+ dogtag_constants=dogtag_constants) -+ CA.dm_password = config.dirman_password -+ -+ CA.configure_certmonger_renewal() -+ CA.import_ra_cert(config.dir + "/ra.p12") -+ CA.fix_ra_perms() - - # The DS instance is created before the keytab, add the SSL cert we - # generated --- -2.4.3 - diff --git a/SOURCES/0076-frontent-Add-summary-class-property-to-CommandOverri.patch b/SOURCES/0076-frontent-Add-summary-class-property-to-CommandOverri.patch new file mode 100644 index 0000000..ab0ece5 --- /dev/null +++ b/SOURCES/0076-frontent-Add-summary-class-property-to-CommandOverri.patch @@ -0,0 +1,34 @@ +From 5b427134d613a49bcbd2fe89e7cac938d664b9e7 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Tue, 9 Aug 2016 17:03:25 +0200 +Subject: [PATCH] frontent: Add summary class property to CommandOverride + +Avoid creating instance of overriden command to get its summary. + +https://fedorahosted.org/freeipa/ticket/6048 + +Reviewed-By: Jan Cholasta +--- + ipaclient/frontend.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/ipaclient/frontend.py b/ipaclient/frontend.py +index aeaed550771d3c6af04a9b34fcae414faacb47d7..587e31c89b3935984e799f7d4c500c652bcb5d43 100644 +--- a/ipaclient/frontend.py ++++ b/ipaclient/frontend.py +@@ -127,6 +127,12 @@ class CommandOverride(Command): + doc = classproperty(__doc_getter) + + @classmethod ++ def __summary_getter(cls): ++ return cls.__get_next().summary ++ ++ summary = classproperty(__summary_getter) ++ ++ @classmethod + def __NO_CLI_getter(cls): + return cls.__get_next().NO_CLI + +-- +2.7.4 + diff --git a/SOURCES/0076-trusts-harden-trust-fetch-domains-oddjobd-based-scri.patch b/SOURCES/0076-trusts-harden-trust-fetch-domains-oddjobd-based-scri.patch deleted file mode 100644 index afdc77b..0000000 --- a/SOURCES/0076-trusts-harden-trust-fetch-domains-oddjobd-based-scri.patch +++ /dev/null @@ -1,135 +0,0 @@ -From 2c577bc650613f5adfcc1efed0bfa40187eb362e Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Thu, 13 Aug 2015 17:18:57 +0300 -Subject: [PATCH] trusts: harden trust-fetch-domains oddjobd-based script - -When ipa-getkeytab is used to fetch trusted domain object credentials, -the fetched entry has always kvno 1. ipa-getkeytab always adds a key to -keytab which means older key versions will be in the SSSD keytab and -will confuse libkrb5 ccache initialization code as all kvno values are -equal to 1. Wrong key is picked up then and kinit fails. - -To solve this problem, always remove existing -/var/lib/sss/keytabs/forest.keytab before retrieving a new one. - -To make sure script's input cannot be used to define what should be -removed (by passing a relative path), make sure we retrieve trusted -forest name from LDAP. If it is not possible to retrieve, the script -will issue an exception and quit. If abrtd is running, this will be -recorded as a 'crash' and an attempt to use script by malicious user -would be recorded as well in the abrtd journal. - -Additionally, as com.redhat.idm.trust-fetch-domains will create -ID ranges for the domains of the trusted forest if they don't exist, -it needs permissions to do so. The permission should be granted only -to cifs/ipa.master@IPA.REALM services which means they must have -krbprincipalname=cifs/*@IPA.REALM,cn=services,... DN and be members of -cn=adtrust agents,cn=sysaccounts,... group. - -Solves https://bugzilla.redhat.com/show_bug.cgi?id=1250190 - -Ticket https://fedorahosted.org/freeipa/ticket/5182 - -Reviewed-By: Tomas Babej ---- - install/oddjob/com.redhat.idm.trust-fetch-domains | 29 +++++++++++++++++++---- - install/updates/20-aci.update | 4 ++++ - 2 files changed, 28 insertions(+), 5 deletions(-) - -diff --git a/install/oddjob/com.redhat.idm.trust-fetch-domains b/install/oddjob/com.redhat.idm.trust-fetch-domains -index e50c81e50e73b258bf08737c2d9a13a8832eb69f..6a2171d5f1936fabd00081bbbcea562a0e7041b8 100755 ---- a/install/oddjob/com.redhat.idm.trust-fetch-domains -+++ b/install/oddjob/com.redhat.idm.trust-fetch-domains -@@ -41,6 +41,9 @@ def retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal): - "-p", oneway_principal, - "-k", oneway_keytab_name, - "-r"] -+ if os.path.isfile(oneway_keytab_name): -+ os.unlink(oneway_keytab_name) -+ - (stdout, stderr, retcode) = ipautil.run(getkeytab_args, - env={'KRB5CCNAME': ccache_name, 'LANG': 'C'}, - raiseonerr=False) -@@ -111,7 +114,6 @@ from ipalib.plugins import trust - # retrieve the keys to oneway_keytab_name. - - keytab_name = '/etc/samba/samba.keytab' --oneway_keytab_name = '/var/lib/sss/keytabs/' + trusted_domain + '.keytab' - - principal = str('cifs/' + api.env.host) - -@@ -137,10 +139,20 @@ else: - old_ccache = os.environ.get('KRB5CCNAME') - api.Backend.ldap2.connect(ccache) - -+# Retrieve own NetBIOS name and trusted forest's name. -+# We use script's input to retrieve the trusted forest's name to sanitize input -+# for file-level access as we might need to wipe out keytab in /var/lib/sss/keytabs - own_trust_dn = DN(('cn', api.env.domain),('cn','ad'), ('cn', 'etc'), api.env.basedn) - own_trust_entry = api.Backend.ldap2.get_entry(own_trust_dn, ['ipantflatname']) --own_trust_flatname = own_trust_entry['ipantflatname'][0].upper() -+own_trust_flatname = own_trust_entry.single_value.get('ipantflatname').upper() -+trusted_domain_dn = DN(('cn', trusted_domain.lower()), api.env.container_adtrusts, api.env.basedn) -+trusted_domain_entry = api.Backend.ldap2.get_entry(trusted_domain_dn, ['cn']) -+trusted_domain = trusted_domain_entry.single_value.get('cn').lower() - -+# At this point if we didn't find trusted forest name, an exception will be raised -+# and script will quit. This is actually intended. -+ -+oneway_keytab_name = '/var/lib/sss/keytabs/' + trusted_domain + '.keytab' - oneway_principal = str('%s$@%s' % (own_trust_flatname, trusted_domain.upper())) - - # If keytab does not exist, retrieve it -@@ -152,11 +164,18 @@ try: - # The keytab may have stale key material (from older trust-add run) - if not os.path.isfile(oneway_ccache_name): - oneway_ccache = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name) -+ else: -+ oneway_ccache_check = KRB5_CCache(oneway_ccache_name) -+ if not oneway_ccache_check.credential_is_valid(oneway_principal): -+ # If credentials were invalid, obtain them again -+ oneway_ccache = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name) -+ else: -+ oneway_ccache = oneway_ccache_check.ccache - except krbV.Krb5Error as e: - # If there was failure on using keytab, assume it is stale and retrieve again - retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal) - --if oneway_ccache: -+try: - # There wasn existing ccache, validate its content - oneway_ccache_check = KRB5_CCache(oneway_ccache_name) - if not oneway_ccache_check.credential_is_valid(oneway_principal): -@@ -164,7 +183,7 @@ if oneway_ccache: - oneway_ccache = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name) - else: - oneway_ccache = oneway_ccache_check.ccache --else: -+except krbV.Krb5Error as e: - oneway_ccache = kinit_keytab(oneway_principal, oneway_keytab_name, oneway_ccache_name) - - # We are done: we have ccache with TDO credentials and can fetch domains -@@ -193,7 +212,7 @@ if domains: - dom['range_type'] = u'ipa-ad-trust' - # Do not pass ipaserver.dcerpc.TrustInstance to trust.add_range - # to force it using existing credentials cache -- trust.add_range(None, range_name, dom['ipanttrusteddomainsid'], -+ trust.add_range(api, None, range_name, dom['ipanttrusteddomainsid'], - trusted_domain, name, **dom) - except errors.DuplicateEntry: - # Ignore updating duplicate entries -diff --git a/install/updates/20-aci.update b/install/updates/20-aci.update -index 0bdeeb6acefad4f79385a1ddaec95df2e40377fb..cba1897e1fd1136fbcbd7c6ccaf03bfa4b696a44 100644 ---- a/install/updates/20-aci.update -+++ b/install/updates/20-aci.update -@@ -87,3 +87,7 @@ add:aci:(targetattr = "usercertificate")(version 3.0;acl "selfservice:Users can - # Hosts can add their own services - dn: cn=services,cn=accounts,$SUFFIX - add:aci: (target = "ldap:///krbprincipalname=*/($$dn)@$REALM,cn=services,cn=accounts,$SUFFIX")(targetfilter = "(objectClass=ipaKrbPrincipal)")(version 3.0;acl "Hosts can add own services"; allow(add) userdn="ldap:///fqdn=($$dn),cn=computers,cn=accounts,$SUFFIX";) -+ -+# CIFS service on the master can manage ID ranges -+dn: cn=ranges,cn=etc,$SUFFIX -+add:aci: (target = "ldap:///cn=*,cn=ranges,cn=etc,$SUFFIX")(targetfilter = "(objectClass=ipaIDrange)")(version 3.0;acl "CIFS service can manage ID ranges for trust"; allow(all) userdn="ldap:///krbprincipalname=cifs/*@$REALM,cn=services,cn=accounts,$SUFFIX" and groupdn="ldap:///cn=adtrust agents,cn=sysaccounts,cn=etc,$SUFFIX";) --- -2.4.3 - diff --git a/SOURCES/0077-schema-cache-Read-server-info-only-once.patch b/SOURCES/0077-schema-cache-Read-server-info-only-once.patch new file mode 100644 index 0000000..5ed5ee1 --- /dev/null +++ b/SOURCES/0077-schema-cache-Read-server-info-only-once.patch @@ -0,0 +1,50 @@ +From 6959578fdbdfd38113b26cd9e4f94b298343a6f0 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Tue, 9 Aug 2016 17:05:17 +0200 +Subject: [PATCH] schema cache: Read server info only once + +Do not open/close the file with every access to plugins. Extensive +access to filesystem may cause significant slowdown. + +https://fedorahosted.org/freeipa/ticket/6048 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/schema.py | 12 +++++++++++- + 1 file changed, 11 insertions(+), 1 deletion(-) + +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index c72109ac3bb9b7a71f9cbc056eaf3a4d8371d035..aadc891750782b0961bc46989e3693d1d3ed0ecb 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -378,6 +378,9 @@ class ServerInfo(collections.MutableMapping): + return self + + def __exit__(self, *_exc_info): ++ self.flush() ++ ++ def flush(self): + if self._dirty: + self._write() + +@@ -603,9 +606,16 @@ def get_package(api, client): + try: + schema = api._schema + except AttributeError: +- with ServerInfo(api.env.hostname) as server_info: ++ try: ++ server_info = api._server_info ++ except AttributeError: ++ server_info = api._server_info = ServerInfo(api) ++ ++ try: + schema = Schema(api, server_info, client) + object.__setattr__(api, '_schema', schema) ++ finally: ++ server_info.flush() + + fingerprint = str(schema['fingerprint']) + package_name = '{}${}'.format(__name__, fingerprint) +-- +2.7.4 + diff --git a/SOURCES/0077-user-undel-Fix-error-messages.patch b/SOURCES/0077-user-undel-Fix-error-messages.patch deleted file mode 100644 index fb41e39..0000000 --- a/SOURCES/0077-user-undel-Fix-error-messages.patch +++ /dev/null @@ -1,41 +0,0 @@ -From f021f35447a0b71957b2294b1000f9229ea064f6 Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Thu, 13 Aug 2015 08:11:38 +0200 -Subject: [PATCH] user-undel: Fix error messages. - -https://fedorahosted.org/freeipa/ticket/5207 - -Reviewed-By: Martin Basti ---- - ipalib/plugins/user.py | 12 +++++------- - 1 file changed, 5 insertions(+), 7 deletions(-) - -diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py -index 90ae7260abf935abf92b49da04c11bc76e836e49..418c51bdafc4e462e2decfe1e8541aaf49705cb0 100644 ---- a/ipalib/plugins/user.py -+++ b/ipalib/plugins/user.py -@@ -827,16 +827,14 @@ class user_undel(LDAPQuery): - - # First check that the user exists and is a delete one - delete_dn = self.obj.get_either_dn(*keys, **options) -- if delete_dn.endswith(DN(self.obj.active_container_dn, api.env.basedn)): -- raise errors.ValidationError( -- name=self.obj.primary_key.cli_name, -- error=_('User %r is already active') % keys[-1][0]) - try: - entry_attrs = self._exc_wrapper(keys, options, ldap.get_entry)(delete_dn) - except errors.NotFound: -- raise errors.ValidationError( -- name=self.obj.primary_key.cli_name, -- error=_('User %r not found') % keys[-1][0]) -+ self.obj.handle_not_found(*keys) -+ if delete_dn.endswith(DN(self.obj.active_container_dn, -+ api.env.basedn)): -+ raise errors.InvocationError( -+ message=_('user "%s" is already active') % keys[-1]) - - active_dn = DN(delete_dn[0], self.obj.active_container_dn, api.env.basedn) - --- -2.4.3 - diff --git a/SOURCES/0078-Prohibit-deletion-of-predefined-profiles.patch b/SOURCES/0078-Prohibit-deletion-of-predefined-profiles.patch deleted file mode 100644 index 5f1c49e..0000000 --- a/SOURCES/0078-Prohibit-deletion-of-predefined-profiles.patch +++ /dev/null @@ -1,87 +0,0 @@ -From ba321efe715dbbb3b4be22cb786995cf441e1a74 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Thu, 13 Aug 2015 02:32:54 -0400 -Subject: [PATCH] Prohibit deletion of predefined profiles - -Deletion of predefined profiles, including the default profile, -should not be allowed. Detect this case and raise an error. - -Also update the predefined profiles collection to use namedtuple, -making it easier to access the various components. - -Fixes: https://fedorahosted.org/freeipa/ticket/5198 -Reviewed-By: Alexander Bokovoy ---- - ipalib/plugins/certprofile.py | 13 +++++++++++-- - ipapython/dogtag.py | 8 +++++--- - 2 files changed, 16 insertions(+), 5 deletions(-) - -diff --git a/ipalib/plugins/certprofile.py b/ipalib/plugins/certprofile.py -index 1dd4f403ee4461b83c053eb36019a8896506bb81..007cc543406b7e5705fd7474f3685cd6a9ce6aca 100644 ---- a/ipalib/plugins/certprofile.py -+++ b/ipalib/plugins/certprofile.py -@@ -3,6 +3,7 @@ - # - - import re -+from operator import attrgetter - - from ipalib import api, Bool, File, Str - from ipalib import output, util -@@ -14,6 +15,7 @@ from ipalib.plugins.baseldap import ( - from ipalib.request import context - from ipalib import ngettext - from ipalib.text import _ -+from ipapython.dogtag import INCLUDED_PROFILES - from ipapython.version import API_VERSION - - from ipalib import errors -@@ -287,9 +289,16 @@ class certprofile_del(LDAPDelete): - __doc__ = _("Delete a Certificate Profile.") - msg_summary = _('Deleted profile "%(value)s"') - -- def execute(self, *args, **kwargs): -+ def pre_callback(self, ldap, dn, *keys, **options): - ca_enabled_check() -- return super(certprofile_del, self).execute(*args, **kwargs) -+ -+ if keys[0] in map(attrgetter('profile_id'), INCLUDED_PROFILES): -+ raise errors.ValidationError(name='profile_id', -+ error=_("Predefined profile '%(profile_id)s' cannot be deleted") -+ % {'profile_id': keys[0]} -+ ) -+ -+ return dn - - def post_callback(self, ldap, dn, *keys, **options): - with self.api.Backend.ra_certprofile as profile_api: -diff --git a/ipapython/dogtag.py b/ipapython/dogtag.py -index 0782d360ccf2ce2c90c4e9cfa66b5159e437e77c..3f0d08154d21a3072e344c311c3e70e414d9dee4 100644 ---- a/ipapython/dogtag.py -+++ b/ipapython/dogtag.py -@@ -17,6 +17,7 @@ - # along with this program. If not, see . - # - -+import collections - import os - import httplib - import xml.dom.minidom -@@ -42,10 +43,11 @@ from ipapython.ipa_log_manager import * - # the configured version. - - -+Profile = collections.namedtuple('Profile', ['profile_id', 'description', 'store_issued']) -+ - INCLUDED_PROFILES = { -- # ( profile_id , description , store_issued) -- (u'caIPAserviceCert', u'Standard profile for network services', True), -- (u'IECUserRoles', u'User profile that includes IECUserRoles extension from request', True), -+ Profile(u'caIPAserviceCert', u'Standard profile for network services', True), -+ Profile(u'IECUserRoles', u'User profile that includes IECUserRoles extension from request', True), - } - - DEFAULT_PROFILE = u'caIPAserviceCert' --- -2.4.3 - diff --git a/SOURCES/0078-schema-cache-Store-API-schema-cache-in-memory.patch b/SOURCES/0078-schema-cache-Store-API-schema-cache-in-memory.patch new file mode 100644 index 0000000..eb9dfd3 --- /dev/null +++ b/SOURCES/0078-schema-cache-Store-API-schema-cache-in-memory.patch @@ -0,0 +1,125 @@ +From 1aa300c53f070436888150ae582dad23cddac03b Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Mon, 15 Aug 2016 08:01:59 +0200 +Subject: [PATCH] schema cache: Store API schema cache in memory + +Read whole cache into memory and keep it there for lifetime of api +object. This removes the need to repetitively open/close the cache and +speeds up every access to it. + +https://fedorahosted.org/freeipa/ticket/6048 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/schema.py | 51 +++++++++++++++++++++----------------- + 1 file changed, 28 insertions(+), 23 deletions(-) + +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index aadc891750782b0961bc46989e3693d1d3ed0ecb..2fc6cce3eca392447cd4230216900116002934f4 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -3,6 +3,7 @@ + # + + import collections ++import contextlib + import errno + import fcntl + import json +@@ -315,24 +316,6 @@ class _SchemaObjectPlugin(_SchemaPlugin): + schema_key = 'classes' + + +-class _LockedZipFile(zipfile.ZipFile): +- """ Add locking to zipfile.ZipFile +- Shared lock is used with read mode, exclusive with write mode. +- """ +- def __enter__(self): +- if 'r' in self.mode: +- fcntl.flock(self.fp, fcntl.LOCK_SH) +- elif 'w' in self.mode or 'a' in self.mode: +- fcntl.flock(self.fp, fcntl.LOCK_EX) +- +- return super(_LockedZipFile, self).__enter__() +- +- def __exit__(self, type_, value, traceback): +- fcntl.flock(self.fp, fcntl.LOCK_UN) +- +- return super(_LockedZipFile, self).__exit__(type_, value, traceback) +- +- + class _SchemaNameSpace(collections.Mapping): + + def __init__(self, schema, name): +@@ -450,6 +433,7 @@ class Schema(object): + self._dict = {} + self._namespaces = {} + self._help = None ++ self._file = six.StringIO() + + for ns in self.namespaces: + self._dict[ns] = {} +@@ -486,9 +470,20 @@ class Schema(object): + except AttributeError: + pass + +- def _open_schema(self, filename, mode): ++ @contextlib.contextmanager ++ def _open(self, filename, mode): + path = os.path.join(self._DIR, filename) +- return _LockedZipFile(path, mode) ++ ++ with open(path, mode) as f: ++ if mode.startswith('r'): ++ fcntl.flock(f, fcntl.LOCK_SH) ++ else: ++ fcntl.flock(f, fcntl.LOCK_EX) ++ ++ try: ++ yield f ++ finally: ++ fcntl.flock(f, fcntl.LOCK_UN) + + def _fetch(self, client): + if not client.isconnected(): +@@ -523,7 +518,11 @@ class Schema(object): + self._expiration = ttl + time.time() + + def _read_schema(self): +- with self._open_schema(self._fingerprint, 'r') as schema: ++ self._file.truncate(0) ++ with self._open(self._fingerprint, 'r') as f: ++ self._file.write(f.read()) ++ ++ with zipfile.ZipFile(self._file, 'r') as schema: + self._dict['fingerprint'] = self._fingerprint + + for name in schema.namelist(): +@@ -566,7 +565,8 @@ class Schema(object): + logger.warning("Failed to write schema: {}".format(e)) + return + +- with self._open_schema(self._fingerprint, 'w') as schema: ++ self._file.truncate(0) ++ with zipfile.ZipFile(self._file, 'w', zipfile.ZIP_DEFLATED) as schema: + for key, value in self._dict.items(): + if key in self.namespaces: + ns = value +@@ -579,8 +579,13 @@ class Schema(object): + schema.writestr('_help', + json.dumps(self._generate_help(self._dict))) + ++ self._file.seek(0) ++ with self._open(self._fingerprint, 'w') as f: ++ f.truncate(0) ++ f.write(self._file.read()) ++ + def _read(self, path): +- with self._open_schema(self._fingerprint, 'r') as zf: ++ with zipfile.ZipFile(self._file, 'r') as zf: + return json.loads(zf.read(path)) + + def read_namespace_member(self, namespace, member): +-- +2.7.4 + diff --git a/SOURCES/0079-client-Do-not-create-instance-just-to-check-isinstan.patch b/SOURCES/0079-client-Do-not-create-instance-just-to-check-isinstan.patch new file mode 100644 index 0000000..60707e8 --- /dev/null +++ b/SOURCES/0079-client-Do-not-create-instance-just-to-check-isinstan.patch @@ -0,0 +1,97 @@ +From bac0d7c286768a67715ca1ac1e835a272e540721 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Thu, 11 Aug 2016 14:30:00 +0200 +Subject: [PATCH] client: Do not create instance just to check isinstance + +Checking that classes are idenical gives the same result and +avoids unnecessary instantiation. + +https://fedorahosted.org/freeipa/ticket/6048 + +Reviewed-By: Jan Cholasta +--- + ipaclient/plugins/automount.py | 4 ++-- + ipaclient/plugins/otptoken_yubikey.py | 3 +-- + ipaclient/plugins/vault.py | 16 ++++++++-------- + 3 files changed, 11 insertions(+), 12 deletions(-) + +diff --git a/ipaclient/plugins/automount.py b/ipaclient/plugins/automount.py +index 925b635ff27411fc7e2f8c3dae17c747216d7fb6..3742705face49d02370e845e3d6e6599a34809eb 100644 +--- a/ipaclient/plugins/automount.py ++++ b/ipaclient/plugins/automount.py +@@ -55,8 +55,8 @@ class _fake_automountlocation_show(Method): + class automountlocation_tofiles(MethodOverride): + @classmethod + def __NO_CLI_getter(cls): +- return isinstance(api.Command.automountlocation_show, +- _fake_automountlocation_show) ++ return (api.Command.get_plugin('automountlocation_show') is ++ _fake_automountlocation_show) + + NO_CLI = classproperty(__NO_CLI_getter) + +diff --git a/ipaclient/plugins/otptoken_yubikey.py b/ipaclient/plugins/otptoken_yubikey.py +index 549376a0ff65d44c5698666a84608849152368b2..1075b6d839c785b44f035050ed5c9773c66d57b7 100644 +--- a/ipaclient/plugins/otptoken_yubikey.py ++++ b/ipaclient/plugins/otptoken_yubikey.py +@@ -77,8 +77,7 @@ class otptoken_add_yubikey(Command): + + @classmethod + def __NO_CLI_getter(cls): +- return isinstance(api.Command.otptoken_add, +- _fake_otptoken_add) ++ return api.Command.get_plugin('otptoken_add') is _fake_otptoken_add + + NO_CLI = classproperty(__NO_CLI_getter) + +diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py +index c0ded21d515fe41bde5fb0e547087cb7789aa6a3..08bbeb50f3bdc756321df9e45496e5388edd92c5 100644 +--- a/ipaclient/plugins/vault.py ++++ b/ipaclient/plugins/vault.py +@@ -205,8 +205,8 @@ class vault_add(Local): + + @classmethod + def __NO_CLI_getter(cls): +- return isinstance(api.Command.vault_add_internal, +- _fake_vault_add_internal) ++ return (api.Command.get_plugin('vault_add_internal') is ++ _fake_vault_add_internal) + + NO_CLI = classproperty(__NO_CLI_getter) + +@@ -411,8 +411,8 @@ class vault_mod(Local): + + @classmethod + def __NO_CLI_getter(cls): +- return isinstance(api.Command.vault_mod_internal, +- _fake_vault_mod_internal) ++ return (api.Command.get_plugin('vault_mod_internal') is ++ _fake_vault_mod_internal) + + NO_CLI = classproperty(__NO_CLI_getter) + +@@ -598,8 +598,8 @@ class vault_archive(Local): + + @classmethod + def __NO_CLI_getter(cls): +- return isinstance(api.Command.vault_archive_internal, +- _fake_vault_archive_internal) ++ return (api.Command.get_plugin('vault_archive_internal') is ++ _fake_vault_archive_internal) + + NO_CLI = classproperty(__NO_CLI_getter) + +@@ -855,8 +855,8 @@ class vault_retrieve(Local): + + @classmethod + def __NO_CLI_getter(cls): +- return isinstance(api.Command.vault_retrieve_internal, +- _fake_vault_retrieve_internal) ++ return (api.Command.get_plugin('vault_retrieve_internal') is ++ _fake_vault_retrieve_internal) + + NO_CLI = classproperty(__NO_CLI_getter) + +-- +2.7.4 + diff --git a/SOURCES/0079-improve-the-handling-of-krb5-related-errors-in-dnsse.patch b/SOURCES/0079-improve-the-handling-of-krb5-related-errors-in-dnsse.patch deleted file mode 100644 index 6faaa63..0000000 --- a/SOURCES/0079-improve-the-handling-of-krb5-related-errors-in-dnsse.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 61d06ac1701a6a3a4afe75bcff64f271991a82ec Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Tue, 18 Aug 2015 18:33:37 +0200 -Subject: [PATCH] improve the handling of krb5-related errors in dnssec daemons - -ipa-dnskeysync* and ipa-ods-exporter handle kerberos errors more gracefully -instead of crashing with tracebacks. - -https://fedorahosted.org/freeipa/ticket/5229 - -Reviewed-By: Martin Basti ---- - daemons/dnssec/ipa-dnskeysync-replica | 10 +++++++++- - daemons/dnssec/ipa-dnskeysyncd | 4 ++-- - daemons/dnssec/ipa-ods-exporter | 10 +++++++++- - 3 files changed, 20 insertions(+), 4 deletions(-) - -diff --git a/daemons/dnssec/ipa-dnskeysync-replica b/daemons/dnssec/ipa-dnskeysync-replica -index 551c2f21d5b85b76a7281f719ce722a6c5830cf7..b80b38962957f922cc871ead471f8da0831bec4d 100755 ---- a/daemons/dnssec/ipa-dnskeysync-replica -+++ b/daemons/dnssec/ipa-dnskeysync-replica -@@ -12,6 +12,7 @@ from binascii import hexlify - from datetime import datetime - import dns.dnssec - import fcntl -+from krbV import Krb5Error - import logging - import os - from pprint import pprint -@@ -141,7 +142,14 @@ log.setLevel(level=logging.DEBUG) - PRINCIPAL = str('%s/%s' % (DAEMONNAME, ipalib.api.env.host)) - log.debug('Kerberos principal: %s', PRINCIPAL) - ccache_filename = os.path.join(WORKDIR, 'ipa-dnskeysync-replica.ccache') --ipautil.kinit_keytab(PRINCIPAL, paths.IPA_DNSKEYSYNCD_KEYTAB, ccache_filename) -+ -+try: -+ ipautil.kinit_keytab(PRINCIPAL, paths.IPA_DNSKEYSYNCD_KEYTAB, -+ ccache_filename, attempts=5) -+except Krb5Error as e: -+ log.critical('Kerberos authentication failed: %s', e) -+ sys.exit(1) -+ - os.environ['KRB5CCNAME'] = ccache_filename - log.debug('Got TGT') - -diff --git a/daemons/dnssec/ipa-dnskeysyncd b/daemons/dnssec/ipa-dnskeysyncd -index a0fcf8b4b2f27627f3ebcb089e212eefda2adbd3..660e34b45084dd5a31967e9493f488632ec00932 100755 ---- a/daemons/dnssec/ipa-dnskeysyncd -+++ b/daemons/dnssec/ipa-dnskeysyncd -@@ -66,9 +66,9 @@ PRINCIPAL = str('%s/%s' % (DAEMONNAME, api.env.host)) - log.debug('Kerberos principal: %s', PRINCIPAL) - ccache_filename = os.path.join(WORKDIR, 'ipa-dnskeysyncd.ccache') - try: -- ipautil.kinit_keytab(PRINCIPAL, KEYTAB_FB, ccache_filename) -+ ipautil.kinit_keytab(PRINCIPAL, KEYTAB_FB, ccache_filename, attempts=5) - except Exception as ex: -- log.critical(ex) -+ log.critical("Kerberos authentication failed: %s", ex) - # signal failure and let init system to restart the daemon - sys.exit(1) - os.environ['KRB5CCNAME'] = ccache_filename -diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter -index 4c6649c2fbfe77e563ab70276a92b59201fcbace..4d5423797fc9d4bdd0a432bac96b8209bb98c6d8 100755 ---- a/daemons/dnssec/ipa-ods-exporter -+++ b/daemons/dnssec/ipa-ods-exporter -@@ -20,6 +20,7 @@ from datetime import datetime - import dateutil.tz - import dns.dnssec - import fcntl -+from krbV import Krb5Error - import logging - import os - import subprocess -@@ -482,7 +483,14 @@ ipalib.api.finalize() - PRINCIPAL = str('%s/%s' % (DAEMONNAME, ipalib.api.env.host)) - log.debug('Kerberos principal: %s', PRINCIPAL) - ccache_name = os.path.join(WORKDIR, 'ipa-ods-exporter.ccache') --ipautil.kinit_keytab(PRINCIPAL, paths.IPA_ODS_EXPORTER_KEYTAB, ccache_name) -+ -+try: -+ ipautil.kinit_keytab(PRINCIPAL, paths.IPA_ODS_EXPORTER_KEYTAB, ccache_name, -+ attempts=5) -+except Krb5Error as e: -+ log.critical('Kerberos authentication failed: %s', e) -+ sys.exit(1) -+ - os.environ['KRB5CCNAME'] = ccache_name - log.debug('Got TGT') - --- -2.4.3 - diff --git a/SOURCES/0080-client-Add-support-for-multiple-IP-addresses-during-.patch b/SOURCES/0080-client-Add-support-for-multiple-IP-addresses-during-.patch deleted file mode 100644 index 2212e58..0000000 --- a/SOURCES/0080-client-Add-support-for-multiple-IP-addresses-during-.patch +++ /dev/null @@ -1,398 +0,0 @@ -From 12cafe49be52deca889c6a909f6451a464085b06 Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Sun, 4 Jan 2015 15:04:18 -0500 -Subject: [PATCH] client: Add support for multiple IP addresses during - installation. - -https://fedorahosted.org/freeipa/ticket/4249 - -Reviewed-By: Martin Basti ---- - ipa-client/ipa-install/ipa-client-install | 289 +++++++++++++++++++++++------- - 1 file changed, 223 insertions(+), 66 deletions(-) - -diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install -index 91323ae115a27d221bcbc43fee887c56d99c8635..793de4fc950ad73b1d88f9ab4bd5178afc8b813d 100755 ---- a/ipa-client/ipa-install/ipa-client-install -+++ b/ipa-client/ipa-install/ipa-client-install -@@ -32,6 +32,7 @@ try: - from optparse import SUPPRESS_HELP, OptionGroup, OptionValueError - import shutil - from krbV import Krb5Error -+ import dns - - import nss.nss as nss - import SSSDConfig -@@ -180,9 +181,15 @@ def parse_options(): - basic_group.add_option("--configure-firefox", dest="configure_firefox", - action="store_true", default=False, - help="configure Firefox") -- parser.add_option_group(basic_group) - basic_group.add_option("--firefox-dir", dest="firefox_dir", default=None, - help="specify directory where Firefox is installed (for example: '/usr/lib/firefox')") -+ basic_group.add_option("--ip-address", dest="ip_addresses", default=[], -+ action="append", help="Specify IP address that should be added to DNS." -+ " This option can be used multiple times") -+ basic_group.add_option("--all-ip-addresses", dest="all_ip_addresses", -+ default=False, action="store_true", help="All routable IP" -+ " addresses configured on any inteface will be added to DNS") -+ parser.add_option_group(basic_group) - - sssd_group = OptionGroup(parser, "SSSD options") - sssd_group.add_option("--permit", dest="permit", -@@ -223,6 +230,15 @@ def parse_options(): - if options.no_nisdomain and options.nisdomain: - parser.error("--no-nisdomain cannot be used together with --nisdomain") - -+ if options.ip_addresses: -+ if options.dns_updates: -+ parser.error("--ip-address cannot be used together with" -+ " --enable-dns-updates") -+ -+ if options.all_ip_addresses: -+ parser.error("--ip-address cannot be used together with" -+ " --all-ip-addresses") -+ - return safe_opts, options - - def logging_setup(options): -@@ -1285,6 +1301,11 @@ def configure_sssd_conf(fstore, cli_realm, cli_domain, cli_server, options, clie - - if options.dns_updates: - domain.set_option('dyndns_update', True) -+ if options.all_ip_addresses: -+ domain.set_option('dyndns_iface', '*') -+ else: -+ iface = get_server_connection_interface(cli_server[0]) -+ domain.set_option('dyndns_iface', iface) - if options.krb5_offline_passwords: - domain.set_option('krb5_store_password_if_offline', True) - -@@ -1501,39 +1522,41 @@ def unconfigure_nisdomain(): - services.knownservices.domainname.disable() - - --def resolve_ipaddress(server): -- """ Connect to the server's LDAP port in order to determine what ip -- address this machine uses as "public" ip (relative to the server). -- -- Returns a tuple with the IP address and address family when -- connection was successful. Socket error is raised otherwise. -- """ -- last_socket_error = None -- -- for res in socket.getaddrinfo(server, 389, socket.AF_UNSPEC, -- socket.SOCK_STREAM): -- af, socktype, proto, canonname, sa = res -- try: -- s = socket.socket(af, socktype, proto) -- except socket.error, e: -- last_socket_error = e -- s = None -+def get_iface_from_ip(ip_addr): -+ ipresult = ipautil.run([paths.IP, '-oneline', 'address', 'show']) -+ for line in ipresult[0].split('\n'): -+ fields = line.split() -+ if len(fields) < 6: - continue -- -+ if fields[2] not in ['inet', 'inet6']: -+ continue -+ (ip, mask) = fields[3].rsplit('/', 1) -+ if ip == ip_addr: -+ return fields[1] -+ else: -+ raise RuntimeError("IP %s not assigned to any interface." % ip_addr) -+ -+ -+def get_local_ipaddresses(iface=None): -+ args = [paths.IP, '-oneline', 'address', 'show'] -+ if iface: -+ args += ['dev', iface] -+ ipresult = ipautil.run(args) -+ lines = ipresult[0].split('\n') -+ ips = [] -+ for line in lines: -+ fields = line.split() -+ if len(fields) < 6: -+ continue -+ if fields[2] not in ['inet', 'inet6']: -+ continue -+ (ip, mask) = fields[3].rsplit('/', 1) - try: -- s.connect(sa) -- sockname = s.getsockname() -- -- # For both IPv4 and IPv6 own IP address is always the first item -- return (sockname[0], af) -- except socket.error, e: -- last_socket_error = e -- finally: -- if s: -- s.close() -+ ips.append(ipautil.CheckedIPAddress(ip)) -+ except ValueError: -+ continue -+ return ips - -- if last_socket_error is not None: -- raise last_socket_error # pylint: disable=E0702 - - def do_nsupdate(update_txt): - root_logger.debug("Writing nsupdate commands to %s:", UPDATE_FILE) -@@ -1558,21 +1581,24 @@ def do_nsupdate(update_txt): - - return result - --UPDATE_TEMPLATE_A = """ --debug -+DELETE_TEMPLATE_A = """ - update delete $HOSTNAME. IN A - show - send --update add $HOSTNAME. $TTL IN A $IPADDRESS --show --send - """ - --UPDATE_TEMPLATE_AAAA = """ --debug -+DELETE_TEMPLATE_AAAA = """ - update delete $HOSTNAME. IN AAAA - show - send -+""" -+ADD_TEMPLATE_A = """ -+update add $HOSTNAME. $TTL IN A $IPADDRESS -+show -+send -+""" -+ -+ADD_TEMPLATE_AAAA = """ - update add $HOSTNAME. $TTL IN AAAA $IPADDRESS - show - send -@@ -1581,46 +1607,174 @@ send - UPDATE_FILE = paths.IPA_DNS_UPDATE_TXT - CCACHE_FILE = paths.IPA_DNS_CCACHE - --def update_dns(server, hostname): - -+def update_dns(server, hostname, options): - try: -- (ip, af) = resolve_ipaddress(server) -- except socket.gaierror, e: -- root_logger.debug("update_dns: could not connect to server: %s", e) -- root_logger.error("Cannot update DNS records! " -- "Failed to connect to server '%s'.", server) -- return -- -- sub_dict = dict(HOSTNAME=hostname, -- IPADDRESS=ip, -- TTL=1200 -- ) -- -- if af == socket.AF_INET: -- template = UPDATE_TEMPLATE_A -- elif af == socket.AF_INET6: -- template = UPDATE_TEMPLATE_AAAA -+ ips = get_local_ipaddresses() -+ except CalledProcessError as e: -+ root_logger.error("Cannot update DNS records. %s" % e) -+ root_logger.debug("Unable to get local IP addresses.") -+ -+ if options.all_ip_addresses: -+ update_ips = ips -+ elif options.ip_addresses: -+ update_ips = [] -+ for ip in options.ip_addresses: -+ update_ips.append(ipautil.CheckedIPAddress(ip)) - else: -- root_logger.info("Failed to determine this machine's ip address.") -- root_logger.warning("Failed to update DNS A record.") -+ try: -+ iface = get_server_connection_interface(server) -+ except RuntimeError as e: -+ root_logger.error("Cannot update DNS records. %s" % e) -+ return -+ try: -+ update_ips = get_local_ipaddresses(iface) -+ except CalledProcessError as e: -+ root_logger.error("Cannot update DNS records. %s" % e) -+ return -+ -+ if not update_ips: -+ root_logger.info("Failed to determine this machine's ip address(es).") - return - -- update_txt = ipautil.template_str(template, sub_dict) -+ update_txt = "debug\n" -+ update_txt += ipautil.template_str(DELETE_TEMPLATE_A, -+ dict(HOSTNAME=hostname)) -+ update_txt += ipautil.template_str(DELETE_TEMPLATE_AAAA, -+ dict(HOSTNAME=hostname)) -+ -+ for ip in update_ips: -+ sub_dict = dict(HOSTNAME=hostname, IPADDRESS=ip, TTL=1200) -+ if ip.version == 4: -+ template = ADD_TEMPLATE_A -+ elif ip.version == 6: -+ template = ADD_TEMPLATE_AAAA -+ update_txt += ipautil.template_str(template, sub_dict) -+ -+ if not do_nsupdate(update_txt): -+ root_logger.error("Failed to update DNS records.") -+ verify_dns_update(hostname, update_ips) -+ - -- if do_nsupdate(update_txt): -- root_logger.info("DNS server record set to: %s -> %s", hostname, ip) -+def verify_dns_update(fqdn, ips): -+ """ -+ Verify that the fqdn resolves to all IP addresses and -+ that there's matching PTR record for every IP address. -+ """ -+ # verify A/AAAA records -+ missing_ips = [str(ip) for ip in ips] -+ extra_ips = [] -+ for record_type in [dns.rdatatype.A, dns.rdatatype.AAAA]: -+ root_logger.debug('DNS resolver: Query: %s IN %s' % -+ (fqdn, dns.rdatatype.to_text(record_type))) -+ try: -+ answers = dns.resolver.query(fqdn, record_type) -+ except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN): -+ root_logger.debug('DNS resolver: No record.') -+ except dns.resolver.NoNameservers: -+ root_logger.debug('DNS resolver: No nameservers answered the' -+ 'query.') -+ except dns.exception.DNSException: -+ root_logger.debug('DNS resolver error.') -+ else: -+ for rdata in answers: -+ try: -+ missing_ips.remove(rdata.address) -+ except ValueError: -+ extra_ips.append(rdata.address) -+ -+ # verify PTR records -+ fqdn_name = dns.name.from_text(fqdn) -+ wrong_reverse = {} -+ missing_reverse = [str(ip) for ip in ips] -+ for ip in ips: -+ ip_str = str(ip) -+ addr = dns.reversename.from_address(ip_str) -+ root_logger.debug('DNS resolver: Query: %s IN PTR' % addr) -+ try: -+ answers = dns.resolver.query(addr, dns.rdatatype.PTR) -+ except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN): -+ root_logger.debug('DNS resolver: No record.') -+ except dns.resolver.NoNameservers: -+ root_logger.debug('DNS resolver: No nameservers answered the' -+ 'query.') -+ except dns.exception.DNSException: -+ root_logger.debug('DNS resolver error.') -+ else: -+ missing_reverse.remove(ip_str) -+ for rdata in answers: -+ if not rdata.target == fqdn_name: -+ wrong_reverse.setdefault(ip_str, []).append(rdata.target) -+ -+ if missing_ips: -+ root_logger.warning('Missing A/AAAA record(s) for host %s: %s.' % -+ (fqdn, ', '.join(missing_ips))) -+ if extra_ips: -+ root_logger.warning('Extra A/AAAA record(s) for host %s: %s.' % -+ (fqdn, ', '.join(extra_ips))) -+ if missing_reverse: -+ root_logger.warning('Missing reverse record(s) for address(es): %s.' % -+ ', '.join(missing_reverse)) -+ if wrong_reverse: -+ root_logger.warning('Incorrect reverse record(s):') -+ for ip in wrong_reverse: -+ for target in wrong_reverse[ip]: -+ root_logger.warning('%s is pointing to %s instead of %s' % -+ (ip, target, fqdn_name)) -+ -+def get_server_connection_interface(server): -+ # connect to IPA server, get all ip addresses of inteface used to connect -+ for res in socket.getaddrinfo(server, 389, socket.AF_UNSPEC, socket.SOCK_STREAM): -+ (af, socktype, proto, canonname, sa) = res -+ try: -+ s = socket.socket(af, socktype, proto) -+ except socket.error as e: -+ last_error = e -+ s = None -+ continue -+ try: -+ s.connect(sa) -+ sockname = s.getsockname() -+ ip = sockname[0] -+ except socket.error as e: -+ last_error = e -+ continue -+ finally: -+ if s: -+ s.close() -+ try: -+ return get_iface_from_ip(ip) -+ except (CalledProcessError, RuntimeError) as e: -+ last_error = e - else: -- root_logger.error("Failed to update DNS records.") -+ msg = "Cannot get server connection interface" -+ if last_error: -+ msg += ": %s" % (last_error) -+ raise RuntimeError(msg) - --def client_dns(server, hostname, dns_updates=False): -+ -+def client_dns(server, hostname, options): - - dns_ok = ipautil.is_host_resolvable(hostname) - - if not dns_ok: -- root_logger.warning("Hostname (%s) not found in DNS", hostname) -+ root_logger.warning("Hostname (%s) does not have A/AAAA record.", -+ hostname) -+ -+ if (options.dns_updates or options.all_ip_addresses or options.ip_addresses -+ or not dns_ok): -+ update_dns(server, hostname, options) - -- if dns_updates or not dns_ok: -- update_dns(server, hostname) -+ -+def check_ip_addresses(options): -+ if options.ip_addresses: -+ for ip in options.ip_addresses: -+ try: -+ ipautil.CheckedIPAddress(ip, match_local=True) -+ except ValueError as e: -+ root_logger.error(e) -+ return False -+ return True - - def update_ssh_keys(server, hostname, ssh_dir, create_sshfp): - if not os.path.isdir(ssh_dir): -@@ -2127,6 +2281,9 @@ def install(options, env, fstore, statestore): - if not options.ca_cert_file and get_cert_path(options.ca_cert_file) == CACERT: - root_logger.warning("Using existing certificate '%s'.", CACERT) - -+ if not check_ip_addresses(options): -+ return CLIENT_INSTALL_ERROR -+ - # Create the discovery instance - ds = ipadiscovery.IPADiscovery() - -@@ -2717,7 +2874,7 @@ def install(options, env, fstore, statestore): - root_logger.info("Added CA certificates to the default NSS database.") - - if not options.on_master: -- client_dns(cli_server[0], hostname, options.dns_updates) -+ client_dns(cli_server[0], hostname, options) - configure_certmonger(fstore, subject_base, cli_realm, hostname, - options, ca_enabled) - --- -2.4.3 - diff --git a/SOURCES/0080-schema-cache-Read-schema-instead-of-rewriting-it-whe.patch b/SOURCES/0080-schema-cache-Read-schema-instead-of-rewriting-it-whe.patch new file mode 100644 index 0000000..acc7d26 --- /dev/null +++ b/SOURCES/0080-schema-cache-Read-schema-instead-of-rewriting-it-whe.patch @@ -0,0 +1,104 @@ +From a9ebd731b23ebf9a56401139fe20dafc50322ff3 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Tue, 16 Aug 2016 15:32:47 +0200 +Subject: [PATCH] schema cache: Read schema instead of rewriting it when + SchemaUpToDate + +https://fedorahosted.org/freeipa/ticket/6048 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/schema.py | 46 ++++++++++++++++++++------------------ + 1 file changed, 24 insertions(+), 22 deletions(-) + +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index 2fc6cce3eca392447cd4230216900116002934f4..e8b3f61bd8460c60630e8710028da79654819bd1 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -17,6 +17,7 @@ import six + + from ipaclient.frontend import ClientCommand, ClientMethod + from ipalib import errors, parameters, plugable ++from ipalib.errors import SchemaUpToDate + from ipalib.frontend import Object + from ipalib.output import Output + from ipalib.parameters import DefaultFrom, Flag, Password, Str +@@ -439,15 +440,14 @@ class Schema(object): + self._dict[ns] = {} + self._namespaces[ns] = _SchemaNameSpace(self, ns) + +- is_known = False +- if not api.env.force_schema_check: +- try: +- self._fingerprint = server_info['fingerprint'] +- self._expiration = server_info['expiration'] +- except KeyError: +- pass +- else: +- is_known = True ++ try: ++ self._fingerprint = server_info['fingerprint'] ++ self._expiration = server_info['expiration'] ++ except KeyError: ++ is_known = False ++ else: ++ is_known = (not api.env.force_schema_check and ++ self._expiration > time.time()) + + if is_known: + try: +@@ -461,14 +461,15 @@ class Schema(object): + self._fetch(client) + except NotAvailable: + raise ++ except SchemaUpToDate as e: ++ self._fingerprint = e.fingerprint ++ self._expiration = time.time() + e.ttl ++ self._read_schema() + else: + self._write_schema() +- finally: +- try: +- server_info['fingerprint'] = self._fingerprint +- server_info['expiration'] = self._expiration +- except AttributeError: +- pass ++ ++ server_info['fingerprint'] = self._fingerprint ++ server_info['expiration'] = self._expiration + + @contextlib.contextmanager + def _open(self, filename, mode): +@@ -501,21 +502,22 @@ class Schema(object): + schema = client.forward(u'schema', **kwargs)['result'] + except errors.CommandError: + raise NotAvailable() +- except errors.SchemaUpToDate as e: +- fp = e.fingerprint +- ttl = e.ttl +- else: ++ ++ try: + fp = schema['fingerprint'] +- ttl = schema.pop('ttl', 0) +- schema.pop('version', None) ++ ttl = schema.pop('ttl') ++ schema.pop('version') + + for key, value in schema.items(): + if key in self.namespaces: + value = {m['full_name']: m for m in value} + self._dict[key] = value ++ except KeyError as e: ++ logger.warning("Failed to fetch schema: %s", e) ++ raise NotAvailable() + + self._fingerprint = fp +- self._expiration = ttl + time.time() ++ self._expiration = time.time() + ttl + + def _read_schema(self): + self._file.truncate(0) +-- +2.7.4 + diff --git a/SOURCES/0081-schema-check-Check-current-client-language-against-c.patch b/SOURCES/0081-schema-check-Check-current-client-language-against-c.patch new file mode 100644 index 0000000..1837ad4 --- /dev/null +++ b/SOURCES/0081-schema-check-Check-current-client-language-against-c.patch @@ -0,0 +1,57 @@ +From 70430cf0c22ab28a145de775aee343b3605c798a Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Tue, 16 Aug 2016 15:36:07 +0200 +Subject: [PATCH] schema check: Check current client language against cached + one + +https://fedorahosted.org/freeipa/ticket/6204 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/schema.py | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index e8b3f61bd8460c60630e8710028da79654819bd1..6fc70bf4b294badedd651e15b7e403cc40619f5c 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -7,6 +7,7 @@ import contextlib + import errno + import fcntl + import json ++import locale + import os + import sys + import time +@@ -440,14 +441,19 @@ class Schema(object): + self._dict[ns] = {} + self._namespaces[ns] = _SchemaNameSpace(self, ns) + ++ self._language = ( ++ locale.setlocale(locale.LC_ALL, '').split('.')[0].lower() ++ ) + try: + self._fingerprint = server_info['fingerprint'] + self._expiration = server_info['expiration'] ++ language = server_info['language'] + except KeyError: + is_known = False + else: + is_known = (not api.env.force_schema_check and +- self._expiration > time.time()) ++ self._expiration > time.time() and ++ self._language == language) + + if is_known: + try: +@@ -470,6 +476,7 @@ class Schema(object): + + server_info['fingerprint'] = self._fingerprint + server_info['expiration'] = self._expiration ++ server_info['language'] = self._language + + @contextlib.contextmanager + def _open(self, filename, mode): +-- +2.7.4 + diff --git a/SOURCES/0081-vault-Fix-vault-find-with-criteria.patch b/SOURCES/0081-vault-Fix-vault-find-with-criteria.patch deleted file mode 100644 index 8b33fad..0000000 --- a/SOURCES/0081-vault-Fix-vault-find-with-criteria.patch +++ /dev/null @@ -1,28 +0,0 @@ -From a97b7c5bd372c7a581c440564f4e9d6f3c12a3ea Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Tue, 18 Aug 2015 21:11:52 +0200 -Subject: [PATCH] vault: Fix vault-find with criteria - -https://fedorahosted.org/freeipa/ticket/5212 - -Reviewed-By: Petr Vobornik ---- - ipalib/plugins/vault.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index 4d430ee88658e7ba7f2863ca4ef1e8672e298923..ff021a6a2106b6bcbd690b50bf58e49249e80500 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -802,7 +802,7 @@ class vault_find(LDAPSearch): - raise errors.InvocationError( - format=_('KRA service is not enabled')) - -- base_dn = self.obj.get_dn(*args, **options) -+ base_dn = self.obj.get_dn(None, **options) - - return (filter, base_dn, scope) - --- -2.4.3 - diff --git a/SOURCES/0082-Fail-on-topology-disconnect-last-role-removal.patch b/SOURCES/0082-Fail-on-topology-disconnect-last-role-removal.patch new file mode 100644 index 0000000..91f2417 --- /dev/null +++ b/SOURCES/0082-Fail-on-topology-disconnect-last-role-removal.patch @@ -0,0 +1,51 @@ +From 90b827a6d23d864bfac96d2ff0f89f1a3ba1d245 Mon Sep 17 00:00:00 2001 +From: Stanislav Laznicka +Date: Fri, 12 Aug 2016 11:59:41 +0200 +Subject: [PATCH] Fail on topology disconnect/last role removal + +Disconnecting topology/removing last-role-host during server +uninstallation should raise error rather than just being logged +if the appropriate ignore settings are not present. + +https://fedorahosted.org/freeipa/ticket/6168 + +Reviewed-By: Martin Babinsky +--- + ipaserver/install/server/install.py | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py +index 94698898934844350488d5fc52d6e1e567624502..86b8402750b503ea7dacd1f4c59c82d9bd4082e6 100644 +--- a/ipaserver/install/server/install.py ++++ b/ipaserver/install/server/install.py +@@ -25,6 +25,7 @@ from ipapython.ipa_log_manager import root_logger + from ipapython.ipautil import ( + decrypt_file, format_netloc, ipa_generate_password, run, user_input, + is_fips_enabled) ++from ipapython.admintool import ScriptError + from ipaplatform import services + from ipaplatform.paths import paths + from ipaplatform.tasks import tasks +@@ -294,7 +295,6 @@ def common_cleanup(func): + def remove_master_from_managed_topology(api_instance, options): + try: + # we may force the removal +- # if the master was already deleted we will just get a warning + server_del_options = dict( + force=True, + ignore_topology_disconnect=options.ignore_topology_disconnect, +@@ -303,8 +303,10 @@ def remove_master_from_managed_topology(api_instance, options): + + replication.run_server_del_as_cli( + api_instance, api_instance.env.host, **server_del_options) +- ++ except errors.ServerRemovalError as e: ++ raise ScriptError(str(e)) + except Exception as e: ++ # if the master was already deleted we will just get a warning + root_logger.warning("Failed to delete master: {}".format(e)) + + +-- +2.9.3 + diff --git a/SOURCES/0082-vault-Add-container-information-to-vault-command-res.patch b/SOURCES/0082-vault-Add-container-information-to-vault-command-res.patch deleted file mode 100644 index 731126b..0000000 --- a/SOURCES/0082-vault-Add-container-information-to-vault-command-res.patch +++ /dev/null @@ -1,112 +0,0 @@ -From 23dd6ad21e09a14a802c7776bf073f22011f7eb6 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Tue, 18 Aug 2015 21:44:13 +0200 -Subject: [PATCH] vault: Add container information to vault command results - -https://fedorahosted.org/freeipa/ticket/5150 - -Reviewed-By: Petr Vobornik ---- - ipalib/plugins/vault.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 44 insertions(+) - -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index ff021a6a2106b6bcbd690b50bf58e49249e80500..712e2d5ddfa723eb84b80a261289a7cf1c75674f 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -322,6 +322,21 @@ class vault(LDAPObject): - label=_('Failed owners'), - flags=['no_create', 'no_update', 'no_search'], - ), -+ Str( -+ 'service?', -+ label=_('Vault service'), -+ flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'}, -+ ), -+ Flag( -+ 'shared?', -+ label=_('Shared vault'), -+ flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'}, -+ ), -+ Str( -+ 'username?', -+ label=_('Vault user'), -+ flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'}, -+ ), - ) - - def get_dn(self, *keys, **options): -@@ -523,6 +538,17 @@ class vault(LDAPObject): - raise errors.AuthenticationError( - message=_('Invalid credentials')) - -+ def get_container_attribute(self, entry, options): -+ if options.get('raw', False): -+ return -+ container_dn = DN(self.container_dn, self.api.env.basedn) -+ if entry.dn.endswith(DN(('cn', 'services'), container_dn)): -+ entry['service'] = entry.dn[1]['cn'] -+ elif entry.dn.endswith(DN(('cn', 'shared'), container_dn)): -+ entry['shared'] = True -+ elif entry.dn.endswith(DN(('cn', 'users'), container_dn)): -+ entry['username'] = entry.dn[1]['cn'] -+ - - @register() - class vault_add(PKQuery, Local): -@@ -738,6 +764,10 @@ class vault_add_internal(LDAPCreate): - - return dn - -+ def post_callback(self, ldap, dn, entry, *keys, **options): -+ self.obj.get_container_attribute(entry, options) -+ return dn -+ - - @register() - class vault_del(LDAPDelete): -@@ -806,6 +836,11 @@ class vault_find(LDAPSearch): - - return (filter, base_dn, scope) - -+ def post_callback(self, ldap, entries, truncated, *args, **options): -+ for entry in entries: -+ self.obj.get_container_attribute(entry, options) -+ return truncated -+ - def exc_callback(self, args, options, exc, call_func, *call_args, - **call_kwargs): - if call_func.__name__ == 'find_entries': -@@ -836,6 +871,10 @@ class vault_mod(LDAPUpdate): - - return dn - -+ def post_callback(self, ldap, dn, entry_attrs, *keys, **options): -+ self.obj.get_container_attribute(entry_attrs, options) -+ return dn -+ - - @register() - class vault_show(LDAPRetrieve): -@@ -854,6 +893,10 @@ class vault_show(LDAPRetrieve): - - return dn - -+ def post_callback(self, ldap, dn, entry_attrs, *keys, **options): -+ self.obj.get_container_attribute(entry_attrs, options) -+ return dn -+ - - @register() - class vaultconfig(Object): -@@ -1452,6 +1495,7 @@ class VaultModMember(LDAPModMember): - def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): - for fail in failed.itervalues(): - fail['services'] = fail.pop('service', []) -+ self.obj.get_container_attribute(entry_attrs, options) - return completed, dn - - --- -2.4.3 - diff --git a/SOURCES/0083-Server-Upgrade-Start-DS-before-CA-is-started.patch b/SOURCES/0083-Server-Upgrade-Start-DS-before-CA-is-started.patch deleted file mode 100644 index db04618..0000000 --- a/SOURCES/0083-Server-Upgrade-Start-DS-before-CA-is-started.patch +++ /dev/null @@ -1,61 +0,0 @@ -From dc32238b191a84f0677e2d3ae47f5b319946faf9 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Tue, 18 Aug 2015 18:01:09 +0200 -Subject: [PATCH] Server Upgrade: Start DS before CA is started. - -https://fedorahosted.org/freeipa/ticket/5232 - -Reviewed-By: Jan Cholasta ---- - ipaserver/install/server/upgrade.py | 14 ++++++++++++-- - 1 file changed, 12 insertions(+), 2 deletions(-) - -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index 692d0c77e0683f4ad35ebbc14d5a34decc098deb..a57682a4bbdaab2a15b4e415223e2f5faa67ba73 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -1328,6 +1328,13 @@ def upgrade_configuration(): - raise RuntimeError("ipa-rewrite.conf doesn't exists (is this server?)") - - # Ok, we are an IPA server, do the additional tests -+ ds_serverid = installutils.realm_to_serverid(api.env.realm) -+ ds = dsinstance.DsInstance() -+ -+ # start DS, CA will not start without running DS, and cause error -+ ds_running = ds.is_running() -+ if not ds_running: -+ ds.start(ds_serverid) - - check_certs() - -@@ -1359,7 +1366,6 @@ def upgrade_configuration(): - 'ca.crl.MasterCRL.enableCRLUpdates', '=') - sub_dict['CLONE']='#' if crl.lower() == 'true' else '' - -- ds_serverid = installutils.realm_to_serverid(api.env.realm) - ds_dirname = dsinstance.config_dirname(ds_serverid) - - upgrade_file(sub_dict, paths.HTTPD_IPA_CONF, -@@ -1396,7 +1402,6 @@ def upgrade_configuration(): - http.change_mod_nss_port_from_http() - http.configure_certmonger_renewal_guard() - -- ds = dsinstance.DsInstance() - ds.configure_dirsrv_ccache() - - # ldap2 connection is not valid after DS restart, close connection otherwise -@@ -1526,6 +1531,11 @@ def upgrade_configuration(): - - set_sssd_domain_option('ipa_server_mode', 'True') - -+ if ds_running and not ds.is_running(): -+ ds.start(ds_serverid) -+ elif not ds_running and ds.is_running(): -+ ds.stop(ds_serverid) -+ - - def upgrade_check(options): - try: --- -2.4.3 - diff --git a/SOURCES/0083-server-install-do-not-prompt-for-cert-file-PIN-repea.patch b/SOURCES/0083-server-install-do-not-prompt-for-cert-file-PIN-repea.patch new file mode 100644 index 0000000..d701518 --- /dev/null +++ b/SOURCES/0083-server-install-do-not-prompt-for-cert-file-PIN-repea.patch @@ -0,0 +1,98 @@ +From 620dced81e4ef95522fcaf50c0b3e060f911754f Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Tue, 16 Aug 2016 17:34:06 +0200 +Subject: [PATCH] server install: do not prompt for cert file PIN repeatedly + +Prompt for PIN only once in interactive mode. + +This fixes ipa-server-install, ipa-server-certinstall and +ipa-replica-prepare prompting over and over when the PIN is empty. + +https://fedorahosted.org/freeipa/ticket/6032 + +Reviewed-By: Pavel Vomacka +--- + ipaserver/install/ipa_replica_prepare.py | 6 +++--- + ipaserver/install/ipa_server_certinstall.py | 3 ++- + ipaserver/install/server/install.py | 6 +++--- + 3 files changed, 8 insertions(+), 7 deletions(-) + +diff --git a/ipaserver/install/ipa_replica_prepare.py b/ipaserver/install/ipa_replica_prepare.py +index fdd32f0c8437a0d8c3947d57089662ea09bb2304..80813086c6a7212bdb6ef9d54202b28808b80076 100644 +--- a/ipaserver/install/ipa_replica_prepare.py ++++ b/ipaserver/install/ipa_replica_prepare.py +@@ -303,7 +303,7 @@ class ReplicaPrepare(admintool.AdminTool): + if options.http_pin is None: + options.http_pin = installutils.read_password( + "Enter Apache Server private key unlock", +- confirm=False, validate=False) ++ confirm=False, validate=False, retry=False) + if options.http_pin is None: + raise admintool.ScriptError( + "Apache Server private key unlock password required") +@@ -317,7 +317,7 @@ class ReplicaPrepare(admintool.AdminTool): + if options.dirsrv_pin is None: + options.dirsrv_pin = installutils.read_password( + "Enter Directory Server private key unlock", +- confirm=False, validate=False) ++ confirm=False, validate=False, retry=False) + if options.dirsrv_pin is None: + raise admintool.ScriptError( + "Directory Server private key unlock password required") +@@ -331,7 +331,7 @@ class ReplicaPrepare(admintool.AdminTool): + if options.pkinit_pin is None: + options.pkinit_pin = installutils.read_password( + "Enter Kerberos KDC private key unlock", +- confirm=False, validate=False) ++ confirm=False, validate=False, retry=False) + if options.pkinit_pin is None: + raise admintool.ScriptError( + "Kerberos KDC private key unlock password required") +diff --git a/ipaserver/install/ipa_server_certinstall.py b/ipaserver/install/ipa_server_certinstall.py +index 5ab47303add479c7c492c251b0cf6646de681a4b..0a8fb214a232e60a89b6c06940b928f97c007b93 100644 +--- a/ipaserver/install/ipa_server_certinstall.py ++++ b/ipaserver/install/ipa_server_certinstall.py +@@ -92,7 +92,8 @@ class ServerCertInstall(admintool.AdminTool): + + if self.options.pin is None: + self.options.pin = installutils.read_password( +- "Enter private key unlock", confirm=False, validate=False) ++ "Enter private key unlock", ++ confirm=False, validate=False, retry=False) + if self.options.pin is None: + raise admintool.ScriptError( + "Private key unlock password required") +diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py +index 86b8402750b503ea7dacd1f4c59c82d9bd4082e6..b33b0243d4d909a561b59d93f0014c390146b333 100644 +--- a/ipaserver/install/server/install.py ++++ b/ipaserver/install/server/install.py +@@ -488,7 +488,7 @@ def install_check(installer): + if options.http_pin is None: + options.http_pin = installutils.read_password( + "Enter Apache Server private key unlock", +- confirm=False, validate=False) ++ confirm=False, validate=False, retry=False) + if options.http_pin is None: + sys.exit( + "Apache Server private key unlock password required") +@@ -504,7 +504,7 @@ def install_check(installer): + if options.dirsrv_pin is None: + options.dirsrv_pin = read_password( + "Enter Directory Server private key unlock", +- confirm=False, validate=False) ++ confirm=False, validate=False, retry=False) + if options.dirsrv_pin is None: + sys.exit( + "Directory Server private key unlock password required") +@@ -520,7 +520,7 @@ def install_check(installer): + if options.pkinit_pin is None: + options.pkinit_pin = read_password( + "Enter Kerberos KDC private key unlock", +- confirm=False, validate=False) ++ confirm=False, validate=False, retry=False) + if options.pkinit_pin is None: + sys.exit( + "Kerberos KDC private key unlock password required") +-- +2.9.3 + diff --git a/SOURCES/0084-cert-request-remove-allowed-extensions-check.patch b/SOURCES/0084-cert-request-remove-allowed-extensions-check.patch deleted file mode 100644 index ee3a5c0..0000000 --- a/SOURCES/0084-cert-request-remove-allowed-extensions-check.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 5a39de97688f517acf5dea952c82b6535352744b Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Thu, 13 Aug 2015 01:42:06 -0400 -Subject: [PATCH] cert-request: remove allowed extensions check - -cert-request currently permits a limited number of request -extensions; uncommon and esoteric extensions are prohibited and this -limits the usefulness of custom profiles. - -The Dogtag profile has total control over what goes into the final -certificate and has the option to reject request based on the -request extensions present or their values, so there is little -reason to restrict what extensions can be used in FreeIPA. Remove -the check. - -Fixes: https://fedorahosted.org/freeipa/ticket/5205 -Reviewed-By: Jan Cholasta ---- - ipalib/plugins/cert.py | 22 +++------------------- - 1 file changed, 3 insertions(+), 19 deletions(-) - -diff --git a/ipalib/plugins/cert.py b/ipalib/plugins/cert.py -index daa698b54f2cc1b645245d312fae0f0500239ea2..7a07039a8488cc11d9bf05ef23642b8059d5921e 100644 ---- a/ipalib/plugins/cert.py -+++ b/ipalib/plugins/cert.py -@@ -306,15 +306,6 @@ class cert_request(VirtualCommand): - ), - ) - -- _allowed_extensions = { -- '2.5.29.14': None, # Subject Key Identifier -- '2.5.29.15': None, # Key Usage -- '2.5.29.17': 'request certificate with subjectaltname', -- '2.5.29.19': None, # Basic Constraints -- '2.5.29.37': None, # Extended Key Usage -- '1.2.840.10070.8.1': None, # IECUserRoles (DNP3 / IEC 62351-8) -- } -- - def execute(self, csr, **kw): - ca_enabled_check() - -@@ -376,12 +367,10 @@ class cert_request(VirtualCommand): - raise errors.CertificateOperationError( - error=_("Failure decoding Certificate Signing Request: %s") % e) - -- # host principals may bypass allowed ext check -+ # self-service and host principals may bypass SAN permission check - if bind_principal != principal and bind_principal_type != HOST: -- for ext in extensions: -- operation = self._allowed_extensions.get(ext) -- if operation: -- self.check_access(operation) -+ if '2.5.29.17' in extensions: -+ self.check_access('request certificate with subjectaltname') - - dn = None - principal_obj = None -@@ -433,11 +422,6 @@ class cert_request(VirtualCommand): - "any of user's email addresses") - ) - -- for ext in extensions: -- if ext not in self._allowed_extensions: -- raise errors.ValidationError( -- name='csr', error=_("extension %s is forbidden") % ext) -- - # We got this far so the principal entry exists, can we write it? - if not ldap.can_write(dn, "usercertificate"): - raise errors.ACIError(info=_("Insufficient 'write' privilege " --- -2.4.3 - diff --git a/SOURCES/0084-service-add-flag-to-allow-S4U2Self.patch b/SOURCES/0084-service-add-flag-to-allow-S4U2Self.patch new file mode 100644 index 0000000..2655bd6 --- /dev/null +++ b/SOURCES/0084-service-add-flag-to-allow-S4U2Self.patch @@ -0,0 +1,122 @@ +From e885fdff4d1bfee23bd41e6e64f64680ae643624 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Thu, 11 Aug 2016 11:52:05 +0300 +Subject: [PATCH] service: add flag to allow S4U2Self + +Prerequisite for: https://fedorahosted.org/freeipa/ticket/5764 + +Reviewed-By: Stanislav Laznicka +--- + API.txt | 12 ++++++++---- + VERSION | 4 ++-- + ipaserver/plugins/service.py | 7 +++++++ + 3 files changed, 17 insertions(+), 6 deletions(-) + +diff --git a/API.txt b/API.txt +index 535d8ec9a4990395207e2455a09a8c1bdef5529a..5b83bfbd0b457b77e0522ab7d83abfae4df3ebe9 100644 +--- a/API.txt ++++ b/API.txt +@@ -2260,7 +2260,7 @@ output: Output('summary', type=[, ]) + output: Output('value', type=[]) + output: Output('warning', type=[, , ]) + command: host_add/1 +-args: 1,24,3 ++args: 1,25,3 + arg: Str('fqdn', cli_name='hostname') + option: Str('addattr*', cli_name='addattr') + option: Flag('all', autofill=True, cli_name='all', default=False) +@@ -2269,6 +2269,7 @@ option: Flag('force', autofill=True, default=False) + option: Str('ip_address?') + option: Str('ipaassignedidview?') + option: Bool('ipakrbokasdelegate?', cli_name='ok_as_delegate') ++option: Bool('ipakrboktoauthasdelegate?', cli_name='ok_to_auth_as_delegate') + option: Bool('ipakrbrequirespreauth?', cli_name='requires_pre_auth') + option: Str('ipasshpubkey*', cli_name='sshpubkey') + option: Str('krbprincipalauthind*', cli_name='auth_ind') +@@ -2437,7 +2438,7 @@ output: ListOfEntries('result') + output: Output('summary', type=[, ]) + output: Output('truncated', type=[]) + command: host_mod/1 +-args: 1,25,3 ++args: 1,26,3 + arg: Str('fqdn', cli_name='hostname') + option: Str('addattr*', cli_name='addattr') + option: Flag('all', autofill=True, cli_name='all', default=False) +@@ -2445,6 +2446,7 @@ option: Str('delattr*', cli_name='delattr') + option: Str('description?', autofill=False, cli_name='desc') + option: Str('ipaassignedidview?', autofill=False) + option: Bool('ipakrbokasdelegate?', autofill=False, cli_name='ok_as_delegate') ++option: Bool('ipakrboktoauthasdelegate?', autofill=False, cli_name='ok_to_auth_as_delegate') + option: Bool('ipakrbrequirespreauth?', autofill=False, cli_name='requires_pre_auth') + option: Str('ipasshpubkey*', autofill=False, cli_name='sshpubkey') + option: Str('krbprincipalauthind*', autofill=False, cli_name='auth_ind') +@@ -4293,13 +4295,14 @@ output: Entry('result') + output: Output('summary', type=[, ]) + output: PrimaryKey('value') + command: service_add/1 +-args: 1,12,3 ++args: 1,13,3 + arg: Principal('krbcanonicalname', cli_name='canonical_principal') + option: Str('addattr*', cli_name='addattr') + option: Flag('all', autofill=True, cli_name='all', default=False) + option: Flag('force', autofill=True, default=False) + option: StrEnum('ipakrbauthzdata*', cli_name='pac_type', values=[u'MS-PAC', u'PAD', u'NONE']) + option: Bool('ipakrbokasdelegate?', cli_name='ok_as_delegate') ++option: Bool('ipakrboktoauthasdelegate?', cli_name='ok_to_auth_as_delegate') + option: Bool('ipakrbrequirespreauth?', cli_name='requires_pre_auth') + option: Str('krbprincipalauthind*', cli_name='auth_ind') + option: Flag('no_members', autofill=True, default=False) +@@ -4435,13 +4438,14 @@ output: ListOfEntries('result') + output: Output('summary', type=[, ]) + output: Output('truncated', type=[]) + command: service_mod/1 +-args: 1,14,3 ++args: 1,15,3 + arg: Principal('krbcanonicalname', cli_name='canonical_principal') + option: Str('addattr*', cli_name='addattr') + option: Flag('all', autofill=True, cli_name='all', default=False) + option: Str('delattr*', cli_name='delattr') + option: StrEnum('ipakrbauthzdata*', autofill=False, cli_name='pac_type', values=[u'MS-PAC', u'PAD', u'NONE']) + option: Bool('ipakrbokasdelegate?', autofill=False, cli_name='ok_as_delegate') ++option: Bool('ipakrboktoauthasdelegate?', autofill=False, cli_name='ok_to_auth_as_delegate') + option: Bool('ipakrbrequirespreauth?', autofill=False, cli_name='requires_pre_auth') + option: Str('krbprincipalauthind*', autofill=False, cli_name='auth_ind') + option: Principal('krbprincipalname*', autofill=False, cli_name='principal') +diff --git a/VERSION b/VERSION +index ca489965050f32d2d8987dfd251ec2b2a0ba1768..a8b89ed305bcfdf2990a7400d005a68d734fa7e8 100644 +--- a/VERSION ++++ b/VERSION +@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 + # # + ######################################################## + IPA_API_VERSION_MAJOR=2 +-IPA_API_VERSION_MINOR=211 +-# Last change: mbabinsk: allow 'value' output param in commands without primary key ++IPA_API_VERSION_MINOR=212 ++# Last change: ab: service: add flag to allow S4U2Self +diff --git a/ipaserver/plugins/service.py b/ipaserver/plugins/service.py +index a44dcaa5e348d3deedda6c0b4f55760ad873cf49..04d1916fe989a8651bcc4d44f1914c460be1081c 100644 +--- a/ipaserver/plugins/service.py ++++ b/ipaserver/plugins/service.py +@@ -171,11 +171,18 @@ ticket_flags_params = ( + doc=_('Client credentials may be delegated to the service'), + flags=['virtual_attribute', 'no_search'], + ), ++ Bool('ipakrboktoauthasdelegate?', ++ cli_name='ok_to_auth_as_delegate', ++ label=_('Trusted to authenticate as user'), ++ doc=_('The service is allowed to authenticate on behalf of a client'), ++ flags=['virtual_attribute', 'no_search'], ++ ), + ) + + _ticket_flags_map = { + 'ipakrbrequirespreauth': 0x00000080, + 'ipakrbokasdelegate': 0x00100000, ++ 'ipakrboktoauthasdelegate': 0x00200000, + } + + _ticket_flags_default = _ticket_flags_map['ipakrbrequirespreauth'] +-- +2.7.4 + diff --git a/SOURCES/0085-Add-trusted-to-auth-as-user-checkbox.patch b/SOURCES/0085-Add-trusted-to-auth-as-user-checkbox.patch new file mode 100644 index 0000000..46d91b1 --- /dev/null +++ b/SOURCES/0085-Add-trusted-to-auth-as-user-checkbox.patch @@ -0,0 +1,50 @@ +From 9bad7f0d876a0ed4f7ee9fdff6ca6d117debf404 Mon Sep 17 00:00:00 2001 +From: Pavel Vomacka +Date: Thu, 11 Aug 2016 18:53:55 +0200 +Subject: [PATCH] Add 'trusted to auth as user' checkbox + +Add new checkbox to host and service details page + +Prerequisite for: https://fedorahosted.org/freeipa/ticket/5764 + +Reviewed-By: Stanislav Laznicka +--- + install/ui/src/freeipa/host.js | 5 +++++ + install/ui/src/freeipa/service.js | 5 +++++ + 2 files changed, 10 insertions(+) + +diff --git a/install/ui/src/freeipa/host.js b/install/ui/src/freeipa/host.js +index 33d443c2bc96c385bd13abf4d85adda6e51db718..87cf264ef20b79aceed639f45d926fd7aef19edf 100644 +--- a/install/ui/src/freeipa/host.js ++++ b/install/ui/src/freeipa/host.js +@@ -142,6 +142,11 @@ return { + flags: ['w_if_no_aci'] + }, + { ++ name: 'ipakrboktoauthasdelegate', ++ $type: 'checkbox', ++ acl_param: 'krbticketflags' ++ }, ++ { + name: 'ipaassignedidview', + $type: 'link', + label: '@i18n:objects.idview.ipaassignedidview', +diff --git a/install/ui/src/freeipa/service.js b/install/ui/src/freeipa/service.js +index 35d486605ebfee41d8b3ffa5bb77bf9e72a60c01..30e336c35b8eece2e5e3ef55629d0c98f097fbf5 100644 +--- a/install/ui/src/freeipa/service.js ++++ b/install/ui/src/freeipa/service.js +@@ -142,6 +142,11 @@ return { + acl_param: 'krbticketflags' + }, + { ++ name: 'ipakrboktoauthasdelegate', ++ $type: 'checkbox', ++ acl_param: 'krbticketflags' ++ }, ++ { + name: 'ipakrbrequirespreauth', + $type: 'checkbox', + acl_param: 'krbticketflags' +-- +2.7.4 + diff --git a/SOURCES/0085-client-Add-description-of-ip-address-and-all-ip-addr.patch b/SOURCES/0085-client-Add-description-of-ip-address-and-all-ip-addr.patch deleted file mode 100644 index 0f5366a..0000000 --- a/SOURCES/0085-client-Add-description-of-ip-address-and-all-ip-addr.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 492e167705075bcecc6f7a79a6476496a2303986 Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Wed, 19 Aug 2015 12:28:34 +0200 -Subject: [PATCH] client: Add description of --ip-address and - --all-ip-addresses to man page - -https://fedorahosted.org/freeipa/ticket/4249 - -Reviewed-By: Martin Basti ---- - ipa-client/man/ipa-client-install.1 | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/ipa-client/man/ipa-client-install.1 b/ipa-client/man/ipa-client-install.1 -index 41437f0ec2fe432c8088cb57cfe01b482e4116e6..0fafd8a3f2ee24b400b1cbeada4ddf7cea9493b0 100644 ---- a/ipa-client/man/ipa-client-install.1 -+++ b/ipa-client/man/ipa-client-install.1 -@@ -180,6 +180,12 @@ Request certificate for the machine. The certificate will be stored in /etc/ipa/ - \fB\-\-automount\-location\fR=\fILOCATION\fR - Configure automount by running ipa\-client\-automount(1) with \fILOCATION\fR as - automount location. -+.TP -+\fB\-\-ip\-address\fR=\fIIP_ADDRESS\fR -+Use \fIIP_ADDRESS\fR in DNS A/AAAA record for this host. May be specified multiple times to add multiple DNS records. -+.TP -+\fB\-\-all\-ip\-addresses\fR -+Create DNS A/AAAA record for each IP address on this host. - - .SS "SSSD OPTIONS" - .TP --- -2.4.3 - diff --git a/SOURCES/0086-Added-new-authentication-method.patch b/SOURCES/0086-Added-new-authentication-method.patch new file mode 100644 index 0000000..fb222f6 --- /dev/null +++ b/SOURCES/0086-Added-new-authentication-method.patch @@ -0,0 +1,79 @@ +From b620de7a08aa626290f166213bb8e1eac62a47be Mon Sep 17 00:00:00 2001 +From: Tiboris +Date: Tue, 16 Aug 2016 14:13:29 +0200 +Subject: [PATCH] Added new authentication method + +Addressing ticket https://fedorahosted.org/freeipa/ticket/5764 + +Reviewed-By: Stanislav Laznicka +--- + ipaserver/plugins/xmlserver.py | 6 +++++- + ipaserver/rpcserver.py | 17 +++++++++++++---- + 2 files changed, 18 insertions(+), 5 deletions(-) + +diff --git a/ipaserver/plugins/xmlserver.py b/ipaserver/plugins/xmlserver.py +index d8fe24e0cb407603e9898e934229c9373f3c8b62..08c7456ed6dbfcc59f532314894031fba584e20a 100644 +--- a/ipaserver/plugins/xmlserver.py ++++ b/ipaserver/plugins/xmlserver.py +@@ -28,12 +28,16 @@ register = Registry() + + + if api.env.context in ('server', 'lite'): +- from ipaserver.rpcserver import wsgi_dispatch, xmlserver, jsonserver_kerb, jsonserver_session, login_kerberos, login_password, change_password, sync_token, xmlserver_session ++ from ipaserver.rpcserver import ( ++ wsgi_dispatch, xmlserver, jsonserver_kerb, jsonserver_session, ++ login_kerberos, login_x509, login_password, change_password, ++ sync_token, xmlserver_session) + register()(wsgi_dispatch) + register()(xmlserver) + register()(jsonserver_kerb) + register()(jsonserver_session) + register()(login_kerberos) ++ register()(login_x509) + register()(login_password) + register()(change_password) + register()(sync_token) +diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py +index d036f3c27521f17709672b830d5aa58167c76b34..e48dc3498d6ed8feb6ea44a9a678a8b8c50e8d9b 100644 +--- a/ipaserver/rpcserver.py ++++ b/ipaserver/rpcserver.py +@@ -857,16 +857,16 @@ class jsonserver_kerb(jsonserver, KerberosWSGIExecutioner): + key = '/json' + + +-class login_kerberos(Backend, KerberosSession, HTTP_Status): +- key = '/session/login_kerberos' ++class KerberosLogin(Backend, KerberosSession, HTTP_Status): ++ key = None + + def _on_finalize(self): +- super(login_kerberos, self)._on_finalize() ++ super(KerberosLogin, self)._on_finalize() + self.api.Backend.wsgi_dispatch.mount(self, self.key) + self.kerb_session_on_finalize() + + def __call__(self, environ, start_response): +- self.debug('WSGI login_kerberos.__call__:') ++ self.debug('WSGI KerberosLogin.__call__:') + + # Get the ccache created by mod_auth_gssapi + user_ccache_name=environ.get('KRB5CCNAME') +@@ -876,6 +876,15 @@ class login_kerberos(Backend, KerberosSession, HTTP_Status): + + return self.finalize_kerberos_acquisition('login_kerberos', user_ccache_name, environ, start_response) + ++ ++class login_kerberos(KerberosLogin): ++ key = '/session/login_kerberos' ++ ++ ++class login_x509(KerberosLogin): ++ key = '/session/login_x509' ++ ++ + class login_password(Backend, KerberosSession, HTTP_Status): + + content_type = 'text/plain' +-- +2.7.4 + diff --git a/SOURCES/0086-Backup-resore-authentication-control-configuration.patch b/SOURCES/0086-Backup-resore-authentication-control-configuration.patch deleted file mode 100644 index f47ed94..0000000 --- a/SOURCES/0086-Backup-resore-authentication-control-configuration.patch +++ /dev/null @@ -1,115 +0,0 @@ -From fcd40cd3f47b15dae8c2e964e890b69906045f32 Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Wed, 19 Aug 2015 08:10:03 +0200 -Subject: [PATCH] Backup/resore authentication control configuration - -https://fedorahosted.org/freeipa/ticket/5071 - -Reviewed-By: Martin Babinsky ---- - ipaplatform/base/tasks.py | 15 +++++++++++++++ - ipaplatform/redhat/authconfig.py | 6 ++++++ - ipaplatform/redhat/tasks.py | 8 ++++++++ - ipaserver/install/ipa_backup.py | 4 ++++ - ipaserver/install/ipa_restore.py | 4 ++++ - 5 files changed, 37 insertions(+) - -diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py -index 08fdb494a3bfc6c59bebf4af2f72f54a26724700..65715145af533c90038b3e8667da07fd28b7ec56 100644 ---- a/ipaplatform/base/tasks.py -+++ b/ipaplatform/base/tasks.py -@@ -150,6 +150,21 @@ class BaseTaskNamespace(object): - - return - -+ def backup_auth_configuration(self, path): -+ """ -+ Create backup of access control configuration. -+ :param path: store the backup here. This will be passed to -+ restore_auth_configuration as well. -+ """ -+ return -+ -+ def restore_auth_configuration(self, path): -+ """ -+ Restore backup of access control configuration. -+ :param path: restore the backup from here. -+ """ -+ return -+ - def set_selinux_booleans(self, required_settings, backup_func=None): - """Set the specified SELinux booleans - -diff --git a/ipaplatform/redhat/authconfig.py b/ipaplatform/redhat/authconfig.py -index 901eb51637d193d80bc3927929d7d436065ec262..edefee8b2b4922ad67cdbac158615ef32c776bb4 100644 ---- a/ipaplatform/redhat/authconfig.py -+++ b/ipaplatform/redhat/authconfig.py -@@ -84,3 +84,9 @@ class RedHatAuthConfig(object): - - args = self.build_args() - ipautil.run(["/usr/sbin/authconfig"] + args) -+ -+ def backup(self, path): -+ ipautil.run(["/usr/sbin/authconfig", "--savebackup", path]) -+ -+ def restore(self, path): -+ ipautil.run(["/usr/sbin/authconfig", "--restorebackup", path]) -diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py -index b26604aa736eb472c88bc0dcbc3a4b515712ce9d..1af99d318c6745b1e5285c7829c2b292f86c8390 100644 ---- a/ipaplatform/redhat/tasks.py -+++ b/ipaplatform/redhat/tasks.py -@@ -161,6 +161,14 @@ class RedHatTaskNamespace(BaseTaskNamespace): - auth_config.add_option("nostart") - auth_config.execute() - -+ def backup_auth_configuration(self, path): -+ auth_config = RedHatAuthConfig() -+ auth_config.backup(path) -+ -+ def restore_auth_configuration(self, path): -+ auth_config = RedHatAuthConfig() -+ auth_config.restore(path) -+ - def reload_systemwide_ca_store(self): - try: - ipautil.run([paths.UPDATE_CA_TRUST]) -diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py -index d7afb3654b09e88321f1ce9f279749b19c2f6414..0ba44b280dfb7c9d9cbbe2470392c3c98ef35bcc 100644 ---- a/ipaserver/install/ipa_backup.py -+++ b/ipaserver/install/ipa_backup.py -@@ -41,6 +41,7 @@ from ipapython import ipaldap - from ipalib.session import ISO8601_DATETIME_FMT - from ipalib.constants import CACERT - from ConfigParser import SafeConfigParser -+from ipaplatform.tasks import tasks - - """ - A test gpg can be generated like this: -@@ -302,6 +303,9 @@ class Backup(admintool.AdminTool): - self.db2ldif(instance, 'userRoot', online=options.online) - self.db2bak(instance, online=options.online) - if not options.data_only: -+ # create backup of auth configuration -+ auth_backup_path = os.path.join(paths.VAR_LIB_IPA, 'auth_backup') -+ tasks.backup_auth_configuration(auth_backup_path) - self.file_backup(options) - self.finalize_backup(options.data_only, options.gpg, options.gpg_keyring) - -diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py -index 528a6daf0d4b6d3dfc69b6bbf8e8b05ad91ce02d..8960626d0f0e438ef198e2d92803983e520051a8 100644 ---- a/ipaserver/install/ipa_restore.py -+++ b/ipaserver/install/ipa_restore.py -@@ -386,6 +386,10 @@ class Restore(admintool.AdminTool): - self.log.info('Starting Directory Server') - dirsrv.start(capture_output=False) - else: -+ # restore access controll configuration -+ auth_backup_path = os.path.join(paths.VAR_LIB_IPA, 'auth_backup') -+ if os.path.exists(auth_backup_path): -+ tasks.restore_auth_configuration(auth_backup_path) - # explicitly enable then disable the pki tomcatd service to - # re-register its instance. FIXME, this is really wierd. - services.knownservices.pki_tomcatd.enable() --- -2.4.3 - diff --git a/SOURCES/0087-Add-flag-to-list-all-service-and-user-vaults.patch b/SOURCES/0087-Add-flag-to-list-all-service-and-user-vaults.patch deleted file mode 100644 index e70f3de..0000000 --- a/SOURCES/0087-Add-flag-to-list-all-service-and-user-vaults.patch +++ /dev/null @@ -1,179 +0,0 @@ -From 0fac76b07e7b15eb46e4db942d5c9890b704549d Mon Sep 17 00:00:00 2001 -From: Christian Heimes -Date: Wed, 19 Aug 2015 13:32:01 +0200 -Subject: [PATCH] Add flag to list all service and user vaults - -The vault-find plugin has two additional arguments to list all -service vaults or user vaults. Since the name of a vault is only unique -for a particular user or service, the commands also print the vault user -or vault service. The virtual attributes were added in rev -01dd951ddc0181b559eb3dd5ff0336c81e245628. - -Example: - -$ ipa vault-find --users ----------------- -2 vaults matched ----------------- - Vault name: myvault - Type: standard - Vault user: admin - - Vault name: UserVault - Type: standard - Vault user: admin ----------------------------- -Number of entries returned 2 ----------------------------- - -$ ipa vault-find --services ----------------- -2 vaults matched ----------------- - Vault name: myvault - Type: standard - Vault service: HTTP/ipatest.freeipa.local@FREEIPA.LOCAL - - Vault name: myvault - Type: standard - Vault service: ldap/ipatest.freeipa.local@FREEIPA.LOCAL ----------------------------- -Number of entries returned 2 ----------------------------- - -https://fedorahosted.org/freeipa/ticket/5150 - -Reviewed-By: Jan Cholasta ---- - API.txt | 4 +++- - VERSION | 4 ++-- - ipalib/plugins/vault.py | 48 +++++++++++++++++++++++++++++++++--------------- - 3 files changed, 38 insertions(+), 18 deletions(-) - -diff --git a/API.txt b/API.txt -index a39b22b602e0baf5d283732d18d83b2a25d5cf50..f23d9a40c647a3c4d209419631794cd36e8e5e2f 100644 ---- a/API.txt -+++ b/API.txt -@@ -5508,7 +5508,7 @@ output: Output('result', , None) - output: Output('summary', (, ), None) - output: ListOfPrimaryKeys('value', None, None) - command: vault_find --args: 1,13,4 -+args: 1,15,4 - arg: Str('criteria?', noextrawhitespace=False) - option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') - option: Str('cn', attribute=True, autofill=False, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=False) -@@ -5518,10 +5518,12 @@ option: Flag('no_members', autofill=True, default=False, exclude='webui') - option: Flag('pkey_only?', autofill=True, default=False) - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') - option: Str('service?') -+option: Flag('services?', autofill=True, default=False) - option: Flag('shared?', autofill=True, default=False) - option: Int('sizelimit?', autofill=False, minvalue=0) - option: Int('timelimit?', autofill=False, minvalue=0) - option: Str('username?', cli_name='user') -+option: Flag('users?', autofill=True, default=False) - option: Str('version?', exclude='webui') - output: Output('count', , None) - output: ListOfEntries('result', (, ), Gettext('A list of LDAP entries', domain='ipa', localedir=None)) -diff --git a/VERSION b/VERSION -index 6569eeb70fa4e8065b5abb9dc89bd4cc6d42bd15..31a4af4a819415740e5c8db9259f934e13418cb5 100644 ---- a/VERSION -+++ b/VERSION -@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 - # # - ######################################################## - IPA_API_VERSION_MAJOR=2 --IPA_API_VERSION_MINOR=150 --# Last change: pvoborni - change type of vault type option to StrEnum -+IPA_API_VERSION_MINOR=151 -+# Last change: cheimes - Add flag to list all service and user vaults -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index 712e2d5ddfa723eb84b80a261289a7cf1c75674f..83dc085b5aadb4e2878e29d17449f0808cc7a9c2 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -343,21 +343,11 @@ class vault(LDAPObject): - """ - Generates vault DN from parameters. - """ -- - service = options.get('service') - shared = options.get('shared') - user = options.get('username') - -- count = 0 -- if service: -- count += 1 -- -- if shared: -- count += 1 -- -- if user: -- count += 1 -- -+ count = (bool(service) + bool(shared) + bool(user)) - if count > 1: - raise errors.MutuallyExclusiveError( - reason=_('Service, shared, and user options ' + -@@ -387,8 +377,10 @@ class vault(LDAPObject): - parent_dn = DN(('cn', service), ('cn', 'services'), container_dn) - elif shared: - parent_dn = DN(('cn', 'shared'), container_dn) -- else: -+ elif user: - parent_dn = DN(('cn', user), ('cn', 'users'), container_dn) -+ else: -+ raise RuntimeError - - return DN(rdns, parent_dn) - -@@ -814,7 +806,16 @@ class vault_del(LDAPDelete): - class vault_find(LDAPSearch): - __doc__ = _('Search for vaults.') - -- takes_options = LDAPSearch.takes_options + vault_options -+ takes_options = LDAPSearch.takes_options + vault_options + ( -+ Flag( -+ 'services?', -+ doc=_('List all service vaults'), -+ ), -+ Flag( -+ 'users?', -+ doc=_('List all user vaults'), -+ ), -+ ) - - has_output_params = LDAPSearch.has_output_params - -@@ -832,9 +833,26 @@ class vault_find(LDAPSearch): - raise errors.InvocationError( - format=_('KRA service is not enabled')) - -- base_dn = self.obj.get_dn(None, **options) -+ if options.get('users') or options.get('services'): -+ mutex = ['service', 'services', 'shared', 'username', 'users'] -+ count = sum(bool(options.get(option)) for option in mutex) -+ if count > 1: -+ raise errors.MutuallyExclusiveError( -+ reason=_('Service(s), shared, and user(s) options ' + -+ 'cannot be specified simultaneously')) -+ -+ scope = ldap.SCOPE_SUBTREE -+ container_dn = DN(self.obj.container_dn, -+ self.api.env.basedn) -+ -+ if options.get('services'): -+ base_dn = DN(('cn', 'services'), container_dn) -+ else: -+ base_dn = DN(('cn', 'users'), container_dn) -+ else: -+ base_dn = self.obj.get_dn(None, **options) - -- return (filter, base_dn, scope) -+ return filter, base_dn, scope - - def post_callback(self, ldap, entries, truncated, *args, **options): - for entry in entries: --- -2.4.3 - diff --git a/SOURCES/0087-schema-cache-Fallback-to-en_us-when-locale-is-not-av.patch b/SOURCES/0087-schema-cache-Fallback-to-en_us-when-locale-is-not-av.patch new file mode 100644 index 0000000..0d7d637 --- /dev/null +++ b/SOURCES/0087-schema-cache-Fallback-to-en_us-when-locale-is-not-av.patch @@ -0,0 +1,39 @@ +From 444907f8dd6d840bfbb97cf65ae754f0d816f706 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Thu, 18 Aug 2016 10:59:09 +0200 +Subject: [PATCH] schema cache: Fallback to 'en_us' when locale is not + available + +https://fedorahosted.org/freeipa/ticket/6204 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/schema.py | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index 6fc70bf4b294badedd651e15b7e403cc40619f5c..8a77a15d489f067ab1312e863178458570403cc6 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -441,9 +441,15 @@ class Schema(object): + self._dict[ns] = {} + self._namespaces[ns] = _SchemaNameSpace(self, ns) + +- self._language = ( +- locale.setlocale(locale.LC_ALL, '').split('.')[0].lower() +- ) ++ # copy-paste from ipalib/rpc.py ++ try: ++ self._language = ( ++ locale.setlocale(locale.LC_ALL, '').split('.')[0].lower() ++ ) ++ except locale.Error: ++ # fallback to default locale ++ self._language = 'en_us' ++ + try: + self._fingerprint = server_info['fingerprint'] + self._expiration = server_info['expiration'] +-- +2.7.4 + diff --git a/SOURCES/0088-Add-user-stage-command.patch b/SOURCES/0088-Add-user-stage-command.patch deleted file mode 100644 index 7de1560..0000000 --- a/SOURCES/0088-Add-user-stage-command.patch +++ /dev/null @@ -1,205 +0,0 @@ -From d5e7ef94033660aed43edb0f2dc4e1eb096579aa Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Mon, 17 Aug 2015 20:11:21 +0200 -Subject: [PATCH] Add user-stage command - -This patch replaces 'stageuser-add --from-delete' with new command -user-stage. - -Original way always required to specify first and last name, and -overall combination of options was hard to manage. The new command -requires only login of deleted user (user-del --preserve). - -https://fedorahosted.org/freeipa/ticket/5041 - -Reviewed-By: Thierry Bordaz -Reviewed-By: Jan Cholasta ---- - API.txt | 10 ++++++++- - VERSION | 4 ++-- - ipalib/plugins/stageuser.py | 44 +++++++------------------------------- - ipalib/plugins/user.py | 51 +++++++++++++++++++++++++++++++++++++++++++++ - 4 files changed, 70 insertions(+), 39 deletions(-) - -diff --git a/API.txt b/API.txt -index f23d9a40c647a3c4d209419631794cd36e8e5e2f..b0f456e725a6c3d24c1071b282de5a28c3b5a671 100644 ---- a/API.txt -+++ b/API.txt -@@ -4211,7 +4211,7 @@ option: Str('displayname', attribute=True, autofill=True, cli_name='displayname' - option: Str('employeenumber', attribute=True, cli_name='employeenumber', multivalue=False, required=False) - option: Str('employeetype', attribute=True, cli_name='employeetype', multivalue=False, required=False) - option: Str('facsimiletelephonenumber', attribute=True, cli_name='fax', multivalue=True, required=False) --option: Flag('from_delete?', autofill=True, cli_name='from_delete', default=False) -+option: DeprecatedParam('from_delete?', cli_name='from_delete', default=False) - option: Str('gecos', attribute=True, autofill=True, cli_name='gecos', multivalue=False, required=False) - option: Int('gidnumber', attribute=True, cli_name='gidnumber', minvalue=1, multivalue=False, required=False) - option: Str('givenname', attribute=True, cli_name='first', multivalue=False, required=True) -@@ -5371,6 +5371,14 @@ option: Str('version?', exclude='webui') - output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) - output: Output('summary', (, ), None) - output: PrimaryKey('value', None, None) -+command: user_stage -+args: 1,2,3 -+arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=True, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=True) -+option: Flag('continue', autofill=True, cli_name='continue', default=False) -+option: Str('version?', exclude='webui') -+output: Output('result', , None) -+output: Output('summary', (, ), None) -+output: ListOfPrimaryKeys('value', None, None) - command: user_status - args: 1,4,4 - arg: Str('uid', attribute=True, cli_name='login', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_.-]{0,252}[a-zA-Z0-9_.$-]?$', primary_key=True, query=True, required=True) -diff --git a/VERSION b/VERSION -index 31a4af4a819415740e5c8db9259f934e13418cb5..9fe2f4d4f9ff6ffd42c2ee7493c385b0a432a6a0 100644 ---- a/VERSION -+++ b/VERSION -@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 - # # - ######################################################## - IPA_API_VERSION_MAJOR=2 --IPA_API_VERSION_MINOR=151 --# Last change: cheimes - Add flag to list all service and user vaults -+IPA_API_VERSION_MINOR=152 -+# Last change: mbasti - add 'user-stage' command -diff --git a/ipalib/plugins/stageuser.py b/ipalib/plugins/stageuser.py -index 41844712042c4456fc515afd316af60b612f164f..b6d98005314ab671af345aacb2e3c9f08193e155 100644 ---- a/ipalib/plugins/stageuser.py -+++ b/ipalib/plugins/stageuser.py -@@ -23,7 +23,8 @@ import posixpath - import os - from copy import deepcopy - from ipalib import api, errors --from ipalib import Flag, Int, Password, Str, Bool, StrEnum, DateTime -+from ipalib import (Flag, Int, Password, Str, Bool, StrEnum, DateTime, -+ DeprecatedParam) - from ipalib.plugable import Registry - from ipalib.plugins.baseldap import LDAPCreate, LDAPQuery, LDAPSearch, DN, entry_to_dict, pkey_to_value - from ipalib.plugins import baseldap -@@ -260,7 +261,7 @@ class stageuser_add(baseuser_add): - has_output_params = baseuser_add.has_output_params + stageuser_output_params - - takes_options = LDAPCreate.takes_options + ( -- Flag('from_delete?', -+ DeprecatedParam('from_delete?', - doc=_('Create Stage user in from a delete user'), - cli_name='from_delete', - default=False, -@@ -270,13 +271,12 @@ class stageuser_add(baseuser_add): - def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): - assert isinstance(dn, DN) - -- if not options.get('from_delete'): -- # then givenname and sn are required attributes -- if 'givenname' not in entry_attrs: -- raise errors.RequirementError(name='givenname', error=_('givenname is required')) -+ # then givenname and sn are required attributes -+ if 'givenname' not in entry_attrs: -+ raise errors.RequirementError(name='givenname', error=_('givenname is required')) - -- if 'sn' not in entry_attrs: -- raise errors.RequirementError(name='sn', error=_('sn is required')) -+ if 'sn' not in entry_attrs: -+ raise errors.RequirementError(name='sn', error=_('sn is required')) - - # we don't want an user private group to be created for this user - # add NO_UPG_MAGIC description attribute to let the DS plugin know -@@ -367,34 +367,6 @@ class stageuser_add(baseuser_add): - - return dn - -- def execute(self, *keys, **options): -- ''' -- A stage entry may be taken from the Delete container. -- In that case we rather do 'MODRDN' than 'ADD'. -- ''' -- if options.get('from_delete'): -- ldap = self.obj.backend -- -- staging_dn = self.obj.get_dn(*keys, **options) -- delete_dn = DN(staging_dn[0], self.obj.delete_container_dn, api.env.basedn) -- new_dn = DN(staging_dn[0], self.obj.stage_container_dn, api.env.basedn) -- # Check that this value is a Active user -- try: -- entry_attrs = self._exc_wrapper(keys, options, ldap.get_entry)(delete_dn, ['dn']) -- except errors.NotFound: -- self.obj.handle_not_found(*keys) -- -- self._exc_wrapper(keys, options, ldap.move_entry)( -- delete_dn, new_dn) -- entry_attrs = entry_to_dict(entry_attrs, **options) -- entry_attrs['dn'] = new_dn -- -- if self.obj.primary_key and keys[-1] is not None: -- return dict(result=entry_attrs, value=keys[-1]) -- return dict(result=entry_attrs, value=u'') -- else: -- return super(stageuser_add, self).execute(*keys, **options) -- - def post_callback(self, ldap, dn, entry_attrs, *keys, **options): - assert isinstance(dn, DN) - config = ldap.get_ipa_config() -diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py -index 418c51bdafc4e462e2decfe1e8541aaf49705cb0..d7cf9666d43b69b0cab91cfa0c98a8373f095ab5 100644 ---- a/ipalib/plugins/user.py -+++ b/ipalib/plugins/user.py -@@ -859,6 +859,57 @@ class user_undel(LDAPQuery): - value=pkey_to_value(keys[0], options), - ) - -+ -+@register() -+class user_stage(LDAPMultiQuery): -+ __doc__ = _('Move deleted user into staged area') -+ -+ has_output = output.standard_multi_delete -+ msg_summary = _('Staged user account "%(value)s"') -+ -+ def execute(self, *keys, **options): -+ staged = [] -+ failed = [] -+ -+ for key in keys[-1]: -+ single_keys = keys[:-1] + (key,) -+ multi_keys = keys[:-1] + ((key,),) -+ -+ user = self.api.Command.user_show(*single_keys, all=True)['result'] -+ new_options = {} -+ for param in self.api.Command.stageuser_add.options(): -+ try: -+ value = user[param.name] -+ except KeyError: -+ continue -+ if param.multivalue and not isinstance(value, (list, tuple)): -+ value = [value] -+ elif not param.multivalue and isinstance(value, (list, tuple)): -+ value = value[0] -+ new_options[param.name] = value -+ -+ try: -+ self.api.Command.stageuser_add(*single_keys, **new_options) -+ try: -+ self.api.Command.user_del(*multi_keys, preserve=False) -+ except errors.ExecutionError: -+ self.api.Command.stageuser_del(*multi_keys) -+ raise -+ except errors.ExecutionError: -+ if not options['continue']: -+ raise -+ failed.append(key) -+ else: -+ staged.append(key) -+ -+ return dict( -+ result=dict( -+ failed=pkey_to_value(failed, options), -+ ), -+ value=pkey_to_value(staged, options), -+ ) -+ -+ - @register() - class user_disable(LDAPQuery): - __doc__ = _('Disable a user account.') --- -2.4.3 - diff --git a/SOURCES/0088-cert-revoke-fix-permission-check-bypass-CVE-2016-540.patch b/SOURCES/0088-cert-revoke-fix-permission-check-bypass-CVE-2016-540.patch new file mode 100644 index 0000000..7876cbf --- /dev/null +++ b/SOURCES/0088-cert-revoke-fix-permission-check-bypass-CVE-2016-540.patch @@ -0,0 +1,132 @@ +From 18d4af260f777920dc2b474a588c3dcda20d8801 Mon Sep 17 00:00:00 2001 +From: Fraser Tweedale +Date: Thu, 30 Jun 2016 10:21:01 +1000 +Subject: [PATCH] cert-revoke: fix permission check bypass (CVE-2016-5404) + +The 'cert_revoke' command checks the 'revoke certificate' +permission, however, if an ACIError is raised, it then invokes the +'cert_show' command. The rational was to re-use a "host manages +certificate" check that is part of the 'cert_show' command, however, +it is sufficient that 'cert_show' executes successfully for +'cert_revoke' to recover from the ACIError continue. Therefore, +anyone with 'retrieve certificate' permission can revoke *any* +certificate and cause various kinds of DoS. + +Fix the problem by extracting the "host manages certificate" check +to its own method and explicitly calling it from 'cert_revoke'. + +Fixes: https://fedorahosted.org/freeipa/ticket/6232 +Reviewed-By: Jan Cholasta +--- + ipaserver/plugins/cert.py | 60 +++++++++++++++++++++++++---------------------- + 1 file changed, 32 insertions(+), 28 deletions(-) + +diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py +index b8df074a186ca91daa8e8f5e725724ea7bc5a663..6dd9f6ffcdcd9d051d50d912996fea2104d71dff 100644 +--- a/ipaserver/plugins/cert.py ++++ b/ipaserver/plugins/cert.py +@@ -242,6 +242,24 @@ def validate_certificate(value): + return x509.validate_certificate(value, x509.DER) + + ++def bind_principal_can_manage_cert(cert): ++ """Check that the bind principal can manage the given cert. ++ ++ ``cert`` ++ An NSS certificate object. ++ ++ """ ++ bind_principal = kerberos.Principal(getattr(context, 'principal')) ++ if not bind_principal.is_host: ++ return False ++ ++ hostname = bind_principal.hostname ++ ++ # If we have a hostname we want to verify that the subject ++ # of the certificate matches it. ++ return hostname == cert.subject.common_name #pylint: disable=E1101 ++ ++ + class BaseCertObject(Object): + takes_params = ( + Bytes( +@@ -744,18 +762,6 @@ class cert_show(Retrieve, CertMethod, VirtualCommand): + def execute(self, serial_number, all=False, raw=False, no_members=False, + **options): + ca_enabled_check() +- hostname = None +- try: +- self.check_access() +- except errors.ACIError as acierr: +- self.debug("Not granted by ACI to retrieve certificate, looking at principal") +- bind_principal = kerberos.Principal(getattr(context, 'principal')) +- if not bind_principal.is_host: +- raise acierr +- hostname = bind_principal.hostname +- +- ca_obj = api.Command.ca_show(options['cacn'])['result'] +- issuer_dn = ca_obj['ipacasubjectdn'][0] + + # Dogtag lightweight CAs have shared serial number domain, so + # we don't tell Dogtag the issuer (but we check the cert after). +@@ -763,7 +769,15 @@ class cert_show(Retrieve, CertMethod, VirtualCommand): + result = self.Backend.ra.get_certificate(str(serial_number)) + cert = x509.load_certificate(result['certificate']) + +- if DN(unicode(cert.issuer)) != DN(issuer_dn): ++ try: ++ self.check_access() ++ except errors.ACIError as acierr: ++ self.debug("Not granted by ACI to retrieve certificate, looking at principal") ++ if not bind_principal_can_manage_cert(cert): ++ raise acierr # pylint: disable=E0702 ++ ++ ca_obj = api.Command.ca_show(options['cacn'])['result'] ++ if DN(unicode(cert.issuer)) != DN(ca_obj['ipacasubjectdn'][0]): + # DN of cert differs from what we requested + raise errors.NotFound( + reason=_("Certificate with serial number %(serial)s " +@@ -789,12 +803,6 @@ class cert_show(Retrieve, CertMethod, VirtualCommand): + result['revoked'] = ('revocation_reason' in result) + self.obj._fill_owners(result) + +- if hostname: +- # If we have a hostname we want to verify that the subject +- # of the certificate matches it, otherwise raise an error +- if hostname != cert.subject.common_name: #pylint: disable=E1101 +- raise acierr +- + return dict(result=result, value=pkey_to_value(serial_number, options)) + + +@@ -819,22 +827,18 @@ class cert_revoke(PKQuery, CertMethod, VirtualCommand): + + # Make sure that the cert specified by issuer+serial exists. + # Will raise NotFound if it does not. +- cert_show_options = dict(cacn=kw['cacn']) +- api.Command.cert_show(unicode(serial_number), **cert_show_options) ++ resp = api.Command.cert_show(unicode(serial_number), cacn=kw['cacn']) + +- hostname = None + try: + self.check_access() + except errors.ACIError as acierr: + self.debug("Not granted by ACI to revoke certificate, looking at principal") + try: +- # Let cert_show() handle verifying that the subject of the +- # cert we're dealing with matches the hostname in the principal +- result = api.Command['cert_show']( +- unicode(serial_number), **cert_show_options +- )['result'] ++ cert = x509.load_certificate(resp['result']['certificate']) ++ if not bind_principal_can_manage_cert(cert): ++ raise acierr + except errors.NotImplementedError: +- pass ++ raise acierr + revocation_reason = kw['revocation_reason'] + if revocation_reason == 7: + raise errors.CertificateOperationError(error=_('7 is not a valid revocation reason')) +-- +2.9.3 + diff --git a/SOURCES/0089-Fix-container-owner-should-be-able-to-add-vault.patch b/SOURCES/0089-Fix-container-owner-should-be-able-to-add-vault.patch new file mode 100644 index 0000000..03c7269 --- /dev/null +++ b/SOURCES/0089-Fix-container-owner-should-be-able-to-add-vault.patch @@ -0,0 +1,34 @@ +From d3e11b06bbb996b1605f15912be106dcf47b357a Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Thu, 18 Aug 2016 10:11:25 +0200 +Subject: [PATCH] Fix: container owner should be able to add vault + +With recent change in DS (CVE fix), ds is not returging DuplicatedEntry +error in case that user is not permitted by ACI to write, but ACIError instead. + +Is safe to ignore ACI error in container, because it will be raised +again later if user has no access to container. + +https://fedorahosted.org/freeipa/ticket/6159 + +Reviewed-By: Martin Basti +--- + ipaserver/plugins/vault.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipaserver/plugins/vault.py b/ipaserver/plugins/vault.py +index c9b7cb942cfbca74134bce4ba039619b4f5f2845..5c4c09685ceb95c6634306c4275008d602099e12 100644 +--- a/ipaserver/plugins/vault.py ++++ b/ipaserver/plugins/vault.py +@@ -783,7 +783,7 @@ class vault_add_internal(LDAPCreate): + + try: + self.obj.create_container(parent_dn, owner_dn) +- except errors.DuplicateEntry as e: ++ except (errors.DuplicateEntry, errors.ACIError): + pass + + # vault should be owned by the creator +-- +2.7.4 + diff --git a/SOURCES/0089-trusts-format-Kerberos-principal-properly-when-fetch.patch b/SOURCES/0089-trusts-format-Kerberos-principal-properly-when-fetch.patch deleted file mode 100644 index bf4caea..0000000 --- a/SOURCES/0089-trusts-format-Kerberos-principal-properly-when-fetch.patch +++ /dev/null @@ -1,46 +0,0 @@ -From e9fdf223cdb39e685ad9c57a7348016917d5cba2 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Thu, 20 Aug 2015 15:12:42 +0300 -Subject: [PATCH] trusts: format Kerberos principal properly when fetching - trust topology - -For bidirectional trust if we have AD administrator credentials, we -should be using them with Kerberos authentication. If we don't have -AD administrator credentials, we should be using -HTTP/ipa.master@IPA.REALM credentials. This means we should ask -formatting 'creds' object in Kerberos style. - -For one-way trust we'll be fetching trust topology as TDO object, -authenticating with pre-created Kerberos credentials cache, so in all -cases we do use Kerberos authentication to talk to Active Directory -domain controllers over cross-forest trust link. - -Part of trust refactoring series. -Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1250190 -Fixes: https://fedorahosted.org/freeipa/ticket/5182 -Reviewed-By: Tomas Babej ---- - ipalib/plugins/trust.py | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) - -diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py -index c7546692bdd8dd827ee9772b72a758042d97aa71..173463ae7d4134b5bd155cc5fa920bfabd0a6958 100644 ---- a/ipalib/plugins/trust.py -+++ b/ipalib/plugins/trust.py -@@ -1479,7 +1479,12 @@ class trustdomain_del(LDAPDelete): - - def fetch_domains_from_trust(myapi, trustinstance, trust_entry, **options): - trust_name = trust_entry['cn'][0] -- creds = generate_creds(trustinstance, style=CRED_STYLE_SAMBA, **options) -+ # We want to use Kerberos if we have admin credentials even with SMB calls -+ # as eventually use of NTLMSSP will be deprecated for trusted domain operations -+ # If admin credentials are missing, 'creds' will be None and fetch_domains -+ # will use HTTP/ipa.master@IPA.REALM principal, e.g. Kerberos authentication -+ # as well. -+ creds = generate_creds(trustinstance, style=CRED_STYLE_KERBEROS, **options) - server = options.get('realm_server', None) - domains = ipaserver.dcerpc.fetch_domains(myapi, - trustinstance.local_flatname, --- -2.4.3 - diff --git a/SOURCES/0090-Change-internal-rsa_-public-private-_key-variable-na.patch b/SOURCES/0090-Change-internal-rsa_-public-private-_key-variable-na.patch deleted file mode 100644 index 0232220..0000000 --- a/SOURCES/0090-Change-internal-rsa_-public-private-_key-variable-na.patch +++ /dev/null @@ -1,52 +0,0 @@ -From 6031fed29f3e81450b48b73eba0f9e716efcb73f Mon Sep 17 00:00:00 2001 -From: Christian Heimes -Date: Tue, 28 Jul 2015 16:12:40 +0200 -Subject: [PATCH] Change internal rsa_(public|private)_key variable names - -In two places the vault plugin refers to rsa public or rsa private key -although the code can handle just any kind of asymmetric algorithms, -e.g. ECDSA. The patch just renames the occurences to avoid more -confusion in the future. - -Reviewed-By: Simo Sorce -Reviewed-By: Martin Basti ---- - ipalib/plugins/vault.py | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index 83dc085b5aadb4e2878e29d17449f0808cc7a9c2..4b2c8a518e5c9a93e5490841a3d2177536c905b1 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -486,11 +486,11 @@ class vault(LDAPObject): - return fernet.encrypt(data) - - elif public_key: -- rsa_public_key = load_pem_public_key( -+ public_key_obj = load_pem_public_key( - data=public_key, - backend=default_backend() - ) -- return rsa_public_key.encrypt( -+ return public_key_obj.encrypt( - data, - padding.OAEP( - mgf=padding.MGF1(algorithm=hashes.SHA1()), -@@ -513,12 +513,12 @@ class vault(LDAPObject): - - elif private_key: - try: -- rsa_private_key = load_pem_private_key( -+ private_key_obj = load_pem_private_key( - data=private_key, - password=None, - backend=default_backend() - ) -- return rsa_private_key.decrypt( -+ return private_key_obj.decrypt( - data, - padding.OAEP( - mgf=padding.MGF1(algorithm=hashes.SHA1()), --- -2.4.3 - diff --git a/SOURCES/0090-ipaserver-dcerpc-reformat-to-make-the-code-closer-to.patch b/SOURCES/0090-ipaserver-dcerpc-reformat-to-make-the-code-closer-to.patch new file mode 100644 index 0000000..f4bc1d9 --- /dev/null +++ b/SOURCES/0090-ipaserver-dcerpc-reformat-to-make-the-code-closer-to.patch @@ -0,0 +1,1005 @@ +From a9a73b0e0b601767324d5b6747b6ba46b6e5e90f Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Tue, 7 Jun 2016 22:41:10 +0300 +Subject: [PATCH] ipaserver/dcerpc: reformat to make the code closer to pep8 + +Because Samba Python bindings provide long-named methods and constants, +sometimes it is impossible to fit into 80 columns without causing +damage to readability of the code. This patchset attempts to reduce +pep8 complaints to a minimum. + +https://fedorahosted.org/freeipa/ticket/6076 + +Reviewed-By: Martin Babinsky +--- + ipaserver/dcerpc.py | 473 +++++++++++++++++++++++++++++++++------------------- + 1 file changed, 298 insertions(+), 175 deletions(-) + +diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py +index 21ac89dfd71271ed384b875f95054d7ad1c0556d..19be6bf7a3617a3b867d51a9358c9926e91049a7 100644 +--- a/ipaserver/dcerpc.py ++++ b/ipaserver/dcerpc.py +@@ -44,10 +44,12 @@ import samba + import random + from cryptography.hazmat.primitives.ciphers import Cipher, algorithms + from cryptography.hazmat.backends import default_backend ++# pylint: disable=F0401 + try: +- from ldap.controls import RequestControl as LDAPControl #pylint: disable=F0401 ++ from ldap.controls import RequestControl as LDAPControl + except ImportError: +- from ldap.controls import LDAPControl as LDAPControl #pylint: disable=F0401 ++ from ldap.controls import LDAPControl as LDAPControl ++# pylint: enable=F0401 + import ldap as _ldap + from ipapython.ipaldap import IPAdmin + from ipaserver.session import krbccache_dir, krbccache_prefix +@@ -74,7 +76,7 @@ and Samba4 python bindings. + + # Both constants can be used as masks against trust direction + # because bi-directional has two lower bits set. +-TRUST_ONEWAY = 1 ++TRUST_ONEWAY = 1 + TRUST_BIDIRECTIONAL = 3 + + # Trust join behavior +@@ -91,31 +93,44 @@ def is_sid_valid(sid): + return True + + +-access_denied_error = errors.ACIError(info=_('CIFS server denied your credentials')) ++access_denied_error = errors.ACIError( ++ info=_('CIFS server denied your credentials')) + dcerpc_error_codes = { + -1073741823: +- errors.RemoteRetrieveError(reason=_('communication with CIFS server was unsuccessful')), ++ errors.RemoteRetrieveError( ++ reason=_('communication with CIFS server was unsuccessful')), + -1073741790: access_denied_error, + -1073741715: access_denied_error, + -1073741614: access_denied_error, + -1073741603: +- errors.ValidationError(name=_('AD domain controller'), error=_('unsupported functional level')), +- -1073741811: # NT_STATUS_INVALID_PARAMETER ++ errors.ValidationError( ++ name=_('AD domain controller'), ++ error=_('unsupported functional level')), ++ -1073741811: # NT_STATUS_INVALID_PARAMETER + errors.RemoteRetrieveError( +- reason=_('AD domain controller complains about communication sequence. It may mean unsynchronized time on both sides, for example')), +- -1073741776: # NT_STATUS_INVALID_PARAMETER_MIX, we simply will skip the binding ++ reason=_('AD domain controller complains about communication ' ++ 'sequence. It may mean unsynchronized time on both ' ++ 'sides, for example')), ++ -1073741776: # NT_STATUS_INVALID_PARAMETER_MIX, ++ # we simply will skip the binding + access_denied_error, +- -1073741772: # NT_STATUS_OBJECT_NAME_NOT_FOUND +- errors.RemoteRetrieveError(reason=_('CIFS server configuration does not allow access to \\\\pipe\\lsarpc')), ++ -1073741772: # NT_STATUS_OBJECT_NAME_NOT_FOUND ++ errors.RemoteRetrieveError( ++ reason=_('CIFS server configuration does not allow ' ++ 'access to \\\\pipe\\lsarpc')), + } + + dcerpc_error_messages = { + "NT_STATUS_OBJECT_NAME_NOT_FOUND": +- errors.NotFound(reason=_('Cannot find specified domain or server name')), ++ errors.NotFound( ++ reason=_('Cannot find specified domain or server name')), + "WERR_NO_LOGON_SERVERS": +- errors.RemoteRetrieveError(reason=_('AD DC was unable to reach any IPA domain controller. Most likely it is a DNS or firewall issue')), ++ errors.RemoteRetrieveError( ++ reason=_('AD DC was unable to reach any IPA domain controller. ' ++ 'Most likely it is a DNS or firewall issue')), + "NT_STATUS_INVALID_PARAMETER_MIX": +- errors.RequirementError(name=_('At least the domain or IP address should be specified')), ++ errors.RequirementError( ++ name=_('At least the domain or IP address should be specified')), + } + + pysss_type_key_translation_dict = { +@@ -126,7 +141,7 @@ pysss_type_key_translation_dict = { + } + + +-def assess_dcerpc_exception(num=None,message=None): ++def assess_dcerpc_exception(num=None, message=None): + """ + Takes error returned by Samba bindings and converts it into + an IPA error class. +@@ -135,8 +150,9 @@ def assess_dcerpc_exception(num=None,message=None): + return dcerpc_error_codes[num] + if message and message in dcerpc_error_messages: + return dcerpc_error_messages[message] +- reason = _('''CIFS server communication error: code "%(num)s", +- message "%(message)s" (both may be "None")''') % dict(num=num, message=message) ++ reason = _('CIFS server communication error: code "%(num)s", ' ++ 'message "%(message)s" (both may be "None")') % \ ++ dict(num=num, message=message) + return errors.RemoteRetrieveError(reason=reason) + + +@@ -182,9 +198,13 @@ class DomainValidator(object): + self._parm = None + + def is_configured(self): +- cn_trust_local = DN(('cn', self.api.env.domain), self.api.env.container_cifsdomains, self.api.env.basedn) ++ cn_trust_local = DN(('cn', self.api.env.domain), ++ self.api.env.container_cifsdomains, ++ self.api.env.basedn) + try: +- entry_attrs = self.ldap.get_entry(cn_trust_local, [self.ATTR_FLATNAME, self.ATTR_SID]) ++ entry_attrs = self.ldap.get_entry(cn_trust_local, ++ [self.ATTR_FLATNAME, ++ self.ATTR_SID]) + self.flatname = entry_attrs[self.ATTR_FLATNAME][0] + self.sid = entry_attrs[self.ATTR_SID][0] + self.dn = entry_attrs.dn +@@ -203,7 +223,8 @@ class DomainValidator(object): + + try: + search_kw = {'objectClass': 'ipaNTTrustedDomain'} +- filter = self.ldap.make_filter(search_kw, rules=self.ldap.MATCH_ALL) ++ filter = self.ldap.make_filter(search_kw, ++ rules=self.ldap.MATCH_ALL) + (entries, truncated) = self.ldap.find_entries( + filter=filter, + base_dn=cn_trust, +@@ -216,22 +237,22 @@ class DomainValidator(object): + # domain names as keys and those are generally case-insensitive + result = ipautil.CIDict() + +- for entry in entries: ++ for e in entries: + try: +- trust_partner = entry[self.ATTR_TRUST_PARTNER][0] +- flatname_normalized = entry[self.ATTR_FLATNAME][0].lower() +- trusted_sid = entry[self.ATTR_TRUSTED_SID][0] +- except KeyError as e: ++ t_partner = e.single_value.get(self.ATTR_TRUST_PARTNER) ++ fname_norm = e.single_value.get(self.ATTR_FLATNAME).lower() ++ trusted_sid = e.single_value.get(self.ATTR_TRUSTED_SID) ++ except KeyError as exc: + # Some piece of trusted domain info in LDAP is missing + # Skip the domain, but leave log entry for investigation + api.log.warning("Trusted domain '%s' entry misses an " +- "attribute: %s", entry.dn, e) ++ "attribute: %s", e.dn, exc) + continue + +- result[trust_partner] = (flatname_normalized, +- security.dom_sid(trusted_sid)) ++ result[t_partner] = (fname_norm, ++ security.dom_sid(trusted_sid)) + return result +- except errors.NotFound as e: ++ except errors.NotFound as exc: + return [] + + def set_trusted_domains(self): +@@ -244,21 +265,22 @@ class DomainValidator(object): + # This means we can't check the correctness of a trusted + # domain SIDs + raise errors.ValidationError(name='sid', +- error=_('no trusted domain is configured')) ++ error=_('no trusted domain ' ++ 'is configured')) + + def get_domain_by_sid(self, sid, exact_match=False): + if not self.domain: + # our domain is not configured or self.is_configured() never run + # reject SIDs as we can't check correctness of them + raise errors.ValidationError(name='sid', +- error=_('domain is not configured')) ++ error=_('domain is not configured')) + + # Parse sid string to see if it is really in a SID format + try: + test_sid = security.dom_sid(sid) + except TypeError: + raise errors.ValidationError(name='sid', +- error=_('SID is not valid')) ++ error=_('SID is not valid')) + + # At this point we have SID_NT_AUTHORITY family SID and really need to + # check it against prefixes of domain SIDs we trust to +@@ -314,30 +336,34 @@ class DomainValidator(object): + return None + + def get_trusted_domain_objects(self, domain=None, flatname=None, filter="", +- attrs=None, scope=_ldap.SCOPE_SUBTREE, basedn=None): ++ attrs=None, scope=_ldap.SCOPE_SUBTREE, ++ basedn=None): + """ +- Search for LDAP objects in a trusted domain specified either by `domain' +- or `flatname'. The actual LDAP search is specified by `filter', `attrs', +- `scope' and `basedn'. When `basedn' is empty, database root DN is used. ++ Search for LDAP objects in a trusted domain specified either by ++ `domain' or `flatname'. The actual LDAP search is specified by ++ `filter', `attrs', `scope' and `basedn'. When `basedn' is empty, ++ database root DN is used. + """ + assert domain is not None or flatname is not None + """Returns SID for the trusted domain object (user or group only)""" + if not self.domain: + # our domain is not configured or self.is_configured() never run + raise errors.ValidationError(name=_('Trust setup'), +- error=_('Our domain is not configured')) ++ error=_('Our domain is ' ++ 'not configured')) + if not self._domains: + self._domains = self.get_trusted_domains() + if len(self._domains) == 0: + # Our domain is configured but no trusted domains are configured + raise errors.ValidationError(name=_('Trust setup'), +- error=_('No trusted domain is not configured')) ++ error=_('No trusted domain is ' ++ 'not configured')) + + entries = None + if domain is not None: + if domain not in self._domains: + raise errors.ValidationError(name=_('trusted domain object'), +- error= _('domain is not trusted')) ++ error=_('domain is not trusted')) + # Now we have a name to check against our list of trusted domains + entries = self.search_in_dc(domain, filter, attrs, scope, basedn) + elif flatname is not None: +@@ -347,53 +373,65 @@ class DomainValidator(object): + for domain in self._domains: + if self._domains[domain][0] == flatname: + found_flatname = True +- entries = self.search_in_dc(domain, filter, attrs, scope, basedn) ++ entries = self.search_in_dc(domain, filter, ++ attrs, scope, basedn) + if entries: + break + if not found_flatname: + raise errors.ValidationError(name=_('trusted domain object'), +- error= _('no trusted domain matched the specified flat name')) ++ error=_('no trusted domain ' ++ 'matched the specified ' ++ 'flat name')) + if not entries: + raise errors.NotFound(reason=_('trusted domain object not found')) + + return entries + +- def get_trusted_domain_object_sid(self, object_name, fallback_to_ldap=True): ++ def get_trusted_domain_object_sid(self, object_name, ++ fallback_to_ldap=True): + result = pysss_nss_idmap.getsidbyname(object_name) +- if object_name in result and (pysss_nss_idmap.SID_KEY in result[object_name]): ++ if object_name in result and \ ++ (pysss_nss_idmap.SID_KEY in result[object_name]): + object_sid = result[object_name][pysss_nss_idmap.SID_KEY] + return object_sid + + # If fallback to AD DC LDAP is not allowed, bail out + if not fallback_to_ldap: + raise errors.ValidationError(name=_('trusted domain object'), +- error= _('SSSD was unable to resolve the object to a valid SID')) ++ error=_('SSSD was unable to resolve ' ++ 'the object to a valid SID')) + + # Else, we are going to contact AD DC LDAP + components = normalize_name(object_name) + if not ('domain' in components or 'flatname' in components): + # No domain or realm specified, ambiguous search +- raise errors.ValidationError(name=_('trusted domain object'), +- error= _('Ambiguous search, user domain was not specified')) ++ raise errors.ValidationError(name=_('trusted domain object'), ++ error=_('Ambiguous search, user ' ++ 'domain was not specified')) + + attrs = ['objectSid'] +- filter = '(&(sAMAccountName=%(name)s)(|(objectClass=user)(objectClass=group)))' \ +- % dict(name=components['name']) ++ filter = '(&(sAMAccountName=%(name)s)' \ ++ '(|(objectClass=user)(objectClass=group)))' \ ++ % dict(name=components['name']) + scope = _ldap.SCOPE_SUBTREE + entries = self.get_trusted_domain_objects(components.get('domain'), +- components.get('flatname'), filter, attrs, scope) ++ components.get('flatname'), ++ filter, attrs, scope) + + if len(entries) > 1: + # Treat non-unique entries as invalid + raise errors.ValidationError(name=_('trusted domain object'), +- error= _('Trusted domain did not return a unique object')) ++ error=_('Trusted domain did not ' ++ 'return a unique object')) + sid = self.__sid_to_str(entries[0]['objectSid'][0]) + try: + test_sid = security.dom_sid(sid) + return unicode(test_sid) + except TypeError as e: + raise errors.ValidationError(name=_('trusted domain object'), +- error= _('Trusted domain did not return a valid SID for the object')) ++ error=_('Trusted domain did not ' ++ 'return a valid SID for ' ++ 'the object')) + + def get_trusted_domain_object_type(self, name_or_sid): + """ +@@ -443,7 +481,8 @@ class DomainValidator(object): + ) + + attrs = ['sAMAccountName'] +- filter = (r'(&(objectSid=%(sid)s)(|(objectClass=user)(objectClass=group)))' ++ filter = (r'(&(objectSid=%(sid)s)' ++ '(|(objectClass=user)(objectClass=group)))' + % dict(sid=escaped_sid)) # sid in binary + domain = self.get_domain_by_sid(sid) + +@@ -454,7 +493,8 @@ class DomainValidator(object): + if len(entries) > 1: + # Treat non-unique entries as invalid + raise errors.ValidationError(name=_('trusted domain object'), +- error=_('Trusted domain did not return a unique object')) ++ error=_('Trusted domain did not ' ++ 'return a unique object')) + + object_name = ( + "%s@%s" % (entries[0].single_value['sAMAccountName'].lower(), +@@ -486,27 +526,31 @@ class DomainValidator(object): + # Now search a trusted domain for a user with this SID + attrs = ['cn'] + filter = '(&(objectClass=user)(objectSid=%(sid)s))' \ +- % dict(sid=object_name) ++ % dict(sid=object_name) + try: +- entries = self.get_trusted_domain_objects(domain=domain, filter=filter, +- attrs=attrs, scope=_ldap.SCOPE_SUBTREE) ++ entries = self.get_trusted_domain_objects(domain=domain, ++ filter=filter, ++ attrs=attrs, ++ scope=_ldap.SCOPE_SUBTREE) + except errors.NotFound: + raise errors.NotFound(reason=_('trusted domain user not found')) + user_dn = entries[0].dn + elif domain or flatname: + attrs = ['cn'] + filter = '(&(sAMAccountName=%(name)s)(objectClass=user))' \ +- % dict(name=name) ++ % dict(name=name) + try: + entries = self.get_trusted_domain_objects(domain, +- flatname, filter, attrs, _ldap.SCOPE_SUBTREE) ++ flatname, filter, attrs, ++ _ldap.SCOPE_SUBTREE) + except errors.NotFound: + raise errors.NotFound(reason=_('trusted domain user not found')) + user_dn = entries[0].dn + else: + # No domain or realm specified, ambiguous search + raise errors.ValidationError(name=_('trusted domain object'), +- error= _('Ambiguous search, user domain was not specified')) ++ error=_('Ambiguous search, ' ++ 'user domain was not specified')) + + # Get SIDs of user object and it's groups + # tokenGroups attribute must be read with a scope BASE for a known user +@@ -514,9 +558,11 @@ class DomainValidator(object): + attrs = ['objectSID', 'tokenGroups'] + filter = "(objectClass=user)" + entries = self.get_trusted_domain_objects(domain, +- flatname, filter, attrs, _ldap.SCOPE_BASE, user_dn) ++ flatname, filter, attrs, ++ _ldap.SCOPE_BASE, user_dn) + object_sid = self.__sid_to_str(entries[0]['objectSid'][0]) +- group_sids = [self.__sid_to_str(sid) for sid in entries[0]['tokenGroups']] ++ group_sids = [self.__sid_to_str(sid) ++ for sid in entries[0]['tokenGroups']] + return (object_sid, group_sids) + + def get_trusted_domain_user_and_groups(self, object_name): +@@ -540,11 +586,14 @@ class DomainValidator(object): + if is_valid_sid: + object_sid = object_name + result = pysss_nss_idmap.getnamebysid(object_name) +- if object_name in result and (pysss_nss_idmap.NAME_KEY in result[object_name]): +- group_list = pysss.getgrouplist(result[object_name][pysss_nss_idmap.NAME_KEY]) ++ if object_name in result and \ ++ (pysss_nss_idmap.NAME_KEY in result[object_name]): ++ group_list = pysss.getgrouplist( ++ result[object_name][pysss_nss_idmap.NAME_KEY]) + else: + result = pysss_nss_idmap.getsidbyname(object_name) +- if object_name in result and (pysss_nss_idmap.SID_KEY in result[object_name]): ++ if object_name in result and \ ++ (pysss_nss_idmap.SID_KEY in result[object_name]): + object_sid = result[object_name][pysss_nss_idmap.SID_KEY] + group_list = pysss.getgrouplist(object_name) + +@@ -552,7 +601,10 @@ class DomainValidator(object): + return self.__get_trusted_domain_user_and_groups(object_name) + + group_sids = pysss_nss_idmap.getsidbyname(group_list) +- return (object_sid, [el[1][pysss_nss_idmap.SID_KEY] for el in group_sids.items()]) ++ return ( ++ object_sid, ++ [el[1][pysss_nss_idmap.SID_KEY] for el in group_sids.items()] ++ ) + + def __sid_to_str(self, sid): + """ +@@ -561,12 +613,13 @@ class DomainValidator(object): + """ + sid_rev_num = ord(sid[0]) + number_sub_id = ord(sid[1]) +- ia = struct.unpack('!Q','\x00\x00'+sid[2:8])[0] ++ ia = struct.unpack('!Q', '\x00\x00'+sid[2:8])[0] + subs = [ +- struct.unpack(' 0: + self.parm.set('netbios name', hostname) + self.creds = creds +@@ -810,14 +867,14 @@ class TrustDomainInstance(object): + self.validation_attempts = 0 + + def __gen_lsa_connection(self, binding): +- if self.creds is None: +- raise errors.RequirementError(name=_('CIFS credentials object')) +- try: +- result = lsa.lsarpc(binding, self.parm, self.creds) +- return result +- except RuntimeError as e: +- num, message = e.args # pylint: disable=unpacking-non-sequence +- raise assess_dcerpc_exception(num=num, message=message) ++ if self.creds is None: ++ raise errors.RequirementError(name=_('CIFS credentials object')) ++ try: ++ result = lsa.lsarpc(binding, self.parm, self.creds) ++ return result ++ except RuntimeError as e: ++ num, message = e.args # pylint: disable=unpacking-non-sequence ++ raise assess_dcerpc_exception(num=num, message=message) + + def init_lsa_pipe(self, remote_host): + """ +@@ -847,30 +904,35 @@ class TrustDomainInstance(object): + # When session key is not available, we just skip this binding + session_attempts = session_attempts + 1 + +- if self._pipe is None and (attempts + session_attempts) == len(bindings): ++ if self._pipe is None and \ ++ (attempts + session_attempts) == len(bindings): + raise errors.ACIError( +- info=_('CIFS server %(host)s denied your credentials') % dict(host=remote_host)) ++ info=_('CIFS server %(host)s denied your credentials') ++ % dict(host=remote_host)) + + if self._pipe is None: + raise errors.RemoteRetrieveError( +- reason=_('Cannot establish LSA connection to %(host)s. Is CIFS server running?') % dict(host=remote_host)) ++ reason=_('Cannot establish LSA connection to %(host)s. ' ++ 'Is CIFS server running?') % dict(host=remote_host)) + self.binding = binding + self.session_key = self._pipe.session_key + + def __gen_lsa_bindings(self, remote_host): + """ +- There are multiple transports to issue LSA calls. However, depending on a +- system in use they may be blocked by local operating system policies. ++ There are multiple transports to issue LSA calls. However, depending on ++ a system in use they may be blocked by local operating system policies. + Generate all we can use. init_lsa_pipe() will try them one by one until + there is one working. + +- We try NCACN_NP before NCACN_IP_TCP and use SMB2 before SMB1 or defaults. ++ We try NCACN_NP before NCACN_IP_TCP and use SMB2 before SMB1. + """ + transports = (u'ncacn_np', u'ncacn_ip_tcp') +- options = ( u'smb2,print', u'print') +- return [u'%s:%s[%s]' % (t, remote_host, o) for t in transports for o in options] ++ options = (u'smb2,print', u'print') ++ return [u'%s:%s[%s]' % (t, remote_host, o) ++ for t in transports for o in options] + +- def retrieve_anonymously(self, remote_host, discover_srv=False, search_pdc=False): ++ def retrieve_anonymously(self, remote_host, ++ discover_srv=False, search_pdc=False): + """ + When retrieving DC information anonymously, we can't get SID of the domain + """ +@@ -896,7 +958,8 @@ class TrustDomainInstance(object): + self.info['is_pdc'] = (result.server_type & nbt.NBT_SERVER_PDC) != 0 + + # Netlogon response doesn't contain SID of the domain. +- # We need to do rootDSE search with LDAP_SERVER_EXTENDED_DN_OID control to reveal the SID ++ # We need to do rootDSE search with LDAP_SERVER_EXTENDED_DN_OID ++ # control to reveal the SID + ldap_uri = 'ldap://%s' % (result.pdc_dns_name) + conn = _ldap.initialize(ldap_uri) + conn.set_option(_ldap.OPT_SERVER_CONTROLS, [ExtendedDNControl()]) +@@ -908,7 +971,7 @@ class TrustDomainInstance(object): + except _ldap.LDAPError as e: + root_logger.error( + "LDAP error when connecting to %(host)s: %(error)s" % +- dict(host=unicode(result.pdc_name), error=str(e))) ++ dict(host=unicode(result.pdc_name), error=str(e))) + except KeyError as e: + root_logger.error("KeyError: {err}, LDAP entry from {host} " + "returned malformed. Your DNS might be " +@@ -930,8 +993,11 @@ class TrustDomainInstance(object): + objectAttribute = lsa.ObjectAttribute() + objectAttribute.sec_qos = lsa.QosInfo() + try: +- self._policy_handle = self._pipe.OpenPolicy2(u"", objectAttribute, security.SEC_FLAG_MAXIMUM_ALLOWED) +- result = self._pipe.QueryInfoPolicy2(self._policy_handle, lsa.LSA_POLICY_INFO_DNS) ++ self._policy_handle = \ ++ self._pipe.OpenPolicy2(u"", objectAttribute, ++ security.SEC_FLAG_MAXIMUM_ALLOWED) ++ result = self._pipe.QueryInfoPolicy2(self._policy_handle, ++ lsa.LSA_POLICY_INFO_DNS) + except RuntimeError as e: + num, message = e.args # pylint: disable=unpacking-non-sequence + raise assess_dcerpc_exception(num=num, message=message) +@@ -944,7 +1010,8 @@ class TrustDomainInstance(object): + self.info['dc'] = remote_host + + try: +- result = self._pipe.QueryInfoPolicy2(self._policy_handle, lsa.LSA_POLICY_INFO_ROLE) ++ result = self._pipe.QueryInfoPolicy2(self._policy_handle, ++ lsa.LSA_POLICY_INFO_ROLE) + except RuntimeError as e: + num, message = e.args # pylint: disable=unpacking-non-sequence + raise assess_dcerpc_exception(num=num, message=message) +@@ -958,18 +1025,18 @@ class TrustDomainInstance(object): + clear_value.size = len(password_blob) + clear_value.password = password_blob + +- clear_authentication_information = drsblobs.AuthenticationInformation() +- clear_authentication_information.LastUpdateTime = samba.unix2nttime(int(time.time())) +- clear_authentication_information.AuthType = lsa.TRUST_AUTH_TYPE_CLEAR +- clear_authentication_information.AuthInfo = clear_value ++ clear_authinfo = drsblobs.AuthenticationInformation() ++ clear_authinfo.LastUpdateTime = samba.unix2nttime(int(time.time())) ++ clear_authinfo.AuthType = lsa.TRUST_AUTH_TYPE_CLEAR ++ clear_authinfo.AuthInfo = clear_value + +- authentication_information_array = drsblobs.AuthenticationInformationArray() +- authentication_information_array.count = 1 +- authentication_information_array.array = [clear_authentication_information] ++ authinfo_array = drsblobs.AuthenticationInformationArray() ++ authinfo_array.count = 1 ++ authinfo_array.array = [clear_authinfo] + + outgoing = drsblobs.trustAuthInOutBlob() + outgoing.count = 1 +- outgoing.current = authentication_information_array ++ outgoing.current = authinfo_array + + confounder = [3]*512 + for i in range(512): +@@ -983,7 +1050,8 @@ class TrustDomainInstance(object): + + trustpass_blob = ndr_pack(trustpass) + +- encrypted_trustpass = arcfour_encrypt(self._pipe.session_key, trustpass_blob) ++ encrypted_trustpass = arcfour_encrypt(self._pipe.session_key, ++ trustpass_blob) + + auth_blob = lsa.DATA_BUF2() + auth_blob.size = len(encrypted_trustpass) +@@ -993,7 +1061,6 @@ class TrustDomainInstance(object): + auth_info.auth_blob = auth_blob + self.auth_info = auth_info + +- + def generate_ftinfo(self, another_domain): + """ + Generates TrustDomainInfoFullInfo2Internal structure +@@ -1032,27 +1099,38 @@ class TrustDomainInstance(object): + # smbd already has the information about itself + ldname = lsa.StringLarge() + ldname.string = another_domain.info['dns_domain'] +- collision_info = self._pipe.lsaRSetForestTrustInformation(self._policy_handle, +- ldname, +- lsa.LSA_FOREST_TRUST_DOMAIN_INFO, +- ftinfo, 0) +- if collision_info: +- root_logger.error("When setting forest trust information, got collision info back:\n%s" % (ndr_print(collision_info))) ++ ftlevel = lsa.LSA_FOREST_TRUST_DOMAIN_INFO ++ # RSetForestTrustInformation returns collision information ++ # for trust topology ++ cinfo = self._pipe.lsaRSetForestTrustInformation( ++ self._policy_handle, ++ ldname, ++ ftlevel, ++ ftinfo, 0) ++ if cinfo: ++ root_logger.error("When setting forest trust information, " ++ "got collision info back:\n%s" ++ % (ndr_print(cinfo))) + except RuntimeError as e: +- # We can ignore the error here -- setting up name suffix routes may fail ++ # We can ignore the error here -- ++ # setting up name suffix routes may fail + pass + +- def establish_trust(self, another_domain, trustdom_secret, trust_type='bidirectional', trust_external=False): ++ def establish_trust(self, another_domain, trustdom_secret, ++ trust_type='bidirectional', trust_external=False): + """ + Establishes trust between our and another domain +- Input: another_domain -- instance of TrustDomainInstance, initialized with #retrieve call ++ Input: another_domain -- instance of TrustDomainInstance, ++ initialized with #retrieve call + trustdom_secret -- shared secred used for the trust + """ + if self.info['name'] == another_domain.info['name']: + # Check that NetBIOS names do not clash + raise errors.ValidationError(name=u'AD Trust Setup', +- error=_('the IPA server and the remote domain cannot share the same ' +- 'NetBIOS name: %s') % self.info['name']) ++ error=_('the IPA server and the ' ++ 'remote domain cannot share ' ++ 'the same NetBIOS name: %s') ++ % self.info['name']) + + self.generate_auth(trustdom_secret) + +@@ -1071,8 +1149,12 @@ class TrustDomainInstance(object): + try: + dname = lsa.String() + dname.string = another_domain.info['dns_domain'] +- res = self._pipe.QueryTrustedDomainInfoByName(self._policy_handle, dname, lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO) +- self._pipe.DeleteTrustedDomain(self._policy_handle, res.info_ex.sid) ++ res = self._pipe.QueryTrustedDomainInfoByName( ++ self._policy_handle, ++ dname, ++ lsa.LSA_TRUSTED_DOMAIN_INFO_FULL_INFO) ++ self._pipe.DeleteTrustedDomain(self._policy_handle, ++ res.info_ex.sid) + except RuntimeError as e: + num, message = e.args # pylint: disable=unpacking-non-sequence + # Ignore anything but access denied (NT_STATUS_ACCESS_DENIED) +@@ -1080,7 +1162,10 @@ class TrustDomainInstance(object): + raise access_denied_error + + try: +- trustdom_handle = self._pipe.CreateTrustedDomainEx2(self._policy_handle, info, self.auth_info, security.SEC_STD_DELETE) ++ trustdom_handle = self._pipe.CreateTrustedDomainEx2( ++ self._policy_handle, ++ info, self.auth_info, ++ security.SEC_STD_DELETE) + except RuntimeError as e: + num, message = e.args # pylint: disable=unpacking-non-sequence + raise assess_dcerpc_exception(num=num, message=message) +@@ -1089,13 +1174,19 @@ class TrustDomainInstance(object): + # trust settings. Samba insists this has to be done with LSA + # OpenTrustedDomain* calls, it is not enough to have a handle + # returned by the CreateTrustedDomainEx2 call. +- trustdom_handle = self._pipe.OpenTrustedDomainByName(self._policy_handle, dname, security.SEC_FLAG_MAXIMUM_ALLOWED) ++ trustdom_handle = self._pipe.OpenTrustedDomainByName( ++ self._policy_handle, ++ dname, ++ security.SEC_FLAG_MAXIMUM_ALLOWED) + try: +- infoclass = lsa.TrustDomainInfoSupportedEncTypes() +- infoclass.enc_types = security.KERB_ENCTYPE_RC4_HMAC_MD5 +- infoclass.enc_types |= security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96 +- infoclass.enc_types |= security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 +- self._pipe.SetInformationTrustedDomain(trustdom_handle, lsa.LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES, infoclass) ++ infocls = lsa.TrustDomainInfoSupportedEncTypes() ++ infocls.enc_types = security.KERB_ENCTYPE_RC4_HMAC_MD5 ++ infocls.enc_types |= security.KERB_ENCTYPE_AES128_CTS_HMAC_SHA1_96 ++ infocls.enc_types |= security.KERB_ENCTYPE_AES256_CTS_HMAC_SHA1_96 ++ self._pipe.SetInformationTrustedDomain( ++ trustdom_handle, ++ lsa.LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES, ++ infocls) + except RuntimeError as e: + # We can ignore the error here -- changing enctypes is for + # improved security but the trust will work with default values as +@@ -1105,13 +1196,16 @@ class TrustDomainInstance(object): + + if not trust_external: + try: +- info = self._pipe.QueryTrustedDomainInfo(trustdom_handle, +- lsa.LSA_TRUSTED_DOMAIN_INFO_INFO_EX) ++ info = self._pipe.QueryTrustedDomainInfo( ++ trustdom_handle, ++ lsa.LSA_TRUSTED_DOMAIN_INFO_INFO_EX) + info.trust_attributes |= lsa.LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE +- self._pipe.SetInformationTrustedDomain(trustdom_handle, +- lsa.LSA_TRUSTED_DOMAIN_INFO_INFO_EX, info) ++ self._pipe.SetInformationTrustedDomain( ++ trustdom_handle, ++ lsa.LSA_TRUSTED_DOMAIN_INFO_INFO_EX, info) + except RuntimeError as e: +- root_logger.error('unable to set trust transitivity status: %s' % (str(e))) ++ root_logger.error( ++ 'unable to set trust transitivity status: %s' % (str(e))) + + if self.info['is_pdc'] or trust_external: + self.update_ftinfo(another_domain) +@@ -1119,12 +1213,13 @@ class TrustDomainInstance(object): + def verify_trust(self, another_domain): + def retrieve_netlogon_info_2(logon_server, domain, function_code, data): + try: +- netr_pipe = netlogon.netlogon(domain.binding, domain.parm, domain.creds) +- result = netr_pipe.netr_LogonControl2Ex(logon_server=logon_server, ++ netr_pipe = netlogon.netlogon(domain.binding, ++ domain.parm, domain.creds) ++ result = netr_pipe.netr_LogonControl2Ex( ++ logon_server=logon_server, + function_code=function_code, + level=2, +- data=data +- ) ++ data=data) + return result + except RuntimeError as e: + num, message = e.args # pylint: disable=unpacking-non-sequence +@@ -1135,9 +1230,11 @@ class TrustDomainInstance(object): + another_domain.info['dns_domain']) + + if result and result.flags and netlogon.NETLOGON_VERIFY_STATUS_RETURNED: +- if result.pdc_connection_status[0] != 0 and result.tc_connection_status[0] != 0: ++ if result.pdc_connection_status[0] != 0 and \ ++ result.tc_connection_status[0] != 0: + if result.pdc_connection_status[1] == "WERR_ACCESS_DENIED": +- # Most likely AD DC hit another IPA replica which yet has no trust secret replicated ++ # Most likely AD DC hit another IPA replica which ++ # yet has no trust secret replicated + + # Sleep and repeat again + self.validation_attempts += 1 +@@ -1176,23 +1273,23 @@ class TrustDomainInstance(object): + + def fetch_domains(api, mydomain, trustdomain, creds=None, server=None): + trust_flags = dict( +- NETR_TRUST_FLAG_IN_FOREST = 0x00000001, +- NETR_TRUST_FLAG_OUTBOUND = 0x00000002, +- NETR_TRUST_FLAG_TREEROOT = 0x00000004, +- NETR_TRUST_FLAG_PRIMARY = 0x00000008, +- NETR_TRUST_FLAG_NATIVE = 0x00000010, +- NETR_TRUST_FLAG_INBOUND = 0x00000020, +- NETR_TRUST_FLAG_MIT_KRB5 = 0x00000080, +- NETR_TRUST_FLAG_AES = 0x00000100) ++ NETR_TRUST_FLAG_IN_FOREST=0x00000001, ++ NETR_TRUST_FLAG_OUTBOUND=0x00000002, ++ NETR_TRUST_FLAG_TREEROOT=0x00000004, ++ NETR_TRUST_FLAG_PRIMARY=0x00000008, ++ NETR_TRUST_FLAG_NATIVE=0x00000010, ++ NETR_TRUST_FLAG_INBOUND=0x00000020, ++ NETR_TRUST_FLAG_MIT_KRB5=0x00000080, ++ NETR_TRUST_FLAG_AES=0x00000100) + + trust_attributes = dict( +- NETR_TRUST_ATTRIBUTE_NON_TRANSITIVE = 0x00000001, +- NETR_TRUST_ATTRIBUTE_UPLEVEL_ONLY = 0x00000002, +- NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN = 0x00000004, +- NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE = 0x00000008, +- NETR_TRUST_ATTRIBUTE_CROSS_ORGANIZATION = 0x00000010, +- NETR_TRUST_ATTRIBUTE_WITHIN_FOREST = 0x00000020, +- NETR_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL = 0x00000040) ++ NETR_TRUST_ATTRIBUTE_NON_TRANSITIVE=0x00000001, ++ NETR_TRUST_ATTRIBUTE_UPLEVEL_ONLY=0x00000002, ++ NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN=0x00000004, ++ NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE=0x00000008, ++ NETR_TRUST_ATTRIBUTE_CROSS_ORGANIZATION=0x00000010, ++ NETR_TRUST_ATTRIBUTE_WITHIN_FOREST=0x00000020, ++ NETR_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL=0x00000040) + + def communicate(td): + td.init_lsa_pipe(td.info['dc']) +@@ -1314,7 +1411,8 @@ class TrustDomainJoins(object): + ld.retrieve(installutils.get_fqdn()) + self.local_domain = ld + +- def populate_remote_domain(self, realm, realm_server=None, realm_admin=None, realm_passwd=None): ++ def populate_remote_domain(self, realm, realm_server=None, ++ realm_admin=None, realm_passwd=None): + def get_instance(self): + # Fetch data from foreign domain using password only + rd = TrustDomainInstance('') +@@ -1330,7 +1428,8 @@ class TrustDomainJoins(object): + if realm_server is None: + rd.retrieve_anonymously(realm, discover_srv=True, search_pdc=True) + else: +- rd.retrieve_anonymously(realm_server, discover_srv=False, search_pdc=True) ++ rd.retrieve_anonymously(realm_server, ++ discover_srv=False, search_pdc=True) + rd.read_only = True + if realm_admin and realm_passwd: + if 'name' in rd.info: +@@ -1339,12 +1438,14 @@ class TrustDomainJoins(object): + # realm admin is in DOMAIN\user format + # strip DOMAIN part as we'll enforce the one discovered + realm_admin = names[-1] +- auth_string = u"%s\%s%%%s" % (rd.info['name'], realm_admin, realm_passwd) ++ auth_string = u"%s\%s%%%s" \ ++ % (rd.info['name'], realm_admin, realm_passwd) + td = get_instance(self) + td.creds.parse_string(auth_string) + td.creds.set_workstation(self.local_domain.hostname) + if realm_server is None: +- # we must have rd.info['dns_hostname'] then, part of anonymous discovery ++ # we must have rd.info['dns_hostname'] then ++ # as it is part of the anonymous discovery + td.retrieve(rd.info['dns_hostname']) + else: + td.retrieve(realm_server) +@@ -1358,8 +1459,8 @@ class TrustDomainJoins(object): + """ + Generate list of records for forest trust information about + our realm domains. Note that the list generated currently +- includes only top level domains, no exclusion domains, and no TDO objects +- as we handle the latter in a separate way ++ includes only top level domains, no exclusion domains, and ++ no TDO objects as we handle the latter in a separate way + """ + if self.local_domain.read_only: + return +@@ -1367,10 +1468,15 @@ class TrustDomainJoins(object): + self.local_domain.ftinfo_records = [] + + realm_domains = self.api.Command.realmdomains_show()['result'] +- # Use realmdomains' modification timestamp to judge records last update time +- entry = self.api.Backend.ldap2.get_entry(realm_domains['dn'], ['modifyTimestamp']) ++ # Use realmdomains' modification timestamp ++ # to judge records' last update time ++ entry = self.api.Backend.ldap2.get_entry( ++ realm_domains['dn'], ['modifyTimestamp']) + # Convert the timestamp to Windows 64-bit timestamp format +- trust_timestamp = long(time.mktime(entry['modifytimestamp'][0].timetuple())*1e7+116444736000000000) ++ trust_timestamp = long( ++ time.mktime( ++ entry.single_value.get('modifytimestamp').timetuple() ++ )*1e7+116444736000000000) + + for dom in realm_domains['associateddomain']: + ftinfo = dict() +@@ -1379,7 +1485,8 @@ class TrustDomainJoins(object): + ftinfo['rec_type'] = lsa.LSA_FOREST_TRUST_TOP_LEVEL_NAME + self.local_domain.ftinfo_records.append(ftinfo) + +- def join_ad_full_credentials(self, realm, realm_server, realm_admin, realm_passwd, trust_type): ++ def join_ad_full_credentials(self, realm, realm_server, realm_admin, ++ realm_passwd, trust_type): + if not self.configured: + return None + +@@ -1392,24 +1499,33 @@ class TrustDomainJoins(object): + ) + + trust_external = bool(self.__allow_behavior & TRUST_JOIN_EXTERNAL) +- if self.remote_domain.info['dns_domain'] != self.remote_domain.info['dns_forest']: ++ if self.remote_domain.info['dns_domain'] != \ ++ self.remote_domain.info['dns_forest']: + if not trust_external: +- raise errors.NotAForestRootError(forest=self.remote_domain.info['dns_forest'], +- domain=self.remote_domain.info['dns_domain']) ++ raise errors.NotAForestRootError( ++ forest=self.remote_domain.info['dns_forest'], ++ domain=self.remote_domain.info['dns_domain']) + + if not self.remote_domain.read_only: + trustdom_pass = samba.generate_random_password(128, 128) + self.get_realmdomains() + self.remote_domain.establish_trust(self.local_domain, +- trustdom_pass, trust_type, trust_external) ++ trustdom_pass, ++ trust_type, trust_external) + self.local_domain.establish_trust(self.remote_domain, +- trustdom_pass, trust_type, trust_external) +- # if trust is inbound, we don't need to verify it because AD DC will respond +- # with WERR_NO_SUCH_DOMAIN -- in only does verification for outbound trusts. ++ trustdom_pass, ++ trust_type, trust_external) ++ # if trust is inbound, we don't need to verify it because ++ # AD DC will respond with WERR_NO_SUCH_DOMAIN -- ++ # it only does verification for outbound trusts. + result = True + if trust_type == TRUST_BIDIRECTIONAL: + result = self.remote_domain.verify_trust(self.local_domain) +- return dict(local=self.local_domain, remote=self.remote_domain, verified=result) ++ return dict( ++ local=self.local_domain, ++ remote=self.remote_domain, ++ verified=result ++ ) + return None + + def join_ad_ipa_half(self, realm, realm_server, trustdom_passwd, trust_type): +@@ -1420,11 +1536,18 @@ class TrustDomainJoins(object): + self.populate_remote_domain(realm, realm_server, realm_passwd=None) + + trust_external = bool(self.__allow_behavior & TRUST_JOIN_EXTERNAL) +- if self.remote_domain.info['dns_domain'] != self.remote_domain.info['dns_forest']: ++ if self.remote_domain.info['dns_domain'] != \ ++ self.remote_domain.info['dns_forest']: + if not trust_external: +- raise errors.NotAForestRootError(forest=self.remote_domain.info['dns_forest'], +- domain=self.remote_domain.info['dns_domain']) ++ raise errors.NotAForestRootError( ++ forest=self.remote_domain.info['dns_forest'], ++ domain=self.remote_domain.info['dns_domain']) + + self.local_domain.establish_trust(self.remote_domain, +- trustdom_passwd, trust_type, trust_external) +- return dict(local=self.local_domain, remote=self.remote_domain, verified=False) ++ trustdom_passwd, ++ trust_type, trust_external) ++ return dict( ++ local=self.local_domain, ++ remote=self.remote_domain, ++ verified=False ++ ) +-- +2.7.4 + diff --git a/SOURCES/0091-improve-the-usability-of-ipa-user-del-preserve-comma.patch b/SOURCES/0091-improve-the-usability-of-ipa-user-del-preserve-comma.patch deleted file mode 100644 index 21a27bc..0000000 --- a/SOURCES/0091-improve-the-usability-of-ipa-user-del-preserve-comma.patch +++ /dev/null @@ -1,170 +0,0 @@ -From 8208a3b4a642b19ebf112d29f4b3f4feae1a6011 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Wed, 19 Aug 2015 14:43:14 +0200 -Subject: [PATCH] improve the usability of `ipa user-del --preserve` command - -`ipa user-del` with `--preserve` option will now process multiple entries and -handle `--continue` option in a manner analogous to `ipa user-del` in normal -mode. - -In addition, it is now no longer possible to permanently delete a user by -accidentally running `ipa user-del --preserve` twice. - -https://fedorahosted.org/freeipa/ticket/5234 -https://fedorahosted.org/freeipa/ticket/5236 - -Reviewed-By: Thierry Bordaz -Reviewed-By: Martin Basti ---- - ipalib/plugins/user.py | 123 ++++++++++++++++++++++++++----------------------- - 1 file changed, 66 insertions(+), 57 deletions(-) - -diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py -index d7cf9666d43b69b0cab91cfa0c98a8373f095ab5..cb47cbb4869cb978f87603817033580647cc2d17 100644 ---- a/ipalib/plugins/user.py -+++ b/ipalib/plugins/user.py -@@ -593,6 +593,60 @@ class user_del(baseuser_del): - ), - ) - -+ def _preserve_user(self, pkey, delete_container, **options): -+ assert isinstance(delete_container, DN) -+ -+ dn = self.obj.get_either_dn(pkey, **options) -+ delete_dn = DN(dn[0], delete_container) -+ ldap = self.obj.backend -+ self.log.debug("preserve move %s -> %s" % (dn, delete_dn)) -+ -+ if dn.endswith(delete_container): -+ raise errors.ExecutionError( -+ _('%s: user is already preserved' % pkey) -+ ) -+ # Check that this value is a Active user -+ try: -+ original_entry_attrs = self._exc_wrapper( -+ pkey, options, ldap.get_entry)(dn, ['dn']) -+ except errors.NotFound: -+ self.obj.handle_not_found(pkey) -+ -+ # start to move the entry to Delete container -+ self._exc_wrapper(pkey, options, ldap.move_entry)(dn, delete_dn, -+ del_old=True) -+ -+ # Then clear the credential attributes -+ attrs_to_clear = ['krbPrincipalKey', 'krbLastPwdChange', -+ 'krbPasswordExpiration', 'userPassword'] -+ -+ entry_attrs = self._exc_wrapper(pkey, options, ldap.get_entry)( -+ delete_dn, attrs_to_clear) -+ -+ clearedCredential = False -+ for attr in attrs_to_clear: -+ if attr.lower() in entry_attrs: -+ del entry_attrs[attr] -+ clearedCredential = True -+ if clearedCredential: -+ self._exc_wrapper(pkey, options, ldap.update_entry)(entry_attrs) -+ -+ # Then restore some original entry attributes -+ attrs_to_restore = ['secretary', 'managedby', 'manager', 'ipauniqueid', -+ 'uidnumber', 'gidnumber', 'passwordHistory'] -+ -+ entry_attrs = self._exc_wrapper( -+ pkey, options, ldap.get_entry)(delete_dn, attrs_to_restore) -+ -+ restoreAttr = False -+ for attr in attrs_to_restore: -+ if ((attr.lower() in original_entry_attrs) and -+ not (attr.lower() in entry_attrs)): -+ restoreAttr = True -+ entry_attrs[attr.lower()] = original_entry_attrs[attr.lower()] -+ if restoreAttr: -+ self._exc_wrapper(pkey, options, ldap.update_entry)(entry_attrs) -+ - def forward(self, *keys, **options): - if self.api.env.context == 'cli': - if options['no_preserve'] and options['preserve']: -@@ -633,68 +687,23 @@ class user_del(baseuser_del): - - def execute(self, *keys, **options): - -- dn = self.obj.get_either_dn(*keys, **options) -- - # We are going to permanent delete or the user is already in the delete container. - delete_container = DN(self.obj.delete_container_dn, self.api.env.basedn) -- user_from_delete_container = dn.endswith(delete_container) -- -- if not options.get('preserve', True) or user_from_delete_container: -- # Remove any ID overrides tied with this user -- remove_ipaobject_overrides(self.obj.backend, self.obj.api, dn) -- -- # Issue a true DEL on that entry -- return super(user_del, self).execute(*keys, **options) - - # The user to delete is active and there is no 'no_preserve' option - if options.get('preserve', False): -- -- ldap = self.obj.backend -- -- # need to handle multiple keys (e.g. keys[-1]=(u'tb8', u'tb9').. -- active_dn = self.obj.get_either_dn(*keys, **options) -- superior_dn = DN(self.obj.delete_container_dn, api.env.basedn) -- delete_dn = DN(active_dn[0], self.obj.delete_container_dn, api.env.basedn) -- self.log.debug("preserve move %s -> %s" % (active_dn, delete_dn)) -- -- # Check that this value is a Active user -- try: -- original_entry_attrs = self._exc_wrapper(keys, options, ldap.get_entry)(active_dn, ['dn']) -- except errors.NotFound: -- raise -- -- # start to move the entry to Delete container -- self._exc_wrapper(keys, options, ldap.move_entry)(active_dn, delete_dn, del_old=True) -- -- # Then clear the credential attributes -- attrs_to_clear = ['krbPrincipalKey', 'krbLastPwdChange', 'krbPasswordExpiration', 'userPassword'] -- try: -- entry_attrs = self._exc_wrapper(keys, options, ldap.get_entry)(delete_dn, attrs_to_clear) -- except errors.NotFound: -- raise -- clearedCredential = False -- for attr in attrs_to_clear: -- if attr.lower() in entry_attrs: -- del entry_attrs[attr] -- clearedCredential = True -- if clearedCredential: -- self._exc_wrapper(keys, options, ldap.update_entry)(entry_attrs) -- -- # Then restore some original entry attributes -- attrs_to_restore = [ 'secretary', 'managedby', 'manager', 'ipauniqueid', 'uidnumber', 'gidnumber', 'passwordHistory'] -- try: -- entry_attrs = self._exc_wrapper(keys, options, ldap.get_entry)(delete_dn, attrs_to_restore) -- except errors.NotFound: -- raise -- restoreAttr = False -- for attr in attrs_to_restore: -- if (attr.lower() in original_entry_attrs) and not (attr.lower() in entry_attrs): -- restoreAttr = True -- entry_attrs[attr.lower()] = original_entry_attrs[attr.lower()] -- if restoreAttr: -- self._exc_wrapper(keys, options, ldap.update_entry)(entry_attrs) -- -- val = dict(result=dict(failed=[]), value=[keys[-1][0]]) -+ failed = [] -+ preserved = [] -+ for pkey in keys[-1]: -+ try: -+ self._preserve_user(pkey, delete_container, **options) -+ preserved.append(pkey_to_value(pkey, options)) -+ except: -+ if not options.get('continue', False): -+ raise -+ failed.append(pkey_to_value(pkey, options)) -+ -+ val = dict(result=dict(failed=failed), value=preserved) - return val - else: - return super(user_del, self).execute(*keys, **options) --- -2.4.3 - diff --git a/SOURCES/0091-trust-automatically-resolve-DNS-trust-conflicts-for-.patch b/SOURCES/0091-trust-automatically-resolve-DNS-trust-conflicts-for-.patch new file mode 100644 index 0000000..3d3a5e8 --- /dev/null +++ b/SOURCES/0091-trust-automatically-resolve-DNS-trust-conflicts-for-.patch @@ -0,0 +1,382 @@ +From 79bcdeb76d51fec5e8eab08f7642e7910e925bb4 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Mon, 15 Aug 2016 18:14:00 +0300 +Subject: [PATCH] trust: automatically resolve DNS trust conflicts for triangle + trusts + +For configuration where: + - AD example.com trusts IPA at ipa.example.com + - AD example.org trusts AD example.com + - a trust is tried to be established between ipa.example.com and + example.org, + +there will be a trust topology conflict detected by example.org domain +controller because ipa.example.com DNS namespace overlaps with +example.com DNS namespace. + +This type of trust topology conflict is documented in MS-ADTS 6.1.6.9.3.2 +"Building Well-Formed msDS-TrustForestTrustInfo Message". A similar +conflict can arise for SID and NetBIOS namespaces. However, unlike SID +and NetBIOS namespaces, we can solve DNS namespace conflict +automatically if there are administrative credentials for example.org +available. + +A manual sequence to solve the DNS namespace conflict is described in +https://msdn.microsoft.com/it-it/library/cc786254%28v=ws.10%29.aspx. +This sequence boils down to the following steps: + + 1. As an administrator of the example.org, you need to add an +exclusion entry for ipa.example.com in the properties of the trust to +example.com + 2. Establish trust between ipa.example.com and example.org + +It is important to add the exclusion entry before step 4 or there will +be conflict recorded which cannot be cleared easily right now due to a +combination of bugs in both IPA and Active Directory. + +This patchset implements automated solution for the case when we have +access to the example.org's administrator credentials: + + 1. Attempt to establish trust and update trust topology information. + 2. If trust topology conflict is detected as result of (1): + 2.1. Fetch trust topology infromation for the conflicting forest + trust + 2.2. Add exclusion entry to our domain to the trust topology obtained + in (2.1) + 2.3. Update trust topology for the conflicting forest trust + 3. Re-establish trust between ipa.example.com and example.org + +We cannot do the same for shared secret trust and for external trust, +though: + + 1. For shared secret trust we don't have administrative credentials + in the forest reporting the conflict + + 2. For the external trust we cannot set topology information due to + MS-LSAD 3.1.4.7.16 because external trust is non-transitive by + definition and thus setting topology information will fail. + +To test this logic one can use two Samba AD forests with FreeIPA +using a sub-domain of one of them. + +Fixes: https://fedorahosted.org/freeipa/ticket/6076 +Reviewed-By: Martin Babinsky +--- + ipalib/errors.py | 29 ++++++- + ipaserver/dcerpc.py | 220 +++++++++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 220 insertions(+), 29 deletions(-) + +diff --git a/ipalib/errors.py b/ipalib/errors.py +index 7b4f15dd60ee80719195ba1b9b85d075b10bdf4f..4cc4455b0abf7d2b1366e1ce6dbb3762bc551cc6 100644 +--- a/ipalib/errors.py ++++ b/ipalib/errors.py +@@ -866,7 +866,6 @@ class NotAForestRootError(InvocationError): + errno = 3016 + format = _("Domain '%(domain)s' is not a root domain for forest '%(forest)s'") + +- + ############################################################################## + # 4000 - 4999: Execution errors + +@@ -1908,6 +1907,34 @@ class DNSResolverError(DNSError): + errno = 4401 + format = _('%(exception)s') + ++class TrustError(ExecutionError): ++ """ ++ **4500** Base class for trust execution errors (*4500 - 4599*). ++ These are typically instantiated when there is an error in establishing or ++ modifying a trust to another forest. ++ """ ++ ++ errno = 4500 ++ ++class TrustTopologyConflictError(TrustError): ++ """ ++ **4501** Raised when an attempt to establish trust fails with a topology ++ conflict against another forest the target forest trusts ++ ++ For example: ++ ++ >>> raise TrustTopologyConflictError(forest='example.test', ++ conflict='my.ad.test', ++ domains=['ad.test']) ++ Traceback (most recent call last): ++ ... ++ TrustTopologyConflictError: Forest 'example.test' has existing trust to forest(s) ['ad.test'] which prevents a trust to 'my.ad.test' ++ """ ++ ++ errno = 4501 ++ format = _("Forest '%(forest)s' has existing trust to forest(s) " ++ "%(domains)s which prevents a trust to '%(conflict)s'") ++ + + ############################################################################## + # 5000 - 5999: Generic errors +diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py +index 19be6bf7a3617a3b867d51a9358c9926e91049a7..a1c12f16a655493808d50e6adb95e618a664a98c 100644 +--- a/ipaserver/dcerpc.py ++++ b/ipaserver/dcerpc.py +@@ -1,7 +1,7 @@ + # Authors: + # Alexander Bokovoy + # +-# Copyright (C) 2011 Red Hat ++# Copyright (C) 2011-2016 Red Hat + # see file 'COPYING' for use and warranty information + # + # Portions (C) Andrew Tridgell, Andrew Bartlett +@@ -140,6 +140,15 @@ pysss_type_key_translation_dict = { + pysss_nss_idmap.ID_BOTH: 'both', + } + ++class TrustTopologyConflictSolved(Exception): ++ """ ++ Internal trust error: raised when previously detected ++ trust topology conflict is automatically solved. ++ ++ No separate errno is assigned as this error should ++ not be visible outside the dcerpc.py code. ++ """ ++ pass + + def assess_dcerpc_exception(num=None, message=None): + """ +@@ -1087,34 +1096,165 @@ class TrustDomainInstance(object): + info.entries = ftinfo_records + return info + ++ def clear_ftinfo_conflict(self, another_domain, cinfo): ++ """ ++ Attempt to clean up the forest trust collisions ++ ++ :param self: the forest we establish trust to ++ :param another_domain: a forest that establishes trust to 'self' ++ :param cinfo: lsa_ForestTrustCollisionInfo structure that contain ++ set of of lsa_ForestTrustCollisionRecord structures ++ :raises: TrustTopologyConflictSolved, TrustTopologyConflictError ++ ++ This code tries to perform intelligent job of going ++ over individual collisions and making exclusion entries ++ for affected IPA namespaces. ++ ++ There are three possible conflict configurations: ++ - conflict of DNS namespace (TLN conflict, LSA_TLN_DISABLED_CONFLICT) ++ - conflict of SID namespace (LSA_SID_DISABLED_CONFLICT) ++ - conflict of NetBIOS namespace (LSA_NB_DISABLED_CONFLICT) ++ ++ we only can handle TLN conflicts because (a) excluding SID namespace ++ is not possible and (b) excluding NetBIOS namespace not possible. ++ These two types of conflicts should result in trust-add CLI error ++ ++ These conflicts can come from external source (another forest) or ++ from internal source (another domain in the same forest). We only ++ can fix the problems with another forest. ++ ++ To resolve TLN conflict we need to do following: ++ 1. Retrieve forest trust information for the forest we conflict on ++ 2. Add an exclusion entry for IPA DNS namespace to it ++ 3. Set forest trust information for the forest we conflict on ++ 4. Re-try establishing trust to the original forest ++ ++ This all can only be done under privileges of Active Directory admin ++ that can change forest trusts. If we cannot have those privileges, ++ the work has to be done manually in the Windows UI for ++ 'Active Directory Domains and Trusts' by the administrator of the ++ original forest. ++ """ ++ ++ # List of entries for unsolved conflicts ++ result = [] ++ ++ trust_timestamp = long(time.time()*1e7+116444736000000000) ++ ++ # Collision information contains entries for specific trusted domains ++ # we collide with. Look into TLN collisions and add a TLN exclusion ++ # entry to the specific domain trust. ++ root_logger.error("Attempt to solve forest trust topology conflicts") ++ for rec in cinfo.entries: ++ if rec.type == lsa.LSA_FOREST_TRUST_COLLISION_TDO: ++ dominfo = self._pipe.lsaRQueryForestTrustInformation( ++ self._policy_handle, ++ rec.name, ++ lsa.LSA_FOREST_TRUST_DOMAIN_INFO) ++ ++ # Oops, we were unable to retrieve trust topology for this ++ # trusted domain (forest). ++ if not dominfo: ++ result.append(rec) ++ root_logger.error("Unable to resolve conflict for " ++ "DNS domain %s in the forest %s " ++ "for domain trust %s. Trust cannot " ++ "be established unless this conflict " ++ "is fixed manually." ++ % (another_domain.info['dns_domain'], ++ self.info['dns_domain'], ++ rec.name.string)) ++ continue ++ ++ # Copy over the entries, extend with TLN exclusion ++ entries = [] ++ for e in dominfo.entries: ++ e1 = lsa.ForestTrustRecord() ++ e1.type = e.type ++ e1.flags = e.flags ++ e1.time = e.time ++ e1.forest_trust_data = e.forest_trust_data ++ entries.append(e1) ++ ++ # Create TLN exclusion record ++ record = lsa.ForestTrustRecord() ++ record.type = lsa.LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX ++ record.flags = 0 ++ record.time = trust_timestamp ++ record.forest_trust_data.string = \ ++ another_domain.info['dns_domain'] ++ entries.append(record) ++ ++ fti = lsa.ForestTrustInformation() ++ fti.count = len(entries) ++ fti.entries = entries ++ ++ # Update the forest trust information now ++ ldname = lsa.StringLarge() ++ ldname.string = rec.name.string ++ cninfo = self._pipe.lsaRSetForestTrustInformation( ++ self._policy_handle, ++ ldname, ++ lsa.LSA_FOREST_TRUST_DOMAIN_INFO, ++ fti, 0) ++ if cninfo: ++ result.append(rec) ++ root_logger.error("When defining exception for DNS " ++ "domain %s in forest %s for " ++ "trusted forest %s, " ++ "got collision info back:\n%s" ++ % (another_domain.info['dns_domain'], ++ self.info['dns_domain'], ++ rec.name.string, ++ ndr_print(cninfo))) ++ else: ++ result.append(rec) ++ root_logger.error("Unable to resolve conflict for " ++ "DNS domain %s in the forest %s " ++ "for in-forest domain %s. Trust cannot " ++ "be established unless this conflict " ++ "is fixed manually." ++ % (another_domain.info['dns_domain'], ++ self.info['dns_domain'], ++ rec.name.string)) ++ ++ if len(result) == 0: ++ root_logger.error("Successfully solved all conflicts") ++ raise TrustTopologyConflictSolved() ++ ++ # Otherwise, raise TrustTopologyConflictError() exception ++ domains = [x.name.string for x in result] ++ raise errors.TrustTopologyConflictError( ++ target=self.info['dns_domain'], ++ conflict=another_domain.info['dns_domain'], ++ domains=domains) ++ ++ ++ + def update_ftinfo(self, another_domain): + """ + Updates forest trust information in this forest corresponding + to the another domain's information. + """ +- try: +- if another_domain.ftinfo_records: +- ftinfo = self.generate_ftinfo(another_domain) +- # Set forest trust information -- we do it only against AD DC as +- # smbd already has the information about itself +- ldname = lsa.StringLarge() +- ldname.string = another_domain.info['dns_domain'] +- ftlevel = lsa.LSA_FOREST_TRUST_DOMAIN_INFO +- # RSetForestTrustInformation returns collision information +- # for trust topology +- cinfo = self._pipe.lsaRSetForestTrustInformation( +- self._policy_handle, +- ldname, +- ftlevel, +- ftinfo, 0) +- if cinfo: +- root_logger.error("When setting forest trust information, " +- "got collision info back:\n%s" +- % (ndr_print(cinfo))) +- except RuntimeError as e: +- # We can ignore the error here -- +- # setting up name suffix routes may fail +- pass ++ if another_domain.ftinfo_records: ++ ftinfo = self.generate_ftinfo(another_domain) ++ # Set forest trust information -- we do it only against AD DC as ++ # smbd already has the information about itself ++ ldname = lsa.StringLarge() ++ ldname.string = another_domain.info['dns_domain'] ++ ftlevel = lsa.LSA_FOREST_TRUST_DOMAIN_INFO ++ # RSetForestTrustInformation returns collision information ++ # for trust topology ++ cinfo = self._pipe.lsaRSetForestTrustInformation( ++ self._policy_handle, ++ ldname, ++ ftlevel, ++ ftinfo, 0) ++ if cinfo: ++ root_logger.error("When setting forest trust information, " ++ "got collision info back:\n%s" ++ % (ndr_print(cinfo))) ++ self.clear_ftinfo_conflict(another_domain, cinfo) + + def establish_trust(self, another_domain, trustdom_secret, + trust_type='bidirectional', trust_external=False): +@@ -1207,7 +1347,19 @@ class TrustDomainInstance(object): + root_logger.error( + 'unable to set trust transitivity status: %s' % (str(e))) + +- if self.info['is_pdc'] or trust_external: ++ # Updating forest trust info may fail ++ # If it failed due to topology conflict, it may be fixed automatically ++ # update_ftinfo() will through exceptions in that case ++ # Note that MS-LSAD 3.1.4.7.16 says: ++ # ------------------------- ++ # The server MUST also make sure that the trust attributes associated ++ # with the trusted domain object referenced by the TrustedDomainName ++ # parameter has the TRUST_ATTRIBUTE_FOREST_TRANSITIVE set. ++ # If the attribute is not present, the server MUST return ++ # STATUS_INVALID_PARAMETER. ++ # ------------------------- ++ # Thus, we must not update forest trust info for the external trust ++ if self.info['is_pdc'] and not trust_external: + self.update_ftinfo(another_domain) + + def verify_trust(self, another_domain): +@@ -1509,9 +1661,21 @@ class TrustDomainJoins(object): + if not self.remote_domain.read_only: + trustdom_pass = samba.generate_random_password(128, 128) + self.get_realmdomains() +- self.remote_domain.establish_trust(self.local_domain, +- trustdom_pass, +- trust_type, trust_external) ++ ++ # Establishing trust may throw an exception for topology ++ # conflict. If it was solved, re-establish the trust again ++ # Otherwise let the CLI to display a message about the conflict ++ try: ++ self.remote_domain.establish_trust(self.local_domain, ++ trustdom_pass, ++ trust_type, trust_external) ++ except TrustTopologyConflictSolved as e: ++ # we solved topology conflict, retry again ++ self.remote_domain.establish_trust(self.local_domain, ++ trustdom_pass, ++ trust_type, trust_external) ++ ++ # For local domain we don't set topology information + self.local_domain.establish_trust(self.remote_domain, + trustdom_pass, + trust_type, trust_external) +-- +2.7.4 + diff --git a/SOURCES/0092-DNSSEC-fix-forward-zone-forwarders-checks.patch b/SOURCES/0092-DNSSEC-fix-forward-zone-forwarders-checks.patch deleted file mode 100644 index d4945d7..0000000 --- a/SOURCES/0092-DNSSEC-fix-forward-zone-forwarders-checks.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 0f44ee49596f565f78144f676f431cb7f29bf15b Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Mon, 24 Aug 2015 12:53:30 +0200 -Subject: [PATCH] DNSSEC: fix forward zone forwarders checks - -https://fedorahosted.org/freeipa/ticket/5179 - -Reviewed-By: Petr Spacek ---- - ipalib/util.py | 13 +++++++------ - 1 file changed, 7 insertions(+), 6 deletions(-) - -diff --git a/ipalib/util.py b/ipalib/util.py -index 649a4875fde0b44844749946cce53d81f7f6eea4..a3500ae29b56ac6a289fbec97d15cf026baf7068 100644 ---- a/ipalib/util.py -+++ b/ipalib/util.py -@@ -694,20 +694,21 @@ def validate_dnssec_zone_forwarder_step2(ipa_ip_addr, fwzone, log=None, - ans_cd = _resolve_record(fwzone, rtype, nameserver_ip=ipa_ip_addr, - edns0=True, dnssec=True, flag_cd=True, - timeout=timeout) -+ except NXDOMAIN as e: -+ # sometimes CD flag is ignored and NXDomain is returned -+ _log_response(log, e) -+ raise DNSSECValidationError(owner=fwzone, rtype=rtype, ip=ipa_ip_addr) - except DNSException as e: - _log_response(log, e) -+ raise UnresolvableRecordError(owner=fwzone, rtype=rtype, -+ ip=ipa_ip_addr, error=e) - - try: - ans_do = _resolve_record(fwzone, rtype, nameserver_ip=ipa_ip_addr, - edns0=True, dnssec=True, timeout=timeout) -- except NXDOMAIN as e: -- # sometimes CD flag is ignored and NXDomain is returned -- _log_response(log, e) -- raise DNSSECValidationError(owner=fwzone, rtype=rtype, ip=ipa_ip_addr) - except DNSException as e: - _log_response(log, e) -- raise UnresolvableRecordError(owner=fwzone, rtype=rtype, ip=ipa_ip_addr, -- error=e) -+ raise DNSSECValidationError(owner=fwzone, rtype=rtype, ip=ipa_ip_addr) - else: - if (ans_do.canonical_name == ans_cd.canonical_name - and ans_do.rrset == ans_cd.rrset): --- -2.4.3 - diff --git a/SOURCES/0092-trust-make-sure-external-trust-topology-is-correctly.patch b/SOURCES/0092-trust-make-sure-external-trust-topology-is-correctly.patch new file mode 100644 index 0000000..ed41671 --- /dev/null +++ b/SOURCES/0092-trust-make-sure-external-trust-topology-is-correctly.patch @@ -0,0 +1,90 @@ +From 2026313385db9ff2d1e74b22b7e2c6be7f7a9705 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Mon, 15 Aug 2016 18:32:25 +0300 +Subject: [PATCH] trust: make sure external trust topology is correctly + rendered + +When external trust is established, it is by definition is +non-transitive: it is not possible to obtain Kerberos tickets to any +service outside the trusted domain. + +Reflect this reality by only accepting UPN suffixes from the external +trust -- since the trusted domain is a part of another forest and UPN +suffixes are forest-wide, there could be user accounts in the trusted +domain that use forest-wide UPN suffix but it will be impossible to +reach the forest root via the externally trusted domain. + +Also, an argument to netr_DsRGetForestTrustInformation() has to be +either forest root domain name or None (NULL). Otherwise we'll get +an error as explained in MS-NRPC 3.5.4.7.5. + +https://fedorahosted.org/freeipa/ticket/6021 + +Reviewed-By: Martin Babinsky +--- + ipaserver/dcerpc.py | 2 +- + ipaserver/plugins/trust.py | 28 +++++++++++++++++----------- + 2 files changed, 18 insertions(+), 12 deletions(-) + +diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py +index a1c12f16a655493808d50e6adb95e618a664a98c..4d98485e17a9113322b7e38629fc43b593e99fd9 100644 +--- a/ipaserver/dcerpc.py ++++ b/ipaserver/dcerpc.py +@@ -1449,7 +1449,7 @@ def fetch_domains(api, mydomain, trustdomain, creds=None, server=None): + # Older FreeIPA versions used netr_DsrEnumerateDomainTrusts call + # but it doesn't provide information about non-domain UPNs associated + # with the forest, thus we have to use netr_DsRGetForestTrustInformation +- domains = netr_pipe.netr_DsRGetForestTrustInformation(td.info['dc'], '', 0) ++ domains = netr_pipe.netr_DsRGetForestTrustInformation(td.info['dc'], None, 0) + return domains + + domains = None +diff --git a/ipaserver/plugins/trust.py b/ipaserver/plugins/trust.py +index f2e0b1ee4b261ddc4f29477f46b7f4027af18892..8a25b560f9ae086ba8524cca22f39e8f67696146 100644 +--- a/ipaserver/plugins/trust.py ++++ b/ipaserver/plugins/trust.py +@@ -1663,6 +1663,23 @@ def add_new_domains_from_trust(myapi, trustinstance, trust_entry, domains, **opt + for x, y in six.iteritems(domains['suffixes']) + if x not in domains['domains']) + ++ try: ++ dn = myapi.Object.trust.get_dn(trust_name, trust_type=u'ad') ++ ldap = myapi.Backend.ldap2 ++ entry = ldap.get_entry(dn) ++ tlns = entry.get('ipantadditionalsuffixes', []) ++ tlns.extend(x for x in suffixes if x not in tlns) ++ entry['ipantadditionalsuffixes'] = tlns ++ ldap.update_entry(entry) ++ except errors.EmptyModlist: ++ pass ++ ++ is_nontransitive = int(trust_entry.get('ipanttrustattributes', ++ [0])[0]) & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE ++ ++ if is_nontransitive: ++ return result ++ + for dom in six.itervalues(domains['domains']): + dom['trust_type'] = u'ad' + try: +@@ -1686,17 +1703,6 @@ def add_new_domains_from_trust(myapi, trustinstance, trust_entry, domains, **opt + # Ignore updating duplicate entries + pass + +- try: +- dn = myapi.Object.trust.get_dn(trust_name, trust_type=u'ad') +- ldap = myapi.Backend.ldap2 +- entry = ldap.get_entry(dn) +- tlns = entry.get('ipantadditionalsuffixes', []) +- tlns.extend(x for x in suffixes if x not in tlns) +- entry['ipantadditionalsuffixes'] = tlns +- ldap.update_entry(entry) +- except errors.EmptyModlist: +- pass +- + return result + + +-- +2.7.4 + diff --git a/SOURCES/0093-Added-support-for-changing-vault-encryption.patch b/SOURCES/0093-Added-support-for-changing-vault-encryption.patch deleted file mode 100644 index 466806e..0000000 --- a/SOURCES/0093-Added-support-for-changing-vault-encryption.patch +++ /dev/null @@ -1,656 +0,0 @@ -From d3271ee9de63d9c6275184875d05762666ba9088 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Fri, 31 Jul 2015 07:53:15 +0200 -Subject: [PATCH] Added support for changing vault encryption. - -The vault-mod command has been modified to support changing vault -encryption attributes (i.e. type, password, public/private keys) -in addition to normal attributes (i.e. description). Changing the -encryption requires retrieving the stored secret with the old -attributes and rearchiving it with the new attributes. - -https://fedorahosted.org/freeipa/ticket/5176 - -Reviewed-By: Martin Basti ---- - API.txt | 27 +++- - VERSION | 4 +- - ipalib/plugins/vault.py | 233 ++++++++++++++++++++++++++-- - ipatests/test_xmlrpc/test_vault_plugin.py | 249 ++++++++++++++++++++++++++++++ - 4 files changed, 498 insertions(+), 15 deletions(-) - -diff --git a/API.txt b/API.txt -index b0f456e725a6c3d24c1071b282de5a28c3b5a671..8105cfb5ba61cabcf5c0f7e1c6e44dfc0cacc9cb 100644 ---- a/API.txt -+++ b/API.txt -@@ -5474,11 +5474,12 @@ output: Output('completed', , None) - output: Output('failed', , None) - output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) - command: vault_archive --args: 1,10,3 -+args: 1,11,3 - arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True) - option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') - option: Bytes('data?') - option: Str('in?') -+option: Flag('override_password?', autofill=True, default=False) - option: Str('password?', cli_name='password') - option: Str('password_file?', cli_name='password_file') - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') -@@ -5538,6 +5539,30 @@ output: ListOfEntries('result', (, ), Gettext('A list - output: Output('summary', (, ), None) - output: Output('truncated', , None) - command: vault_mod -+args: 1,18,3 -+arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True) -+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') -+option: Flag('change_password?', autofill=True, default=False) -+option: Str('description?', cli_name='desc') -+option: Bytes('ipavaultpublickey?', cli_name='public_key') -+option: Bytes('ipavaultsalt?', cli_name='salt') -+option: Str('ipavaulttype?', cli_name='type') -+option: Str('new_password?', cli_name='new_password') -+option: Str('new_password_file?', cli_name='new_password_file') -+option: Str('old_password?', cli_name='old_password') -+option: Str('old_password_file?', cli_name='old_password_file') -+option: Bytes('private_key?', cli_name='private_key') -+option: Str('private_key_file?', cli_name='private_key_file') -+option: Str('public_key_file?', cli_name='public_key_file') -+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') -+option: Str('service?') -+option: Flag('shared?', autofill=True, default=False) -+option: Str('username?', cli_name='user') -+option: Str('version?', exclude='webui') -+output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) -+output: Output('summary', (, ), None) -+output: PrimaryKey('value', None, None) -+command: vault_mod_internal - args: 1,15,3 - arg: Str('cn', attribute=True, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=True) - option: Str('addattr*', cli_name='addattr', exclude='webui') -diff --git a/VERSION b/VERSION -index 9fe2f4d4f9ff6ffd42c2ee7493c385b0a432a6a0..3fdd2db88a7b2b6d3bd36ba0d7257c9994bc06af 100644 ---- a/VERSION -+++ b/VERSION -@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 - # # - ######################################################## - IPA_API_VERSION_MAJOR=2 --IPA_API_VERSION_MINOR=152 --# Last change: mbasti - add 'user-stage' command -+IPA_API_VERSION_MINOR=153 -+# Last change: edewata - Added support for changing vault encryption. -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index 4b2c8a518e5c9a93e5490841a3d2177536c905b1..6a07a76b5b85680536b27fd147d8ec1583bb0bc7 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -116,11 +116,37 @@ EXAMPLES: - ipa vault-show - [--user |--service |--shared] - """) + _(""" -- Modify a vault: -+ Modify vault description: - ipa vault-mod - [--user |--service |--shared] - --desc - """) + _(""" -+ Modify vault type: -+ ipa vault-mod -+ [--user |--service |--shared] -+ --type -+ [old password/private key] -+ [new password/public key] -+""") + _(""" -+ Modify symmetric vault password: -+ ipa vault-mod -+ [--user |--service |--shared] -+ --change-password -+ ipa vault-mod -+ [--user |--service |--shared] -+ --old-password -+ --new-password -+ ipa vault-mod -+ [--user |--service |--shared] -+ --old-password-file -+ --new-password-file -+""") + _(""" -+ Modify asymmetric vault keys: -+ ipa vault-mod -+ [--user |--service |--shared] -+ --private-key-file -+ --public-key-file -+""") + _(""" - Delete a vault: - ipa vault-del - [--user |--service |--shared] -@@ -457,7 +483,7 @@ class vault(LDAPObject): - - print ' ** Passwords do not match! **' - -- def get_existing_password(self, new=False): -+ def get_existing_password(self): - """ - Gets existing password from user. - """ -@@ -871,9 +897,182 @@ class vault_find(LDAPSearch): - - - @register() --class vault_mod(LDAPUpdate): -+class vault_mod(PKQuery, Local): - __doc__ = _('Modify a vault.') - -+ takes_options = vault_options + ( -+ Str( -+ 'description?', -+ cli_name='desc', -+ doc=_('Vault description'), -+ ), -+ Str( -+ 'ipavaulttype?', -+ cli_name='type', -+ doc=_('Vault type'), -+ ), -+ Bytes( -+ 'ipavaultsalt?', -+ cli_name='salt', -+ doc=_('Vault salt'), -+ ), -+ Flag( -+ 'change_password?', -+ doc=_('Change password'), -+ ), -+ Str( -+ 'old_password?', -+ cli_name='old_password', -+ doc=_('Old vault password'), -+ ), -+ Str( # TODO: use File parameter -+ 'old_password_file?', -+ cli_name='old_password_file', -+ doc=_('File containing the old vault password'), -+ ), -+ Str( -+ 'new_password?', -+ cli_name='new_password', -+ doc=_('New vault password'), -+ ), -+ Str( # TODO: use File parameter -+ 'new_password_file?', -+ cli_name='new_password_file', -+ doc=_('File containing the new vault password'), -+ ), -+ Bytes( -+ 'private_key?', -+ cli_name='private_key', -+ doc=_('Old vault private key'), -+ ), -+ Str( # TODO: use File parameter -+ 'private_key_file?', -+ cli_name='private_key_file', -+ doc=_('File containing the old vault private key'), -+ ), -+ Bytes( -+ 'ipavaultpublickey?', -+ cli_name='public_key', -+ doc=_('New vault public key'), -+ ), -+ Str( # TODO: use File parameter -+ 'public_key_file?', -+ cli_name='public_key_file', -+ doc=_('File containing the new vault public key'), -+ ), -+ ) -+ -+ has_output = output.standard_entry -+ -+ def forward(self, *args, **options): -+ -+ vault_type = options.pop('ipavaulttype', False) -+ salt = options.pop('ipavaultsalt', False) -+ change_password = options.pop('change_password', False) -+ -+ old_password = options.pop('old_password', None) -+ old_password_file = options.pop('old_password_file', None) -+ new_password = options.pop('new_password', None) -+ new_password_file = options.pop('new_password_file', None) -+ -+ old_private_key = options.pop('private_key', None) -+ old_private_key_file = options.pop('private_key_file', None) -+ new_public_key = options.pop('ipavaultpublickey', None) -+ new_public_key_file = options.pop('public_key_file', None) -+ -+ if self.api.env.in_server: -+ backend = self.api.Backend.ldap2 -+ else: -+ backend = self.api.Backend.rpcclient -+ if not backend.isconnected(): -+ backend.connect(ccache=krbV.default_context().default_ccache()) -+ -+ # determine the vault type based on parameters specified -+ if vault_type: -+ pass -+ -+ elif change_password or new_password or new_password_file or salt: -+ vault_type = u'symmetric' -+ -+ elif new_public_key or new_public_key_file: -+ vault_type = u'asymmetric' -+ -+ # if vault type is specified, retrieve existing secret -+ if vault_type: -+ opts = options.copy() -+ opts.pop('description', None) -+ -+ opts['password'] = old_password -+ opts['password_file'] = old_password_file -+ opts['private_key'] = old_private_key -+ opts['private_key_file'] = old_private_key_file -+ -+ response = self.api.Command.vault_retrieve(*args, **opts) -+ data = response['result']['data'] -+ -+ opts = options.copy() -+ -+ # if vault type is specified, update crypto attributes -+ if vault_type: -+ opts['ipavaulttype'] = vault_type -+ -+ if vault_type == u'standard': -+ opts['ipavaultsalt'] = None -+ opts['ipavaultpublickey'] = None -+ -+ elif vault_type == u'symmetric': -+ if salt: -+ opts['ipavaultsalt'] = salt -+ else: -+ opts['ipavaultsalt'] = os.urandom(16) -+ -+ opts['ipavaultpublickey'] = None -+ -+ elif vault_type == u'asymmetric': -+ -+ # get new vault public key -+ if new_public_key and new_public_key_file: -+ raise errors.MutuallyExclusiveError( -+ reason=_('New public key specified multiple times')) -+ -+ elif new_public_key: -+ pass -+ -+ elif new_public_key_file: -+ new_public_key = validated_read('public_key_file', -+ new_public_key_file, -+ mode='rb') -+ -+ else: -+ raise errors.ValidationError( -+ name='ipavaultpublickey', -+ error=_('Missing new vault public key')) -+ -+ opts['ipavaultsalt'] = None -+ opts['ipavaultpublickey'] = new_public_key -+ -+ response = self.api.Command.vault_mod_internal(*args, **opts) -+ -+ # if vault type is specified, rearchive existing secret -+ if vault_type: -+ opts = options.copy() -+ opts.pop('description', None) -+ -+ opts['data'] = data -+ opts['password'] = new_password -+ opts['password_file'] = new_password_file -+ opts['override_password'] = True -+ -+ self.api.Command.vault_archive(*args, **opts) -+ -+ return response -+ -+ -+@register() -+class vault_mod_internal(LDAPUpdate): -+ -+ NO_CLI = True -+ - takes_options = LDAPUpdate.takes_options + vault_options - - msg_summary = _('Modified vault "%(value)s"') -@@ -994,6 +1193,10 @@ class vault_archive(PKQuery, Local): - cli_name='password_file', - doc=_('File containing the vault password'), - ), -+ Flag( -+ 'override_password?', -+ doc=_('Override existing password'), -+ ), - ) - - has_output = output.standard_entry -@@ -1008,6 +1211,8 @@ class vault_archive(PKQuery, Local): - password = options.get('password') - password_file = options.get('password_file') - -+ override_password = options.pop('override_password', False) -+ - # don't send these parameters to server - if 'data' in options: - del options['data'] -@@ -1062,15 +1267,19 @@ class vault_archive(PKQuery, Local): - password = password.rstrip('\n') - - else: -- password = self.obj.get_existing_password() -- -- # verify password by retrieving existing data -- opts = options.copy() -- opts['password'] = password -- try: -- self.api.Command.vault_retrieve(*args, **opts) -- except errors.NotFound: -- pass -+ if override_password: -+ password = self.obj.get_new_password() -+ else: -+ password = self.obj.get_existing_password() -+ -+ if not override_password: -+ # verify password by retrieving existing data -+ opts = options.copy() -+ opts['password'] = password -+ try: -+ self.api.Command.vault_retrieve(*args, **opts) -+ except errors.NotFound: -+ pass - - salt = vault['ipavaultsalt'][0] - -diff --git a/ipatests/test_xmlrpc/test_vault_plugin.py b/ipatests/test_xmlrpc/test_vault_plugin.py -index fe2f2f67d664e0640fdda99fd3e2f068ee61cb01..40ce46406702740ef5a781c3d3569b4f2e088b92 100644 ---- a/ipatests/test_xmlrpc/test_vault_plugin.py -+++ b/ipatests/test_xmlrpc/test_vault_plugin.py -@@ -36,6 +36,7 @@ asymmetric_vault_name = u'asymmetric_test_vault' - secret = ''.join(map(chr, xrange(0, 256))) - - password = u'password' -+other_password = u'other_password' - - public_key = """ - -----BEGIN PUBLIC KEY----- -@@ -79,6 +80,48 @@ kUlCMj24a8XsShzYTWBIyW2ngvGe3pQ9PfjkUdm0LGZjYITCBvgOKw== - -----END RSA PRIVATE KEY----- - """ - -+other_public_key = """ -+-----BEGIN PUBLIC KEY----- -+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv7E/QLVyKjrgDctZ50U7 -+rmtL7Ks1QLoccp9WvZJ6WI1rYd0fX5FySS4dI6QTNZc6qww8NeNuZtkoxT9m1wkk -+Rl/3wK7fWNLenH/+VHOaTQc20exg7ztfsO7JIsmKmigtticdR5C4jLfjcOp+WjLH -+w3zrmrO5SIZ8njxMoDcQJa2vu/t281U/I7ti8ue09FSitIECU05vgmPS+MnXR8HK -+PxXqrNkjl29mXNbPiByWwlse3Prwved9I7fwgpiHJqUBFudD/0tZ4DWyLG7t9wM1 -+O8gRaRg1r+ENVpmMSvXo4+8+bR3rEYddD5zU7nKXafeuthXlXplae/8uZmCiSI63 -+TwIDAQAB -+-----END PUBLIC KEY----- -+""" -+ -+other_private_key = """ -+-----BEGIN RSA PRIVATE KEY----- -+MIIEpgIBAAKCAQEAv7E/QLVyKjrgDctZ50U7rmtL7Ks1QLoccp9WvZJ6WI1rYd0f -+X5FySS4dI6QTNZc6qww8NeNuZtkoxT9m1wkkRl/3wK7fWNLenH/+VHOaTQc20exg -+7ztfsO7JIsmKmigtticdR5C4jLfjcOp+WjLHw3zrmrO5SIZ8njxMoDcQJa2vu/t2 -+81U/I7ti8ue09FSitIECU05vgmPS+MnXR8HKPxXqrNkjl29mXNbPiByWwlse3Prw -+ved9I7fwgpiHJqUBFudD/0tZ4DWyLG7t9wM1O8gRaRg1r+ENVpmMSvXo4+8+bR3r -+EYddD5zU7nKXafeuthXlXplae/8uZmCiSI63TwIDAQABAoIBAQCA+0GFR9F+isjx -+Xy+qBpKmxLl8kKKvX8r+cSpLOkEqTlW/rqqKgnI0vVuL/L2UJKKsLvpghBxoBZyC -+RCvtatBGrhIlS0UrHg/9m73Ek1hylfUUAQokTn4PrkwWJSgmm/xOATmZSs5ymNTn -+yFCmXl69sdNR77YvD5bQXeBtOT+bKXy7yQ1TmYPwwSjL+WSlMV6ZfE3HNVmxPTpk -+CTFS638cJblWk9MUIy8HIlhu6If2P4RnHr7ZGGivhREayvs0zXcAfqhIyFHruxSE -+yYnmqH9paWjv5mP3YyLoKr+NUvvxnBr/9wCTt0TKgG8G6rpkHuPDLQni9wUGnew8 -+QdMgFEohAoGBAPH4vaVB5gDVfvIqwJBsBLHpPq72GvxjrM/exD0jIIpXZxz9gCql -+CmC5b1RS1uy8PMoc/RO4CE7UTLaTesciP6LjTD1RhH3rLLJO8/iVC1RXgMrCLHLm -+ZQnDhIQGGNQxpvBjQy5ZOWat2dFxYhHN630IFPOtrWsOmJ5HsL1JrjzxAoGBAMrO -+R1zNwQ42VbJS6AFshZVjmUV2h3REGh4zG/9IqL0Hz493hyCTGoDPLLXIbtkqNqzQ -+XibSZ9RMVPKKTiNQTx91DTgh4Anz8xUr84tA2iAf3ayNWKi3Y3GhmP2EWp1qYeom -+kV8Uq0lt4dHZuEo3LuqvbtbzlF9qUXqKS5qy6Tg/AoGBAKCp02o2HjzxhS/QeTmr -+r1ZeE7PiTzrECAuh01TwzPtuW1XhcEdgfEqK9cPcmT5pIkflBZkhOcr1pdYYiI5O -+TEigeY/BX6KoE251hALLG9GtpCN82DyWhAH+oy9ySOwj5793eTT+I2HtD1LE4SQH -+QVQsmJTP/fS2pVl7KnwUvy9RAoGBAKzo2qchNewsHzx+uxgbsnkABfnXaP2T4sDE -+yqYJCPTB6BFl02vOf9Y6zN/gF8JH333P2bY3xhaXTgXMLXqmSg+D+NVW7HEP8Lyo -+UGj1zgN9p74qdODEGqETKiFb6vYzcW/1mhP6x18/tDz658k+611kXZge7O288+MK -+bhNjXrx5AoGBAMox25PcxVgOjCd9+LdUcIOG6LQ971eCH1NKL9YAekICnwMrStbK -+veCYju6ok4ZWnMiH8MR1jgC39RWtjJZwynCuPXUP2/vZkoVf1tCZyz7dSm8TdS/2 -+5NdOHVy7+NQcEPSm7/FmXdpcR9ZSGAuxMBfnEUibdyz5LdJGnFUN/+HS -+-----END RSA PRIVATE KEY----- -+""" -+ - - class test_vault_plugin(Declarative): - -@@ -580,6 +623,48 @@ class test_vault_plugin(Declarative): - }, - - { -+ 'desc': 'Change standard vault to symmetric vault', -+ 'command': ( -+ 'vault_mod', -+ [standard_vault_name], -+ { -+ 'ipavaulttype': u'symmetric', -+ 'new_password': password, -+ }, -+ ), -+ 'expected': { -+ 'value': standard_vault_name, -+ 'summary': u'Modified vault "%s"' % standard_vault_name, -+ 'result': { -+ 'cn': [standard_vault_name], -+ 'ipavaulttype': [u'symmetric'], -+ 'ipavaultsalt': [fuzzy_string], -+ 'owner_user': [u'admin'], -+ }, -+ }, -+ }, -+ -+ { -+ 'desc': 'Retrieve secret from standard vault converted to ' -+ 'symmetric vault', -+ 'command': ( -+ 'vault_retrieve', -+ [standard_vault_name], -+ { -+ 'password': password, -+ }, -+ ), -+ 'expected': { -+ 'value': standard_vault_name, -+ 'summary': 'Retrieved data from vault "%s"' -+ % standard_vault_name, -+ 'result': { -+ 'data': secret, -+ }, -+ }, -+ }, -+ -+ { - 'desc': 'Create symmetric vault', - 'command': ( - 'vault_add', -@@ -642,6 +727,90 @@ class test_vault_plugin(Declarative): - }, - - { -+ 'desc': 'Change symmetric vault password', -+ 'command': ( -+ 'vault_mod', -+ [symmetric_vault_name], -+ { -+ 'old_password': password, -+ 'new_password': other_password, -+ }, -+ ), -+ 'expected': { -+ 'value': symmetric_vault_name, -+ 'summary': u'Modified vault "%s"' % symmetric_vault_name, -+ 'result': { -+ 'cn': [symmetric_vault_name], -+ 'ipavaulttype': [u'symmetric'], -+ 'ipavaultsalt': [fuzzy_string], -+ 'owner_user': [u'admin'], -+ }, -+ }, -+ }, -+ -+ { -+ 'desc': 'Retrieve secret from symmetric vault with new password', -+ 'command': ( -+ 'vault_retrieve', -+ [symmetric_vault_name], -+ { -+ 'password': other_password, -+ }, -+ ), -+ 'expected': { -+ 'value': symmetric_vault_name, -+ 'summary': 'Retrieved data from vault "%s"' -+ % symmetric_vault_name, -+ 'result': { -+ 'data': secret, -+ }, -+ }, -+ }, -+ -+ { -+ 'desc': 'Change symmetric vault to asymmetric vault', -+ 'command': ( -+ 'vault_mod', -+ [symmetric_vault_name], -+ { -+ 'ipavaulttype': u'asymmetric', -+ 'old_password': other_password, -+ 'ipavaultpublickey': public_key, -+ }, -+ ), -+ 'expected': { -+ 'value': symmetric_vault_name, -+ 'summary': u'Modified vault "%s"' % symmetric_vault_name, -+ 'result': { -+ 'cn': [symmetric_vault_name], -+ 'ipavaulttype': [u'asymmetric'], -+ 'ipavaultpublickey': [public_key], -+ 'owner_user': [u'admin'], -+ }, -+ }, -+ }, -+ -+ { -+ 'desc': 'Retrieve secret from symmetric vault converted to ' -+ 'asymmetric vault', -+ 'command': ( -+ 'vault_retrieve', -+ [symmetric_vault_name], -+ { -+ 'private_key': private_key, -+ }, -+ ), -+ 'expected': { -+ 'value': symmetric_vault_name, -+ 'summary': 'Retrieved data from vault "%s"' -+ % symmetric_vault_name, -+ 'result': { -+ 'data': secret, -+ }, -+ }, -+ }, -+ -+ { - 'desc': 'Create asymmetric vault', - 'command': ( - 'vault_add', -@@ -702,4 +871,84 @@ class test_vault_plugin(Declarative): - }, - }, - -+ { -+ 'desc': 'Change asymmetric vault keys', -+ 'command': ( -+ 'vault_mod', -+ [asymmetric_vault_name], -+ { -+ 'private_key': private_key, -+ 'ipavaultpublickey': other_public_key, -+ }, -+ ), -+ 'expected': { -+ 'value': asymmetric_vault_name, -+ 'summary': u'Modified vault "%s"' % asymmetric_vault_name, -+ 'result': { -+ 'cn': [asymmetric_vault_name], -+ 'ipavaulttype': [u'asymmetric'], -+ 'ipavaultpublickey': [other_public_key], -+ 'owner_user': [u'admin'], -+ }, -+ }, -+ }, -+ -+ { -+ 'desc': 'Retrieve secret from asymmetric vault with new keys', -+ 'command': ( -+ 'vault_retrieve', -+ [asymmetric_vault_name], -+ { -+ 'private_key': other_private_key, -+ }, -+ ), -+ 'expected': { -+ 'value': asymmetric_vault_name, -+ 'summary': 'Retrieved data from vault "%s"' -+ % asymmetric_vault_name, -+ 'result': { -+ 'data': secret, -+ }, -+ }, -+ }, -+ -+ { -+ 'desc': 'Change asymmetric vault to standard vault', -+ 'command': ( -+ 'vault_mod', -+ [asymmetric_vault_name], -+ { -+ 'ipavaulttype': u'standard', -+ 'private_key': other_private_key, -+ }, -+ ), -+ 'expected': { -+ 'value': asymmetric_vault_name, -+ 'summary': u'Modified vault "%s"' % asymmetric_vault_name, -+ 'result': { -+ 'cn': [asymmetric_vault_name], -+ 'ipavaulttype': [u'standard'], -+ 'owner_user': [u'admin'], -+ }, -+ }, -+ }, -+ -+ { -+ 'desc': 'Retrieve secret from asymmetric vault converted to ' -+ 'standard vault', -+ 'command': ( -+ 'vault_retrieve', -+ [asymmetric_vault_name], -+ {}, -+ ), -+ 'expected': { -+ 'value': asymmetric_vault_name, -+ 'summary': 'Retrieved data from vault "%s"' -+ % asymmetric_vault_name, -+ 'result': { -+ 'data': secret, -+ }, -+ }, -+ }, -+ - ] --- -2.4.3 - diff --git a/SOURCES/0093-trust-make-sure-ID-range-is-created-for-the-child-do.patch b/SOURCES/0093-trust-make-sure-ID-range-is-created-for-the-child-do.patch new file mode 100644 index 0000000..eab6add --- /dev/null +++ b/SOURCES/0093-trust-make-sure-ID-range-is-created-for-the-child-do.patch @@ -0,0 +1,71 @@ +From 590c3649471832092a20a5eaf09ed0418ae468f6 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Sat, 6 Aug 2016 11:12:13 +0300 +Subject: [PATCH] trust: make sure ID range is created for the child domain + even if it exists + +ID ranges for child domains of a forest trust were created incorrectly +in FreeIPA 4.4.0 due to refactoring of -- if the domain was already +existing, we never attempted to create the ID range for it. + +At the same time, when domain was missing, we attempted to add ID range +and passed both forest root and the child domain names to add_range(). +However, add_range() only looks at the first positional argument which +was the forest root name. That ID range always exists (it is created +before child domains are processed). + +Modify the code to make sure child domain name is passed as the first +positional argument. In addition, the oddjob helper should explicitly +set context='server' so that idrange code will be able to see and use +ipaserver/dcerpc.py helpers. + +Resolves: https://fedorahosted.org/freeipa/ticket/5738 +Reviewed-By: Martin Babinsky +--- + install/oddjob/com.redhat.idm.trust-fetch-domains | 2 +- + ipaserver/plugins/trust.py | 10 +++++++--- + 2 files changed, 8 insertions(+), 4 deletions(-) + +diff --git a/install/oddjob/com.redhat.idm.trust-fetch-domains b/install/oddjob/com.redhat.idm.trust-fetch-domains +index 7c948fd53bd54bf3638ef3cc4407576b9011f4fb..bffa021cd4f01d31b7271d1ad84420884ce8d99e 100755 +--- a/install/oddjob/com.redhat.idm.trust-fetch-domains ++++ b/install/oddjob/com.redhat.idm.trust-fetch-domains +@@ -76,7 +76,7 @@ env._bootstrap(debug=options.debug, log=None) + env._finalize_core(**dict(DEFAULT_CONFIG)) + + # Initialize the API with the proper debug level +-api.bootstrap(in_server=True, debug=env.debug, log=None) ++api.bootstrap(in_server=True, debug=env.debug, log=None, context='server') + api.finalize() + + # Only import trust plugin after api is initialized or internal imports +diff --git a/ipaserver/plugins/trust.py b/ipaserver/plugins/trust.py +index 8a25b560f9ae086ba8524cca22f39e8f67696146..b9d9b122a90de62946307b99b44932129eb611e8 100644 +--- a/ipaserver/plugins/trust.py ++++ b/ipaserver/plugins/trust.py +@@ -1690,15 +1690,19 @@ def add_new_domains_from_trust(myapi, trustinstance, trust_entry, domains, **opt + if 'raw' in options: + dom['raw'] = options['raw'] + +- res = myapi.Command.trustdomain_add(trust_name, name, **dom) +- result.append(res['result']) ++ try: ++ res = myapi.Command.trustdomain_add(trust_name, name, **dom) ++ result.append(res['result']) ++ except errors.DuplicateEntry: ++ # Ignore updating duplicate entries ++ pass + + if idrange_type != u'ipa-ad-trust-posix': + range_name = name.upper() + '_id_range' + dom['range_type'] = u'ipa-ad-trust' + add_range(myapi, trustinstance, + range_name, dom['ipanttrusteddomainsid'], +- trust_name, name, **dom) ++ name, **dom) + except errors.DuplicateEntry: + # Ignore updating duplicate entries + pass +-- +2.7.4 + diff --git a/SOURCES/0094-ipa-kdb-simplify-trusted-domain-parent-search.patch b/SOURCES/0094-ipa-kdb-simplify-trusted-domain-parent-search.patch new file mode 100644 index 0000000..416bba9 --- /dev/null +++ b/SOURCES/0094-ipa-kdb-simplify-trusted-domain-parent-search.patch @@ -0,0 +1,87 @@ +From 6c69ea75765b93768ccc3cf55a4813f2d4b81dac Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Sun, 7 Aug 2016 21:42:14 +0300 +Subject: [PATCH] ipa-kdb: simplify trusted domain parent search + +In terms of cross-forest trust parent domain is the root domain of +the forest because we only have trust established with the forest root. + +In FreeIPA LDAP store all sub-domains stored in cn=, +cn=ad,cn=trusts,... subtree. Thus, a first RDN after cn=ad is the +forest root domain. This allows us to simplify logic of finding +the parent domain. + +For complex hierachical forests with more than two levels of +sub-domains, this will still be true because of the forest trust: +as forest trust is established to the forest root domain, any +communication to any sub-domain must traverse forest root domain's +domain controller. + +Note that SSSD also generated incorrectly CA paths information +for forests with non-hierarchical tree-roots. In such cases +IPA KDC got confused and mistakenly assumed direct trust to the +non-hierarchical tree-root instead of going through the forest +root domain. See https://fedorahosted.org/sssd/ticket/3103 for +details. + +Resolves: https://fedorahosted.org/freeipa/ticket/5738 +Reviewed-By: Martin Babinsky +--- + daemons/ipa-kdb/ipa_kdb_mspac.c | 27 ++++++++++++++------------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c +index 80e7055fd6cd7b962eeffbccc675a73d73700793..76e9e99d0b691d06ccc86e0e851fb7e226d62597 100644 +--- a/daemons/ipa-kdb/ipa_kdb_mspac.c ++++ b/daemons/ipa-kdb/ipa_kdb_mspac.c +@@ -2420,6 +2420,7 @@ krb5_error_code ipadb_mspac_get_trusted_domains(struct ipadb_context *ipactx) + char *base = NULL; + char *dnstr = NULL; + char *dnl = NULL; ++ LDAPDN dn = NULL; + char **sid_blacklist_incoming = NULL; + char **sid_blacklist_outgoing = NULL; + int ret, n, i; +@@ -2547,26 +2548,26 @@ krb5_error_code ipadb_mspac_get_trusted_domains(struct ipadb_context *ipactx) + goto done; + } + +- /* Note that after ldap_str2rdn() call dnl will point to end of one RDN +- * which would be '\0' for trust root domain and ',' for subdomain */ + dnl--; dnl[0] = '\0'; +- ret = ldap_str2rdn(dnstr, &rdn, &dnl, LDAP_DN_FORMAT_LDAPV3); ++ /* Create a DN, which is now everything before the base, ++ * to get list of rdn values -- the last one would be a root domain. ++ * Since with cross-forest trust we have to route everything via root ++ * domain, that is enough for us to assign parentship. */ ++ ret = ldap_str2dn(dnstr, &dn, LDAP_DN_FORMAT_LDAPV3); + if (ret) { + goto done; + } + +- ldap_rdnfree(rdn); +- +- if (dnl[0] != '\0') { +- dnl++; +- ret = ldap_str2rdn(dnl, &rdn, &dnl, LDAP_DN_FORMAT_LDAPV3); +- if (ret) { +- goto done; +- } +- t[n].parent_name = strndup(rdn[0]->la_value.bv_val, rdn[0]->la_value.bv_len); +- ldap_rdnfree(rdn); ++ rdn = NULL; ++ for (i = 0; dn[i] != NULL; i++) { ++ rdn = dn[i]; + } + ++ /* We should have a single AVA in the domain RDN */ ++ t[n].parent_name = strndup(rdn[0]->la_value.bv_val, rdn[0]->la_value.bv_len); ++ ++ ldap_dnfree(dn); ++ + free(dnstr); + dnstr = NULL; + } +-- +2.7.4 + diff --git a/SOURCES/0094-vault-change-default-vault-type-to-symmetric.patch b/SOURCES/0094-vault-change-default-vault-type-to-symmetric.patch deleted file mode 100644 index 791afdb..0000000 --- a/SOURCES/0094-vault-change-default-vault-type-to-symmetric.patch +++ /dev/null @@ -1,115 +0,0 @@ -From 1c3faaeec41e54896536f2a3f2c3a2034d99bbdf Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Tue, 25 Aug 2015 18:25:50 +0200 -Subject: [PATCH] vault: change default vault type to symmetric - -https://fedorahosted.org/freeipa/ticket/5251 - -Reviewed-By: Martin Basti ---- - API.txt | 8 ++++---- - VERSION | 4 ++-- - ipalib/plugins/vault.py | 11 ++++++++--- - 3 files changed, 14 insertions(+), 9 deletions(-) - -diff --git a/API.txt b/API.txt -index 8105cfb5ba61cabcf5c0f7e1c6e44dfc0cacc9cb..871ddb5b7ee8b9bbae219eac673d52ad7229edc7 100644 ---- a/API.txt -+++ b/API.txt -@@ -5411,7 +5411,7 @@ option: Str('addattr*', cli_name='addattr', exclude='webui') - option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') - option: Str('description?', cli_name='desc') - option: Bytes('ipavaultpublickey?', cli_name='public_key') --option: Str('ipavaulttype?', cli_name='type') -+option: StrEnum('ipavaulttype?', autofill=True, cli_name='type', default=u'symmetric', values=(u'standard', u'symmetric', u'asymmetric')) - option: Str('password?', cli_name='password') - option: Str('password_file?', cli_name='password_file') - option: Str('public_key_file?', cli_name='public_key_file') -@@ -5431,7 +5431,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui - option: Str('description', attribute=True, cli_name='desc', multivalue=False, required=False) - option: Bytes('ipavaultpublickey', attribute=True, cli_name='public_key', multivalue=False, required=False) - option: Bytes('ipavaultsalt', attribute=True, cli_name='salt', multivalue=False, required=False) --option: StrEnum('ipavaulttype', attribute=True, autofill=True, cli_name='type', default=u'standard', multivalue=False, required=False, values=(u'standard', u'symmetric', u'asymmetric')) -+option: StrEnum('ipavaulttype', attribute=True, autofill=True, cli_name='type', default=u'symmetric', multivalue=False, required=False, values=(u'standard', u'symmetric', u'asymmetric')) - option: Flag('no_members', autofill=True, default=False, exclude='webui') - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') - option: Str('service?') -@@ -5522,7 +5522,7 @@ arg: Str('criteria?', noextrawhitespace=False) - option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') - option: Str('cn', attribute=True, autofill=False, cli_name='name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.-]+$', primary_key=True, query=True, required=False) - option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, query=True, required=False) --option: StrEnum('ipavaulttype', attribute=True, autofill=False, cli_name='type', default=u'standard', multivalue=False, query=True, required=False, values=(u'standard', u'symmetric', u'asymmetric')) -+option: StrEnum('ipavaulttype', attribute=True, autofill=False, cli_name='type', default=u'symmetric', multivalue=False, query=True, required=False, values=(u'standard', u'symmetric', u'asymmetric')) - option: Flag('no_members', autofill=True, default=False, exclude='webui') - option: Flag('pkey_only?', autofill=True, default=False) - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') -@@ -5571,7 +5571,7 @@ option: Str('delattr*', cli_name='delattr', exclude='webui') - option: Str('description', attribute=True, autofill=False, cli_name='desc', multivalue=False, required=False) - option: Bytes('ipavaultpublickey', attribute=True, autofill=False, cli_name='public_key', multivalue=False, required=False) - option: Bytes('ipavaultsalt', attribute=True, autofill=False, cli_name='salt', multivalue=False, required=False) --option: StrEnum('ipavaulttype', attribute=True, autofill=False, cli_name='type', default=u'standard', multivalue=False, required=False, values=(u'standard', u'symmetric', u'asymmetric')) -+option: StrEnum('ipavaulttype', attribute=True, autofill=False, cli_name='type', default=u'symmetric', multivalue=False, required=False, values=(u'standard', u'symmetric', u'asymmetric')) - option: Flag('no_members', autofill=True, default=False, exclude='webui') - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') - option: Flag('rights', autofill=True, default=False) -diff --git a/VERSION b/VERSION -index 3fdd2db88a7b2b6d3bd36ba0d7257c9994bc06af..c102e020bbbec921b0f4a2141d1c768ac093acf8 100644 ---- a/VERSION -+++ b/VERSION -@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 - # # - ######################################################## - IPA_API_VERSION_MAJOR=2 --IPA_API_VERSION_MINOR=153 --# Last change: edewata - Added support for changing vault encryption. -+IPA_API_VERSION_MINOR=154 -+# Last change: pvoborni - change default vault type to 'symmetric' -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index 6a07a76b5b85680536b27fd147d8ec1583bb0bc7..667524465031b6d027afbabeea48871e29c0e1e4 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -101,6 +101,7 @@ EXAMPLES: - Add a standard vault: - ipa vault-add - [--user |--service |--shared] -+ --type standard - """) + _(""" - Add a symmetric vault: - ipa vault-add -@@ -311,7 +312,7 @@ class vault(LDAPObject): - label=_('Type'), - doc=_('Vault type'), - values=(u'standard', u'symmetric', u'asymmetric', ), -- default=u'standard', -+ default=u'symmetric', - autofill=True, - ), - Bytes( -@@ -578,10 +579,14 @@ class vault_add(PKQuery, Local): - cli_name='desc', - doc=_('Vault description'), - ), -- Str( -+ StrEnum( - 'ipavaulttype?', - cli_name='type', -+ label=_('Type'), - doc=_('Vault type'), -+ values=(u'standard', u'symmetric', u'asymmetric', ), -+ default=u'symmetric', -+ autofill=True, - ), - Str( - 'password?', -@@ -609,7 +614,7 @@ class vault_add(PKQuery, Local): - - def forward(self, *args, **options): - -- vault_type = options.get('ipavaulttype', u'standard') -+ vault_type = options.get('ipavaulttype') - password = options.get('password') - password_file = options.get('password_file') - public_key = options.get('ipavaultpublickey') --- -2.4.3 - diff --git a/SOURCES/0095-Remove-Custodia-server-keys-from-LDAP.patch b/SOURCES/0095-Remove-Custodia-server-keys-from-LDAP.patch new file mode 100644 index 0000000..c4fdee1 --- /dev/null +++ b/SOURCES/0095-Remove-Custodia-server-keys-from-LDAP.patch @@ -0,0 +1,78 @@ +From dd108a1fd1088f6a4f382cccec2aec69c7d9f0fe Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Mon, 8 Aug 2016 16:06:08 +0200 +Subject: [PATCH] Remove Custodia server keys from LDAP + +The server-del plugin now removes the Custodia keys for encryption and +key signing from LDAP. + +https://fedorahosted.org/freeipa/ticket/6015 + +Reviewed-By: Martin Basti +--- + ipalib/constants.py | 1 + + ipaserver/plugins/server.py | 29 +++++++++++++++++++++++++++++ + 2 files changed, 30 insertions(+) + +diff --git a/ipalib/constants.py b/ipalib/constants.py +index 0574bb3aa457dd79a6d64f6b8a6b57161d32da92..9b351e260f15211330521453b3ffcd41433a04bb 100644 +--- a/ipalib/constants.py ++++ b/ipalib/constants.py +@@ -124,6 +124,7 @@ DEFAULT_CONFIG = ( + ('container_locations', DN(('cn', 'locations'), ('cn', 'etc'))), + ('container_ca', DN(('cn', 'cas'), ('cn', 'ca'))), + ('container_dnsservers', DN(('cn', 'servers'), ('cn', 'dns'))), ++ ('container_custodia', DN(('cn', 'custodia'), ('cn', 'ipa'), ('cn', 'etc'))), + + # Ports, hosts, and URIs: + ('xmlrpc_uri', 'http://localhost:8888/ipa/xml'), +diff --git a/ipaserver/plugins/server.py b/ipaserver/plugins/server.py +index b245dcf72a2f9f32f52ec9acf68d96c69d6169c5..d62c0232c5e33642e44a088dbfd9f10675d733f4 100644 +--- a/ipaserver/plugins/server.py ++++ b/ipaserver/plugins/server.py +@@ -609,6 +609,32 @@ class server_del(LDAPDelete): + message=_("Failed to remove server %(master)s from server " + "list: %(err)s") % dict(master=master, err=e))) + ++ def _remove_server_custodia_keys(self, ldap, master): ++ """ ++ Delete all Custodia encryption and signing keys ++ """ ++ conn = self.Backend.ldap2 ++ env = self.api.env ++ # search for memberPrincipal=*/fqdn@realm ++ member_filter = ldap.make_filter_from_attr( ++ 'memberPrincipal', "/{}@{}".format(master, env.realm), ++ exact=False, leading_wildcard=True, trailing_wildcard=False) ++ custodia_subtree = DN(env.container_custodia, env.basedn) ++ try: ++ entries = conn.get_entries(custodia_subtree, ++ ldap.SCOPE_SUBTREE, ++ filter=member_filter) ++ for entry in entries: ++ conn.delete_entry(entry) ++ except errors.NotFound: ++ pass ++ except Exception as e: ++ self.add_message( ++ messages.ServerRemovalWarning( ++ message=_( ++ "Failed to clean up Custodia keys for " ++ "%(master)s: %(err)s") % dict(master=master, err=e))) ++ + def _remove_server_host_services(self, ldap, master): + """ + delete server kerberos key and all its svc principals +@@ -682,6 +708,9 @@ class server_del(LDAPDelete): + # remove the references to master's ldap/http principals + self._remove_server_principal_references(pkey) + ++ # remove Custodia encryption and signing keys ++ self._remove_server_custodia_keys(ldap, pkey) ++ + # finally destroy all Kerberos principals + self._remove_server_host_services(ldap, pkey) + +-- +2.7.4 + diff --git a/SOURCES/0095-fix-missing-information-in-object-metadata.patch b/SOURCES/0095-fix-missing-information-in-object-metadata.patch deleted file mode 100644 index 5c60f17..0000000 --- a/SOURCES/0095-fix-missing-information-in-object-metadata.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 6ed7f2846c04c5b6a570787b8022797c279aaaee Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Tue, 25 Aug 2015 16:26:00 +0200 -Subject: [PATCH] fix missing information in object metadata - -Missing 'required' values in takes_params causes Web UI to treat required -fields as optional. - -Regression caused by ba0a1c6b33e2519a48754602413c8379fb1f0ff1 - -https://fedorahosted.org/freeipa/ticket/5258 - -Reviewed-By: Martin Basti ---- - ipalib/parameters.py | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - -diff --git a/ipalib/parameters.py b/ipalib/parameters.py -index 6cc6f8c9244abb9e895782f40cbdde63b2144d22..5ced5067ed2657962c35d7d675c4ddd822df6a36 100644 ---- a/ipalib/parameters.py -+++ b/ipalib/parameters.py -@@ -922,12 +922,23 @@ class Param(ReadOnly): - - def __json__(self): - json_dict = {} -- for key in self.__kw: -- json_dict[key] = json_serialize(self.__kw[key]) -+ for (a, k, d) in self.kwargs: -+ if k in (callable, DefaultFrom): -+ continue -+ elif isinstance(getattr(self, a), frozenset): -+ json_dict[a] = [k for k in getattr(self, a, [])] -+ else: -+ val = getattr(self, a, '') -+ if val is None: -+ # ignore 'not set' because lack of their presence is -+ # the information itself -+ continue -+ json_dict[a] = json_serialize(val) -+ - json_dict['class'] = self.__class__.__name__ - json_dict['name'] = self.name - json_dict['type'] = self.type.__name__ -- json_dict['flags'] = json_serialize([f for f in self.flags]) -+ - return json_dict - - --- -2.4.3 - diff --git a/SOURCES/0096-Handled-empty-hostname-in-server-del-command.patch b/SOURCES/0096-Handled-empty-hostname-in-server-del-command.patch new file mode 100644 index 0000000..0d24e57 --- /dev/null +++ b/SOURCES/0096-Handled-empty-hostname-in-server-del-command.patch @@ -0,0 +1,42 @@ +From eddc43e5973cb81d88fe2e88bab5eed72d7d3cff Mon Sep 17 00:00:00 2001 +From: Abhijeet Kasurde +Date: Tue, 23 Aug 2016 17:34:51 +0530 +Subject: [PATCH] Handled empty hostname in server-del command + +Fixes: https://fedorahosted.org/freeipa/ticket/6248 + +Signed-off-by: Abhijeet Kasurde +Reviewed-By: Martin Basti +Reviewed-By: Stanislav Laznicka +--- + ipaclient/plugins/server.py | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/ipaclient/plugins/server.py b/ipaclient/plugins/server.py +index 725a2ce95708529bd4e1de7fc364c2aba0d805de..5356dbbf58373eebeab1c8c59ff0e23b374a15f3 100644 +--- a/ipaclient/plugins/server.py ++++ b/ipaclient/plugins/server.py +@@ -3,7 +3,7 @@ + # + + from ipaclient.frontend import MethodOverride +-from ipalib import _ ++from ipalib import _, errors + from ipalib.plugable import Registry + + register = Registry() +@@ -12,6 +12,10 @@ register = Registry() + @register(override=True, no_fail=True) + class server_del(MethodOverride): + def interactive_prompt_callback(self, kw): ++ server_list = kw.get('cn') ++ if not server_list: ++ raise errors.RequirementError(name='cn') ++ + self.api.Backend.textui.print_plain( + _("Removing %(servers)s from replication topology, " +- "please wait...") % {'servers': ', '.join(kw['cn'])}) ++ "please wait...") % {'servers': ', '.join(server_list)}) +-- +2.7.4 + diff --git a/SOURCES/0096-webui-add-option-to-establish-bidirectional-trust.patch b/SOURCES/0096-webui-add-option-to-establish-bidirectional-trust.patch deleted file mode 100644 index 0532445..0000000 --- a/SOURCES/0096-webui-add-option-to-establish-bidirectional-trust.patch +++ /dev/null @@ -1,46 +0,0 @@ -From 85a5f70811b223edf86ce395b9ec781e788758d1 Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Tue, 25 Aug 2015 17:17:04 +0200 -Subject: [PATCH] webui: add option to establish bidirectional trust - -https://fedorahosted.org/freeipa/ticket/5259 - -Reviewed-By: Tomas Babej ---- - install/ui/src/freeipa/trust.js | 13 ++++++++++++- - 1 file changed, 12 insertions(+), 1 deletion(-) - -diff --git a/install/ui/src/freeipa/trust.js b/install/ui/src/freeipa/trust.js -index 51cfefb99fe10010385b528af209ad535e88b673..f26e2f21b7c8a97536a0a5cb23484da4173d6463 100644 ---- a/install/ui/src/freeipa/trust.js -+++ b/install/ui/src/freeipa/trust.js -@@ -172,6 +172,12 @@ return { - widget: 'realm.realm_server' - }, - { -+ $type: 'checkbox', -+ name: 'bidirectional', -+ metadata: '@mc-opt:trust_add:bidirectional', -+ widget: 'realm.bidirectional' -+ }, -+ { - name: 'realm_admin', - label: '@i18n:objects.trust.account', - widget: 'method.realm_admin' -@@ -224,7 +230,12 @@ return { - $type: 'details_section', - name: 'realm', - widgets: [ -- 'realm_server' -+ 'realm_server', -+ { -+ $type: 'checkbox', -+ name: 'bidirectional', -+ tooltip: '@mc-opt:trust_add:bidirectional:doc' -+ } - ] - }, - { --- -2.4.3 - diff --git a/SOURCES/0097-Removed-clear-text-passwords-from-KRA-install-log.patch b/SOURCES/0097-Removed-clear-text-passwords-from-KRA-install-log.patch deleted file mode 100644 index b5dda55..0000000 --- a/SOURCES/0097-Removed-clear-text-passwords-from-KRA-install-log.patch +++ /dev/null @@ -1,95 +0,0 @@ -From bb60e6d76d0dfa8106e195cc830b3ce685e84f77 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Sat, 22 Aug 2015 01:14:16 +0200 -Subject: [PATCH] Removed clear text passwords from KRA install log. - -The ipa-kra-install tool has been modified to use password files -instead of clear text passwords when invoking pki tool such that -the passwords are no longer visible in ipaserver-kra-install.log. - -https://fedorahosted.org/freeipa/ticket/5246 - -Reviewed-By: Alexander Bokovoy ---- - ipaplatform/base/paths.py | 2 ++ - ipaserver/install/krainstance.py | 16 ++++++++-------- - 2 files changed, 10 insertions(+), 8 deletions(-) - -diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py -index 0dd3c7fda3020264a1ace8f2d13557cfddf18c2d..5c8f25d6ef85fab2b9b30a660cd1c0360dbe9931 100644 ---- a/ipaplatform/base/paths.py -+++ b/ipaplatform/base/paths.py -@@ -343,6 +343,8 @@ class BasePathNamespace(object): - SLAPD_INSTANCE_SOCKET_TEMPLATE = "/var/run/slapd-%s.socket" - ALL_SLAPD_INSTANCE_SOCKETS = "/var/run/slapd-*.socket" - ADMIN_CERT_PATH = '/root/.dogtag/pki-tomcat/ca_admin.cert' -+ KRA_NSSDB_PASSWORD_FILE = "/root/.dogtag/pki-tomcat/kra/password.conf" -+ KRA_PKCS12_PASSWORD_FILE = "/root/.dogtag/pki-tomcat/kra/pkcs12_password.conf" - ENTROPY_AVAIL = '/proc/sys/kernel/random/entropy_avail' - LDIF2DB = '/usr/sbin/ldif2db' - DB2LDIF = '/usr/sbin/db2ldif' -diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py -index fa50c3dec897d63b9d3522d196054163f7b3369a..e5cdbf5e7714603041e3f0156e87311994175b18 100644 ---- a/ipaserver/install/krainstance.py -+++ b/ipaserver/install/krainstance.py -@@ -275,16 +275,16 @@ class KRAInstance(DogtagInstance): - # import CA certificate into temporary security database - args = ["/usr/bin/pki", - "-d", self.agent_db, -- "-c", self.admin_password, -+ "-C", paths.KRA_NSSDB_PASSWORD_FILE, - "client-cert-import", - "--pkcs12", paths.KRACERT_P12, -- "--pkcs12-password", self.admin_password] -+ "--pkcs12-password-file", paths.KRA_PKCS12_PASSWORD_FILE] - ipautil.run(args) - - # trust CA certificate - args = ["/usr/bin/pki", - "-d", self.agent_db, -- "-c", self.admin_password, -+ "-C", paths.KRA_NSSDB_PASSWORD_FILE, - "client-cert-mod", "Certificate Authority - %s" % api.env.realm, - "--trust", "CT,c,"] - ipautil.run(args) -@@ -292,16 +292,16 @@ class KRAInstance(DogtagInstance): - # import Dogtag admin certificate into temporary security database - args = ["/usr/bin/pki", - "-d", self.agent_db, -- "-c", self.admin_password, -+ "-C", paths.KRA_NSSDB_PASSWORD_FILE, - "client-cert-import", - "--pkcs12", paths.DOGTAG_ADMIN_P12, -- "--pkcs12-password", self.admin_password] -+ "--pkcs12-password-file", paths.KRA_PKCS12_PASSWORD_FILE] - ipautil.run(args) - - # as Dogtag admin, create ipakra user in KRA - args = ["/usr/bin/pki", - "-d", self.agent_db, -- "-c", self.admin_password, -+ "-C", paths.KRA_NSSDB_PASSWORD_FILE, - "-n", "ipa-ca-agent", - "kra-user-add", "ipakra", - "--fullName", "IPA KRA User"] -@@ -310,7 +310,7 @@ class KRAInstance(DogtagInstance): - # as Dogtag admin, add ipakra into KRA agents group - args = ["/usr/bin/pki", - "-d", self.agent_db, -- "-c", self.admin_password, -+ "-C", paths.KRA_NSSDB_PASSWORD_FILE, - "-n", "ipa-ca-agent", - "kra-user-membership-add", "ipakra", "Data Recovery Manager Agents"] - ipautil.run(args) -@@ -330,7 +330,7 @@ class KRAInstance(DogtagInstance): - # as Dogtag admin, upload and assign ipaCert to ipakra - args = ["/usr/bin/pki", - "-d", self.agent_db, -- "-c", self.admin_password, -+ "-C", paths.KRA_NSSDB_PASSWORD_FILE, - "-n", "ipa-ca-agent", - "kra-user-cert-add", "ipakra", - "--input", filename] --- -2.4.3 - diff --git a/SOURCES/0097-Secure-permissions-of-Custodia-server.keys.patch b/SOURCES/0097-Secure-permissions-of-Custodia-server.keys.patch new file mode 100644 index 0000000..6da375e --- /dev/null +++ b/SOURCES/0097-Secure-permissions-of-Custodia-server.keys.patch @@ -0,0 +1,69 @@ +From f7d3a49f3cf88b5950b11a19785794348d072c20 Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Mon, 8 Aug 2016 15:05:52 +0200 +Subject: [PATCH] Secure permissions of Custodia server.keys + +Custodia's server.keys file contain the private RSA keys for encrypting +and signing Custodia messages. The file was created with permission 644 +and is only secured by permission 700 of the directory +/etc/ipa/custodia. The installer and upgrader ensure that the file +has 600. + +https://bugzilla.redhat.com/show_bug.cgi?id=1353936 +https://fedorahosted.org/freeipa/ticket/6056 + +Reviewed-By: Martin Basti +--- + ipapython/secrets/kem.py | 5 ++++- + ipaserver/install/custodiainstance.py | 5 +++++ + 2 files changed, 9 insertions(+), 1 deletion(-) + +diff --git a/ipapython/secrets/kem.py b/ipapython/secrets/kem.py +index d45efe8cc4fb63ae9d8c0b2c920fd1f9e5331a9d..fb51e64a678bbdec45d690a5223bd61f84ef770e 100644 +--- a/ipapython/secrets/kem.py ++++ b/ipapython/secrets/kem.py +@@ -1,6 +1,7 @@ + # Copyright (C) 2015 IPA Project Contributors, see COPYING for license + + from __future__ import print_function ++import os + from ipaplatform.paths import paths + from six.moves.configparser import ConfigParser + from ipapython.dn import DN +@@ -143,7 +144,9 @@ class KEMLdap(iSecLdap): + def newServerKeys(path, keyid): + skey = JWK(generate='RSA', use='sig', kid=keyid) + ekey = JWK(generate='RSA', use='enc', kid=keyid) +- with open(path, 'w+') as f: ++ with open(path, 'w') as f: ++ os.fchmod(f.fileno(), 0o600) ++ os.fchown(f.fileno(), 0, 0) + f.write('[%s,%s]' % (skey.export(), ekey.export())) + return [skey.get_op_key('verify'), ekey.get_op_key('encrypt')] + +diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py +index fd30430bbf9c39e7153986999199474cfca60d09..785f86fc159f2d73184ea5bb3c0303cecde153df 100644 +--- a/ipaserver/install/custodiainstance.py ++++ b/ipaserver/install/custodiainstance.py +@@ -15,6 +15,7 @@ from jwcrypto.common import json_decode + import functools + import shutil + import os ++import stat + import tempfile + import pwd + +@@ -73,6 +74,10 @@ class CustodiaInstance(SimpleServiceInstance): + if not sysupgrade.get_upgrade_state("custodia", "installed"): + root_logger.info("Custodia service is being configured") + self.create_instance() ++ mode = os.stat(self.server_keys).st_mode ++ if stat.S_IMODE(mode) != 0o600: ++ root_logger.info("Secure server.keys mode") ++ os.chmod(self.server_keys, 0o600) + + def create_replica(self, master_host_name): + suffix = ipautil.realm_to_suffix(self.realm) +-- +2.7.4 + diff --git a/SOURCES/0098-Require-httpd-2.4.6-31-with-mod_proxy-Unix-socket-su.patch b/SOURCES/0098-Require-httpd-2.4.6-31-with-mod_proxy-Unix-socket-su.patch new file mode 100644 index 0000000..f8a52c6 --- /dev/null +++ b/SOURCES/0098-Require-httpd-2.4.6-31-with-mod_proxy-Unix-socket-su.patch @@ -0,0 +1,45 @@ +From eaa631227fa1a89d55c8dbaa236b7c8a1cdf7d9c Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Wed, 24 Aug 2016 12:28:47 +0200 +Subject: [PATCH] Require httpd 2.4.6-31 with mod_proxy Unix socket support + +httpd 2.4.6-6 does not support mod_proxy ProxyPass for Unix sockets. The +feature is provided by 2.4.7 upstream was backported to 2.4.6-31 +(bz1168081). It's required to proxy Custodia. + +https://bugzilla.redhat.com/show_bug.cgi?id=1168081 +https://httpd.apache.org/docs/trunk/mod/mod_proxy.html#proxypass + +https://fedorahosted.org/freeipa/ticket/6251 + +Signed-off-by: Christian Heimes +Reviewed-By: Martin Basti +--- + freeipa.spec.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/freeipa.spec.in b/freeipa.spec.in +index 29b63c9300b73d82aea88dbcf50f2f6ab5f9e9bd..08343d9f2049680185ddd32428b040824d882d66 100644 +--- a/freeipa.spec.in ++++ b/freeipa.spec.in +@@ -141,7 +141,7 @@ Requires(post): krb5-server >= %{krb5_base_version}, krb5-server < %{krb5_base_v + Requires: krb5-pkinit-openssl + Requires: cyrus-sasl-gssapi%{?_isa} + Requires: ntp +-Requires: httpd >= 2.4.6-6 ++Requires: httpd >= 2.4.6-31 + Requires: mod_wsgi + Requires: mod_auth_gssapi >= 1.4.0 + Requires: mod_nss >= 1.0.8-26 +@@ -231,7 +231,7 @@ Summary: Common files used by IPA server + Group: System Environment/Base + BuildArch: noarch + Requires: %{name}-client-common = %{version}-%{release} +-Requires: httpd >= 2.4.6-6 ++Requires: httpd >= 2.4.6-31 + Requires: systemd-units >= 38 + Requires: custodia + +-- +2.7.4 + diff --git a/SOURCES/0098-certprofile-prevent-rename-modrdn.patch b/SOURCES/0098-certprofile-prevent-rename-modrdn.patch deleted file mode 100644 index 5fab0b7..0000000 --- a/SOURCES/0098-certprofile-prevent-rename-modrdn.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 80767a47c9eda6c82f172b87a6a901be9ebf0c9a Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Mon, 24 Aug 2015 20:25:10 -0400 -Subject: [PATCH] certprofile: prevent rename (modrdn) - -Fixes: https://fedorahosted.org/freeipa/ticket/5247 -Reviewed-By: Alexander Bokovoy ---- - ipalib/plugins/certprofile.py | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/ipalib/plugins/certprofile.py b/ipalib/plugins/certprofile.py -index 007cc543406b7e5705fd7474f3685cd6a9ce6aca..a0ffa38608400860994c771e4eba81304ead27be 100644 ---- a/ipalib/plugins/certprofile.py -+++ b/ipalib/plugins/certprofile.py -@@ -323,8 +323,9 @@ class certprofile_mod(LDAPUpdate): - def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): - ca_enabled_check() - # Once a profile id is set it cannot be changed -- if 'cn' in entry_attrs: -- raise errors.ACIError(info=_('cn is immutable')) -+ if 'rename' in options or 'cn' in entry_attrs: -+ raise errors.ProtectedEntryError(label='certprofile', key=keys[0], -+ reason=_('Certificate profiles cannot be renamed')) - if 'file' in options: - with self.api.Backend.ra_certprofile as profile_api: - profile_api.disable_profile(keys[0]) --- -2.4.3 - diff --git a/SOURCES/0099-Fix-ipa-server-install-in-pure-IPv6-environment.patch b/SOURCES/0099-Fix-ipa-server-install-in-pure-IPv6-environment.patch new file mode 100644 index 0000000..1a66f1f --- /dev/null +++ b/SOURCES/0099-Fix-ipa-server-install-in-pure-IPv6-environment.patch @@ -0,0 +1,34 @@ +From 2dab553e06ce7b01a285c9d80866a6efa80d254d Mon Sep 17 00:00:00 2001 +From: Tomas Krizek +Date: Fri, 19 Aug 2016 12:16:54 +0200 +Subject: [PATCH] Fix ipa-server-install in pure IPv6 environment + +Installation in pure IPv6 environment failed because pki-tomcat tried to use +IPv4 loopback. Configuring tomcat to use IPv6 loopback instead of IPv4 fixes +this issue. + +https://fedorahosted.org/freeipa/ticket/4291 + +Reviewed-By: Martin Basti +--- + ipaserver/install/cainstance.py | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py +index 070498fe8a394802ea55f848a268e2b6563ec472..e94fec5f6fd898b66dc12407be6e3f671ac3f4de 100644 +--- a/ipaserver/install/cainstance.py ++++ b/ipaserver/install/cainstance.py +@@ -577,6 +577,10 @@ class CAInstance(DogtagInstance): + config.set("CA", "pki_external_ca_cert_chain_path", cert_chain_file.name) + config.set("CA", "pki_external_step_two", "True") + ++ # PKI IPv6 Configuration ++ config.add_section("Tomcat") ++ config.set("Tomcat", "pki_ajp_host", "::1") ++ + # Generate configuration file + with open(cfg_file, "wb") as f: + config.write(f) +-- +2.7.4 + diff --git a/SOURCES/0099-vault-Limit-size-of-data-stored-in-vault.patch b/SOURCES/0099-vault-Limit-size-of-data-stored-in-vault.patch deleted file mode 100644 index 3606295..0000000 --- a/SOURCES/0099-vault-Limit-size-of-data-stored-in-vault.patch +++ /dev/null @@ -1,57 +0,0 @@ -From a9367de918ae4f28159275b32f1d6d4716de0122 Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Wed, 26 Aug 2015 14:11:21 +0200 -Subject: [PATCH] vault: Limit size of data stored in vault - -https://fedorahosted.org/freeipa/ticket/5231 - -Reviewed-By: Petr Vobornik ---- - ipalib/plugins/vault.py | 21 ++++++++++++++++++++- - 1 file changed, 20 insertions(+), 1 deletion(-) - -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index 667524465031b6d027afbabeea48871e29c0e1e4..e369eeee20f5652942681f7c3e268e6173005452 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -237,6 +237,7 @@ def validated_read(argname, filename, mode='r', encoding=None): - - register = Registry() - -+MAX_VAULT_DATA_SIZE = 2**20 # = 1 MB - - vault_options = ( - Str( -@@ -1233,10 +1234,28 @@ class vault_archive(PKQuery, Local): - raise errors.MutuallyExclusiveError( - reason=_('Input data specified multiple times')) - -+ elif data: -+ if len(data) > MAX_VAULT_DATA_SIZE: -+ raise errors.ValidationError(name="data", error=_( -+ "Size of data exceeds the limit. Current vault data size " -+ "limit is %(limit)d B") -+ % {'limit': MAX_VAULT_DATA_SIZE}) -+ - elif input_file: -+ try: -+ stat = os.stat(input_file) -+ except OSError as exc: -+ raise errors.ValidationError(name="in", error=_( -+ "Cannot read file '%(filename)s': %(exc)s") -+ % {'filename': input_file, 'exc': exc[1]}) -+ if stat.st_size > MAX_VAULT_DATA_SIZE: -+ raise errors.ValidationError(name="in", error=_( -+ "Size of data exceeds the limit. Current vault data size " -+ "limit is %(limit)d B") -+ % {'limit': MAX_VAULT_DATA_SIZE}) - data = validated_read('in', input_file, mode='rb') - -- elif not data: -+ else: - data = '' - - if self.api.env.in_server: --- -2.4.3 - diff --git a/SOURCES/0100-ipactl-Do-not-start-stop-restart-single-service-mult.patch b/SOURCES/0100-ipactl-Do-not-start-stop-restart-single-service-mult.patch deleted file mode 100644 index a6dde81..0000000 --- a/SOURCES/0100-ipactl-Do-not-start-stop-restart-single-service-mult.patch +++ /dev/null @@ -1,89 +0,0 @@ -From 92224c6e83ca7ad196478b0057b523b6f2b7d150 Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Wed, 26 Aug 2015 15:10:16 +0200 -Subject: [PATCH] ipactl: Do not start/stop/restart single service multiple - times - -In case multiple services are provided by single system daemon -it is not needed to start/stop/restart it mutiple time. - -https://fedorahosted.org/freeipa/ticket/5248 - -Reviewed-By: Petr Vobornik ---- - install/tools/ipactl | 17 ++++++++++++++++- - 1 file changed, 16 insertions(+), 1 deletion(-) - -diff --git a/install/tools/ipactl b/install/tools/ipactl -index 52dfe67ddb65939bc1f431ccc67d9f03114c0454..acad7ff3771561d5dce530317b65aaf117f153a1 100755 ---- a/install/tools/ipactl -+++ b/install/tools/ipactl -@@ -45,6 +45,16 @@ def check_IPA_configuration(): - raise IpactlError("IPA is not configured " + - "(see man pages of ipa-server-install for help)", 6) - -+def deduplicate(lst): -+ new_lst = [] -+ s = set(lst) -+ for i in lst: -+ if i in s: -+ s.remove(i) -+ new_lst.append(i) -+ -+ return new_lst -+ - def is_dirsrv_debugging_enabled(): - """ - Check the 389-ds instance to see if debugging is enabled. -@@ -283,6 +293,7 @@ def ipa_start(options): - # no service to start - return - -+ svc_list = deduplicate(svc_list) - for svc in svc_list: - svchandle = services.service(svc) - try: -@@ -321,6 +332,7 @@ def ipa_stop(options): - finally: - raise IpactlError() - -+ svc_list = deduplicate(svc_list) - for svc in reversed(svc_list): - svchandle = services.service(svc) - try: -@@ -398,6 +410,7 @@ def ipa_restart(options): - - if len(old_svc_list) != 0: - # we need to definitely stop some services -+ old_svc_list = deduplicate(old_svc_list) - for svc in reversed(old_svc_list): - svchandle = services.service(svc) - try: -@@ -422,7 +435,7 @@ def ipa_restart(options): - - if len(svc_list) != 0: - # there are services to restart -- -+ svc_list = deduplicate(svc_list) - for svc in svc_list: - svchandle = services.service(svc) - try: -@@ -444,6 +457,7 @@ def ipa_restart(options): - - if len(new_svc_list) != 0: - # we still need to start some services -+ new_svc_list = deduplicate(new_svc_list) - for svc in new_svc_list: - svchandle = services.service(svc) - try: -@@ -494,6 +508,7 @@ def ipa_status(options): - if len(svc_list) == 0: - return - -+ svc_list = deduplicate(svc_list) - for svc in svc_list: - svchandle = services.service(svc) - try: --- -2.4.3 - diff --git a/SOURCES/0100-support-multiple-uid-values-in-schema-compatibility-.patch b/SOURCES/0100-support-multiple-uid-values-in-schema-compatibility-.patch new file mode 100644 index 0000000..58433e2 --- /dev/null +++ b/SOURCES/0100-support-multiple-uid-values-in-schema-compatibility-.patch @@ -0,0 +1,53 @@ +From 485e70f9ca0e7352b17839b2375092f7a886bc81 Mon Sep 17 00:00:00 2001 +From: Alexander Bokovoy +Date: Thu, 4 Aug 2016 09:58:50 +0300 +Subject: [PATCH] support multiple uid values in schema compatibility tree + +https://fedorahosted.org/freeipa/ticket/6138 + +Reviewed-By: Thierry Bordaz +--- + freeipa.spec.in | 4 +++- + install/updates/10-schema_compat.update | 4 ++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/freeipa.spec.in b/freeipa.spec.in +index 08343d9f2049680185ddd32428b040824d882d66..7456a9ea77ec289312eb11c05709018b3d6d0c90 100644 +--- a/freeipa.spec.in ++++ b/freeipa.spec.in +@@ -12,9 +12,11 @@ + %if 0%{?rhel} + %global samba_version 4.0.5-1 + %global selinux_policy_version 3.12.1-153 ++%global slapi_nis_version 0.56.0-4 + %else + %global samba_version 2:4.0.5-1 + %global selinux_policy_version 3.13.1-158.4 ++%global slapi_nis_version 0.56.1 + %endif + + %define krb5_base_version %(LC_ALL=C rpm -q --qf '%%{VERSION}' krb5-devel | grep -Eo '^[^.]+\.[^.]+') +@@ -156,7 +158,7 @@ Requires(pre): systemd-units + Requires(post): systemd-units + Requires: selinux-policy >= %{selinux_policy_version} + Requires(post): selinux-policy-base >= %{selinux_policy_version} +-Requires: slapi-nis >= 0.56.0 ++Requires: slapi-nis >= %{slapi_nis_version} + Requires: pki-ca >= 10.3.4 + Requires: pki-kra >= 10.3.4 + Requires(preun): python systemd-units +diff --git a/install/updates/10-schema_compat.update b/install/updates/10-schema_compat.update +index e4c257d323644a93757e01027d3b8ed62c2ca98c..fbe8703407aacd75baf160630c20835a1b4ddc65 100644 +--- a/install/updates/10-schema_compat.update ++++ b/install/updates/10-schema_compat.update +@@ -87,3 +87,7 @@ add:schema-compat-entry-attribute: %ifeq("ipauniqueid","%{ipauniqueid}","objectc + add:schema-compat-entry-attribute: %ifeq("ipauniqueid","%{ipauniqueid}","ipaanchoruuid=:IPA:$DOMAIN:%{ipauniqueid}","") + add:schema-compat-entry-attribute: ipaanchoruuid=%{ipaanchoruuid} + add:schema-compat-entry-attribute: %ifeq("ipaanchoruuid","%{ipaanchoruuid}","objectclass=ipaOverrideTarget","") ++ ++dn: cn=users,cn=Schema Compatibility,cn=plugins,cn=config ++add:schema-compat-entry-attribute: uid=%{uid} ++replace:schema-compat-entry-rdn: uid=%{uid}::uid=%first("%{uid}") +-- +2.7.4 + diff --git a/SOURCES/0101-cert-renewal-Include-KRA-users-in-Dogtag-LDAP-update.patch b/SOURCES/0101-cert-renewal-Include-KRA-users-in-Dogtag-LDAP-update.patch deleted file mode 100644 index fb706b1..0000000 --- a/SOURCES/0101-cert-renewal-Include-KRA-users-in-Dogtag-LDAP-update.patch +++ /dev/null @@ -1,46 +0,0 @@ -From a4ea0af1fb74ac9bdf9afe1bee62cddf65f5160e Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Thu, 27 Aug 2015 07:23:39 +0200 -Subject: [PATCH] cert renewal: Include KRA users in Dogtag LDAP update - -https://fedorahosted.org/freeipa/ticket/5253 - -Reviewed-By: Alexander Bokovoy ---- - ipaserver/install/cainstance.py | 13 +++++++++---- - 1 file changed, 9 insertions(+), 4 deletions(-) - -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index 5fd3017e16e0d7ed4b4f8eead0e59266fdaff097..ecd9300036353426097d929918be974cbbb5c69d 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -1575,7 +1575,7 @@ def update_people_entry(dercert): - - Returns True or False - """ -- base_dn = DN(('ou','People'), ('o','ipaca')) -+ base_dn = DN(('o', 'ipaca')) - serial_number = x509.get_serial_number(dercert, datatype=x509.DER) - subject = x509.get_subject(dercert, datatype=x509.DER) - issuer = x509.get_issuer(dercert, datatype=x509.DER) -@@ -1591,9 +1591,14 @@ def update_people_entry(dercert): - conn = ldap2.ldap2(api, ldap_uri=dogtag_uri) - conn.connect(autobind=True) - -- db_filter = conn.make_filter( -- {'description': ';%s;%s' % (issuer, subject)}, -- exact=False, trailing_wildcard=False) -+ db_filter = conn.combine_filters( -+ [ -+ conn.make_filter({'objectClass': 'inetOrgPerson'}), -+ conn.make_filter( -+ {'description': ';%s;%s' % (issuer, subject)}, -+ exact=False, trailing_wildcard=False), -+ ], -+ conn.MATCH_ALL) - try: - entries = conn.get_entries(base_dn, conn.SCOPE_SUBTREE, db_filter) - except errors.NotFound: --- -2.5.1 - diff --git a/SOURCES/0101-custodia-include-known-CA-certs-in-the-PKCS-12-file-.patch b/SOURCES/0101-custodia-include-known-CA-certs-in-the-PKCS-12-file-.patch new file mode 100644 index 0000000..256e70a --- /dev/null +++ b/SOURCES/0101-custodia-include-known-CA-certs-in-the-PKCS-12-file-.patch @@ -0,0 +1,43 @@ +From 70ec9193404463ad62ee6fe14a033425906e6b13 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Tue, 23 Aug 2016 10:39:08 +0200 +Subject: [PATCH] custodia: include known CA certs in the PKCS#12 file for + Dogtag + +This fixes CA replica install in a topology upgraded from CA-less to +CA-full. + +https://fedorahosted.org/freeipa/ticket/6207 + +Reviewed-By: Martin Basti +--- + ipaserver/install/custodiainstance.py | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py +index 785f86fc159f2d73184ea5bb3c0303cecde153df..18bd51426cde09af6a34855a49db386a72cc6b9c 100644 +--- a/ipaserver/install/custodiainstance.py ++++ b/ipaserver/install/custodiainstance.py +@@ -2,6 +2,7 @@ + + from ipapython.secrets.kem import IPAKEMKeys + from ipapython.secrets.client import CustodiaClient ++from ipaserver.install.certs import CertDB + from ipaplatform.paths import paths + from ipaplatform.constants import constants + from ipaserver.install.service import SimpleServiceInstance +@@ -154,6 +155,11 @@ class CustodiaInstance(SimpleServiceInstance): + '-i', pk12file, + '-w', pk12pwfile]) + ++ # Add CA certificates ++ tmpdb = CertDB(self.realm, nssdir=tmpnssdir) ++ self.suffix = ipautil.realm_to_suffix(self.realm) ++ self.import_ca_certs(tmpdb, True) ++ + # Now that we gathered all certs, re-export + ipautil.run([paths.PKCS12EXPORT, + '-d', tmpnssdir, +-- +2.7.4 + diff --git a/SOURCES/0102-cert-renewal-Automatically-update-KRA-agent-PEM-file.patch b/SOURCES/0102-cert-renewal-Automatically-update-KRA-agent-PEM-file.patch deleted file mode 100644 index 0350832..0000000 --- a/SOURCES/0102-cert-renewal-Automatically-update-KRA-agent-PEM-file.patch +++ /dev/null @@ -1,45 +0,0 @@ -From f0e3715b39ea2682f4ef689f5d5864e16117fb00 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Thu, 27 Aug 2015 07:37:24 +0200 -Subject: [PATCH] cert renewal: Automatically update KRA agent PEM file - -https://fedorahosted.org/freeipa/ticket/5253 - -Reviewed-By: Alexander Bokovoy ---- - install/restart_scripts/renew_ra_cert | 12 +++++++++++- - 1 file changed, 11 insertions(+), 1 deletion(-) - -diff --git a/install/restart_scripts/renew_ra_cert b/install/restart_scripts/renew_ra_cert -index 1f8fcae6fa09033f7a5c6448e0bbef14a5f76844..93ffd4035723831f3955bcdf5a2082fd1ec5e22a 100644 ---- a/install/restart_scripts/renew_ra_cert -+++ b/install/restart_scripts/renew_ra_cert -@@ -29,7 +29,7 @@ import traceback - - from ipapython import ipautil - from ipalib import api --from ipaserver.install import certs, cainstance -+from ipaserver.install import certs, cainstance, krainstance - from ipaplatform import services - from ipaplatform.paths import paths - -@@ -60,6 +60,16 @@ def _main(): - - # Load it into dogtag - cainstance.update_people_entry(dercert) -+ -+ kra = krainstance.KRAInstance(api.env.realm) -+ if kra.is_installed(): -+ # export ipaCert with private key for client authentication -+ args = ["/usr/bin/pki", -+ "-d", paths.HTTPD_ALIAS_DIR, -+ "-C", paths.ALIAS_PWDFILE_TXT, -+ "client-cert-show", "ipaCert", -+ "--client-cert", paths.KRA_AGENT_PEM] -+ ipautil.run(args) - finally: - shutil.rmtree(tmpdir) - --- -2.5.1 - diff --git a/SOURCES/0102-otptoken-permission-Convert-custom-type-parameters-o.patch b/SOURCES/0102-otptoken-permission-Convert-custom-type-parameters-o.patch new file mode 100644 index 0000000..017a0ef --- /dev/null +++ b/SOURCES/0102-otptoken-permission-Convert-custom-type-parameters-o.patch @@ -0,0 +1,46 @@ +From 321bd7bf56109c546a92298d54bcaccfe1289800 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Thu, 25 Aug 2016 11:53:39 +0200 +Subject: [PATCH] otptoken, permission: Convert custom type parameters on + server + +Force client to send the value of ipatokenotpkey and ipapermlocation as +entered by user. + +https://fedorahosted.org/freeipa/ticket/6247 + +Reviewed-By: Jan Cholasta +--- + ipaserver/plugins/otptoken.py | 2 ++ + ipaserver/plugins/permission.py | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/ipaserver/plugins/otptoken.py b/ipaserver/plugins/otptoken.py +index 39012e2f9106c33c520e19f14331fc440333015a..0b4250043618b4f434d2f8b337b88ee396c312ce 100644 +--- a/ipaserver/plugins/otptoken.py ++++ b/ipaserver/plugins/otptoken.py +@@ -214,6 +214,8 @@ class otptoken(LDAPObject): + doc=_('Token secret (Base32; default: random)'), + default_from=lambda: os.urandom(KEY_LENGTH), + autofill=True, ++ # force server-side conversion ++ normalizer=lambda x: x, + flags=('no_display', 'no_update', 'no_search'), + ), + StrEnum('ipatokenotpalgorithm?', +diff --git a/ipaserver/plugins/permission.py b/ipaserver/plugins/permission.py +index 830773ae7a09f0197da702e4ec31b0b58f1214dd..0c040ce874534dc4716e700493e547df5b97ea99 100644 +--- a/ipaserver/plugins/permission.py ++++ b/ipaserver/plugins/permission.py +@@ -283,6 +283,8 @@ class permission(baseldap.LDAPObject): + cli_name='subtree', + label=_('Subtree'), + doc=_('Subtree to apply permissions to'), ++ # force server-side conversion ++ normalizer=lambda x: x, + flags={'ask_create'}, + ), + Str( +-- +2.7.4 + diff --git a/SOURCES/0103-DNSSEC-remove-DNSSEC-is-experimental-warnings.patch b/SOURCES/0103-DNSSEC-remove-DNSSEC-is-experimental-warnings.patch deleted file mode 100644 index eeb2b27..0000000 --- a/SOURCES/0103-DNSSEC-remove-DNSSEC-is-experimental-warnings.patch +++ /dev/null @@ -1,72 +0,0 @@ -From 36d0ae5682bd4e71ba3c27900f4699c07aa27f68 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Mon, 31 Aug 2015 13:51:02 +0200 -Subject: [PATCH] DNSSEC: remove "DNSSEC is experimental" warnings - -https://fedorahosted.org/freeipa/ticket/5265 - -Reviewed-By: Martin Babinsky ---- - ipalib/plugins/dns.py | 18 ------------------ - ipaserver/install/dns.py | 2 -- - 2 files changed, 20 deletions(-) - -diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py -index 512a653c3cc8ee641debec0d20f58e17eff08266..a3d562edb186682a872073e6c83a416b6a4cbc09 100644 ---- a/ipalib/plugins/dns.py -+++ b/ipalib/plugins/dns.py -@@ -2624,22 +2624,6 @@ class dnszone(DNSZoneBase): - messages.add_message(options.get('version', VERSION_WITHOUT_CAPABILITIES), - result, messages.ForwardersWarning()) - -- def _warning_dnssec_experimental(self, result, *keys, **options): -- # add warning when user use option --dnssec -- if 'idnssecinlinesigning' in options: -- if options['idnssecinlinesigning'] is True: -- messages.add_message(options['version'], result, -- messages.DNSSECWarning( -- additional_info=_("Visit 'http://www.freeipa.org/page/Releases/4.1.0#DNSSEC_Support'.") -- )) -- else: -- messages.add_message(options['version'], result, -- messages.DNSSECWarning( -- additional_info=_("If you encounter any problems please " -- "report them and restart 'named' service on affected IPA " -- "server.") -- )) -- - def _warning_name_server_option(self, result, context, **options): - if getattr(context, 'show_warning_nameserver_option', False): - messages.add_message( -@@ -2735,7 +2719,6 @@ class dnszone_add(DNSZoneBase_add): - result = super(dnszone_add, self).execute(*keys, **options) - self._warning_deprecated_option(result, **options) - self.obj._warning_forwarding(result, **options) -- self.obj._warning_dnssec_experimental(result, *keys, **options) - self.obj._warning_name_server_option(result, context, **options) - self.obj._warning_fw_zone_is_not_effective(result, *keys, **options) - return result -@@ -2826,7 +2809,6 @@ class dnszone_mod(DNSZoneBase_mod): - def execute(self, *keys, **options): - result = super(dnszone_mod, self).execute(*keys, **options) - self.obj._warning_forwarding(result, **options) -- self.obj._warning_dnssec_experimental(result, *keys, **options) - self.obj._warning_name_server_option(result, context, **options) - return result - -diff --git a/ipaserver/install/dns.py b/ipaserver/install/dns.py -index 9430d189978b0984b0b71d7d754516a4135053fb..538e99fbe01a34cee627f1cebd938be19777c134 100644 ---- a/ipaserver/install/dns.py -+++ b/ipaserver/install/dns.py -@@ -126,8 +126,6 @@ def install_check(standalone, replica, options, hostname): - print "NOTE: DNSSEC zone signing is not enabled by default" - print "" - if options.dnssec_master: -- print "DNSSEC support is experimental!" -- print "" - print "Plan carefully, replacing DNSSEC key master is not recommended" - print "" - print "" --- -2.5.1 - diff --git a/SOURCES/0103-Raise-DuplicatedEnrty-error-when-user-exists-in-dele.patch b/SOURCES/0103-Raise-DuplicatedEnrty-error-when-user-exists-in-dele.patch new file mode 100644 index 0000000..716b615 --- /dev/null +++ b/SOURCES/0103-Raise-DuplicatedEnrty-error-when-user-exists-in-dele.patch @@ -0,0 +1,61 @@ +From ef2480e2a9a10665208a6547fe3d3cb1d4047763 Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Fri, 19 Aug 2016 10:39:40 +0200 +Subject: [PATCH] Raise DuplicatedEnrty error when user exists in + delete_container + +We do not have right to write to users delete_container. In case that +user already exists in that container and we tried to add entry, we +receive ACIError. This must be checked and DuplicationEntry error must +be raised before. + +https://fedorahosted.org/freeipa/ticket/6199 + +Reviewed-By: Jan Cholasta +--- + ipaserver/plugins/user.py | 15 +++++++++++++-- + 1 file changed, 13 insertions(+), 2 deletions(-) + +diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py +index 935ea892cde9e2cb5b21f4714fd93e73c3fa53d5..d690f01ab4d155f6b403790a7215e1777f383604 100644 +--- a/ipaserver/plugins/user.py ++++ b/ipaserver/plugins/user.py +@@ -381,6 +381,10 @@ class user(baseuser): + ), + ) + ++ def get_delete_dn(self, *keys, **options): ++ active_dn = self.get_dn(*keys, **options) ++ return DN(active_dn[0], self.delete_container_dn, api.env.basedn) ++ + def get_either_dn(self, *keys, **options): + ''' + Returns the DN of a user +@@ -397,7 +401,7 @@ class user(baseuser): + dn = active_dn + except errors.NotFound: + # Check that this value is a Delete user +- delete_dn = DN(active_dn[0], self.delete_container_dn, api.env.basedn) ++ delete_dn = self.get_delete_dn(*keys, **options) + try: + ldap.get_entry(delete_dn, ['dn']) + +@@ -441,7 +445,14 @@ class user_add(baseuser_add): + ) + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): +- dn = self.obj.get_either_dn(*keys, **options) ++ delete_dn = self.obj.get_delete_dn(*keys, **options) ++ try: ++ ldap.get_entry(delete_dn, ['']) ++ except errors.NotFound: ++ pass ++ else: ++ raise self.obj.handle_duplicate_entry(*keys) ++ + if not options.get('noprivate', False): + try: + # The Managed Entries plugin will allow a user to be created +-- +2.7.4 + diff --git a/SOURCES/0104-Backup-back-up-the-hosts-file.patch b/SOURCES/0104-Backup-back-up-the-hosts-file.patch deleted file mode 100644 index e581e41..0000000 --- a/SOURCES/0104-Backup-back-up-the-hosts-file.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 89b5a01486f8a5200323c753f6ac278d089ba05e Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Tue, 1 Sep 2015 16:24:44 +0200 -Subject: [PATCH] Backup: back up the hosts file - -https://fedorahosted.org/freeipa/ticket/5275 - -Reviewed-By: Martin Babinsky ---- - ipaserver/install/ipa_backup.py | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py -index 0ba44b280dfb7c9d9cbbe2470392c3c98ef35bcc..8df1005a222220a0ece95a3691766ed3cd00a0d9 100644 ---- a/ipaserver/install/ipa_backup.py -+++ b/ipaserver/install/ipa_backup.py -@@ -178,6 +178,7 @@ class Backup(admintool.AdminTool): - paths.DNSSEC_SOFTHSM_PIN_SO, - paths.IPA_ODS_EXPORTER_KEYTAB, - paths.IPA_DNSKEYSYNCD_KEYTAB, -+ paths.HOSTS, - ) + tuple( - os.path.join(base, file) - for base in (paths.NSS_DB_DIR, paths.IPA_NSSDB_DIR) --- -2.5.1 - diff --git a/SOURCES/0104-cert-add-missing-param-values-to-cert-find-output.patch b/SOURCES/0104-cert-add-missing-param-values-to-cert-find-output.patch new file mode 100644 index 0000000..f37807b --- /dev/null +++ b/SOURCES/0104-cert-add-missing-param-values-to-cert-find-output.patch @@ -0,0 +1,32 @@ +From 7bad2b168b2abbfcd0d81afe7f52342648b75bc4 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Mon, 29 Aug 2016 17:49:56 +0200 +Subject: [PATCH] cert: add missing param values to cert-find output + +Add back `serial_number_hex` and `revoked` param values to cert-find output +accidentally removed in commit c718ef058847bb39e78236e8af0ad69ac961bbcf. + +https://fedorahosted.org/freeipa/ticket/6269 + +Reviewed-By: Alexander Bokovoy +--- + ipaserver/plugins/cert.py | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py +index 6dd9f6ffcdcd9d051d50d912996fea2104d71dff..a1166a0d0e5b09586832550c055fc6714c3efe26 100644 +--- a/ipaserver/plugins/cert.py ++++ b/ipaserver/plugins/cert.py +@@ -1083,7 +1083,8 @@ class cert_find(Search, CertMethod): + obj = ra_obj + obj['issuer'] = issuer + obj['subject'] = DN(ra_obj['subject']) +- del obj['serial_number_hex'] ++ obj['revoked'] = ( ++ ra_obj['status'] in (u'REVOKED', u'REVOKED_EXPIRED')) + + if all: + ra_obj = ra.get_certificate(str(serial_number)) +-- +2.7.4 + diff --git a/SOURCES/0105-certprofile-remove-rename-option.patch b/SOURCES/0105-certprofile-remove-rename-option.patch deleted file mode 100644 index a3d7d58..0000000 --- a/SOURCES/0105-certprofile-remove-rename-option.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 4b6bd162df3eed18c124527467b9beea930169db Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Tue, 1 Sep 2015 21:04:34 -0400 -Subject: [PATCH] certprofile: remove 'rename' option - -The initial fix of ticket 5247 rejected renames, but left the option -behind for API compatibility. Remove the option now, according to -the consensus that because it never worked, it is fine to remove it. - -Fixes: https://fedorahosted.org/freeipa/ticket/5247 -Reviewed-By: Petr Vobornik ---- - API.txt | 3 +-- - VERSION | 4 ++-- - ipalib/plugins/certprofile.py | 3 +-- - 3 files changed, 4 insertions(+), 6 deletions(-) - -diff --git a/API.txt b/API.txt -index 871ddb5b7ee8b9bbae219eac673d52ad7229edc7..5253e1585e000f39d6e185a94548037dfe54d4d8 100644 ---- a/API.txt -+++ b/API.txt -@@ -731,7 +731,7 @@ output: Entry('result', , Gettext('A dictionary representing an LDA - output: Output('summary', (, ), None) - output: PrimaryKey('value', None, None) - command: certprofile_mod --args: 1,11,3 -+args: 1,10,3 - arg: Str('cn', attribute=True, cli_name='id', multivalue=False, primary_key=True, query=True, required=True) - option: Str('addattr*', cli_name='addattr', exclude='webui') - option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') -@@ -740,7 +740,6 @@ option: Str('description', attribute=True, autofill=False, cli_name='desc', mult - option: File('file?', cli_name='file') - option: Bool('ipacertprofilestoreissued', attribute=True, autofill=False, cli_name='store', default=True, multivalue=False, required=False) - option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') --option: Str('rename', cli_name='rename', multivalue=False, primary_key=True, required=False) - option: Flag('rights', autofill=True, default=False) - option: Str('setattr*', cli_name='setattr', exclude='webui') - option: Str('version?', exclude='webui') -diff --git a/VERSION b/VERSION -index c102e020bbbec921b0f4a2141d1c768ac093acf8..da721fdd548023dc3dcd9b4f6a8ba72922a3c6f2 100644 ---- a/VERSION -+++ b/VERSION -@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 - # # - ######################################################## - IPA_API_VERSION_MAJOR=2 --IPA_API_VERSION_MINOR=154 --# Last change: pvoborni - change default vault type to 'symmetric' -+IPA_API_VERSION_MINOR=155 -+# Last change: ftweedal - remove certprofile 'rename' option -diff --git a/ipalib/plugins/certprofile.py b/ipalib/plugins/certprofile.py -index a0ffa38608400860994c771e4eba81304ead27be..bd835f4c241ba1936555869d481262a8093bbb42 100644 ---- a/ipalib/plugins/certprofile.py -+++ b/ipalib/plugins/certprofile.py -@@ -115,7 +115,6 @@ class certprofile(LDAPObject): - search_attributes = [ - 'cn', 'description', 'ipacertprofilestoreissued' - ] -- rdn_is_primary_key = True - label = _('Certificate Profiles') - label_singular = _('Certificate Profile') - -@@ -323,7 +322,7 @@ class certprofile_mod(LDAPUpdate): - def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): - ca_enabled_check() - # Once a profile id is set it cannot be changed -- if 'rename' in options or 'cn' in entry_attrs: -+ if 'cn' in entry_attrs: - raise errors.ProtectedEntryError(label='certprofile', key=keys[0], - reason=_('Certificate profiles cannot be renamed')) - if 'file' in options: --- -2.5.1 - diff --git a/SOURCES/0105-rpcserver-assume-version-1-for-unversioned-command-c.patch b/SOURCES/0105-rpcserver-assume-version-1-for-unversioned-command-c.patch new file mode 100644 index 0000000..acafde6 --- /dev/null +++ b/SOURCES/0105-rpcserver-assume-version-1-for-unversioned-command-c.patch @@ -0,0 +1,130 @@ +From 96bb5ecac07255fd4b6149c617c5ef23b7e7c84f Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Mon, 29 Aug 2016 14:49:44 +0200 +Subject: [PATCH] rpcserver: assume version 1 for unversioned command calls + +When a command is called on the server over RPC without its version +specified, assume version 1 instead of the highest known version. + +This ensures backward compatibility with old clients, which do not support +versioned commands and understand only the first version of any given +command. + +https://fedorahosted.org/freeipa/ticket/6217 + +Reviewed-By: David Kupka +--- + ipaserver/rpcserver.py | 43 +++++++++++++++++++++++++++---------------- + 1 file changed, 27 insertions(+), 16 deletions(-) + +diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py +index e48dc3498d6ed8feb6ea44a9a678a8b8c50e8d9b..dd446ae849076d350c97ce9cd6c5a704783f39c0 100644 +--- a/ipaserver/rpcserver.py ++++ b/ipaserver/rpcserver.py +@@ -42,7 +42,7 @@ from ipalib import plugable, errors + from ipalib.capabilities import VERSION_WITHOUT_CAPABILITIES + from ipalib.frontend import Local + from ipalib.backend import Executioner +-from ipalib.errors import (PublicError, InternalError, CommandError, JSONError, ++from ipalib.errors import (PublicError, InternalError, JSONError, + CCacheError, RefererError, InvalidSessionPassword, NotFound, ACIError, + ExecutionError, PasswordExpired, KrbPrincipalExpired, UserLocked) + from ipalib.request import context, destroy_context +@@ -311,6 +311,21 @@ class WSGIExecutioner(Executioner): + if 'wsgi_dispatch' in self.api.Backend: + self.api.Backend.wsgi_dispatch.mount(self, self.key) + ++ def __get_command(self, name): ++ try: ++ # assume version 1 for unversioned command calls ++ command = self.api.Command[name, '1'] ++ except KeyError: ++ try: ++ command = self.api.Command[name] ++ except KeyError: ++ command = None ++ ++ if command is None or isinstance(command, Local): ++ raise errors.CommandError(name=name) ++ ++ return command ++ + def wsgi_execute(self, environ): + result = None + error = None +@@ -319,6 +334,7 @@ class WSGIExecutioner(Executioner): + name = None + args = () + options = {} ++ command = None + + e = None + if not 'HTTP_REFERER' in environ: +@@ -345,11 +361,9 @@ class WSGIExecutioner(Executioner): + (name, args, options, _id) = self.simple_unmarshal(environ) + if name in self._system_commands: + result = self._system_commands[name](self, *args, **options) +- elif (name not in self.api.Command or +- isinstance(self.api.Command[name], Local)): +- raise CommandError(name=name) + else: +- result = self.Command[name](*args, **options) ++ command = self.__get_command(name) ++ result = command(*args, **options) + except PublicError as e: + if self.api.env.debug: + self.debug('WSGI wsgi_execute PublicError: %s', traceback.format_exc()) +@@ -363,9 +377,9 @@ class WSGIExecutioner(Executioner): + os.environ['LANG'] = lang + + principal = getattr(context, 'principal', 'UNKNOWN') +- if name and name in self.Command: ++ if command is not None: + try: +- params = self.Command[name].args_options_2_params(*args, **options) ++ params = command.args_options_2_params(*args, **options) + except Exception as e: + self.info( + 'exception %s caught when converting options: %s', e.__class__.__name__, str(e) +@@ -380,7 +394,7 @@ class WSGIExecutioner(Executioner): + type(self).__name__, + principal, + name, +- ', '.join(self.Command[name]._repr_iter(**params)), ++ ', '.join(command._repr_iter(**params)), + result_string) + else: + self.info('[%s] %s: %s: %s', +@@ -698,24 +712,21 @@ class xmlserver(KerberosWSGIExecutioner): + # TODO + # for now let's not go out of our way to document standard XML-RPC + return u'undef' +- elif (method_name in self.api.Command and +- not isinstance(self.api.Command[method_name], Local)): ++ else: ++ self.__get_command(method_name) ++ + # All IPA commands return a dict (struct), + # and take a params, options - list and dict (array, struct) + return [[u'struct', u'array', u'struct']] +- else: +- raise errors.CommandError(name=method_name) + + def methodHelp(self, *params): + """get method docstring for XML-RPC introspection""" + method_name = self._get_method_name('system.methodHelp', *params) + if method_name in self._system_commands: + return u'' +- elif (method_name in self.api.Command and +- not isinstance(self.api.Command[method_name], Local)): +- return unicode(self.Command[method_name].doc or '') + else: +- raise errors.CommandError(name=method_name) ++ command = self.__get_command(method_name) ++ return unicode(command.doc or '') + + _system_commands = { + 'system.listMethods': listMethods, +-- +2.7.4 + diff --git a/SOURCES/0106-Installer-do-not-modify-etc-hosts-before-user-agreem.patch b/SOURCES/0106-Installer-do-not-modify-etc-hosts-before-user-agreem.patch deleted file mode 100644 index a158b1d..0000000 --- a/SOURCES/0106-Installer-do-not-modify-etc-hosts-before-user-agreem.patch +++ /dev/null @@ -1,235 +0,0 @@ -From b6c7247319575a376ac9a480ae6ceda39a2bd968 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Tue, 1 Sep 2015 19:05:01 +0200 -Subject: [PATCH] Installer: do not modify /etc/hosts before user agreement - -https://fedorahosted.org/freeipa/ticket/4561 - -As side effect this also fixes: -https://fedorahosted.org/freeipa/ticket/5266 - -Reviewed-By: David Kupka ---- - ipaserver/install/dns.py | 9 ++++++-- - ipaserver/install/installutils.py | 36 +++++++++++++++++++----------- - ipaserver/install/server/install.py | 14 ++++++++++-- - ipaserver/install/server/replicainstall.py | 12 +++++++++- - 4 files changed, 53 insertions(+), 18 deletions(-) - -diff --git a/ipaserver/install/dns.py b/ipaserver/install/dns.py -index 538e99fbe01a34cee627f1cebd938be19777c134..099e35dc331722607c8ca02cdbc7a0e66f8c4754 100644 ---- a/ipaserver/install/dns.py -+++ b/ipaserver/install/dns.py -@@ -19,6 +19,7 @@ from ipapython.ipaldap import AUTOBIND_ENABLED - from ipapython.ipautil import user_input - from ipaserver.install.installutils import get_server_ip_address - from ipaserver.install.installutils import read_dns_forwarders -+from ipaserver.install.installutils import update_hosts_file - from ipaserver.install import bindinstance - from ipaserver.install import dnskeysyncinstance - from ipaserver.install import ntpinstance -@@ -225,8 +226,8 @@ def install_check(standalone, replica, options, hostname): - "the original kasp.db file." % - ", ".join([str(zone) for zone in dnssec_zones])) - -- ip_addresses = get_server_ip_address( -- hostname, fstore, options.unattended, True, options.ip_addresses) -+ ip_addresses = get_server_ip_address(hostname, options.unattended, -+ True, options.ip_addresses) - - if options.no_forwarders: - dns_forwarders = () -@@ -277,6 +278,10 @@ def install(standalone, replica, options): - - conf_ntp = ntpinstance.NTPInstance(fstore).is_enabled() - -+ if standalone: -+ # otherwise this is done by server/replica installer -+ update_hosts_file(ip_addresses, api.env.host, fstore) -+ - bind = bindinstance.BindInstance(fstore, ldapi=True, - autobind=AUTOBIND_ENABLED) - bind.setup(api.env.host, ip_addresses, api.env.realm, api.env.domain, -diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py -index 02e8526317dbab909ed48a1823000922ce6e6b7a..81a025597c97b41377c35a6714bf1d3001c868cc 100644 ---- a/ipaserver/install/installutils.py -+++ b/ipaserver/install/installutils.py -@@ -264,7 +264,8 @@ def read_ip_address(host_name, fstore): - - return ip_parsed - --def read_ip_addresses(host_name, fstore): -+ -+def read_ip_addresses(): - ips = [] - print "Enter the IP address to use, or press Enter to finish." - while True: -@@ -470,7 +471,7 @@ def get_host_name(no_host_dns): - verify_fqdn(hostname, no_host_dns) - return hostname - --def get_server_ip_address(host_name, fstore, unattended, setup_dns, ip_addresses): -+def get_server_ip_address(host_name, unattended, setup_dns, ip_addresses): - # Check we have a public IP that is associated with the hostname - try: - hostaddr = resolve_host(host_name) -@@ -483,8 +484,6 @@ def get_server_ip_address(host_name, fstore, unattended, setup_dns, ip_addresses - print >> sys.stderr, "Please fix your /etc/hosts file and restart the setup program" - sys.exit(1) - -- ip_add_to_hosts = False -- - ips = [] - if len(hostaddr): - for ha in hostaddr: -@@ -495,7 +494,7 @@ def get_server_ip_address(host_name, fstore, unattended, setup_dns, ip_addresses - - if not ips and not ip_addresses: - if not unattended: -- ip_addresses = read_ip_addresses(host_name, fstore) -+ ip_addresses = read_ip_addresses() - - if ip_addresses: - if setup_dns: -@@ -511,22 +510,16 @@ def get_server_ip_address(host_name, fstore, unattended, setup_dns, ip_addresses - print >>sys.stderr, "Provided but not resolved address(es): %s" % \ - ", ".join(str(ip) for ip in (set(ip_addresses) - set(ips))) - sys.exit(1) -- ip_add_to_hosts = True - - if not ips: - print >> sys.stderr, "No usable IP address provided nor resolved." - sys.exit(1) - - for ip_address in ips: -- # check /etc/hosts sanity, add a record when needed -+ # check /etc/hosts sanity - hosts_record = record_in_hosts(str(ip_address)) - -- if hosts_record is None: -- if ip_add_to_hosts or setup_dns: -- print "Adding ["+str(ip_address)+" "+host_name+"] to your /etc/hosts file" -- fstore.backup_file(paths.HOSTS) -- add_record_to_hosts(str(ip_address), host_name) -- else: -+ if hosts_record is not None: - primary_host = hosts_record[1][0] - if primary_host != host_name: - print >>sys.stderr, "Error: there is already a record in /etc/hosts for IP address %s:" \ -@@ -539,6 +532,23 @@ def get_server_ip_address(host_name, fstore, unattended, setup_dns, ip_addresses - - return ips - -+ -+def update_hosts_file(ip_addresses, host_name, fstore): -+ """ -+ Update hosts with specified addresses -+ :param ip_addresses: list of IP addresses -+ :return: -+ """ -+ if not fstore.has_file(paths.HOSTS): -+ fstore.backup_file(paths.HOSTS) -+ for ip_address in ip_addresses: -+ if record_in_hosts(str(ip_address)): -+ continue -+ print "Adding [{address!s} {name}] to your /etc/hosts file".format( -+ address=ip_address, name=host_name) -+ add_record_to_hosts(str(ip_address), host_name) -+ -+ - def expand_replica_info(filename, password): - """ - Decrypt and expand a replica installation file into a temporary -diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py -index ff517513473a458a84f63c5c1308a8cc0b8699f8..9d7036a7786a35e6aa2429254d62c8afb30970db 100644 ---- a/ipaserver/install/server/install.py -+++ b/ipaserver/install/server/install.py -@@ -32,7 +32,8 @@ from ipaserver.install import ( - otpdinstance, replication, service, sysupgrade) - from ipaserver.install.installutils import ( - IPA_MODULES, BadHostError, get_fqdn, get_server_ip_address, -- is_ipa_configured, load_pkcs12, read_password, verify_fqdn) -+ is_ipa_configured, load_pkcs12, read_password, verify_fqdn, -+ update_hosts_file) - from ipaserver.plugins.ldap2 import ldap2 - try: - from ipaserver.install import adtrustinstance -@@ -607,10 +608,15 @@ def install_check(installer): - dns.install_check(False, False, options, host_name) - ip_addresses = dns.ip_addresses - else: -- ip_addresses = get_server_ip_address(host_name, fstore, -+ ip_addresses = get_server_ip_address(host_name, - not installer.interactive, False, - options.ip_addresses) - -+ # installer needs to update hosts file when DNS subsystem will be -+ # installed or custom addresses are used -+ if options.ip_addresses or options.setup_dns: -+ installer._update_hosts_file = True -+ - print - print "The IPA Master Server will be configured with:" - print "Hostname: %s" % host_name -@@ -709,6 +715,9 @@ def install(installer): - # configure /etc/sysconfig/network to contain the custom hostname - tasks.backup_and_replace_hostname(fstore, sstore, host_name) - -+ if installer._update_hosts_file: -+ update_hosts_file(ip_addresses, host_name, fstore) -+ - # Create DS user/group if it doesn't exist yet - dsinstance.create_ds_user() - -@@ -1494,6 +1503,7 @@ class Server(common.Installable, common.Interactive, core.Composite): - self._external_cert_file = None - self._external_ca_file = None - self._ca_cert = None -+ self._update_hosts_file = False - - #pylint: disable=no-member - -diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py -index 0725c7763e505ca0cc5a8892414a3c36c557cf1d..6f9a6141fe9af44806244ce52df59c191dc966b0 100644 ---- a/ipaserver/install/server/replicainstall.py -+++ b/ipaserver/install/server/replicainstall.py -@@ -502,11 +502,17 @@ def install_check(installer): - - if options.setup_dns: - dns.install_check(False, True, options, config.host_name) -+ config.ips = dns.ip_addresses - else: - config.ips = installutils.get_server_ip_address( -- config.host_name, fstore, not installer.interactive, False, -+ config.host_name, not installer.interactive, False, - options.ip_addresses) - -+ # installer needs to update hosts file when DNS subsystem will be -+ # installed or custom addresses are used -+ if options.setup_dns or options.ip_addresses: -+ installer._update_hosts_file = True -+ - # check connection - if not options.skip_conncheck: - replica_conn_check( -@@ -528,6 +534,9 @@ def install(installer): - - dogtag_constants = dogtag.install_constants - -+ if installer._update_hosts_file: -+ installutils.update_hosts_file(config.ips, config.host_name, fstore) -+ - # Create DS user/group if it doesn't exist yet - dsinstance.create_ds_user() - -@@ -785,6 +794,7 @@ class Replica(common.Installable, common.Interactive, core.Composite): - - self._top_dir = None - self._config = None -+ self._update_hosts_file = False - - #pylint: disable=no-member - --- -2.5.1 - diff --git a/SOURCES/0106-custodia-force-reconnect-before-retrieving-CA-certs-.patch b/SOURCES/0106-custodia-force-reconnect-before-retrieving-CA-certs-.patch new file mode 100644 index 0000000..c88ceb7 --- /dev/null +++ b/SOURCES/0106-custodia-force-reconnect-before-retrieving-CA-certs-.patch @@ -0,0 +1,34 @@ +From d5723c202f45edc17c45a7f2a1970eebed259dd5 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Thu, 1 Sep 2016 10:32:18 +0200 +Subject: [PATCH] custodia: force reconnect before retrieving CA certs from + LDAP + +Force reconnect to LDAP as DS might have been restarted after the +connection was opened, rendering the connection invalid. + +This fixes a crash in ipa-replica-install with --setup-ca. + +https://fedorahosted.org/freeipa/ticket/6207 + +Reviewed-By: Martin Basti +--- + ipaserver/install/custodiainstance.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py +index 18bd51426cde09af6a34855a49db386a72cc6b9c..32740274ceae17eebeeb32ef5e043cf4b738ee0d 100644 +--- a/ipaserver/install/custodiainstance.py ++++ b/ipaserver/install/custodiainstance.py +@@ -158,6 +158,8 @@ class CustodiaInstance(SimpleServiceInstance): + # Add CA certificates + tmpdb = CertDB(self.realm, nssdir=tmpnssdir) + self.suffix = ipautil.realm_to_suffix(self.realm) ++ if self.admin_conn is not None: ++ self.ldap_disconnect() + self.import_ca_certs(tmpdb, True) + + # Now that we gathered all certs, re-export +-- +2.7.4 + diff --git a/SOURCES/0107-DNSSEC-backup-and-restore-opendnssec-zone-list-file.patch b/SOURCES/0107-DNSSEC-backup-and-restore-opendnssec-zone-list-file.patch deleted file mode 100644 index b07436f..0000000 --- a/SOURCES/0107-DNSSEC-backup-and-restore-opendnssec-zone-list-file.patch +++ /dev/null @@ -1,43 +0,0 @@ -From 7b04b9e603bf6517458cccae7509e99f10c8a0ec Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Tue, 1 Sep 2015 12:10:00 +0200 -Subject: [PATCH] DNSSEC: backup and restore opendnssec zone list file - -When zone list is not restored after unninstall, this may slow down -enbaling DNSSEC signing for zones and print unwanted -errors into log after new installation. - -Related to: https://fedorahosted.org/freeipa/ticket/5273 - -Reviewed-By: Petr Spacek ---- - ipaserver/install/opendnssecinstance.py | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/ipaserver/install/opendnssecinstance.py b/ipaserver/install/opendnssecinstance.py -index 0f1af828ea245046330fdfab77db130ca14faba3..c5377d910d8f38a1ea0e05461ecf1b92f05ca2ca 100644 ---- a/ipaserver/install/opendnssecinstance.py -+++ b/ipaserver/install/opendnssecinstance.py -@@ -171,6 +171,9 @@ class OpenDNSSECInstance(service.Service): - if not self.fstore.has_file(paths.OPENDNSSEC_KASP_FILE): - self.fstore.backup_file(paths.OPENDNSSEC_KASP_FILE) - -+ if not self.fstore.has_file(paths.OPENDNSSEC_ZONELIST_FILE): -+ self.fstore.backup_file(paths.OPENDNSSEC_ZONELIST_FILE) -+ - pin_fd = open(paths.DNSSEC_SOFTHSM_PIN, "r") - pin = pin_fd.read() - pin_fd.close() -@@ -357,7 +360,8 @@ class OpenDNSSECInstance(service.Service): - paths.IPA_KASP_DB_BACKUP) - - for f in [paths.OPENDNSSEC_CONF_FILE, paths.OPENDNSSEC_KASP_FILE, -- paths.OPENDNSSEC_KASP_DB, paths.SYSCONFIG_ODS]: -+ paths.OPENDNSSEC_KASP_DB, paths.SYSCONFIG_ODS, -+ paths.OPENDNSSEC_ZONELIST_FILE]: - try: - self.fstore.restore_file(f) - except ValueError, error: --- -2.5.1 - diff --git a/SOURCES/0107-rpcserver-fix-crash-in-XML-RPC-system-commands.patch b/SOURCES/0107-rpcserver-fix-crash-in-XML-RPC-system-commands.patch new file mode 100644 index 0000000..4bd2649 --- /dev/null +++ b/SOURCES/0107-rpcserver-fix-crash-in-XML-RPC-system-commands.patch @@ -0,0 +1,59 @@ +From 71910b902993cb0b263bc5a6483fcce733820c80 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Thu, 1 Sep 2016 09:59:37 +0200 +Subject: [PATCH] rpcserver: fix crash in XML-RPC system commands + +Fix an AttributeError in XML-RPC methodSignature and methodHelp commands +caused by incorrect mangled name usage. + +https://fedorahosted.org/freeipa/ticket/6217 + +Reviewed-By: Lenka Doudova +Reviewed-By: David Kupka +--- + ipaserver/rpcserver.py | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py +index dd446ae849076d350c97ce9cd6c5a704783f39c0..f1d5a40694f015fd7f9ad05836ec55c6906d764e 100644 +--- a/ipaserver/rpcserver.py ++++ b/ipaserver/rpcserver.py +@@ -311,7 +311,7 @@ class WSGIExecutioner(Executioner): + if 'wsgi_dispatch' in self.api.Backend: + self.api.Backend.wsgi_dispatch.mount(self, self.key) + +- def __get_command(self, name): ++ def _get_command(self, name): + try: + # assume version 1 for unversioned command calls + command = self.api.Command[name, '1'] +@@ -362,7 +362,7 @@ class WSGIExecutioner(Executioner): + if name in self._system_commands: + result = self._system_commands[name](self, *args, **options) + else: +- command = self.__get_command(name) ++ command = self._get_command(name) + result = command(*args, **options) + except PublicError as e: + if self.api.env.debug: +@@ -713,7 +713,7 @@ class xmlserver(KerberosWSGIExecutioner): + # for now let's not go out of our way to document standard XML-RPC + return u'undef' + else: +- self.__get_command(method_name) ++ self._get_command(method_name) + + # All IPA commands return a dict (struct), + # and take a params, options - list and dict (array, struct) +@@ -725,7 +725,7 @@ class xmlserver(KerberosWSGIExecutioner): + if method_name in self._system_commands: + return u'' + else: +- command = self.__get_command(method_name) ++ command = self._get_command(method_name) + return unicode(command.doc or '') + + _system_commands = { +-- +2.7.4 + diff --git a/SOURCES/0108-DNSSEC-remove-ccache-and-keytab-of-ipa-ods-exporter.patch b/SOURCES/0108-DNSSEC-remove-ccache-and-keytab-of-ipa-ods-exporter.patch deleted file mode 100644 index bb67a96..0000000 --- a/SOURCES/0108-DNSSEC-remove-ccache-and-keytab-of-ipa-ods-exporter.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 832335c92c7ce21ffb8ea9315837aebc2a085d88 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Tue, 1 Sep 2015 16:17:16 +0200 -Subject: [PATCH] DNSSEC: remove ccache and keytab of ipa-ods-exporter - -Reusing old ccache after reinstall causes authentication error. And -prevents DNSSEC from working. - -Related to ticket: https://fedorahosted.org/freeipa/ticket/5273 - -Reviewed-By: Petr Spacek ---- - daemons/dnssec/ipa-ods-exporter | 2 +- - ipaplatform/base/paths.py | 1 + - ipaserver/install/odsexporterinstance.py | 7 +++++++ - 3 files changed, 9 insertions(+), 1 deletion(-) - -diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter -index 4d5423797fc9d4bdd0a432bac96b8209bb98c6d8..62eca71da10ee6f3efd4d391a274278875714570 100755 ---- a/daemons/dnssec/ipa-ods-exporter -+++ b/daemons/dnssec/ipa-ods-exporter -@@ -482,7 +482,7 @@ ipalib.api.finalize() - # Kerberos initialization - PRINCIPAL = str('%s/%s' % (DAEMONNAME, ipalib.api.env.host)) - log.debug('Kerberos principal: %s', PRINCIPAL) --ccache_name = os.path.join(WORKDIR, 'ipa-ods-exporter.ccache') -+ccache_name = paths.IPA_ODS_EXPORTER_CCACHE - - try: - ipautil.kinit_keytab(PRINCIPAL, paths.IPA_ODS_EXPORTER_KEYTAB, ccache_name, -diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py -index 5c8f25d6ef85fab2b9b30a660cd1c0360dbe9931..a407c1273f01b3465bcb1985dd41f2f242346a62 100644 ---- a/ipaplatform/base/paths.py -+++ b/ipaplatform/base/paths.py -@@ -333,6 +333,7 @@ class BasePathNamespace(object): - NAMED_RUN = "/var/named/data/named.run" - VAR_OPENDNSSEC_DIR = "/var/opendnssec" - OPENDNSSEC_KASP_DB = "/var/opendnssec/kasp.db" -+ IPA_ODS_EXPORTER_CCACHE = "/var/opendnssec/tmp/ipa-ods-exporter.ccache" - VAR_RUN_DIRSRV_DIR = "/var/run/dirsrv" - KRB5CC_HTTPD = "/var/run/httpd/ipa/krbcache/krb5ccache" - IPA_RENEWAL_LOCK = "/var/run/ipa/renewal.lock" -diff --git a/ipaserver/install/odsexporterinstance.py b/ipaserver/install/odsexporterinstance.py -index 248943d6c0ca4b71815bcf7526d575842f6ce426..db45d2b812ff6d2d56cb8fb326119658bd1f4b7e 100644 ---- a/ipaserver/install/odsexporterinstance.py -+++ b/ipaserver/install/odsexporterinstance.py -@@ -93,6 +93,13 @@ class ODSExporterInstance(service.Service): - - def __setup_principal(self): - assert self.ods_uid is not None -+ -+ for f in [paths.IPA_ODS_EXPORTER_CCACHE, paths.IPA_ODS_EXPORTER_KEYTAB]: -+ try: -+ os.remove(f) -+ except OSError: -+ pass -+ - dns_exporter_principal = "ipa-ods-exporter/" + self.fqdn + "@" + self.realm - installutils.kadmin_addprinc(dns_exporter_principal) - --- -2.5.1 - diff --git a/SOURCES/0108-compat-Save-server-s-API-version-in-for-pre-schema-s.patch b/SOURCES/0108-compat-Save-server-s-API-version-in-for-pre-schema-s.patch new file mode 100644 index 0000000..ea6cd5e --- /dev/null +++ b/SOURCES/0108-compat-Save-server-s-API-version-in-for-pre-schema-s.patch @@ -0,0 +1,346 @@ +From b738ea5d78d7c6d7ba9d72c7cd57fe10f0f1b305 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Tue, 26 Jul 2016 13:35:22 +0200 +Subject: [PATCH] compat: Save server's API version in for pre-schema servers + +When client comunicates with server that doesn't support 'schema' +command it needs to determine its api version to be able to use the +right compat code. Storing information about server version reduces the +need to call 'env' or 'ping' command only to first time the server is +contacted. + +https://fedorahosted.org/freeipa/ticket/6069 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/__init__.py | 81 ++++++++++++++++++++++++++++++- + ipaclient/remote_plugins/compat.py | 29 +++++++----- + ipaclient/remote_plugins/schema.py | 92 +++--------------------------------- + ipaplatform/base/paths.py | 15 ++++++ + 4 files changed, 116 insertions(+), 101 deletions(-) + +diff --git a/ipaclient/remote_plugins/__init__.py b/ipaclient/remote_plugins/__init__.py +index 6454a4f4ef956a1ef545b82a649ebf26ef6edd7b..2be9222be693a5c4a04a735c216f590d75c1ecfe 100644 +--- a/ipaclient/remote_plugins/__init__.py ++++ b/ipaclient/remote_plugins/__init__.py +@@ -2,9 +2,79 @@ + # Copyright (C) 2016 FreeIPA Contributors see COPYING for license + # + ++import collections ++import errno ++import json ++import os ++ + from . import compat + from . import schema + from ipaclient.plugins.rpcclient import rpcclient ++from ipaplatform.paths import paths ++from ipapython.dnsutil import DNSName ++from ipapython.ipa_log_manager import log_mgr ++ ++logger = log_mgr.get_logger(__name__) ++ ++ ++class ServerInfo(collections.MutableMapping): ++ _DIR = os.path.join(paths.USER_CACHE_PATH, 'ipa', 'servers') ++ ++ def __init__(self, api): ++ hostname = DNSName(api.env.server).ToASCII() ++ self._path = os.path.join(self._DIR, hostname) ++ self._dict = {} ++ self._dirty = False ++ ++ self._read() ++ ++ def __enter__(self): ++ return self ++ ++ def __exit__(self, *_exc_info): ++ self.flush() ++ ++ def flush(self): ++ if self._dirty: ++ self._write() ++ ++ def _read(self): ++ try: ++ with open(self._path, 'r') as sc: ++ self._dict = json.load(sc) ++ except EnvironmentError as e: ++ if e.errno != errno.ENOENT: ++ logger.warning('Failed to read server info: {}'.format(e)) ++ ++ def _write(self): ++ try: ++ try: ++ os.makedirs(self._DIR) ++ except EnvironmentError as e: ++ if e.errno != errno.EEXIST: ++ raise ++ with open(self._path, 'w') as sc: ++ json.dump(self._dict, sc) ++ except EnvironmentError as e: ++ logger.warning('Failed to write server info: {}'.format(e)) ++ ++ def __getitem__(self, key): ++ return self._dict[key] ++ ++ def __setitem__(self, key, value): ++ if key not in self._dict or self._dict[key] != value: ++ self._dirty = True ++ self._dict[key] = value ++ ++ def __delitem__(self, key): ++ del self._dict[key] ++ self._dirty = True ++ ++ def __iter__(self): ++ return iter(self._dict) ++ ++ def __len__(self): ++ return len(self._dict) + + + def get_package(api): +@@ -13,11 +83,18 @@ def get_package(api): + else: + client = rpcclient(api) + client.finalize() ++ ++ try: ++ server_info = api._server_info ++ except AttributeError: ++ server_info = api._server_info = ServerInfo(api) ++ + try: +- plugins = schema.get_package(api, client) ++ plugins = schema.get_package(api, server_info, client) + except schema.NotAvailable: +- plugins = compat.get_package(api, client) ++ plugins = compat.get_package(api, server_info, client) + finally: ++ server_info.flush() + if client.isconnected(): + client.disconnect() + +diff --git a/ipaclient/remote_plugins/compat.py b/ipaclient/remote_plugins/compat.py +index aef5718fcaade157487c0e65562c3bc8a11ad7de..b6d099a075deaaa17143f8ddddfb11d97b75f0ed 100644 +--- a/ipaclient/remote_plugins/compat.py ++++ b/ipaclient/remote_plugins/compat.py +@@ -31,23 +31,26 @@ class CompatObject(Object): + pass + + +-def get_package(api, client): +- if not client.isconnected(): +- client.connect(verbose=False) +- +- env = client.forward(u'env', u'api_version', version=u'2.0') ++def get_package(api, server_info, client): + try: +- server_version = env['result']['api_version'] ++ server_version = server_info['version'] + except KeyError: +- ping = client.forward(u'ping', version=u'2.0') ++ if not client.isconnected(): ++ client.connect(verbose=False) ++ env = client.forward(u'env', u'api_version', version=u'2.0') + try: +- match = re.search(u'API version (2\.[0-9]+)', ping['summary']) ++ server_version = env['result']['api_version'] + except KeyError: +- match = None +- if match is not None: +- server_version = match.group(1) +- else: +- server_version = u'2.0' ++ ping = client.forward(u'ping', u'api_version', version=u'2.0') ++ try: ++ match = re.search(u'API version (2\.[0-9]+)', ping['summary']) ++ except KeyError: ++ match = None ++ if match is not None: ++ server_version = match.group(1) ++ else: ++ server_version = u'2.0' ++ server_info['version'] = server_version + server_version = LooseVersion(server_version) + + package_names = {} +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index 8a77a15d489f067ab1312e863178458570403cc6..553da35127188b1ae842a7a0b58433e632c82b9f 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -22,6 +22,7 @@ from ipalib.errors import SchemaUpToDate + from ipalib.frontend import Object + from ipalib.output import Output + from ipalib.parameters import DefaultFrom, Flag, Password, Str ++from ipaplatform.paths import paths + from ipapython.ipautil import fsdecode + from ipapython.dn import DN + from ipapython.dnsutil import DNSName +@@ -59,17 +60,6 @@ _PARAMS = { + 'str': parameters.Str, + } + +-USER_CACHE_PATH = ( +- os.environ.get('XDG_CACHE_HOME') or +- os.path.join( +- os.environ.get( +- 'HOME', +- os.path.expanduser('~') +- ), +- '.cache' +- ) +-) +- + logger = log_mgr.get_logger(__name__) + + +@@ -348,66 +338,6 @@ class NotAvailable(Exception): + pass + + +-class ServerInfo(collections.MutableMapping): +- _DIR = os.path.join(USER_CACHE_PATH, 'ipa', 'servers') +- +- def __init__(self, api): +- hostname = DNSName(api.env.server).ToASCII() +- self._path = os.path.join(self._DIR, hostname) +- self._dict = {} +- self._dirty = False +- +- self._read() +- +- def __enter__(self): +- return self +- +- def __exit__(self, *_exc_info): +- self.flush() +- +- def flush(self): +- if self._dirty: +- self._write() +- +- def _read(self): +- try: +- with open(self._path, 'r') as sc: +- self._dict = json.load(sc) +- except EnvironmentError as e: +- if e.errno != errno.ENOENT: +- logger.warning('Failed to read server info: {}'.format(e)) +- +- def _write(self): +- try: +- try: +- os.makedirs(self._DIR) +- except EnvironmentError as e: +- if e.errno != errno.EEXIST: +- raise +- with open(self._path, 'w') as sc: +- json.dump(self._dict, sc) +- except EnvironmentError as e: +- logger.warning('Failed to write server info: {}'.format(e)) +- +- def __getitem__(self, key): +- return self._dict[key] +- +- def __setitem__(self, key, value): +- if key not in self._dict or self._dict[key] != value: +- self._dirty = True +- self._dict[key] = value +- +- def __delitem__(self, key): +- del self._dict[key] +- self._dirty = True +- +- def __iter__(self): +- return iter(self._dict) +- +- def __len__(self): +- return len(self._dict) +- +- + class Schema(object): + """ + Store and provide schema for commands and topics +@@ -429,7 +359,7 @@ class Schema(object): + + """ + namespaces = {'classes', 'commands', 'topics'} +- _DIR = os.path.join(USER_CACHE_PATH, 'ipa', 'schema', FORMAT) ++ _DIR = os.path.join(paths.USER_CACHE_PATH, 'ipa', 'schema', FORMAT) + + def __init__(self, api, server_info, client): + self._dict = {} +@@ -538,8 +468,6 @@ class Schema(object): + self._file.write(f.read()) + + with zipfile.ZipFile(self._file, 'r') as schema: +- self._dict['fingerprint'] = self._fingerprint +- + for name in schema.namelist(): + ns, _slash, key = name.partition('/') + if ns in self.namespaces: +@@ -622,22 +550,14 @@ class Schema(object): + return self._help[namespace][member] + + +-def get_package(api, client): ++def get_package(api, server_info, client): + try: + schema = api._schema + except AttributeError: +- try: +- server_info = api._server_info +- except AttributeError: +- server_info = api._server_info = ServerInfo(api) +- +- try: +- schema = Schema(api, server_info, client) +- object.__setattr__(api, '_schema', schema) +- finally: +- server_info.flush() ++ schema = Schema(api, server_info, client) ++ object.__setattr__(api, '_schema', schema) + +- fingerprint = str(schema['fingerprint']) ++ fingerprint = str(server_info['fingerprint']) + package_name = '{}${}'.format(__name__, fingerprint) + package_dir = '{}${}'.format(os.path.splitext(__file__)[0], fingerprint) + +diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py +index 5ffe689950792a40c179533c8baf2794c2388696..065a2011027bf362abd498d227e24928ccf66724 100644 +--- a/ipaplatform/base/paths.py ++++ b/ipaplatform/base/paths.py +@@ -21,6 +21,8 @@ + This base platform module exports default filesystem paths. + ''' + ++import os ++ + + class BasePathNamespace(object): + BASH = "/bin/bash" +@@ -353,4 +355,17 @@ class BasePathNamespace(object): + IPA_CUSTODIA_AUDIT_LOG = '/var/log/ipa-custodia.audit.log' + IPA_GETKEYTAB = '/usr/sbin/ipa-getkeytab' + ++ @property ++ def USER_CACHE_PATH(self): ++ return ( ++ os.environ.get('XDG_CACHE_HOME') or ++ os.path.join( ++ os.environ.get( ++ 'HOME', ++ os.path.expanduser('~') ++ ), ++ '.cache' ++ ) ++ ) ++ + path_namespace = BasePathNamespace +-- +2.7.4 + diff --git a/SOURCES/0109-DNSSEC-prevent-ipa-ods-exporter-from-looping-after-s.patch b/SOURCES/0109-DNSSEC-prevent-ipa-ods-exporter-from-looping-after-s.patch deleted file mode 100644 index 2bad936..0000000 --- a/SOURCES/0109-DNSSEC-prevent-ipa-ods-exporter-from-looping-after-s.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 29cf6ce568747eca90497a29aa21927ac2b69496 Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Mon, 31 Aug 2015 17:58:07 +0200 -Subject: [PATCH] DNSSEC: prevent ipa-ods-exporter from looping after service - auto-restart - -It might happen that systemd will restart the service even if there is -no incomming connection to service socket. In that case we want to exit -because HSM synchronization is done before socket.accept() and we want -to synchronize HSM and DNS zones at the same time. - -https://fedorahosted.org/freeipa/ticket/5273 - -Reviewed-By: Martin Basti -Reviewed-By: Oleg Fayans ---- - daemons/dnssec/ipa-ods-exporter | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter -index 62eca71da10ee6f3efd4d391a274278875714570..9544db149aed6574a8962d6c8e6b6f1bc520d6db 100755 ---- a/daemons/dnssec/ipa-ods-exporter -+++ b/daemons/dnssec/ipa-ods-exporter -@@ -25,6 +25,7 @@ import logging - import os - import subprocess - import socket -+import select - import sys - import systemd.daemon - import systemd.journal -@@ -346,7 +347,12 @@ def receive_systemd_command(log): - raise KeyError('Exactly one socket is expected.') - - sck = socket.fromfd(fds[0], socket.AF_UNIX, socket.SOCK_STREAM) -+ rlist, wlist, xlist = select.select([sck], [], [], 0) -+ if not rlist: -+ log.critical('socket activation did not return socket with a command') -+ sys.exit(0) - -+ log.debug('accepting new connection') - conn, addr = sck.accept() - log.debug('accepted new connection %s', repr(conn)) - --- -2.5.1 - diff --git a/SOURCES/0109-compat-Fix-ping-command-call.patch b/SOURCES/0109-compat-Fix-ping-command-call.patch new file mode 100644 index 0000000..ac1a53c --- /dev/null +++ b/SOURCES/0109-compat-Fix-ping-command-call.patch @@ -0,0 +1,30 @@ +From a13d964ab5b76816a38170f569c3edb4cbe3e06d Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Tue, 16 Aug 2016 16:49:57 +0200 +Subject: [PATCH] compat: Fix ping command call + +Remove extra argument from client.forward call. + +https://fedorahosted.org/freeipa/ticket/6095 + +Reviewed-By: Jan Cholasta +--- + ipaclient/remote_plugins/compat.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipaclient/remote_plugins/compat.py b/ipaclient/remote_plugins/compat.py +index b6d099a075deaaa17143f8ddddfb11d97b75f0ed..5e08cb0ed73becbc17e724864d1a853142a5ef6f 100644 +--- a/ipaclient/remote_plugins/compat.py ++++ b/ipaclient/remote_plugins/compat.py +@@ -41,7 +41,7 @@ def get_package(api, server_info, client): + try: + server_version = env['result']['api_version'] + except KeyError: +- ping = client.forward(u'ping', u'api_version', version=u'2.0') ++ ping = client.forward(u'ping', version=u'2.0') + try: + match = re.search(u'API version (2\.[0-9]+)', ping['summary']) + except KeyError: +-- +2.7.4 + diff --git a/SOURCES/0110-DNSSEC-Fix-deadlock-in-ipa-ods-exporter-ods-enforcer.patch b/SOURCES/0110-DNSSEC-Fix-deadlock-in-ipa-ods-exporter-ods-enforcer.patch deleted file mode 100644 index 51fd00d..0000000 --- a/SOURCES/0110-DNSSEC-Fix-deadlock-in-ipa-ods-exporter-ods-enforcer.patch +++ /dev/null @@ -1,97 +0,0 @@ -From c50f7610b1781ccbd6f169805d29d84e34e46db8 Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Mon, 31 Aug 2015 18:01:12 +0200 -Subject: [PATCH] DNSSEC: Fix deadlock in ipa-ods-exporter <-> ods-enforcerd - interaction - -https://fedorahosted.org/freeipa/ticket/5273 - -Reviewed-By: Martin Basti -Reviewed-By: Oleg Fayans ---- - daemons/dnssec/ipa-ods-exporter | 39 +++++++++++++++++++++++++++++++-------- - 1 file changed, 31 insertions(+), 8 deletions(-) - -diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter -index 9544db149aed6574a8962d6c8e6b6f1bc520d6db..76c7e484c65888b3d722448ee669ca8d95e3f3d9 100755 ---- a/daemons/dnssec/ipa-ods-exporter -+++ b/daemons/dnssec/ipa-ods-exporter -@@ -368,12 +368,12 @@ def parse_command(cmd): - """ - if cmd == 'ipa-hsm-update': - return (0, -- 'HSM synchronization finished, exiting.', -+ 'HSM synchronization finished, skipping zone synchronization.', - None) - - elif cmd == 'ipa-full-update': - return (None, -- 'Synchronization of all zones requested.', -+ 'Synchronization of all zones was finished.', - None) - - elif not cmd.startswith('update '): -@@ -386,7 +386,7 @@ def parse_command(cmd): - else: - zone_name = cmd2ods_zone_name(cmd) - return (None, -- 'Update request for zone "%s" queued.\n' % zone_name, -+ 'Zone was "%s" updated.\n' % zone_name, - zone_name) - - def send_systemd_reply(conn, reply): -@@ -541,18 +541,29 @@ except KeyError as e: - - exitcode, msg, zone_name = parse_command(cmd) - --if conn: -- send_systemd_reply(conn, msg) - if exitcode is not None: -+ if conn: -+ send_systemd_reply(conn, msg) - log.info(msg) - sys.exit(exitcode) - else: - log.debug(msg) - - # Open DB directly and read key timestamps etc. --with ods_db_lock(): -- db = sqlite3.connect(paths.OPENDNSSEC_KASP_DB, -- isolation_level="EXCLUSIVE") -+db = None -+try: -+ # LOCK WARNING: -+ # ods-enforcerd is holding kasp.db.our_lock when processing all zones and -+ # the lock is unlocked only after all calls to ods-signer are finished, -+ # i.e. when ods-enforcerd receives reply from each ods-signer call. -+ # -+ # Consequently, ipa-ods-exporter (ods-signerd implementation) must not -+ # request kasp.db.our_lock to prevent deadlocks. -+ # SQLite transaction isolation should suffice. -+ # Beware: Reply can be sent back only after DB is unlocked and closed -+ # otherwise ods-enforcerd will fail. -+ -+ db = sqlite3.connect(paths.OPENDNSSEC_KASP_DB) - db.row_factory = sqlite3.Row - db.execute('BEGIN') - -@@ -564,4 +575,16 @@ with ods_db_lock(): - for zone_row in db.execute("SELECT name FROM zones"): - sync_zone(log, ldap, dns_dn, zone_row['name']) - -+except Exception as ex: -+ msg = "ipa-ods-exporter exception: %s" % ex -+ raise ex -+ -+finally: -+ try: -+ if db: -+ db.close() -+ finally: -+ if conn: -+ send_systemd_reply(conn, msg) -+ - log.debug('Done') --- -2.5.1 - diff --git a/SOURCES/0110-Fix-man-page-ipa-replica-manage-remove-duplicate-c-o.patch b/SOURCES/0110-Fix-man-page-ipa-replica-manage-remove-duplicate-c-o.patch new file mode 100644 index 0000000..4afdce0 --- /dev/null +++ b/SOURCES/0110-Fix-man-page-ipa-replica-manage-remove-duplicate-c-o.patch @@ -0,0 +1,36 @@ +From bce240ec6a80d5d401387d727ea891f7c961c879 Mon Sep 17 00:00:00 2001 +From: Petr Spacek +Date: Mon, 22 Aug 2016 08:33:34 +0200 +Subject: [PATCH] Fix man page ipa-replica-manage: remove duplicate -c option + from --no-lookup + +https://fedorahosted.org/freeipa/ticket/6233 + +Reviewed-By: Martin Basti +--- + install/tools/man/ipa-replica-manage.1 | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/install/tools/man/ipa-replica-manage.1 b/install/tools/man/ipa-replica-manage.1 +index 34cd314a517ae2f74da7bc87d6336e62d7b57118..ed975c92c4453798e6536a75318d5e5065c876a4 100644 +--- a/install/tools/man/ipa-replica-manage.1 ++++ b/install/tools/man/ipa-replica-manage.1 +@@ -109,12 +109,12 @@ Provide additional information + \fB\-f\fR, \fB\-\-force\fR + Ignore some types of errors, don't prompt when deleting a master + .TP +-\fB\-c\fR, \fB\-\-no\-lookup\fR +-Do not perform DNS lookup checks. +-.TP + \fB\-c\fR, \fB\-\-cleanup\fR + When deleting a master with the \-\-force flag, remove leftover references to an already deleted master. + .TP ++\fB\-\-no\-lookup\fR ++Do not perform DNS lookup checks. ++.TP + \fB\-\-binddn\fR=\fIADMIN_DN\fR + Bind DN to use with remote server (default is cn=Directory Manager) \- Be careful to quote this value on the command line + .TP +-- +2.7.4 + diff --git a/SOURCES/0111-DNSSEC-Fix-HSM-synchronization-in-ipa-dnskeysyncd-wh.patch b/SOURCES/0111-DNSSEC-Fix-HSM-synchronization-in-ipa-dnskeysyncd-wh.patch deleted file mode 100644 index 705c9c7..0000000 --- a/SOURCES/0111-DNSSEC-Fix-HSM-synchronization-in-ipa-dnskeysyncd-wh.patch +++ /dev/null @@ -1,27 +0,0 @@ -From fec0e8360bbd2ead6eb522348ed2b05bd6fdf7bb Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Mon, 31 Aug 2015 18:03:33 +0200 -Subject: [PATCH] DNSSEC: Fix HSM synchronization in ipa-dnskeysyncd when - running on DNSSEC key master - -https://fedorahosted.org/freeipa/ticket/5273 - -Reviewed-By: Martin Basti -Reviewed-By: Oleg Fayans ---- - ipapython/dnssec/keysyncer.py | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/ipapython/dnssec/keysyncer.py b/ipapython/dnssec/keysyncer.py -index 837602fb4e7c74a7099a351c727d1435b5645706..de5b5aa5f670db4c58fb92b989e181d45d887b55 100644 ---- a/ipapython/dnssec/keysyncer.py -+++ b/ipapython/dnssec/keysyncer.py -@@ -177,4 +177,4 @@ class KeySyncer(SyncReplConsumer): - return - if not self.init_done: - return -- ipautil.run([paths.ODS_SIGNER]) -+ ipautil.run([paths.ODS_SIGNER, 'ipa-hsm-update']) --- -2.5.1 - diff --git a/SOURCES/0111-cert-include-CA-name-in-cert-command-output.patch b/SOURCES/0111-cert-include-CA-name-in-cert-command-output.patch new file mode 100644 index 0000000..2499a32 --- /dev/null +++ b/SOURCES/0111-cert-include-CA-name-in-cert-command-output.patch @@ -0,0 +1,112 @@ +From c5fe2ba58e011425d56d5edc7823d575e3366b7d Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Tue, 23 Aug 2016 13:59:33 +0200 +Subject: [PATCH] cert: include CA name in cert command output + +Include name of the CA that issued a certificate in cert-request, cert-show +and cert-find. + +This allows the caller to call further commands on the cert without having +to call ca-find to find the name of the CA. + +https://fedorahosted.org/freeipa/ticket/6151 + +Reviewed-By: Martin Basti +--- + ipaserver/plugins/cert.py | 33 ++++++++++++++++++++++++--------- + 1 file changed, 24 insertions(+), 9 deletions(-) + +diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py +index a1166a0d0e5b09586832550c055fc6714c3efe26..67eaeba33610321bf88143dc4ac06a94887427cd 100644 +--- a/ipaserver/plugins/cert.py ++++ b/ipaserver/plugins/cert.py +@@ -262,6 +262,15 @@ def bind_principal_can_manage_cert(cert): + + class BaseCertObject(Object): + takes_params = ( ++ Str( ++ 'cacn?', ++ cli_name='ca', ++ default=IPA_CA_CN, ++ autofill=True, ++ label=_('Issuing CA'), ++ doc=_('Name of issuing CA'), ++ flags={'no_create', 'no_update', 'no_search'}, ++ ), + Bytes( + 'certificate', validate_certificate, + label=_("Certificate"), +@@ -336,14 +345,7 @@ class BaseCertObject(Object): + + class BaseCertMethod(Method): + def get_options(self): +- yield Str('cacn?', +- cli_name='ca', +- default=IPA_CA_CN, +- autofill=True, +- query=True, +- label=_('Issuing CA'), +- doc=_('Name of issuing CA'), +- ) ++ yield self.obj.params['cacn'].clone(query=True) + + for option in super(BaseCertMethod, self).get_options(): + yield option +@@ -432,7 +434,8 @@ class cert_request(Create, BaseCertMethod, VirtualCommand): + # referencing nonexistant CA) and look up authority ID. + # + ca = kw['cacn'] +- ca_id = api.Command.ca_show(ca)['result']['ipacaid'][0] ++ ca_obj = api.Command.ca_show(ca)['result'] ++ ca_id = ca_obj['ipacaid'][0] + + """ + Access control is partially handled by the ACI titled +@@ -623,6 +626,7 @@ class cert_request(Create, BaseCertMethod, VirtualCommand): + if not raw: + self.obj._parse(result) + result['request_id'] = int(result['request_id']) ++ result['cacn'] = ca_obj['cn'][0] + + # Success? Then add it to the principal's entry + # (unless the profile tells us not to) +@@ -802,6 +806,7 @@ class cert_show(Retrieve, CertMethod, VirtualCommand): + self.obj._parse(result) + result['revoked'] = ('revocation_reason' in result) + self.obj._fill_owners(result) ++ result['cacn'] = ca_obj['cn'][0] + + return dict(result=result, value=pkey_to_value(serial_number, options)) + +@@ -1072,11 +1077,19 @@ class cert_find(Search, CertMethod): + raise + return result, False, complete + ++ ca_objs = self.api.Command.ca_find()['result'] ++ ca_objs = {DN(ca['ipacasubjectdn'][0]): ca for ca in ca_objs} ++ + ra = self.api.Backend.ra + for ra_obj in ra.find(ra_options): + issuer = DN(ra_obj['issuer']) + serial_number = ra_obj['serial_number'] + ++ try: ++ ca_obj = ca_objs[issuer] ++ except KeyError: ++ continue ++ + if pkey_only: + obj = {'serial_number': serial_number} + else: +@@ -1093,6 +1106,8 @@ class cert_find(Search, CertMethod): + ra_obj['certificate'].replace('\r\n', '')) + self.obj._parse(obj) + ++ obj['cacn'] = ca_obj['cn'][0] ++ + result[issuer, serial_number] = obj + + return result, False, complete +-- +2.7.4 + diff --git a/SOURCES/0112-DNSSEC-Fix-key-metadata-export.patch b/SOURCES/0112-DNSSEC-Fix-key-metadata-export.patch deleted file mode 100644 index 719266d..0000000 --- a/SOURCES/0112-DNSSEC-Fix-key-metadata-export.patch +++ /dev/null @@ -1,32 +0,0 @@ -From b250ac5d752b3565b4fdfb74e8de38784ba93d89 Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Mon, 31 Aug 2015 18:40:50 +0200 -Subject: [PATCH] DNSSEC: Fix key metadata export - -Incorrect SQL join condition could lead to situation where metadata from -ZSK and KSK were interchanged. - -https://fedorahosted.org/freeipa/ticket/5273 - -Reviewed-By: Martin Basti -Reviewed-By: Oleg Fayans ---- - daemons/dnssec/ipa-ods-exporter | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter -index 76c7e484c65888b3d722448ee669ca8d95e3f3d9..e0c88936d5983297483c504d422c8d1ee483b6cf 100755 ---- a/daemons/dnssec/ipa-ods-exporter -+++ b/daemons/dnssec/ipa-ods-exporter -@@ -174,7 +174,7 @@ def get_ods_keys(zone_name): - - # get all keys for given zone ID - cur = db.execute("SELECT kp.HSMkey_id, kp.generate, kp.algorithm, dnsk.publish, dnsk.active, dnsk.retire, dnsk.dead, dnsk.keytype " -- "FROM keypairs AS kp JOIN dnsseckeys AS dnsk ON kp.id = dnsk.id " -+ "FROM keypairs AS kp JOIN dnsseckeys AS dnsk ON kp.id = dnsk.keypair_id " - "WHERE dnsk.zone_id = ?", (zone_id,)) - keys = {} - for row in cur: --- -2.5.1 - diff --git a/SOURCES/0112-Fix-CA-ACL-Check-on-SubjectAltNames.patch b/SOURCES/0112-Fix-CA-ACL-Check-on-SubjectAltNames.patch new file mode 100644 index 0000000..a5043e2 --- /dev/null +++ b/SOURCES/0112-Fix-CA-ACL-Check-on-SubjectAltNames.patch @@ -0,0 +1,55 @@ +From 645ddb282a5b75cc17a80c97445cf61806b53cb4 Mon Sep 17 00:00:00 2001 +From: Simo Sorce +Date: Tue, 26 Jul 2016 11:25:27 -0400 +Subject: [PATCH] Fix CA ACL Check on SubjectAltNames + +The code is supposed to check that the SAN name is also authorized to be used +with the specified profile id. +The original principal has already been checked. + +Signed-off-by: Simo Sorce +Reviewed-By: Fraser Tweedale +Reviewed-By: Martin Babinsky +--- + ipaserver/plugins/cert.py | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py +index 67eaeba33610321bf88143dc4ac06a94887427cd..6495bf1491f939a032fad03fe4ef86839c0575ef 100644 +--- a/ipaserver/plugins/cert.py ++++ b/ipaserver/plugins/cert.py +@@ -565,14 +565,18 @@ class cert_request(Create, BaseCertMethod, VirtualCommand): + for name_type, name in subjectaltname: + if name_type == pkcs10.SAN_DNSNAME: + name = unicode(name) ++ alt_principal = None + alt_principal_obj = None +- alt_principal_string = unicode(principal) + try: + if principal_type == HOST: ++ alt_principal = kerberos.Principal( ++ (u'host', name), principal.realm) + alt_principal_obj = api.Command['host_show'](name, all=True) + elif principal_type == SERVICE: ++ alt_principal = kerberos.Principal( ++ (principal.service_name, name), principal.realm) + alt_principal_obj = api.Command['service_show']( +- alt_principal_string, all=True) ++ alt_principal, all=True) + elif principal_type == USER: + raise errors.ValidationError( + name='csr', +@@ -592,8 +596,8 @@ class cert_request(Create, BaseCertMethod, VirtualCommand): + raise errors.ACIError(info=_( + "Insufficient privilege to create a certificate " + "with subject alt name '%s'.") % name) +- if alt_principal_string is not None and not bypass_caacl: +- caacl_check(principal_type, principal, ca, profile_id) ++ if alt_principal is not None and not bypass_caacl: ++ caacl_check(principal_type, alt_principal, ca, profile_id) + elif name_type in (pkcs10.SAN_OTHERNAME_KRB5PRINCIPALNAME, + pkcs10.SAN_OTHERNAME_UPN): + if name != principal_string: +-- +2.7.4 + diff --git a/SOURCES/0113-DNSSEC-Wrap-master-key-using-RSA-OAEP-instead-of-old.patch b/SOURCES/0113-DNSSEC-Wrap-master-key-using-RSA-OAEP-instead-of-old.patch deleted file mode 100644 index abc1a74..0000000 --- a/SOURCES/0113-DNSSEC-Wrap-master-key-using-RSA-OAEP-instead-of-old.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 7bcdc22d4e08739837039027f7c939a7469b8110 Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Tue, 1 Sep 2015 18:16:06 +0200 -Subject: [PATCH] DNSSEC: Wrap master key using RSA OAEP instead of old PKCS - v1.5. - -https://fedorahosted.org/freeipa/ticket/5273 - -Reviewed-By: Martin Basti ---- - daemons/dnssec/ipa-ods-exporter | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter -index e0c88936d5983297483c504d422c8d1ee483b6cf..f30a2253a713d857aa4e7566e52a0a45f7bd50c2 100755 ---- a/daemons/dnssec/ipa-ods-exporter -+++ b/daemons/dnssec/ipa-ods-exporter -@@ -53,8 +53,7 @@ KEYTAB_FB = paths.IPA_ODS_EXPORTER_KEYTAB - ODS_SE_MAXLINE = 1024 # from ODS common/config.h - ODS_DB_LOCK_PATH = "%s%s" % (paths.OPENDNSSEC_KASP_DB, '.our_lock') - --# TODO: MECH_RSA_OAEP --SECRETKEY_WRAPPING_MECH = 'rsaPkcs' -+SECRETKEY_WRAPPING_MECH = 'rsaPkcsOaep' - PRIVKEY_WRAPPING_MECH = 'aesKeyWrapPad' - - # DNSKEY flag constants -@@ -294,7 +293,8 @@ def master2ldap_master_keys_sync(log, ldapkeydb, localhsm): - hexlify(mkey_id), hexlify(replica_key_id))) - replica_key = localhsm.replica_pubkeys_wrap[replica_key_id] - keydata = localhsm.p11.export_wrapped_key(mkey_local.handle, -- replica_key.handle, _ipap11helper.MECH_RSA_PKCS) -+ replica_key.handle, -+ wrappingmech_name2id[SECRETKEY_WRAPPING_MECH]) - mkey_ldap.add_wrapped_data(keydata, SECRETKEY_WRAPPING_MECH, - replica_key_id) - --- -2.5.1 - diff --git a/SOURCES/0113-do-not-use-trusted-forest-name-to-construct-domain-a.patch b/SOURCES/0113-do-not-use-trusted-forest-name-to-construct-domain-a.patch new file mode 100644 index 0000000..be6a22a --- /dev/null +++ b/SOURCES/0113-do-not-use-trusted-forest-name-to-construct-domain-a.patch @@ -0,0 +1,37 @@ +From c8f3d08c4b90bf89dd4c180d14ced95c14692ff7 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Wed, 31 Aug 2016 13:59:14 +0200 +Subject: [PATCH] do not use trusted forest name to construct domain admin + principal + +When `trust-add` is supplied AD domain admin name without realm component, the +code appends the uppercased AD forest root domain name to construct the full +principal. This can cause authentication error, however, when external trust +with non-root domain is requested. + +We should instead use the supplied DNS domain name (if valid) as a realm +component. + +https://fedorahosted.org/freeipa/ticket/6277 + +Reviewed-By: Alexander Bokovoy +--- + ipaserver/plugins/trust.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipaserver/plugins/trust.py b/ipaserver/plugins/trust.py +index b9d9b122a90de62946307b99b44932129eb611e8..8ed96c253e7c7862f60ad668aa6c252038274624 100644 +--- a/ipaserver/plugins/trust.py ++++ b/ipaserver/plugins/trust.py +@@ -319,7 +319,7 @@ def generate_creds(trustinstance, style, **options): + else: + sp = admin_name.split(sep) + if len(sp) == 1: +- sp.append(trustinstance.remote_domain.info['dns_forest'].upper()) ++ sp.append(trustinstance.remote_domain.info['dns_domain'].upper()) + creds = u"{name}%{password}".format(name=sep.join(sp), + password=password) + return creds +-- +2.7.4 + diff --git a/SOURCES/0114-Always-fetch-forest-info-from-root-DCs-when-establis.patch b/SOURCES/0114-Always-fetch-forest-info-from-root-DCs-when-establis.patch new file mode 100644 index 0000000..540d3cc --- /dev/null +++ b/SOURCES/0114-Always-fetch-forest-info-from-root-DCs-when-establis.patch @@ -0,0 +1,85 @@ +From 95d17d4e632effc37eda54e77a71cbf2cf2f888c Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Thu, 1 Sep 2016 09:30:23 +0200 +Subject: [PATCH] Always fetch forest info from root DCs when establishing + two-way trust + +Prior To Windows Server 2012R2, the `netr_DsRGetForestTrustInformation` calls +performed against non-root forest domain DCs were automatically routed to the +root domain DCs to resolve trust topology information. + +This is no longer the case, so the `dcerpc.fetch_domains` function must +explicitly contact root domain DCs even in the case when an external two-way +trust to non-root domain is requested. + +https://fedorahosted.org/freeipa/ticket/6057 + +Reviewed-By: Alexander Bokovoy +--- + ipaserver/plugins/trust.py | 29 +++++++++++++++++++++-------- + 1 file changed, 21 insertions(+), 8 deletions(-) + +diff --git a/ipaserver/plugins/trust.py b/ipaserver/plugins/trust.py +index 8ed96c253e7c7862f60ad668aa6c252038274624..b3cb56c14496c0d56d3f3fedddee8d123f929344 100644 +--- a/ipaserver/plugins/trust.py ++++ b/ipaserver/plugins/trust.py +@@ -770,7 +770,7 @@ sides. + # Bidirectional trust allows us to use cross-realm TGT, so we can + # run the call under original user's credentials + res = fetch_domains_from_trust(self.api, self.trustinstance, +- result['result'], **options) ++ **options) + domains = add_new_domains_from_trust(self.api, self.trustinstance, + result['result'], res, **options) + else: +@@ -1631,8 +1631,21 @@ class trustdomain_del(LDAPDelete): + return result + + +-def fetch_domains_from_trust(myapi, trustinstance, trust_entry, **options): +- trust_name = trust_entry['cn'][0] ++def fetch_domains_from_trust(myapi, trustinstance, **options): ++ """ ++ Contact trust forest root DC and fetch trusted forest topology information. ++ ++ :param myapi: API instance ++ :param trustinstance: Initialized instance of `dcerpc.TrustDomainJoins` ++ class ++ :param options: options passed from API command's `execute()` method ++ ++ :returns: dict containing forest domain information and forest-wide UPN ++ suffixes (if any) ++ """ ++ ++ forest_root_name = trustinstance.remote_domain.info['dns_forest'] ++ + # We want to use Kerberos if we have admin credentials even with SMB calls + # as eventually use of NTLMSSP will be deprecated for trusted domain operations + # If admin credentials are missing, 'creds' will be None and fetch_domains +@@ -1640,10 +1653,10 @@ def fetch_domains_from_trust(myapi, trustinstance, trust_entry, **options): + # as well. + creds = generate_creds(trustinstance, style=CRED_STYLE_KERBEROS, **options) + server = options.get('realm_server', None) +- domains = ipaserver.dcerpc.fetch_domains(myapi, +- trustinstance.local_flatname, +- trust_name, creds=creds, +- server=server) ++ domains = ipaserver.dcerpc.fetch_domains( ++ myapi, trustinstance.local_flatname, forest_root_name, creds=creds, ++ server=server) ++ + return domains + + +@@ -1749,7 +1762,7 @@ class trust_fetch_domains(LDAPRetrieve): + 'on the IPA server first' + ) + ) +- res = fetch_domains_from_trust(self.api, trustinstance, trust, **options) ++ res = fetch_domains_from_trust(self.api, trustinstance, **options) + domains = add_new_domains_from_trust(self.api, trustinstance, trust, res, **options) + + if len(domains) > 0: +-- +2.7.4 + diff --git a/SOURCES/0114-ldap-Make-ldap2-connection-management-thread-safe-ag.patch b/SOURCES/0114-ldap-Make-ldap2-connection-management-thread-safe-ag.patch deleted file mode 100644 index 0c98cc6..0000000 --- a/SOURCES/0114-ldap-Make-ldap2-connection-management-thread-safe-ag.patch +++ /dev/null @@ -1,177 +0,0 @@ -From 96cadaec3c16b296627991ed517d7015fbe2882f Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Wed, 2 Sep 2015 14:04:17 +0200 -Subject: [PATCH] ldap: Make ldap2 connection management thread-safe again - -This fixes the connection code in LDAPClient to not store the LDAP connection -in an attribute of the object, which in combination with ldap2's per-thread -connections lead to race conditions resulting in connection failures. ldap2 -code was updated accordingly. - -https://fedorahosted.org/freeipa/ticket/5268 - -Reviewed-By: Tomas Babej ---- - ipapython/ipaldap.py | 32 +++++++++----------------------- - ipaserver/plugins/ldap2.py | 29 +++++++++++++---------------- - 2 files changed, 22 insertions(+), 39 deletions(-) - -diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py -index ef7c41a37c1f46290afbb11f912d7a4b8ea224c9..4443db03bcee25033abf63786016a7931f7eed20 100644 ---- a/ipapython/ipaldap.py -+++ b/ipapython/ipaldap.py -@@ -710,11 +710,10 @@ class LDAPClient(object): - self._decode_attrs = decode_attrs - - self.log = log_mgr.get_logger(self) -- self._conn = None - self._has_schema = False - self._schema = None - -- self._connect() -+ self._conn = self._connect() - - @property - def conn(self): -@@ -1023,29 +1022,16 @@ class LDAPClient(object): - """ - Close the connection. - """ -- if self._conn is not None: -- self._disconnect() -+ self._conn = None - - def _connect(self): -- if self._conn is not None: -- raise errors.DatabaseError( -- desc="Can't connect to server", info="Already connected") -- - with self.error_handler(): -- # bypass ldap2's locking -- object.__setattr__(self, '_conn', -- ldap.initialize(self.ldap_uri)) -+ conn = ldap.initialize(self.ldap_uri) - - if self._start_tls: -- self._conn.start_tls_s() -- -- def _disconnect(self): -- if self._conn is None: -- raise errors.DatabaseError( -- desc="Can't disconnect from server", info="Not connected") -+ conn.start_tls_s() - -- # bypass ldap2's locking -- object.__setattr__(self, '_conn', None) -+ return conn - - def simple_bind(self, bind_dn, bind_password, server_controls=None, - client_controls=None): -@@ -1059,7 +1045,7 @@ class LDAPClient(object): - assert isinstance(bind_dn, DN) - bind_dn = str(bind_dn) - bind_password = self.encode(bind_password) -- self._conn.simple_bind_s( -+ self.conn.simple_bind_s( - bind_dn, bind_password, server_controls, client_controls) - - def external_bind(self, user_name, server_controls=None, -@@ -1070,7 +1056,7 @@ class LDAPClient(object): - with self.error_handler(): - auth_tokens = ldap.sasl.external(user_name) - self._flush_schema() -- self._conn.sasl_interactive_bind_s( -+ self.conn.sasl_interactive_bind_s( - '', auth_tokens, server_controls, client_controls) - - def gssapi_bind(self, server_controls=None, client_controls=None): -@@ -1080,7 +1066,7 @@ class LDAPClient(object): - with self.error_handler(): - auth_tokens = ldap.sasl.sasl({}, 'GSSAPI') - self._flush_schema() -- self._conn.sasl_interactive_bind_s( -+ self.conn.sasl_interactive_bind_s( - '', auth_tokens, server_controls, client_controls) - - def unbind(self): -@@ -1089,7 +1075,7 @@ class LDAPClient(object): - """ - with self.error_handler(): - self._flush_schema() -- self._conn.unbind_s() -+ self.conn.unbind_s() - - def make_dn_from_attr(self, attr, value, parent_dn=None): - """ -diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py -index 68feee4f09eb12e50867dfbe3c482a359838aa82..deb0592ab68ab8eb712a6d29fdffd8776e2e289a 100644 ---- a/ipaserver/plugins/ldap2.py -+++ b/ipaserver/plugins/ldap2.py -@@ -76,10 +76,7 @@ class ldap2(CrudBackend, LDAPClient): - # do not set it - pass - -- def _disconnect(self): -- pass -- -- def __del__(self): -+ def close(self): - if self.isconnected(): - self.disconnect() - -@@ -118,10 +115,11 @@ class ldap2(CrudBackend, LDAPClient): - if debug_level: - _ldap.set_option(_ldap.OPT_DEBUG_LEVEL, debug_level) - -- LDAPClient._connect(self) -- conn = self._conn -+ client = LDAPClient(self.ldap_uri, -+ force_schema_updates=self._force_schema_updates) -+ conn = client._conn - -- with self.error_handler(): -+ with client.error_handler(): - if self.ldap_uri.startswith('ldapi://') and ccache: - conn.set_option(_ldap.OPT_HOST_NAME, self.api.env.host) - minssf = conn.get_option(_ldap.OPT_X_SASL_SSF_MIN) -@@ -147,29 +145,28 @@ class ldap2(CrudBackend, LDAPClient): - context=krbV.default_context()).principal().name - - os.environ['KRB5CCNAME'] = ccache -- self.gssapi_bind(server_controls=serverctrls, -- client_controls=clientctrls) -+ client.gssapi_bind(server_controls=serverctrls, -+ client_controls=clientctrls) - setattr(context, 'principal', principal) - else: - # no kerberos ccache, use simple bind or external sasl - if autobind: - pent = pwd.getpwuid(os.geteuid()) -- self.external_bind(pent.pw_name, -+ client.external_bind(pent.pw_name, -+ server_controls=serverctrls, -+ client_controls=clientctrls) -+ else: -+ client.simple_bind(bind_dn, bind_pw, - server_controls=serverctrls, - client_controls=clientctrls) -- else: -- self.simple_bind(bind_dn, bind_pw, -- server_controls=serverctrls, -- client_controls=clientctrls) - - return conn - - def destroy_connection(self): - """Disconnect from LDAP server.""" - try: -- if self._conn is not None: -+ if self.conn is not None: - self.unbind() -- LDAPClient._disconnect(self) - except errors.PublicError: - # ignore when trying to unbind multiple times - pass --- -2.5.1 - diff --git a/SOURCES/0115-Using-LDAPI-to-setup-CA-and-KRA-agents.patch b/SOURCES/0115-Using-LDAPI-to-setup-CA-and-KRA-agents.patch deleted file mode 100644 index 8dc5c60..0000000 --- a/SOURCES/0115-Using-LDAPI-to-setup-CA-and-KRA-agents.patch +++ /dev/null @@ -1,271 +0,0 @@ -From 0ceb0c7b9730314cb8dfff7d2af9ef811a96aa13 Mon Sep 17 00:00:00 2001 -From: "Endi S. Dewata" -Date: Thu, 27 Aug 2015 06:44:29 +0200 -Subject: [PATCH] Using LDAPI to setup CA and KRA agents. - -The CA and KRA installation code has been modified to use LDAPI -to create the CA and KRA agents directly in the CA and KRA -database. This way it's no longer necessary to use the Directory -Manager password or CA and KRA admin certificate. - -https://fedorahosted.org/freeipa/ticket/5257 - -Reviewed-By: Martin Basti ---- - ipaplatform/base/paths.py | 2 - - ipaserver/install/cainstance.py | 49 ++++++++++------- - ipaserver/install/krainstance.py | 113 +++++++++++++++------------------------ - 3 files changed, 72 insertions(+), 92 deletions(-) - -diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py -index a407c1273f01b3465bcb1985dd41f2f242346a62..ff75e0d7a5a0250ce71e67b0302bbaab64c5e935 100644 ---- a/ipaplatform/base/paths.py -+++ b/ipaplatform/base/paths.py -@@ -344,8 +344,6 @@ class BasePathNamespace(object): - SLAPD_INSTANCE_SOCKET_TEMPLATE = "/var/run/slapd-%s.socket" - ALL_SLAPD_INSTANCE_SOCKETS = "/var/run/slapd-*.socket" - ADMIN_CERT_PATH = '/root/.dogtag/pki-tomcat/ca_admin.cert' -- KRA_NSSDB_PASSWORD_FILE = "/root/.dogtag/pki-tomcat/kra/password.conf" -- KRA_PKCS12_PASSWORD_FILE = "/root/.dogtag/pki-tomcat/kra/pkcs12_password.conf" - ENTROPY_AVAIL = '/proc/sys/kernel/random/entropy_avail' - LDIF2DB = '/usr/sbin/ldif2db' - DB2LDIF = '/usr/sbin/db2ldif' -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index ecd9300036353426097d929918be974cbbb5c69d..a4504a35a42b8c8ea2a96738c82c546ebebf569f 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -464,7 +464,7 @@ class CAInstance(DogtagInstance): - self.step("restarting certificate server", self.restart_instance) - self.step("requesting RA certificate from CA", self.__request_ra_certificate) - self.step("issuing RA agent certificate", self.__issue_ra_cert) -- self.step("adding RA agent as a trusted user", self.__configure_ra) -+ self.step("adding RA agent as a trusted user", self.__create_ca_agent) - self.step("authorizing RA to modify profiles", self.__configure_profiles_acl) - self.step("configure certmonger for renewals", self.configure_certmonger_renewal) - self.step("configure certificate renewals", self.configure_renewal) -@@ -903,18 +903,26 @@ class CAInstance(DogtagInstance): - - self.configure_agent_renewal() - -- def __configure_ra(self): -- # Create an RA user in the CA LDAP server and add that user to -- # the appropriate groups so it can issue certificates without -- # manual intervention. -- conn = ipaldap.IPAdmin(self.fqdn, self.ds_port) -- conn.do_simple_bind(DN(('cn', 'Directory Manager')), self.dm_password) -+ def __create_ca_agent(self): -+ """ -+ Create CA agent, assign a certificate, and add the user to -+ the appropriate groups for accessing CA services. -+ """ - -- decoded = base64.b64decode(self.ra_cert) -+ # get ipaCert certificate -+ cert_data = base64.b64decode(self.ra_cert) -+ cert = x509.load_certificate(cert_data, x509.DER) - -- entry_dn = DN(('uid', "ipara"), ('ou', 'People'), self.basedn) -+ # connect to CA database -+ server_id = installutils.realm_to_serverid(api.env.realm) -+ dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id -+ conn = ldap2.ldap2(api, ldap_uri=dogtag_uri) -+ conn.connect(autobind=True) -+ -+ # create ipara user with ipaCert certificate -+ user_dn = DN(('uid', "ipara"), ('ou', 'People'), self.basedn) - entry = conn.make_entry( -- entry_dn, -+ user_dn, - objectClass=['top', 'person', 'organizationalPerson', - 'inetOrgPerson', 'cmsuser'], - uid=["ipara"], -@@ -922,23 +930,24 @@ class CAInstance(DogtagInstance): - cn=["ipara"], - usertype=["agentType"], - userstate=["1"], -- userCertificate=[decoded], -+ userCertificate=[cert_data], - description=['2;%s;%s;%s' % ( -- str(self.requestId), -+ cert.serial_number, - DN(('CN', 'Certificate Authority'), self.subject_base), - DN(('CN', 'IPA RA'), self.subject_base))]) -- - conn.add_entry(entry) - -- dn = DN(('cn', 'Certificate Manager Agents'), ('ou', 'groups'), self.basedn) -- modlist = [(0, 'uniqueMember', '%s' % entry_dn)] -- conn.modify_s(dn, modlist) -+ # add ipara user to Certificate Manager Agents group -+ group_dn = DN(('cn', 'Certificate Manager Agents'), ('ou', 'groups'), -+ self.basedn) -+ conn.add_entry_to_group(user_dn, group_dn, 'uniqueMember') - -- dn = DN(('cn', 'Registration Manager Agents'), ('ou', 'groups'), self.basedn) -- modlist = [(0, 'uniqueMember', '%s' % entry_dn)] -- conn.modify_s(dn, modlist) -+ # add ipara user to Registration Manager Agents group -+ group_dn = DN(('cn', 'Registration Manager Agents'), ('ou', 'groups'), -+ self.basedn) -+ conn.add_entry_to_group(user_dn, group_dn, 'uniqueMember') - -- conn.unbind() -+ conn.disconnect() - - def __configure_profiles_acl(self): - """Allow the Certificate Manager Agents group to modify profiles.""" -diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py -index e5cdbf5e7714603041e3f0156e87311994175b18..958fe6fb095e69f83342ce8299d1586b8bbacd47 100644 ---- a/ipaserver/install/krainstance.py -+++ b/ipaserver/install/krainstance.py -@@ -25,17 +25,21 @@ import sys - import tempfile - - from ipalib import api -+from ipalib import x509 - from ipaplatform import services - from ipaplatform.paths import paths -+from ipapython import certdb - from ipapython import dogtag - from ipapython import ipautil - from ipapython.dn import DN - from ipaserver.install import certs - from ipaserver.install import cainstance -+from ipaserver.install import installutils - from ipaserver.install import ldapupdate - from ipaserver.install import service - from ipaserver.install.dogtaginstance import DogtagInstance - from ipaserver.install.dogtaginstance import DEFAULT_DSPORT, PKI_USER -+from ipaserver.plugins import ldap2 - from ipapython.ipa_log_manager import log_mgr - - # When IPA is installed with DNS support, this CNAME should hold all IPA -@@ -111,8 +115,8 @@ class KRAInstance(DogtagInstance): - - self.step("configuring KRA instance", self.__spawn_instance) - if not self.clone: -- self.step("add RA user to KRA agent group", -- self.__add_ra_user_to_agent_group) -+ self.step("create KRA agent", -+ self.__create_kra_agent) - self.step("restarting KRA", self.restart_instance) - self.step("configure certmonger for renewals", - self.configure_certmonger_renewal) -@@ -267,77 +271,46 @@ class KRAInstance(DogtagInstance): - - self.log.debug("completed creating KRA instance") - -- def __add_ra_user_to_agent_group(self): -+ def __create_kra_agent(self): - """ -- Add RA agent created for CA to KRA agent group. -+ Create KRA agent, assign a certificate, and add the user to -+ the appropriate groups for accessing KRA services. - """ - -- # import CA certificate into temporary security database -- args = ["/usr/bin/pki", -- "-d", self.agent_db, -- "-C", paths.KRA_NSSDB_PASSWORD_FILE, -- "client-cert-import", -- "--pkcs12", paths.KRACERT_P12, -- "--pkcs12-password-file", paths.KRA_PKCS12_PASSWORD_FILE] -- ipautil.run(args) -- -- # trust CA certificate -- args = ["/usr/bin/pki", -- "-d", self.agent_db, -- "-C", paths.KRA_NSSDB_PASSWORD_FILE, -- "client-cert-mod", "Certificate Authority - %s" % api.env.realm, -- "--trust", "CT,c,"] -- ipautil.run(args) -- -- # import Dogtag admin certificate into temporary security database -- args = ["/usr/bin/pki", -- "-d", self.agent_db, -- "-C", paths.KRA_NSSDB_PASSWORD_FILE, -- "client-cert-import", -- "--pkcs12", paths.DOGTAG_ADMIN_P12, -- "--pkcs12-password-file", paths.KRA_PKCS12_PASSWORD_FILE] -- ipautil.run(args) -- -- # as Dogtag admin, create ipakra user in KRA -- args = ["/usr/bin/pki", -- "-d", self.agent_db, -- "-C", paths.KRA_NSSDB_PASSWORD_FILE, -- "-n", "ipa-ca-agent", -- "kra-user-add", "ipakra", -- "--fullName", "IPA KRA User"] -- ipautil.run(args) -- -- # as Dogtag admin, add ipakra into KRA agents group -- args = ["/usr/bin/pki", -- "-d", self.agent_db, -- "-C", paths.KRA_NSSDB_PASSWORD_FILE, -- "-n", "ipa-ca-agent", -- "kra-user-membership-add", "ipakra", "Data Recovery Manager Agents"] -- ipautil.run(args) -- -- # assign ipaCert to ipakra -- (file, filename) = tempfile.mkstemp() -- os.close(file) -- try: -- # export ipaCert without private key -- args = ["/usr/bin/pki", -- "-d", paths.HTTPD_ALIAS_DIR, -- "-C", paths.ALIAS_PWDFILE_TXT, -- "client-cert-show", "ipaCert", -- "--cert", filename] -- ipautil.run(args) -- -- # as Dogtag admin, upload and assign ipaCert to ipakra -- args = ["/usr/bin/pki", -- "-d", self.agent_db, -- "-C", paths.KRA_NSSDB_PASSWORD_FILE, -- "-n", "ipa-ca-agent", -- "kra-user-cert-add", "ipakra", -- "--input", filename] -- ipautil.run(args) -- -- finally: -- os.remove(filename) -+ # get ipaCert certificate -+ with certdb.NSSDatabase(paths.HTTPD_ALIAS_DIR) as ipa_nssdb: -+ cert_data = ipa_nssdb.get_cert("ipaCert") -+ cert = x509.load_certificate(cert_data, x509.DER) -+ -+ # connect to KRA database -+ server_id = installutils.realm_to_serverid(api.env.realm) -+ dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id -+ conn = ldap2.ldap2(api, ldap_uri=dogtag_uri) -+ conn.connect(autobind=True) -+ -+ # create ipakra user with ipaCert certificate -+ user_dn = DN(('uid', "ipakra"), ('ou', 'people'), self.basedn) -+ entry = conn.make_entry( -+ user_dn, -+ objectClass=['top', 'person', 'organizationalPerson', -+ 'inetOrgPerson', 'cmsuser'], -+ uid=["ipakra"], -+ sn=["IPA KRA User"], -+ cn=["IPA KRA User"], -+ usertype=["undefined"], -+ userCertificate=[cert_data], -+ description=['2;%s;%s;%s' % ( -+ cert.serial_number, -+ DN(('CN', 'Certificate Authority'), self.subject_base), -+ DN(('CN', 'IPA RA'), self.subject_base))]) -+ conn.add_entry(entry) -+ -+ # add ipakra user to Data Recovery Manager Agents group -+ group_dn = DN(('cn', 'Data Recovery Manager Agents'), ('ou', 'groups'), -+ self.basedn) -+ conn.add_entry_to_group(user_dn, group_dn, 'uniqueMember') -+ -+ conn.disconnect() - - def __add_vault_container(self): - sub_dict = { --- -2.5.1 - diff --git a/SOURCES/0115-factor-out-populate_remote_domain-method-into-module.patch b/SOURCES/0115-factor-out-populate_remote_domain-method-into-module.patch new file mode 100644 index 0000000..522e57d --- /dev/null +++ b/SOURCES/0115-factor-out-populate_remote_domain-method-into-module.patch @@ -0,0 +1,132 @@ +From 9b3a64e24a25a6ebbf7e755ae67c2f0eb2bfdf39 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Thu, 1 Sep 2016 18:09:05 +0200 +Subject: [PATCH] factor out `populate_remote_domain` method into module-level + function + +This allows for re-use of this method in cases where the caller can not or +wishes not to instantiate local Samba domain to retrieve information about +remote ones. + +https://fedorahosted.org/freeipa/ticket/6057 + +Reviewed-By: Alexander Bokovoy +--- + ipaserver/dcerpc.py | 94 ++++++++++++++++++++++++++++++----------------------- + 1 file changed, 53 insertions(+), 41 deletions(-) + +diff --git a/ipaserver/dcerpc.py b/ipaserver/dcerpc.py +index 4d98485e17a9113322b7e38629fc43b593e99fd9..71b8ba6f17bea6b52ae26fe2467de380e5458099 100644 +--- a/ipaserver/dcerpc.py ++++ b/ipaserver/dcerpc.py +@@ -1534,6 +1534,52 @@ def fetch_domains(api, mydomain, trustdomain, creds=None, server=None): + return result + + ++def retrieve_remote_domain(hostname, local_flatname, ++ realm, realm_server=None, ++ realm_admin=None, realm_passwd=None): ++ def get_instance(local_flatname): ++ # Fetch data from foreign domain using password only ++ rd = TrustDomainInstance('') ++ rd.parm.set('workgroup', local_flatname) ++ rd.creds = credentials.Credentials() ++ rd.creds.set_kerberos_state(credentials.DONT_USE_KERBEROS) ++ rd.creds.guess(rd.parm) ++ return rd ++ ++ rd = get_instance(local_flatname) ++ rd.creds.set_anonymous() ++ rd.creds.set_workstation(hostname) ++ if realm_server is None: ++ rd.retrieve_anonymously(realm, discover_srv=True, search_pdc=True) ++ else: ++ rd.retrieve_anonymously(realm_server, ++ discover_srv=False, search_pdc=True) ++ rd.read_only = True ++ if realm_admin and realm_passwd: ++ if 'name' in rd.info: ++ names = realm_admin.split('\\') ++ if len(names) > 1: ++ # realm admin is in DOMAIN\user format ++ # strip DOMAIN part as we'll enforce the one discovered ++ realm_admin = names[-1] ++ auth_string = u"%s\%s%%%s" \ ++ % (rd.info['name'], realm_admin, realm_passwd) ++ td = get_instance(local_flatname) ++ td.creds.parse_string(auth_string) ++ td.creds.set_workstation(hostname) ++ if realm_server is None: ++ # we must have rd.info['dns_hostname'] then ++ # as it is part of the anonymous discovery ++ td.retrieve(rd.info['dns_hostname']) ++ else: ++ td.retrieve(realm_server) ++ td.read_only = False ++ return td ++ ++ # Otherwise, use anonymously obtained data ++ return rd ++ ++ + class TrustDomainJoins(object): + def __init__(self, api): + self.api = api +@@ -1565,47 +1611,13 @@ class TrustDomainJoins(object): + + def populate_remote_domain(self, realm, realm_server=None, + realm_admin=None, realm_passwd=None): +- def get_instance(self): +- # Fetch data from foreign domain using password only +- rd = TrustDomainInstance('') +- rd.parm.set('workgroup', self.local_domain.info['name']) +- rd.creds = credentials.Credentials() +- rd.creds.set_kerberos_state(credentials.DONT_USE_KERBEROS) +- rd.creds.guess(rd.parm) +- return rd +- +- rd = get_instance(self) +- rd.creds.set_anonymous() +- rd.creds.set_workstation(self.local_domain.hostname) +- if realm_server is None: +- rd.retrieve_anonymously(realm, discover_srv=True, search_pdc=True) +- else: +- rd.retrieve_anonymously(realm_server, +- discover_srv=False, search_pdc=True) +- rd.read_only = True +- if realm_admin and realm_passwd: +- if 'name' in rd.info: +- names = realm_admin.split('\\') +- if len(names) > 1: +- # realm admin is in DOMAIN\user format +- # strip DOMAIN part as we'll enforce the one discovered +- realm_admin = names[-1] +- auth_string = u"%s\%s%%%s" \ +- % (rd.info['name'], realm_admin, realm_passwd) +- td = get_instance(self) +- td.creds.parse_string(auth_string) +- td.creds.set_workstation(self.local_domain.hostname) +- if realm_server is None: +- # we must have rd.info['dns_hostname'] then +- # as it is part of the anonymous discovery +- td.retrieve(rd.info['dns_hostname']) +- else: +- td.retrieve(realm_server) +- td.read_only = False +- self.remote_domain = td +- return +- # Otherwise, use anonymously obtained data +- self.remote_domain = rd ++ self.remote_domain = retrieve_remote_domain( ++ self.local_domain.hostname, ++ self.local_domain.info['name'], ++ realm, ++ realm_server=realm_server, ++ realm_admin=realm_admin, ++ realm_passwd=realm_passwd) + + def get_realmdomains(self): + """ +-- +2.7.4 + diff --git a/SOURCES/0116-Always-fetch-forest-info-from-root-DCs-when-establis.patch b/SOURCES/0116-Always-fetch-forest-info-from-root-DCs-when-establis.patch new file mode 100644 index 0000000..2defd3e --- /dev/null +++ b/SOURCES/0116-Always-fetch-forest-info-from-root-DCs-when-establis.patch @@ -0,0 +1,67 @@ +From 6686a4d8906f283a394eb9991af1ab6b66d5dfd1 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Thu, 1 Sep 2016 18:14:22 +0200 +Subject: [PATCH] Always fetch forest info from root DCs when establishing + one-way trust + +Prior To Windows Server 2012R2, the `netr_DsRGetForestTrustInformation` calls +performed against non-root forest domain DCs were automatically routed to +the root domain DCs to resolve trust topology information. + +This is no longer the case, so the `com.redhat.idm.trust-fetch-domains` oddjob +helper used to establish one-way needs to explicitly contact root domain DCs +even in the case when an external trust to non-root domain is requested. + +https://fedorahosted.org/freeipa/ticket/6057 + +Reviewed-By: Alexander Bokovoy +--- + install/oddjob/com.redhat.idm.trust-fetch-domains | 25 ++++++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) + +diff --git a/install/oddjob/com.redhat.idm.trust-fetch-domains b/install/oddjob/com.redhat.idm.trust-fetch-domains +index bffa021cd4f01d31b7271d1ad84420884ce8d99e..32406ac9274f63251180a1e1051e1f1e60f5ecec 100755 +--- a/install/oddjob/com.redhat.idm.trust-fetch-domains ++++ b/install/oddjob/com.redhat.idm.trust-fetch-domains +@@ -40,6 +40,24 @@ def retrieve_keytab(api, ccache_name, oneway_keytab_name, oneway_principal): + pass + + ++def get_forest_root_domain(api_instance, trusted_domain): ++ """ ++ retrieve trusted forest root domain for given domain name ++ ++ :param api_instance: IPA API instance ++ :param trusted_domain: trusted domain name ++ ++ :returns: forest root domain DNS name ++ """ ++ trustconfig_show = api_instance.Command.trustconfig_show ++ flatname = trustconfig_show()['result']['ipantflatname'][0] ++ ++ remote_domain = dcerpc.retrieve_remote_domain( ++ api_instance.env.host, flatname, trusted_domain) ++ ++ return remote_domain.info['dns_forest'] ++ ++ + def parse_options(): + usage = "%prog \n" + parser = config.IPAOptionParser(usage=usage, +@@ -169,7 +187,12 @@ except gssapi.exceptions.GSSError: + # We are done: we have ccache with TDO credentials and can fetch domains + ipa_domain = api.env.domain + os.environ['KRB5CCNAME'] = oneway_ccache_name +-domains = dcerpc.fetch_domains(api, ipa_domain, trusted_domain, creds=True) ++ ++# retrieve the forest root domain name and contact it to retrieve trust ++# topology info ++forest_root = get_forest_root_domain(api, trusted_domain) ++ ++domains = dcerpc.fetch_domains(api, ipa_domain, forest_root, creds=True) + trust_domain_object = api.Command.trust_show(trusted_domain, raw=True)['result'] + trust.add_new_domains_from_trust(api, None, trust_domain_object, domains) + +-- +2.7.4 + diff --git a/SOURCES/0116-load-RA-backend-plugins-during-standalone-CA-install.patch b/SOURCES/0116-load-RA-backend-plugins-during-standalone-CA-install.patch deleted file mode 100644 index d4d8af4..0000000 --- a/SOURCES/0116-load-RA-backend-plugins-during-standalone-CA-install.patch +++ /dev/null @@ -1,35 +0,0 @@ -From c26fec494cc348282d037efb88927f70df17f584 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Fri, 4 Sep 2015 15:14:48 +0200 -Subject: [PATCH] load RA backend plugins during standalone CA install on - CA-less IPA master - -CA-less IPA master has 'ra_plugin' set to 'none' in IPA config. When setting -up Dogtag CA on the master we must override this setting in order to load -dogtag backend plugins and succesfully complete CA installation. - -https://fedorahosted.org/freeipa/ticket/5288 - -Reviewed-By: Jan Cholasta ---- - install/tools/ipa-ca-install | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install -index 8b1cea8d557f315ae38c2448e816ca0b2557077f..6564e4d0304d4e189b133c495b75f200b04e2988 100755 ---- a/install/tools/ipa-ca-install -+++ b/install/tools/ipa-ca-install -@@ -160,7 +160,9 @@ def install_master(safe_options, options): - if not dsinstance.DsInstance().is_configured(): - sys.exit("IPA server is not configured on this system.\n") - -- api.bootstrap(in_server=True) -+ # override ra_plugin setting read from default.conf so that we have -+ # functional dogtag backend plugins during CA install -+ api.bootstrap(in_server=True, ra_plugin='dogtag') - api.finalize() - - dm_password = options.password --- -2.5.1 - diff --git a/SOURCES/0117-Handle-timeout-error-in-ipa-httpd-kdcproxy.patch b/SOURCES/0117-Handle-timeout-error-in-ipa-httpd-kdcproxy.patch deleted file mode 100644 index 389ac69..0000000 --- a/SOURCES/0117-Handle-timeout-error-in-ipa-httpd-kdcproxy.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 6b5411bd9bf98bd7c4bb695b37c2e878f4b0f1ef Mon Sep 17 00:00:00 2001 -From: Christian Heimes -Date: Thu, 10 Sep 2015 11:54:32 +0200 -Subject: [PATCH] Handle timeout error in ipa-httpd-kdcproxy - -The ipa-httpd-kdcproxy script now handles LDAP timeout errors correctly. -A timeout does no longer result into an Apache startup error. - -https://fedorahosted.org/freeipa/ticket/5292 - -Reviewed-By: Martin Basti ---- - install/tools/ipa-httpd-kdcproxy | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/install/tools/ipa-httpd-kdcproxy b/install/tools/ipa-httpd-kdcproxy -index 60b22f2cc321d416871c74f3b4d580594c186a85..5e9863f8bd82e1628030b0b767a6697ab2a1d7bd 100755 ---- a/install/tools/ipa-httpd-kdcproxy -+++ b/install/tools/ipa-httpd-kdcproxy -@@ -24,6 +24,7 @@ This script creates or removes the symlink from /etc/ipa/ipa-kdc-proxy.conf - to /etc/httpd/conf.d/. It's called from ExecStartPre hook in httpd.service. - """ - import os -+import socket - import sys - - from ipalib import api, errors -@@ -81,7 +82,7 @@ class KDCProxyConfig(object): - # EXTERNAL bind as root user - self.con.ldapi = True - self.con.do_bind(timeout=self.time_limit) -- except errors.NetworkError as e: -+ except (errors.NetworkError, socket.timeout) as e: - msg = 'Unable to connect to dirsrv: %s' % e - raise CheckError(msg) - except errors.AuthorizationError as e: --- -2.4.3 - diff --git a/SOURCES/0117-cli-use-full-name-when-executing-a-command.patch b/SOURCES/0117-cli-use-full-name-when-executing-a-command.patch new file mode 100644 index 0000000..7bf6ae2 --- /dev/null +++ b/SOURCES/0117-cli-use-full-name-when-executing-a-command.patch @@ -0,0 +1,31 @@ +From 5139c4ad3a4601d0fc7204b46e2a889d44a79b36 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Mon, 5 Sep 2016 10:18:13 +0200 +Subject: [PATCH] cli: use full name when executing a command + +Fixes the CLI not to always call the default version of a command even when +the version was explicitly specified. + +https://fedorahosted.org/freeipa/ticket/6279 + +Reviewed-By: Martin Basti +--- + ipalib/cli.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipalib/cli.py b/ipalib/cli.py +index d89a5320853ecf575c7ba710b2db2e62e1003141..df9e6cfd20fead7fd28667386c359db250e64b20 100644 +--- a/ipalib/cli.py ++++ b/ipalib/cli.py +@@ -1101,7 +1101,7 @@ class cli(backend.Executioner): + cmd = self.get_command(argv) + if cmd is None: + return +- name = cmd.name ++ name = cmd.full_name + kw = self.parse(cmd, argv[1:]) + if not isinstance(cmd, frontend.Local): + self.create_context() +-- +2.7.4 + diff --git a/SOURCES/0118-Server-Upgrade-backup-CS.cfg-when-dogtag-is-turned-o.patch b/SOURCES/0118-Server-Upgrade-backup-CS.cfg-when-dogtag-is-turned-o.patch deleted file mode 100644 index 2edc965..0000000 --- a/SOURCES/0118-Server-Upgrade-backup-CS.cfg-when-dogtag-is-turned-o.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 908019639e5e0975d3cd73c3c851319224737dcd Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Thu, 10 Sep 2015 18:46:00 +0200 -Subject: [PATCH] Server Upgrade: backup CS.cfg when dogtag is turned off - -Is unable to made CS.cfg when dogtag is running. - -https://fedorahosted.org/freeipa/ticket/5287 - -Reviewed-By: David Kupka ---- - ipaserver/install/server/upgrade.py | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index a57682a4bbdaab2a15b4e415223e2f5faa67ba73..5288f8fcc5fb56b13773e3bb8ea6a5a6c8c0e8a9 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -1354,10 +1354,13 @@ def upgrade_configuration(): - sub_dict['SUBJECT_BASE'] = subject_base - - ca = cainstance.CAInstance(api.env.realm, certs.NSS_DIR) -- ca.backup_config() - - with installutils.stopped_service(configured_constants.SERVICE_NAME, - configured_constants.PKI_INSTANCE_NAME): -+ -+ # Dogtag must be stopped to be able to backup CS.cfg config -+ ca.backup_config() -+ - # migrate CRL publish dir before the location in ipa.conf is updated - ca_restart = migrate_crl_publish_dir(ca) - --- -2.4.3 - diff --git a/SOURCES/0118-Use-RSA-OAEP-instead-of-RSA-PKCS-1-v1.5.patch b/SOURCES/0118-Use-RSA-OAEP-instead-of-RSA-PKCS-1-v1.5.patch new file mode 100644 index 0000000..301cfd9 --- /dev/null +++ b/SOURCES/0118-Use-RSA-OAEP-instead-of-RSA-PKCS-1-v1.5.patch @@ -0,0 +1,33 @@ +From 88b8163fa5f3b4f01dab588c2b08db9258c55be1 Mon Sep 17 00:00:00 2001 +From: Christian Heimes +Date: Mon, 5 Sep 2016 15:38:48 +0200 +Subject: [PATCH] Use RSA-OAEP instead of RSA PKCS#1 v1.5 + +jwcrypto's RSA1-5 (PKCS#1 v1.5) is vulnerable to padding oracle +side-channel attacks. OAEP (PKCS#1 v2.0) is a safe, more modern +alternative. + +https://fedorahosted.org/freeipa/ticket/6278 + +Signed-off-by: Christian Heimes +Reviewed-By: Martin Basti +--- + ipapython/secrets/client.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ipapython/secrets/client.py b/ipapython/secrets/client.py +index 56ed6f7944c46393ed225cde1b5e0bb80fe6bef0..d9cc7d0f5b066dfd8efba480feb5f271ed1ebe83 100644 +--- a/ipapython/secrets/client.py ++++ b/ipapython/secrets/client.py +@@ -86,7 +86,7 @@ class CustodiaClient(object): + url = 'https://%s/ipa/keys/%s' % (self.server, keyname) + + # Prepare signed/encrypted request +- encalg = ('RSA1_5', 'A256CBC-HS512') ++ encalg = ('RSA-OAEP', 'A256CBC-HS512') + request = self.kemcli.make_request(keyname, encalg=encalg) + + # Prepare Authentication header +-- +2.7.4 + diff --git a/SOURCES/0119-Fix-ipa-certupdate-for-CA-less-installation.patch b/SOURCES/0119-Fix-ipa-certupdate-for-CA-less-installation.patch new file mode 100644 index 0000000..31d64a9 --- /dev/null +++ b/SOURCES/0119-Fix-ipa-certupdate-for-CA-less-installation.patch @@ -0,0 +1,44 @@ +From 0c3b7bd3b51626fc7f29c98087e1d59ea079bcda Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Thu, 1 Sep 2016 15:53:38 +0200 +Subject: [PATCH] Fix ipa-certupdate for CA-less installation + +In a CA-less installation, ipa-certupdate fails with the error message: + $ ipa-certupdate + trying https://vm-180.abc.idm.lab.eng.brq.redhat.com/ipa/session/json + Forwarding 'ca_is_enabled' to json server 'https://vm-180.abc.idm.lab.eng.brq.redhat.com/ipa/session/json' + Forwarding 'ca_find/1' to json server 'https://vm-180.abc.idm.lab.eng.brq.redhat.com/ipa/session/json' + CA is not configured + The ipa-certupdate command failed. + +The issue happens because ipa-certupdate tries to call ca_find even on a +CA_less deployment. The fix skips the call to ca_find in this case. + +https://fedorahosted.org/freeipa/ticket/6288 + +Reviewed-By: Tomas Krizek +--- + ipaclient/ipa_certupdate.py | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/ipaclient/ipa_certupdate.py b/ipaclient/ipa_certupdate.py +index e59047a2705eb8ccb98b5213c4c8771f55a29bc5..f340f32bcdca5f5d98177f7aa9af366b67d8dd80 100644 +--- a/ipaclient/ipa_certupdate.py ++++ b/ipaclient/ipa_certupdate.py +@@ -87,9 +87,10 @@ class CertUpdate(admintool.AdminTool): + + # find lightweight CAs (on renewal master only) + lwcas = [] +- for ca_obj in api.Command.ca_find()['result']: +- if IPA_CA_CN not in ca_obj['cn']: +- lwcas.append(ca_obj) ++ if ca_enabled: ++ for ca_obj in api.Command.ca_find()['result']: ++ if IPA_CA_CN not in ca_obj['cn']: ++ lwcas.append(ca_obj) + + api.Backend.rpcclient.disconnect() + finally: +-- +2.7.4 + diff --git a/SOURCES/0119-IPA-Restore-allows-to-specify-files-that-should-be-r.patch b/SOURCES/0119-IPA-Restore-allows-to-specify-files-that-should-be-r.patch deleted file mode 100644 index 27a4fda..0000000 --- a/SOURCES/0119-IPA-Restore-allows-to-specify-files-that-should-be-r.patch +++ /dev/null @@ -1,75 +0,0 @@ -From 98e289720cbe58e2d921ee95d316644c1bb5cce8 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Thu, 10 Sep 2015 16:35:54 +0200 -Subject: [PATCH] IPA Restore: allows to specify files that should be removed - -Some files/directories should be removed before backup files are copied -to filesystem. - -In case of DNSSEC, the /var/lib/ipa/dnssec/tokens directory has to be -removed, otherwise tokens that are backed up and existing tokens will be -mixed and SOFTHSM log in will not work - -https://fedorahosted.org/freeipa/ticket/5293 - -Reviewed-By: David Kupka ---- - ipaserver/install/ipa_restore.py | 28 ++++++++++++++++++++++++++++ - 1 file changed, 28 insertions(+) - -diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py -index 8960626d0f0e438ef198e2d92803983e520051a8..dc57a4937365ad1db960955cf21e1bf2d2eb3dda 100644 ---- a/ipaserver/install/ipa_restore.py -+++ b/ipaserver/install/ipa_restore.py -@@ -128,6 +128,14 @@ class Restore(admintool.AdminTool): - - description = "Restore IPA files and databases." - -+ # directories and files listed here will be removed from filesystem before -+ # files from backup are copied -+ DIRS_TO_BE_REMOVED = [ -+ paths.DNSSEC_TOKENS_DIR, -+ ] -+ -+ FILES_TO_BE_REMOVED = [] -+ - def __init__(self, options, args): - super(Restore, self).__init__(options, args) - self._conn = None -@@ -365,6 +373,7 @@ class Restore(admintool.AdminTool): - - # We do either a full file restore or we restore data. - if restore_type == 'FULL': -+ self.remove_old_files() - if 'CA' in self.backup_services: - create_ca_user() - self.cert_restore_prepare() -@@ -640,6 +649,25 @@ class Restore(admintool.AdminTool): - (paths.IPA_DEFAULT_CONF, stderr)) - os.chdir(cwd) - -+ def remove_old_files(self): -+ """ -+ Removes all directories, files or temporal files that should be -+ removed before backup files are copied, to prevent errors. -+ """ -+ for d in self.DIRS_TO_BE_REMOVED: -+ try: -+ shutil.rmtree(d) -+ except OSError as e: -+ if e.errno != 2: # 2: dir does not exist -+ self.log.warning("Could not remove directory: %s (%s)", -+ d, e) -+ -+ for f in self.FILES_TO_BE_REMOVED: -+ try: -+ os.remove(f) -+ except OSError as e: -+ if e.errno != 2: # 2: file does not exist -+ self.log.warning("Could not remove file: %s (%s)", f, e) - - def file_restore(self, nologs=False): - ''' --- -2.4.3 - diff --git a/SOURCES/0120-Track-lightweight-CAs-on-replica-installation.patch b/SOURCES/0120-Track-lightweight-CAs-on-replica-installation.patch new file mode 100644 index 0000000..dc2fe2f --- /dev/null +++ b/SOURCES/0120-Track-lightweight-CAs-on-replica-installation.patch @@ -0,0 +1,208 @@ +From 01fcae3f99ba3368cb88418e14b6bbbe81bc555d Mon Sep 17 00:00:00 2001 +From: Fraser Tweedale +Date: Tue, 23 Aug 2016 16:14:30 +1000 +Subject: [PATCH] Track lightweight CAs on replica installation + +Add Certmonger tracking requests for lightweight CAs on replica +installation. As part of this change, extract most of the +lightweight CA tracking code out of ipa-certupdate and into +cainstance. + +Fixes: https://fedorahosted.org/freeipa/ticket/6019 +Reviewed-By: Martin Babinsky +--- + ipaclient/ipa_certupdate.py | 53 ++++++--------------------------- + ipalib/constants.py | 2 ++ + ipaserver/install/cainstance.py | 66 +++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 77 insertions(+), 44 deletions(-) + +diff --git a/ipaclient/ipa_certupdate.py b/ipaclient/ipa_certupdate.py +index f340f32bcdca5f5d98177f7aa9af366b67d8dd80..4b97b85b83c8b1a130d6db9cdcc7a76fc569af9e 100644 +--- a/ipaclient/ipa_certupdate.py ++++ b/ipaclient/ipa_certupdate.py +@@ -29,10 +29,8 @@ from ipaplatform import services + from ipaplatform.paths import paths + from ipaplatform.tasks import tasks + from ipalib import api, errors, x509, certstore +-from ipalib.constants import IPA_CA_CN ++from ipalib.constants import IPA_CA_NICKNAME, RENEWAL_CA_NAME + +-IPA_CA_NICKNAME = 'caSigningCert cert-pki-ca' +-RENEWAL_CA_NAME = 'dogtag-ipa-ca-renew-agent' + + class CertUpdate(admintool.AdminTool): + command_name = 'ipa-certupdate' +@@ -85,12 +83,7 @@ class CertUpdate(admintool.AdminTool): + certs = certstore.get_ca_certs(ldap, api.env.basedn, + api.env.realm, ca_enabled) + +- # find lightweight CAs (on renewal master only) +- lwcas = [] +- if ca_enabled: +- for ca_obj in api.Command.ca_find()['result']: +- if IPA_CA_CN not in ca_obj['cn']: +- lwcas.append(ca_obj) ++ lwcas = api.Command.ca_find()['result'] + + api.Backend.rpcclient.disconnect() + finally: +@@ -99,8 +92,13 @@ class CertUpdate(admintool.AdminTool): + server_fstore = sysrestore.FileStore(paths.SYSRESTORE) + if server_fstore.has_files(): + self.update_server(certs) +- for entry in lwcas: +- self.server_track_lightweight_ca(entry) ++ try: ++ from ipaserver.install import cainstance ++ cainstance.add_lightweight_ca_tracking_requests( ++ self.log, lwcas) ++ except Exception as e: ++ self.log.exception( ++ "Failed to add lightweight CA tracking requests") + + self.update_client(certs) + +@@ -164,39 +162,6 @@ class CertUpdate(admintool.AdminTool): + + self.update_file(paths.CA_CRT, certs) + +- def server_track_lightweight_ca(self, entry): +- nickname = "{} {}".format(IPA_CA_NICKNAME, entry['ipacaid'][0]) +- criteria = { +- 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR, +- 'cert-nickname': nickname, +- 'ca-name': RENEWAL_CA_NAME, +- } +- request_id = certmonger.get_request_id(criteria) +- if request_id is None: +- try: +- certmonger.dogtag_start_tracking( +- secdir=paths.PKI_TOMCAT_ALIAS_DIR, +- pin=certmonger.get_pin('internal'), +- pinfile=None, +- nickname=nickname, +- ca=RENEWAL_CA_NAME, +- pre_command='stop_pkicad', +- post_command='renew_ca_cert "%s"' % nickname, +- ) +- request_id = certmonger.get_request_id(criteria) +- certmonger.modify(request_id, profile='ipaCACertRenewal') +- self.log.debug( +- 'Lightweight CA renewal: ' +- 'added tracking request for "%s"', nickname) +- except RuntimeError as e: +- self.log.error( +- 'Lightweight CA renewal: Certmonger failed to ' +- 'start tracking certificate: %s', e) +- else: +- self.log.debug( +- 'Lightweight CA renewal: ' +- 'already tracking certificate "%s"', nickname) +- + def update_file(self, filename, certs, mode=0o444): + certs = (c[0] for c in certs if c[2] is not False) + try: +diff --git a/ipalib/constants.py b/ipalib/constants.py +index 9b351e260f15211330521453b3ffcd41433a04bb..04515dcd25d066d8f1ab79ae8e8b96e909a1d884 100644 +--- a/ipalib/constants.py ++++ b/ipalib/constants.py +@@ -274,3 +274,5 @@ CA_SUFFIX_NAME = 'ca' + PKI_GSSAPI_SERVICE_NAME = 'dogtag' + IPA_CA_CN = u'ipa' + IPA_CA_RECORD = "ipa-ca" ++IPA_CA_NICKNAME = 'caSigningCert cert-pki-ca' ++RENEWAL_CA_NAME = 'dogtag-ipa-ca-renew-agent' +diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py +index e94fec5f6fd898b66dc12407be6e3f671ac3f4de..3551887cd8ff8baa5e17f8969c84fb92d7552ef3 100644 +--- a/ipaserver/install/cainstance.py ++++ b/ipaserver/install/cainstance.py +@@ -1382,6 +1382,9 @@ class CAInstance(DogtagInstance): + + self.step("enabling CA instance", self.__enable_instance) + ++ self.step("configuring certmonger renewal for lightweight CAs", ++ self.__add_lightweight_ca_tracking_requests) ++ + self.start_creation(runtime=210) + + def setup_lightweight_ca_key_retrieval(self): +@@ -1447,6 +1450,22 @@ class CAInstance(DogtagInstance): + os.chmod(keyfile, 0o600) + os.chown(keyfile, pent.pw_uid, pent.pw_gid) + ++ def __add_lightweight_ca_tracking_requests(self): ++ if not self.admin_conn: ++ self.ldap_connect() ++ ++ try: ++ lwcas = self.admin_conn.get_entries( ++ base_dn=api.env.basedn, ++ filter='(objectclass=ipaca)', ++ attrs_list=['cn', 'ipacaid'], ++ ) ++ add_lightweight_ca_tracking_requests(self.log, lwcas) ++ except errors.NotFound: ++ # shouldn't happen, but don't fail if it does ++ root_logger.warning( ++ "Did not find any lightweight CAs; nothing to track") ++ + + def replica_ca_install_check(config): + if not config.setup_ca: +@@ -2069,6 +2088,53 @@ def ensure_default_caacl(): + api.Backend.ldap2.disconnect() + + ++def add_lightweight_ca_tracking_requests(logger, lwcas): ++ """Add tracking requests for the given lightweight CAs. ++ ++ The entries must have the 'cn' and 'ipacaid' attributes. ++ ++ The IPA CA, if present, is skipped. ++ ++ """ ++ for entry in lwcas: ++ if ipalib.constants.IPA_CA_CN in entry['cn']: ++ continue ++ ++ nickname = "{} {}".format( ++ ipalib.constants.IPA_CA_NICKNAME, ++ entry['ipacaid'][0]) ++ criteria = { ++ 'cert-database': paths.PKI_TOMCAT_ALIAS_DIR, ++ 'cert-nickname': nickname, ++ 'ca-name': ipalib.constants.RENEWAL_CA_NAME, ++ } ++ request_id = certmonger.get_request_id(criteria) ++ if request_id is None: ++ try: ++ certmonger.dogtag_start_tracking( ++ secdir=paths.PKI_TOMCAT_ALIAS_DIR, ++ pin=certmonger.get_pin('internal'), ++ pinfile=None, ++ nickname=nickname, ++ ca=ipalib.constants.RENEWAL_CA_NAME, ++ pre_command='stop_pkicad', ++ post_command='renew_ca_cert "%s"' % nickname, ++ ) ++ request_id = certmonger.get_request_id(criteria) ++ certmonger.modify(request_id, profile='ipaCACertRenewal') ++ logger.debug( ++ 'Lightweight CA renewal: ' ++ 'added tracking request for "%s"', nickname) ++ except RuntimeError as e: ++ logger.error( ++ 'Lightweight CA renewal: Certmonger failed to ' ++ 'start tracking certificate: %s', e) ++ else: ++ logger.debug( ++ 'Lightweight CA renewal: ' ++ 'already tracking certificate "%s"', nickname) ++ ++ + def update_ipa_conf(): + """ + Update IPA configuration file to ensure that RA plugins are enabled and +-- +2.7.4 + diff --git a/SOURCES/0120-config-allow-user-host-attributes-with-tagging-optio.patch b/SOURCES/0120-config-allow-user-host-attributes-with-tagging-optio.patch deleted file mode 100644 index 926c779..0000000 --- a/SOURCES/0120-config-allow-user-host-attributes-with-tagging-optio.patch +++ /dev/null @@ -1,35 +0,0 @@ -From 19f9ad712fc8d8652d66b8aac8befd9d83dad721 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Wed, 16 Sep 2015 08:24:22 +0200 -Subject: [PATCH] config: allow user/host attributes with tagging options - -https://fedorahosted.org/freeipa/ticket/5295 - -Reviewed-By: David Kupka ---- - ipalib/plugins/config.py | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/ipalib/plugins/config.py b/ipalib/plugins/config.py -index 6267313d5e9af2d97f45f987115de143d7aa7915..76368c0887f782153c3131c7833f78afe86dcf89 100644 ---- a/ipalib/plugins/config.py -+++ b/ipalib/plugins/config.py -@@ -262,6 +262,7 @@ class config_mod(LDAPUpdate): - fields = entry_attrs[k].split(',') - for a in fields: - a = a.strip() -+ a, tomato, olive = a.partition(';') - if a not in allowed_attrs: - raise errors.ValidationError( - name=k, error=_('attribute "%s" not allowed') % a -@@ -281,6 +282,7 @@ class config_mod(LDAPUpdate): - if self.api.Object[obj].uuid_attribute: - checked_attrs = checked_attrs + [self.api.Object[obj].uuid_attribute] - for obj_attr in checked_attrs: -+ obj_attr, tomato, olive = obj_attr.partition(';') - if obj_attr in OPERATIONAL_ATTRIBUTES: - continue - if obj_attr in self.api.Object[obj].params and \ --- -2.4.3 - diff --git a/SOURCES/0121-dns-normalize-record-type-read-interactively-in-dnsr.patch b/SOURCES/0121-dns-normalize-record-type-read-interactively-in-dnsr.patch new file mode 100644 index 0000000..f2700cb --- /dev/null +++ b/SOURCES/0121-dns-normalize-record-type-read-interactively-in-dnsr.patch @@ -0,0 +1,36 @@ +From 52ad614c1d2c7dedc46ce2420cbd146a623fbd94 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Mon, 5 Sep 2016 09:35:42 +0200 +Subject: [PATCH] dns: normalize record type read interactively in + dnsrecord_add + +When dnsrecord_add is called without options in interactive mode, it +prompts the user to enter a record type. The record type is expected to be +upper case further in the code, which causes non-upper case values not to +work correctly. + +Fix this issue by upper casing the value after it is read. + +https://fedorahosted.org/freeipa/ticket/6203 + +Reviewed-By: Martin Basti +--- + ipaclient/plugins/dns.py | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/ipaclient/plugins/dns.py b/ipaclient/plugins/dns.py +index e17c282fab2bf1ede095fe37e5cb240eaea21e35..db9c17f8b523365779e53adfb2acc43f4a23401f 100644 +--- a/ipaclient/plugins/dns.py ++++ b/ipaclient/plugins/dns.py +@@ -175,6 +175,8 @@ class dnsrecord_add(MethodOverride): + if rrtype is None: + return + ++ rrtype = rrtype.upper() ++ + try: + name = record_name_format % rrtype.lower() + param = self.params[name] +-- +2.7.4 + diff --git a/SOURCES/0121-winsync-Add-inetUser-objectclass-to-the-passsync-sys.patch b/SOURCES/0121-winsync-Add-inetUser-objectclass-to-the-passsync-sys.patch deleted file mode 100644 index f3350a8..0000000 --- a/SOURCES/0121-winsync-Add-inetUser-objectclass-to-the-passsync-sys.patch +++ /dev/null @@ -1,52 +0,0 @@ -From e2c2bd871a0282628364dcb83d1feba44c5f71dc Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Tue, 15 Sep 2015 11:28:18 +0200 -Subject: [PATCH] winsync: Add inetUser objectclass to the passsync sysaccount - -https://bugzilla.redhat.com/show_bug.cgi?id=1262315 - -Reviewed-By: Petr Vobornik ---- - install/updates/73-winsync.update | 3 +++ - install/updates/Makefile.am | 1 + - ipaserver/install/replication.py | 2 +- - 3 files changed, 5 insertions(+), 1 deletion(-) - create mode 100644 install/updates/73-winsync.update - -diff --git a/install/updates/73-winsync.update b/install/updates/73-winsync.update -new file mode 100644 -index 0000000000000000000000000000000000000000..538eaa1cb6f97a73bfaadd61ac2ce9e9137739cf ---- /dev/null -+++ b/install/updates/73-winsync.update -@@ -0,0 +1,3 @@ -+# Add a inetUser objectclass to the passsync user -+dn: uid=passsync,cn=sysaccounts,cn=etc,$SUFFIX -+addifexist: objectClass: inetUser -diff --git a/install/updates/Makefile.am b/install/updates/Makefile.am -index 2693e4f8f81dc1464a43041e5104ea4363440933..1f4a91c9bb4222f99ad7a7ad16e376aeef7f525b 100644 ---- a/install/updates/Makefile.am -+++ b/install/updates/Makefile.am -@@ -51,6 +51,7 @@ app_DATA = \ - 62-ranges.update \ - 71-idviews.update \ - 72-domainlevels.update \ -+ 73-winsync.update \ - 90-post_upgrade_plugins.update \ - $(NULL) - -diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py -index 2b36a5eb9287bf1789009a3198e540e333869e98..4bd3849e5e91c7251856362891f6c8848da43448 100644 ---- a/ipaserver/install/replication.py -+++ b/ipaserver/install/replication.py -@@ -565,7 +565,7 @@ class ReplicationManager(object): - print "Adding Windows PassSync system account" - entry = conn.make_entry( - pass_dn, -- objectclass=["account", "simplesecurityobject"], -+ objectclass=["account", "simplesecurityobject", "inetUser"], - uid=["passsync"], - userPassword=[password], - ) --- -2.4.3 - diff --git a/SOURCES/0122-baseldap-make-subtree-deletion-optional-in-LDAPDelet.patch b/SOURCES/0122-baseldap-make-subtree-deletion-optional-in-LDAPDelet.patch deleted file mode 100644 index 5065a0a..0000000 --- a/SOURCES/0122-baseldap-make-subtree-deletion-optional-in-LDAPDelet.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 8cd08a619b275155e21d71c1368a73c8814a8640 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Thu, 17 Sep 2015 11:14:54 +0200 -Subject: [PATCH] baseldap: make subtree deletion optional in LDAPDelete - -https://fedorahosted.org/freeipa/ticket/5250 - -Reviewed-By: Petr Vobornik ---- - ipalib/plugins/baseldap.py | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py -index 31f38946afcbb51638bcab68a6e74ec309eba0e4..15b6bb2365705bb6b0dc0df258c6a5b59c4b7d8d 100644 ---- a/ipalib/plugins/baseldap.py -+++ b/ipalib/plugins/baseldap.py -@@ -1565,6 +1565,8 @@ class LDAPDelete(LDAPMultiQuery): - - has_output_params = global_output_params - -+ subtree_delete = True -+ - def execute(self, *keys, **options): - ldap = self.obj.backend - -@@ -1600,6 +1602,8 @@ class LDAPDelete(LDAPMultiQuery): - except errors.NotFound: - self.obj.handle_not_found(*nkeys) - except errors.NotAllowedOnNonLeaf: -+ if not self.subtree_delete: -+ raise - # this entry is not a leaf entry, delete all child nodes - delete_subtree(dn) - --- -2.4.3 - diff --git a/SOURCES/0122-dns-prompt-for-missing-record-parts-in-CLI.patch b/SOURCES/0122-dns-prompt-for-missing-record-parts-in-CLI.patch new file mode 100644 index 0000000..f7bcdf2 --- /dev/null +++ b/SOURCES/0122-dns-prompt-for-missing-record-parts-in-CLI.patch @@ -0,0 +1,201 @@ +From 7563ae6257c56555e502d40bc6fc2e142f850094 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Fri, 2 Sep 2016 16:42:57 +0200 +Subject: [PATCH] dns: prompt for missing record parts in CLI + +Fix the code which determines if a record part is required and thus should +be prompted not to wrongfully consider all record parts to be optional. + +https://fedorahosted.org/freeipa/ticket/6203 + +Reviewed-By: Martin Basti +--- + API.txt | 29 +++++++++++++++++++++++++++++ + VERSION | 4 ++-- + ipaclient/plugins/dns.py | 30 ++++++++++++++++-------------- + ipaserver/plugins/dns.py | 15 +++++++++++++++ + 4 files changed, 62 insertions(+), 16 deletions(-) + +diff --git a/API.txt b/API.txt +index 5b83bfbd0b457b77e0522ab7d83abfae4df3ebe9..fb5bf83cea0633130217cf1327481c8e9b11c4fc 100644 +--- a/API.txt ++++ b/API.txt +@@ -6312,9 +6312,20 @@ default: dns_is_enabled/1 + default: dns_resolve/1 + default: dns_system_records/1 + default: dns_update_system_records/1 ++default: dnsa6record/1 ++default: dnsaaaarecord/1 ++default: dnsafsdbrecord/1 ++default: dnsaplrecord/1 ++default: dnsarecord/1 ++default: dnscertrecord/1 ++default: dnscnamerecord/1 + default: dnsconfig/1 + default: dnsconfig_mod/1 + default: dnsconfig_show/1 ++default: dnsdhcidrecord/1 ++default: dnsdlvrecord/1 ++default: dnsdnamerecord/1 ++default: dnsdsrecord/1 + default: dnsforwardzone/1 + default: dnsforwardzone_add/1 + default: dnsforwardzone_add_permission/1 +@@ -6325,6 +6336,16 @@ default: dnsforwardzone_find/1 + default: dnsforwardzone_mod/1 + default: dnsforwardzone_remove_permission/1 + default: dnsforwardzone_show/1 ++default: dnshiprecord/1 ++default: dnsipseckeyrecord/1 ++default: dnskeyrecord/1 ++default: dnskxrecord/1 ++default: dnslocrecord/1 ++default: dnsmxrecord/1 ++default: dnsnaptrrecord/1 ++default: dnsnsecrecord/1 ++default: dnsnsrecord/1 ++default: dnsptrrecord/1 + default: dnsrecord/1 + default: dnsrecord_add/1 + default: dnsrecord_del/1 +@@ -6333,12 +6354,20 @@ default: dnsrecord_find/1 + default: dnsrecord_mod/1 + default: dnsrecord_show/1 + default: dnsrecord_split_parts/1 ++default: dnsrprecord/1 ++default: dnsrrsigrecord/1 + default: dnsserver/1 + default: dnsserver_add/1 + default: dnsserver_del/1 + default: dnsserver_find/1 + default: dnsserver_mod/1 + default: dnsserver_show/1 ++default: dnssigrecord/1 ++default: dnsspfrecord/1 ++default: dnssrvrecord/1 ++default: dnssshfprecord/1 ++default: dnstlsarecord/1 ++default: dnstxtrecord/1 + default: dnszone/1 + default: dnszone_add/1 + default: dnszone_add_permission/1 +diff --git a/VERSION b/VERSION +index a8b89ed305bcfdf2990a7400d005a68d734fa7e8..796e9fea36b72f3a63372c84b9bfb1538efccfb7 100644 +--- a/VERSION ++++ b/VERSION +@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 + # # + ######################################################## + IPA_API_VERSION_MAJOR=2 +-IPA_API_VERSION_MINOR=212 +-# Last change: ab: service: add flag to allow S4U2Self ++IPA_API_VERSION_MINOR=213 ++# Last change: dns: prompt for missing record parts in CLI +diff --git a/ipaclient/plugins/dns.py b/ipaclient/plugins/dns.py +index db9c17f8b523365779e53adfb2acc43f4a23401f..5e29b8c6666f94f52add7f2e1de8679127886fc2 100644 +--- a/ipaclient/plugins/dns.py ++++ b/ipaclient/plugins/dns.py +@@ -25,10 +25,10 @@ import copy + + from ipaclient.frontend import MethodOverride + from ipalib import errors +-from ipalib.dns import (get_part_rrtype, +- get_record_rrtype, ++from ipalib.dns import (get_record_rrtype, + has_cli_options, + iterate_rrparams_by_parts, ++ part_name_format, + record_name_format) + from ipalib.parameters import Bool + from ipalib.plugable import Registry +@@ -46,9 +46,9 @@ _rev_top_record_types = ('PTR', ) + _zone_top_record_types = ('NS', 'MX', 'LOC', ) + + +-def __get_part_param(cmd, part, output_kw, default=None): +- name = part.name +- label = unicode(part.label) ++def __get_part_param(rrtype, cmd, part, output_kw, default=None): ++ name = part_name_format % (rrtype.lower(), part.name) ++ label = unicode(cmd.params[name].label) + optional = not part.required + + output_kw[name] = cmd.prompt_param(part, +@@ -64,29 +64,31 @@ def prompt_parts(rrtype, cmd, mod_dnsvalue=None): + name, mod_dnsvalue)['result'] + + user_options = {} +- parts = [p for p in cmd.params() if get_part_rrtype(p.name) == rrtype] +- if not parts: ++ try: ++ rrobj = cmd.api.Object['dns{}record'.format(rrtype.lower())] ++ except KeyError: + return user_options + +- for part_id, part in enumerate(parts): ++ for part_id, part in enumerate(rrobj.params()): + if mod_parts: + default = mod_parts[part_id] + else: + default = None + +- __get_part_param(cmd, part, user_options, default) ++ __get_part_param(rrtype, cmd, part, user_options, default) + + return user_options + + + def prompt_missing_parts(rrtype, cmd, kw, prompt_optional=False): + user_options = {} +- parts = [p for p in cmd.params() if get_part_rrtype(p.name) == rrtype] +- if not parts: ++ try: ++ rrobj = cmd.api.Object['dns{}record'.format(rrtype.lower())] ++ except KeyError: + return user_options + +- for part in parts: +- name = part.name ++ for part in rrobj.params(): ++ name = part_name_format % (rrtype.lower(), part.name) + + if name in kw: + continue +@@ -96,7 +98,7 @@ def prompt_missing_parts(rrtype, cmd, kw, prompt_optional=False): + continue + + default = part.get_default(**kw) +- __get_part_param(cmd, part, user_options, default) ++ __get_part_param(rrtype, cmd, part, user_options, default) + + return user_options + +diff --git a/ipaserver/plugins/dns.py b/ipaserver/plugins/dns.py +index 6f1bd716d202bd85dfc46b5eb94f73e85683b917..f048351e649fe0e8e2893627946333b14c11018a 100644 +--- a/ipaserver/plugins/dns.py ++++ b/ipaserver/plugins/dns.py +@@ -3471,6 +3471,21 @@ class dnsrecord(LDAPObject): + ) + + ++# Make DNS record types available as objects in the API. ++# This is used by the CLI to get otherwise unavailable attributes of record ++# parts. ++for param in _dns_records: ++ register()( ++ type( ++ 'dns{}record'.format(param.rrtype.lower()), ++ (Object,), ++ dict( ++ takes_params=(param.parts or ()) + (param.extra or ()), ++ ) ++ ) ++ ) ++ ++ + @register() + class dnsrecord_split_parts(Command): + NO_CLI = True +-- +2.7.4 + diff --git a/SOURCES/0123-dns-fix-crash-in-interactive-mode-against-old-server.patch b/SOURCES/0123-dns-fix-crash-in-interactive-mode-against-old-server.patch new file mode 100644 index 0000000..c826cda --- /dev/null +++ b/SOURCES/0123-dns-fix-crash-in-interactive-mode-against-old-server.patch @@ -0,0 +1,106 @@ +From 89544d521e6aa52e8b9e5e7dc4676046b5792abd Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Tue, 23 Aug 2016 12:53:39 +0200 +Subject: [PATCH] dns: fix crash in interactive mode against old servers + +Add a client-side fallback of the dnsrecord_split_parts command for old +servers to avoid CommandError in dnsrecord_add and dnsrecord_mod CLI +interactive mode. + +https://fedorahosted.org/freeipa/ticket/6203 + +Reviewed-By: Martin Basti +--- + ipaclient/plugins/dns.py | 62 +++++++++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 61 insertions(+), 1 deletion(-) + +diff --git a/ipaclient/plugins/dns.py b/ipaclient/plugins/dns.py +index 5e29b8c6666f94f52add7f2e1de8679127886fc2..b9ab709bf0b1d72cfb9d32aeefd77a0e8bc74d7a 100644 +--- a/ipaclient/plugins/dns.py ++++ b/ipaclient/plugins/dns.py +@@ -22,6 +22,7 @@ from __future__ import print_function + + import six + import copy ++import re + + from ipaclient.frontend import MethodOverride + from ipalib import errors +@@ -30,7 +31,8 @@ from ipalib.dns import (get_record_rrtype, + iterate_rrparams_by_parts, + part_name_format, + record_name_format) +-from ipalib.parameters import Bool ++from ipalib.frontend import Command ++from ipalib.parameters import Bool, Str + from ipalib.plugable import Registry + from ipalib import _, ngettext + from ipapython.dnsutil import DNSName +@@ -121,6 +123,64 @@ class dnszone_mod(DNSZoneMethodOverride): + pass + + ++# Support old servers without dnsrecord_split_parts ++# Do not add anything new here! ++@register(no_fail=True) ++class dnsrecord_split_parts(Command): ++ NO_CLI = True ++ ++ takes_args = ( ++ Str('name'), ++ Str('value'), ++ ) ++ ++ def execute(self, name, value, *args, **options): ++ def split_exactly(count): ++ values = value.split() ++ if len(values) != count: ++ return None ++ return tuple(values) ++ ++ result = () ++ ++ rrtype = get_record_rrtype(name) ++ if rrtype in ('A', 'AAAA', 'CNAME', 'DNAME', 'NS', 'PTR'): ++ result = split_exactly(1) ++ elif rrtype in ('AFSDB', 'KX', 'MX'): ++ result = split_exactly(2) ++ elif rrtype in ('CERT', 'DLV', 'DS', 'SRV', 'TLSA'): ++ result = split_exactly(4) ++ elif rrtype in ('NAPTR'): ++ result = split_exactly(6) ++ elif rrtype in ('A6', 'TXT'): ++ result = (value,) ++ elif rrtype == 'LOC': ++ regex = re.compile( ++ r'(?P\d{1,2}\s+)' ++ r'(?:(?P\d{1,2}\s+)' ++ r'(?P\d{1,2}(?:\.\d{1,3})?\s+)?)?' ++ r'(?P[NS])\s+' ++ r'(?P\d{1,3}\s+)' ++ r'(?:(?P\d{1,2}\s+)' ++ r'(?P\d{1,2}(?:\.\d{1,3})?\s+)?)?' ++ r'(?P[WE])\s+' ++ r'(?P-?\d{1,8}(?:\.\d{1,2})?)m?' ++ r'(?:\s+(?P\d{1,8}(?:\.\d{1,2})?)m?' ++ r'(?:\s+(?P\d{1,8}(?:\.\d{1,2})?)m?' ++ r'(?:\s+(?P\d{1,8}(?:\.\d{1,2})?)m?\s*)?)?)?$') ++ ++ m = regex.match(value) ++ if m is not None: ++ result = tuple( ++ x.strip() if x is not None else x for x in m.groups()) ++ elif rrtype == 'SSHFP': ++ values = value.split(None, 2) ++ if len(values) == 3: ++ result = tuple(values) ++ ++ return dict(result=result) ++ ++ + @register(override=True, no_fail=True) + class dnsrecord_add(MethodOverride): + no_option_msg = 'No options to add a specific record provided.\n' \ +-- +2.7.4 + diff --git a/SOURCES/0123-vault-add-vault-container-commands.patch b/SOURCES/0123-vault-add-vault-container-commands.patch deleted file mode 100644 index 3ea8578..0000000 --- a/SOURCES/0123-vault-add-vault-container-commands.patch +++ /dev/null @@ -1,364 +0,0 @@ -From 83bfd97806d3900f62cac007b66cc8daa0c45234 Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Tue, 25 Aug 2015 19:56:00 +0200 -Subject: [PATCH] vault: add vault container commands - -adds commands: -* vaultcontainer-show [--service |--user |--shared ] -* vaultcontainer-del [--service |--user |--shared ] -* vaultcontainer-add-owner - [--service |--user |--shared ] - [--users ] [--groups ] [--services ] -* vaultcontainer-remove-owner - [--service |--user |--shared ] - [--users ] [--groups ] [--services ] - -https://fedorahosted.org/freeipa/ticket/5250 - -Reviewed-By: Petr Vobornik ---- - API.txt | 53 +++++++++++ - VERSION | 4 +- - ipalib/plugins/vault.py | 243 +++++++++++++++++++++++++++++++++++++++++++----- - 3 files changed, 277 insertions(+), 23 deletions(-) - -diff --git a/API.txt b/API.txt -index 5253e1585e000f39d6e185a94548037dfe54d4d8..4d36a9885157de13529573b3a386b4ef39eba176 100644 ---- a/API.txt -+++ b/API.txt -@@ -5667,6 +5667,59 @@ option: Str('version?', exclude='webui') - output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) - output: Output('summary', (, ), None) - output: PrimaryKey('value', None, None) -+command: vaultcontainer_add_owner -+args: 0,10,3 -+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') -+option: Str('group*', alwaysask=True, cli_name='groups', csv=True) -+option: Flag('no_members', autofill=True, default=False, exclude='webui') -+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') -+option: Str('service?') -+option: Str('services', alwaysask=True, cli_name='services', csv=True, multivalue=True, required=False) -+option: Flag('shared?', autofill=True, default=False) -+option: Str('user*', alwaysask=True, cli_name='users', csv=True) -+option: Str('username?', cli_name='user') -+option: Str('version?', exclude='webui') -+output: Output('completed', , None) -+output: Output('failed', , None) -+output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) -+command: vaultcontainer_del -+args: 0,5,3 -+option: Flag('continue', autofill=True, cli_name='continue', default=False) -+option: Str('service?') -+option: Flag('shared?', autofill=True, default=False) -+option: Str('username?', cli_name='user') -+option: Str('version?', exclude='webui') -+output: Output('result', , None) -+output: Output('summary', (, ), None) -+output: ListOfPrimaryKeys('value', None, None) -+command: vaultcontainer_remove_owner -+args: 0,10,3 -+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') -+option: Str('group*', alwaysask=True, cli_name='groups', csv=True) -+option: Flag('no_members', autofill=True, default=False, exclude='webui') -+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') -+option: Str('service?') -+option: Str('services', alwaysask=True, cli_name='services', csv=True, multivalue=True, required=False) -+option: Flag('shared?', autofill=True, default=False) -+option: Str('user*', alwaysask=True, cli_name='users', csv=True) -+option: Str('username?', cli_name='user') -+option: Str('version?', exclude='webui') -+output: Output('completed', , None) -+output: Output('failed', , None) -+output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) -+command: vaultcontainer_show -+args: 0,8,3 -+option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') -+option: Flag('no_members', autofill=True, default=False, exclude='webui') -+option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') -+option: Flag('rights', autofill=True, default=False) -+option: Str('service?') -+option: Flag('shared?', autofill=True, default=False) -+option: Str('username?', cli_name='user') -+option: Str('version?', exclude='webui') -+output: Entry('result', , Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) -+output: Output('summary', (, ), None) -+output: PrimaryKey('value', None, None) - capability: messages 2.52 - capability: optional_uid_params 2.54 - capability: permissions2 2.69 -diff --git a/VERSION b/VERSION -index da721fdd548023dc3dcd9b4f6a8ba72922a3c6f2..c2b5c87a2615d77e75259edfb8e3a6b7740fac52 100644 ---- a/VERSION -+++ b/VERSION -@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 - # # - ######################################################## - IPA_API_VERSION_MAJOR=2 --IPA_API_VERSION_MINOR=155 --# Last change: ftweedal - remove certprofile 'rename' option -+IPA_API_VERSION_MINOR=156 -+# Last change: pvoborni - add vault container commands -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index e369eeee20f5652942681f7c3e268e6173005452..733741dfc2c87995055599cc3816f321ec344496 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -257,6 +257,228 @@ vault_options = ( - ) - - -+class VaultModMember(LDAPModMember): -+ def get_options(self): -+ for param in super(VaultModMember, self).get_options(): -+ if param.name == 'service' and param not in vault_options: -+ param = param.clone_rename('services') -+ yield param -+ -+ def get_member_dns(self, **options): -+ if 'services' in options: -+ options['service'] = options.pop('services') -+ else: -+ options.pop('service', None) -+ return super(VaultModMember, self).get_member_dns(**options) -+ -+ def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): -+ for fail in failed.itervalues(): -+ fail['services'] = fail.pop('service', []) -+ self.obj.get_container_attribute(entry_attrs, options) -+ return completed, dn -+ -+ -+@register() -+class vaultcontainer(LDAPObject): -+ __doc__ = _(""" -+ Vault Container object. -+ """) -+ -+ container_dn = api.env.container_vault -+ -+ object_name = _('vaultcontainer') -+ object_name_plural = _('vaultcontainers') -+ object_class = ['ipaVaultContainer'] -+ -+ attribute_members = { -+ 'owner': ['user', 'group', 'service'], -+ } -+ -+ label = _('Vault Containers') -+ label_singular = _('Vault Container') -+ -+ takes_params = ( -+ Str( -+ 'owner_user?', -+ label=_('Owner users'), -+ ), -+ Str( -+ 'owner_group?', -+ label=_('Owner groups'), -+ ), -+ Str( -+ 'owner_service?', -+ label=_('Owner services'), -+ ), -+ Str( -+ 'owner?', -+ label=_('Failed owners'), -+ ), -+ Str( -+ 'service?', -+ label=_('Vault service'), -+ flags={'virtual_attribute'}, -+ ), -+ Flag( -+ 'shared?', -+ label=_('Shared vault'), -+ flags={'virtual_attribute'}, -+ ), -+ Str( -+ 'username?', -+ label=_('Vault user'), -+ flags={'virtual_attribute'}, -+ ), -+ ) -+ -+ def get_dn(self, *keys, **options): -+ """ -+ Generates vault DN from parameters. -+ """ -+ service = options.get('service') -+ shared = options.get('shared') -+ user = options.get('username') -+ -+ count = (bool(service) + bool(shared) + bool(user)) -+ if count > 1: -+ raise errors.MutuallyExclusiveError( -+ reason=_('Service, shared and user options ' + -+ 'cannot be specified simultaneously')) -+ -+ parent_dn = super(vaultcontainer, self).get_dn(*keys, **options) -+ -+ if not count: -+ principal = getattr(context, 'principal') -+ -+ if principal.startswith('host/'): -+ raise errors.NotImplementedError( -+ reason=_('Host is not supported')) -+ -+ (name, realm) = split_principal(principal) -+ if '/' in name: -+ service = name -+ else: -+ user = name -+ -+ if service: -+ dn = DN(('cn', service), ('cn', 'services'), parent_dn) -+ elif shared: -+ dn = DN(('cn', 'shared'), parent_dn) -+ elif user: -+ dn = DN(('cn', user), ('cn', 'users'), parent_dn) -+ else: -+ raise RuntimeError -+ -+ return dn -+ -+ def get_container_attribute(self, entry, options): -+ if options.get('raw', False): -+ return -+ container_dn = DN(self.container_dn, self.api.env.basedn) -+ if entry.dn.endswith(DN(('cn', 'services'), container_dn)): -+ entry['service'] = entry.dn[0]['cn'] -+ elif entry.dn.endswith(DN(('cn', 'shared'), container_dn)): -+ entry['shared'] = True -+ elif entry.dn.endswith(DN(('cn', 'users'), container_dn)): -+ entry['username'] = entry.dn[0]['cn'] -+ -+ -+@register() -+class vaultcontainer_show(LDAPRetrieve): -+ __doc__ = _('Display information about a vault container.') -+ -+ takes_options = LDAPRetrieve.takes_options + vault_options -+ -+ has_output_params = LDAPRetrieve.has_output_params -+ -+ def pre_callback(self, ldap, dn, attrs_list, *keys, **options): -+ assert isinstance(dn, DN) -+ -+ if not self.api.Command.kra_is_enabled()['result']: -+ raise errors.InvocationError( -+ format=_('KRA service is not enabled')) -+ -+ return dn -+ -+ def post_callback(self, ldap, dn, entry_attrs, *keys, **options): -+ self.obj.get_container_attribute(entry_attrs, options) -+ return dn -+ -+ -+@register() -+class vaultcontainer_del(LDAPDelete): -+ __doc__ = _('Delete a vault container.') -+ -+ takes_options = LDAPDelete.takes_options + vault_options -+ -+ msg_summary = _('Deleted vault container') -+ -+ subtree_delete = False -+ -+ def pre_callback(self, ldap, dn, *keys, **options): -+ assert isinstance(dn, DN) -+ -+ if not self.api.Command.kra_is_enabled()['result']: -+ raise errors.InvocationError( -+ format=_('KRA service is not enabled')) -+ -+ return dn -+ -+ def execute(self, *keys, **options): -+ keys = keys + (u'',) -+ return super(vaultcontainer_del, self).execute(*keys, **options) -+ -+ -+@register() -+class vaultcontainer_add_owner(VaultModMember, LDAPAddMember): -+ __doc__ = _('Add owners to a vault container.') -+ -+ takes_options = LDAPAddMember.takes_options + vault_options -+ -+ member_attributes = ['owner'] -+ member_param_label = _('owner %s') -+ member_count_out = ('%i owner added.', '%i owners added.') -+ -+ has_output = ( -+ output.Entry('result'), -+ output.Output( -+ 'failed', -+ type=dict, -+ doc=_('Owners that could not be added'), -+ ), -+ output.Output( -+ 'completed', -+ type=int, -+ doc=_('Number of owners added'), -+ ), -+ ) -+ -+ -+@register() -+class vaultcontainer_remove_owner(VaultModMember, LDAPRemoveMember): -+ __doc__ = _('Remove owners from a vault container.') -+ -+ takes_options = LDAPRemoveMember.takes_options + vault_options -+ -+ member_attributes = ['owner'] -+ member_param_label = _('owner %s') -+ member_count_out = ('%i owner removed.', '%i owners removed.') -+ -+ has_output = ( -+ output.Entry('result'), -+ output.Output( -+ 'failed', -+ type=dict, -+ doc=_('Owners that could not be removed'), -+ ), -+ output.Output( -+ 'completed', -+ type=int, -+ doc=_('Number of owners removed'), -+ ), -+ ) -+ -+ - @register() - class vault(LDAPObject): - __doc__ = _(""" -@@ -1729,27 +1951,6 @@ class vault_retrieve_internal(PKQuery): - return response - - --class VaultModMember(LDAPModMember): -- def get_options(self): -- for param in super(VaultModMember, self).get_options(): -- if param.name == 'service' and param not in vault_options: -- param = param.clone_rename('services') -- yield param -- -- def get_member_dns(self, **options): -- if 'services' in options: -- options['service'] = options.pop('services') -- else: -- options.pop('service', None) -- return super(VaultModMember, self).get_member_dns(**options) -- -- def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): -- for fail in failed.itervalues(): -- fail['services'] = fail.pop('service', []) -- self.obj.get_container_attribute(entry_attrs, options) -- return completed, dn -- -- - @register() - class vault_add_owner(VaultModMember, LDAPAddMember): - __doc__ = _('Add owners to a vault.') --- -2.4.3 - diff --git a/SOURCES/0124-schema-cache-Store-and-check-info-for-pre-schema-ser.patch b/SOURCES/0124-schema-cache-Store-and-check-info-for-pre-schema-ser.patch new file mode 100644 index 0000000..a634f3b --- /dev/null +++ b/SOURCES/0124-schema-cache-Store-and-check-info-for-pre-schema-ser.patch @@ -0,0 +1,393 @@ +From 2618c2fbbd9e23f79a667ac373b0a828cdd5d643 Mon Sep 17 00:00:00 2001 +From: David Kupka +Date: Mon, 22 Aug 2016 13:34:30 +0200 +Subject: [PATCH] schema cache: Store and check info for pre-schema servers + +Cache CommandError answer to schema command to avoid sending the command +to pre-schema servers every time. This information expires after some +time (1 hour) in order to start using schema as soon as the server is +upgraded. + +https://fedorahosted.org/freeipa/ticket/6095 + +Signed-off-by: Jan Cholasta +Signed-off-by: David Kupka +Reviewed-By: Tomas Krizek +--- + ipaclient/remote_plugins/__init__.py | 80 +++++++++++++-------- + ipaclient/remote_plugins/compat.py | 9 ++- + ipaclient/remote_plugins/schema.py | 130 ++++++++++++++++++----------------- + 3 files changed, 128 insertions(+), 91 deletions(-) + +diff --git a/ipaclient/remote_plugins/__init__.py b/ipaclient/remote_plugins/__init__.py +index 2be9222be693a5c4a04a735c216f590d75c1ecfe..b783c32819e58f49532531b6d7f3a594c17bae16 100644 +--- a/ipaclient/remote_plugins/__init__.py ++++ b/ipaclient/remote_plugins/__init__.py +@@ -5,7 +5,9 @@ + import collections + import errno + import json ++import locale + import os ++import time + + from . import compat + from . import schema +@@ -23,20 +25,18 @@ class ServerInfo(collections.MutableMapping): + def __init__(self, api): + hostname = DNSName(api.env.server).ToASCII() + self._path = os.path.join(self._DIR, hostname) ++ self._force_check = api.env.force_schema_check + self._dict = {} +- self._dirty = False + +- self._read() +- +- def __enter__(self): +- return self +- +- def __exit__(self, *_exc_info): +- self.flush() ++ # copy-paste from ipalib/rpc.py ++ try: ++ self._language = ( ++ locale.setlocale(locale.LC_ALL, '').split('.')[0].lower() ++ ) ++ except locale.Error: ++ self._language = 'en_us' + +- def flush(self): +- if self._dirty: +- self._write() ++ self._read() + + def _read(self): + try: +@@ -62,13 +62,10 @@ class ServerInfo(collections.MutableMapping): + return self._dict[key] + + def __setitem__(self, key, value): +- if key not in self._dict or self._dict[key] != value: +- self._dirty = True + self._dict[key] = value + + def __delitem__(self, key): + del self._dict[key] +- self._dirty = True + + def __iter__(self): + return iter(self._dict) +@@ -76,26 +73,55 @@ class ServerInfo(collections.MutableMapping): + def __len__(self): + return len(self._dict) + ++ def update_validity(self, ttl=None): ++ if ttl is None: ++ ttl = 3600 ++ self['expiration'] = time.time() + ttl ++ self['language'] = self._language ++ self._write() ++ ++ def is_valid(self): ++ if self._force_check: ++ return False ++ ++ try: ++ expiration = self._dict['expiration'] ++ language = self._dict['language'] ++ except KeyError: ++ # if any of these is missing consider the entry expired ++ return False ++ ++ if expiration < time.time(): ++ # validity passed ++ return False ++ ++ if language != self._language: ++ # language changed since last check ++ return False ++ ++ return True ++ + + def get_package(api): + if api.env.in_tree: + from ipaserver import plugins + else: +- client = rpcclient(api) +- client.finalize() +- + try: +- server_info = api._server_info ++ plugins = api._remote_plugins + except AttributeError: +- server_info = api._server_info = ServerInfo(api) ++ server_info = ServerInfo(api) + +- try: +- plugins = schema.get_package(api, server_info, client) +- except schema.NotAvailable: +- plugins = compat.get_package(api, server_info, client) +- finally: +- server_info.flush() +- if client.isconnected(): +- client.disconnect() ++ client = rpcclient(api) ++ client.finalize() ++ ++ try: ++ plugins = schema.get_package(server_info, client) ++ except schema.NotAvailable: ++ plugins = compat.get_package(server_info, client) ++ finally: ++ if client.isconnected(): ++ client.disconnect() ++ ++ object.__setattr__(api, '_remote_plugins', plugins) + + return plugins +diff --git a/ipaclient/remote_plugins/compat.py b/ipaclient/remote_plugins/compat.py +index 5e08cb0ed73becbc17e724864d1a853142a5ef6f..984eecd3f86fada96084d70bbbeb81c3730346e8 100644 +--- a/ipaclient/remote_plugins/compat.py ++++ b/ipaclient/remote_plugins/compat.py +@@ -31,10 +31,15 @@ class CompatObject(Object): + pass + + +-def get_package(api, server_info, client): ++def get_package(server_info, client): + try: + server_version = server_info['version'] + except KeyError: ++ is_valid = False ++ else: ++ is_valid = server_info.is_valid() ++ ++ if not is_valid: + if not client.isconnected(): + client.connect(verbose=False) + env = client.forward(u'env', u'api_version', version=u'2.0') +@@ -51,6 +56,8 @@ def get_package(api, server_info, client): + else: + server_version = u'2.0' + server_info['version'] = server_version ++ server_info.update_validity() ++ + server_version = LooseVersion(server_version) + + package_names = {} +diff --git a/ipaclient/remote_plugins/schema.py b/ipaclient/remote_plugins/schema.py +index 553da35127188b1ae842a7a0b58433e632c82b9f..5634fd1c8fc9c4f9276b57eac2e4abecc8d7c792 100644 +--- a/ipaclient/remote_plugins/schema.py ++++ b/ipaclient/remote_plugins/schema.py +@@ -7,10 +7,8 @@ import contextlib + import errno + import fcntl + import json +-import locale + import os + import sys +-import time + import types + import zipfile + +@@ -220,7 +218,7 @@ class _SchemaPlugin(object): + + def __call__(self, api): + if self._class is None: +- schema = api._schema[self.schema_key][self.full_name] ++ schema = self._schema[self.schema_key][self.full_name] + name, bases, class_dict = self._create_class(api, schema) + self._class = type(name, bases, class_dict) + +@@ -361,7 +359,7 @@ class Schema(object): + namespaces = {'classes', 'commands', 'topics'} + _DIR = os.path.join(paths.USER_CACHE_PATH, 'ipa', 'schema', FORMAT) + +- def __init__(self, api, server_info, client): ++ def __init__(self, client, fingerprint=None): + self._dict = {} + self._namespaces = {} + self._help = None +@@ -371,48 +369,29 @@ class Schema(object): + self._dict[ns] = {} + self._namespaces[ns] = _SchemaNameSpace(self, ns) + +- # copy-paste from ipalib/rpc.py +- try: +- self._language = ( +- locale.setlocale(locale.LC_ALL, '').split('.')[0].lower() +- ) +- except locale.Error: +- # fallback to default locale +- self._language = 'en_us' +- +- try: +- self._fingerprint = server_info['fingerprint'] +- self._expiration = server_info['expiration'] +- language = server_info['language'] +- except KeyError: +- is_known = False +- else: +- is_known = (not api.env.force_schema_check and +- self._expiration > time.time() and +- self._language == language) ++ ttl = None ++ read_failed = False + +- if is_known: ++ if fingerprint is not None: + try: +- self._read_schema() +- except Exception: +- pass +- else: +- return +- +- try: +- self._fetch(client) +- except NotAvailable: +- raise +- except SchemaUpToDate as e: +- self._fingerprint = e.fingerprint +- self._expiration = time.time() + e.ttl +- self._read_schema() +- else: +- self._write_schema() ++ self._read_schema(fingerprint) ++ except Exception as e: ++ # Failed to read the schema from cache. There may be a lot of ++ # causes and not much we can do about it. Just ensure we will ++ # ignore the cache and fetch the schema from server. ++ logger.warning("Failed to read schema: {}".format(e)) ++ fingerprint = None ++ read_failed = True ++ ++ if fingerprint is None: ++ fingerprint, ttl = self._fetch(client, ignore_cache=read_failed) ++ try: ++ self._write_schema(fingerprint) ++ except Exception as e: ++ logger.warning("Failed to write schema: {}".format(e)) + +- server_info['fingerprint'] = self._fingerprint +- server_info['expiration'] = self._expiration +- server_info['language'] = self._language ++ self.fingerprint = fingerprint ++ self.ttl = ttl + + @contextlib.contextmanager + def _open(self, filename, mode): +@@ -429,14 +408,16 @@ class Schema(object): + finally: + fcntl.flock(f, fcntl.LOCK_UN) + +- def _fetch(self, client): ++ def _fetch(self, client, ignore_cache=False): + if not client.isconnected(): + client.connect(verbose=False) + +- try: +- fps = [fsdecode(f) for f in os.listdir(self._DIR)] +- except EnvironmentError: +- fps = [] ++ fps = [] ++ if not ignore_cache: ++ try: ++ fps = [fsdecode(f) for f in os.listdir(self._DIR)] ++ except EnvironmentError: ++ pass + + kwargs = {u'version': u'2.170'} + if fps: +@@ -459,12 +440,11 @@ class Schema(object): + logger.warning("Failed to fetch schema: %s", e) + raise NotAvailable() + +- self._fingerprint = fp +- self._expiration = time.time() + ttl ++ return (fp, ttl,) + +- def _read_schema(self): ++ def _read_schema(self, fingerprint): + self._file.truncate(0) +- with self._open(self._fingerprint, 'r') as f: ++ with self._open(fingerprint, 'r') as f: + self._file.write(f.read()) + + with zipfile.ZipFile(self._file, 'r') as schema: +@@ -500,13 +480,12 @@ class Schema(object): + + return halp + +- def _write_schema(self): ++ def _write_schema(self, fingerprint): + try: + os.makedirs(self._DIR) + except EnvironmentError as e: + if e.errno != errno.EEXIST: +- logger.warning("Failed to write schema: {}".format(e)) +- return ++ raise + + self._file.truncate(0) + with zipfile.ZipFile(self._file, 'w', zipfile.ZIP_DEFLATED) as schema: +@@ -523,7 +502,7 @@ class Schema(object): + json.dumps(self._generate_help(self._dict))) + + self._file.seek(0) +- with self._open(self._fingerprint, 'w') as f: ++ with self._open(fingerprint, 'w') as f: + f.truncate(0) + f.write(self._file.read()) + +@@ -550,14 +529,39 @@ class Schema(object): + return self._help[namespace][member] + + +-def get_package(api, server_info, client): +- try: +- schema = api._schema +- except AttributeError: +- schema = Schema(api, server_info, client) +- object.__setattr__(api, '_schema', schema) ++def get_package(server_info, client): ++ NO_FINGERPRINT = object() ++ ++ fingerprint = NO_FINGERPRINT ++ if server_info.is_valid(): ++ fingerprint = server_info.get('fingerprint', fingerprint) ++ ++ if fingerprint is not None: ++ try: ++ try: ++ if fingerprint is NO_FINGERPRINT: ++ schema = Schema(client) ++ else: ++ schema = Schema(client, fingerprint) ++ except SchemaUpToDate as e: ++ schema = Schema(client, e.fingerprint) ++ except NotAvailable: ++ fingerprint = None ++ ttl = None ++ except SchemaUpToDate as e: ++ fingerprint = e.fingerprint ++ ttl = e.ttl ++ else: ++ fingerprint = schema.fingerprint ++ ttl = schema.ttl ++ ++ server_info['fingerprint'] = fingerprint ++ server_info.update_validity(ttl) ++ ++ if fingerprint is None: ++ raise NotAvailable() + +- fingerprint = str(server_info['fingerprint']) ++ fingerprint = str(fingerprint) + package_name = '{}${}'.format(__name__, fingerprint) + package_dir = '{}${}'.format(os.path.splitext(__file__)[0], fingerprint) + +-- +2.7.4 + diff --git a/SOURCES/0124-vault-set-owner-to-current-user-on-container-creatio.patch b/SOURCES/0124-vault-set-owner-to-current-user-on-container-creatio.patch deleted file mode 100644 index 5c92146..0000000 --- a/SOURCES/0124-vault-set-owner-to-current-user-on-container-creatio.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 8defa7ddd68ade04f71254fc86762ac235721cce Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Thu, 3 Sep 2015 08:46:59 +0200 -Subject: [PATCH] vault: set owner to current user on container creation - -This reverts commit 419754b1c11139435ae5b5082a51026da0d5e730. - -https://fedorahosted.org/freeipa/ticket/5250 - -Reviewed-By: Petr Vobornik ---- - ipalib/plugins/vault.py | 21 +-------------------- - 1 file changed, 1 insertion(+), 20 deletions(-) - -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index 733741dfc2c87995055599cc3816f321ec344496..d9551c2f0cfc16973131c61db45bc606d2844fb6 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -981,27 +981,8 @@ class vault_add_internal(LDAPCreate): - - parent_dn = DN(*dn[1:]) - -- container_dn = DN(self.api.Object.vault.container_dn, -- self.api.env.basedn) -- -- services_dn = DN(('cn', 'services'), container_dn) -- users_dn = DN(('cn', 'users'), container_dn) -- -- if dn.endswith(services_dn): -- # service container should be owned by the service -- service = parent_dn[0]['cn'] -- parent_owner_dn = self.api.Object.service.get_dn(service) -- -- elif dn.endswith(users_dn): -- # user container should be owned by the user -- user = parent_dn[0]['cn'] -- parent_owner_dn = self.api.Object.user.get_dn(user) -- -- else: -- parent_owner_dn = owner_dn -- - try: -- self.obj.create_container(parent_dn, parent_owner_dn) -+ self.obj.create_container(parent_dn, owner_dn) - except errors.DuplicateEntry as e: - pass - --- -2.4.3 - diff --git a/SOURCES/0125-Fix-parse-errors-with-link-local-addresses.patch b/SOURCES/0125-Fix-parse-errors-with-link-local-addresses.patch new file mode 100644 index 0000000..146fff5 --- /dev/null +++ b/SOURCES/0125-Fix-parse-errors-with-link-local-addresses.patch @@ -0,0 +1,38 @@ +From fd11c06c34a45688c7609872b93413823f9ccb4d Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Mon, 5 Sep 2016 14:33:58 +0200 +Subject: [PATCH] Fix parse errors with link-local addresses + +Link-local addresses received from netifaces contains '%suffix' that +causes parse error in IPNetwork class. We must remove %suffix before +it us used in IPNetwork objects. + +https://fedorahosted.org/freeipa/ticket/6296 + +Reviewed-By: Tomas Krizek +--- + ipapython/ipautil.py | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py +index fdfebb65ecb8b62108852f6517b5ffb22fd7eedc..a099ea45747100946aa97bb5010ae58c49a089ba 100644 +--- a/ipapython/ipautil.py ++++ b/ipapython/ipautil.py +@@ -173,8 +173,13 @@ class CheckedIPAddress(UnsafeIPAddress): + iface = None + for interface in netifaces.interfaces(): + for ifdata in netifaces.ifaddresses(interface).get(family, []): ++ ++ # link-local addresses contain '%suffix' that causes parse ++ # errors in IPNetwork ++ ifaddr = ifdata['addr'].split(u'%', 1)[0] ++ + ifnet = netaddr.IPNetwork('{addr}/{netmask}'.format( +- addr=ifdata['addr'], ++ addr=ifaddr, + netmask=ifdata['netmask'] + )) + if ifnet == self._net or ( +-- +2.7.4 + diff --git a/SOURCES/0125-vault-update-access-control.patch b/SOURCES/0125-vault-update-access-control.patch deleted file mode 100644 index 7351dab..0000000 --- a/SOURCES/0125-vault-update-access-control.patch +++ /dev/null @@ -1,51 +0,0 @@ -From a2f2794513b30bb6b2cbdf96872e5d5904bf114d Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Thu, 3 Sep 2015 09:02:41 +0200 -Subject: [PATCH] vault: update access control - -Do not allow vault and container owners to manage owners. Allow adding vaults -and containers only if owner is set to the current user. - -https://fedorahosted.org/freeipa/ticket/5250 - -Reviewed-By: Petr Vobornik ---- - install/share/vault.update | 22 ++++++++++++++-------- - 1 file changed, 14 insertions(+), 8 deletions(-) - -diff --git a/install/share/vault.update b/install/share/vault.update -index 14421b5189efe9b3d9491e845e74debca6e18941..4f0023840b34c2d2bae4e362e34be1764c430ad1 100644 ---- a/install/share/vault.update -+++ b/install/share/vault.update -@@ -7,14 +7,20 @@ dn: cn=vaults,cn=kra,$SUFFIX - default: objectClass: top - default: objectClass: ipaVaultContainer - default: cn: vaults --default: aci: (target="ldap:///cn=*,cn=users,cn=vaults,cn=kra,$SUFFIX")(version 3.0; acl "Allow users to create private container"; allow (add) userdn = "ldap:///uid=($$attr.cn),cn=users,cn=accounts,$SUFFIX";) --default: aci: (target="ldap:///cn=*,cn=services,cn=vaults,cn=kra,$SUFFIX")(version 3.0; acl "Allow services to create private container"; allow (add) userdn = "ldap:///krbprincipalname=($$attr.cn)@$REALM,cn=services,cn=accounts,$SUFFIX";) --default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Container owners can manage vaults in the container"; allow(read, search, compare, add, delete) userattr="parent[1].owner#USERDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Indirect container owners can manage vaults in the container"; allow(read, search, compare, add, delete) userattr="parent[1].owner#GROUPDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Vault members can access the vault"; allow(read, search, compare) userattr="member#USERDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Indirect vault members can access the vault"; allow(read, search, compare) userattr="member#GROUPDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Vault owners can manage the vault"; allow(read, search, compare, write) userattr="owner#USERDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Indirect vault owners can manage the vault"; allow(read, search, compare, write) userattr="owner#GROUPDN";) -+default: aci: (target="ldap:///cn=*,cn=users,cn=vaults,cn=kra,$SUFFIX")(targetfilter="(objectClass=ipaVaultContainer)")(version 3.0; acl "Allow users to create private container"; allow(add) userdn="ldap:///uid=($$attr.cn),cn=users,cn=accounts,$SUFFIX" and userattr="owner#SELFDN";) -+default: aci: (target="ldap:///cn=*,cn=services,cn=vaults,cn=kra,$SUFFIX")(targetfilter="(objectClass=ipaVaultContainer)")(version 3.0; acl "Allow services to create private container"; allow(add) userdn="ldap:///krbprincipalname=($$attr.cn)@$REALM,cn=services,cn=accounts,$SUFFIX" and userattr="owner#SELFDN";) -+default: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description || owner")(version 3.0; acl "Container owners can access the container"; allow(read, search, compare) userattr="owner#USERDN";) -+default: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description || owner")(version 3.0; acl "Indirect container owners can access the container"; allow(read, search, compare) userattr="owner#GROUPDN";) -+default: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description")(version 3.0; acl "Container owners can manage the container"; allow(write, delete) userattr="owner#USERDN";) -+default: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description")(version 3.0; acl "Indirect container owners can manage the container"; allow(write, delete) userattr="owner#GROUPDN";) -+default: aci: (targetfilter="(objectClass=ipaVault)")(version 3.0; acl "Container owners can add vaults in the container"; allow(add) userattr="parent[1].owner#USERDN" and userattr="owner#SELFDN";) -+default: aci: (targetfilter="(objectClass=ipaVault)")(version 3.0; acl "Indirect container owners can add vaults in the container"; allow(add) userattr="parent[1].owner#GROUPDN" and userattr="owner#SELFDN";) -+default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || owner || member")(version 3.0; acl "Vault owners can access the vault"; allow(read, search, compare) userattr="owner#USERDN";) -+default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || owner || member")(version 3.0; acl "Indirect vault owners can access the vault"; allow(read, search, compare) userattr="owner#GROUPDN";) -+default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || owner || member")(version 3.0; acl "Vault members can access the vault"; allow(read, search, compare) userattr="member#USERDN";) -+default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || owner || member")(version 3.0; acl "Indirect vault members can access the vault"; allow(read, search, compare) userattr="member#GROUPDN";) -+default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || member")(version 3.0; acl "Vault owners can manage the vault"; allow(write, delete) userattr="owner#USERDN";) -+default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || member")(version 3.0; acl "Indirect vault owners can manage the vault"; allow(write, delete) userattr="owner#GROUPDN";) - - dn: cn=services,cn=vaults,cn=kra,$SUFFIX - default: objectClass: top --- -2.4.3 - diff --git a/SOURCES/0126-Add-support-for-additional-options-taken-from-table-.patch b/SOURCES/0126-Add-support-for-additional-options-taken-from-table-.patch new file mode 100644 index 0000000..957f4d7 --- /dev/null +++ b/SOURCES/0126-Add-support-for-additional-options-taken-from-table-.patch @@ -0,0 +1,104 @@ +From a5918fbd136d1b597e30629f66a3d69d567737f3 Mon Sep 17 00:00:00 2001 +From: Pavel Vomacka +Date: Fri, 26 Aug 2016 12:50:00 +0200 +Subject: [PATCH] Add support for additional options taken from table facet + +Sometimes the entity_show command must be called with options which are gathered +from result of entity_find command. These options needs to be passed as +arguments in URL which points to details page. + +This functionality is implemented to table facet. There is new property +'additional_navigation_arguments' which is prepared for array of attributes +which will be passed to URL. + +Part of: https://fedorahosted.org/freeipa/ticket/6238 + +Reviewed-By: Petr Vobornik +--- + install/ui/src/freeipa/facet.js | 49 ++++++++++++++++++++++++++++++++++++++++- + 1 file changed, 48 insertions(+), 1 deletion(-) + +diff --git a/install/ui/src/freeipa/facet.js b/install/ui/src/freeipa/facet.js +index 4553c5c65e6c334ed451e9c2f1a89ddc455d71c3..06eca189fa2c7b125fdfbd964e6192ddf709b2c8 100644 +--- a/install/ui/src/freeipa/facet.js ++++ b/install/ui/src/freeipa/facet.js +@@ -1819,6 +1819,15 @@ exp.table_facet = IPA.table_facet = function(spec, no_init) { + var that = IPA.facet(spec, no_init); + + /** ++ * Names of additional row attributes which will be send to another facet ++ * during navigation as URL parameters. ++ * ++ * @property {Array} ++ */ ++ that.additional_navigation_arguments = spec.additional_navigation_arguments; ++ ++ ++ /** + * Entity of data displayed in the table + * @property {entity.entity} + */ +@@ -2268,6 +2277,38 @@ exp.table_facet = IPA.table_facet = function(spec, no_init) { + + + /** ++ * Extract data from command response and return them. ++ * ++ * @param pkey {string} primary key of row which is chosen ++ * @param attrs {Array} names of attributes which will be extracted ++ */ ++ that.get_row_attribute_values = function(key, attrs) { ++ var result = that.data.result.result; ++ var options = {}; ++ var row; ++ ++ if (result) { ++ for (var i=0, l=result.length; i -Date: Thu, 3 Sep 2015 09:32:11 +0200 -Subject: [PATCH] vault: add permissions and administrator privilege - -https://fedorahosted.org/freeipa/ticket/5250 - -Reviewed-By: Petr Vobornik ---- - ACI.txt | 22 ++++++++ - install/updates/40-delegation.update | 8 +++ - ipalib/plugins/vault.py | 98 ++++++++++++++++++++++++++++++++++++ - 3 files changed, 128 insertions(+) - -diff --git a/ACI.txt b/ACI.txt -index 99099275e1383f16aca122e05e34b2330f4d06a3..40fa822217eaee8d0966491b10cdf7e0739a87ce 100644 ---- a/ACI.txt -+++ b/ACI.txt -@@ -338,6 +338,28 @@ dn: cn=users,cn=accounts,dc=ipa,dc=example - aci: (targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Remove Users";allow (delete) groupdn = "ldap:///cn=System: Remove Users,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: cn=users,cn=accounts,dc=ipa,dc=example - aci: (targetattr = "krblastadminunlock || krbloginfailedcount || nsaccountlock")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Unlock User";allow (write) groupdn = "ldap:///cn=System: Unlock User,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+dn: dc=ipa,dc=example -+aci: (target = "ldap:///cn=vaults,cn=kra,dc=ipa,dc=example")(targetfilter = "(objectclass=ipaVault)")(version 3.0;acl "permission:System: Add Vaults";allow (add) groupdn = "ldap:///cn=System: Add Vaults,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+dn: dc=ipa,dc=example -+aci: (target = "ldap:///cn=vaults,cn=kra,dc=ipa,dc=example")(targetfilter = "(objectclass=ipaVault)")(version 3.0;acl "permission:System: Delete Vaults";allow (delete) groupdn = "ldap:///cn=System: Delete Vaults,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+dn: dc=ipa,dc=example -+aci: (targetattr = "member")(target = "ldap:///cn=vaults,cn=kra,dc=ipa,dc=example")(targetfilter = "(objectclass=ipaVault)")(version 3.0;acl "permission:System: Manage Vault Membership";allow (write) groupdn = "ldap:///cn=System: Manage Vault Membership,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+dn: dc=ipa,dc=example -+aci: (targetattr = "owner")(target = "ldap:///cn=vaults,cn=kra,dc=ipa,dc=example")(targetfilter = "(objectclass=ipaVault)")(version 3.0;acl "permission:System: Manage Vault Ownership";allow (write) groupdn = "ldap:///cn=System: Manage Vault Ownership,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+dn: dc=ipa,dc=example -+aci: (targetattr = "cn || description || ipavaultpublickey || ipavaultsalt || ipavaulttype || objectclass")(target = "ldap:///cn=vaults,cn=kra,dc=ipa,dc=example")(targetfilter = "(objectclass=ipaVault)")(version 3.0;acl "permission:System: Modify Vaults";allow (write) groupdn = "ldap:///cn=System: Modify Vaults,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+dn: dc=ipa,dc=example -+aci: (targetattr = "cn || createtimestamp || description || entryusn || ipavaultpublickey || ipavaultsalt || ipavaulttype || member || memberhost || memberuser || modifytimestamp || objectclass || owner")(target = "ldap:///cn=vaults,cn=kra,dc=ipa,dc=example")(targetfilter = "(objectclass=ipaVault)")(version 3.0;acl "permission:System: Read Vaults";allow (compare,read,search) groupdn = "ldap:///cn=System: Read Vaults,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+dn: dc=ipa,dc=example -+aci: (target = "ldap:///cn=vaults,cn=kra,dc=ipa,dc=example")(targetfilter = "(objectclass=ipaVaultContainer)")(version 3.0;acl "permission:System: Add Vault Containers";allow (add) groupdn = "ldap:///cn=System: Add Vault Containers,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+dn: dc=ipa,dc=example -+aci: (target = "ldap:///cn=vaults,cn=kra,dc=ipa,dc=example")(targetfilter = "(objectclass=ipaVaultContainer)")(version 3.0;acl "permission:System: Delete Vault Containers";allow (delete) groupdn = "ldap:///cn=System: Delete Vault Containers,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+dn: dc=ipa,dc=example -+aci: (targetattr = "owner")(target = "ldap:///cn=vaults,cn=kra,dc=ipa,dc=example")(targetfilter = "(objectclass=ipaVaultContainer)")(version 3.0;acl "permission:System: Manage Vault Container Ownership";allow (write) groupdn = "ldap:///cn=System: Manage Vault Container Ownership,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+dn: dc=ipa,dc=example -+aci: (targetattr = "cn || description || objectclass")(target = "ldap:///cn=vaults,cn=kra,dc=ipa,dc=example")(targetfilter = "(objectclass=ipaVaultContainer)")(version 3.0;acl "permission:System: Modify Vault Containers";allow (write) groupdn = "ldap:///cn=System: Modify Vault Containers,cn=permissions,cn=pbac,dc=ipa,dc=example";) -+dn: dc=ipa,dc=example -+aci: (targetattr = "cn || createtimestamp || description || entryusn || modifytimestamp || objectclass || owner")(target = "ldap:///cn=vaults,cn=kra,dc=ipa,dc=example")(targetfilter = "(objectclass=ipaVaultContainer)")(version 3.0;acl "permission:System: Read Vault Containers";allow (compare,read,search) groupdn = "ldap:///cn=System: Read Vault Containers,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: cn=ca_renewal,cn=ipa,cn=etc,dc=ipa,dc=example - aci: (target = "ldap:///cn=caSigningCert cert-pki-ca,cn=ca_renewal,cn=ipa,cn=etc,dc=ipa,dc=example")(targetfilter = "(objectclass=pkiuser)")(version 3.0;acl "permission:System: Add CA Certificate For Renewal";allow (add) groupdn = "ldap:///cn=System: Add CA Certificate For Renewal,cn=permissions,cn=pbac,dc=ipa,dc=example";) - dn: cn=certificates,cn=ipa,cn=etc,dc=ipa,dc=example -diff --git a/install/updates/40-delegation.update b/install/updates/40-delegation.update -index 8d4f6296cbed7fcc968c2193022cb50b488c8561..08906a663c818695b8af29449c6ce8fab2dfdbee 100644 ---- a/install/updates/40-delegation.update -+++ b/install/updates/40-delegation.update -@@ -260,3 +260,11 @@ default:objectClass: groupofnames - default:objectClass: top - default:cn: CA Administrator - default:description: CA Administrator -+ -+# Vault Administrators -+dn: cn=Vault Administrators,cn=privileges,cn=pbac,$SUFFIX -+default:objectClass: nestedgroup -+default:objectClass: groupofnames -+default:objectClass: top -+default:cn: Vault Administrators -+default:description: Vault Administrators -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index d9551c2f0cfc16973131c61db45bc606d2844fb6..1159a84d58eb152cccdd791c96a1c876754bfa7d 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -289,6 +289,7 @@ class vaultcontainer(LDAPObject): - object_name = _('vaultcontainer') - object_name_plural = _('vaultcontainers') - object_class = ['ipaVaultContainer'] -+ permission_filter_objectclasses = ['ipaVaultContainer'] - - attribute_members = { - 'owner': ['user', 'group', 'service'], -@@ -297,6 +298,48 @@ class vaultcontainer(LDAPObject): - label = _('Vault Containers') - label_singular = _('Vault Container') - -+ managed_permissions = { -+ 'System: Read Vault Containers': { -+ 'ipapermlocation': api.env.basedn, -+ 'ipapermtarget': DN(api.env.container_vault, api.env.basedn), -+ 'ipapermright': {'read', 'search', 'compare'}, -+ 'ipapermdefaultattr': { -+ 'objectclass', 'cn', 'description', 'owner', -+ }, -+ 'default_privileges': {'Vault Administrators'}, -+ }, -+ 'System: Add Vault Containers': { -+ 'ipapermlocation': api.env.basedn, -+ 'ipapermtarget': DN(api.env.container_vault, api.env.basedn), -+ 'ipapermright': {'add'}, -+ 'default_privileges': {'Vault Administrators'}, -+ }, -+ 'System: Delete Vault Containers': { -+ 'ipapermlocation': api.env.basedn, -+ 'ipapermtarget': DN(api.env.container_vault, api.env.basedn), -+ 'ipapermright': {'delete'}, -+ 'default_privileges': {'Vault Administrators'}, -+ }, -+ 'System: Modify Vault Containers': { -+ 'ipapermlocation': api.env.basedn, -+ 'ipapermtarget': DN(api.env.container_vault, api.env.basedn), -+ 'ipapermright': {'write'}, -+ 'ipapermdefaultattr': { -+ 'objectclass', 'cn', 'description', -+ }, -+ 'default_privileges': {'Vault Administrators'}, -+ }, -+ 'System: Manage Vault Container Ownership': { -+ 'ipapermlocation': api.env.basedn, -+ 'ipapermtarget': DN(api.env.container_vault, api.env.basedn), -+ 'ipapermright': {'write'}, -+ 'ipapermdefaultattr': { -+ 'owner', -+ }, -+ 'default_privileges': {'Vault Administrators'}, -+ }, -+ } -+ - takes_params = ( - Str( - 'owner_user?', -@@ -491,6 +534,7 @@ class vault(LDAPObject): - object_name_plural = _('vaults') - - object_class = ['ipaVault'] -+ permission_filter_objectclasses = ['ipaVault'] - default_attributes = [ - 'cn', - 'description', -@@ -513,6 +557,60 @@ class vault(LDAPObject): - label = _('Vaults') - label_singular = _('Vault') - -+ managed_permissions = { -+ 'System: Read Vaults': { -+ 'ipapermlocation': api.env.basedn, -+ 'ipapermtarget': DN(api.env.container_vault, api.env.basedn), -+ 'ipapermright': {'read', 'search', 'compare'}, -+ 'ipapermdefaultattr': { -+ 'objectclass', 'cn', 'description', 'ipavaulttype', -+ 'ipavaultsalt', 'ipavaultpublickey', 'owner', 'member', -+ 'memberuser', 'memberhost', -+ }, -+ 'default_privileges': {'Vault Administrators'}, -+ }, -+ 'System: Add Vaults': { -+ 'ipapermlocation': api.env.basedn, -+ 'ipapermtarget': DN(api.env.container_vault, api.env.basedn), -+ 'ipapermright': {'add'}, -+ 'default_privileges': {'Vault Administrators'}, -+ }, -+ 'System: Delete Vaults': { -+ 'ipapermlocation': api.env.basedn, -+ 'ipapermtarget': DN(api.env.container_vault, api.env.basedn), -+ 'ipapermright': {'delete'}, -+ 'default_privileges': {'Vault Administrators'}, -+ }, -+ 'System: Modify Vaults': { -+ 'ipapermlocation': api.env.basedn, -+ 'ipapermtarget': DN(api.env.container_vault, api.env.basedn), -+ 'ipapermright': {'write'}, -+ 'ipapermdefaultattr': { -+ 'objectclass', 'cn', 'description', 'ipavaulttype', -+ 'ipavaultsalt', 'ipavaultpublickey', -+ }, -+ 'default_privileges': {'Vault Administrators'}, -+ }, -+ 'System: Manage Vault Ownership': { -+ 'ipapermlocation': api.env.basedn, -+ 'ipapermtarget': DN(api.env.container_vault, api.env.basedn), -+ 'ipapermright': {'write'}, -+ 'ipapermdefaultattr': { -+ 'owner', -+ }, -+ 'default_privileges': {'Vault Administrators'}, -+ }, -+ 'System: Manage Vault Membership': { -+ 'ipapermlocation': api.env.basedn, -+ 'ipapermtarget': DN(api.env.container_vault, api.env.basedn), -+ 'ipapermright': {'write'}, -+ 'ipapermdefaultattr': { -+ 'member', -+ }, -+ 'default_privileges': {'Vault Administrators'}, -+ }, -+ } -+ - takes_params = ( - Str( - 'cn', --- -2.4.3 - diff --git a/SOURCES/0127-WebUI-Fix-showing-certificates-issued-by-sub-CA.patch b/SOURCES/0127-WebUI-Fix-showing-certificates-issued-by-sub-CA.patch new file mode 100644 index 0000000..85f7b6d --- /dev/null +++ b/SOURCES/0127-WebUI-Fix-showing-certificates-issued-by-sub-CA.patch @@ -0,0 +1,57 @@ +From f718361b95258244df1d26b5f15d3a8098259939 Mon Sep 17 00:00:00 2001 +From: Pavel Vomacka +Date: Fri, 26 Aug 2016 13:03:58 +0200 +Subject: [PATCH] WebUI: Fix showing certificates issued by sub-CA + +The cert-show command needs to be called with cacn option. Cacn option is +passed using URL attribute. + +https://fedorahosted.org/freeipa/ticket/6238 + +Reviewed-By: Petr Vobornik +--- + install/ui/src/freeipa/certificate.js | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/install/ui/src/freeipa/certificate.js b/install/ui/src/freeipa/certificate.js +index 232bdbf2fa95c3a68943539cd80129d481d8563a..e67c348b7edbd2e273f18ed1df40ef8b5b5e59c3 100755 +--- a/install/ui/src/freeipa/certificate.js ++++ b/install/ui/src/freeipa/certificate.js +@@ -1543,6 +1543,7 @@ return { + row_enabled_attribute: 'status', + facet_groups: [exp.facet_group], + facet_group: 'certificates', ++ additional_navigation_arguments: [ 'cacn' ], + pagination: false, + no_update: true, + columns: [ +@@ -1552,6 +1553,7 @@ return { + width: '90px' + }, + 'subject', ++ 'cacn', + { + name: 'status', + width: '120px' +@@ -1645,6 +1647,7 @@ return { + fields: [ + 'serial_number', + 'serial_number_hex', ++ 'cacn', + 'subject', + { + name: 'issuer', +@@ -1772,6 +1775,10 @@ IPA.cert.details_facet = function(spec, no_init) { + var command = that.details_facet_create_refresh_command(); + delete command.options.all; + delete command.options.rights; ++ ++ command.options = command.options || {}; ++ $.extend(command.options, { cacn: that.state.cacn }); ++ + return command; + }; + +-- +2.7.4 + diff --git a/SOURCES/0127-install-support-KRA-update.patch b/SOURCES/0127-install-support-KRA-update.patch deleted file mode 100644 index 449803d..0000000 --- a/SOURCES/0127-install-support-KRA-update.patch +++ /dev/null @@ -1,213 +0,0 @@ -From 78eaf8b944f1b8f177aedabeaaeaa72c1dc4091e Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Mon, 14 Sep 2015 07:56:44 +0200 -Subject: [PATCH] install: support KRA update - -https://fedorahosted.org/freeipa/ticket/5250 - -Reviewed-By: Petr Vobornik ---- - freeipa.spec.in | 1 - - install/share/Makefile.am | 2 +- - install/share/vault.ldif | 29 +++++++++++++++++++++++++++++ - install/share/vault.update | 38 -------------------------------------- - install/updates/40-vault.update | 23 +++++++++++++++++++++++ - install/updates/Makefile.am | 1 + - ipaplatform/base/paths.py | 1 - - ipaserver/install/krainstance.py | 7 ++++++- - 8 files changed, 60 insertions(+), 42 deletions(-) - create mode 100644 install/share/vault.ldif - delete mode 100644 install/share/vault.update - create mode 100644 install/updates/40-vault.update - -diff --git a/freeipa.spec.in b/freeipa.spec.in -index e9ba596fec1f8d179d4f834485e35a4814db898d..d8e24a5af47fbfca89ccb9c3d07dcfca5a8073d9 100644 ---- a/freeipa.spec.in -+++ b/freeipa.spec.in -@@ -746,7 +746,6 @@ fi - %{_usr}/share/ipa/copy-schema-to-ca.py* - %{_usr}/share/ipa/*.ldif - %{_usr}/share/ipa/*.uldif --%{_usr}/share/ipa/*.update - %{_usr}/share/ipa/*.template - %dir %{_usr}/share/ipa/advise - %dir %{_usr}/share/ipa/advise/legacy -diff --git a/install/share/Makefile.am b/install/share/Makefile.am -index 80e959a751a0800c4d56c379a73b68a2f12570d7..d68c40e693a1d86c70d8ccd81ef2c915b2e1f61e 100644 ---- a/install/share/Makefile.am -+++ b/install/share/Makefile.am -@@ -83,7 +83,7 @@ app_DATA = \ - copy-schema-to-ca.py \ - sasl-mapping-fallback.ldif \ - schema-update.ldif \ -- vault.update \ -+ vault.ldif \ - kdcproxy.conf \ - kdcproxy-enable.uldif \ - kdcproxy-disable.uldif \ -diff --git a/install/share/vault.ldif b/install/share/vault.ldif -new file mode 100644 -index 0000000000000000000000000000000000000000..06dd83c5c45bd3143b8374965b9a02d311afdb42 ---- /dev/null -+++ b/install/share/vault.ldif -@@ -0,0 +1,29 @@ -+dn: cn=kra,$SUFFIX -+changetype: add -+objectClass: top -+objectClass: nsContainer -+cn: kra -+ -+dn: cn=vaults,cn=kra,$SUFFIX -+changetype: add -+objectClass: top -+objectClass: ipaVaultContainer -+cn: vaults -+ -+dn: cn=services,cn=vaults,cn=kra,$SUFFIX -+changetype: add -+objectClass: top -+objectClass: ipaVaultContainer -+cn: services -+ -+dn: cn=shared,cn=vaults,cn=kra,$SUFFIX -+changetype: add -+objectClass: top -+objectClass: ipaVaultContainer -+cn: shared -+ -+dn: cn=users,cn=vaults,cn=kra,$SUFFIX -+changetype: add -+objectClass: top -+objectClass: ipaVaultContainer -+cn: users -diff --git a/install/share/vault.update b/install/share/vault.update -deleted file mode 100644 -index 4f0023840b34c2d2bae4e362e34be1764c430ad1..0000000000000000000000000000000000000000 ---- a/install/share/vault.update -+++ /dev/null -@@ -1,38 +0,0 @@ --dn: cn=kra,$SUFFIX --default: objectClass: top --default: objectClass: nsContainer --default: cn: kra -- --dn: cn=vaults,cn=kra,$SUFFIX --default: objectClass: top --default: objectClass: ipaVaultContainer --default: cn: vaults --default: aci: (target="ldap:///cn=*,cn=users,cn=vaults,cn=kra,$SUFFIX")(targetfilter="(objectClass=ipaVaultContainer)")(version 3.0; acl "Allow users to create private container"; allow(add) userdn="ldap:///uid=($$attr.cn),cn=users,cn=accounts,$SUFFIX" and userattr="owner#SELFDN";) --default: aci: (target="ldap:///cn=*,cn=services,cn=vaults,cn=kra,$SUFFIX")(targetfilter="(objectClass=ipaVaultContainer)")(version 3.0; acl "Allow services to create private container"; allow(add) userdn="ldap:///krbprincipalname=($$attr.cn)@$REALM,cn=services,cn=accounts,$SUFFIX" and userattr="owner#SELFDN";) --default: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description || owner")(version 3.0; acl "Container owners can access the container"; allow(read, search, compare) userattr="owner#USERDN";) --default: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description || owner")(version 3.0; acl "Indirect container owners can access the container"; allow(read, search, compare) userattr="owner#GROUPDN";) --default: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description")(version 3.0; acl "Container owners can manage the container"; allow(write, delete) userattr="owner#USERDN";) --default: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description")(version 3.0; acl "Indirect container owners can manage the container"; allow(write, delete) userattr="owner#GROUPDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(version 3.0; acl "Container owners can add vaults in the container"; allow(add) userattr="parent[1].owner#USERDN" and userattr="owner#SELFDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(version 3.0; acl "Indirect container owners can add vaults in the container"; allow(add) userattr="parent[1].owner#GROUPDN" and userattr="owner#SELFDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || owner || member")(version 3.0; acl "Vault owners can access the vault"; allow(read, search, compare) userattr="owner#USERDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || owner || member")(version 3.0; acl "Indirect vault owners can access the vault"; allow(read, search, compare) userattr="owner#GROUPDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || owner || member")(version 3.0; acl "Vault members can access the vault"; allow(read, search, compare) userattr="member#USERDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || owner || member")(version 3.0; acl "Indirect vault members can access the vault"; allow(read, search, compare) userattr="member#GROUPDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || member")(version 3.0; acl "Vault owners can manage the vault"; allow(write, delete) userattr="owner#USERDN";) --default: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || member")(version 3.0; acl "Indirect vault owners can manage the vault"; allow(write, delete) userattr="owner#GROUPDN";) -- --dn: cn=services,cn=vaults,cn=kra,$SUFFIX --default: objectClass: top --default: objectClass: ipaVaultContainer --default: cn: services -- --dn: cn=shared,cn=vaults,cn=kra,$SUFFIX --default: objectClass: top --default: objectClass: ipaVaultContainer --default: cn: shared -- --dn: cn=users,cn=vaults,cn=kra,$SUFFIX --default: objectClass: top --default: objectClass: ipaVaultContainer --default: cn: users -diff --git a/install/updates/40-vault.update b/install/updates/40-vault.update -new file mode 100644 -index 0000000000000000000000000000000000000000..3daea5b1988333d4d482463af0eec4163e4f0760 ---- /dev/null -+++ b/install/updates/40-vault.update -@@ -0,0 +1,23 @@ -+dn: cn=vaults,cn=kra,$SUFFIX -+remove: aci: (target="ldap:///cn=*,cn=users,cn=vaults,cn=kra,$SUFFIX")(version 3.0; acl "Allow users to create private container"; allow (add) userdn = "ldap:///uid=($$attr.cn),cn=users,cn=accounts,$SUFFIX";) -+remove: aci: (target="ldap:///cn=*,cn=services,cn=vaults,cn=kra,$SUFFIX")(version 3.0; acl "Allow services to create private container"; allow (add) userdn = "ldap:///krbprincipalname=($$attr.cn)@$REALM,cn=services,cn=accounts,$SUFFIX";) -+remove: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Container owners can manage vaults in the container"; allow(read, search, compare, add, delete) userattr="parent[1].owner#USERDN";) -+remove: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Indirect container owners can manage vaults in the container"; allow(read, search, compare, add, delete) userattr="parent[1].owner#GROUPDN";) -+remove: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Vault members can access the vault"; allow(read, search, compare) userattr="member#USERDN";) -+remove: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Indirect vault members can access the vault"; allow(read, search, compare) userattr="member#GROUPDN";) -+remove: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Vault owners can manage the vault"; allow(read, search, compare, write) userattr="owner#USERDN";) -+remove: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Indirect vault owners can manage the vault"; allow(read, search, compare, write) userattr="owner#GROUPDN";) -+addifexist: aci: (target="ldap:///cn=*,cn=users,cn=vaults,cn=kra,$SUFFIX")(targetfilter="(objectClass=ipaVaultContainer)")(version 3.0; acl "Allow users to create private container"; allow(add) userdn="ldap:///uid=($$attr.cn),cn=users,cn=accounts,$SUFFIX" and userattr="owner#SELFDN";) -+addifexist: aci: (target="ldap:///cn=*,cn=services,cn=vaults,cn=kra,$SUFFIX")(targetfilter="(objectClass=ipaVaultContainer)")(version 3.0; acl "Allow services to create private container"; allow(add) userdn="ldap:///krbprincipalname=($$attr.cn)@$REALM,cn=services,cn=accounts,$SUFFIX" and userattr="owner#SELFDN";) -+addifexist: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description || owner")(version 3.0; acl "Container owners can access the container"; allow(read, search, compare) userattr="owner#USERDN";) -+addifexist: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description || owner")(version 3.0; acl "Indirect container owners can access the container"; allow(read, search, compare) userattr="owner#GROUPDN";) -+addifexist: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description")(version 3.0; acl "Container owners can manage the container"; allow(write, delete) userattr="owner#USERDN";) -+addifexist: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description")(version 3.0; acl "Indirect container owners can manage the container"; allow(write, delete) userattr="owner#GROUPDN";) -+addifexist: aci: (targetfilter="(objectClass=ipaVault)")(version 3.0; acl "Container owners can add vaults in the container"; allow(add) userattr="parent[1].owner#USERDN" and userattr="owner#SELFDN";) -+addifexist: aci: (targetfilter="(objectClass=ipaVault)")(version 3.0; acl "Indirect container owners can add vaults in the container"; allow(add) userattr="parent[1].owner#GROUPDN" and userattr="owner#SELFDN";) -+addifexist: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || owner || member")(version 3.0; acl "Vault owners can access the vault"; allow(read, search, compare) userattr="owner#USERDN";) -+addifexist: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || owner || member")(version 3.0; acl "Indirect vault owners can access the vault"; allow(read, search, compare) userattr="owner#GROUPDN";) -+addifexist: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || owner || member")(version 3.0; acl "Vault members can access the vault"; allow(read, search, compare) userattr="member#USERDN";) -+addifexist: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || owner || member")(version 3.0; acl "Indirect vault members can access the vault"; allow(read, search, compare) userattr="member#GROUPDN";) -+addifexist: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || member")(version 3.0; acl "Vault owners can manage the vault"; allow(write, delete) userattr="owner#USERDN";) -+addifexist: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="objectClass || cn || description || ipaVaultType || ipaVaultSalt || ipaVaultPublicKey || member")(version 3.0; acl "Indirect vault owners can manage the vault"; allow(write, delete) userattr="owner#GROUPDN";) -diff --git a/install/updates/Makefile.am b/install/updates/Makefile.am -index 1f4a91c9bb4222f99ad7a7ad16e376aeef7f525b..26e4c04ed66a4a2061a3bb3ca2f4a6cd84502598 100644 ---- a/install/updates/Makefile.am -+++ b/install/updates/Makefile.am -@@ -34,6 +34,7 @@ app_DATA = \ - 40-automember.update \ - 40-certprofile.update \ - 40-otp.update \ -+ 40-vault.update \ - 41-caacl.update \ - 45-roles.update \ - 50-7_bit_check.update \ -diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py -index ff75e0d7a5a0250ce71e67b0302bbaab64c5e935..3930c93fcba06959dd34507ecc29f92e33637775 100644 ---- a/ipaplatform/base/paths.py -+++ b/ipaplatform/base/paths.py -@@ -251,7 +251,6 @@ class BasePathNamespace(object): - SCHEMA_COMPAT_ULDIF = "/usr/share/ipa/schema_compat.uldif" - IPA_JS_PLUGINS_DIR = "/usr/share/ipa/ui/js/plugins" - UPDATES_DIR = "/usr/share/ipa/updates/" -- VAULT_UPDATE = "/usr/share/ipa/vault.update" - PKI_CONF_SERVER_XML_TEMPLATE = "/usr/share/pki/%s/conf/server.xml" - CACHE_IPA_SESSIONS = "/var/cache/ipa/sessions" - VAR_KERBEROS_KRB5KDC_DIR = "/var/kerberos/krb5kdc/" -diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py -index 958fe6fb095e69f83342ce8299d1586b8bbacd47..48268b0be5331cced1aee6b7f3358333b65de6dd 100644 ---- a/ipaserver/install/krainstance.py -+++ b/ipaserver/install/krainstance.py -@@ -124,6 +124,7 @@ class KRAInstance(DogtagInstance): - self.step("configure HTTP to proxy connections", - self.http_proxy) - self.step("add vault container", self.__add_vault_container) -+ self.step("apply LDAP updates", self.__apply_updates) - - self.start_creation(runtime=126) - -@@ -313,13 +314,17 @@ class KRAInstance(DogtagInstance): - conn.disconnect() - - def __add_vault_container(self): -+ self._ldap_mod('vault.ldif', {'SUFFIX': self.suffix}) -+ self.ldap_disconnect() -+ -+ def __apply_updates(self): - sub_dict = { - 'SUFFIX': self.suffix, - } - - ld = ldapupdate.LDAPUpdate(dm_password=self.dm_password, - sub_dict=sub_dict) -- ld.update([paths.VAULT_UPDATE]) -+ ld.update([os.path.join(paths.UPDATES_DIR, '40-vault.update')]) - - @staticmethod - def update_cert_config(nickname, cert, dogtag_constants=None): --- -2.4.3 - diff --git a/SOURCES/0128-WebUI-add-support-for-sub-CAs-while-revoking-certifi.patch b/SOURCES/0128-WebUI-add-support-for-sub-CAs-while-revoking-certifi.patch new file mode 100644 index 0000000..5d1de8c --- /dev/null +++ b/SOURCES/0128-WebUI-add-support-for-sub-CAs-while-revoking-certifi.patch @@ -0,0 +1,252 @@ +From f5efedd4c4f25e423e83c45efdc779fa567eb451 Mon Sep 17 00:00:00 2001 +From: Pavel Vomacka +Date: Fri, 26 Aug 2016 13:11:22 +0200 +Subject: [PATCH] WebUI add support for sub-CAs while revoking certificates + +Also the same for removing certificate hold. + +https://fedorahosted.org/freeipa/ticket/6216 + +Reviewed-By: Petr Vobornik +Reviewed-By: Stanislav Laznicka +--- + install/ui/src/freeipa/certificate.js | 129 ++++++++++++++++++++++++++-------- + install/ui/src/freeipa/widget.js | 1 + + 2 files changed, 100 insertions(+), 30 deletions(-) + +diff --git a/install/ui/src/freeipa/certificate.js b/install/ui/src/freeipa/certificate.js +index e67c348b7edbd2e273f18ed1df40ef8b5b5e59c3..9ab40027817cdcc242762399a0b4d9f41afec0b7 100755 +--- a/install/ui/src/freeipa/certificate.js ++++ b/install/ui/src/freeipa/certificate.js +@@ -244,44 +244,104 @@ IPA.cert.download_dialog = function(spec) { + return that; + }; + +-IPA.cert.revoke_dialog = function(spec) { ++IPA.cert.revocation_reason_select_widget = function(spec) { ++ spec = spec || {}; ++ ++ var that = IPA.select_widget(spec); ++ ++ that.create_options = function() { ++ for (var i=0; i').appendTo(td); +- for (var i=0; i', { +- 'value': i, +- 'html': text.get('@i18n:objects.cert.'+reason) +- }).appendTo(that.select); +- } ++ that.init = function() { ++ var note = text.get('@i18n:objects.cert.revoke_confirmation'); ++ that.widgets.get_widget('note.note').html = note; + }; + ++ if (!no_init) that.init(); ++ + return that; + }; + +@@ -718,7 +778,7 @@ IPA.cert.request_action = function(spec) { + return that; + }; + +-IPA.cert.perform_revoke = function(spec, sn, revocation_reason) { ++IPA.cert.perform_revoke = function(spec, sn, revocation_reason, cacn) { + + spec.hide_activity_icon = spec.hide_activity_icon || false; + +@@ -728,7 +788,8 @@ IPA.cert.perform_revoke = function(spec, sn, revocation_reason) { + hide_activity_icon: spec.hide_activity_icon, + args: [ sn ], + options: { +- 'revocation_reason': revocation_reason ++ revocation_reason: revocation_reason, ++ cacn: cacn + }, + notify_activity_start: spec.notify_activity_start, + notify_activity_end: spec.notify_activity_end, +@@ -782,7 +843,8 @@ IPA.cert.revoke_action = function(spec) { + + var sn = facet.certificate.serial_number; + var revocation_reason = that.dialog.get_reason(); +- IPA.cert.perform_revoke(spec, sn, revocation_reason); ++ var cacn = that.dialog.get_cacn(); ++ IPA.cert.perform_revoke(spec, sn, revocation_reason, cacn); + }; + + return that; +@@ -835,19 +897,22 @@ IPA.cert.remove_hold_action = function(spec) { + } + }; + +- IPA.cert.perform_remove_hold(spec, facet.certificate.serial_number); +- ++ IPA.cert.perform_remove_hold(spec, facet.certificate.serial_number, ++ facet.state.cacn); + }; + + return that; + }; + +-IPA.cert.perform_remove_hold = function(spec, sn) { ++IPA.cert.perform_remove_hold = function(spec, sn, cacn) { + + rpc.command({ + entity: 'cert', + method: 'remove_hold', + args: [sn], ++ options: { ++ cacn: cacn ++ }, + on_success: spec.on_success + }).execute(); + }; +@@ -1360,13 +1425,15 @@ IPA.cert.cert_widget = function(spec) { + }; + + var sn = that.certificate.serial_number; ++ var cacn = dialog.get_cacn(); + var revocation_reason = dialog.get_reason(); +- IPA.cert.perform_revoke(command_spec, sn, revocation_reason); ++ IPA.cert.perform_revoke(command_spec, sn, revocation_reason, cacn); + } + }; + + var dialog = IPA.cert.revoke_dialog(spec); + dialog.open(); ++ dialog.set_cacn(that.certificate.cacn); + }; + + that.perform_remove_hold = function() { +@@ -1392,7 +1459,8 @@ IPA.cert.cert_widget = function(spec) { + }; + + var sn = that.certificate.serial_number; +- IPA.cert.perform_remove_hold(command_spec, sn); ++ var cacn = that.certificate.cacn; ++ IPA.cert.perform_remove_hold(command_spec, sn, cacn); + } + }; + +@@ -1834,6 +1902,7 @@ exp.register = function() { + f.register('certificate_status', IPA.cert.status_field); + f.register('revocation_reason', IPA.revocation_reason_field); + w.register('revocation_reason', IPA.text_widget); ++ w.register('revocation_reason_select', IPA.cert.revocation_reason_select_widget); + + a.register('cert_request', IPA.cert.request_action); + a.register('download_cert', IPA.cert.download_action); +diff --git a/install/ui/src/freeipa/widget.js b/install/ui/src/freeipa/widget.js +index 9151ebac9438e9e674f81bfb1ccfe7a63872b1ae..4769ca616e4337e8f10339048f9851252e6dfd2e 100644 +--- a/install/ui/src/freeipa/widget.js ++++ b/install/ui/src/freeipa/widget.js +@@ -2878,6 +2878,7 @@ IPA.select_widget = function(spec) { + // methods that should be invoked by subclasses + that.select_save = that.save; + that.select_update = that.update; ++ that.select_create_options = that.create_options; + + return that; + }; +-- +2.7.4 + diff --git a/SOURCES/0128-webui-use-manual-Firefox-configuration-for-Firefox-4.patch b/SOURCES/0128-webui-use-manual-Firefox-configuration-for-Firefox-4.patch deleted file mode 100644 index d0ee5e0..0000000 --- a/SOURCES/0128-webui-use-manual-Firefox-configuration-for-Firefox-4.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 27f97386a0259a8b12700e5d671a2de86c98661f Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Thu, 17 Sep 2015 17:41:06 +0200 -Subject: [PATCH] webui: use manual Firefox configuration for Firefox >= 40 - -The intended course of action is to show manual configuration in -browserconfig.html instead of configuration with the extension -for versions of Firefox >= 40. - -The reasoning is: -* plan for enterprise environments was not published yet which - forces as to use AMO (addons.mozilla.org) -* with AMO the user experience is worse than a manual configuration - -steps for AMO: -* go to AMO page -* installed the extension -* go back to IPA page -* probably refresh -* click configure -* confirm - -manual config: -* go to about:config -* set network.negotiate-auth.trusted-uris with *domain.name - -https://fedorahosted.org/freeipa/ticket/4906 - -Reviewed-By: Martin Basti ---- - install/html/browserconfig.html | 25 ++++++++++++++++++++++--- - install/html/ffconfig_page.js | 24 +++++++++++++++++++++--- - 2 files changed, 43 insertions(+), 6 deletions(-) - -diff --git a/install/html/browserconfig.html b/install/html/browserconfig.html -index d721a4ad2a3b684a4bf45602584fee78f4613360..9c5cf68211281723e12b518f346aac43c1541cdc 100644 ---- a/install/html/browserconfig.html -+++ b/install/html/browserconfig.html -@@ -69,7 +69,7 @@ -

- - --

-+ - --
-+ - -+
-+

Step 2

-+
    -+
  1. -+ In the address bar of Firefox, type about:config to display the list of current configuration options. -+
  2. -+
  3. -+ In the Filter field, type negotiate to restrict the list of options. -+
  4. -+
  5. -+ Double-click the network.negotiate-auth.trusted-uris entry to display the Enter string value dialog box. -+
  6. -+
  7. -+ Enter the name of the domain against which you want to authenticate, for example, .example.com. -+
  8. -+
-+
-+ -
--

Step 4

-+ -+

Step 3

-

Return to Web UI

-
-
-diff --git a/install/html/ffconfig_page.js b/install/html/ffconfig_page.js -index 4e59db0aa5424d3c664d3d651843b26b440d50a9..536332ee8358fb007da840b587df92e627dd7b58 100644 ---- a/install/html/ffconfig_page.js -+++ b/install/html/ffconfig_page.js -@@ -87,7 +87,7 @@ - - if (!browser.mozilla) { - $('#wrongbrowser').show(); -- set_enabled(['#step1', '#step2', '#step3'], false); -+ set_enabled(['#step2b'], false); - } else { - // Disable for all version of FF older than 15. Theoretically - // the extension is compatible with version 3.6, 10 and later -@@ -95,8 +95,26 @@ - // resource from chrome.manifest - if (compare_version(browser.version, '15') === -1) { - $('#step2a').show(); -- set_enabled(['#step2', '#step3'], false); -- }// else if (compare_version(version, '15') === -1) { -+ $('#step2').show(); -+ $('#step3').show(); -+ $('#step4header').show(); -+ $('#step3bheader').hide(); -+ set_enabled(['#step2', '#step3', '#step2b'], false); -+ } else if (compare_version(browser.version, '40') === -1) { -+ // FF is > 15 < 40 -+ // show krb extension method -+ $('#step2').show(); -+ $('#step3').show(); -+ $('#step4header').show(); -+ $('#step3bheader').hide(); -+ $('#step2b').hide(); -+ } -+ // else -+ // Firefox since version 40 has new extension signing policy -+ // this policy prevents to use self-signed FF extension and -+ // thus a manual config is needed - which is the default (step2b) -+ -+ // else if (compare_version(version, '15') === -1) { - // $('#step2a').show(); - // $('#older-compatible').show(); - // $('#older-required').hide(); --- -2.4.3 - diff --git a/SOURCES/0129-cert-fix-cert-find-certificate-when-the-cert-is-not-.patch b/SOURCES/0129-cert-fix-cert-find-certificate-when-the-cert-is-not-.patch new file mode 100644 index 0000000..49e9537 --- /dev/null +++ b/SOURCES/0129-cert-fix-cert-find-certificate-when-the-cert-is-not-.patch @@ -0,0 +1,46 @@ +From 95a8519afa82707c8d3b2e60f65cbc4d79d144e2 Mon Sep 17 00:00:00 2001 +From: Jan Cholasta +Date: Wed, 7 Sep 2016 08:06:10 +0200 +Subject: [PATCH] cert: fix cert-find --certificate when the cert is not in + LDAP + +Always return the cert specified in --certificate in cert-find result, even +when the cert is not found in LDAP. + +https://fedorahosted.org/freeipa/ticket/6304 + +Reviewed-By: David Kupka +--- + ipaserver/plugins/cert.py | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py +index 6495bf1491f939a032fad03fe4ef86839c0575ef..00bae4560d601e28e0b983786bff9144bcc1b065 100644 +--- a/ipaserver/plugins/cert.py ++++ b/ipaserver/plugins/cert.py +@@ -1142,17 +1142,15 @@ class cert_find(Search, CertMethod): + rule) + filters.append(filter) + +- cert = options.get('certificate') +- if cert is not None: +- filter = ldap.make_filter_from_attr('usercertificate', cert) +- filters.append(filter) +- + result = collections.OrderedDict() + complete = bool(filters) + +- if cert is None: ++ cert = options.get('certificate') ++ if cert is not None: ++ filter = ldap.make_filter_from_attr('usercertificate', cert) ++ else: + filter = '(usercertificate=*)' +- filters.append(filter) ++ filters.append(filter) + + filter = ldap.combine_filters(filters, ldap.MATCH_ALL) + try: +-- +2.7.4 + diff --git a/SOURCES/0129-ipa-backup-Add-mechanism-to-store-empty-directory-st.patch b/SOURCES/0129-ipa-backup-Add-mechanism-to-store-empty-directory-st.patch deleted file mode 100644 index 4425903..0000000 --- a/SOURCES/0129-ipa-backup-Add-mechanism-to-store-empty-directory-st.patch +++ /dev/null @@ -1,130 +0,0 @@ -From 9b2593e54f12e28a8f1dc502ddb44cf237f0ddec Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Thu, 17 Sep 2015 17:09:33 +0200 -Subject: [PATCH] ipa-backup: Add mechanism to store empty directory structure - -Certain subcomponents of IPA, such as Dogtag, cannot function if -non-critical directories (such as log directories) have not been -stored in the backup. - -This patch implements storage of selected empty directories, -while preserving attributes and SELinux context. - -https://fedorahosted.org/freeipa/ticket/5297 - -Reviewed-By: Martin Basti ---- - freeipa.spec.in | 1 + - ipaplatform/base/paths.py | 3 +++ - ipaserver/install/ipa_backup.py | 50 ++++++++++++++++++++++++++++++++++++++--- - 3 files changed, 51 insertions(+), 3 deletions(-) - -diff --git a/freeipa.spec.in b/freeipa.spec.in -index d8e24a5af47fbfca89ccb9c3d07dcfca5a8073d9..a8515487757556f337a4bbfc1cc14e8fb4707ccd 100644 ---- a/freeipa.spec.in -+++ b/freeipa.spec.in -@@ -162,6 +162,7 @@ Requires: softhsm >= 2.0.0rc1-1 - Requires: p11-kit - Requires: systemd-python - Requires: %{etc_systemd_dir} -+Requires: gzip - - Conflicts: %{alt_name}-server - Obsoletes: %{alt_name}-server < %{version} -diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py -index 3930c93fcba06959dd34507ecc29f92e33637775..97c330c31844fcf19bec2e96bf2b23cba5f7f3f0 100644 ---- a/ipaplatform/base/paths.py -+++ b/ipaplatform/base/paths.py -@@ -328,6 +328,9 @@ class BasePathNamespace(object): - TOMCAT_CA_DIR = "/var/log/pki/pki-tomcat/ca" - TOMCAT_CA_ARCHIVE_DIR = "/var/log/pki/pki-tomcat/ca/archive" - TOMCAT_SIGNEDAUDIT_DIR = "/var/log/pki/pki-tomcat/ca/signedAudit" -+ TOMCAT_KRA_DIR = "/var/log/pki/pki-tomcat/kra" -+ TOMCAT_KRA_ARCHIVE_DIR = "/var/log/pki/pki-tomcat/kra/archive" -+ TOMCAT_KRA_SIGNEDAUDIT_DIR = "/var/log/pki/pki-tomcat/kra/signedAudit" - LOG_SECURE = "/var/log/secure" - NAMED_RUN = "/var/named/data/named.run" - VAR_OPENDNSSEC_DIR = "/var/opendnssec" -diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py -index 8df1005a222220a0ece95a3691766ed3cd00a0d9..3bd2ef0203c1b5b596e092987acd894491ecae26 100644 ---- a/ipaserver/install/ipa_backup.py -+++ b/ipaserver/install/ipa_backup.py -@@ -202,6 +202,16 @@ class Backup(admintool.AdminTool): - paths.NAMED_RUN, - ) - -+ required_dirs=( -+ paths.TOMCAT_TOPLEVEL_DIR, -+ paths.TOMCAT_CA_DIR, -+ paths.TOMCAT_SIGNEDAUDIT_DIR, -+ paths.TOMCAT_CA_ARCHIVE_DIR, -+ paths.TOMCAT_KRA_DIR, -+ paths.TOMCAT_KRA_SIGNEDAUDIT_DIR, -+ paths.TOMCAT_KRA_ARCHIVE_DIR, -+ ) -+ - def __init__(self, options, args): - super(Backup, self).__init__(options, args) - self._conn = None -@@ -486,13 +496,15 @@ class Backup(admintool.AdminTool): - def verify_directories(dirs): - return [s for s in dirs if os.path.exists(s)] - -+ tarfile = os.path.join(self.dir, 'files.tar') -+ - self.log.info("Backing up files") - args = ['tar', - '--exclude=/var/lib/ipa/backup', - '--xattrs', - '--selinux', -- '-czf', -- os.path.join(self.dir, 'files.tar') -+ '-cf', -+ tarfile - ] - - args.extend(verify_directories(self.dirs)) -@@ -503,7 +515,39 @@ class Backup(admintool.AdminTool): - - (stdout, stderr, rc) = run(args, raiseonerr=False) - if rc != 0: -- raise admintool.ScriptError('tar returned non-zero %d: %s' % (rc, stdout)) -+ raise admintool.ScriptError('tar returned non-zero code ' -+ '%d: %s' % (rc, stderr)) -+ -+ # Backup the necessary directory structure. This is a separate -+ # call since we are using the '--no-recursion' flag to store -+ # the directory structure only, no files. -+ missing_directories = verify_directories(self.required_dirs) -+ -+ if missing_directories: -+ args = ['tar', -+ '--exclude=/var/lib/ipa/backup', -+ '--xattrs', -+ '--selinux', -+ '--no-recursion', -+ '-rf', # -r appends to an existing archive -+ tarfile, -+ ] -+ args.extend(missing_directories) -+ -+ (stdout, stderr, rc) = run(args, raiseonerr=False) -+ if rc != 0: -+ raise admintool.ScriptError('tar returned non-zero %d when adding ' -+ 'directory structure: %s' % (rc, stderr)) -+ -+ # Compress the archive. This is done separately, since 'tar' cannot -+ # append to a compressed archive. -+ (stdout, stderr, rc) = run(['gzip', tarfile], raiseonerr=False) -+ if rc != 0: -+ raise admintool.ScriptError('gzip returned non-zero %d when ' -+ 'compressing the backup: %s' % (rc, stderr)) -+ -+ # Rename the archive back to files.tar to preserve compatibility -+ os.rename(os.path.join(self.dir, 'files.tar.gz'), tarfile) - - - def create_header(self, data_only): --- -2.4.3 - diff --git a/SOURCES/0130-Make-host-service-cert-revocation-aware-of-lightweig.patch b/SOURCES/0130-Make-host-service-cert-revocation-aware-of-lightweig.patch new file mode 100644 index 0000000..d154616 --- /dev/null +++ b/SOURCES/0130-Make-host-service-cert-revocation-aware-of-lightweig.patch @@ -0,0 +1,184 @@ +From c9428fe0a1230fb9ea9c18c895c0834678e94da8 Mon Sep 17 00:00:00 2001 +From: Fraser Tweedale +Date: Fri, 26 Aug 2016 15:31:13 +1000 +Subject: [PATCH] Make host/service cert revocation aware of lightweight CAs + +Revocation of host/service certs on host/service deletion or other +operations is broken when cert is issued by a lightweight (sub)CA, +causing the delete operation to be aborted. Look up the issuing CA +and pass it to 'cert_revoke' to fix the issue. + +Fixes: https://fedorahosted.org/freeipa/ticket/6221 +Reviewed-By: Jan Cholasta +--- + ipaserver/plugins/host.py | 20 +++++++--------- + ipaserver/plugins/service.py | 56 ++++++++++++++++++++++---------------------- + 2 files changed, 37 insertions(+), 39 deletions(-) + +diff --git a/ipaserver/plugins/host.py b/ipaserver/plugins/host.py +index 03c64c637cbba0aee1b6569f3b5dbe200953bff8..2362b6247af87b4ce63c21083e6bc8ac39db0804 100644 +--- a/ipaserver/plugins/host.py ++++ b/ipaserver/plugins/host.py +@@ -843,12 +843,8 @@ class host_del(LDAPDelete): + ) + + if self.api.Command.ca_is_enabled()['result']: +- try: +- entry_attrs = ldap.get_entry(dn, ['usercertificate']) +- except errors.NotFound: +- self.obj.handle_not_found(*keys) +- +- revoke_certs(entry_attrs.get('usercertificate', []), self.log) ++ certs = self.api.Command.cert_find(host=keys)['result'] ++ revoke_certs(certs) + + return dn + +@@ -910,7 +906,9 @@ class host_mod(LDAPUpdate): + old_certs = entry_attrs_old.get('usercertificate', []) + old_certs_der = [x509.normalize_certificate(c) for c in old_certs] + removed_certs_der = set(old_certs_der) - set(certs_der) +- revoke_certs(removed_certs_der, self.log) ++ for der in removed_certs_der: ++ rm_certs = api.Command.cert_find(certificate=der)['result'] ++ revoke_certs(rm_certs) + + if certs: + entry_attrs['usercertificate'] = certs_der +@@ -1196,10 +1194,10 @@ class host_disable(LDAPQuery): + except errors.NotFound: + self.obj.handle_not_found(*keys) + if self.api.Command.ca_is_enabled()['result']: +- certs = entry_attrs.get('usercertificate', []) ++ certs = self.api.Command.cert_find(host=keys)['result'] + + if certs: +- revoke_certs(certs, self.log) ++ revoke_certs(certs) + # Remove the usercertificate altogether + entry_attrs['usercertificate'] = None + ldap.update_entry(entry_attrs) +@@ -1341,8 +1339,8 @@ class host_remove_cert(LDAPRemoveAttributeViaOption): + def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) + +- if 'usercertificate' in options: +- revoke_certs(options['usercertificate'], self.log) ++ for cert in options.get('usercertificate', []): ++ revoke_certs(api.Command.cert_find(certificate=cert)['result']) + + return dn + +diff --git a/ipaserver/plugins/service.py b/ipaserver/plugins/service.py +index 04d1916fe989a8651bcc4d44f1914c460be1081c..093525f2e7cb84b18f0658dcb5d7c786e45c6ab6 100644 +--- a/ipaserver/plugins/service.py ++++ b/ipaserver/plugins/service.py +@@ -220,37 +220,38 @@ def validate_certificate(ugettext, cert): + x509.validate_certificate(cert, datatype=x509.DER) + + +-def revoke_certs(certs, logger=None): ++def revoke_certs(certs): + """ + revoke the certificates removed from host/service entry +- """ +- for cert in certs: +- try: +- cert = x509.normalize_certificate(cert) +- except errors.CertificateFormatError as e: +- if logger is not None: +- logger.info("Problem decoding certificate: %s" % e) + +- serial = unicode(x509.get_serial_number(cert, x509.DER)) ++ :param certs: Output of a 'cert_find' command. + +- try: +- result = api.Command['cert_show'](unicode(serial))['result'] +- except errors.CertificateOperationError: +- continue +- if 'revocation_reason' in result: ++ """ ++ for cert in certs: ++ if 'cacn' not in cert: ++ # Cert is known to IPA, but has no associated CA. ++ # If it was issued by 3rd-party CA, we can't revoke it. ++ # If it was issued by a Dogtag lightweight CA that was ++ # subsequently deleted, we can't revoke it via IPA. ++ # We could go directly to Dogtag to revoke it, but the ++ # issuer's cert should have been revoked so never mind. + continue +- if x509.normalize_certificate(result['certificate']) != cert: ++ ++ if cert['revoked']: ++ # cert is already revoked + continue + + try: +- api.Command['cert_revoke'](unicode(serial), +- revocation_reason=4) ++ api.Command['cert_revoke']( ++ cert['serial_number'], ++ cacn=cert['cacn'], ++ revocation_reason=4, ++ ) + except errors.NotImplementedError: + # some CA's might not implement revoke + pass + + +- + def set_certificate_attrs(entry_attrs): + """ + Set individual attributes from some values from a certificate. +@@ -674,11 +675,8 @@ class service_del(LDAPDelete): + # custom services allow them to manage them. + check_required_principal(ldap, keys[-1]) + if self.api.Command.ca_is_enabled()['result']: +- try: +- entry_attrs = ldap.get_entry(dn, ['usercertificate']) +- except errors.NotFound: +- self.obj.handle_not_found(*keys) +- revoke_certs(entry_attrs.get('usercertificate', []), self.log) ++ certs = self.api.Command.cert_find(service=keys)['result'] ++ revoke_certs(certs) + + return dn + +@@ -711,7 +709,9 @@ class service_mod(LDAPUpdate): + old_certs = entry_attrs_old.get('usercertificate', []) + old_certs_der = [x509.normalize_certificate(c) for c in old_certs] + removed_certs_der = set(old_certs_der) - set(certs_der) +- revoke_certs(removed_certs_der, self.log) ++ for der in removed_certs_der: ++ rm_certs = api.Command.cert_find(certificate=der)['result'] ++ revoke_certs(rm_certs) + + if certs: + entry_attrs['usercertificate'] = certs_der +@@ -950,10 +950,10 @@ class service_disable(LDAPQuery): + done_work = False + + if self.api.Command.ca_is_enabled()['result']: +- certs = entry_attrs.get('usercertificate', []) ++ certs = self.api.Command.cert_find(service=keys)['result'] + + if len(certs) > 0: +- revoke_certs(certs, self.log) ++ revoke_certs(certs) + # Remove the usercertificate altogether + entry_attrs['usercertificate'] = None + ldap.update_entry(entry_attrs) +@@ -989,8 +989,8 @@ class service_remove_cert(LDAPRemoveAttributeViaOption): + def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) + +- if 'usercertificate' in options: +- revoke_certs(options['usercertificate'], self.log) ++ for cert in options.get('usercertificate', []): ++ revoke_certs(api.Command.cert_find(certificate=cert)['result']) + + return dn + +-- +2.7.4 + diff --git a/SOURCES/0130-install-create-kdcproxy-user-during-server-install.patch b/SOURCES/0130-install-create-kdcproxy-user-during-server-install.patch deleted file mode 100644 index 53757d0..0000000 --- a/SOURCES/0130-install-create-kdcproxy-user-during-server-install.patch +++ /dev/null @@ -1,131 +0,0 @@ -From 99989ab3a9017ea9defc80c5a7047c119c29ff34 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Mon, 21 Sep 2015 10:09:50 +0200 -Subject: [PATCH] install: create kdcproxy user during server install - -This change makes kdcproxy user creation consistent with DS and CA user -creation. Before, the user was created in the spec file, in %pre scriptlet -of freeipa-server. - -https://fedorahosted.org/freeipa/ticket/5314 - -Reviewed-By: Martin Babinsky ---- - freeipa.spec.in | 11 ----------- - ipaserver/install/httpinstance.py | 14 ++++++++++++++ - ipaserver/install/ipa_restore.py | 4 +++- - ipaserver/install/server/upgrade.py | 1 + - 4 files changed, 18 insertions(+), 12 deletions(-) - -diff --git a/freeipa.spec.in b/freeipa.spec.in -index a8515487757556f337a4bbfc1cc14e8fb4707ccd..530f6141872804ab3801f2da6271fce0d9308a09 100644 ---- a/freeipa.spec.in -+++ b/freeipa.spec.in -@@ -24,10 +24,6 @@ - - %define _hardened_build 1 - --%define kdcproxy_user kdcproxy --%define kdcproxy_group kdcproxy --%define kdcproxy_home %{_sharedstatedir}/kdcproxy -- - Name: freeipa - Version: __VERSION__ - Release: __RELEASE__%{?dist} -@@ -568,13 +564,6 @@ if [ -e /usr/sbin/ipa_kpasswd ]; then - # END - fi - --# create kdcproxy user --getent group %{kdcproxy_group} >/dev/null || groupadd -r %{kdcproxy_group} --getent passwd %{kdcproxy_user} >/dev/null || \ -- /usr/sbin/useradd -r -m -c "IPA KDC Proxy User" -s /sbin/nologin \ -- -g %{kdcproxy_group} -d %{kdcproxy_home} %{kdcproxy_user} --exit 0 -- - %postun server-trust-ad - if [ "$1" -ge "1" ]; then - if [ "`readlink %{_sysconfdir}/alternatives/winbind_krb5_locator.so`" == "/dev/null" ]; then -diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py -index 792825621f68844a2b0b1265eeeb37e4247d66f8..4f2902e1b1ac03d9c6bd1949b66ede9abb5be28e 100644 ---- a/ipaserver/install/httpinstance.py -+++ b/ipaserver/install/httpinstance.py -@@ -49,6 +49,8 @@ SELINUX_BOOLEAN_SETTINGS = dict( - httpd_run_ipa='on', - ) - -+KDCPROXY_USER = 'kdcproxy' -+ - - def httpd_443_configured(): - """ -@@ -75,6 +77,17 @@ def httpd_443_configured(): - - return False - -+ -+def create_kdcproxy_user(): -+ """Create KDC proxy user/group if it doesn't exist yet.""" -+ tasks.create_system_user( -+ name=KDCPROXY_USER, -+ group=KDCPROXY_USER, -+ homedir=paths.VAR_LIB, -+ shell=paths.NOLOGIN, -+ ) -+ -+ - class WebGuiInstance(service.SimpleServiceInstance): - def __init__(self): - service.SimpleServiceInstance.__init__(self, "ipa_webgui") -@@ -139,6 +152,7 @@ class HTTPInstance(service.Service): - self.step("clean up any existing httpd ccache", self.remove_httpd_ccache) - self.step("configuring SELinux for httpd", self.configure_selinux_for_httpd) - if not self.is_kdcproxy_configured(): -+ self.step("create KDC proxy user", create_kdcproxy_user) - self.step("create KDC proxy config", self.create_kdcproxy_conf) - self.step("enable KDC proxy", self.enable_kdcproxy) - self.step("restarting httpd", self.__start) -diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py -index dc57a4937365ad1db960955cf21e1bf2d2eb3dda..57d5deb1e68af6e9ceb51f4dd751b8a59d9ac513 100644 ---- a/ipaserver/install/ipa_restore.py -+++ b/ipaserver/install/ipa_restore.py -@@ -370,6 +370,7 @@ class Restore(admintool.AdminTool): - - self.restore_selinux_booleans() - -+ http = httpinstance.HTTPInstance() - - # We do either a full file restore or we restore data. - if restore_type == 'FULL': -@@ -381,6 +382,8 @@ class Restore(admintool.AdminTool): - self.cert_restore() - if 'CA' in self.backup_services: - self.__create_dogtag_log_dirs() -+ if http.is_kdcproxy_configured(): -+ httpinstance.create_kdcproxy_user() - - # Always restore the data from ldif - # If we are restoring PKI-IPA then we need to restore the -@@ -409,7 +412,6 @@ class Restore(admintool.AdminTool): - self.log.info('Restarting SSSD') - sssd = services.service('sssd') - sssd.restart() -- http = httpinstance.HTTPInstance() - http.remove_httpd_ccache() - finally: - try: -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index 5288f8fcc5fb56b13773e3bb8ea6a5a6c8c0e8a9..0194f75477321a9e1660335ac8283d35aff8a0ec 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -1439,6 +1439,7 @@ def upgrade_configuration(): - http.realm = api.env.realm - http.suffix = ipautil.realm_to_suffix(api.env.realm) - http.ldap_connect() -+ httpinstance.create_kdcproxy_user() - http.create_kdcproxy_conf() - http.enable_kdcproxy() - --- -2.4.3 - diff --git a/SOURCES/0131-Fix-regression-introduced-in-ipa-certupdate.patch b/SOURCES/0131-Fix-regression-introduced-in-ipa-certupdate.patch new file mode 100644 index 0000000..18cc8e1 --- /dev/null +++ b/SOURCES/0131-Fix-regression-introduced-in-ipa-certupdate.patch @@ -0,0 +1,33 @@ +From 29933c3f480344b7066554f3e66874c2aa4625a8 Mon Sep 17 00:00:00 2001 +From: Florence Blanc-Renaud +Date: Fri, 9 Sep 2016 15:04:35 +0200 +Subject: [PATCH] Fix regression introduced in ipa-certupdate + +The fix for 6288 was overwritten by commit 08b768313020c45bfa82d67cd214afabf605f4b3. + +https://fedorahosted.org/freeipa/ticket/6288 + +Reviewed-By: Martin Babinsky +--- + ipaclient/ipa_certupdate.py | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/ipaclient/ipa_certupdate.py b/ipaclient/ipa_certupdate.py +index 4b97b85b83c8b1a130d6db9cdcc7a76fc569af9e..52f73e196c8f18c9f944dd7eeaa442780e17cb7d 100644 +--- a/ipaclient/ipa_certupdate.py ++++ b/ipaclient/ipa_certupdate.py +@@ -83,7 +83,10 @@ class CertUpdate(admintool.AdminTool): + certs = certstore.get_ca_certs(ldap, api.env.basedn, + api.env.realm, ca_enabled) + +- lwcas = api.Command.ca_find()['result'] ++ if ca_enabled: ++ lwcas = api.Command.ca_find()['result'] ++ else: ++ lwcas = [] + + api.Backend.rpcclient.disconnect() + finally: +-- +2.9.3 + diff --git a/SOURCES/0131-destroy-httpd-ccache-after-stopping-the-service.patch b/SOURCES/0131-destroy-httpd-ccache-after-stopping-the-service.patch deleted file mode 100644 index ee9fba5..0000000 --- a/SOURCES/0131-destroy-httpd-ccache-after-stopping-the-service.patch +++ /dev/null @@ -1,27 +0,0 @@ -From be295102c07510a8136e016c0af0e67363d513c2 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Wed, 16 Sep 2015 18:35:21 +0200 -Subject: [PATCH] destroy httpd ccache after stopping the service - -This will force recreation of the file-based ccache after IPA restore and -prevent a mismatch between cached and restored Kerberos keys. - -https://fedorahosted.org/freeipa/ticket/5296 - -Reviewed-By: Martin Basti ---- - init/systemd/httpd.service | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/init/systemd/httpd.service b/init/systemd/httpd.service -index e68f39eca759db50ad18d8db1faa3b704cb15ede..7ce8f04d8b9bb3663e59d4fdc610af0eb4478178 100644 ---- a/init/systemd/httpd.service -+++ b/init/systemd/httpd.service -@@ -4,3 +4,4 @@ - Environment=KRB5CCNAME=/var/run/httpd/ipa/krbcache/krb5ccache - Environment=KDCPROXY_CONFIG=/etc/ipa/kdcproxy/kdcproxy.conf - ExecStartPre=/usr/libexec/ipa/ipa-httpd-kdcproxy -+ExecStopPost=-/usr/bin/kdestroy -A --- -2.4.3 - diff --git a/SOURCES/0132-Start-named-during-configuration-upgrade.patch b/SOURCES/0132-Start-named-during-configuration-upgrade.patch new file mode 100644 index 0000000..89b1e1f --- /dev/null +++ b/SOURCES/0132-Start-named-during-configuration-upgrade.patch @@ -0,0 +1,48 @@ +From 82ffbefb88013e125e8377fe525fdef1de0c7ad4 Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Tue, 13 Sep 2016 18:37:43 +0200 +Subject: [PATCH] Start named during configuration upgrade. + +Some upgrade steps require bind running, to be succesfull. Upgrader +makes sure that bind starts. + +https://fedorahosted.org/freeipa/ticket/6205 + +Reviewed-By: Martin Babinsky +--- + ipaserver/install/server/upgrade.py | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py +index 43427178b11f63797a9537eadee836d7cf224311..e1343f423cec21f02e3d9581012496baa7b30cc6 100644 +--- a/ipaserver/install/server/upgrade.py ++++ b/ipaserver/install/server/upgrade.py +@@ -1706,6 +1706,15 @@ def upgrade_configuration(): + cleanup_kdc(fstore) + cleanup_adtrust(fstore) + setup_firefox_extension(fstore) ++ ++ bind = bindinstance.BindInstance(fstore) ++ if bind.is_configured() and not bind.is_running(): ++ # some upgrade steps may require bind running ++ bind_started = True ++ bind.start() ++ else: ++ bind_started = False ++ + add_ca_dns_records() + + # Any of the following functions returns True iff the named.conf file +@@ -1736,6 +1745,9 @@ def upgrade_configuration(): + except ipautil.CalledProcessError as e: + root_logger.error("Failed to restart %s: %s", bind.service_name, e) + ++ if bind_started: ++ bind.stop() ++ + custodia = custodiainstance.CustodiaInstance(api.env.host, api.env.realm) + custodia.upgrade_instance() + +-- +2.7.4 + diff --git a/SOURCES/0132-platform-add-option-to-create-home-directory-when-ad.patch b/SOURCES/0132-platform-add-option-to-create-home-directory-when-ad.patch deleted file mode 100644 index 5cb723f..0000000 --- a/SOURCES/0132-platform-add-option-to-create-home-directory-when-ad.patch +++ /dev/null @@ -1,70 +0,0 @@ -From d17b314d405d2c127a3d51d2076e8982d43aa505 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Wed, 23 Sep 2015 13:09:44 +0200 -Subject: [PATCH] platform: add option to create home directory when adding - user - -https://fedorahosted.org/freeipa/ticket/5314 - -Reviewed-By: Martin Babinsky ---- - ipaplatform/base/tasks.py | 8 ++++++-- - ipaplatform/redhat/tasks.py | 4 ++-- - 2 files changed, 8 insertions(+), 4 deletions(-) - -diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py -index 65715145af533c90038b3e8667da07fd28b7ec56..573287c6bf732991946a75c8817899ee6c1842e3 100644 ---- a/ipaplatform/base/tasks.py -+++ b/ipaplatform/base/tasks.py -@@ -184,7 +184,7 @@ class BaseTaskNamespace(object): - - return - -- def create_system_user(self, name, group, homedir, shell, uid = None, gid = None, comment = None): -+ def create_system_user(self, name, group, homedir, shell, uid=None, gid=None, comment=None, create_homedir=False): - """Create a system user with a corresponding group""" - try: - grp.getgrnam(group) -@@ -211,12 +211,16 @@ class BaseTaskNamespace(object): - '-g', group, - '-d', homedir, - '-s', shell, -- '-M', '-r', name, -+ '-r', name, - ] - if uid: - args += ['-u', str(uid)] - if comment: - args += ['-c', comment] -+ if create_homedir: -+ args += ['-m'] -+ else: -+ args += ['-M'] - try: - ipautil.run(args) - log.debug('Done adding user') -diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py -index 1af99d318c6745b1e5285c7829c2b292f86c8390..db31cd04cb234fac8fee97f3579ba2ca919f3262 100644 ---- a/ipaplatform/redhat/tasks.py -+++ b/ipaplatform/redhat/tasks.py -@@ -399,7 +399,7 @@ class RedHatTaskNamespace(BaseTaskNamespace): - - return True - -- def create_system_user(self, name, group, homedir, shell, uid = None, gid = None, comment = None): -+ def create_system_user(self, name, group, homedir, shell, uid=None, gid=None, comment=None, create_homedir=False): - """ - Create a system user with a corresponding group - -@@ -420,7 +420,7 @@ class RedHatTaskNamespace(BaseTaskNamespace): - comment = 'DS System User' - - super(RedHatTaskNamespace, self).create_system_user(name, group, -- homedir, shell, uid, gid, comment) -+ homedir, shell, uid, gid, comment, create_homedir) - - - tasks = RedHatTaskNamespace() --- -2.4.3 - diff --git a/SOURCES/0133-Catch-DNS-exceptions-during-emptyzones-named.conf-up.patch b/SOURCES/0133-Catch-DNS-exceptions-during-emptyzones-named.conf-up.patch new file mode 100644 index 0000000..db5de87 --- /dev/null +++ b/SOURCES/0133-Catch-DNS-exceptions-during-emptyzones-named.conf-up.patch @@ -0,0 +1,54 @@ +From bbc716fa6c58305e81962ea9f7e7e710ff51ad99 Mon Sep 17 00:00:00 2001 +From: Martin Basti +Date: Tue, 13 Sep 2016 19:12:40 +0200 +Subject: [PATCH] Catch DNS exceptions during emptyzones named.conf upgrade + +For some reasons named may not be runnig and this cause fail of this +upgrade step. This step is not critical so only ERROR message with +recommendation is shown. + +https://fedorahosted.org/freeipa/ticket/6205 + +Reviewed-By: Martin Babinsky +--- + ipaserver/install/server/upgrade.py | 17 ++++++++++++++--- + 1 file changed, 14 insertions(+), 3 deletions(-) + +diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py +index e1343f423cec21f02e3d9581012496baa7b30cc6..3b23c2e688f436453cfa185f87780b7ff5cafa16 100644 +--- a/ipaserver/install/server/upgrade.py ++++ b/ipaserver/install/server/upgrade.py +@@ -11,6 +11,8 @@ import pwd + import fileinput + import sys + ++import dns.exception ++ + import six + from six.moves.configparser import SafeConfigParser + +@@ -840,9 +842,18 @@ def named_update_global_forwarder_policy(): + 'forward_policy_conflict_with_empty_zones_handled', + True + ) +- if not dnsutil.has_empty_zone_addresses(api.env.host): +- # guess: local server does not have IP addresses from private ranges +- # so hopefully automatic empty zones are not a problem ++ try: ++ if not dnsutil.has_empty_zone_addresses(api.env.host): ++ # guess: local server does not have IP addresses from private ++ # ranges so hopefully automatic empty zones are not a problem ++ return False ++ except dns.exception.DNSException as ex: ++ root_logger.error( ++ 'Skipping update of global DNS forwarder in named.conf: ' ++ 'Unable to determine if local server is using an ' ++ 'IP address belonging to an automatic empty zone. ' ++ 'Consider changing forwarding policy to "only". ' ++ 'DNS exception: %s', ex) + return False + + if bindinstance.named_conf_get_directive( +-- +2.7.4 + diff --git a/SOURCES/0133-install-fix-kdcproxy-user-home-directory.patch b/SOURCES/0133-install-fix-kdcproxy-user-home-directory.patch deleted file mode 100644 index 941b000..0000000 --- a/SOURCES/0133-install-fix-kdcproxy-user-home-directory.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 8a866620f36356e570dcee332db6f487837435a6 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Wed, 23 Sep 2015 10:35:06 +0200 -Subject: [PATCH] install: fix kdcproxy user home directory - -https://fedorahosted.org/freeipa/ticket/5314 - -Reviewed-By: Martin Babinsky ---- - freeipa.spec.in | 1 + - ipaplatform/base/paths.py | 1 + - ipaserver/install/httpinstance.py | 4 +++- - 3 files changed, 5 insertions(+), 1 deletion(-) - -diff --git a/freeipa.spec.in b/freeipa.spec.in -index 530f6141872804ab3801f2da6271fce0d9308a09..6527109b422a1e3065d5a540c3e2a3af670f2ebf 100644 ---- a/freeipa.spec.in -+++ b/freeipa.spec.in -@@ -702,6 +702,7 @@ fi - %{_libexecdir}/ipa/ipa-dnskeysync-replica - %{_libexecdir}/ipa/ipa-ods-exporter - %{_libexecdir}/ipa/ipa-httpd-kdcproxy -+%ghost %verify(not owner group) %dir %{_sharedstatedir}/kdcproxy - %config(noreplace) %{_sysconfdir}/sysconfig/ipa_memcached - %config(noreplace) %{_sysconfdir}/sysconfig/ipa-dnskeysyncd - %config(noreplace) %{_sysconfdir}/sysconfig/ipa-ods-exporter -diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py -index 97c330c31844fcf19bec2e96bf2b23cba5f7f3f0..215caf90ea1ca4e5db8f43f8f09002ce5d5cd280 100644 ---- a/ipaplatform/base/paths.py -+++ b/ipaplatform/base/paths.py -@@ -286,6 +286,7 @@ class BasePathNamespace(object): - REPLICA_INFO_GPG_TEMPLATE = "/var/lib/ipa/replica-info-%s.gpg" - SYSRESTORE = "/var/lib/ipa/sysrestore" - STATEFILE_DIR = "/var/lib/ipa/sysupgrade" -+ VAR_LIB_KDCPROXY = "/var/lib/kdcproxy" - VAR_LIB_PKI_DIR = "/var/lib/pki" - VAR_LIB_PKI_CA_DIR = "/var/lib/pki-ca" - PKI_ALIAS_CA_P12 = "/var/lib/pki-ca/alias/ca.p12" -diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py -index 4f2902e1b1ac03d9c6bd1949b66ede9abb5be28e..f55e698f7eb3d8f8aa603f99d750a009a806b70a 100644 ---- a/ipaserver/install/httpinstance.py -+++ b/ipaserver/install/httpinstance.py -@@ -83,8 +83,10 @@ def create_kdcproxy_user(): - tasks.create_system_user( - name=KDCPROXY_USER, - group=KDCPROXY_USER, -- homedir=paths.VAR_LIB, -+ homedir=paths.VAR_LIB_KDCPROXY, - shell=paths.NOLOGIN, -+ comment="IPA KDC Proxy User", -+ create_homedir=True, - ) - - --- -2.4.3 - diff --git a/SOURCES/0134-trust-fetch-domains-contact-forest-DCs-when-fetching.patch b/SOURCES/0134-trust-fetch-domains-contact-forest-DCs-when-fetching.patch new file mode 100644 index 0000000..d09400a --- /dev/null +++ b/SOURCES/0134-trust-fetch-domains-contact-forest-DCs-when-fetching.patch @@ -0,0 +1,60 @@ +From 1db0d09a59c6fbfdfd080f9f78f5a5d9b61e2c19 Mon Sep 17 00:00:00 2001 +From: Martin Babinsky +Date: Tue, 13 Sep 2016 15:59:40 +0200 +Subject: [PATCH] trust-fetch-domains: contact forest DCs when fetching trust + domain info + +The code should always contact forest root DCs when requesting trust domain +info. In the case of one-way or external trusts +`com.redhat.idm.trust-fetch-domains` helper is leveraged, otherwise forest +root domain is contacted directly through Samba using the credentials of HTTP +principal. + +https://fedorahosted.org/freeipa/ticket/6328 + +Reviewed-By: Alexander Bokovoy +--- + ipaserver/plugins/trust.py | 14 +++++++++++--- + 1 file changed, 11 insertions(+), 3 deletions(-) + +diff --git a/ipaserver/plugins/trust.py b/ipaserver/plugins/trust.py +index b3cb56c14496c0d56d3f3fedddee8d123f929344..720a45a4d12d59f00e3e63f2b4f62edd45646065 100644 +--- a/ipaserver/plugins/trust.py ++++ b/ipaserver/plugins/trust.py +@@ -1739,15 +1739,20 @@ class trust_fetch_domains(LDAPRetrieve): + ldap = self.api.Backend.ldap2 + verify_samba_component_presence(ldap, self.api) + +- trust = self.api.Command.trust_show(keys[0], raw=True)['result'] ++ trust = self.api.Command.trust_show( ++ keys[0], all=True, raw=True)['result'] + + result = dict() + result['result'] = [] + result['count'] = 0 + result['truncated'] = False + +- # For one-way trust fetch over DBus. we don't get the list in this case. +- if int(trust['ipanttrustdirection'][0]) != TRUST_BIDIRECTIONAL: ++ trust_direction = int(trust['ipanttrustdirection'][0]) ++ is_nontransitive = int(trust.get('ipanttrustattributes', ++ [0])[0]) & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE ++ # For one-way trust and external trust fetch over DBus. ++ # We don't get the list in this case. ++ if trust_direction != TRUST_BIDIRECTIONAL or is_nontransitive: + fetch_trusted_domains_over_dbus(self.api, self.log, keys[0]) + result['summary'] = unicode(_('List of trust domains successfully refreshed. Use trustdomain-find command to list them.')) + return result +@@ -1762,6 +1767,9 @@ class trust_fetch_domains(LDAPRetrieve): + 'on the IPA server first' + ) + ) ++ ++ trustinstance.populate_remote_domain(keys[0]) ++ + res = fetch_domains_from_trust(self.api, trustinstance, **options) + domains = add_new_domains_from_trust(self.api, trustinstance, trust, res, **options) + +-- +2.7.4 + diff --git a/SOURCES/0134-winsync-migrate-Convert-entity-names-to-posix-friend.patch b/SOURCES/0134-winsync-migrate-Convert-entity-names-to-posix-friend.patch deleted file mode 100644 index ba75602..0000000 --- a/SOURCES/0134-winsync-migrate-Convert-entity-names-to-posix-friend.patch +++ /dev/null @@ -1,104 +0,0 @@ -From d8395581497150602dc11248ba6ce380a3394254 Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Wed, 23 Sep 2015 13:27:35 +0200 -Subject: [PATCH] winsync-migrate: Convert entity names to posix friendly - strings - -During the migration from winsync replicated users to their -trusted identities, memberships are being preserved. However, -trusted users are external and as such cannot be added as -direct members to the IPA entities. External groups which -encapsulate the migrated users are added as members to those -entities instead. - -The name of the external group is generated from the type -of the entity and its name. However, the entity's name can -contain characters which are invalid for use in the group -name. - -Adds a helper function to convert a given string to a string -which would be valid for such use and leverages it in the -winsync-migrate tool. - -https://fedorahosted.org/freeipa/ticket/5319 - -Reviewed-By: Martin Babinsky ---- - ipapython/ipautil.py | 23 +++++++++++++++++++++++ - ipaserver/install/ipa_winsync_migrate.py | 15 ++++++++++++--- - 2 files changed, 35 insertions(+), 3 deletions(-) - -diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py -index 88e89706b8e2aa6dea80809510d88bceaa836e85..64fe9bc27e58c8ecfcfabe69690db0493a10c3b1 100644 ---- a/ipapython/ipautil.py -+++ b/ipapython/ipautil.py -@@ -1318,6 +1318,29 @@ def restore_hostname(statestore): - except CalledProcessError, e: - print >>sys.stderr, "Failed to set this machine hostname back to %s: %s" % (old_hostname, str(e)) - -+def posixify(string): -+ """ -+ Convert a string to a more strict alpha-numeric representation. -+ -+ - Alpha-numeric, underscore, dot and dash characters are accepted -+ - Space is converted to underscore -+ - Other characters are omitted -+ - Leading dash is stripped -+ -+ Note: This mapping is not one-to-one and may map different input to the -+ same result. When using posixify, make sure the you do not map two different -+ entities to one unintentionally. -+ """ -+ -+ def valid_char(char): -+ return char.isalnum() or char in ('_', '.', '-') -+ -+ # First replace space characters -+ replaced = string.replace(' ','_') -+ omitted = ''.join(filter(valid_char, replaced)) -+ -+ # Leading dash is not allowed -+ return omitted.lstrip('-') - - @contextmanager - def private_ccache(path=None): -diff --git a/ipaserver/install/ipa_winsync_migrate.py b/ipaserver/install/ipa_winsync_migrate.py -index c327e502e6bfb6e402931e1962fe2410570b2bc2..4dacde3f27ead341fd4d7d2a744d28f74d5c5b95 100644 ---- a/ipaserver/install/ipa_winsync_migrate.py -+++ b/ipaserver/install/ipa_winsync_migrate.py -@@ -24,7 +24,7 @@ from ipalib import api - from ipalib import errors - from ipapython import admintool - from ipapython.dn import DN --from ipapython.ipautil import realm_to_suffix -+from ipapython.ipautil import realm_to_suffix, posixify - from ipapython.ipa_log_manager import log_mgr - from ipaserver.plugins.ldap2 import ldap2 - from ipaserver.install import replication -@@ -214,12 +214,21 @@ class WinsyncMigrate(admintool.AdminTool): - - def winsync_group_name(object_entry): - """ -- Returns the generated name of group containing migrated external users -+ Returns the generated name of group containing migrated external -+ users. -+ -+ The group name is of the form: -+ "__winsync_external" -+ -+ Object name is converted to posix-friendly string by omitting -+ and/or replacing characters. This may lead to collisions, i.e. -+ if both 'trust_admins' and 'trust admin' groups have winsync -+ users being migrated. - """ - - return u"{0}_{1}_winsync_external".format( - winsync_group_prefix, -- object_entry['cn'][0] -+ posixify(object_entry['cn'][0]) - ) - - def create_winsync_group(object_entry): --- -2.4.3 - diff --git a/SOURCES/0135-winsync-migrate-Properly-handle-collisions-in-the-na.patch b/SOURCES/0135-winsync-migrate-Properly-handle-collisions-in-the-na.patch deleted file mode 100644 index 10c42c1..0000000 --- a/SOURCES/0135-winsync-migrate-Properly-handle-collisions-in-the-na.patch +++ /dev/null @@ -1,57 +0,0 @@ -From 6f0660a342320ecec805bc158ba31f43394f5ab2 Mon Sep 17 00:00:00 2001 -From: Tomas Babej -Date: Wed, 23 Sep 2015 13:28:33 +0200 -Subject: [PATCH] winsync-migrate: Properly handle collisions in the names of - external groups - -Since the names of the external groups containing the migrated users -must be stripped of characters which are not valid for use in group names, -two different groups might be mapped to one during this process. - -Properly handle collisions in the names by adding an incremental -numeric suffix. - -https://fedorahosted.org/freeipa/ticket/5319 - -Reviewed-By: Martin Babinsky ---- - ipaserver/install/ipa_winsync_migrate.py | 17 ++++++++++++++--- - 1 file changed, 14 insertions(+), 3 deletions(-) - -diff --git a/ipaserver/install/ipa_winsync_migrate.py b/ipaserver/install/ipa_winsync_migrate.py -index 4dacde3f27ead341fd4d7d2a744d28f74d5c5b95..13c5ddef383204451cbc4bb662c8a1befc1d5f93 100644 ---- a/ipaserver/install/ipa_winsync_migrate.py -+++ b/ipaserver/install/ipa_winsync_migrate.py -@@ -231,15 +231,26 @@ class WinsyncMigrate(admintool.AdminTool): - posixify(object_entry['cn'][0]) - ) - -- def create_winsync_group(object_entry): -+ def create_winsync_group(object_entry, suffix=0): - """ - Creates the group containing migrated external users that were - previously available via winsync. - """ - - name = winsync_group_name(object_entry) -- api.Command['group_add'](name, external=True) -- api.Command[object_membership_command](object_entry['cn'][0], group=[name]) -+ -+ # Only non-trivial suffix is appended at the end -+ if suffix != 0: -+ name += str(suffix) -+ -+ try: -+ api.Command['group_add'](name, external=True) -+ except errors.DuplicateEntry: -+ # If there is a collision, let's try again with a higher suffix -+ create_winsync_group(object_entry, suffix=suffix+1) -+ else: -+ # In case of no collision, add the membership -+ api.Command[object_membership_command](object_entry['cn'][0], group=[name]) - - # Search for all objects containing the given user as a direct member - member_filter = self.ldap.make_filter_from_attr(user_dn_attribute, --- -2.4.3 - diff --git a/SOURCES/0136-Fix-an-integer-underflow-bug-in-libotp.patch b/SOURCES/0136-Fix-an-integer-underflow-bug-in-libotp.patch deleted file mode 100644 index 339958a..0000000 --- a/SOURCES/0136-Fix-an-integer-underflow-bug-in-libotp.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 0ee0de08a6b389a7593198c918dc894c87dcbe96 Mon Sep 17 00:00:00 2001 -From: Nathaniel McCallum -Date: Fri, 25 Sep 2015 11:35:03 -0400 -Subject: [PATCH] Fix an integer underflow bug in libotp - -Temporarily storing the offset time in an unsigned integer causes the -value of the offset to underflow when a (valid) negative offset value -is generated. Using a signed variable avoids this problem. - -https://fedorahosted.org/freeipa/ticket/5333 - -Reviewed-By: Tomas Babej ---- - daemons/ipa-slapi-plugins/libotp/otp_token.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - -diff --git a/daemons/ipa-slapi-plugins/libotp/otp_token.c b/daemons/ipa-slapi-plugins/libotp/otp_token.c -index 9b90c6a1137b468103d73cd85fd7e0fcafcee616..a3cbfb0621c071f8addb29f7ce02f870a807c61d 100644 ---- a/daemons/ipa-slapi-plugins/libotp/otp_token.c -+++ b/daemons/ipa-slapi-plugins/libotp/otp_token.c -@@ -199,10 +199,10 @@ static bool validate(struct otp_token *token, time_t now, ssize_t step, - case TYPE_TOTP: - /* Perform optional synchronization steps. */ - if (second != NULL) { -- tmp = (step - now / token->totp.step) * token->totp.step; -- if (!writeattr(token, T("clockOffset"), tmp)) -+ long long off = (step - now / token->totp.step) * token->totp.step; -+ if (!writeattr(token, T("clockOffset"), off)) - return false; -- token->totp.offset = tmp; -+ token->totp.offset = off; - } - token->totp.watermark = step; - break; --- -2.4.3 - diff --git a/SOURCES/0137-do-not-overwrite-files-with-local-users-groups-when-.patch b/SOURCES/0137-do-not-overwrite-files-with-local-users-groups-when-.patch deleted file mode 100644 index fb28b1f..0000000 --- a/SOURCES/0137-do-not-overwrite-files-with-local-users-groups-when-.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 54b62df055fda613aa985ccd971968123c0ad113 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Fri, 25 Sep 2015 18:00:30 +0200 -Subject: [PATCH] do not overwrite files with local users/groups when restoring - authconfig - -the patch fixes regression in ipa-restore caused by overwriting /etc/passwd, -/etc/shadow and fiends during restore of authconfig configuration files. These -files are now excluded from authconfig backup dir. - -https://fedorahosted.org/freeipa/ticket/5328 - -Reviewed-By: David Kupka ---- - ipaplatform/redhat/authconfig.py | 12 ++++++++++++ - 1 file changed, 12 insertions(+) - -diff --git a/ipaplatform/redhat/authconfig.py b/ipaplatform/redhat/authconfig.py -index edefee8b2b4922ad67cdbac158615ef32c776bb4..7b06d583d8f8dba3df589edf73ec20f7b80c20a4 100644 ---- a/ipaplatform/redhat/authconfig.py -+++ b/ipaplatform/redhat/authconfig.py -@@ -19,7 +19,9 @@ - # along with this program. If not, see . - - from ipapython import ipautil -+import os - -+FILES_TO_NOT_BACKUP = ['passwd', 'group', 'shadow', 'gshadow'] - - class RedHatAuthConfig(object): - """ -@@ -88,5 +90,15 @@ class RedHatAuthConfig(object): - def backup(self, path): - ipautil.run(["/usr/sbin/authconfig", "--savebackup", path]) - -+ # do not backup these files since we don't want to mess with -+ # users/groups during restore. Authconfig doesn't seem to mind about -+ # having them deleted from backup dir -+ files_to_remove = [os.path.join(path, f) for f in FILES_TO_NOT_BACKUP] -+ for filename in files_to_remove: -+ try: -+ os.remove(filename) -+ except OSError: -+ pass -+ - def restore(self, path): - ipautil.run(["/usr/sbin/authconfig", "--restorebackup", path]) --- -2.4.3 - diff --git a/SOURCES/0138-install-fix-KRA-agent-PEM-file-permissions.patch b/SOURCES/0138-install-fix-KRA-agent-PEM-file-permissions.patch deleted file mode 100644 index fac95ef..0000000 --- a/SOURCES/0138-install-fix-KRA-agent-PEM-file-permissions.patch +++ /dev/null @@ -1,153 +0,0 @@ -From 3b41a53830fc7d0fdb301437cdceb7fcddff25a5 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Mon, 21 Sep 2015 08:32:04 +0200 -Subject: [PATCH] install: fix KRA agent PEM file permissions - -This fixes CVE-2015-5284. - -https://fedorahosted.org/freeipa/ticket/5347 - -Reviewed-By: Martin Basti ---- - install/restart_scripts/renew_ra_cert | 8 +------- - ipaserver/install/dogtaginstance.py | 22 ++++++++++++++++++++++ - ipaserver/install/krainstance.py | 12 +++--------- - ipaserver/install/server/upgrade.py | 19 +++++++++++++++++++ - 4 files changed, 45 insertions(+), 16 deletions(-) - -diff --git a/install/restart_scripts/renew_ra_cert b/install/restart_scripts/renew_ra_cert -index 93ffd4035723831f3955bcdf5a2082fd1ec5e22a..8a6bf3f7c1081db9710cf29e0f8e5f705d920b72 100644 ---- a/install/restart_scripts/renew_ra_cert -+++ b/install/restart_scripts/renew_ra_cert -@@ -63,13 +63,7 @@ def _main(): - - kra = krainstance.KRAInstance(api.env.realm) - if kra.is_installed(): -- # export ipaCert with private key for client authentication -- args = ["/usr/bin/pki", -- "-d", paths.HTTPD_ALIAS_DIR, -- "-C", paths.ALIAS_PWDFILE_TXT, -- "client-cert-show", "ipaCert", -- "--client-cert", paths.KRA_AGENT_PEM] -- ipautil.run(args) -+ krainstance.export_kra_agent_pem() - finally: - shutil.rmtree(tmpdir) - -diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py -index 33f39f7930b4151200f2880d02a0bc2c152c0025..940b3ea9b13897d7e9e2878a47a8c66ce5ce9f0a 100644 ---- a/ipaserver/install/dogtaginstance.py -+++ b/ipaserver/install/dogtaginstance.py -@@ -23,6 +23,7 @@ import shutil - import tempfile - import traceback - import dbus -+import pwd - - from pki.client import PKIConnection - import pki.system -@@ -88,6 +89,27 @@ def is_installing_replica(sys_type): - return False - - -+def export_kra_agent_pem(): -+ """ -+ Export ipaCert with private key for client authentication. -+ """ -+ fd, filename = tempfile.mkstemp(dir=paths.HTTPD_ALIAS_DIR) -+ os.close(fd) -+ -+ args = ["/usr/bin/pki", -+ "-d", paths.HTTPD_ALIAS_DIR, -+ "-C", paths.ALIAS_PWDFILE_TXT, -+ "client-cert-show", "ipaCert", -+ "--client-cert", filename] -+ ipautil.run(args) -+ -+ pent = pwd.getpwnam("apache") -+ os.chown(filename, 0, pent.pw_gid) -+ os.chmod(filename, 0o440) -+ -+ os.rename(filename, paths.KRA_AGENT_PEM) -+ -+ - class DogtagInstance(service.Service): - """ - This is the base class for a Dogtag 10+ instance, which uses a -diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py -index 48268b0be5331cced1aee6b7f3358333b65de6dd..0000192745b6d7f9f402267e435f7223f1bf8849 100644 ---- a/ipaserver/install/krainstance.py -+++ b/ipaserver/install/krainstance.py -@@ -37,8 +37,8 @@ from ipaserver.install import cainstance - from ipaserver.install import installutils - from ipaserver.install import ldapupdate - from ipaserver.install import service --from ipaserver.install.dogtaginstance import DogtagInstance --from ipaserver.install.dogtaginstance import DEFAULT_DSPORT, PKI_USER -+from ipaserver.install.dogtaginstance import ( -+ DEFAULT_DSPORT, PKI_USER, export_kra_agent_pem, DogtagInstance) - from ipaserver.plugins import ldap2 - from ipapython.ipa_log_manager import log_mgr - -@@ -262,13 +262,7 @@ class KRAInstance(DogtagInstance): - - shutil.move(paths.KRA_BACKUP_KEYS_P12, paths.KRACERT_P12) - -- # export ipaCert with private key for client authentication -- args = ["/usr/bin/pki", -- "-d", paths.HTTPD_ALIAS_DIR, -- "-C", paths.ALIAS_PWDFILE_TXT, -- "client-cert-show", "ipaCert", -- "--client-cert", paths.KRA_AGENT_PEM] -- ipautil.run(args) -+ export_kra_agent_pem() - - self.log.debug("completed creating KRA instance") - -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index 0194f75477321a9e1660335ac8283d35aff8a0ec..ab08c62352c0e5cf145f299e7727886b2f295037 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -35,6 +35,7 @@ from ipaserver.install import otpdinstance - from ipaserver.install import schemaupdate - from ipaserver.install import sysupgrade - from ipaserver.install import dnskeysyncinstance -+from ipaserver.install import krainstance - from ipaserver.install.upgradeinstance import IPAUpgrade - from ipaserver.install.ldapupdate import BadSyntax - -@@ -1244,6 +1245,23 @@ def fix_trust_flags(): - sysupgrade.set_upgrade_state('http', 'fix_trust_flags', True) - - -+def export_kra_agent_pem(): -+ root_logger.info('[Exporting KRA agent PEM file]') -+ -+ if sysupgrade.get_upgrade_state('http', 'export_kra_agent_pem'): -+ root_logger.info("KRA agent PEM file already exported") -+ return -+ -+ kra = krainstance.KRAInstance(api.env.realm) -+ if not kra.is_installed(): -+ root_logger.info("KRA is not installed") -+ return -+ -+ krainstance.export_kra_agent_pem() -+ -+ sysupgrade.set_upgrade_state('http', 'export_kra_agent_pem', True) -+ -+ - def update_mod_nss_protocol(http): - root_logger.info('[Updating mod_nss protocol versions]') - -@@ -1446,6 +1464,7 @@ def upgrade_configuration(): - http.stop() - update_mod_nss_protocol(http) - fix_trust_flags() -+ export_kra_agent_pem() - http.start() - - uninstall_selfsign(ds, http) --- -2.4.3 - diff --git a/SOURCES/0139-install-always-export-KRA-agent-PEM-file.patch b/SOURCES/0139-install-always-export-KRA-agent-PEM-file.patch deleted file mode 100644 index 9e590b0..0000000 --- a/SOURCES/0139-install-always-export-KRA-agent-PEM-file.patch +++ /dev/null @@ -1,97 +0,0 @@ -From d644d5533a7ccf61cc557f8fe8a5ee1d93bc19fd Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Wed, 16 Sep 2015 09:05:20 +0200 -Subject: [PATCH] install: always export KRA agent PEM file - -Export the file even when KRA is not installed locally so that vault commands -work on all IPA replicas. - -https://fedorahosted.org/freeipa/ticket/5302 - -Reviewed-By: Martin Basti ---- - install/restart_scripts/renew_ra_cert | 3 +-- - ipaserver/install/cainstance.py | 8 ++++++-- - ipaserver/install/krainstance.py | 2 -- - ipaserver/install/server/upgrade.py | 5 ++--- - 4 files changed, 9 insertions(+), 9 deletions(-) - -diff --git a/install/restart_scripts/renew_ra_cert b/install/restart_scripts/renew_ra_cert -index 8a6bf3f7c1081db9710cf29e0f8e5f705d920b72..3a36f739ae53391e502356f7b6b4fd96a536c3a6 100644 ---- a/install/restart_scripts/renew_ra_cert -+++ b/install/restart_scripts/renew_ra_cert -@@ -61,8 +61,7 @@ def _main(): - # Load it into dogtag - cainstance.update_people_entry(dercert) - -- kra = krainstance.KRAInstance(api.env.realm) -- if kra.is_installed(): -+ if api.Command.kra_is_enabled()['result']: - krainstance.export_kra_agent_pem() - finally: - shutil.rmtree(tmpdir) -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index a4504a35a42b8c8ea2a96738c82c546ebebf569f..dfe023c08c9b8d1b28f1659b7c5a6395f3afe879 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -62,8 +62,8 @@ from ipaserver.install import certs - from ipaserver.install import dsinstance - from ipaserver.install import installutils - from ipaserver.install import service --from ipaserver.install.dogtaginstance import DogtagInstance --from ipaserver.install.dogtaginstance import PKI_USER, DEFAULT_DSPORT -+from ipaserver.install.dogtaginstance import ( -+ DEFAULT_DSPORT, PKI_USER, export_kra_agent_pem, DogtagInstance) - from ipaserver.plugins import ldap2 - - -@@ -885,6 +885,8 @@ class CAInstance(DogtagInstance): - finally: - os.remove(agent_name) - -+ export_kra_agent_pem() -+ - def import_ra_cert(self, rafile): - """ - Cloned RAs will use the same RA agent cert as the master so we -@@ -903,6 +905,8 @@ class CAInstance(DogtagInstance): - - self.configure_agent_renewal() - -+ export_kra_agent_pem() -+ - def __create_ca_agent(self): - """ - Create CA agent, assign a certificate, and add the user to -diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py -index 0000192745b6d7f9f402267e435f7223f1bf8849..69fe636732e6d3a8c1e0c460b641f061e519df92 100644 ---- a/ipaserver/install/krainstance.py -+++ b/ipaserver/install/krainstance.py -@@ -262,8 +262,6 @@ class KRAInstance(DogtagInstance): - - shutil.move(paths.KRA_BACKUP_KEYS_P12, paths.KRACERT_P12) - -- export_kra_agent_pem() -- - self.log.debug("completed creating KRA instance") - - def __create_kra_agent(self): -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index ab08c62352c0e5cf145f299e7727886b2f295037..51a2dd3d0e3693c12f11579a84175c7719651da9 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -1252,9 +1252,8 @@ def export_kra_agent_pem(): - root_logger.info("KRA agent PEM file already exported") - return - -- kra = krainstance.KRAInstance(api.env.realm) -- if not kra.is_installed(): -- root_logger.info("KRA is not installed") -+ if not api.Command.kra_is_enabled()['result']: -+ root_logger.info("KRA is not enabled") - return - - krainstance.export_kra_agent_pem() --- -2.4.3 - diff --git a/SOURCES/0140-vault-select-a-server-with-KRA-for-vault-operations.patch b/SOURCES/0140-vault-select-a-server-with-KRA-for-vault-operations.patch deleted file mode 100644 index d7b8678..0000000 --- a/SOURCES/0140-vault-select-a-server-with-KRA-for-vault-operations.patch +++ /dev/null @@ -1,72 +0,0 @@ -From f81f6028428f232052fa372bf3b11fa1e7b3905e Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Wed, 30 Sep 2015 09:05:33 +0200 -Subject: [PATCH] vault: select a server with KRA for vault operations - -This uses the same mechanism which is used for the CA. - -https://fedorahosted.org/freeipa/ticket/5302 - -Reviewed-By: Martin Basti ---- - ipalib/constants.py | 3 --- - ipaserver/plugins/dogtag.py | 22 +++++++++++++++++++++- - 2 files changed, 21 insertions(+), 4 deletions(-) - -diff --git a/ipalib/constants.py b/ipalib/constants.py -index 1509151bac7e0abca081cbba033701db410fc54c..0c5fc49456307ed261acb057ce6612274da2c453 100644 ---- a/ipalib/constants.py -+++ b/ipalib/constants.py -@@ -167,9 +167,6 @@ DEFAULT_CONFIG = ( - ('ca_agent_install_port', None), - ('ca_ee_install_port', None), - -- # KRA plugin -- ('kra_host', FQDN), # Set in Env._finalize_core() -- - # Topology plugin - ('recommended_max_agmts', 4), # Recommended maximum number of replication - # agreements -diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py -index 47279921a5428f388f84967b7bbe05d758e475bd..f5f8eb67067c87f07c06e556fb9fc73792fbbc64 100644 ---- a/ipaserver/plugins/dogtag.py -+++ b/ipaserver/plugins/dogtag.py -@@ -1902,6 +1902,26 @@ class kra(Backend): - - super(kra, self).__init__(api) - -+ @property -+ def kra_host(self): -+ """ -+ :return: host -+ as str -+ -+ Select our KRA host. -+ """ -+ ldap2 = self.api.Backend.ldap2 -+ if host_has_service(api.env.ca_host, ldap2, "KRA"): -+ return api.env.ca_host -+ if api.env.host != api.env.ca_host: -+ if host_has_service(api.env.host, ldap2, "KRA"): -+ return api.env.host -+ host = select_any_master(ldap2, "KRA") -+ if host: -+ return host -+ else: -+ return api.env.ca_host -+ - def get_client(self): - """ - Returns an authenticated KRA client to access KRA services. -@@ -1921,7 +1941,7 @@ class kra(Backend): - # https://fedorahosted.org/freeipa/ticket/4557 - connection = PKIConnection( - 'https', -- api.env.kra_host, -+ self.kra_host, - str(self.kra_port), - 'kra') - --- -2.4.3 - diff --git a/SOURCES/0141-schema-do-not-derive-ipaVaultPublicKey-from-ipaPubli.patch b/SOURCES/0141-schema-do-not-derive-ipaVaultPublicKey-from-ipaPubli.patch deleted file mode 100644 index fde35d7..0000000 --- a/SOURCES/0141-schema-do-not-derive-ipaVaultPublicKey-from-ipaPubli.patch +++ /dev/null @@ -1,32 +0,0 @@ -From a60d3bb3c3ccaf9e3055fbfe855f931bd71cd8b0 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Mon, 12 Oct 2015 08:04:38 +0200 -Subject: [PATCH] schema: do not derive ipaVaultPublicKey from ipaPublicKey - -This is a workaround for DS bug: -https://bugzilla.redhat.com/show_bug.cgi?id=1267782 - -https://fedorahosted.org/freeipa/ticket/5359 - -Reviewed-By: Alexander Bokovoy ---- - install/share/60basev3.ldif | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/install/share/60basev3.ldif b/install/share/60basev3.ldif -index 16d7c21d9291d1cd1bdc70f7d908191a7939dd56..f04044cc43efff737a1016e5870e7a322908dad5 100644 ---- a/install/share/60basev3.ldif -+++ b/install/share/60basev3.ldif -@@ -58,7 +58,8 @@ attributeTypes: (2.16.840.1.113730.3.8.11.70 NAME 'ipaPermTargetTo' DESC 'Destin - attributeTypes: (2.16.840.1.113730.3.8.11.71 NAME 'ipaPermTargetFrom' DESC 'Source location from where moving an entry IPA permission ACI' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE X-ORIGIN 'IPA v4.0' ) - attributeTypes: (2.16.840.1.113730.3.8.18.2.1 NAME 'ipaVaultType' DESC 'IPA vault type' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v4.2') - attributeTypes: (2.16.840.1.113730.3.8.18.2.2 NAME 'ipaVaultSalt' DESC 'IPA vault salt' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 X-ORIGIN 'IPA v4.2' ) --attributeTypes: (2.16.840.1.113730.3.8.18.2.3 NAME 'ipaVaultPublicKey' DESC 'IPA vault public key' SUP ipaPublicKey X-ORIGIN 'IPA v4.2' ) -+# FIXME: https://bugzilla.redhat.com/show_bug.cgi?id=1267782 -+attributeTypes: (2.16.840.1.113730.3.8.18.2.3 NAME 'ipaVaultPublicKey' DESC 'IPA vault public key' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 X-ORIGIN 'IPA v4.2' ) - objectClasses: (2.16.840.1.113730.3.8.12.1 NAME 'ipaExternalGroup' SUP top STRUCTURAL MUST ( cn ) MAY ( ipaExternalMember $ memberOf $ description $ owner) X-ORIGIN 'IPA v3' ) - objectClasses: (2.16.840.1.113730.3.8.12.2 NAME 'ipaNTUserAttrs' SUP top AUXILIARY MUST ( ipaNTSecurityIdentifier ) MAY ( ipaNTHash $ ipaNTLogonScript $ ipaNTProfilePath $ ipaNTHomeDirectory $ ipaNTHomeDirectoryDrive ) X-ORIGIN 'IPA v3' ) - objectClasses: (2.16.840.1.113730.3.8.12.3 NAME 'ipaNTGroupAttrs' SUP top AUXILIARY MUST ( ipaNTSecurityIdentifier ) X-ORIGIN 'IPA v3' ) --- -2.4.3 - diff --git a/SOURCES/0142-upgrade-make-sure-ldap2-is-connected-in-export_kra_a.patch b/SOURCES/0142-upgrade-make-sure-ldap2-is-connected-in-export_kra_a.patch deleted file mode 100644 index 02ef3e2..0000000 --- a/SOURCES/0142-upgrade-make-sure-ldap2-is-connected-in-export_kra_a.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 60cbb2471829504edb207c0914edd56a962593cf Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Mon, 12 Oct 2015 14:58:40 +0200 -Subject: [PATCH] upgrade: make sure ldap2 is connected in export_kra_agent_pem - -https://fedorahosted.org/freeipa/ticket/5360 - -Reviewed-By: Ales 'alich' Marecek ---- - ipaserver/install/server/upgrade.py | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index 51a2dd3d0e3693c12f11579a84175c7719651da9..e0a45a097171613397db42e1c035f0d818a3ecf5 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -1252,6 +1252,13 @@ def export_kra_agent_pem(): - root_logger.info("KRA agent PEM file already exported") - return - -+ if not api.Backend.ldap2.isconnected(): -+ try: -+ api.Backend.ldap2.connect(autobind=True) -+ except ipalib.errors.PublicError as e: -+ root_logger.error("Cannot connect to LDAP: %s", e) -+ return -+ - if not api.Command.kra_is_enabled()['result']: - root_logger.info("KRA is not enabled") - return --- -2.4.3 - diff --git a/SOURCES/0143-vault-fix-private-service-vault-creation.patch b/SOURCES/0143-vault-fix-private-service-vault-creation.patch deleted file mode 100644 index 58d5fee..0000000 --- a/SOURCES/0143-vault-fix-private-service-vault-creation.patch +++ /dev/null @@ -1,53 +0,0 @@ -From 997adec1729490ec9c3316862a4393002e708894 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Tue, 13 Oct 2015 10:10:48 +0200 -Subject: [PATCH] vault: fix private service vault creation - -https://fedorahosted.org/freeipa/ticket/5361 - -Reviewed-By: Petr Vobornik ---- - install/updates/40-vault.update | 3 ++- - ipalib/plugins/vault.py | 4 ++-- - 2 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/install/updates/40-vault.update b/install/updates/40-vault.update -index 3daea5b1988333d4d482463af0eec4163e4f0760..8d03f348c0ec9aded11f47bad5d1de6e013607cd 100644 ---- a/install/updates/40-vault.update -+++ b/install/updates/40-vault.update -@@ -7,8 +7,9 @@ remove: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0 - remove: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Indirect vault members can access the vault"; allow(read, search, compare) userattr="member#GROUPDN";) - remove: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Vault owners can manage the vault"; allow(read, search, compare, write) userattr="owner#USERDN";) - remove: aci: (targetfilter="(objectClass=ipaVault)")(targetattr="*")(version 3.0; acl "Indirect vault owners can manage the vault"; allow(read, search, compare, write) userattr="owner#GROUPDN";) -+remove: aci: (target="ldap:///cn=*,cn=services,cn=vaults,cn=kra,$SUFFIX")(targetfilter="(objectClass=ipaVaultContainer)")(version 3.0; acl "Allow services to create private container"; allow(add) userdn="ldap:///krbprincipalname=($$attr.cn)@$REALM,cn=services,cn=accounts,$SUFFIX" and userattr="owner#SELFDN";) - addifexist: aci: (target="ldap:///cn=*,cn=users,cn=vaults,cn=kra,$SUFFIX")(targetfilter="(objectClass=ipaVaultContainer)")(version 3.0; acl "Allow users to create private container"; allow(add) userdn="ldap:///uid=($$attr.cn),cn=users,cn=accounts,$SUFFIX" and userattr="owner#SELFDN";) --addifexist: aci: (target="ldap:///cn=*,cn=services,cn=vaults,cn=kra,$SUFFIX")(targetfilter="(objectClass=ipaVaultContainer)")(version 3.0; acl "Allow services to create private container"; allow(add) userdn="ldap:///krbprincipalname=($$attr.cn)@$REALM,cn=services,cn=accounts,$SUFFIX" and userattr="owner#SELFDN";) -+addifexist: aci: (target="ldap:///cn=*,cn=services,cn=vaults,cn=kra,$SUFFIX")(targetfilter="(objectClass=ipaVaultContainer)")(version 3.0; acl "Allow services to create private container"; allow(add) userdn="ldap:///krbprincipalname=($$attr.cn),cn=services,cn=accounts,$SUFFIX" and userattr="owner#SELFDN";) - addifexist: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description || owner")(version 3.0; acl "Container owners can access the container"; allow(read, search, compare) userattr="owner#USERDN";) - addifexist: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description || owner")(version 3.0; acl "Indirect container owners can access the container"; allow(read, search, compare) userattr="owner#GROUPDN";) - addifexist: aci: (targetfilter="(objectClass=ipaVaultContainer)")(targetattr="objectClass || cn || description")(version 3.0; acl "Container owners can manage the container"; allow(write, delete) userattr="owner#USERDN";) -diff --git a/ipalib/plugins/vault.py b/ipalib/plugins/vault.py -index 1159a84d58eb152cccdd791c96a1c876754bfa7d..d1d7f2a738999299bc9355a431e7adb6f514064e 100644 ---- a/ipalib/plugins/vault.py -+++ b/ipalib/plugins/vault.py -@@ -399,7 +399,7 @@ class vaultcontainer(LDAPObject): - - (name, realm) = split_principal(principal) - if '/' in name: -- service = name -+ service = principal - else: - user = name - -@@ -717,7 +717,7 @@ class vault(LDAPObject): - - (name, realm) = split_principal(principal) - if '/' in name: -- service = name -+ service = principal - else: - user = name - --- -2.4.3 - diff --git a/SOURCES/0144-install-fix-command-line-option-validation.patch b/SOURCES/0144-install-fix-command-line-option-validation.patch deleted file mode 100644 index 814b1f4..0000000 --- a/SOURCES/0144-install-fix-command-line-option-validation.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 4ab54ece01d015f6b4e58542e377f60bc6726815 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Mon, 2 Nov 2015 15:32:35 +0100 -Subject: [PATCH] install: fix command line option validation - -The code which calls the validators was accidentally removed, re-add it. - -https://fedorahosted.org/freeipa/ticket/5386 -https://fedorahosted.org/freeipa/ticket/5391 -https://fedorahosted.org/freeipa/ticket/5392 - -Reviewed-By: Martin Babinsky ---- - ipapython/install/cli.py | 7 +++++-- - ipapython/install/core.py | 3 ++- - 2 files changed, 7 insertions(+), 3 deletions(-) - -diff --git a/ipapython/install/cli.py b/ipapython/install/cli.py -index 1ba9a815c4c499dff0e7974f399f2de31eb932cd..f6cc0fc351fd1f9fc3f51987bbb938deca377fe1 100644 ---- a/ipapython/install/cli.py -+++ b/ipapython/install/cli.py -@@ -275,7 +275,8 @@ class ConfigureTool(admintool.AdminTool): - kwargs = {} - - transformed_cls = self._transform(self.configurable_class) -- for owner_cls, name in transformed_cls.knobs(): -+ knob_classes = {n: getattr(c, n) for c, n in transformed_cls.knobs()} -+ for name in knob_classes: - value = getattr(self.options, name, None) - if value is not None: - kwargs[name] = value -@@ -287,8 +288,10 @@ class ConfigureTool(admintool.AdminTool): - try: - cfgr = transformed_cls(**kwargs) - except core.KnobValueError as e: -- knob_cls = getattr(transformed_cls, e.name) -+ knob_cls = knob_classes[e.name] - try: -+ if self.positional_arguments is None: -+ raise IndexError - index = self.positional_arguments.index(e.name) - except IndexError: - cli_name = knob_cls.cli_name or e.name.replace('_', '-') -diff --git a/ipapython/install/core.py b/ipapython/install/core.py -index c313c278e09cbf68e4f5c4b4c57f00d6e2870bea..91ae854cdb2a8846e2a2673a5bfe54b4f75f3823 100644 ---- a/ipapython/install/core.py -+++ b/ipapython/install/core.py -@@ -226,7 +226,8 @@ class Configurable(object): - except KeyError: - pass - else: -- setattr(self, name, value) -+ prop = knob_cls(self) -+ prop.__set__(self, value) - - if kwargs: - extra = sorted(kwargs.keys()) --- -2.4.3 - diff --git a/SOURCES/0145-install-export-KRA-agent-PEM-file-in-ipa-kra-install.patch b/SOURCES/0145-install-export-KRA-agent-PEM-file-in-ipa-kra-install.patch deleted file mode 100644 index fa18aa2..0000000 --- a/SOURCES/0145-install-export-KRA-agent-PEM-file-in-ipa-kra-install.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 11856273c3819b58f8b5aa28aab2046ff113ffbe Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Thu, 19 Nov 2015 08:50:05 +0100 -Subject: [PATCH] install: export KRA agent PEM file in ipa-kra-install - -https://fedorahosted.org/freeipa/ticket/5462 - -Reviewed-By: Martin Babinsky ---- - ipaserver/install/krainstance.py | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py -index 69fe636732e6d3a8c1e0c460b641f061e519df92..0000192745b6d7f9f402267e435f7223f1bf8849 100644 ---- a/ipaserver/install/krainstance.py -+++ b/ipaserver/install/krainstance.py -@@ -262,6 +262,8 @@ class KRAInstance(DogtagInstance): - - shutil.move(paths.KRA_BACKUP_KEYS_P12, paths.KRACERT_P12) - -+ export_kra_agent_pem() -+ - self.log.debug("completed creating KRA instance") - - def __create_kra_agent(self): --- -2.4.3 - diff --git a/SOURCES/0146-cert-renewal-make-renewal-of-ipaCert-atomic.patch b/SOURCES/0146-cert-renewal-make-renewal-of-ipaCert-atomic.patch deleted file mode 100644 index b7e43e9..0000000 --- a/SOURCES/0146-cert-renewal-make-renewal-of-ipaCert-atomic.patch +++ /dev/null @@ -1,111 +0,0 @@ -From 09ead70bf9a081d8e2961a83d5dfe64d8f4c0399 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Mon, 9 Nov 2015 10:53:02 +0100 -Subject: [PATCH] cert renewal: make renewal of ipaCert atomic - -This prevents errors when renewing other certificates during the renewal of -ipaCert. - -https://fedorahosted.org/freeipa/ticket/5436 - -Reviewed-By: David Kupka ---- - install/restart_scripts/Makefile.am | 1 + - install/restart_scripts/renew_ra_cert | 5 ++++- - install/restart_scripts/renew_ra_cert_pre | 18 ++++++++++++++++++ - ipaserver/install/cainstance.py | 2 +- - ipaserver/install/server/upgrade.py | 4 ++-- - 5 files changed, 26 insertions(+), 4 deletions(-) - create mode 100755 install/restart_scripts/renew_ra_cert_pre - -diff --git a/install/restart_scripts/Makefile.am b/install/restart_scripts/Makefile.am -index 58057aa3198c892fc8ebb0df403495566ed77d1d..c4bf8195ea85ee0a9dba53fc2581e90c18a9127d 100644 ---- a/install/restart_scripts/Makefile.am -+++ b/install/restart_scripts/Makefile.am -@@ -7,6 +7,7 @@ app_DATA = \ - renew_ca_cert \ - renew_ra_cert \ - stop_pkicad \ -+ renew_ra_cert_pre \ - $(NULL) - - EXTRA_DIST = \ -diff --git a/install/restart_scripts/renew_ra_cert b/install/restart_scripts/renew_ra_cert -index 3a36f739ae53391e502356f7b6b4fd96a536c3a6..988ada946aed47d1f2b76c1add48ea8c8d64a161 100644 ---- a/install/restart_scripts/renew_ra_cert -+++ b/install/restart_scripts/renew_ra_cert -@@ -77,8 +77,11 @@ def _main(): - - - def main(): -- with certs.renewal_lock: -+ try: - _main() -+ finally: -+ # lock acquired in renew_ra_cert_pre -+ certs.renewal_lock.release('renew_ra_cert') - - - try: -diff --git a/install/restart_scripts/renew_ra_cert_pre b/install/restart_scripts/renew_ra_cert_pre -new file mode 100755 -index 0000000000000000000000000000000000000000..d0f743c099162e4c5afd7d96287e58492246db35 ---- /dev/null -+++ b/install/restart_scripts/renew_ra_cert_pre -@@ -0,0 +1,18 @@ -+#!/usr/bin/python2 -E -+# -+# Copyright (C) 2015 FreeIPA Contributors see COPYING for license -+# -+ -+import syslog -+import traceback -+ -+from ipaserver.install import certs -+ -+ -+def main(): -+ certs.renewal_lock.acquire('renew_ra_cert') -+ -+try: -+ main() -+except Exception: -+ syslog.syslog(syslog.LOG_ERR, traceback.format_exc()) -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index dfe023c08c9b8d1b28f1659b7c5a6395f3afe879..d230c9bdcab68f02cce32a2aeb89ca3e2143eefe 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -1305,7 +1305,7 @@ class CAInstance(DogtagInstance): - pin=None, - pinfile=paths.ALIAS_PWDFILE_TXT, - secdir=paths.HTTPD_ALIAS_DIR, -- pre_command=None, -+ pre_command='renew_ra_cert_pre', - post_command='renew_ra_cert') - except RuntimeError, e: - self.log.error( -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index e0a45a097171613397db42e1c035f0d818a3ecf5..c8f744c392c7b859459bda63c1f397226553d4ba 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -799,7 +799,7 @@ def certificate_renewal_update(ca): - dogtag_constants = dogtag.configured_constants() - - # bump version when requests is changed -- version = 3 -+ version = 4 - requests = ( - ( - dogtag_constants.ALIAS_DIR, -@@ -837,7 +837,7 @@ def certificate_renewal_update(ca): - paths.HTTPD_ALIAS_DIR, - 'ipaCert', - 'dogtag-ipa-ca-renew-agent', -- None, -+ 'renew_ra_cert_pre', - 'renew_ra_cert', - None, - ), --- -2.4.3 - diff --git a/SOURCES/0147-suppress-errors-arising-from-adding-existing-LDAP-en.patch b/SOURCES/0147-suppress-errors-arising-from-adding-existing-LDAP-en.patch deleted file mode 100644 index 919da9e..0000000 --- a/SOURCES/0147-suppress-errors-arising-from-adding-existing-LDAP-en.patch +++ /dev/null @@ -1,73 +0,0 @@ -From a41ee5aef75e47667defc7b01b89a25309bd4c8d Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Thu, 19 Nov 2015 14:33:49 +0100 -Subject: [PATCH] suppress errors arising from adding existing LDAP entries - during KRA install - -https://fedorahosted.org/freeipa/ticket/5346 - -Reviewed-By: Jan Cholasta ---- - ipaserver/install/krainstance.py | 16 ++++++++++++++-- - ipaserver/install/service.py | 4 +++- - 2 files changed, 17 insertions(+), 3 deletions(-) - -diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py -index 0000192745b6d7f9f402267e435f7223f1bf8849..a2514debae600bdc46afb92e426a5f616529fde2 100644 ---- a/ipaserver/install/krainstance.py -+++ b/ipaserver/install/krainstance.py -@@ -47,6 +47,8 @@ from ipapython.ipa_log_manager import log_mgr - IPA_KRA_RECORD = "ipa-kra" - - -+LDAPMOD_ERR_ALREADY_EXISTS = 68 -+ - class KRAInstance(DogtagInstance): - """ - We assume that the CA has already been installed, and we use the -@@ -308,8 +310,18 @@ class KRAInstance(DogtagInstance): - conn.disconnect() - - def __add_vault_container(self): -- self._ldap_mod('vault.ldif', {'SUFFIX': self.suffix}) -- self.ldap_disconnect() -+ try: -+ self._ldap_mod('vault.ldif', {'SUFFIX': self.suffix}, -+ raise_on_err=True) -+ except ipautil.CalledProcessError as e: -+ if e.returncode == LDAPMOD_ERR_ALREADY_EXISTS: -+ self.log.debug("Vault container already exists") -+ else: -+ self.log.error("Failed to add vault container: {0}".format(e)) -+ finally: -+ # we need to disconnect from LDAP, because _ldap_mod() makes the -+ # connection without actually using it -+ self.ldap_disconnect() - - def __apply_updates(self): - sub_dict = { -diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py -index 2f5f565b16b42bf82889f9d32b80cf6fa584d438..597c20a60c712a6e521a7b9471f6732cceb27fe7 100644 ---- a/ipaserver/install/service.py -+++ b/ipaserver/install/service.py -@@ -155,7 +155,7 @@ class Service(object): - self.admin_conn.unbind() - self.admin_conn = None - -- def _ldap_mod(self, ldif, sub_dict=None): -+ def _ldap_mod(self, ldif, sub_dict=None, raise_on_err=False): - pw_name = None - fd = None - path = ipautil.SHARE_DIR + ldif -@@ -199,6 +199,8 @@ class Service(object): - try: - ipautil.run(args, nolog=nologlist) - except ipautil.CalledProcessError, e: -+ if raise_on_err: -+ raise - root_logger.critical("Failed to load %s: %s" % (ldif, str(e))) - finally: - if pw_name: --- -2.4.3 - diff --git a/SOURCES/0148-fix-caching-in-get_ipa_config.patch b/SOURCES/0148-fix-caching-in-get_ipa_config.patch deleted file mode 100644 index af0084c..0000000 --- a/SOURCES/0148-fix-caching-in-get_ipa_config.patch +++ /dev/null @@ -1,31 +0,0 @@ -From 823340f96f16ee7924ba6ce54c8fe43e3ea41469 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Thu, 19 Nov 2015 13:25:49 +0100 -Subject: [PATCH] fix caching in get_ipa_config - -Different opbject types were compared thus always result of comparation -was False and caching does not work. - -https://fedorahosted.org/freeipa/ticket/5463 - -Reviewed-By: Jan Cholasta ---- - 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 deb0592ab68ab8eb712a6d29fdffd8776e2e289a..5d2945f90f54ba2a099271a3715f4f9c14866e97 100644 ---- a/ipaserver/plugins/ldap2.py -+++ b/ipaserver/plugins/ldap2.py -@@ -204,7 +204,7 @@ class ldap2(CrudBackend, LDAPClient): - - try: - config_entry = getattr(context, 'config_entry') -- if config_entry.conn is self.conn: -+ if config_entry.conn.conn is self.conn: - return config_entry - except AttributeError: - # Not in our context yet --- -2.4.3 - diff --git a/SOURCES/0149-client-install-do-not-corrupt-OpenSSH-config-with-Ma.patch b/SOURCES/0149-client-install-do-not-corrupt-OpenSSH-config-with-Ma.patch deleted file mode 100644 index 9513440..0000000 --- a/SOURCES/0149-client-install-do-not-corrupt-OpenSSH-config-with-Ma.patch +++ /dev/null @@ -1,56 +0,0 @@ -From 64dc38643ead5cb00f3f42562a92769de10ef7b5 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Fri, 20 Nov 2015 09:35:43 +0100 -Subject: [PATCH] client install: do not corrupt OpenSSH config with Match - sections - -https://fedorahosted.org/freeipa/ticket/5461 - -Reviewed-By: Martin Babinsky ---- - ipa-client/ipa-install/ipa-client-install | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install -index 793de4fc950ad73b1d88f9ab4bd5178afc8b813d..543c6f027f2312792e7ad33533db8e7c10a3cddb 100755 ---- a/ipa-client/ipa-install/ipa-client-install -+++ b/ipa-client/ipa-install/ipa-client-install -@@ -1330,6 +1330,7 @@ def change_ssh_config(filename, changes, sections): - section_keys = tuple(key.lower() for key in sections) - - lines = [] -+ in_section = False - for line in f: - line = line.rstrip('\n') - pline = line.strip() -@@ -1338,7 +1339,7 @@ def change_ssh_config(filename, changes, sections): - continue - option = pline.split()[0].lower() - if option in section_keys: -- lines.append(line) -+ in_section = True - break - if option in change_keys: - line = '#' + line -@@ -1346,6 +1347,9 @@ def change_ssh_config(filename, changes, sections): - for option, value in changes.items(): - if value is not None: - lines.append('%s %s' % (option, value)) -+ if in_section: -+ lines.append('') -+ lines.append(line) - for line in f: - line = line.rstrip('\n') - lines.append(line) -@@ -1386,7 +1390,7 @@ def configure_ssh_config(fstore, options): - changes['VerifyHostKeyDNS'] = 'yes' - changes['HostKeyAlgorithms'] = 'ssh-rsa,ssh-dss' - -- change_ssh_config(ssh_config, changes, ['Host']) -+ change_ssh_config(ssh_config, changes, ['Host', 'Match']) - root_logger.info('Configured %s', ssh_config) - - def configure_sshd_config(fstore, options): --- -2.4.3 - diff --git a/SOURCES/0150-upgrade-fix-migration-of-old-dns-forward-zones.patch b/SOURCES/0150-upgrade-fix-migration-of-old-dns-forward-zones.patch deleted file mode 100644 index d5bf1d4..0000000 --- a/SOURCES/0150-upgrade-fix-migration-of-old-dns-forward-zones.patch +++ /dev/null @@ -1,221 +0,0 @@ -From 7623bc99813156ce11167ae429a756f920258151 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Fri, 20 Nov 2015 11:53:06 +0100 -Subject: [PATCH] upgrade: fix migration of old dns forward zones - -Plugins should call self.api not the global one during upgrade - -https://fedorahosted.org/freeipa/ticket/5472 - -Reviewed-By: Petr Spacek ---- - ipalib/plugins/dns.py | 51 +++++++++++++++++++++++++++------------------------ - 1 file changed, 27 insertions(+), 24 deletions(-) - -diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py -index a3d562edb186682a872073e6c83a416b6a4cbc09..37a2c64cbacae5cc5626f17fac68848768af3242 100644 ---- a/ipalib/plugins/dns.py -+++ b/ipalib/plugins/dns.py -@@ -1735,7 +1735,7 @@ def _normalize_zone(zone): - return zone - - --def _get_auth_zone_ldap(name): -+def _get_auth_zone_ldap(api, name): - """ - Find authoritative zone in LDAP for name. Only active zones are considered. - :param name: -@@ -1781,7 +1781,7 @@ def _get_auth_zone_ldap(name): - return max(matched_auth_zones, key=len), truncated - - --def _get_longest_match_ns_delegation_ldap(zone, name): -+def _get_longest_match_ns_delegation_ldap(api, zone, name): - """ - Searches for deepest delegation for name in LDAP zone. - -@@ -1857,7 +1857,7 @@ def _get_longest_match_ns_delegation_ldap(zone, name): - return max(matched_records, key=len), truncated - - --def _find_subtree_forward_zones_ldap(name, child_zones_only=False): -+def _find_subtree_forward_zones_ldap(api, name, child_zones_only=False): - """ - Search for forwardzone and all child forwardzones - Filter: (|(*..)(.)) -@@ -1911,7 +1911,7 @@ def _find_subtree_forward_zones_ldap(name, child_zones_only=False): - return result, truncated - - --def _get_zone_which_makes_fw_zone_ineffective(fwzonename): -+def _get_zone_which_makes_fw_zone_ineffective(api, fwzonename): - """ - Check if forward zone is effective. - -@@ -1936,12 +1936,12 @@ def _get_zone_which_makes_fw_zone_ineffective(fwzonename): - """ - assert isinstance(fwzonename, DNSName) - -- auth_zone, truncated_zone = _get_auth_zone_ldap(fwzonename) -+ auth_zone, truncated_zone = _get_auth_zone_ldap(api, fwzonename) - if not auth_zone: - return None, truncated_zone - - delegation_record_name, truncated_ns =\ -- _get_longest_match_ns_delegation_ldap(auth_zone, fwzonename) -+ _get_longest_match_ns_delegation_ldap(api, auth_zone, fwzonename) - - truncated = truncated_ns or truncated_zone - -@@ -1951,12 +1951,12 @@ def _get_zone_which_makes_fw_zone_ineffective(fwzonename): - return auth_zone, truncated - - --def _add_warning_fw_zone_is_not_effective(result, fwzone, version): -+def _add_warning_fw_zone_is_not_effective(api, result, fwzone, version): - """ - Adds warning message to result, if required - """ - authoritative_zone, truncated = \ -- _get_zone_which_makes_fw_zone_ineffective(fwzone) -+ _get_zone_which_makes_fw_zone_ineffective(api, fwzone) - if authoritative_zone: - # forward zone is not effective and forwarding will not work - messages.add_message( -@@ -2072,7 +2072,7 @@ class DNSZoneBase(LDAPObject): - def _remove_permission(self, zone): - permission_name = self.permission_name(zone) - try: -- api.Command['permission_del'](permission_name, force=True) -+ self.api.Command['permission_del'](permission_name, force=True) - except errors.NotFound, e: - if zone == DNSName.root: # special case root zone - raise -@@ -2082,7 +2082,8 @@ class DNSZoneBase(LDAPObject): - zone.relativize(DNSName.root) - ) - try: -- api.Command['permission_del'](permission_name_rel, force=True) -+ self.api.Command['permission_del'](permission_name_rel, -+ force=True) - except errors.NotFound: - raise e # re-raise original exception - -@@ -2272,7 +2273,8 @@ class DNSZoneBase_add_permission(LDAPQuery): - keys[-1].relativize(DNSName.root) - ) - try: -- api.Object['permission'].get_dn_if_exists(permission_name_rel) -+ self.api.Object['permission'].get_dn_if_exists( -+ permission_name_rel) - except errors.NotFound: - pass - else: -@@ -2283,7 +2285,7 @@ class DNSZoneBase_add_permission(LDAPQuery): - } - ) - -- permission = api.Command['permission_add_noaci'](permission_name, -+ permission = self.api.Command['permission_add_noaci'](permission_name, - ipapermissiontype=u'SYSTEM' - )['result'] - -@@ -2643,12 +2645,12 @@ class dnszone(DNSZoneBase): - """ - zone = keys[-1] - affected_fw_zones, truncated = _find_subtree_forward_zones_ldap( -- zone, child_zones_only=True) -+ self.api, zone, child_zones_only=True) - if not affected_fw_zones: - return - - for fwzone in affected_fw_zones: -- _add_warning_fw_zone_is_not_effective(result, fwzone, -+ _add_warning_fw_zone_is_not_effective(self.api, result, fwzone, - options['version']) - - -@@ -2686,7 +2688,8 @@ class dnszone_add(DNSZoneBase_add): - dn = super(dnszone_add, self).pre_callback( - ldap, dn, entry_attrs, attrs_list, *keys, **options) - -- nameservers = [normalize_zone(x) for x in api.Object.dnsrecord.get_dns_masters()] -+ nameservers = [normalize_zone(x) for x in -+ self.api.Object.dnsrecord.get_dns_masters()] - server = normalize_zone(api.env.host) - zone = keys[-1] - -@@ -2735,7 +2738,7 @@ class dnszone_add(DNSZoneBase_add): - not zone.is_reverse() and - zone != DNSName.root): - try: -- api.Command['realmdomains_mod'](add_domain=unicode(zone), -+ self.api.Command['realmdomains_mod'](add_domain=unicode(zone), - force=True) - except (errors.EmptyModlist, errors.ValidationError): - pass -@@ -2769,8 +2772,8 @@ class dnszone_del(DNSZoneBase_del): - not zone.is_reverse() and zone != DNSName.root - ): - try: -- api.Command['realmdomains_mod'](del_domain=unicode(zone), -- force=True) -+ self.api.Command['realmdomains_mod']( -+ del_domain=unicode(zone), force=True) - except (errors.AttrValueNotFound, errors.ValidationError): - pass - -@@ -3476,12 +3479,12 @@ class dnsrecord(LDAPObject): - record_name_absolute = record_name_absolute.derelativize(zone) - - affected_fw_zones, truncated = _find_subtree_forward_zones_ldap( -- record_name_absolute) -+ self.api, record_name_absolute) - if not affected_fw_zones: - return - - for fwzone in affected_fw_zones: -- _add_warning_fw_zone_is_not_effective(result, fwzone, -+ _add_warning_fw_zone_is_not_effective(self.api, result, fwzone, - options['version']) - - -@@ -3831,7 +3834,7 @@ class dnsrecord_mod(LDAPUpdate): - - # get DNS record first so that the NotFound exception is raised - # before the helper would start -- dns_record = api.Command['dnsrecord_show'](kw['dnszoneidnsname'], kw['idnsname'])['result'] -+ dns_record = self.api.Command['dnsrecord_show'](kw['dnszoneidnsname'], kw['idnsname'])['result'] - rec_types = [rec_type for rec_type in dns_record if rec_type in _record_attributes] - - self.Backend.textui.print_plain(_("No option to modify specific record provided.")) -@@ -4019,7 +4022,7 @@ class dnsrecord_del(LDAPUpdate): - - # get DNS record first so that the NotFound exception is raised - # before the helper would start -- dns_record = api.Command['dnsrecord_show'](kw['dnszoneidnsname'], kw['idnsname'])['result'] -+ dns_record = self.api.Command['dnsrecord_show'](kw['dnszoneidnsname'], kw['idnsname'])['result'] - rec_types = [rec_type for rec_type in dns_record if rec_type in _record_attributes] - - self.Backend.textui.print_plain(_("No option to delete specific record provided.")) -@@ -4334,7 +4337,7 @@ class dnsforwardzone(DNSZoneBase): - - def _warning_fw_zone_is_not_effective(self, result, *keys, **options): - fwzone = keys[-1] -- _add_warning_fw_zone_is_not_effective(result, fwzone, -+ _add_warning_fw_zone_is_not_effective(self.api, result, fwzone, - options['version']) - - def _warning_if_forwarders_do_not_work(self, result, new_zone, -@@ -4374,7 +4377,7 @@ class dnsforwardzone(DNSZoneBase): - # validation is configured just in named.conf per replica - - ipa_dns_masters = [normalize_zone(x) for x in -- api.Object.dnsrecord.get_dns_masters()] -+ self.api.Object.dnsrecord.get_dns_masters()] - - if not ipa_dns_masters: - # something very bad happened, DNS is installed, but no IPA DNS --- -2.4.3 - diff --git a/SOURCES/0151-TLS-and-Dogtag-HTTPS-request-logging-improvements.patch b/SOURCES/0151-TLS-and-Dogtag-HTTPS-request-logging-improvements.patch deleted file mode 100644 index 43f99b9..0000000 --- a/SOURCES/0151-TLS-and-Dogtag-HTTPS-request-logging-improvements.patch +++ /dev/null @@ -1,62 +0,0 @@ -From c54278c3c90bb5999e1b7c2ed745f6f2b2a83d19 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Fri, 20 Nov 2015 15:39:00 +1100 -Subject: [PATCH] TLS and Dogtag HTTPS request logging improvements - -Pretty printing the TLS peer certificate to logs on every request -introduces a lot of noise; do not log it (subject name, key usage -and validity are still logged). - -Fix and tidy up some HTTP logging messages for Dogtag requests. - -Part of: https://fedorahosted.org/freeipa/ticket/5269 - -Reviewed-By: Jan Cholasta ---- - ipapython/dogtag.py | 9 ++++----- - ipapython/nsslib.py | 3 --- - 2 files changed, 4 insertions(+), 8 deletions(-) - -diff --git a/ipapython/dogtag.py b/ipapython/dogtag.py -index 3f0d08154d21a3072e344c311c3e70e414d9dee4..26b2de6ca77202fa9ccc61ee16ed7623e10ecb5f 100644 ---- a/ipapython/dogtag.py -+++ b/ipapython/dogtag.py -@@ -314,7 +314,7 @@ def _httplib_request( - if isinstance(host, unicode): - host = host.encode('utf-8') - uri = '%s://%s%s' % (protocol, ipautil.format_netloc(host, port), path) -- root_logger.debug('request %r', uri) -+ root_logger.debug('request %s %s', method, uri) - root_logger.debug('request body %r', request_body) - - headers = headers or {} -@@ -337,9 +337,8 @@ def _httplib_request( - except Exception, e: - raise NetworkError(uri=uri, error=str(e)) - -- root_logger.debug('request status %d', http_status) -- root_logger.debug('request reason_phrase %r', http_reason_phrase) -- root_logger.debug('request headers %s', http_headers) -- root_logger.debug('request body %r', http_body) -+ root_logger.debug('response status %d %s', http_status, http_reason_phrase) -+ root_logger.debug('response headers %s', http_headers) -+ root_logger.debug('response body %r', http_body) - - return http_status, http_reason_phrase, http_headers, http_body -diff --git a/ipapython/nsslib.py b/ipapython/nsslib.py -index def6b104e18fa67268a8c5a8629b533783fb5a95..79b8dc5be6a26cd6136ac62a4fa49572d765a9a0 100644 ---- a/ipapython/nsslib.py -+++ b/ipapython/nsslib.py -@@ -39,9 +39,6 @@ def auth_certificate_callback(sock, check_sig, is_server, certdb): - - cert = sock.get_peer_certificate() - -- root_logger.debug("auth_certificate_callback: check_sig=%s is_server=%s\n%s", -- check_sig, is_server, str(cert)) -- - pin_args = sock.get_pkcs11_pin_arg() - if pin_args is None: - pin_args = () --- -2.4.3 - diff --git a/SOURCES/0152-Avoid-race-condition-caused-by-profile-delete-and-re.patch b/SOURCES/0152-Avoid-race-condition-caused-by-profile-delete-and-re.patch deleted file mode 100644 index 45b175c..0000000 --- a/SOURCES/0152-Avoid-race-condition-caused-by-profile-delete-and-re.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 08d26c374ae6198b5a1ec59556ca8814329b845f Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Fri, 20 Nov 2015 15:59:11 +1100 -Subject: [PATCH] Avoid race condition caused by profile delete and recreate - -When importing IPA-managed certificate profiles into Dogtag, -profiles with the same name (usually caIPAserviceCert) are removed, -then immediately recreated with the new profile data. This causes a -race condition - Dogtag's LDAPProfileSystem profileChangeMonitor -thread could observe and process the deletion after the profile was -recreated, disappearing it again. - -Update the profile instead of deleting and recreating it to avoid -this race condition. - -Fixes: https://fedorahosted.org/freeipa/ticket/5269 -Reviewed-By: Jan Cholasta ---- - ipaserver/install/cainstance.py | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index d230c9bdcab68f02cce32a2aeb89ca3e2143eefe..3e3dce93de2b8ca48a3fe3ea5994ee92a1b0ce49 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -1812,8 +1812,7 @@ def _create_dogtag_profile(profile_id, profile_data): - root_logger.debug( - "Failed to disable profile '%s' " - "(it is probably already disabled)") -- profile_api.delete_profile(profile_id) -- profile_api.create_profile(profile_data) -+ profile_api.update_profile(profile_id, profile_data) - - # enable the profile - try: --- -2.4.3 - diff --git a/SOURCES/0153-ipa-cacert-renew-Fix-connection-to-ldap.patch b/SOURCES/0153-ipa-cacert-renew-Fix-connection-to-ldap.patch deleted file mode 100644 index f686c28..0000000 --- a/SOURCES/0153-ipa-cacert-renew-Fix-connection-to-ldap.patch +++ /dev/null @@ -1,117 +0,0 @@ -From 87f6b21c9bc837cf90fc8b9d0708aeff060e48f3 Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Mon, 23 Nov 2015 06:38:17 +0000 -Subject: [PATCH] ipa-cacert-renew: Fix connection to ldap. - -https://fedorahosted.org/freeipa/ticket/5468 - -Reviewed-By: Jan Cholasta ---- - ipaserver/install/ipa_cacert_manage.py | 32 ++++++++++++++------------------ - 1 file changed, 14 insertions(+), 18 deletions(-) - -diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py -index 01ec805fc2094326d119827b4358c143f45f3ec4..8790b7066d7641864f8d83c6339cd0a73c620be0 100644 ---- a/ipaserver/install/ipa_cacert_manage.py -+++ b/ipaserver/install/ipa_cacert_manage.py -@@ -105,9 +105,7 @@ class CACertManage(admintool.AdminTool): - - if ((command == 'renew' and options.external_cert_files) or - command == 'install'): -- self.conn = self.ldap_connect() -- else: -- self.conn = None -+ self.ldap_connect() - - try: - if command == 'renew': -@@ -115,23 +113,21 @@ class CACertManage(admintool.AdminTool): - elif command == 'install': - rc = self.install() - finally: -- if self.conn is not None: -- self.conn.disconnect() -+ if api.Backend.ldap2.isconnected(): -+ api.Backend.ldap2.disconnect() - - return rc - - def ldap_connect(self): -- conn = ldap2(api) -- - password = self.options.password - if not password: - try: - ccache = krbV.default_context().default_ccache() -- conn.connect(ccache=ccache) -+ api.Backend.ldap2.connect(ccache=ccache) - except (krbV.Krb5Error, errors.ACIError): - pass - else: -- return conn -+ return - - password = installutils.read_password( - "Directory Manager", confirm=False, validate=False) -@@ -139,9 +135,8 @@ class CACertManage(admintool.AdminTool): - raise admintool.ScriptError( - "Directory Manager password required") - -- conn.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=password) -+ api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=password) - -- return conn - - def renew(self): - ca = cainstance.CAInstance(api.env.realm, certs.NSS_DIR) -@@ -202,9 +197,10 @@ class CACertManage(admintool.AdminTool): - "--external-cert-file=/path/to/external_ca_certificate") - - def renew_external_step_2(self, ca, old_cert): -- print "Importing the renewed CA certificate, please wait" -+ print("Importing the renewed CA certificate, please wait") - - options = self.options -+ conn = api.Backend.ldap2 - cert_file, ca_file = installutils.load_external_cert( - options.external_cert_files, x509.subject_base()) - -@@ -273,21 +269,21 @@ class CACertManage(admintool.AdminTool): - except RuntimeError: - break - certstore.put_ca_cert_nss( -- self.conn, api.env.basedn, ca_cert, nickname, ',,') -+ conn, api.env.basedn, ca_cert, nickname, ',,') - - dn = DN(('cn', self.cert_nickname), ('cn', 'ca_renewal'), - ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn) - try: -- entry = self.conn.get_entry(dn, ['usercertificate']) -+ entry = conn.get_entry(dn, ['usercertificate']) - entry['usercertificate'] = [cert] -- self.conn.update_entry(entry) -+ conn.update_entry(entry) - except errors.NotFound: -- entry = self.conn.make_entry( -+ entry = conn.make_entry( - dn, - objectclass=['top', 'pkiuser', 'nscontainer'], - cn=[self.cert_nickname], - usercertificate=[cert]) -- self.conn.add_entry(entry) -+ conn.add_entry(entry) - except errors.EmptyModlist: - pass - -@@ -362,7 +358,7 @@ class CACertManage(admintool.AdminTool): - - try: - certstore.put_ca_cert_nss( -- self.conn, api.env.basedn, cert, nickname, trust_flags) -+ api.Backend.ldap2, api.env.basedn, cert, nickname, trust_flags) - except ValueError, e: - raise admintool.ScriptError( - "Failed to install the certificate: %s" % e) --- -2.4.3 - diff --git a/SOURCES/0154-ipa-otptoken-import-Fix-connection-to-ldap.patch b/SOURCES/0154-ipa-otptoken-import-Fix-connection-to-ldap.patch deleted file mode 100644 index f47d768..0000000 --- a/SOURCES/0154-ipa-otptoken-import-Fix-connection-to-ldap.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 23adad20399216198b34d9eadaf53b95f755d0be Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Mon, 23 Nov 2015 07:48:40 +0000 -Subject: [PATCH] ipa-otptoken-import: Fix connection to ldap. - -https://fedorahosted.org/freeipa/ticket/5475 - -Reviewed-By: Jan Cholasta ---- - ipaserver/install/ipa_otptoken_import.py | 5 ++--- - 1 file changed, 2 insertions(+), 3 deletions(-) - -diff --git a/ipaserver/install/ipa_otptoken_import.py b/ipaserver/install/ipa_otptoken_import.py -index 386ca4273c413d9f6a121956d0db3f0c44fe5c24..9be44cfe677a7d33ce3ec7725e23fdbf8141190a 100644 ---- a/ipaserver/install/ipa_otptoken_import.py -+++ b/ipaserver/install/ipa_otptoken_import.py -@@ -507,10 +507,9 @@ class OTPTokenImport(admintool.AdminTool): - api.bootstrap(in_server=True) - api.finalize() - -- conn = ldap2(api) - try: - ccache = krbV.default_context().default_ccache() -- conn.connect(ccache=ccache) -+ api.Backend.ldap2.connect(ccache=ccache) - except (krbV.Krb5Error, errors.ACIError): - raise admintool.ScriptError("Unable to connect to LDAP! Did you kinit?") - -@@ -525,7 +524,7 @@ class OTPTokenImport(admintool.AdminTool): - self.log.info("Added token: %s", keypkg.id) - keypkg.remove() - finally: -- conn.disconnect() -+ api.Backend.ldap2.disconnect() - - # Write out the XML file without the tokens that succeeded. - self.doc.save(self.output) --- -2.4.3 - diff --git a/SOURCES/0155-Do-not-erroneously-reinit-NSS-in-Dogtag-interface.patch b/SOURCES/0155-Do-not-erroneously-reinit-NSS-in-Dogtag-interface.patch deleted file mode 100644 index 2120e45..0000000 --- a/SOURCES/0155-Do-not-erroneously-reinit-NSS-in-Dogtag-interface.patch +++ /dev/null @@ -1,33 +0,0 @@ -From b5aec7bdc5a164133b247925c41d1d41e29a63e5 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Mon, 23 Nov 2015 12:09:32 +1100 -Subject: [PATCH] Do not erroneously reinit NSS in Dogtag interface - -The Dogtag interface always attempts to (re)init NSS, which can fail -with SEC_ERROR_BUSY. Do not reinitialise NSS when it has already -been initialised with the given dbdir. - -Part of: https://fedorahosted.org/freeipa/ticket/5459 - -Reviewed-By: Jan Cholasta ---- - ipapython/dogtag.py | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/ipapython/dogtag.py b/ipapython/dogtag.py -index 26b2de6ca77202fa9ccc61ee16ed7623e10ecb5f..8996902ba92f0fdd6106e2650c2decde375c593b 100644 ---- a/ipapython/dogtag.py -+++ b/ipapython/dogtag.py -@@ -255,7 +255,8 @@ def https_request(host, port, url, secdir, password, nickname, - """ - - def connection_factory(host, port): -- conn = nsslib.NSSConnection(host, port, dbdir=secdir, -+ no_init = secdir == nsslib.current_dbdir -+ conn = nsslib.NSSConnection(host, port, dbdir=secdir, no_init=no_init, - tls_version_min=api.env.tls_version_min, - tls_version_max=api.env.tls_version_max) - conn.set_debuglevel(0) --- -2.4.3 - diff --git a/SOURCES/0156-Add-profiles-and-default-CA-ACL-on-migration.patch b/SOURCES/0156-Add-profiles-and-default-CA-ACL-on-migration.patch deleted file mode 100644 index a3f99a6..0000000 --- a/SOURCES/0156-Add-profiles-and-default-CA-ACL-on-migration.patch +++ /dev/null @@ -1,381 +0,0 @@ -From 5fb869896c9ed6327f5f004022cdee42f758f78c Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Mon, 23 Nov 2015 12:09:32 +1100 -Subject: [PATCH] Add profiles and default CA ACL on migration - -Profiles and the default CA ACL were not being added during replica -install from pre-4.2 servers. Update ipa-replica-install to add -these if they are missing. - -Also update the caacl plugin to prevent deletion of the default CA -ACL and instruct the administrator to disable it instead. - -To ensure that the cainstance installation can add profiles, supply -the RA certificate as part of the instance configuration. -Certmonger renewal setup is avoided at this point because the NSSDB -gets reinitialised later in installation procedure. - -Also move the addition of the default CA ACL from dsinstance -installation to cainstance installation. - -Fixes: https://fedorahosted.org/freeipa/ticket/5459 -Reviewed-By: Jan Cholasta ---- - install/share/Makefile.am | 1 - - install/share/default-caacl.ldif | 11 --- - install/updates/50-dogtag10-migration.update | 1 + - ipalib/plugins/caacl.py | 8 +++ - ipaserver/install/ca.py | 5 +- - ipaserver/install/cainstance.py | 100 ++++++++++++++++++++------- - ipaserver/install/dsinstance.py | 4 -- - ipaserver/install/server/replicainstall.py | 3 + - ipaserver/install/server/upgrade.py | 13 +--- - 9 files changed, 90 insertions(+), 56 deletions(-) - delete mode 100644 install/share/default-caacl.ldif - -diff --git a/install/share/Makefile.am b/install/share/Makefile.am -index d68c40e693a1d86c70d8ccd81ef2c915b2e1f61e..e4cca8708ab0042d6cb37eba31341e53e3cdac4d 100644 ---- a/install/share/Makefile.am -+++ b/install/share/Makefile.am -@@ -29,7 +29,6 @@ app_DATA = \ - bootstrap-template.ldif \ - caJarSigningCert.cfg.template \ - default-aci.ldif \ -- default-caacl.ldif \ - default-hbac.ldif \ - default-smb-group.ldif \ - default-trust-view.ldif \ -diff --git a/install/share/default-caacl.ldif b/install/share/default-caacl.ldif -deleted file mode 100644 -index f3cd5b4d4e3a79bc6638dc1ffdd7028596ded254..0000000000000000000000000000000000000000 ---- a/install/share/default-caacl.ldif -+++ /dev/null -@@ -1,11 +0,0 @@ --# default CA ACL that grants use of caIPAserviceCert on top-level CA to all hosts and services --dn: ipauniqueid=autogenerate,cn=caacls,cn=ca,$SUFFIX --changetype: add --objectclass: ipaassociation --objectclass: ipacaacl --ipauniqueid: autogenerate --cn: hosts_services_caIPAserviceCert --ipaenabledflag: TRUE --ipamembercertprofile: cn=caIPAserviceCert,cn=certprofiles,cn=ca,$SUFFIX --hostcategory: all --servicecategory: all -diff --git a/install/updates/50-dogtag10-migration.update b/install/updates/50-dogtag10-migration.update -index 2ab9d15bd220540dbc6b3fcd7928fc15c42caf80..0070c308aefc39aa4c27a046d185ce6d268e6270 100644 ---- a/install/updates/50-dogtag10-migration.update -+++ b/install/updates/50-dogtag10-migration.update -@@ -16,3 +16,4 @@ addifexist:resourceACLS:certServer.ca.groups:execute:allow (execute) group="Admi - addifexist:resourceACLS:certServer.ca.users:execute:allow (execute) group="Administrators":Admins may execute user operations - replace:resourceACLS:certServer.securitydomain.domainxml:read,modify:allow (read) user="anybody";allow (modify) group="Subsystem Group":Anybody is allowed to read domain.xml but only Subsystem group is allowed to modify the domain.xml::certServer.securitydomain.domainxml:read,modify:allow (read) user="anybody";allow (modify) group="Subsystem Group" || group="Enterprise CA Administrators" || group="Enterprise KRA Administrators" || group="Enterprise RA Administrators" || group="Enterprise OCSP Administrators" || group="Enterprise TKS Administrators" || group="Enterprise TPS Administrators":Anybody is allowed to read domain.xml but only Subsystem group and Enterprise Administrators are allowed to modify the domain.xml - replace:resourceACLS:certServer.ca.connectorInfo:read,modify:allow (modify,read) group="Enterprise KRA Administrators":Only Enterprise Administrators are allowed to update the connector information::certServer.ca.connectorInfo:read,modify:allow (read) group="Enterprise KRA Administrators";allow (modify) group="Enterprise KRA Administrators" || group="Subsystem Group":Only Enterprise Administrators and Subsystem Group are allowed to update the connector information -+addifexist:resourceACLS:certServer.profile.configuration:read,modify:allow (read,modify) group="Certificate Manager Agents":Certificate Manager agents may modify (create/update/delete) and read profiles -diff --git a/ipalib/plugins/caacl.py b/ipalib/plugins/caacl.py -index 247d6df143aef1fba9f0ee74a9f7d8386bef5180..64dbec16e11e9fa2a67287b195b4bd1180a379e7 100644 ---- a/ipalib/plugins/caacl.py -+++ b/ipalib/plugins/caacl.py -@@ -307,6 +307,14 @@ class caacl_del(LDAPDelete): - - msg_summary = _('Deleted CA ACL "%(value)s"') - -+ def pre_callback(self, ldap, dn, *keys, **options): -+ if keys[0] == 'hosts_services_caIPAserviceCert': -+ raise errors.ProtectedEntryError( -+ label=_("CA ACL"), -+ key=keys[0], -+ reason=_("default CA ACL can be only disabled")) -+ return dn -+ - - @register() - class caacl_mod(LDAPUpdate): -diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py -index 498cc48a742d1b2d862eb9dfdb18743cfb211b78..0de992cb0c15f8161aae4937699baae2a94d305a 100644 ---- a/ipaserver/install/ca.py -+++ b/ipaserver/install/ca.py -@@ -126,9 +126,10 @@ def install_step_0(standalone, replica_config, options): - if standalone: - api.Backend.ldap2.disconnect() - -- cainstance.install_replica_ca(replica_config, postinstall) -+ cainstance.install_replica_ca(replica_config, postinstall, -+ ra_p12=getattr(options, 'ra_p12', None)) - -- if standalone: -+ if standalone and not api.Backend.ldap2.isconnected(): - api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), - bind_pw=dm_password) - -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index 3e3dce93de2b8ca48a3fe3ea5994ee92a1b0ce49..189876f3c0d980e78165d73eed86b2830ac8c5b8 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -391,7 +391,7 @@ class CAInstance(DogtagInstance): - cert_file=None, cert_chain_file=None, - master_replication_port=None, - subject_base=None, ca_signing_algorithm=None, -- ca_type=None): -+ ca_type=None, ra_p12=None): - """Create a CA instance. - - For Dogtag 9, this may involve creating the pki-ca instance. -@@ -465,7 +465,10 @@ class CAInstance(DogtagInstance): - self.step("requesting RA certificate from CA", self.__request_ra_certificate) - self.step("issuing RA agent certificate", self.__issue_ra_cert) - self.step("adding RA agent as a trusted user", self.__create_ca_agent) -- self.step("authorizing RA to modify profiles", self.__configure_profiles_acl) -+ elif ra_p12 is not None: -+ self.step("importing RA certificate from PKCS #12 file", -+ lambda: self.import_ra_cert(ra_p12, configure_renewal=False)) -+ self.step("authorizing RA to modify profiles", configure_profiles_acl) - self.step("configure certmonger for renewals", self.configure_certmonger_renewal) - self.step("configure certificate renewals", self.configure_renewal) - if not self.clone: -@@ -473,9 +476,12 @@ class CAInstance(DogtagInstance): - self.step("configure Server-Cert certificate renewal", self.track_servercert) - self.step("Configure HTTP to proxy connections", - self.http_proxy) -- if not self.clone: -- self.step("restarting certificate server", self.restart_instance) -- self.step("Importing IPA certificate profiles", import_included_profiles) -+ self.step("restarting certificate server", self.restart_instance) -+ self.step("migrating certificate profiles to LDAP", -+ migrate_profiles_to_ldap) -+ self.step("importing IPA certificate profiles", -+ import_included_profiles) -+ self.step("adding default CA ACL", ensure_default_caacl) - - self.start_creation(runtime=210) - -@@ -887,7 +893,7 @@ class CAInstance(DogtagInstance): - - export_kra_agent_pem() - -- def import_ra_cert(self, rafile): -+ def import_ra_cert(self, rafile, configure_renewal=True): - """ - Cloned RAs will use the same RA agent cert as the master so we - need to import from a PKCS#12 file. -@@ -903,7 +909,8 @@ class CAInstance(DogtagInstance): - finally: - os.remove(agent_name) - -- self.configure_agent_renewal() -+ if configure_renewal: -+ self.configure_agent_renewal() - - export_kra_agent_pem() - -@@ -953,10 +960,6 @@ class CAInstance(DogtagInstance): - - conn.disconnect() - -- def __configure_profiles_acl(self): -- """Allow the Certificate Manager Agents group to modify profiles.""" -- configure_profiles_acl() -- - def __run_certutil(self, args, database=None, pwd_file=None, stdin=None): - if not database: - database = self.ra_agent_db -@@ -1491,7 +1494,7 @@ def replica_ca_install_check(config): - exit('IPA schema missing on master CA directory server') - - --def install_replica_ca(config, postinstall=False): -+def install_replica_ca(config, postinstall=False, ra_p12=None): - """ - Install a CA on a replica. - -@@ -1533,7 +1536,7 @@ def install_replica_ca(config, postinstall=False): - ca.create_ra_agent_db = False - ca.configure_instance(config.host_name, config.domain_name, - config.dirman_password, config.dirman_password, -- pkcs12_info=(cafile,), -+ pkcs12_info=(cafile,), ra_p12=ra_p12, - master_host=config.master_host_name, - master_replication_port=config.ca_ds_port, - subject_base=config.subject_base) -@@ -1658,6 +1661,14 @@ def update_people_entry(dercert): - return True - - def ensure_ldap_profiles_container(): -+ ensure_entry( -+ DN(('ou', 'certificateProfiles'), ('ou', 'ca'), ('o', 'ipaca')), -+ objectclass=['top', 'organizationalUnit'], -+ ou=['certificateProfiles'], -+ ) -+ -+ -+def ensure_entry(dn, **attrs): - server_id = installutils.realm_to_serverid(api.env.realm) - dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id - -@@ -1665,40 +1676,39 @@ def ensure_ldap_profiles_container(): - if not conn.isconnected(): - conn.connect(autobind=True) - -- dn = DN(('ou', 'certificateProfiles'), ('ou', 'ca'), ('o', 'ipaca')) - try: - conn.get_entry(dn) - except errors.NotFound: - # entry doesn't exist; add it -- entry = conn.make_entry( -- dn, -- objectclass=['top', 'organizationalUnit'], -- ou=['certificateProfiles'], -- ) -+ entry = conn.make_entry(dn, **attrs) - conn.add_entry(entry) - - conn.disconnect() - - - def configure_profiles_acl(): -+ """Allow the Certificate Manager Agents group to modify profiles.""" - server_id = installutils.realm_to_serverid(api.env.realm) - dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id - updated = False - - dn = DN(('cn', 'aclResources'), ('o', 'ipaca')) -- rule = ( -+ new_rules = [ - 'certServer.profile.configuration:read,modify:allow (read,modify) ' - 'group="Certificate Manager Agents":' -- 'Certificate Manager agents may modify (create/update/delete) and read profiles' -- ) -- modlist = [(ldap.MOD_ADD, 'resourceACLS', [rule])] -+ 'Certificate Manager agents may modify (create/update/delete) and read profiles', -+ -+ 'certServer.ca.account:login,logout:allow (login,logout) ' -+ 'user="anybody":Anybody can login and logout', -+ ] - - conn = ldap2.ldap2(api, ldap_uri=dogtag_uri) - if not conn.isconnected(): - conn.connect(autobind=True) -- rules = conn.get_entry(dn).get('resourceACLS', []) -- if rule not in rules: -- conn.conn.modify_s(str(dn), modlist) -+ cur_rules = conn.get_entry(dn).get('resourceACLS', []) -+ add_rules = [rule for rule in new_rules if rule not in cur_rules] -+ if add_rules: -+ conn.conn.modify_s(str(dn), [(ldap.MOD_ADD, 'resourceACLS', add_rules)]) - updated = True - - conn.disconnect() -@@ -1718,6 +1728,17 @@ def import_included_profiles(): - if not conn.isconnected(): - conn.connect(autobind=True) - -+ ensure_entry( -+ DN(('cn', 'ca'), api.env.basedn), -+ objectclass=['top', 'nsContainer'], -+ cn=['ca'], -+ ) -+ ensure_entry( -+ DN(api.env.container_certprofile, api.env.basedn), -+ objectclass=['top', 'nsContainer'], -+ cn=['certprofiles'], -+ ) -+ - api.Backend.ra_certprofile._read_password() - api.Backend.ra_certprofile.override_port = 8443 - -@@ -1823,6 +1844,33 @@ def _create_dogtag_profile(profile_id, profile_data): - "(it is probably already enabled)") - - -+def ensure_default_caacl(): -+ """Add the default CA ACL if missing.""" -+ if not api.Backend.ldap2.isconnected(): -+ try: -+ api.Backend.ldap2.connect(autobind=True) -+ except errors.PublicError as e: -+ root_logger.error("Cannot connect to LDAP to add CA ACLs: %s", e) -+ return -+ -+ ensure_entry( -+ DN(('cn', 'ca'), api.env.basedn), -+ objectclass=['top', 'nsContainer'], -+ cn=['ca'], -+ ) -+ ensure_entry( -+ DN(api.env.container_caacl, api.env.basedn), -+ objectclass=['top', 'nsContainer'], -+ cn=['certprofiles'], -+ ) -+ -+ if not api.Command.caacl_find()['result']: -+ api.Command.caacl_add(u'hosts_services_caIPAserviceCert', -+ hostcategory=u'all', servicecategory=u'all') -+ api.Command.caacl_add_profile(u'hosts_services_caIPAserviceCert', -+ certprofile=(u'caIPAserviceCert',)) -+ -+ - if __name__ == "__main__": - standard_logging_setup("install.log") - ds = dsinstance.DsInstance() -diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py -index f33a9e03a4148dde69fc61441c878f5126f8e455..d78158532c4c88d9aa9acf3c65d278f5151458d8 100644 ---- a/ipaserver/install/dsinstance.py -+++ b/ipaserver/install/dsinstance.py -@@ -310,7 +310,6 @@ class DsInstance(service.Service): - self.step("adding range check plugin", self.__add_range_check_plugin) - if hbac_allow: - self.step("creating default HBAC rule allow_all", self.add_hbac) -- self.step("creating default CA ACL rule", self.add_caacl) - self.step("adding entries for topology management", self.__add_topology_entries) - - self.__common_post_setup() -@@ -745,9 +744,6 @@ class DsInstance(service.Service): - def add_hbac(self): - self._ldap_mod("default-hbac.ldif", self.sub_dict) - -- def add_caacl(self): -- self._ldap_mod("default-caacl.ldif", self.sub_dict) -- - def change_admin_password(self, password): - root_logger.debug("Changing admin password") - dirname = config_dirname(self.serverid) -diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py -index 6f9a6141fe9af44806244ce52df59c191dc966b0..6e9157cabc49161ba27983cbf1de1428d1b48b7d 100644 ---- a/ipaserver/install/server/replicainstall.py -+++ b/ipaserver/install/server/replicainstall.py -@@ -573,6 +573,9 @@ def install(installer): - options.domain_name = config.domain_name - options.host_name = config.host_name - -+ if ipautil.file_exists(config.dir + "/cacert.p12"): -+ options.ra_p12 = config.dir + "/ra.p12" -+ - ca.install(False, config, options) - - krb = install_krb(config, setup_pkinit=not options.no_pkinit) -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index c8f744c392c7b859459bda63c1f397226553d4ba..945cb3ebd63767cb1d57083e1da7c5605ac5a2f9 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -1321,18 +1321,7 @@ def add_default_caacl(ca): - return - - if ca.is_configured(): -- if not api.Backend.ldap2.isconnected(): -- try: -- api.Backend.ldap2.connect(autobind=True) -- except ipalib.errors.PublicError as e: -- root_logger.error("Cannot connect to LDAP to add CA ACLs: %s", e) -- return -- -- if not api.Command.caacl_find()['result']: -- api.Command.caacl_add(u'hosts_services_caIPAserviceCert', -- hostcategory=u'all', servicecategory=u'all') -- api.Command.caacl_add_profile(u'hosts_services_caIPAserviceCert', -- certprofile=(u'caIPAserviceCert',)) -+ cainstance.ensure_default_caacl() - - sysupgrade.set_upgrade_state('caacl', 'add_default_caacl', True) - --- -2.4.3 - diff --git a/SOURCES/0157-disconnect-ldap2-backend-after-adding-default-CA-ACL.patch b/SOURCES/0157-disconnect-ldap2-backend-after-adding-default-CA-ACL.patch deleted file mode 100644 index 5f8959b..0000000 --- a/SOURCES/0157-disconnect-ldap2-backend-after-adding-default-CA-ACL.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 245f54de1d4e2189b1234000916a7d591fa151b9 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Tue, 24 Nov 2015 14:43:10 +0100 -Subject: [PATCH] disconnect ldap2 backend after adding default CA ACL profiles - -ensure_default_caacl() was leaking open api.Backend.ldap2 connection which -could crash server/replica installation at later stages. This patch ensures -that after checking default CA ACL profiles the backend is disconnected. - -https://fedorahosted.org/freeipa/ticket/5459 - -Reviewed-By: Tomas Babej ---- - ipaserver/install/cainstance.py | 3 +++ - 1 file changed, 3 insertions(+) - -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index 189876f3c0d980e78165d73eed86b2830ac8c5b8..c72d11d1e0b86c040dc497744cda87aab22caafd 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -1870,6 +1870,9 @@ def ensure_default_caacl(): - api.Command.caacl_add_profile(u'hosts_services_caIPAserviceCert', - certprofile=(u'caIPAserviceCert',)) - -+ if api.Backend.ldap2.isconnected(): -+ api.Backend.ldap2.disconnect() -+ - - if __name__ == "__main__": - standard_logging_setup("install.log") --- -2.4.3 - diff --git a/SOURCES/0158-do-not-disconnect-when-using-existing-connection-to-.patch b/SOURCES/0158-do-not-disconnect-when-using-existing-connection-to-.patch deleted file mode 100644 index ddd390b..0000000 --- a/SOURCES/0158-do-not-disconnect-when-using-existing-connection-to-.patch +++ /dev/null @@ -1,39 +0,0 @@ -From bce98a84720aa6ffdec72e923248719c3cbea8d3 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Tue, 24 Nov 2015 16:40:52 +0100 -Subject: [PATCH] do not disconnect when using existing connection to check - default CA ACLs - -https://fedorahosted.org/freeipa/ticket/5459 - -Reviewed-By: Jan Cholasta ---- - ipaserver/install/cainstance.py | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index c72d11d1e0b86c040dc497744cda87aab22caafd..c20bf39c12cff0777d90efad2b0d8d136ee37ec9 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -1846,7 +1846,8 @@ def _create_dogtag_profile(profile_id, profile_data): - - def ensure_default_caacl(): - """Add the default CA ACL if missing.""" -- if not api.Backend.ldap2.isconnected(): -+ is_already_connected = api.Backend.ldap2.isconnected() -+ if not is_already_connected: - try: - api.Backend.ldap2.connect(autobind=True) - except errors.PublicError as e: -@@ -1870,7 +1871,7 @@ def ensure_default_caacl(): - api.Command.caacl_add_profile(u'hosts_services_caIPAserviceCert', - certprofile=(u'caIPAserviceCert',)) - -- if api.Backend.ldap2.isconnected(): -+ if not is_already_connected: - api.Backend.ldap2.disconnect() - - --- -2.4.3 - diff --git a/SOURCES/0159-Fix-upgrade-of-forwardzones-when-zone-is-in-realmdom.patch b/SOURCES/0159-Fix-upgrade-of-forwardzones-when-zone-is-in-realmdom.patch deleted file mode 100644 index 8b3c1f3..0000000 --- a/SOURCES/0159-Fix-upgrade-of-forwardzones-when-zone-is-in-realmdom.patch +++ /dev/null @@ -1,37 +0,0 @@ -From c466f49b39869ec9817cda4a0485b00a14c52782 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Wed, 25 Nov 2015 09:57:07 +0100 -Subject: [PATCH] Fix upgrade of forwardzones when zone is in realmdomains - -https://fedorahosted.org/freeipa/ticket/5472 - -Reviewed-By: Petr Spacek ---- - ipalib/plugins/realmdomains.py | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/ipalib/plugins/realmdomains.py b/ipalib/plugins/realmdomains.py -index c53340591bd0f0f02fcc9db3142b74197aff551b..54c07a7a11a23e82717a30e4ac8a50502bfc7b51 100644 ---- a/ipalib/plugins/realmdomains.py -+++ b/ipalib/plugins/realmdomains.py -@@ -185,7 +185,7 @@ class realmdomains_mod(LDAPUpdate): - if d == api.env.domain: - continue - try: -- api.Command['dnsrecord_add']( -+ self.api.Command['dnsrecord_add']( - unicode(d), - u'_kerberos', - txtrecord=api.env.realm -@@ -200,7 +200,7 @@ class realmdomains_mod(LDAPUpdate): - if d == api.env.domain: - continue - try: -- api.Command['dnsrecord_del']( -+ self.api.Command['dnsrecord_del']( - unicode(d), - u'_kerberos', - txtrecord=api.env.realm --- -2.4.3 - diff --git a/SOURCES/0160-Fix-version-comparison.patch b/SOURCES/0160-Fix-version-comparison.patch deleted file mode 100644 index a3857f1..0000000 --- a/SOURCES/0160-Fix-version-comparison.patch +++ /dev/null @@ -1,114 +0,0 @@ -From 30902db32fcc04dccbaf40839f44cdf4f505f588 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Wed, 9 Dec 2015 18:53:35 +0100 -Subject: [PATCH] Fix version comparison - -Use RPM library to compare vendor versions of IPA for redhat platform - -https://fedorahosted.org/freeipa/ticket/5535 - -Reviewed-By: Tomas Babej ---- - freeipa.spec.in | 1 + - ipaplatform/redhat/tasks.py | 53 +++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 54 insertions(+) - -diff --git a/freeipa.spec.in b/freeipa.spec.in -index 6527109b422a1e3065d5a540c3e2a3af670f2ebf..01d42bc621c83541af7517d6d91eb37fd5b5c5cc 100644 ---- a/freeipa.spec.in -+++ b/freeipa.spec.in -@@ -159,6 +159,7 @@ Requires: p11-kit - Requires: systemd-python - Requires: %{etc_systemd_dir} - Requires: gzip -+Requires: rpm-python - - Conflicts: %{alt_name}-server - Obsoletes: %{alt_name}-server < %{version} -diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py -index db31cd04cb234fac8fee97f3579ba2ca919f3262..2e894d776dcd5542e6c11cc0210add8ad9d90298 100644 ---- a/ipaplatform/redhat/tasks.py -+++ b/ipaplatform/redhat/tasks.py -@@ -30,6 +30,8 @@ import socket - import sys - import urllib - import base64 -+import rpm -+from functools import total_ordering - - from subprocess import CalledProcessError - from nss.error import NSPRError -@@ -46,6 +48,35 @@ from ipaplatform.redhat.authconfig import RedHatAuthConfig - from ipaplatform.base.tasks import BaseTaskNamespace - - -+# copied from rpmUtils/miscutils.py -+def stringToVersion(verstring): -+ if verstring in [None, '']: -+ return (None, None, None) -+ i = verstring.find(':') -+ if i != -1: -+ try: -+ epoch = str(long(verstring[:i])) -+ except ValueError: -+ # look, garbage in the epoch field, how fun, kill it -+ epoch = '0' # this is our fallback, deal -+ else: -+ epoch = '0' -+ j = verstring.find('-') -+ if j != -1: -+ if verstring[i + 1:j] == '': -+ version = None -+ else: -+ version = verstring[i + 1:j] -+ release = verstring[j + 1:] -+ else: -+ if verstring[i + 1:] == '': -+ version = None -+ else: -+ version = verstring[i + 1:] -+ release = None -+ return (epoch, version, release) -+ -+ - log = log_mgr.get_logger(__name__) - - -@@ -65,6 +96,21 @@ def selinux_enabled(): - return False - - -+@total_ordering -+class IPAVersion(object): -+ -+ def __init__(self, version): -+ self.version_tuple = stringToVersion(version) -+ -+ def __eq__(self, other): -+ assert isinstance(other, IPAVersion) -+ return rpm.labelCompare(self.version_tuple, other.version_tuple) == 0 -+ -+ def __lt__(self, other): -+ assert isinstance(other, IPAVersion) -+ return rpm.labelCompare(self.version_tuple, other.version_tuple) == -1 -+ -+ - class RedHatTaskNamespace(BaseTaskNamespace): - - def restore_context(self, filepath, restorecon=paths.SBIN_RESTORECON): -@@ -422,5 +468,12 @@ class RedHatTaskNamespace(BaseTaskNamespace): - super(RedHatTaskNamespace, self).create_system_user(name, group, - homedir, shell, uid, gid, comment, create_homedir) - -+ def parse_ipa_version(self, version): -+ """ -+ :param version: textual version -+ :return: object implementing proper __cmp__ method for version compare -+ """ -+ return IPAVersion(version) -+ - - tasks = RedHatTaskNamespace() --- -2.4.3 - diff --git a/SOURCES/0161-DNS-fix-file-permissions.patch b/SOURCES/0161-DNS-fix-file-permissions.patch deleted file mode 100644 index d8a0304..0000000 --- a/SOURCES/0161-DNS-fix-file-permissions.patch +++ /dev/null @@ -1,40 +0,0 @@ -From 7aae209ba77a09de7cb09792d6ac16bb80683a2f Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Wed, 9 Dec 2015 12:12:22 +0100 -Subject: [PATCH] DNS: fix file permissions - -With non default umask named-pkcs11 cannot access the softhsm token storage - -https://fedorahosted.org/freeipa/ticket/5520 - -Reviewed-By: Tomas Babej ---- - ipaserver/install/dnskeysyncinstance.py | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/ipaserver/install/dnskeysyncinstance.py b/ipaserver/install/dnskeysyncinstance.py -index 7d1351ccc57a5dbd7d537741545ad44d0dcd5eb1..590343c4e97fc882f296ac1aa69e43de9d35ed65 100644 ---- a/ipaserver/install/dnskeysyncinstance.py -+++ b/ipaserver/install/dnskeysyncinstance.py -@@ -200,7 +200,9 @@ class DNSKeySyncInstance(service.Service): - # create dnssec directory - if not os.path.exists(paths.IPA_DNSSEC_DIR): - self.logger.debug("Creating %s directory", paths.IPA_DNSSEC_DIR) -- os.mkdir(paths.IPA_DNSSEC_DIR, 0770) -+ os.mkdir(paths.IPA_DNSSEC_DIR) -+ os.chmod(paths.IPA_DNSSEC_DIR, 0770) -+ - # chown ods:named - os.chown(paths.IPA_DNSSEC_DIR, self.ods_uid, self.named_gid) - -@@ -217,6 +219,7 @@ class DNSKeySyncInstance(service.Service): - named_fd.truncate(0) - named_fd.write(softhsm_conf_txt) - named_fd.close() -+ os.chmod(paths.DNSSEC_SOFTHSM2_CONF, 0644) - - # setting up named to use softhsm2 - if not self.fstore.has_file(paths.SYSCONFIG_NAMED): --- -2.4.3 - diff --git a/SOURCES/0162-Explicitly-call-chmod-on-newly-created-directories.patch b/SOURCES/0162-Explicitly-call-chmod-on-newly-created-directories.patch deleted file mode 100644 index e85ee8f..0000000 --- a/SOURCES/0162-Explicitly-call-chmod-on-newly-created-directories.patch +++ /dev/null @@ -1,121 +0,0 @@ -From 7d7bb4789504a3f84e8ccf52abc06e8de109289a Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Wed, 9 Dec 2015 13:40:04 +0100 -Subject: [PATCH] Explicitly call chmod on newly created directories - -Without calling os.chmod(), umask is effective and may cause that -directory is created with permission that causes failure. - -This can be related to https://fedorahosted.org/freeipa/ticket/5520 - -Reviewed-By: Tomas Babej ---- - ipaplatform/base/services.py | 2 +- - ipaserver/install/cainstance.py | 1 + - ipaserver/install/ipa_backup.py | 7 ++++--- - ipaserver/install/ipa_replica_prepare.py | 3 ++- - ipaserver/install/ipa_restore.py | 10 ++++++---- - 5 files changed, 14 insertions(+), 9 deletions(-) - -diff --git a/ipaplatform/base/services.py b/ipaplatform/base/services.py -index 56e959e919e42281431240451071a2d4b8048e4a..b068a2f3b00549fffa20feffb6a3158382fc7e9a 100644 ---- a/ipaplatform/base/services.py -+++ b/ipaplatform/base/services.py -@@ -421,7 +421,7 @@ class SystemdService(PlatformService): - - try: - if not ipautil.dir_exists(srv_tgt): -- os.mkdir(srv_tgt) -+ os.mkdir(srv_tgt, 0755) - if os.path.exists(srv_lnk): - # Remove old link - os.unlink(srv_lnk) -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index c20bf39c12cff0777d90efad2b0d8d136ee37ec9..d9bf4f31af5a922dd6f977a5011f50ce7cea8896 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -978,6 +978,7 @@ class CAInstance(DogtagInstance): - - if not ipautil.dir_exists(self.ra_agent_db): - os.mkdir(self.ra_agent_db) -+ os.chmod(self.ra_agent_db, 0755) - - # Create the password file for this db - hex_str = binascii.hexlify(os.urandom(10)) -diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py -index 3bd2ef0203c1b5b596e092987acd894491ecae26..a5a4bef0a17f641fcea565d9a79c3e6887a064a7 100644 ---- a/ipaserver/install/ipa_backup.py -+++ b/ipaserver/install/ipa_backup.py -@@ -279,8 +279,8 @@ class Backup(admintool.AdminTool): - os.chown(self.top_dir, pent.pw_uid, pent.pw_gid) - os.chmod(self.top_dir, 0750) - self.dir = os.path.join(self.top_dir, "ipa") -- os.mkdir(self.dir, 0750) -- -+ os.mkdir(self.dir) -+ os.chmod(self.dir, 0750) - os.chown(self.dir, pent.pw_uid, pent.pw_gid) - - self.header = os.path.join(self.top_dir, 'header') -@@ -605,7 +605,8 @@ class Backup(admintool.AdminTool): - backup_dir = os.path.join(paths.IPA_BACKUP_DIR, time.strftime('ipa-full-%Y-%m-%d-%H-%M-%S')) - filename = os.path.join(backup_dir, "ipa-full.tar") - -- os.mkdir(backup_dir, 0700) -+ os.mkdir(backup_dir) -+ os.chmod(backup_dir, 0700) - - cwd = os.getcwd() - os.chdir(self.dir) -diff --git a/ipaserver/install/ipa_replica_prepare.py b/ipaserver/install/ipa_replica_prepare.py -index 5246f5f5469c85571d04c99d872f38018802abaa..b9ae60e9bc9d40be5f86e312980846b2ad80f67d 100644 ---- a/ipaserver/install/ipa_replica_prepare.py -+++ b/ipaserver/install/ipa_replica_prepare.py -@@ -345,7 +345,8 @@ class ReplicaPrepare(admintool.AdminTool): - - self.top_dir = tempfile.mkdtemp("ipa") - self.dir = os.path.join(self.top_dir, "realm_info") -- os.mkdir(self.dir, 0700) -+ os.mkdir(self.dir) -+ os.chmod(self.dir, 0700) - try: - self.copy_ds_certificate() - -diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py -index 57d5deb1e68af6e9ceb51f4dd751b8a59d9ac513..cdc460301ad8aeb658fec18da565238a376d1c0c 100644 ---- a/ipaserver/install/ipa_restore.py -+++ b/ipaserver/install/ipa_restore.py -@@ -300,8 +300,8 @@ class Restore(admintool.AdminTool): - os.chown(self.top_dir, pent.pw_uid, pent.pw_gid) - os.chmod(self.top_dir, 0750) - self.dir = os.path.join(self.top_dir, "ipa") -- os.mkdir(self.dir, 0750) -- -+ os.mkdir(self.dir) -+ os.chmod(self.dir, 0750) - os.chown(self.dir, pent.pw_uid, pent.pw_gid) - - cwd = os.getcwd() -@@ -527,7 +527,8 @@ class Restore(admintool.AdminTool): - - if not os.path.exists(ldifdir): - pent = pwd.getpwnam(DS_USER) -- os.mkdir(ldifdir, 0770) -+ os.mkdir(ldifdir) -+ os.chmod(ldifdir, 0770) - os.chown(ldifdir, pent.pw_uid, pent.pw_gid) - - ipautil.backup_file(ldiffile) -@@ -804,7 +805,8 @@ class Restore(admintool.AdminTool): - for dir in dirs: - try: - self.log.debug('Creating %s' % dir) -- os.mkdir(dir, 0770) -+ os.mkdir(dir) -+ os.chmod(dir, 0770) - os.chown(dir, pent.pw_uid, pent.pw_gid) - tasks.restore_context(dir) - except Exception, e: --- -2.4.3 - diff --git a/SOURCES/0163-Fix-replace-mkdir-with-chmod.patch b/SOURCES/0163-Fix-replace-mkdir-with-chmod.patch deleted file mode 100644 index 433a1d6..0000000 --- a/SOURCES/0163-Fix-replace-mkdir-with-chmod.patch +++ /dev/null @@ -1,31 +0,0 @@ -From a600614ba36e192b168fcb4f9547c70fdc304707 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Tue, 22 Dec 2015 16:34:32 +0100 -Subject: [PATCH] Fix: replace mkdir with chmod - -In original patches, extra mkdir has been added instead of chmod. - -https://fedorahosted.org/freeipa/ticket/5520 - -Reviewed-By: Martin Basti ---- - ipaplatform/base/services.py | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/ipaplatform/base/services.py b/ipaplatform/base/services.py -index b068a2f3b00549fffa20feffb6a3158382fc7e9a..d280557c4f1c8ba353ba093736d577cc6c2a47a9 100644 ---- a/ipaplatform/base/services.py -+++ b/ipaplatform/base/services.py -@@ -421,7 +421,8 @@ class SystemdService(PlatformService): - - try: - if not ipautil.dir_exists(srv_tgt): -- os.mkdir(srv_tgt, 0755) -+ os.mkdir(srv_tgt) -+ os.chmod(srv_tgt, 0755) - if os.path.exists(srv_lnk): - # Remove old link - os.unlink(srv_lnk) --- -2.4.3 - diff --git a/SOURCES/0164-DNSSEC-Improve-error-reporting-from-ipa-ods-exporter.patch b/SOURCES/0164-DNSSEC-Improve-error-reporting-from-ipa-ods-exporter.patch deleted file mode 100644 index b646527..0000000 --- a/SOURCES/0164-DNSSEC-Improve-error-reporting-from-ipa-ods-exporter.patch +++ /dev/null @@ -1,38 +0,0 @@ -From 06df4a281c5e4b2be4840fb42129478279792a9d Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Thu, 26 Nov 2015 14:56:00 +0100 -Subject: [PATCH] DNSSEC: Improve error reporting from ipa-ods-exporter - -https://fedorahosted.org/freeipa/ticket/5348 - -Reviewed-By: Martin Basti -Reviewed-By: Martin Basti ---- - daemons/dnssec/ipa-ods-exporter | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter -index f30a2253a713d857aa4e7566e52a0a45f7bd50c2..12a9294ae05d2ce8d206a2bbf74cc00d81259efa 100755 ---- a/daemons/dnssec/ipa-ods-exporter -+++ b/daemons/dnssec/ipa-ods-exporter -@@ -31,6 +31,7 @@ import systemd.daemon - import systemd.journal - import sqlite3 - import time -+import traceback - - import ipalib - from ipapython.dn import DN -@@ -576,7 +577,8 @@ try: - sync_zone(log, ldap, dns_dn, zone_row['name']) - - except Exception as ex: -- msg = "ipa-ods-exporter exception: %s" % ex -+ msg = "ipa-ods-exporter exception: %s" % traceback.format_exc(ex) -+ log.exception(ex) - raise ex - - finally: --- -2.4.3 - diff --git a/SOURCES/0165-DNSSEC-Make-sure-that-current-state-in-OpenDNSSEC-ma.patch b/SOURCES/0165-DNSSEC-Make-sure-that-current-state-in-OpenDNSSEC-ma.patch deleted file mode 100644 index a8906ff..0000000 --- a/SOURCES/0165-DNSSEC-Make-sure-that-current-state-in-OpenDNSSEC-ma.patch +++ /dev/null @@ -1,174 +0,0 @@ -From 6c012544655b3730ebb0a1551cdbce04ab686cfb Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Tue, 24 Nov 2015 12:49:40 +0100 -Subject: [PATCH] DNSSEC: Make sure that current state in OpenDNSSEC matches - key state in LDAP - -Previously we published timestamps of planned state changes in LDAP. -This led to situations where state transition in OpenDNSSEC was blocked -by an additional condition (or unavailability of OpenDNSSEC) but BIND -actually did the transition as planned. - -Additionally key state mapping was incorrect for KSK so sometimes KSK -was not used for signing when it should. - -Example (for code without this fix): -- Add a zone and let OpenDNSSEC to generate keys. -- Wait until keys are in state "published" and next state is "inactive". -- Shutdown OpenDNSSEC or break replication from DNSSEC key master. -- See that keys on DNS replicas will transition to state "inactive" even - though it should not happen because OpenDNSSEC is not available - (i.e. new keys may not be available). -- End result is that affected zone will not be signed anymore, even - though it should stay signed with the old keys. - -https://fedorahosted.org/freeipa/ticket/5348 - -Reviewed-By: Martin Basti -Reviewed-By: Martin Basti ---- - daemons/dnssec/ipa-ods-exporter | 105 ++++++++++++++++++++++++++++++++++++---- - 1 file changed, 95 insertions(+), 10 deletions(-) - -diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter -index 12a9294ae05d2ce8d206a2bbf74cc00d81259efa..6ed7588847042e742abeef724940eec31f23ca8f 100755 ---- a/daemons/dnssec/ipa-ods-exporter -+++ b/daemons/dnssec/ipa-ods-exporter -@@ -57,6 +57,14 @@ ODS_DB_LOCK_PATH = "%s%s" % (paths.OPENDNSSEC_KASP_DB, '.our_lock') - SECRETKEY_WRAPPING_MECH = 'rsaPkcsOaep' - PRIVKEY_WRAPPING_MECH = 'aesKeyWrapPad' - -+# Constants from OpenDNSSEC's enforcer/ksm/include/ksm/ksm.h -+KSM_STATE_PUBLISH = 2 -+KSM_STATE_READY = 3 -+KSM_STATE_ACTIVE = 4 -+KSM_STATE_RETIRE = 5 -+KSM_STATE_DEAD = 6 -+KSM_STATE_KEYPUBLISH = 10 -+ - # DNSKEY flag constants - dnskey_flag_by_value = { - 0x0001: 'SEP', -@@ -122,6 +130,77 @@ def sql2ldap_keyid(sql_keyid): - #uri += '%'.join(sql_keyid[i:i+2] for i in range(0, len(sql_keyid), 2)) - return {"idnsSecKeyRef": uri} - -+def ods2bind_timestamps(key_state, key_type, ods_times): -+ """Transform (timestamps and key states) from ODS to set of BIND timestamps -+ with equivalent meaning. At the same time, remove timestamps -+ for future/planned state transitions to prevent ODS & BIND -+ from desynchronizing. -+ -+ OpenDNSSEC database may contain timestamps for state transitions planned -+ in the future, but timestamp itself is not sufficient information because -+ there could be some additional condition which is guaded by OpenDNSSEC -+ itself. -+ -+ BIND works directly with timestamps without any additional conditions. -+ This difference causes problem when state transition planned in OpenDNSSEC -+ does not happen as originally planned for some reason. -+ -+ At the same time, this difference causes problem when OpenDNSSEC on DNSSEC -+ key master and BIND instances on replicas are not synchronized. This -+ happens when DNSSEC key master is down, or a replication is down. Even -+ a temporary desynchronization could cause DNSSEC validation failures -+ which could have huge impact. -+ -+ To prevent this problem, this function removes all timestamps corresponding -+ to future state transitions. As a result, BIND will not do state transition -+ until it happens in OpenDNSSEC first and until the change is replicated. -+ -+ Also, timestamp mapping depends on key type and is not 1:1. -+ For detailed description of the mapping please see -+ https://fedorahosted.org/bind-dyndb-ldap/wiki/BIND9/Design/DNSSEC/OpenDNSSEC2BINDKeyStates -+ """ -+ bind_times = {} -+ # idnsSecKeyCreated is equivalent to SQL column 'created' -+ bind_times['idnsSecKeyCreated'] = ods_times['idnsSecKeyCreated'] -+ -+ # set of key states where publishing in DNS zone is desired is taken from -+ # opendnssec/enforcer/ksm/ksm_request.c:KsmRequestIssueKeys() -+ # TODO: support for RFC 5011, requires OpenDNSSEC v1.4.8+ -+ if ('idnsSecKeyPublish' in ods_times and -+ key_state in {KSM_STATE_PUBLISH, KSM_STATE_READY, KSM_STATE_ACTIVE, -+ KSM_STATE_RETIRE, KSM_STATE_KEYPUBLISH}): -+ bind_times['idnsSecKeyPublish'] = ods_times['idnsSecKeyPublish'] -+ -+ # ZSK and KSK handling differs in enforcerd, see -+ # opendnssec/enforcer/enforcerd/enforcer.c:commKeyConfig() -+ if key_type == 'ZSK': -+ # idnsSecKeyActivate cannot be set before the key reaches ACTIVE state -+ if ('idnsSecKeyActivate' in ods_times and -+ key_state in {KSM_STATE_ACTIVE, KSM_STATE_RETIRE, KSM_STATE_DEAD}): -+ bind_times['idnsSecKeyActivate'] = ods_times['idnsSecKeyActivate'] -+ -+ # idnsSecKeyInactive cannot be set before the key reaches RETIRE state -+ if ('idnsSecKeyInactive' in ods_times and -+ key_state in {KSM_STATE_RETIRE, KSM_STATE_DEAD}): -+ bind_times['idnsSecKeyInactive'] = ods_times['idnsSecKeyInactive'] -+ -+ elif key_type == 'KSK': -+ # KSK is special: it is used for signing as long as it is in zone -+ if ('idnsSecKeyPublish' in ods_times and -+ key_state in {KSM_STATE_PUBLISH, KSM_STATE_READY, KSM_STATE_ACTIVE, -+ KSM_STATE_RETIRE, KSM_STATE_KEYPUBLISH}): -+ bind_times['idnsSecKeyActivate'] = ods_times['idnsSecKeyPublish'] -+ # idnsSecKeyInactive is ignored for KSK on purpose -+ -+ else: -+ assert False, "unsupported key type %s" % key_type -+ -+ # idnsSecKeyDelete is relevant only in DEAD state -+ if 'idnsSecKeyDelete' in ods_times and key_state == KSM_STATE_DEAD: -+ bind_times['idnsSecKeyDelete'] = ods_times['idnsSecKeyDelete'] -+ -+ return bind_times -+ - class ods_db_lock(object): - def __enter__(self): - self.f = open(ODS_DB_LOCK_PATH, 'w') -@@ -172,18 +251,20 @@ def get_ods_keys(zone_name): - assert len(rows) == 1, "exactly one DNS zone should exist in ODS DB" - zone_id = rows[0][0] - -- # get all keys for given zone ID -- cur = db.execute("SELECT kp.HSMkey_id, kp.generate, kp.algorithm, dnsk.publish, dnsk.active, dnsk.retire, dnsk.dead, dnsk.keytype " -- "FROM keypairs AS kp JOIN dnsseckeys AS dnsk ON kp.id = dnsk.keypair_id " -- "WHERE dnsk.zone_id = ?", (zone_id,)) -+ # get relevant keys for given zone ID: -+ # ignore keys which were generated but not used yet -+ # key state check is using constants from -+ # OpenDNSSEC's enforcer/ksm/include/ksm/ksm.h -+ # WARNING! OpenDNSSEC version 1 and 2 are using different constants! -+ cur = db.execute("SELECT kp.HSMkey_id, kp.generate, kp.algorithm, " -+ "dnsk.publish, dnsk.active, dnsk.retire, dnsk.dead, " -+ "dnsk.keytype, dnsk.state " -+ "FROM keypairs AS kp " -+ "JOIN dnsseckeys AS dnsk ON kp.id = dnsk.keypair_id " -+ "WHERE dnsk.zone_id = ?", (zone_id,)) - keys = {} - for row in cur: -- key_data = sql2datetimes(row) -- if 'idnsSecKeyDelete' in key_data \ -- and key_data['idnsSecKeyDelete'] > datetime.now(): -- continue # ignore deleted keys -- -- key_data.update(sql2ldap_flags(row['keytype'])) -+ key_data = sql2ldap_flags(row['keytype']) - assert key_data.get('idnsSecKeyZONE', None) == 'TRUE', \ - 'unexpected key type 0x%x' % row['keytype'] - if key_data.get('idnsSecKeySEP', 'FALSE') == 'TRUE': -@@ -191,6 +272,10 @@ def get_ods_keys(zone_name): - else: - key_type = 'ZSK' - -+ # transform key state to timestamps for BIND with equivalent semantics -+ ods_times = sql2datetimes(row) -+ key_data.update(ods2bind_timestamps(row['state'], key_type, ods_times)) -+ - key_data.update(sql2ldap_algorithm(row['algorithm'])) - key_id = "%s-%s-%s" % (key_type, - datetime2ldap(key_data['idnsSecKeyCreated']), --- -2.4.3 - diff --git a/SOURCES/0166-DNSSEC-Make-sure-that-current-key-state-in-LDAP-matc.patch b/SOURCES/0166-DNSSEC-Make-sure-that-current-key-state-in-LDAP-matc.patch deleted file mode 100644 index 532001c..0000000 --- a/SOURCES/0166-DNSSEC-Make-sure-that-current-key-state-in-LDAP-matc.patch +++ /dev/null @@ -1,51 +0,0 @@ -From 31a9cec3fc366954b3cb8943621834fdfce04bd3 Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Thu, 26 Nov 2015 15:19:03 +0100 -Subject: [PATCH] DNSSEC: Make sure that current key state in LDAP matches key - state in BIND - -We have to explicitly specify "none" value to prevent dnssec-keyfromlabel -utility from using current time for keys without "publish" and "activate" -timestamps. - -Previously this lead to situation where key was in (intermediate) state -"generated" in OpenDNSSEC but BIND started to use this key for signing. - -https://fedorahosted.org/freeipa/ticket/5348 - -Reviewed-By: Martin Basti -Reviewed-By: Martin Basti ---- - ipapython/dnssec/bindmgr.py | 6 +++++- - 1 file changed, 5 insertions(+), 1 deletion(-) - -diff --git a/ipapython/dnssec/bindmgr.py b/ipapython/dnssec/bindmgr.py -index 2c6781609594fa27812af3a01d16318198a3e120..70caaf4ee74f594c652cd82bccb8964e172bc719 100644 ---- a/ipapython/dnssec/bindmgr.py -+++ b/ipapython/dnssec/bindmgr.py -@@ -58,6 +58,8 @@ class BINDMgr(object): - return dt.strftime(time_bindfmt) - - def dates2params(self, ldap_attrs): -+ """Convert LDAP timestamps to list of parameters suitable -+ for dnssec-keyfromlabel utility""" - attr2param = {'idnsseckeypublish': '-P', - 'idnsseckeyactivate': '-A', - 'idnsseckeyinactive': '-I', -@@ -65,10 +67,12 @@ class BINDMgr(object): - - params = [] - for attr, param in attr2param.items(): -+ params.append(param) - if attr in ldap_attrs: -- params.append(param) - assert len(ldap_attrs[attr]) == 1, 'Timestamp %s is expected to be single-valued' % attr - params.append(self.time_ldap2bindfmt(ldap_attrs[attr][0])) -+ else: -+ params.append('none') - - return params - --- -2.4.3 - diff --git a/SOURCES/0167-DNSSEC-remove-obsolete-TODO-note.patch b/SOURCES/0167-DNSSEC-remove-obsolete-TODO-note.patch deleted file mode 100644 index 55a9a89..0000000 --- a/SOURCES/0167-DNSSEC-remove-obsolete-TODO-note.patch +++ /dev/null @@ -1,28 +0,0 @@ -From bb592115d2fbab6ca9a1b664c3d9bf1bcad5ba0f Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Wed, 2 Dec 2015 12:58:23 +0100 -Subject: [PATCH] DNSSEC: remove obsolete TODO note - -https://fedorahosted.org/freeipa/ticket/5348 - -Reviewed-By: Martin Basti -Reviewed-By: Martin Basti ---- - ipapython/dnssec/ldapkeydb.py | 1 - - 1 file changed, 1 deletion(-) - -diff --git a/ipapython/dnssec/ldapkeydb.py b/ipapython/dnssec/ldapkeydb.py -index 23e6b019c2f2d2644bd389ffec4772b99b8cfc37..74371ae19ca2fb7564a343cc79be20798b99f6d2 100644 ---- a/ipapython/dnssec/ldapkeydb.py -+++ b/ipapython/dnssec/ldapkeydb.py -@@ -181,7 +181,6 @@ class MasterKey(Key): - # TODO: replace this with 'autogenerate' to prevent collisions - uuid_rdn = DN('ipk11UniqueId=%s' % uuid.uuid1()) - entry_dn = DN(uuid_rdn, self.ldapkeydb.base_dn) -- # TODO: add ipaWrappingMech attribute - entry = self.ldap.make_entry(entry_dn, - objectClass=['ipaSecretKeyObject', 'ipk11Object'], - ipaSecretKey=data, --- -2.4.3 - diff --git a/SOURCES/0168-DNSSEC-add-debug-mode-to-ldapkeydb.py.patch b/SOURCES/0168-DNSSEC-add-debug-mode-to-ldapkeydb.py.patch deleted file mode 100644 index 7c1e7fb..0000000 --- a/SOURCES/0168-DNSSEC-add-debug-mode-to-ldapkeydb.py.patch +++ /dev/null @@ -1,105 +0,0 @@ -From 3daffad0d0e14790147fb7a3ba9be7072b79f3e2 Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Tue, 15 Dec 2015 14:13:23 +0100 -Subject: [PATCH] DNSSEC: add debug mode to ldapkeydb.py - -ldapkeydb.py can be executed directly now. In that case it will print -out key metadata as obtained using IPA LDAP API. - -Kerberos credential cache has to be filled with principal posessing -appropriate access rights before the script is execured. - -https://fedorahosted.org/freeipa/ticket/5348 - -Reviewed-By: Martin Basti -Reviewed-By: Martin Basti ---- - ipapython/dnssec/ldapkeydb.py | 54 +++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 52 insertions(+), 2 deletions(-) - -diff --git a/ipapython/dnssec/ldapkeydb.py b/ipapython/dnssec/ldapkeydb.py -index 74371ae19ca2fb7564a343cc79be20798b99f6d2..54a1fba1d2db8f27c9c9b881ff42201365852587 100644 ---- a/ipapython/dnssec/ldapkeydb.py -+++ b/ipapython/dnssec/ldapkeydb.py -@@ -4,6 +4,8 @@ - - from binascii import hexlify - import collections -+import logging -+from pprint import pprint - import sys - import time - -@@ -11,6 +13,7 @@ import ipalib - from ipapython.dn import DN - from ipapython import ipaldap - from ipapython import ipautil -+from ipapython import ipa_log_manager - from ipaplatform.paths import paths - - from abshsm import attrs_name2id, attrs_id2name, bool_attr_names, populate_pkcs11_metadata, AbstractHSM -@@ -135,8 +138,12 @@ class Key(collections.MutableMapping): - def __len__(self): - return len(self.entry) - -- def __str__(self): -- return str(self.entry) -+ def __repr__(self): -+ sanitized = dict(self.entry) -+ for attr in ['ipaPrivateKey', 'ipaPublicKey', 'ipk11publickeyinfo']: -+ if attr in sanitized: -+ del sanitized[attr] -+ return repr(sanitized) - - def _cleanup_key(self): - """remove default values from LDAP entry""" -@@ -347,3 +354,46 @@ class LdapKeyDB(AbstractHSM): - '(&(objectClass=ipk11PrivateKey)(objectClass=ipaPrivateKeyObject)(objectClass=ipk11PublicKey)(objectClass=ipaPublicKeyObject))')) - - return self.cache_zone_keypairs -+ -+if __name__ == '__main__': -+ # this is debugging mode -+ # print information we think are useful to stdout -+ # other garbage goes via logger to stderr -+ ipa_log_manager.standard_logging_setup(debug=True) -+ log = ipa_log_manager.root_logger -+ -+ # IPA framework initialization -+ ipalib.api.bootstrap(in_server=True, log=None) # no logging to file -+ ipalib.api.finalize() -+ -+ # LDAP initialization -+ dns_dn = DN(ipalib.api.env.container_dns, ipalib.api.env.basedn) -+ ldap = ipaldap.LDAPClient(ipalib.api.env.ldap_uri) -+ log.debug('Connecting to LDAP') -+ # GSSAPI will be used, used has to be kinited already -+ ldap.gssapi_bind() -+ log.debug('Connected') -+ -+ ldapkeydb = LdapKeyDB(log, ldap, DN(('cn', 'keys'), ('cn', 'sec'), -+ ipalib.api.env.container_dns, -+ ipalib.api.env.basedn)) -+ -+ print('replica public keys: CKA_WRAP = TRUE') -+ print('====================================') -+ for pubkey_id, pubkey in ldapkeydb.replica_pubkeys_wrap.items(): -+ print(hexlify(pubkey_id)) -+ pprint(pubkey) -+ -+ print('') -+ print('master keys') -+ print('===========') -+ for mkey_id, mkey in ldapkeydb.master_keys.items(): -+ print(hexlify(mkey_id)) -+ pprint(mkey) -+ -+ print('') -+ print('zone key pairs') -+ print('==============') -+ for key_id, key in ldapkeydb.zone_keypairs.items(): -+ print(hexlify(key_id)) -+ pprint(key) --- -2.4.3 - diff --git a/SOURCES/0169-DNSSEC-logging-improvements-in-ipa-ods-exporter.patch b/SOURCES/0169-DNSSEC-logging-improvements-in-ipa-ods-exporter.patch deleted file mode 100644 index 1c357a0..0000000 --- a/SOURCES/0169-DNSSEC-logging-improvements-in-ipa-ods-exporter.patch +++ /dev/null @@ -1,69 +0,0 @@ -From 7398819200c9a3a32effa52793240a054bc4b10f Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Tue, 15 Dec 2015 14:16:52 +0100 -Subject: [PATCH] DNSSEC: logging improvements in ipa-ods-exporter - -https://fedorahosted.org/freeipa/ticket/5348 - -Reviewed-By: Martin Basti -Reviewed-By: Martin Basti ---- - daemons/dnssec/ipa-ods-exporter | 17 +++++++++++------ - 1 file changed, 11 insertions(+), 6 deletions(-) - -diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter -index 6ed7588847042e742abeef724940eec31f23ca8f..051fa53a950f7afbea5e9b1e541a9435aa02bc17 100755 ---- a/daemons/dnssec/ipa-ods-exporter -+++ b/daemons/dnssec/ipa-ods-exporter -@@ -491,6 +491,11 @@ def cmd2ods_zone_name(cmd): - return zone_name - - def sync_zone(log, ldap, dns_dn, zone_name): -+ """synchronize metadata about zone keys for single DNS zone -+ -+ Key material has to be synchronized elsewhere. -+ Keep in mind that keys could be shared among multiple zones!""" -+ log.getChild("%s.%s" % (__name__, zone_name)) - log.debug('synchronizing zone "%s"', zone_name) - ods_keys = get_ods_keys(zone_name) - ods_keys_id = set(ods_keys.keys()) -@@ -523,30 +528,30 @@ def sync_zone(log, ldap, dns_dn, zone_name): - ldap_keys_id = set(ldap_keys.keys()) - - new_keys_id = ods_keys_id - ldap_keys_id -- log.info('new keys from ODS: %s', new_keys_id) -+ log.info('new key metadata from ODS: %s', new_keys_id) - for key_id in new_keys_id: - cn = "cn=%s" % key_id - key_dn = DN(cn, keys_dn) -- log.debug('adding key "%s" to LDAP', key_dn) -+ log.debug('adding key metadata "%s" to LDAP', key_dn) - ldap_key = ldap.make_entry(key_dn, - objectClass=['idnsSecKey'], - **ods_keys[key_id]) - ldap.add_entry(ldap_key) - - deleted_keys_id = ldap_keys_id - ods_keys_id -- log.info('deleted keys in LDAP: %s', deleted_keys_id) -+ log.info('deleted key metadata in LDAP: %s', deleted_keys_id) - for key_id in deleted_keys_id: - cn = "cn=%s" % key_id - key_dn = DN(cn, keys_dn) -- log.debug('deleting key "%s" from LDAP', key_dn) -+ log.debug('deleting key metadata "%s" from LDAP', key_dn) - ldap.delete_entry(key_dn) - - update_keys_id = ldap_keys_id.intersection(ods_keys_id) -- log.info('keys in LDAP & ODS: %s', update_keys_id) -+ log.info('key metadata in LDAP & ODS: %s', update_keys_id) - for key_id in update_keys_id: - ldap_key = ldap_keys[key_id] - ods_key = ods_keys[key_id] -- log.debug('updating key "%s" in LDAP', ldap_key.dn) -+ log.debug('updating key metadata "%s" in LDAP', ldap_key.dn) - ldap_key.update(ods_key) - try: - ldap.update_entry(ldap_key) --- -2.4.3 - diff --git a/SOURCES/0170-DNSSEC-remove-keys-purged-by-OpenDNSSEC-from-master-.patch b/SOURCES/0170-DNSSEC-remove-keys-purged-by-OpenDNSSEC-from-master-.patch deleted file mode 100644 index c204e3c..0000000 --- a/SOURCES/0170-DNSSEC-remove-keys-purged-by-OpenDNSSEC-from-master-.patch +++ /dev/null @@ -1,248 +0,0 @@ -From db24ab9357ea63deaf25e8b9c5b3ad2d08a0c82b Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Tue, 15 Dec 2015 15:22:45 +0100 -Subject: [PATCH] DNSSEC: remove keys purged by OpenDNSSEC from master HSM from - LDAP - -Key purging has to be only only after key metadata purging so -ipa-dnskeysyncd on replices does not fail while dereferencing -non-existing keys. - -https://fedorahosted.org/freeipa/ticket/5334 - -Reviewed-By: Martin Basti -Reviewed-By: Martin Basti ---- - daemons/dnssec/ipa-ods-exporter | 45 ++++++++++++++++++++++---- - ipapython/dnssec/ldapkeydb.py | 72 ++++++++++++++++++++++++++++++++++------- - 2 files changed, 99 insertions(+), 18 deletions(-) - -diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter -index 051fa53a950f7afbea5e9b1e541a9435aa02bc17..2a1cc4315355569b24ec6ef42a68f4d64fee9f4f 100755 ---- a/daemons/dnssec/ipa-ods-exporter -+++ b/daemons/dnssec/ipa-ods-exporter -@@ -387,7 +387,10 @@ def master2ldap_master_keys_sync(log, ldapkeydb, localhsm): - ldapkeydb.flush() - - def master2ldap_zone_keys_sync(log, ldapkeydb, localhsm): -- # synchroniza zone keys -+ """add and update zone key material from local HSM to LDAP -+ -+ No key material will be removed, only new keys will be added or updated. -+ Key removal is hanled by master2ldap_zone_keys_purge().""" - log = log.getChild('master2ldap_zone_keys') - keypairs_ldap = ldapkeydb.zone_keypairs - log.debug("zone keys in LDAP: %s", hex_set(keypairs_ldap)) -@@ -396,10 +399,10 @@ def master2ldap_zone_keys_sync(log, ldapkeydb, localhsm): - privkeys_local = localhsm.zone_privkeys - log.debug("zone keys in local HSM: %s", hex_set(privkeys_local)) - -- assert set(pubkeys_local) == set(privkeys_local), \ -- "IDs of private and public keys for DNS zones in local HSM does " \ -- "not match to key pairs: %s vs. %s" % \ -- (hex_set(pubkeys_local), hex_set(privkeys_local)) -+ assert set(pubkeys_local) == set(privkeys_local), ( -+ "IDs of private and public keys for DNS zones in local HSM does " -+ "not match to key pairs: %s vs. %s" % -+ (hex_set(pubkeys_local), hex_set(privkeys_local))) - - new_keys = set(pubkeys_local) - set(keypairs_ldap) - log.debug("new zone keys in local HSM: %s", hex_set(new_keys)) -@@ -420,6 +423,29 @@ def master2ldap_zone_keys_sync(log, ldapkeydb, localhsm): - sync_set_metadata_2ldap(log, privkeys_local, keypairs_ldap) - ldapkeydb.flush() - -+def master2ldap_zone_keys_purge(log, ldapkeydb, localhsm): -+ """purge removed key material from LDAP (but not metadata) -+ -+ Keys which are present in LDAP but not in local HSM will be removed. -+ Key metadata must be removed first so references to removed key material -+ are removed before actually removing the keys.""" -+ keypairs_ldap = ldapkeydb.zone_keypairs -+ log.debug("zone keys in LDAP: %s", hex_set(keypairs_ldap)) -+ -+ pubkeys_local = localhsm.zone_pubkeys -+ privkeys_local = localhsm.zone_privkeys -+ log.debug("zone keys in local HSM: %s", hex_set(privkeys_local)) -+ assert set(pubkeys_local) == set(privkeys_local), \ -+ "IDs of private and public keys for DNS zones in local HSM does " \ -+ "not match to key pairs: %s vs. %s" % \ -+ (hex_set(pubkeys_local), hex_set(privkeys_local)) -+ -+ deleted_key_ids = set(keypairs_ldap) - set(pubkeys_local) -+ log.debug("zone keys deleted from local HSM but present in LDAP: %s", -+ hex_set(deleted_key_ids)) -+ for zkey_id in deleted_key_ids: -+ keypairs_ldap[zkey_id].schedule_deletion() -+ ldapkeydb.flush() - - def hex_set(s): - out = set() -@@ -600,7 +626,7 @@ ldap.connect(ccache=ccache_name) - log.debug('Connected') - - --### DNSSEC master: key synchronization -+### DNSSEC master: key material upload & synchronization (but not deletion) - ldapkeydb = LdapKeyDB(log, ldap, DN(('cn', 'keys'), ('cn', 'sec'), - ipalib.api.env.container_dns, - ipalib.api.env.basedn)) -@@ -612,7 +638,7 @@ master2ldap_master_keys_sync(log, ldapkeydb, localhsm) - master2ldap_zone_keys_sync(log, ldapkeydb, localhsm) - - --### DNSSEC master: DNSSEC key metadata upload -+### DNSSEC master: DNSSEC key metadata upload & synchronization & deletion - # command receive is delayed so the command will stay in socket queue until - # the problem with LDAP server or HSM is fixed - try: -@@ -666,6 +692,11 @@ try: - for zone_row in db.execute("SELECT name FROM zones"): - sync_zone(log, ldap, dns_dn, zone_row['name']) - -+ ### DNSSEC master: DNSSEC key material purging -+ # references to old key material were removed above in sync_zone() -+ # so now we can purge old key material from LDAP -+ master2ldap_zone_keys_purge(log, ldapkeydb, localhsm) -+ - except Exception as ex: - msg = "ipa-ods-exporter exception: %s" % traceback.format_exc(ex) - log.exception(ex) -diff --git a/ipapython/dnssec/ldapkeydb.py b/ipapython/dnssec/ldapkeydb.py -index 54a1fba1d2db8f27c9c9b881ff42201365852587..2131508cc6779d1cc99c417a31da866b7fdcf2c2 100644 ---- a/ipapython/dnssec/ldapkeydb.py -+++ b/ipapython/dnssec/ldapkeydb.py -@@ -105,40 +105,56 @@ def get_default_attrs(object_classes): - result.update(defaults[cls]) - return result - -+ - class Key(collections.MutableMapping): - """abstraction to hide LDAP entry weirdnesses: - - non-normalized attribute names - - boolean attributes returned as strings -+ - planned entry deletion prevents subsequent use of the instance - """ - def __init__(self, entry, ldap, ldapkeydb): - self.entry = entry -+ self._delentry = None # indicates that object was deleted - self.ldap = ldap - self.ldapkeydb = ldapkeydb - self.log = ldap.log.getChild(__name__) - -+ def __assert_not_deleted(self): -+ assert self.entry and not self._delentry, ( -+ "attempt to use to-be-deleted entry %s detected" -+ % self._delentry.dn) -+ - def __getitem__(self, key): -+ self.__assert_not_deleted() - val = self.entry.single_value[key] - if key.lower() in bool_attr_names: - val = ldap_bool(val) - return val - - def __setitem__(self, key, value): -+ self.__assert_not_deleted() - self.entry[key] = value - - def __delitem__(self, key): -+ self.__assert_not_deleted() - del self.entry[key] - - def __iter__(self): - """generates list of ipa names of all PKCS#11 attributes present in the object""" -+ self.__assert_not_deleted() - for ipa_name in self.entry.keys(): - lowercase = ipa_name.lower() - if lowercase in attrs_name2id: - yield lowercase - - def __len__(self): -+ self.__assert_not_deleted() - return len(self.entry) - - def __repr__(self): -+ if self._delentry: -+ return 'deleted entry: %s' % repr(self._delentry) -+ - sanitized = dict(self.entry) - for attr in ['ipaPrivateKey', 'ipaPublicKey', 'ipk11publickeyinfo']: - if attr in sanitized: -@@ -153,6 +169,49 @@ class Key(collections.MutableMapping): - if self.get(attr, empty) == default_attrs[attr]: - del self[attr] - -+ def _update_key(self): -+ """remove default values from LDAP entry and write back changes""" -+ if self._delentry: -+ self._delete_key() -+ return -+ -+ self._cleanup_key() -+ -+ try: -+ self.ldap.update_entry(self.entry) -+ except ipalib.errors.EmptyModlist: -+ pass -+ -+ def _delete_key(self): -+ """remove key metadata entry from LDAP -+ -+ After calling this, the python object is no longer valid and all -+ subsequent method calls on it will fail. -+ """ -+ assert not self.entry, ( -+ "Key._delete_key() called before Key.schedule_deletion()") -+ assert self._delentry, "Key._delete_key() called more than once" -+ self.log.debug('deleting key id 0x%s DN %s from LDAP', -+ hexlify(self._delentry.single_value['ipk11id']), -+ self._delentry.dn) -+ self.ldap.delete_entry(self._delentry) -+ self._delentry = None -+ self.ldap = None -+ self.ldapkeydb = None -+ -+ def schedule_deletion(self): -+ """schedule key deletion from LDAP -+ -+ Calling schedule_deletion() will make this object incompatible with -+ normal Key. After that the object must not be read or modified. -+ Key metadata will be actually deleted when LdapKeyDB.flush() is called. -+ """ -+ assert not self._delentry, ( -+ "Key.schedule_deletion() called more than once") -+ self._delentry = self.entry -+ self.entry = None -+ -+ - class ReplicaKey(Key): - # TODO: object class assert - def __init__(self, entry, ldap, ldapkeydb): -@@ -239,21 +298,12 @@ class LdapKeyDB(AbstractHSM): - self._update_keys() - return keys - -- def _update_key(self, key): -- """remove default values from LDAP entry and write back changes""" -- key._cleanup_key() -- -- try: -- self.ldap.update_entry(key.entry) -- except ipalib.errors.EmptyModlist: -- pass -- - def _update_keys(self): - for cache in [self.cache_masterkeys, self.cache_replica_pubkeys_wrap, -- self.cache_zone_keypairs]: -+ self.cache_zone_keypairs]: - if cache: - for key in cache.itervalues(): -- self._update_key(key) -+ key._update_key() - - def flush(self): - """write back content of caches to LDAP""" --- -2.4.3 - diff --git a/SOURCES/0171-DNSSEC-ipa-dnskeysyncd-Skip-zones-with-old-DNSSEC-me.patch b/SOURCES/0171-DNSSEC-ipa-dnskeysyncd-Skip-zones-with-old-DNSSEC-me.patch deleted file mode 100644 index d248eb3..0000000 --- a/SOURCES/0171-DNSSEC-ipa-dnskeysyncd-Skip-zones-with-old-DNSSEC-me.patch +++ /dev/null @@ -1,125 +0,0 @@ -From 96695bb8e414be941e07d43652516a99cfd89a24 Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Sun, 20 Dec 2015 18:36:48 +0100 -Subject: [PATCH] DNSSEC: ipa-dnskeysyncd: Skip zones with old DNSSEC metadata - in LDAP - -This filtering is useful in cases where LDAP contains DNS zones which -have old metadata objects and DNSSEC disabled. Such zones must be -ignored to prevent errors while calling dnssec-keyfromlabel or rndc. - -https://fedorahosted.org/freeipa/ticket/5348 - -Reviewed-By: Martin Basti -Reviewed-By: Martin Basti ---- - ipapython/dnssec/bindmgr.py | 16 +++++++++++++--- - ipapython/dnssec/keysyncer.py | 24 ++++++++++++++++++------ - 2 files changed, 31 insertions(+), 9 deletions(-) - -diff --git a/ipapython/dnssec/bindmgr.py b/ipapython/dnssec/bindmgr.py -index 70caaf4ee74f594c652cd82bccb8964e172bc719..d81dad940df49e79f4534c2224c10ecf192794ba 100644 ---- a/ipapython/dnssec/bindmgr.py -+++ b/ipapython/dnssec/bindmgr.py -@@ -191,10 +191,20 @@ class BINDMgr(object): - - self.notify_zone(zone) - -- def sync(self): -- """Synchronize list of zones in LDAP with BIND.""" -+ def sync(self, dnssec_zones): -+ """Synchronize list of zones in LDAP with BIND. -+ -+ dnssec_zones lists zones which should be processed. All other zones -+ will be ignored even though they were modified using ldap_event(). -+ -+ This filter is useful in cases where LDAP contains DNS zones which -+ have old metadata objects and DNSSEC disabled. Such zones must be -+ ignored to prevent errors while calling dnssec-keyfromlabel or rndc. -+ """ - self.log.debug('Key metadata in LDAP: %s' % self.ldap_keys) -- for zone in self.modified_zones: -+ self.log.debug('Zones modified but skipped during bindmgr.sync: %s', -+ self.modified_zones - dnssec_zones) -+ for zone in self.modified_zones.intersection(dnssec_zones): - self.sync_zone(zone) - - self.modified_zones = set() -diff --git a/ipapython/dnssec/keysyncer.py b/ipapython/dnssec/keysyncer.py -index de5b5aa5f670db4c58fb92b989e181d45d887b55..5ba9baaab30b07d2f4e4ae3a3507898d08a0d6c1 100644 ---- a/ipapython/dnssec/keysyncer.py -+++ b/ipapython/dnssec/keysyncer.py -@@ -6,6 +6,8 @@ import logging - import ldap.dn - import os - -+import dns.name -+ - from ipaplatform.paths import paths - from ipapython import ipautil - -@@ -33,6 +35,7 @@ class KeySyncer(SyncReplConsumer): - - self.bindmgr = BINDMgr(self.api) - self.init_done = False -+ self.dnssec_zones = set() - SyncReplConsumer.__init__(self, *args, **kwargs) - - def _get_objclass(self, attrs): -@@ -112,7 +115,7 @@ class KeySyncer(SyncReplConsumer): - self.ods_sync() - self.hsm_replica_sync() - self.hsm_master_sync() -- self.bindmgr.sync() -+ self.bindmgr.sync(self.dnssec_zones) - - # idnsSecKey wrapper - # Assumption: metadata points to the same key blob all the time, -@@ -121,23 +124,29 @@ class KeySyncer(SyncReplConsumer): - def key_meta_add(self, uuid, dn, newattrs): - self.hsm_replica_sync() - self.bindmgr.ldap_event('add', uuid, newattrs) -- self.bindmgr_sync() -+ self.bindmgr_sync(self.dnssec_zones) - - def key_meta_del(self, uuid, dn, oldattrs): - self.bindmgr.ldap_event('del', uuid, oldattrs) -- self.bindmgr_sync() -+ self.bindmgr_sync(self.dnssec_zones) - self.hsm_replica_sync() - - def key_metadata_sync(self, uuid, dn, oldattrs, newattrs): - self.bindmgr.ldap_event('mod', uuid, newattrs) -- self.bindmgr_sync() -+ self.bindmgr_sync(self.dnssec_zones) - -- def bindmgr_sync(self): -+ def bindmgr_sync(self, dnssec_zones): - if self.init_done: -- self.bindmgr.sync() -+ self.bindmgr.sync(dnssec_zones) - - # idnsZone wrapper - def zone_add(self, uuid, dn, newattrs): -+ zone = dns.name.from_text(newattrs['idnsname'][0]) -+ if self.__is_dnssec_enabled(newattrs): -+ self.dnssec_zones.add(zone) -+ else: -+ self.dnssec_zones.discard(zone) -+ - if not self.ismaster: - return - -@@ -146,6 +155,9 @@ class KeySyncer(SyncReplConsumer): - self.ods_sync() - - def zone_del(self, uuid, dn, oldattrs): -+ zone = dns.name.from_text(oldattrs['idnsname'][0]) -+ self.dnssec_zones.discard(zone) -+ - if not self.ismaster: - return - --- -2.4.3 - diff --git a/SOURCES/0172-DNSSEC-ipa-ods-exporter-add-ldap-cleanup-command.patch b/SOURCES/0172-DNSSEC-ipa-ods-exporter-add-ldap-cleanup-command.patch deleted file mode 100644 index d28cb57..0000000 --- a/SOURCES/0172-DNSSEC-ipa-ods-exporter-add-ldap-cleanup-command.patch +++ /dev/null @@ -1,142 +0,0 @@ -From a5687f3070877fc28435d9db4d5fed8c521dbf41 Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Sun, 20 Dec 2015 19:19:28 +0100 -Subject: [PATCH] DNSSEC: ipa-ods-exporter: add ldap-cleanup command - -Command "ldap-cleanup " will remove all key metadata from -LDAP. This can be used manually in sequence like: -ldap-cleanup -update -to delete all key metadata from LDAP and re-export them from OpenDNSSEC. - -ldap-cleanup command should be called when disabling DNSSEC on a DNS -zone to remove stale key metadata from LDAP. - -https://fedorahosted.org/freeipa/ticket/5348 - -Reviewed-By: Martin Basti -Reviewed-By: Martin Basti ---- - daemons/dnssec/ipa-ods-exporter | 60 ++++++++++++++++++++++++++++++++--------- - 1 file changed, 48 insertions(+), 12 deletions(-) - -diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter -index 2a1cc4315355569b24ec6ef42a68f4d64fee9f4f..8abb5cf7c6d1e5e8ea996b8925d2e8cffc44133c 100755 ---- a/daemons/dnssec/ipa-ods-exporter -+++ b/daemons/dnssec/ipa-ods-exporter -@@ -227,7 +227,9 @@ def get_ldap_zone(ldap, dns_base, name): - except ipalib.errors.NotFound: - continue - -- assert ldap_zone is not None, 'DNS zone "%s" should exist in LDAP' % name -+ if ldap_zone is None: -+ raise ipalib.errors.NotFound( -+ reason='DNS zone "%s" not found in LDAP' % name) - - return ldap_zone - -@@ -481,25 +483,37 @@ def parse_command(cmd): - if cmd == 'ipa-hsm-update': - return (0, - 'HSM synchronization finished, skipping zone synchronization.', -- None) -+ None, -+ cmd) - - elif cmd == 'ipa-full-update': - return (None, - 'Synchronization of all zones was finished.', -- None) -+ None, -+ cmd) -+ -+ elif cmd.startswith('ldap-cleanup '): -+ zone_name = cmd2ods_zone_name(cmd) -+ return (None, -+ 'Zone "%s" metadata will be removed from LDAP.\n' % zone_name, -+ zone_name, -+ 'ldap-cleanup') - -- elif not cmd.startswith('update '): -+ elif cmd.startswith('update '): -+ zone_name = cmd2ods_zone_name(cmd) -+ return (None, -+ 'Zone "%s" metadata will be updated in LDAP.\n' % zone_name, -+ zone_name, -+ 'update') -+ -+ else: - return (0, - 'Command "%s" is not supported by IPA; ' - 'HSM synchronization was finished and the command ' - 'will be ignored.' % cmd, -+ None, - None) - -- else: -- zone_name = cmd2ods_zone_name(cmd) -- return (None, -- 'Zone was "%s" updated.\n' % zone_name, -- zone_name) - - def send_systemd_reply(conn, reply): - # Reply & close connection early. -@@ -510,7 +524,7 @@ def send_systemd_reply(conn, reply): - - def cmd2ods_zone_name(cmd): - # ODS stores zone name without trailing period -- zone_name = cmd[7:].strip() -+ zone_name = cmd.split(' ', 1)[1].strip() - if len(zone_name) > 1 and zone_name[-1] == '.': - zone_name = zone_name[:-1] - -@@ -584,6 +598,25 @@ def sync_zone(log, ldap, dns_dn, zone_name): - except ipalib.errors.EmptyModlist: - continue - -+def cleanup_ldap_zone(log, ldap, dns_dn, zone_name): -+ """delete all key metadata about zone keys for single DNS zone -+ -+ Key material has to be synchronized elsewhere. -+ Keep in mind that keys could be shared among multiple zones!""" -+ log = log.getChild("%s.%s" % (__name__, zone_name)) -+ log.debug('cleaning up key metadata from zone "%s"', zone_name) -+ -+ try: -+ ldap_zone = get_ldap_zone(ldap, dns_dn, zone_name) -+ ldap_keys = get_ldap_keys(ldap, ldap_zone.dn) -+ except ipalib.errors.NotFound as ex: -+ # zone or cn=keys container does not exist, we are done -+ log.debug(str(ex)) -+ return -+ -+ for ldap_key in ldap_keys: -+ log.debug('deleting key metadata "%s"', ldap_key.dn) -+ ldap.delete_entry(ldap_key) - - log = logging.getLogger('root') - # this service is usually socket-activated -@@ -656,7 +689,7 @@ except KeyError as e: - conn = None - cmd = sys.argv[1] - --exitcode, msg, zone_name = parse_command(cmd) -+exitcode, msg, zone_name, cmd = parse_command(cmd) - - if exitcode is not None: - if conn: -@@ -686,7 +719,10 @@ try: - - if zone_name is not None: - # only one zone should be processed -- sync_zone(log, ldap, dns_dn, zone_name) -+ if cmd == 'update': -+ sync_zone(log, ldap, dns_dn, zone_name) -+ elif cmd == 'ldap-cleanup': -+ cleanup_ldap_zone(log, ldap, dns_dn, zone_name) - else: - # process all zones - for zone_row in db.execute("SELECT name FROM zones"): --- -2.4.3 - diff --git a/SOURCES/0173-DNSSEC-ipa-dnskeysyncd-call-ods-signer-ldap-cleanup-.patch b/SOURCES/0173-DNSSEC-ipa-dnskeysyncd-call-ods-signer-ldap-cleanup-.patch deleted file mode 100644 index 2f5d404..0000000 --- a/SOURCES/0173-DNSSEC-ipa-dnskeysyncd-call-ods-signer-ldap-cleanup-.patch +++ /dev/null @@ -1,44 +0,0 @@ -From dbb7b91bf052bc4d5a4f545044e8949b67b511db Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Sun, 20 Dec 2015 19:35:55 +0100 -Subject: [PATCH] DNSSEC: ipa-dnskeysyncd: call ods-signer ldap-cleanup on zone - removal - -Command "ldap-cleanup " is called to remove all key metadata from -LDAP. This command is now called when disabling DNSSEC on a DNS zone. The stale -metadata were causing problems when re-enabling DNSSEC on the same zone. - -https://fedorahosted.org/freeipa/ticket/5348 - -Reviewed-By: Martin Basti -Reviewed-By: Martin Basti ---- - ipapython/dnssec/odsmgr.py | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/ipapython/dnssec/odsmgr.py b/ipapython/dnssec/odsmgr.py -index efbe16cc6ebf050d9cf347ed97b2b2e4b37c8a6e..44d94ac3ab9e68feba067e8f14530894bda22855 100644 ---- a/ipapython/dnssec/odsmgr.py -+++ b/ipapython/dnssec/odsmgr.py -@@ -152,12 +152,18 @@ class ODSMgr(object): - output = self.ksmutil(cmd) - self.log.info(output) - self.notify_enforcer() -+ self.cleanup_signer(name) - - def notify_enforcer(self): - cmd = ['notify'] - output = self.ksmutil(cmd) - self.log.info(output) - -+ def cleanup_signer(self, zone_name): -+ cmd = ['ods-signer', 'ldap-cleanup', str(zone_name)] -+ output = ipautil.run(cmd, capture_output=True) -+ self.log.info(output) -+ - def ldap_event(self, op, uuid, attrs): - """Record single LDAP event - zone addition or deletion. - --- -2.4.3 - diff --git a/SOURCES/0174-DNSSEC-Log-debug-messages-at-log-level-DEBUG.patch b/SOURCES/0174-DNSSEC-Log-debug-messages-at-log-level-DEBUG.patch deleted file mode 100644 index 1388c9d..0000000 --- a/SOURCES/0174-DNSSEC-Log-debug-messages-at-log-level-DEBUG.patch +++ /dev/null @@ -1,29 +0,0 @@ -From d3c3377ecf597787af7d8975f6d0a822798585f9 Mon Sep 17 00:00:00 2001 -From: Petr Spacek -Date: Tue, 24 Nov 2015 12:49:16 +0100 -Subject: [PATCH] DNSSEC: Log debug messages at log level DEBUG - -https://fedorahosted.org/freeipa/ticket/5348 - -Reviewed-By: Martin Basti -Reviewed-By: Martin Basti ---- - daemons/dnssec/ipa-ods-exporter | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/daemons/dnssec/ipa-ods-exporter b/daemons/dnssec/ipa-ods-exporter -index 8abb5cf7c6d1e5e8ea996b8925d2e8cffc44133c..2b71b0c38eeb9c5f61adecdb802c081433e3db27 100755 ---- a/daemons/dnssec/ipa-ods-exporter -+++ b/daemons/dnssec/ipa-ods-exporter -@@ -310,7 +310,7 @@ def ldap2master_replica_keys_sync(log, ldapkeydb, localhsm): - log.info("new replica keys in LDAP: %s", hex_set(new_replica_keys)) - for key_id in new_replica_keys: - new_key_ldap = ldapkeydb.replica_pubkeys_wrap[key_id] -- log.error('label=%s, id=%s, data=%s', -+ log.debug('label=%s, id=%s, data=%s', - new_key_ldap['ipk11label'], - hexlify(new_key_ldap['ipk11id']), - hexlify(new_key_ldap['ipapublickey'])) --- -2.4.3 - diff --git a/SOURCES/0175-Allow-to-used-mixed-case-for-sysrestore.patch b/SOURCES/0175-Allow-to-used-mixed-case-for-sysrestore.patch deleted file mode 100644 index 24d9208..0000000 --- a/SOURCES/0175-Allow-to-used-mixed-case-for-sysrestore.patch +++ /dev/null @@ -1,86 +0,0 @@ -From f7e06707be5c590ce03a50117da483931a0680c6 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Tue, 5 Jan 2016 17:58:49 +0100 -Subject: [PATCH] Allow to used mixed case for sysrestore - -This commit allows to use mixed case of keys for sysrestore, before this -commit all keys were saved in lowercase what prevents to accesing them. - -Original usage of mixed case for sysretore key in opendssecinstance had -to be changed to lowercase to prevent issues on already installed -systems. - -https://fedorahosted.org/freeipa/ticket/5574 - -Reviewed-By: Martin Babinsky ---- - ipapython/sysrestore.py | 4 ++++ - ipaserver/install/opendnssecinstance.py | 6 ++++-- - 2 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/ipapython/sysrestore.py b/ipapython/sysrestore.py -index 1a111258bc0f6dd503673028d3a990821f077fef..97f0d760ae58c8d4bd0409565bf47167a689a06c 100644 ---- a/ipapython/sysrestore.py -+++ b/ipapython/sysrestore.py -@@ -67,6 +67,7 @@ class FileStore: - self.files = {} - - p = ConfigParser.SafeConfigParser() -+ p.optionxform = str - p.read(self._index) - - for section in p.sections(): -@@ -88,6 +89,7 @@ class FileStore: - return - - p = ConfigParser.SafeConfigParser() -+ p.optionxform = str - - p.add_section('files') - for (key, value) in self.files.items(): -@@ -324,6 +326,7 @@ class StateFile: - self.modules = {} - - p = ConfigParser.SafeConfigParser() -+ p.optionxform = str - p.read(self._path) - - for module in p.sections(): -@@ -352,6 +355,7 @@ class StateFile: - return - - p = ConfigParser.SafeConfigParser() -+ p.optionxform = str - - for module in self.modules.keys(): - p.add_section(module) -diff --git a/ipaserver/install/opendnssecinstance.py b/ipaserver/install/opendnssecinstance.py -index c5377d910d8f38a1ea0e05461ecf1b92f05ca2ca..2ab320b8e5db6c7c4e03850ecfe26e0e178d04a1 100644 ---- a/ipaserver/install/opendnssecinstance.py -+++ b/ipaserver/install/opendnssecinstance.py -@@ -265,11 +265,11 @@ class OpenDNSSECInstance(service.Service): - - def __setup_dnssec(self): - # run once only -- if self.get_state("KASP_DB_configured") and not self.kasp_db_file: -+ if self.get_state("kasp_db_configured") and not self.kasp_db_file: - root_logger.debug("Already configured, skipping step") - return - -- self.backup_state("KASP_DB_configured", True) -+ self.backup_state("kasp_db_configured", True) - - if not self.fstore.has_file(paths.OPENDNSSEC_KASP_DB): - self.fstore.backup_file(paths.OPENDNSSEC_KASP_DB) -@@ -368,6 +368,8 @@ class OpenDNSSECInstance(service.Service): - root_logger.debug(error) - pass - -+ self.restore_state("kasp_db_configured") # just eat state -+ - # disabled by default, by ldap_enable() - if enabled: - self.enable() --- -2.4.3 - diff --git a/SOURCES/0176-prevent-crash-of-CA-less-server-upgrade-due-to-absen.patch b/SOURCES/0176-prevent-crash-of-CA-less-server-upgrade-due-to-absen.patch deleted file mode 100644 index b24e5d7..0000000 --- a/SOURCES/0176-prevent-crash-of-CA-less-server-upgrade-due-to-absen.patch +++ /dev/null @@ -1,77 +0,0 @@ -From 61f54afcde1df217fec01aa9ab38b0b9b704c501 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Tue, 5 Jan 2016 13:00:24 +0100 -Subject: [PATCH] prevent crash of CA-less server upgrade due to absent - certmonger - -ipa-server-upgrade tests whether certmonger service is running before -attempting to upgrade IPA master. This causes the upgrader to always fail when -there is no CA installer and certmonger is not needed, effectively preventing -CA-less IPA master to upgrade succefuly. - -This test is now skipped if CA is not enabled. - -https://fedorahosted.org/freeipa/ticket/5519 - -Reviewed-By: Jan Cholasta ---- - ipaserver/install/server/upgrade.py | 29 +++++++++++++++++++++++++++-- - 1 file changed, 27 insertions(+), 2 deletions(-) - -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index 945cb3ebd63767cb1d57083e1da7c5605ac5a2f9..616fba5c1a5b3737481aecbb09ab5344641a3b04 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -292,6 +292,24 @@ def setup_firefox_extension(fstore): - http.setup_firefox_extension(realm, domain) - - -+def is_ca_enabled(): -+ """ -+ check whether there is an active CA master -+ :return: True if there is an active CA in topology, False otherwise -+ """ -+ ldap2 = api.Backend.ldap2 -+ was_connected = ldap2.isconnected() -+ -+ if not was_connected: -+ ldap2.connect() -+ -+ try: -+ return api.Command.ca_is_enabled()['result'] -+ finally: -+ if not was_connected: -+ ldap2.disconnect() -+ -+ - def ca_configure_profiles_acl(ca): - root_logger.info('[Authorizing RA Agent to modify profiles]') - -@@ -1416,7 +1434,9 @@ def upgrade_configuration(): - http = httpinstance.HTTPInstance(fstore) - http.configure_selinux_for_httpd() - http.change_mod_nss_port_from_http() -- http.configure_certmonger_renewal_guard() -+ -+ if is_ca_enabled(): -+ http.configure_certmonger_renewal_guard() - - ds.configure_dirsrv_ccache() - -@@ -1562,7 +1582,12 @@ def upgrade_check(options): - print unicode(e) - sys.exit(1) - -- if not services.knownservices.certmonger.is_running(): -+ try: -+ ca_is_enabled = is_ca_enabled() -+ except Exception as e: -+ raise RuntimeError("Cannot connect to LDAP server: {0}".format(e)) -+ -+ if not services.knownservices.certmonger.is_running() and ca_is_enabled: - raise RuntimeError('Certmonger is not running. Start certmonger and run upgrade again.') - - if not options.skip_version_check: --- -2.4.3 - diff --git a/SOURCES/0177-Upgrade-Fix-upgrade-of-NIS-Server-configuration.patch b/SOURCES/0177-Upgrade-Fix-upgrade-of-NIS-Server-configuration.patch deleted file mode 100644 index 6dd6c5d..0000000 --- a/SOURCES/0177-Upgrade-Fix-upgrade-of-NIS-Server-configuration.patch +++ /dev/null @@ -1,251 +0,0 @@ -From e22b4320033803331ce8960d05113666fe9192ec Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Wed, 6 Jan 2016 19:47:22 +0100 -Subject: [PATCH] Upgrade: Fix upgrade of NIS Server configuration - -Former upgrade file always created the NIS Server container, that caused -the ipa-nis-manage did not set all required NIS maps. Default creation -of container has been removed. - -Updating of NIS Server configuration and -NIS maps is done only if the NIS Server container exists. - -https://fedorahosted.org/freeipa/ticket/5507 - -Reviewed-By: Alexander Bokovoy ---- - install/share/Makefile.am | 1 + - install/share/nis-update.uldif | 38 +++++++++++++++ - install/updates/50-nis.update | 58 ++-------------------- - ipaplatform/base/paths.py | 1 + - ipaserver/install/plugins/update_nis.py | 86 +++++++++++++++++++++++++++++++++ - 5 files changed, 129 insertions(+), 55 deletions(-) - create mode 100644 install/share/nis-update.uldif - create mode 100644 ipaserver/install/plugins/update_nis.py - -diff --git a/install/share/Makefile.am b/install/share/Makefile.am -index e4cca8708ab0042d6cb37eba31341e53e3cdac4d..09a341ce177e16e14e7d606e5628e6ca21ddf872 100644 ---- a/install/share/Makefile.am -+++ b/install/share/Makefile.am -@@ -60,6 +60,7 @@ app_DATA = \ - memberof-task.ldif \ - memberof-conf.ldif \ - nis.uldif \ -+ nis-update.uldif \ - opendnssec_conf.template \ - opendnssec_kasp.template \ - unique-attributes.ldif \ -diff --git a/install/share/nis-update.uldif b/install/share/nis-update.uldif -new file mode 100644 -index 0000000000000000000000000000000000000000..e602c1de061fbcece349b2d86970c4db5051473b ---- /dev/null -+++ b/install/share/nis-update.uldif -@@ -0,0 +1,38 @@ -+# Updates for NIS -+ -+# Correct syntax error that caused users to not appear -+dn: nis-domain=$DOMAIN+nis-map=netgroup, cn=NIS Server, cn=plugins, cn=config -+replace:nis-value-format: %merge(" ","%{memberNisNetgroup}","(%link(\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%{externalHost}\\\\\\\",\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\",\",\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\"%deref(\\\\\\\"memberUser\\\\\\\",\\\\\\\"uid\\\\\\\")\\\",\\\"%deref_r(\\\\\\\"member\\\\\\\",\\\\\\\"uid\\\\\\\")\\\",\\\"%deref_r(\\\\\\\"memberUser\\\\\\\",\\\\\\\"member\\\\\\\",\\\\\\\"uid\\\\\\\")\\\")\\\")\",\"-\"),%{nisDomainName:-})")::%merge(" ","%{memberNisNetgroup}","(%link(\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%{externalHost}\\\\\\\",\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\",\",\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\"),%{nisDomainName:-})") -+ -+# Correct syntax error that caused nested netgroups to not work -+# https://bugzilla.redhat.com/show_bug.cgi?id=788625 -+dn: nis-domain=$DOMAIN+nis-map=netgroup, cn=NIS Server, cn=plugins, cn=config -+replace:nis-value-format: %merge(" ","%{memberNisNetgroup}","(%link(\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%{externalHost}\\\\\\\",\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\",\",\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\"),%{nisDomainName:-})")::%merge(" ","%deref_f(\"member\",\"(objectclass=ipanisNetgroup)\",\"cn\")","(%link(\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%{externalHost}\\\\\\\",\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\",\",\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\"),%{nisDomainName:-})") -+ -+# Make the padding an expression so usercat and hostcat always gets -+# evaluated when displaying entries. -+# https://bugzilla.redhat.com/show_bug.cgi?id=767372 -+dn: nis-domain=$DOMAIN+nis-map=netgroup, cn=NIS Server, cn=plugins, cn=config -+replace:nis-value-format: %merge(" ","%deref_f(\"member\",\"(objectclass=ipanisNetgroup)\",\"cn\")","(%link(\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%{externalHost}\\\\\\\",\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\",\",\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\"),%{nisDomainName:-})")::%merge(" ","%deref_f(\"member\",\"(objectclass=ipanisNetgroup)\",\"cn\")","(%link(\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%{externalHost}\\\\\\\",\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"-\\\")\",\",\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"-\\\")\"),%{nisDomainName:-})") -+ -+dn: nis-domain=$DOMAIN+nis-map=ethers.byaddr, cn=NIS Server, cn=plugins, cn=config -+default:objectclass: top -+default:objectclass: extensibleObject -+default:nis-domain: $DOMAIN -+default:nis-map: ethers.byaddr -+default:nis-base: cn=computers, cn=accounts, $SUFFIX -+default:nis-filter: (&(macAddress=*)(fqdn=*)(objectClass=ipaHost)) -+default:nis-keys-format: %mregsub("%{macAddress} %{fqdn}","(..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..) (.*)","%1:%2:%3:%4:%5:%6") -+default:nis-values-format: %mregsub("%{macAddress} %{fqdn}","(..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..) (.*)","%1:%2:%3:%4:%5:%6 %7") -+default:nis-secure: no -+ -+dn: nis-domain=$DOMAIN+nis-map=ethers.byname, cn=NIS Server, cn=plugins, cn=config -+default:objectclass: top -+default:objectclass: extensibleObject -+default:nis-domain: $DOMAIN -+default:nis-map: ethers.byname -+default:nis-base: cn=computers, cn=accounts, $SUFFIX -+default:nis-filter: (&(macAddress=*)(fqdn=*)(objectClass=ipaHost)) -+default:nis-keys-format: %mregsub("%{macAddress} %{fqdn}","(..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..) (.*)","%7") -+default:nis-values-format: %mregsub("%{macAddress} %{fqdn}","(..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..) (.*)","%1:%2:%3:%4:%5:%6 %7") -+default:nis-secure: no -diff --git a/install/updates/50-nis.update b/install/updates/50-nis.update -index 149889ec7bdb38073eb6df88628792526cfe58e6..05a166f003aefc50fc25f10f01f7364d752425bc 100644 ---- a/install/updates/50-nis.update -+++ b/install/updates/50-nis.update -@@ -1,55 +1,3 @@ --# NIS Server plugin must be disabled by default --# command 'ipa-nis-manage enable' enables NIS server --dn: cn=NIS Server,cn=plugins,cn=config --default:objectclass: top --default:objectclass: nsSlapdPlugin --default:objectclass: extensibleObject --default:cn: NIS Server --default:nsslapd-pluginpath: /usr/lib$LIBARCH/dirsrv/plugins/nisserver-plugin.so --default:nsslapd-plugininitfunc: nis_plugin_init --default:nsslapd-plugintype: object --default:nsslapd-pluginbetxn: on --default:nsslapd-pluginenabled: off --default:nsslapd-pluginid: nis-server --default:nsslapd-pluginversion: 0.10 --default:nsslapd-pluginvendor: redhat.com --default:nsslapd-plugindescription: NIS Server Plugin --default:nis-tcp-wrappers-name: nis-server -- --# Correct syntax error that caused users to not appear --dn: nis-domain=$DOMAIN+nis-map=netgroup, cn=NIS Server, cn=plugins, cn=config --replace:nis-value-format: %merge(" ","%{memberNisNetgroup}","(%link(\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%{externalHost}\\\\\\\",\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\",\",\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\"%deref(\\\\\\\"memberUser\\\\\\\",\\\\\\\"uid\\\\\\\")\\\",\\\"%deref_r(\\\\\\\"member\\\\\\\",\\\\\\\"uid\\\\\\\")\\\",\\\"%deref_r(\\\\\\\"memberUser\\\\\\\",\\\\\\\"member\\\\\\\",\\\\\\\"uid\\\\\\\")\\\")\\\")\",\"-\"),%{nisDomainName:-})")::%merge(" ","%{memberNisNetgroup}","(%link(\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%{externalHost}\\\\\\\",\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\",\",\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\"),%{nisDomainName:-})") -- --# Correct syntax error that caused nested netgroups to not work --# https://bugzilla.redhat.com/show_bug.cgi?id=788625 --dn: nis-domain=$DOMAIN+nis-map=netgroup, cn=NIS Server, cn=plugins, cn=config --replace:nis-value-format: %merge(" ","%{memberNisNetgroup}","(%link(\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%{externalHost}\\\\\\\",\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\",\",\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\"),%{nisDomainName:-})")::%merge(" ","%deref_f(\"member\",\"(objectclass=ipanisNetgroup)\",\"cn\")","(%link(\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%{externalHost}\\\\\\\",\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\",\",\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\"),%{nisDomainName:-})") -- --# Make the padding an expression so usercat and hostcat always gets --# evaluated when displaying entries. --# https://bugzilla.redhat.com/show_bug.cgi?id=767372 --dn: nis-domain=$DOMAIN+nis-map=netgroup, cn=NIS Server, cn=plugins, cn=config --replace:nis-value-format: %merge(" ","%deref_f(\"member\",\"(objectclass=ipanisNetgroup)\",\"cn\")","(%link(\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%{externalHost}\\\\\\\",\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\",\",\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"-\"),%{nisDomainName:-})")::%merge(" ","%deref_f(\"member\",\"(objectclass=ipanisNetgroup)\",\"cn\")","(%link(\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%{externalHost}\\\\\\\",\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberHost\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"fqdn\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"%ifeq(\\\"hostCategory\\\",\\\"all\\\",\\\"\\\",\\\"-\\\")\",\",\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"%collect(\\\\\\\"%deref(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\",\\\\\\\"%deref_r(\\\\\\\\\\\\\\\"memberUser\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"member\\\\\\\\\\\\\\\",\\\\\\\\\\\\\\\"uid\\\\\\\\\\\\\\\")\\\\\\\")\\\")\",\"%ifeq(\\\"userCategory\\\",\\\"all\\\",\\\"\\\",\\\"-\\\")\"),%{nisDomainName:-})") -- --dn: nis-domain=$DOMAIN+nis-map=ethers.byaddr, cn=NIS Server, cn=plugins, cn=config --default:objectclass: top --default:objectclass: extensibleObject --default:nis-domain: $DOMAIN --default:nis-map: ethers.byaddr --default:nis-base: cn=computers, cn=accounts, $SUFFIX --default:nis-filter: (&(macAddress=*)(fqdn=*)(objectClass=ipaHost)) --default:nis-keys-format: %mregsub("%{macAddress} %{fqdn}","(..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..) (.*)","%1:%2:%3:%4:%5:%6") --default:nis-values-format: %mregsub("%{macAddress} %{fqdn}","(..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..) (.*)","%1:%2:%3:%4:%5:%6 %7") --default:nis-secure: no -- --dn: nis-domain=$DOMAIN+nis-map=ethers.byname, cn=NIS Server, cn=plugins, cn=config --default:objectclass: top --default:objectclass: extensibleObject --default:nis-domain: $DOMAIN --default:nis-map: ethers.byname --default:nis-base: cn=computers, cn=accounts, $SUFFIX --default:nis-filter: (&(macAddress=*)(fqdn=*)(objectClass=ipaHost)) --default:nis-keys-format: %mregsub("%{macAddress} %{fqdn}","(..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..) (.*)","%7") --default:nis-values-format: %mregsub("%{macAddress} %{fqdn}","(..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..)[:\\\|-](..) (.*)","%1:%2:%3:%4:%5:%6 %7") --default:nis-secure: no -- -+# Updates are applied only if NIS plugin has been configured -+# update definitions are located in install/share/nis-update.uldif -+plugin: update_nis_configuration -diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py -index 215caf90ea1ca4e5db8f43f8f09002ce5d5cd280..12eb50bb2edd1680313c1e23c7ec83ede9fbd70c 100644 ---- a/ipaplatform/base/paths.py -+++ b/ipaplatform/base/paths.py -@@ -247,6 +247,7 @@ class BasePathNamespace(object): - HTML_KRBREALM_CON = "/usr/share/ipa/html/krbrealm.con" - PREFERENCES_HTML = "/usr/share/ipa/html/preferences.html" - NIS_ULDIF = "/usr/share/ipa/nis.uldif" -+ NIS_UPDATE_ULDIF = "/usr/share/ipa/nis-update.uldif" - IPA_PLUGINS = "/usr/share/ipa/plugins" - SCHEMA_COMPAT_ULDIF = "/usr/share/ipa/schema_compat.uldif" - IPA_JS_PLUGINS_DIR = "/usr/share/ipa/ui/js/plugins" -diff --git a/ipaserver/install/plugins/update_nis.py b/ipaserver/install/plugins/update_nis.py -new file mode 100644 -index 0000000000000000000000000000000000000000..6e12fed8c26cd3b12052700f4d4be5734121fc64 ---- /dev/null -+++ b/ipaserver/install/plugins/update_nis.py -@@ -0,0 +1,86 @@ -+# -+# Copyright (C) 2015 FreeIPA Contributors see COPYING for license -+# -+ -+from ipalib.plugable import Registry -+from ipalib import errors -+from ipalib import Updater -+from ipaplatform.paths import paths -+from ipapython.dn import DN -+from ipaserver.install import sysupgrade -+from ipaserver.install.ldapupdate import LDAPUpdate -+ -+register = Registry() -+ -+ -+@register() -+class update_nis_configuration(Updater): -+ """Update NIS configuration -+ -+ NIS configuration can be updated only if NIS Server was configured via -+ ipa-nis-manage command. -+ """ -+ -+ def __recover_from_missing_maps(self, ldap): -+ # https://fedorahosted.org/freeipa/ticket/5507 -+ # if all following DNs are missing, but 'NIS Server' container exists -+ # we are experiencig bug and maps should be fixed -+ -+ if sysupgrade.get_upgrade_state('nis', -+ 'done_recover_from_missing_maps'): -+ # this recover must be done only once, a user may deleted some -+ # maps, we do not want to restore them again -+ return -+ -+ self.log.debug("Recovering from missing NIS maps bug") -+ -+ suffix = "cn=NIS Server,cn=plugins,cn=config" -+ domain = self.api.env.domain -+ missing_dn_list = [ -+ DN(nis_map.format(domain=domain, suffix=suffix)) for nis_map in [ -+ "nis-domain={domain}+nis-map=passwd.byname,{suffix}", -+ "nis-domain={domain}+nis-map=passwd.byuid,{suffix}", -+ "nis-domain={domain}+nis-map=group.byname,{suffix}", -+ "nis-domain={domain}+nis-map=group.bygid,{suffix}", -+ "nis-domain={domain}+nis-map=netid.byname,{suffix}", -+ "nis-domain={domain}+nis-map=netgroup,{suffix}", -+ ] -+ ] -+ -+ for dn in missing_dn_list: -+ try: -+ ldap.get_entry(dn, attrs_list=['cn']) -+ except errors.NotFound: -+ pass -+ else: -+ # bug is not effective, at least one of 'possible missing' -+ # maps was detected -+ return -+ -+ sysupgrade.set_upgrade_state('nis', 'done_recover_from_missing_maps', -+ True) -+ -+ # bug is effective run update to recreate missing maps -+ ld = LDAPUpdate(sub_dict={}, ldapi=True) -+ ld.update([paths.NIS_ULDIF]) -+ -+ def execute(self, **options): -+ ldap = self.api.Backend.ldap2 -+ dn = DN(('cn', 'NIS Server'), ('cn', 'plugins'), ('cn', 'config')) -+ try: -+ ldap.get_entry(dn, attrs_list=['cn']) -+ except errors.NotFound: -+ # NIS is not configured on system, do not execute update -+ self.log.debug("Skipping NIS update, NIS Server is not configured") -+ -+ # container does not exist, bug #5507 is not effective -+ sysupgrade.set_upgrade_state( -+ 'nis', 'done_recover_from_missing_maps', True) -+ else: -+ self.__recover_from_missing_maps(ldap) -+ -+ self.log.debug("Executing NIS Server update") -+ ld = LDAPUpdate(sub_dict={}, ldapi=True) -+ ld.update([paths.NIS_UPDATE_ULDIF]) -+ -+ return False, () --- -2.4.3 - diff --git a/SOURCES/0178-use-FFI-call-to-rpmvercmp-function-for-version-compa.patch b/SOURCES/0178-use-FFI-call-to-rpmvercmp-function-for-version-compa.patch deleted file mode 100644 index efe0431..0000000 --- a/SOURCES/0178-use-FFI-call-to-rpmvercmp-function-for-version-compa.patch +++ /dev/null @@ -1,112 +0,0 @@ -From fcdfeb962a0643dca7f2e1a32f0a5e9f8ff5595d Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Mon, 11 Jan 2016 16:22:40 +0100 -Subject: [PATCH] use FFI call to rpmvercmp function for version comparison - -Stop using rpm-python to compare package versions since the implicit NSS -initialization upon the module import breaks NSS handling in IPA code. Call -rpm-libs C-API function via CFFI instead. - -Big thanks to Martin Kosek for sharing the code snippet -that spurred this patch. - -https://fedorahosted.org/freeipa/ticket/5572 - -Reviewed-By: Jan Cholasta ---- - freeipa.spec.in | 2 +- - ipaplatform/redhat/tasks.py | 44 ++++++++++++-------------------------------- - 2 files changed, 13 insertions(+), 33 deletions(-) - -diff --git a/freeipa.spec.in b/freeipa.spec.in -index 01d42bc621c83541af7517d6d91eb37fd5b5c5cc..cd26d4ce66e320f8b8bf6aaa3e738b4c11f89aa9 100644 ---- a/freeipa.spec.in -+++ b/freeipa.spec.in -@@ -159,7 +159,7 @@ Requires: p11-kit - Requires: systemd-python - Requires: %{etc_systemd_dir} - Requires: gzip --Requires: rpm-python -+Requires: rpm-libs - - Conflicts: %{alt_name}-server - Obsoletes: %{alt_name}-server < %{version} -diff --git a/ipaplatform/redhat/tasks.py b/ipaplatform/redhat/tasks.py -index 2e894d776dcd5542e6c11cc0210add8ad9d90298..9be3ef664e6d15c31e53b7a8123de7b6bb2b81fe 100644 ---- a/ipaplatform/redhat/tasks.py -+++ b/ipaplatform/redhat/tasks.py -@@ -30,7 +30,8 @@ import socket - import sys - import urllib - import base64 --import rpm -+from cffi import FFI -+from ctypes.util import find_library - from functools import total_ordering - - from subprocess import CalledProcessError -@@ -47,35 +48,14 @@ from ipaplatform.paths import paths - from ipaplatform.redhat.authconfig import RedHatAuthConfig - from ipaplatform.base.tasks import BaseTaskNamespace - -+_ffi = FFI() -+_ffi.cdef(""" -+int rpmvercmp (const char *a, const char *b); -+""") - --# copied from rpmUtils/miscutils.py --def stringToVersion(verstring): -- if verstring in [None, '']: -- return (None, None, None) -- i = verstring.find(':') -- if i != -1: -- try: -- epoch = str(long(verstring[:i])) -- except ValueError: -- # look, garbage in the epoch field, how fun, kill it -- epoch = '0' # this is our fallback, deal -- else: -- epoch = '0' -- j = verstring.find('-') -- if j != -1: -- if verstring[i + 1:j] == '': -- version = None -- else: -- version = verstring[i + 1:j] -- release = verstring[j + 1:] -- else: -- if verstring[i + 1:] == '': -- version = None -- else: -- version = verstring[i + 1:] -- release = None -- return (epoch, version, release) -- -+# use ctypes loader to get correct librpm.so library version according to -+# https://cffi.readthedocs.org/en/latest/overview.html#id8 -+_librpm = _ffi.dlopen(find_library("rpm")) - - log = log_mgr.get_logger(__name__) - -@@ -100,15 +80,15 @@ def selinux_enabled(): - class IPAVersion(object): - - def __init__(self, version): -- self.version_tuple = stringToVersion(version) -+ self.version = version - - def __eq__(self, other): - assert isinstance(other, IPAVersion) -- return rpm.labelCompare(self.version_tuple, other.version_tuple) == 0 -+ return _librpm.rpmvercmp(self.version, other.version) == 0 - - def __lt__(self, other): - assert isinstance(other, IPAVersion) -- return rpm.labelCompare(self.version_tuple, other.version_tuple) == -1 -+ return _librpm.rpmvercmp(self.version, other.version) < 0 - - - class RedHatTaskNamespace(BaseTaskNamespace): --- -2.4.3 - diff --git a/SOURCES/0179-ipalib-assume-version-2.0-when-skip_version_check-is.patch b/SOURCES/0179-ipalib-assume-version-2.0-when-skip_version_check-is.patch deleted file mode 100644 index 1563374..0000000 --- a/SOURCES/0179-ipalib-assume-version-2.0-when-skip_version_check-is.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 88c057bc798b2606bafbed5c0b76475b0640b5e8 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Tue, 12 Jan 2016 15:41:43 +0100 -Subject: [PATCH] ipalib: assume version 2.0 when skip_version_check is enabled - -https://fedorahosted.org/freeipa/ticket/5601 - -Reviewed-By: Martin Basti ---- - ipalib/frontend.py | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - -diff --git a/ipalib/frontend.py b/ipalib/frontend.py -index 2ca3aaea82ea63702052eedbd7e4081f239cbaed..8adcee925a24fd546d7000e9239353da273e0bc9 100644 ---- a/ipalib/frontend.py -+++ b/ipalib/frontend.py -@@ -26,7 +26,6 @@ from distutils import version - - from ipapython.version import API_VERSION - from ipapython.ipa_log_manager import root_logger --from ipalib.capabilities import VERSION_WITHOUT_CAPABILITIES - from base import NameSpace - from plugable import Plugin - from parameters import create_param, Param, Str, Flag, Password -@@ -425,7 +424,7 @@ class Command(HasParam): - if version_provided: - self.verify_client_version(unicode(options['version'])) - elif self.api.env.skip_version_check and not self.api.env.in_server: -- options['version'] = VERSION_WITHOUT_CAPABILITIES -+ options['version'] = u'2.0' - else: - options['version'] = API_VERSION - params = self.args_options_2_params(*args, **options) --- -2.4.3 - diff --git a/SOURCES/0180-always-start-certmonger-during-IPA-server-configurat.patch b/SOURCES/0180-always-start-certmonger-during-IPA-server-configurat.patch deleted file mode 100644 index b53e599..0000000 --- a/SOURCES/0180-always-start-certmonger-during-IPA-server-configurat.patch +++ /dev/null @@ -1,87 +0,0 @@ -From 80115a38d78db0c2a31dea06786af41eafb234f0 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Mon, 1 Feb 2016 12:59:04 +0100 -Subject: [PATCH] always start certmonger during IPA server configuration - upgrade - -This patch fixes a regression introduced by commit -bef0f4c5c38e7ff6415e8f8c96dc306ef7f0ce56. Instead of checking whether -there is CA installed in the topology, we should always start certmonger -service during upgrade regardless when CA was configured. - -https://fedorahosted.org/freeipa/ticket/5655 - -Reviewed-By: Jan Cholasta -Reviewed-By: Martin Basti ---- - ipaserver/install/server/upgrade.py | 33 +++++---------------------------- - 1 file changed, 5 insertions(+), 28 deletions(-) - -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index 616fba5c1a5b3737481aecbb09ab5344641a3b04..1f1cfeb672809c0298c69c121ac38d6c7a482d11 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -292,24 +292,6 @@ def setup_firefox_extension(fstore): - http.setup_firefox_extension(realm, domain) - - --def is_ca_enabled(): -- """ -- check whether there is an active CA master -- :return: True if there is an active CA in topology, False otherwise -- """ -- ldap2 = api.Backend.ldap2 -- was_connected = ldap2.isconnected() -- -- if not was_connected: -- ldap2.connect() -- -- try: -- return api.Command.ca_is_enabled()['result'] -- finally: -- if not was_connected: -- ldap2.disconnect() -- -- - def ca_configure_profiles_acl(ca): - root_logger.info('[Authorizing RA Agent to modify profiles]') - -@@ -1420,6 +1402,10 @@ def upgrade_configuration(): - ) - upgrade_pki(ca, fstore) - -+ certmonger_service = services.knownservices.certmonger -+ if ca.is_configured() and not certmonger_service.is_running(): -+ certmonger_service.start() -+ - ca.configure_certmonger_renewal_guard() - - update_dbmodules(api.env.realm) -@@ -1435,8 +1421,7 @@ def upgrade_configuration(): - http.configure_selinux_for_httpd() - http.change_mod_nss_port_from_http() - -- if is_ca_enabled(): -- http.configure_certmonger_renewal_guard() -+ http.configure_certmonger_renewal_guard() - - ds.configure_dirsrv_ccache() - -@@ -1582,14 +1567,6 @@ def upgrade_check(options): - print unicode(e) - sys.exit(1) - -- try: -- ca_is_enabled = is_ca_enabled() -- except Exception as e: -- raise RuntimeError("Cannot connect to LDAP server: {0}".format(e)) -- -- if not services.knownservices.certmonger.is_running() and ca_is_enabled: -- raise RuntimeError('Certmonger is not running. Start certmonger and run upgrade again.') -- - if not options.skip_version_check: - # check IPA version and data version - try: --- -2.5.0 - diff --git a/SOURCES/0181-ipa-kdb-map_groups-consider-all-results.patch b/SOURCES/0181-ipa-kdb-map_groups-consider-all-results.patch deleted file mode 100644 index 2402c56..0000000 --- a/SOURCES/0181-ipa-kdb-map_groups-consider-all-results.patch +++ /dev/null @@ -1,145 +0,0 @@ -From d9d27cae99fe6f71daf250bfff71ee406fa3d23c Mon Sep 17 00:00:00 2001 -From: Sumit Bose -Date: Wed, 16 Dec 2015 12:38:16 +0100 -Subject: [PATCH] ipa-kdb: map_groups() consider all results - -Resolves https://fedorahosted.org/freeipa/ticket/5573 - -Reviewed-By: Jakub Hrozek -Reviewed-By: Alexander Bokovoy ---- - daemons/ipa-kdb/ipa_kdb_mspac.c | 108 +++++++++++++++++++++------------------- - 1 file changed, 56 insertions(+), 52 deletions(-) - -diff --git a/daemons/ipa-kdb/ipa_kdb_mspac.c b/daemons/ipa-kdb/ipa_kdb_mspac.c -index 3c0dca839314273ae309b3b65ec7cf103e9c6da7..de40a145210c36ea0d35e0cc491fe9d3d76efea0 100644 ---- a/daemons/ipa-kdb/ipa_kdb_mspac.c -+++ b/daemons/ipa-kdb/ipa_kdb_mspac.c -@@ -1082,68 +1082,72 @@ static int map_groups(TALLOC_CTX *memctx, krb5_context kcontext, - continue; - } - -- ldap_derefresponse_free(deref_results); -- ret = ipadb_ldap_deref_results(ipactx->lcontext, lentry, &deref_results); -- switch (ret) { -- case ENOENT: -- /* No entry found, try next SID */ -- break; -- case 0: -- if (deref_results == NULL) { -- krb5_klog_syslog(LOG_ERR, "No results."); -+ do { -+ ldap_derefresponse_free(deref_results); -+ ret = ipadb_ldap_deref_results(ipactx->lcontext, lentry, &deref_results); -+ switch (ret) { -+ case ENOENT: -+ /* No entry found, try next SID */ - break; -- } -+ case 0: -+ if (deref_results == NULL) { -+ krb5_klog_syslog(LOG_ERR, "No results."); -+ break; -+ } - -- for (dres = deref_results; dres; dres = dres->next) { -- count++; -- } -+ for (dres = deref_results; dres; dres = dres->next) { -+ count++; -+ } - -- sids = talloc_realloc(memctx, sids, struct dom_sid, count); -- if (sids == NULL) { -- krb5_klog_syslog(LOG_ERR, "talloc_realloc failed."); -- kerr = ENOMEM; -- goto done; -- } -+ sids = talloc_realloc(memctx, sids, struct dom_sid, count); -+ if (sids == NULL) { -+ krb5_klog_syslog(LOG_ERR, "talloc_realloc failed."); -+ kerr = ENOMEM; -+ goto done; -+ } - -- for (dres = deref_results; dres; dres = dres->next) { -- gid = 0; -- memset(&sid, '\0', sizeof(struct dom_sid)); -- for (dval = dres->attrVals; dval; dval = dval->next) { -- if (strcasecmp(dval->type, "gidNumber") == 0) { -- errno = 0; -- gid = strtoul((char *)dval->vals[0].bv_val, -- &endptr,10); -- if (gid == 0 || gid >= UINT32_MAX || errno != 0 || -- *endptr != '\0') { -- continue; -+ for (dres = deref_results; dres; dres = dres->next) { -+ gid = 0; -+ memset(&sid, '\0', sizeof(struct dom_sid)); -+ for (dval = dres->attrVals; dval; dval = dval->next) { -+ if (strcasecmp(dval->type, "gidNumber") == 0) { -+ errno = 0; -+ gid = strtoul((char *)dval->vals[0].bv_val, -+ &endptr,10); -+ if (gid == 0 || gid >= UINT32_MAX || errno != 0 || -+ *endptr != '\0') { -+ continue; -+ } - } -- } -- if (strcasecmp(dval->type, -- "ipaNTSecurityIdentifier") == 0) { -- kerr = string_to_sid((char *)dval->vals[0].bv_val, &sid); -- if (kerr != 0) { -- continue; -+ if (strcasecmp(dval->type, -+ "ipaNTSecurityIdentifier") == 0) { -+ kerr = string_to_sid((char *)dval->vals[0].bv_val, &sid); -+ if (kerr != 0) { -+ continue; -+ } - } - } -- } -- if (gid != 0 && sid.sid_rev_num != 0) { -- /* TODO: check if gid maps to sid */ -- if (sid_index >= count) { -- krb5_klog_syslog(LOG_ERR, "Index larger than " -- "array, this shoould " -- "never happen."); -- kerr = EFAULT; -- goto done; -+ if (gid != 0 && sid.sid_rev_num != 0) { -+ /* TODO: check if gid maps to sid */ -+ if (sid_index >= count) { -+ krb5_klog_syslog(LOG_ERR, "Index larger than " -+ "array, this shoould " -+ "never happen."); -+ kerr = EFAULT; -+ goto done; -+ } -+ memcpy(&sids[sid_index], &sid, sizeof(struct dom_sid)); -+ sid_index++; - } -- memcpy(&sids[sid_index], &sid, sizeof(struct dom_sid)); -- sid_index++; - } -- } - -- break; -- default: -- goto done; -- } -+ break; -+ default: -+ goto done; -+ } -+ -+ lentry = ldap_next_entry(ipactx->lcontext, lentry); -+ } while (lentry != NULL); - } - - *_ipa_group_sids_count = sid_index; --- -2.7.1 - diff --git a/SOURCES/0182-ipa-ca-install-print-more-specific-errors-when-CA-is.patch b/SOURCES/0182-ipa-ca-install-print-more-specific-errors-when-CA-is.patch deleted file mode 100644 index 9941c4a..0000000 --- a/SOURCES/0182-ipa-ca-install-print-more-specific-errors-when-CA-is.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 3d13e08deee3586635e583c1d5ac8c722530ac2f Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Wed, 15 Jul 2015 14:15:49 +0200 -Subject: [PATCH] ipa-ca-install: print more specific errors when CA is already - installed - -This patch implements a more thorough checking for already installed CAs -during standalone CA installation using ipa-ca-install. The installer now -differentiates between CA that is already installed locally and CA installed -on one or more masters in topology and prints an appropriate error message. - -https://fedorahosted.org/freeipa/ticket/4492 - -Reviewed-By: Martin Basti ---- - ipaserver/install/ca.py | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py -index 0de992cb0c15f8161aae4937699baae2a94d305a..84cbf423246534259cd6b7a8cca25caa16e5594f 100644 ---- a/ipaserver/install/ca.py -+++ b/ipaserver/install/ca.py -@@ -45,8 +45,16 @@ def install_check(standalone, replica_config, options): - - return - -- if standalone and api.Command.ca_is_enabled()['result']: -- sys.exit("CA is already installed.\n") -+ if standalone: -+ if cainstance.is_ca_installed_locally(): -+ sys.exit("CA is already installed on this host.") -+ elif api.Command.ca_is_enabled()['result']: -+ sys.exit( -+ "One or more CA masters are already present in IPA realm " -+ "'%s'.\nIf you wish to replicate CA to this host, please " -+ "re-run 'ipa-ca-install'\nwith a replica file generated on " -+ "an existing CA master as argument." % realm_name -+ ) - - if options.external_cert_files: - if not cainstance.is_step_one_done(): --- -2.5.0 - diff --git a/SOURCES/0183-installer-Propagate-option-values-from-components-in.patch b/SOURCES/0183-installer-Propagate-option-values-from-components-in.patch deleted file mode 100644 index 02b9eaf..0000000 --- a/SOURCES/0183-installer-Propagate-option-values-from-components-in.patch +++ /dev/null @@ -1,132 +0,0 @@ -From 95447911535974731a931b1d758f6cfd985c1e59 Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Wed, 16 Dec 2015 12:43:13 +0000 -Subject: [PATCH] installer: Propagate option values from components instead of - copying them. - -https://fedorahosted.org/freeipa/ticket/5556 - -Reviewed-By: Jan Cholasta ---- - ipapython/install/core.py | 21 ++++++++++++++++++--- - ipaserver/install/server/install.py | 25 ------------------------- - ipaserver/install/server/replicainstall.py | 12 +----------- - 3 files changed, 19 insertions(+), 39 deletions(-) - -diff --git a/ipapython/install/core.py b/ipapython/install/core.py -index 91ae854cdb2a8846e2a2673a5bfe54b4f75f3823..3bb13267326b8cf1f22bb34dcf1e03402479446e 100644 ---- a/ipapython/install/core.py -+++ b/ipapython/install/core.py -@@ -484,6 +484,21 @@ class Composite(Configurable): - for comp_cls in result: - yield comp_cls.__outer_class__, comp_cls.__outer_name__ - -+ def __getattr__(self, name): -+ for owner_cls, knob_name in self.knobs(): -+ if knob_name == name: -+ break -+ else: -+ raise AttributeError(name) -+ -+ for component in self.__components: -+ if isinstance(component, owner_cls): -+ break -+ else: -+ raise AttributeError(name) -+ -+ return getattr(component, name) -+ - def _reset(self): - self.__components = list(self._get_components()) - -@@ -501,8 +516,7 @@ class Composite(Configurable): - try: - validator.next() - except StopIteration: -- if child.done(): -- self.__components.remove(child) -+ pass - else: - new_validate.append((child, validator)) - if not new_validate: -@@ -516,7 +530,8 @@ class Composite(Configurable): - - yield from_(super(Composite, self)._configure()) - -- execute = [(c, c._executor()) for c in self.__components] -+ execute = [(c, c._executor()) for c in self.__components -+ if not c.done()] - while True: - new_execute = [] - for child, executor in execute: -diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py -index 9d7036a7786a35e6aa2429254d62c8afb30970db..71992db0d39e1969649587486031a8fb1a03419d 100644 ---- a/ipaserver/install/server/install.py -+++ b/ipaserver/install/server/install.py -@@ -1592,35 +1592,10 @@ class Server(common.Installable, common.Interactive, core.Composite): - - self.setup_ca = False - self.setup_kra = False -- self.external_ca = self.ca.external_ca -- self.external_ca_type = self.ca.external_ca_type -- self.external_cert_files = self.ca.external_cert_files -- self.no_pkinit = self.ca.no_pkinit -- self.dirsrv_cert_files = self.ca.dirsrv_cert_files -- self.http_cert_files = self.ca.http_cert_files -- self.pkinit_cert_files = self.ca.pkinit_cert_files -- self.dirsrv_pin = self.ca.dirsrv_pin -- self.http_pin = self.ca.http_pin -- self.pkinit_pin = self.ca.pkinit_pin -- self.dirsrv_cert_name = self.ca.dirsrv_cert_name -- self.http_cert_name = self.ca.http_cert_name -- self.pkinit_cert_name = self.ca.pkinit_cert_name -- self.ca_cert_files = self.ca.ca_cert_files -- self.subject = self.ca.subject -- self.ca_signing_algorithm = self.ca.ca_signing_algorithm -- self.setup_dns = self.dns.setup_dns -- self.forwarders = self.dns.forwarders -- self.no_forwarders = self.dns.no_forwarders -- self.reverse_zones = self.dns.reverse_zones -- self.no_reverse = self.dns.no_reverse -- self.no_dnssec_validation = self.dns.no_dnssec_validation - self.dnssec_master = False - self.disable_dnssec_master = False - self.kasp_db_file = None - self.force = False -- self.zonemgr = self.dns.zonemgr -- self.no_host_dns = self.dns.no_host_dns -- self.no_dns_sshfp = self.dns.no_dns_sshfp - - self.unattended = not self.interactive - -diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py -index 6e9157cabc49161ba27983cbf1de1428d1b48b7d..a5d4a77f3daa8110ad0be064085b12b20da853cf 100644 ---- a/ipaserver/install/server/replicainstall.py -+++ b/ipaserver/install/server/replicainstall.py -@@ -847,22 +847,12 @@ class Replica(common.Installable, common.Interactive, core.Composite): - - self.external_ca = False - self.external_cert_files = None -- self.no_pkinit = self.ca.no_pkinit -- self.skip_schema_check = self.ca.skip_schema_check -- -- self.setup_dns = self.dns.setup_dns -- self.forwarders = self.dns.forwarders -- self.no_forwarders = self.dns.no_forwarders -- self.reverse_zones = self.dns.reverse_zones -- self.no_reverse = self.dns.no_reverse -- self.no_dnssec_validation = self.dns.no_dnssec_validation -+ - self.dnssec_master = False - self.disable_dnssec_master = False - self.kasp_db_file = None - self.force = False - self.zonemgr = None -- self.no_host_dns = self.dns.no_host_dns -- self.no_dns_sshfp = self.dns.no_dns_sshfp - - self.unattended = not self.interactive - --- -2.5.0 - diff --git a/SOURCES/0184-installer-Fix-logic-of-reading-option-values-from-ca.patch b/SOURCES/0184-installer-Fix-logic-of-reading-option-values-from-ca.patch deleted file mode 100644 index ef50523..0000000 --- a/SOURCES/0184-installer-Fix-logic-of-reading-option-values-from-ca.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 71809fb6071a86156f881e20d4845cbd47606862 Mon Sep 17 00:00:00 2001 -From: David Kupka -Date: Wed, 16 Dec 2015 12:45:24 +0000 -Subject: [PATCH] installer: Fix logic of reading option values from cache. - -Only options explicitly set must be stored before installer exits first step -of external CA setup. When installer continues all stored option values must -be restored. - -https://fedorahosted.org/freeipa/ticket/5556 - -Reviewed-By: Jan Cholasta ---- - ipaserver/install/server/install.py | 7 +++---- - 1 file changed, 3 insertions(+), 4 deletions(-) - -diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py -index 71992db0d39e1969649587486031a8fb1a03419d..01dffd08d4c929ebc5ecb6e6b0a8b685c1320dbd 100644 ---- a/ipaserver/install/server/install.py -+++ b/ipaserver/install/server/install.py -@@ -343,9 +343,7 @@ def install_check(installer): - sys.exit("Directory Manager password required") - try: - cache_vars = read_cache(dm_password) -- for name, value in cache_vars.iteritems(): -- if name not in options.__dict__: -- options.__dict__[name] = value -+ options.__dict__.update(cache_vars) - if cache_vars.get('external_ca', False): - options.external_ca = False - options.interactive = False -@@ -767,7 +765,8 @@ def install(installer): - options.host_name = host_name - options.forwarders = dns.dns_forwarders - options.reverse_zones = dns.reverse_zones -- cache_vars = {n: getattr(options, n) for o, n in installer.knobs()} -+ cache_vars = {n: options.__dict__[n] for o, n in installer.knobs() -+ if n in options.__dict__} - write_cache(cache_vars) - - ca.install_step_0(False, None, options) --- -2.5.0 - diff --git a/SOURCES/0185-Fixed-login-error-message-box-in-LoginScreen-page.patch b/SOURCES/0185-Fixed-login-error-message-box-in-LoginScreen-page.patch deleted file mode 100644 index d9aa1d0..0000000 --- a/SOURCES/0185-Fixed-login-error-message-box-in-LoginScreen-page.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 303e3aea45c310e8a2508ac540264520d5d3eda4 Mon Sep 17 00:00:00 2001 -From: Abhijeet Kasurde -Date: Mon, 28 Dec 2015 12:33:11 +0530 -Subject: [PATCH] Fixed login error message box in LoginScreen page - -Fix added for showing error message returned from server to client -browser. User is now notified with proper error messages returned by -server. - -https://bugzilla.redhat.com/show_bug.cgi?id=1293870 - -Signed-off-by: Abhijeet Kasurde -Reviewed-By: Petr Vobornik ---- - install/ui/src/freeipa/widgets/LoginScreen.js | 8 ++++---- - 1 file changed, 4 insertions(+), 4 deletions(-) - -diff --git a/install/ui/src/freeipa/widgets/LoginScreen.js b/install/ui/src/freeipa/widgets/LoginScreen.js -index eb95b9161f05eeac1ec9aed286c9730dada85d59..2c778b50cfb10bfa8eef25c5456c6ce913e02695 100644 ---- a/install/ui/src/freeipa/widgets/LoginScreen.js -+++ b/install/ui/src/freeipa/widgets/LoginScreen.js -@@ -272,12 +272,12 @@ define(['dojo/_base/declare', - } - this.set('view', 'login'); - } else { -+ otp_f.set_value(''); -+ new_f.set_value(''); -+ ver_f.set_value(''); - val_summary.add_error('login', result.message); - } - -- otp_f.set_value(''); -- new_f.set_value(''); -- ver_f.set_value(''); - }, - - refresh: function() { -@@ -426,4 +426,4 @@ define(['dojo/_base/declare', - ]; - - return LoginScreen; --}); -\ No newline at end of file -+}); --- -2.5.0 - diff --git a/SOURCES/0186-cert-renewal-import-all-external-CA-certs-on-IPA-CA-.patch b/SOURCES/0186-cert-renewal-import-all-external-CA-certs-on-IPA-CA-.patch deleted file mode 100644 index 3cebd4e..0000000 --- a/SOURCES/0186-cert-renewal-import-all-external-CA-certs-on-IPA-CA-.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 8d651ef5a00c418138c355aa95259246090705b7 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Thu, 21 Jan 2016 08:58:56 +0100 -Subject: [PATCH] cert renewal: import all external CA certs on IPA CA cert - renewal - -Import all external CA certs to the Dogtag NSS database on IPA CA cert -renewal. This fixes Dogtag not being able to connect to DS which uses 3rd -party server cert after ipa-certupdate. - -https://fedorahosted.org/freeipa/ticket/5595 - -Reviewed-By: Martin Babinsky ---- - install/restart_scripts/renew_ca_cert | 28 +++++++++------------------- - 1 file changed, 9 insertions(+), 19 deletions(-) - -diff --git a/install/restart_scripts/renew_ca_cert b/install/restart_scripts/renew_ca_cert -index 86f5765b7d8bbeafd5379831020a952a7aa6db41..92dc0e6685f61f34bd6df941ef63ac138ad7965b 100644 ---- a/install/restart_scripts/renew_ca_cert -+++ b/install/restart_scripts/renew_ca_cert -@@ -28,7 +28,6 @@ import shutil - import traceback - - from ipapython import dogtag, ipautil --from ipapython.dn import DN - from ipalib import api, errors, x509, certstore - from ipaserver.install import certs, cainstance, installutils - from ipaserver.plugins.ldap2 import ldap2 -@@ -158,11 +157,9 @@ def _main(): - "Updating CA certificate failed: %s" % e) - - # Add external CA certificates -- ca_issuer = str(x509.get_issuer(cert, x509.DER)) - try: -- ca_certs = certstore.get_ca_certs( -- conn, api.env.basedn, api.env.realm, False, -- filter_subject=ca_issuer) -+ ca_certs = certstore.get_ca_certs_nss( -+ conn, api.env.basedn, api.env.realm, False) - except Exception, e: - syslog.syslog( - syslog.LOG_ERR, -@@ -170,25 +167,18 @@ def _main(): - "%s" % e) - ca_certs = [] - -- for ca_cert, ca_nick, ca_trusted, ca_eku in ca_certs: -- ca_subject = DN(str(x509.get_subject(ca_cert, x509.DER))) -- nick_base = ' - '.join(rdn[-1].value for rdn in ca_subject) -- nick = nick_base -- i = 1 -- while db.has_nickname(nick): -- nick = '%s [%s]' % (nick_base, i) -- i += 1 -- if ca_trusted is False: -- flags = 'p,p,p' -- else: -- flags = 'CT,c,' -- -+ for ca_cert, ca_nick, ca_flags in ca_certs: - try: -- db.add_cert(ca_cert, nick, flags) -+ db.add_cert(ca_cert, ca_nick, ca_flags) - except ipautil.CalledProcessError, e: - syslog.syslog( - syslog.LOG_ERR, - "Failed to add certificate %s" % ca_nick) -+ -+ # Pass Dogtag's self-tests -+ for ca_nick in db.find_root_cert(nickname)[-2:-1]: -+ ca_flags = dict(cc[1:] for cc in ca_certs)[ca_nick] -+ db.trust_root_cert(ca_nick, 'C' + ca_flags) - finally: - if conn is not None and conn.isconnected(): - conn.disconnect() --- -2.5.0 - diff --git a/SOURCES/0187-CA-install-explicitly-set-dogtag_version-to-10.patch b/SOURCES/0187-CA-install-explicitly-set-dogtag_version-to-10.patch deleted file mode 100644 index 5d9d2ff..0000000 --- a/SOURCES/0187-CA-install-explicitly-set-dogtag_version-to-10.patch +++ /dev/null @@ -1,78 +0,0 @@ -From c7f76e4f6c0f288b184152f5f6f45d11287914b3 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Mon, 25 Jan 2016 08:48:42 +0100 -Subject: [PATCH] CA install: explicitly set dogtag_version to 10 - -When installing new CA master, explicitly set the dogtag_version option to -10 in api.bootstrap() to prevent failures in code which expects the value -to be 10 rather than the default value of 9. - -https://fedorahosted.org/freeipa/ticket/5611 - -Reviewed-By: Martin Babinsky ---- - install/tools/ipa-ca-install | 2 +- - ipaserver/install/cainstance.py | 6 +++--- - ipaserver/install/server/upgrade.py | 2 +- - 3 files changed, 5 insertions(+), 5 deletions(-) - -diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install -index 6564e4d0304d4e189b133c495b75f200b04e2988..e8ccaef5b90807f452f77c2b62641df3952180d6 100755 ---- a/install/tools/ipa-ca-install -+++ b/install/tools/ipa-ca-install -@@ -162,7 +162,7 @@ def install_master(safe_options, options): - - # override ra_plugin setting read from default.conf so that we have - # functional dogtag backend plugins during CA install -- api.bootstrap(in_server=True, ra_plugin='dogtag') -+ api.bootstrap(in_server=True, ra_plugin='dogtag', dogtag_version=10) - api.finalize() - - dm_password = options.password -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index d9bf4f31af5a922dd6f977a5011f50ce7cea8896..369902ad04b197c9e9516503c1f81c4de1ef153b 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -478,7 +478,7 @@ class CAInstance(DogtagInstance): - self.http_proxy) - self.step("restarting certificate server", self.restart_instance) - self.step("migrating certificate profiles to LDAP", -- migrate_profiles_to_ldap) -+ lambda: migrate_profiles_to_ldap(self.dogtag_constants)) - self.step("importing IPA certificate profiles", - import_included_profiles) - self.step("adding default CA ACL", ensure_default_caacl) -@@ -1768,7 +1768,7 @@ def import_included_profiles(): - conn.disconnect() - - --def migrate_profiles_to_ldap(): -+def migrate_profiles_to_ldap(dogtag_constants): - """Migrate profiles from filesystem to LDAP. - - This must be run *after* switching to the LDAPProfileSubsystem -@@ -1783,7 +1783,7 @@ def migrate_profiles_to_ldap(): - api.Backend.ra_certprofile._read_password() - api.Backend.ra_certprofile.override_port = 8443 - -- with open(dogtag.configured_constants().CS_CFG_PATH) as f: -+ with open(dogtag_constants.CS_CFG_PATH) as f: - cs_cfg = f.read() - match = re.search(r'^profile\.list=(\S*)', cs_cfg, re.MULTILINE) - profile_ids = match.group(1).split(',') -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index 1f1cfeb672809c0298c69c121ac38d6c7a482d11..0a46635979497f8028465c2295b22485fd9c0279 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -336,7 +336,7 @@ def ca_enable_ldap_profile_subsystem(ca): - separator='=') - - ca.restart(dogtag.configured_constants().PKI_INSTANCE_NAME) -- cainstance.migrate_profiles_to_ldap() -+ cainstance.migrate_profiles_to_ldap(caconfig) - - return needs_update - --- -2.5.0 - diff --git a/SOURCES/0188-fix-standalone-installation-of-externally-signed-CA-.patch b/SOURCES/0188-fix-standalone-installation-of-externally-signed-CA-.patch deleted file mode 100644 index cb659dc..0000000 --- a/SOURCES/0188-fix-standalone-installation-of-externally-signed-CA-.patch +++ /dev/null @@ -1,30 +0,0 @@ -From 06c2e339f28ab697c830dc1f9d6ef89b833b2d1a Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Tue, 26 Jan 2016 13:02:44 +0100 -Subject: [PATCH] fix standalone installation of externally signed CA on IPA - master - -https://fedorahosted.org/freeipa/ticket/5636 - -Reviewed-By: Martin Basti ---- - ipaserver/install/ca.py | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py -index 84cbf423246534259cd6b7a8cca25caa16e5594f..d2fb5feeaf96e8450eddb1bc4e65ef3316b05b38 100644 ---- a/ipaserver/install/ca.py -+++ b/ipaserver/install/ca.py -@@ -46,7 +46,8 @@ def install_check(standalone, replica_config, options): - return - - if standalone: -- if cainstance.is_ca_installed_locally(): -+ if (not options.external_cert_files and -+ cainstance.is_ca_installed_locally()): - sys.exit("CA is already installed on this host.") - elif api.Command.ca_is_enabled()['result']: - sys.exit( --- -2.5.0 - diff --git a/SOURCES/0189-replica-install-validate-DS-and-HTTP-server-certific.patch b/SOURCES/0189-replica-install-validate-DS-and-HTTP-server-certific.patch deleted file mode 100644 index 01f3b25..0000000 --- a/SOURCES/0189-replica-install-validate-DS-and-HTTP-server-certific.patch +++ /dev/null @@ -1,74 +0,0 @@ -From 8ee71c8aab262ba0041ee9ac84fb862a5fda32cf Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Thu, 21 Jan 2016 15:48:30 +0100 -Subject: [PATCH] replica install: validate DS and HTTP server certificates - -Validate the DS and HTTP certificates from the replica info file early in -ipa-replica-install to prevent crashes later. - -https://fedorahosted.org/freeipa/ticket/5598 - -Reviewed-By: Martin Babinsky ---- - ipaserver/install/server/replicainstall.py | 31 +++++++++++++++++++++++++++++- - 1 file changed, 30 insertions(+), 1 deletion(-) - -diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py -index a5d4a77f3daa8110ad0be064085b12b20da853cf..317eda92dd4322542f035c2df4dba919a5898cc7 100644 ---- a/ipaserver/install/server/replicainstall.py -+++ b/ipaserver/install/server/replicainstall.py -@@ -356,6 +356,8 @@ def install_check(installer): - config.setup_ca = options.setup_ca - config.setup_kra = options.setup_kra - -+ ca_enabled = ipautil.file_exists(config.dir + "/cacert.p12") -+ - # Create the management framework config file - # Note: We must do this before bootstraping and finalizing ipalib.api - old_umask = os.umask(022) # must be readable for httpd -@@ -371,7 +373,7 @@ def install_check(installer): - ipautil.format_netloc(config.host_name)) - fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % - installutils.realm_to_serverid(config.realm_name)) -- if ipautil.file_exists(config.dir + "/cacert.p12"): -+ if ca_enabled: - fd.write("enable_ra=True\n") - fd.write("ra_plugin=dogtag\n") - fd.write("dogtag_version=%s\n" % -@@ -395,6 +397,33 @@ def install_check(installer): - raise RuntimeError("CA cert file is not available. Please run " - "ipa-replica-prepare to create a new replica file.") - -+ for pkcs12_name, pin_name in (('dscert.p12', 'dirsrv_pin.txt'), -+ ('httpcert.p12', 'http_pin.txt')): -+ pkcs12_info = make_pkcs12_info(config.dir, pkcs12_name, pin_name) -+ tmp_db_dir = tempfile.mkdtemp('ipa') -+ try: -+ tmp_db = certs.CertDB(config.realm_name, -+ nssdir=tmp_db_dir, -+ subject_base=config.subject_base) -+ if ca_enabled: -+ trust_flags = 'CT,C,C' -+ else: -+ trust_flags = None -+ tmp_db.create_from_pkcs12(pkcs12_info[0], pkcs12_info[1], -+ ca_file=cafile, -+ trust_flags=trust_flags) -+ if not tmp_db.find_server_certs(): -+ raise RuntimeError( -+ "Could not find a suitable server cert in import in %s" % -+ pkcs12_info[0]) -+ except Exception as e: -+ root_logger.error('%s', e) -+ raise RuntimeError( -+ "Server cert is not valid. Please run ipa-replica-prepare to " -+ "create a new replica file.") -+ finally: -+ shutil.rmtree(tmp_db_dir) -+ - ldapuri = 'ldaps://%s' % ipautil.format_netloc(config.master_host_name) - remote_api = create_api(mode=None) - remote_api.bootstrap(in_server=True, context='installer', --- -2.5.0 - diff --git a/SOURCES/0190-Do-not-decode-HTTP-reason-phrase-from-Dogtag.patch b/SOURCES/0190-Do-not-decode-HTTP-reason-phrase-from-Dogtag.patch deleted file mode 100644 index 220c9ce..0000000 --- a/SOURCES/0190-Do-not-decode-HTTP-reason-phrase-from-Dogtag.patch +++ /dev/null @@ -1,294 +0,0 @@ -From ca08d7d3a7562588b09b78b7079b2c15e572a484 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Wed, 6 Jan 2016 14:50:42 +1100 -Subject: [PATCH] Do not decode HTTP reason phrase from Dogtag - -The HTTP reason phrase sent by Dogtag is assumed to be encoded in -UTF-8, but the encoding used by Tomcat is dependent on system -locale, causing decode errors in some locales. - -The reason phrase is optional and will not be sent in a future -version of Tomcat[1], so do not bother decoding and returning it. - -[1] https://github.com/apache/tomcat/commit/707ab1c77f3bc189e1c3f29b641506db4c8bce37 - -Fixes: https://fedorahosted.org/freeipa/ticket/5578 -Reviewed-By: Jan Cholasta ---- - ipapython/dogtag.py | 23 +++++++++++------------ - ipaserver/install/certs.py | 7 +++---- - ipaserver/plugins/dogtag.py | 44 ++++++++++++++++++++++---------------------- - 3 files changed, 36 insertions(+), 38 deletions(-) - -diff --git a/ipapython/dogtag.py b/ipapython/dogtag.py -index 8996902ba92f0fdd6106e2650c2decde375c593b..652bc3d13f2b47b35f6da30579f2df5f083dbff2 100644 ---- a/ipapython/dogtag.py -+++ b/ipapython/dogtag.py -@@ -230,14 +230,14 @@ def ca_status(ca_host=None, use_proxy=True): - ca_port = 443 - else: - ca_port = 8443 -- status, reason, headers, body = unauthenticated_https_request( -+ status, headers, body = unauthenticated_https_request( - ca_host, ca_port, '/ca/admin/ca/getStatus') - if status == 503: - # Service temporarily unavailable -- return reason -+ return status - elif status != 200: - raise errors.RemoteRetrieveError( -- reason=_("Retrieving CA status failed: %s") % reason) -+ reason=_("Retrieving CA status failed with status %d") % status) - return _parse_ca_status(body) - - -@@ -248,8 +248,8 @@ def https_request(host, port, url, secdir, password, nickname, - :param url: The path (not complete URL!) to post to. - :param body: The request body (encodes kw if None) - :param kw: Keyword arguments to encode into POST body. -- :return: (http_status, http_reason_phrase, http_headers, http_body) -- as (integer, unicode, dict, str) -+ :return: (http_status, http_headers, http_body) -+ as (integer, dict, str) - - Perform a client authenticated HTTPS request - """ -@@ -277,8 +277,8 @@ def http_request(host, port, url, **kw): - """ - :param url: The path (not complete URL!) to post to. - :param kw: Keyword arguments to encode into POST body. -- :return: (http_status, http_reason_phrase, http_headers, http_body) -- as (integer, unicode, dict, str) -+ :return: (http_status, http_headers, http_body) -+ as (integer, dict, str) - - Perform an HTTP request. - """ -@@ -291,8 +291,8 @@ def unauthenticated_https_request(host, port, url, **kw): - """ - :param url: The path (not complete URL!) to post to. - :param kw: Keyword arguments to encode into POST body. -- :return: (http_status, http_reason_phrase, http_headers, http_body) -- as (integer, unicode, dict, str) -+ :return: (http_status, http_headers, http_body) -+ as (integer, dict, str) - - Perform an unauthenticated HTTPS request. - """ -@@ -331,15 +331,14 @@ def _httplib_request( - res = conn.getresponse() - - http_status = res.status -- http_reason_phrase = unicode(res.reason, 'utf-8') - http_headers = res.msg.dict - http_body = res.read() - conn.close() - except Exception, e: - raise NetworkError(uri=uri, error=str(e)) - -- root_logger.debug('response status %d %s', http_status, http_reason_phrase) -+ root_logger.debug('response status %d', http_status) - root_logger.debug('response headers %s', http_headers) - root_logger.debug('response body %r', http_body) - -- return http_status, http_reason_phrase, http_headers, http_body -+ return http_status, http_headers, http_body -diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py -index 564332e6fde0698a23884922c5018fab59da7e4d..f8a9c9ecfd2fa1accb792c4748bc69f30701af6a 100644 ---- a/ipaserver/install/certs.py -+++ b/ipaserver/install/certs.py -@@ -402,12 +402,11 @@ class CertDB(object): - dogtag.configured_constants().EE_SECURE_PORT, - "/ca/ee/ca/profileSubmitSSLClient", - self.secdir, password, "ipaCert", **params) -- http_status, http_reason_phrase, http_headers, http_body = result -+ http_status, http_headers, http_body = result - - if http_status != 200: - raise CertificateOperationError( -- error=_('Unable to communicate with CMS (%s)') % -- http_reason_phrase) -+ error=_('Unable to communicate with CMS (status %d)') % http_status) - - # The result is an XML blob. Pull the certificate out of that - doc = xml.dom.minidom.parseString(http_body) -@@ -459,7 +458,7 @@ class CertDB(object): - dogtag.configured_constants().EE_SECURE_PORT, - "/ca/ee/ca/profileSubmitSSLClient", - self.secdir, password, "ipaCert", **params) -- http_status, http_reason_phrase, http_headers, http_body = result -+ http_status, http_headers, http_body = result - if http_status != 200: - raise RuntimeError("Unable to submit cert request") - -diff --git a/ipaserver/plugins/dogtag.py b/ipaserver/plugins/dogtag.py -index f5f8eb67067c87f07c06e556fb9fc73792fbbc64..3029a9144d80a9b081853b95259fcd37e35d8c2b 100644 ---- a/ipaserver/plugins/dogtag.py -+++ b/ipaserver/plugins/dogtag.py -@@ -1350,8 +1350,8 @@ class ra(rabase.rabase): - """ - :param url: The URL to post to. - :param kw: Keyword arguments to encode into POST body. -- :return: (http_status, http_reason_phrase, http_headers, http_body) -- as (integer, unicode, dict, str) -+ :return: (http_status, http_headers, http_body) -+ as (integer, dict, str) - - Perform an HTTP request. - """ -@@ -1361,8 +1361,8 @@ class ra(rabase.rabase): - """ - :param url: The URL to post to. - :param kw: Keyword arguments to encode into POST body. -- :return: (http_status, http_reason_phrase, http_headers, http_body) -- as (integer, unicode, dict, str) -+ :return: (http_status, http_headers, http_body) -+ as (integer, dict, str) - - Perform an HTTPS request - """ -@@ -1422,7 +1422,7 @@ class ra(rabase.rabase): - self.debug('%s.check_request_status()', self.fullname) - - # Call CMS -- http_status, http_reason_phrase, http_headers, http_body = \ -+ http_status, http_headers, http_body = \ - self._request('/ca/ee/ca/checkRequest', - self.env.ca_port, - requestId=request_id, -@@ -1431,7 +1431,7 @@ class ra(rabase.rabase): - # Parse and handle errors - if http_status != 200: - self.raise_certificate_operation_error('check_request_status', -- detail=http_reason_phrase) -+ detail=http_status) - - parse_result = self.get_parse_result_xml(http_body, parse_check_request_result_xml) - request_status = parse_result['request_status'] -@@ -1507,7 +1507,7 @@ class ra(rabase.rabase): - serial_number = int(serial_number, 0) - - # Call CMS -- http_status, http_reason_phrase, http_headers, http_body = \ -+ http_status, http_headers, http_body = \ - self._sslget('/ca/agent/ca/displayBySerial', - self.env.ca_agent_port, - serialNumber=str(serial_number), -@@ -1517,7 +1517,7 @@ class ra(rabase.rabase): - # Parse and handle errors - if http_status != 200: - self.raise_certificate_operation_error('get_certificate', -- detail=http_reason_phrase) -+ detail=http_status) - - parse_result = self.get_parse_result_xml(http_body, parse_display_cert_xml) - request_status = parse_result['request_status'] -@@ -1575,7 +1575,7 @@ class ra(rabase.rabase): - self.debug('%s.request_certificate()', self.fullname) - - # Call CMS -- http_status, http_reason_phrase, http_headers, http_body = \ -+ http_status, http_headers, http_body = \ - self._sslget('/ca/eeca/ca/profileSubmitSSLClient', - self.env.ca_ee_port, - profileId=profile_id, -@@ -1585,7 +1585,7 @@ class ra(rabase.rabase): - # Parse and handle errors - if http_status != 200: - self.raise_certificate_operation_error('request_certificate', -- detail=http_reason_phrase) -+ detail=http_status) - - parse_result = self.get_parse_result_xml(http_body, parse_profile_submit_result_xml) - # Note different status return, it's not request_status, it's error_code -@@ -1654,7 +1654,7 @@ class ra(rabase.rabase): - serial_number = int(serial_number, 0) - - # Call CMS -- http_status, http_reason_phrase, http_headers, http_body = \ -+ http_status, http_headers, http_body = \ - self._sslget('/ca/agent/ca/doRevoke', - self.env.ca_agent_port, - op='revoke', -@@ -1666,7 +1666,7 @@ class ra(rabase.rabase): - # Parse and handle errors - if http_status != 200: - self.raise_certificate_operation_error('revoke_certificate', -- detail=http_reason_phrase) -+ detail=http_status) - - parse_result = self.get_parse_result_xml(http_body, parse_revoke_cert_xml) - request_status = parse_result['request_status'] -@@ -1717,7 +1717,7 @@ class ra(rabase.rabase): - serial_number = int(serial_number, 0) - - # Call CMS -- http_status, http_reason_phrase, http_headers, http_body = \ -+ http_status, http_headers, http_body = \ - self._sslget('/ca/agent/ca/doUnrevoke', - self.env.ca_agent_port, - serialNumber=str(serial_number), -@@ -1726,7 +1726,7 @@ class ra(rabase.rabase): - # Parse and handle errors - if http_status != 200: - self.raise_certificate_operation_error('take_certificate_off_hold', -- detail=http_reason_phrase) -+ detail=http_status) - - - parse_result = self.get_parse_result_xml(http_body, parse_unrevoke_cert_xml) -@@ -2027,7 +2027,7 @@ class RestClient(Backend): - """Log into the REST API""" - if self.cookie is not None: - return -- status, status_text, resp_headers, resp_body = dogtag.https_request( -+ status, resp_headers, resp_body = dogtag.https_request( - self.ca_host, self.override_port or self.env.ca_agent_port, - '/ca/rest/account/login', - self.sec_dir, self.password, self.ipa_certificate_nickname, -@@ -2053,8 +2053,8 @@ class RestClient(Backend): - """ - :param url: The URL to post to. - :param kw: Keyword arguments to encode into POST body. -- :return: (http_status, http_reason_phrase, http_headers, http_body) -- as (integer, unicode, dict, str) -+ :return: (http_status, http_headers, http_body) -+ as (integer, dict, str) - - Perform an HTTPS request - """ -@@ -2068,7 +2068,7 @@ class RestClient(Backend): - resource = os.path.join('/ca/rest', self.path, path) - - # perform main request -- status, status_text, resp_headers, resp_body = dogtag.https_request( -+ status, resp_headers, resp_body = dogtag.https_request( - self.ca_host, self.override_port or self.env.ca_agent_port, - resource, - self.sec_dir, self.password, self.ipa_certificate_nickname, -@@ -2077,10 +2077,10 @@ class RestClient(Backend): - if status < 200 or status >= 300: - explanation = self._parse_dogtag_error(resp_body) or '' - raise errors.RemoteRetrieveError( -- reason=_('Non-2xx response from CA REST API: %(status)d %(status_text)s. %(explanation)s') -- % {'status': status, 'status_text': status_text, 'explanation': explanation} -+ reason=_('Non-2xx response from CA REST API: %(status)d. %(explanation)s') -+ % {'status': status, 'explanation': explanation} - ) -- return (status, status_text, resp_headers, resp_body) -+ return (status, resp_headers, resp_body) - - - class ra_certprofile(RestClient): -@@ -2105,7 +2105,7 @@ class ra_certprofile(RestClient): - """ - Read the profile configuration from Dogtag - """ -- status, status_text, resp_headers, resp_body = self._ssldo( -+ status, resp_headers, resp_body = self._ssldo( - 'GET', profile_id + '/raw') - return resp_body - --- -2.5.0 - diff --git a/SOURCES/0191-upgrade-unconditional-import-of-certificate-profiles.patch b/SOURCES/0191-upgrade-unconditional-import-of-certificate-profiles.patch deleted file mode 100644 index db607c5..0000000 --- a/SOURCES/0191-upgrade-unconditional-import-of-certificate-profiles.patch +++ /dev/null @@ -1,66 +0,0 @@ -From 52e2e879fa4decf67a19d6c79f4ec409b6a0dce7 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Mon, 22 Feb 2016 13:35:41 +0100 -Subject: [PATCH] upgrade: unconditional import of certificate profiles into - LDAP - -During IPA server upgrade, the migration of Dogtag profiles into LDAP -backend was bound to the update of CS.cfg which enabled the LDAP profile -subsystem. If the subsequent profile migration failed, the subsequent -upgrades were not executing the migration code leaving CA subsystem in -broken state. Therefore the migration code path should be executed -regardless of the status of the main Dogtag config file. - -https://fedorahosted.org/freeipa/ticket/5682 - -Reviewed-By: Fraser Tweedale -Reviewed-By: Jan Cholasta ---- - ipaserver/install/cainstance.py | 8 ++++++-- - ipaserver/install/server/upgrade.py | 4 +++- - 2 files changed, 9 insertions(+), 3 deletions(-) - -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index 369902ad04b197c9e9516503c1f81c4de1ef153b..1a98c438786ae7dad208212fff23e3a760c95b3c 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -1807,7 +1807,6 @@ def migrate_profiles_to_ldap(dogtag_constants): - continue - class_id = match.group(1) - -- root_logger.info("Migrating profile '%s' to LDAP", profile_id) - with open(filename) as f: - profile_data = f.read() - if profile_data[-1] != '\n': -@@ -1824,7 +1823,12 @@ def _create_dogtag_profile(profile_id, profile_data): - # import the profile - try: - profile_api.create_profile(profile_data) -- except errors.RemoteRetrieveError: -+ root_logger.info("Profile '%s' successfully migrated to LDAP", -+ profile_id) -+ except errors.RemoteRetrieveError as e: -+ root_logger.debug("Error migrating '{}': {}".format( -+ profile_id, e)) -+ - # conflicting profile; replace it if we are - # installing IPA, but keep it for upgrades - if api.env.context == 'installer': -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index 0a46635979497f8028465c2295b22485fd9c0279..258d976c83844f89c1a939303b685fd6565b79e5 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -336,7 +336,9 @@ def ca_enable_ldap_profile_subsystem(ca): - separator='=') - - ca.restart(dogtag.configured_constants().PKI_INSTANCE_NAME) -- cainstance.migrate_profiles_to_ldap(caconfig) -+ -+ root_logger.info('[Migrating certificate profiles to LDAP]') -+ cainstance.migrate_profiles_to_ldap(caconfig) - - return needs_update - --- -2.5.0 - diff --git a/SOURCES/0192-upgrade-fix-config-of-sidgen-and-extdom-plugins.patch b/SOURCES/0192-upgrade-fix-config-of-sidgen-and-extdom-plugins.patch deleted file mode 100644 index c0aee5a..0000000 --- a/SOURCES/0192-upgrade-fix-config-of-sidgen-and-extdom-plugins.patch +++ /dev/null @@ -1,279 +0,0 @@ -From c7df4a1856e740e88ac3633344815d5a0ff0d1f2 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Thu, 18 Feb 2016 19:59:50 +0100 -Subject: [PATCH] upgrade: fix config of sidgen and extdom plugins - -During upgrade to IPA 4.2, literally "$SUFFIX" value was added to -configuration of sidgen and extdom plugins. This cause that SID are not properly configured. - -Upgrade must fix "$SUFFIX" to reals suffix DN, and run sidgen task -against IPA domain (if exists). - -All trusts added when plugins configuration was broken must be re-added. - -https://fedorahosted.org/freeipa/ticket/5665 - -Reviewed-By: Alexander Bokovoy -Reviewed-By: Tomas Babej ---- - install/updates/90-post_upgrade_plugins.update | 2 + - ipaserver/install/dsinstance.py | 12 +- - ipaserver/install/plugins/adtrust.py | 153 ++++++++++++++++++++++++- - ipaserver/install/server/upgrade.py | 4 +- - 4 files changed, 162 insertions(+), 9 deletions(-) - -diff --git a/install/updates/90-post_upgrade_plugins.update b/install/updates/90-post_upgrade_plugins.update -index 3df3a4574705dbd8df8f25149c13877898afb66b..f0d77138520f41376d71478d3633ea4c19f66195 100644 ---- a/install/updates/90-post_upgrade_plugins.update -+++ b/install/updates/90-post_upgrade_plugins.update -@@ -4,6 +4,8 @@ - # middle - plugin: update_dnszones - plugin: update_dns_limits -+plugin: update_sigden_extdom_broken_config -+plugin: update_sids - plugin: update_default_range - plugin: update_default_trust_view - plugin: update_ca_renewal_master -diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py -index d78158532c4c88d9aa9acf3c65d278f5151458d8..7044782bac8068f7470b62bd7489b5319269b119 100644 ---- a/ipaserver/install/dsinstance.py -+++ b/ipaserver/install/dsinstance.py -@@ -925,9 +925,9 @@ class DsInstance(service.Service): - """ - Add sidgen directory server plugin configuration if it does not already exist. - """ -- self._ldap_mod('ipa-sidgen-conf.ldif', self.sub_dict) -+ self.add_sidgen_plugin(self.sub_dict['SUFFIX']) - -- def add_sidgen_plugin(self): -+ def add_sidgen_plugin(self, suffix): - """ - Add sidgen plugin configuration only if it does not already exist. - """ -@@ -935,7 +935,7 @@ class DsInstance(service.Service): - try: - self.admin_conn.get_entry(dn) - except errors.NotFound: -- self._add_sidgen_plugin() -+ self._ldap_mod('ipa-sidgen-conf.ldif', dict(SUFFIX=suffix)) - else: - root_logger.debug("sidgen plugin is already configured") - -@@ -943,9 +943,9 @@ class DsInstance(service.Service): - """ - Add directory server configuration for the extdom extended operation. - """ -- self._ldap_mod('ipa-extdom-extop-conf.ldif', self.sub_dict) -+ self.add_extdom_plugin(self.sub_dict['SUFFIX']) - -- def add_extdom_plugin(self): -+ def add_extdom_plugin(self, suffix): - """ - Add extdom configuration if it does not already exist. - """ -@@ -953,7 +953,7 @@ class DsInstance(service.Service): - try: - self.admin_conn.get_entry(dn) - except errors.NotFound: -- self._add_extdom_plugin() -+ self._ldap_mod('ipa-extdom-extop-conf.ldif', dict(SUFFIX=suffix)) - else: - root_logger.debug("extdom plugin is already configured") - -diff --git a/ipaserver/install/plugins/adtrust.py b/ipaserver/install/plugins/adtrust.py -index 45bcc5f2fe532446342300ff0c5e1e7149cf023b..4990a34f8972a0ffba098642c1ead09f976852e6 100644 ---- a/ipaserver/install/plugins/adtrust.py -+++ b/ipaserver/install/plugins/adtrust.py -@@ -24,6 +24,7 @@ from ipapython.dn import DN - from ipapython.ipa_log_manager import * - from ipapython import sysrestore - from ipaserver.install import installutils -+from ipaserver.install import sysupgrade - - DEFAULT_ID_RANGE_SIZE = 200000 - -@@ -164,7 +165,6 @@ class update_default_trust_view(Updater): - - return False, [update] - -- - class update_oddjobd_for_adtrust(Updater): - """ - Enables and starts oddjobd daemon if ipa-adtrust-install has been run -@@ -184,6 +184,157 @@ class update_oddjobd_for_adtrust(Updater): - - return False, [] - -+ -+class update_sigden_extdom_broken_config(Updater): -+ """Fix configuration of sidgen and extdom plugins -+ -+ Upgrade to IPA 4.2+ cause that sidgen and extdom plugins have improperly -+ configured basedn. -+ -+ All trusts which have been added when config was broken must to be -+ re-added manually. -+ -+ https://fedorahosted.org/freeipa/ticket/5665 -+ """ -+ -+ sidgen_config_dn = DN("cn=IPA SIDGEN,cn=plugins,cn=config") -+ extdom_config_dn = DN("cn=ipa_extdom_extop,cn=plugins,cn=config") -+ -+ def _fix_config(self): -+ """Due upgrade error configuration of sidgen and extdom plugins may -+ contain literally "$SUFFIX" value instead of real DN in nsslapd-basedn -+ attribute -+ -+ :return: True if config was fixed, False if fix is not needed -+ """ -+ ldap = self.api.Backend.ldap2 -+ basedn_attr = 'nsslapd-basedn' -+ modified = False -+ -+ for dn in (self.sidgen_config_dn, self.extdom_config_dn): -+ try: -+ entry = ldap.get_entry(dn, attrs_list=[basedn_attr]) -+ except errors.NotFound: -+ self.log.debug("configuration for %s not found, skipping", dn) -+ else: -+ configured_suffix = entry.single_value.get(basedn_attr) -+ if configured_suffix is None: -+ raise RuntimeError( -+ "Missing attribute {attr} in {dn}".format( -+ attr=basedn_attr, dn=dn -+ ) -+ ) -+ elif configured_suffix == "$SUFFIX": -+ # configured value is wrong, fix it -+ entry.single_value[basedn_attr] = str(self.api.env.basedn) -+ self.log.debug("updating attribute %s of %s to correct " -+ "value %s", basedn_attr, dn, -+ self.api.env.basedn) -+ ldap.update_entry(entry) -+ modified = True -+ else: -+ self.log.debug("configured basedn for %s is okay", dn) -+ -+ return modified -+ -+ def execute(self, **options): -+ if sysupgrade.get_upgrade_state('sidgen', 'config_basedn_updated'): -+ self.log.debug("Already done, skipping") -+ return False, () -+ -+ restart = False -+ if self._fix_config(): -+ sysupgrade.set_upgrade_state('sidgen', 'update_sids', True) -+ restart = True # DS has to be restarted to apply changes -+ -+ sysupgrade.set_upgrade_state('sidgen', 'config_basedn_updated', True) -+ return restart, () -+ -+ -+class update_sids(Updater): -+ """SIDs may be not created properly if bug with wrong configuration for -+ sidgen and extdom plugins is effective -+ -+ This must be run after "update_sigden_extdom_broken_config" -+ https://fedorahosted.org/freeipa/ticket/5665 -+ """ -+ sidgen_config_dn = DN("cn=IPA SIDGEN,cn=plugins,cn=config") -+ -+ def execute(self, **options): -+ ldap = self.api.Backend.ldap2 -+ -+ if sysupgrade.get_upgrade_state('sidgen', 'update_sids') is not True: -+ self.log.debug("SIDs do not need to be generated") -+ return False, () -+ -+ # check if IPA domain for AD trust has been created, and if we need to -+ # regenerate missing SIDs if attribute 'ipaNTSecurityIdentifier' -+ domain_IPA_AD_dn = DN( -+ ('cn', self.api.env.domain), -+ self.api.env.container_cifsdomains, -+ self.api.env.basedn) -+ attr_name = 'ipaNTSecurityIdentifier' -+ -+ try: -+ entry = ldap.get_entry(domain_IPA_AD_dn, attrs_list=[attr_name]) -+ except errors.NotFound: -+ self.log.debug("IPA domain object %s is not configured", -+ domain_IPA_AD_dn) -+ sysupgrade.set_upgrade_state('sidgen', 'update_sids', False) -+ return False, () -+ else: -+ if not entry.single_value.get(attr_name): -+ # we need to run sidgen task -+ sidgen_task_dn = DN( -+ "cn=generate domain sid,cn=ipa-sidgen-task,cn=tasks," -+ "cn=config") -+ sidgen_tasks_attr = { -+ "objectclass": ["top", "extensibleObject"], -+ "cn": ["sidgen"], -+ "delay": [0], -+ "nsslapd-basedn": [self.api.env.basedn], -+ } -+ -+ task_entry = ldap.make_entry(sidgen_task_dn, -+ **sidgen_tasks_attr) -+ try: -+ ldap.add_entry(task_entry) -+ except errors.DuplicateEntry: -+ self.log.debug("sidgen task already created") -+ else: -+ self.log.debug("sidgen task has been created") -+ -+ # we have to check all trusts domains which may been affected by the -+ # bug. Symptom is missing 'ipaNTSecurityIdentifier' attribute -+ -+ base_dn = DN(self.api.env.container_adtrusts, self.api.env.basedn) -+ try: -+ trust_domain_entries, truncated = ldap.find_entries( -+ base_dn=base_dn, -+ scope=ldap.SCOPE_ONELEVEL, -+ attrs_list=["cn"], -+ # more types of trusts can be stored under cn=trusts, we need -+ # the type with ipaNTTrustPartner attribute -+ filter="(!(%s=*))" % attr_name -+ ) -+ except errors.NotFound: -+ pass -+ else: -+ if truncated: -+ self.log.warning("update_sids: Search results were truncated") -+ -+ for entry in trust_domain_entries: -+ domain = entry.single_value["cn"] -+ self.log.error( -+ "Your trust to %s is broken. Please re-create it by " -+ "running 'ipa trust-add' again.", domain) -+ -+ sysupgrade.set_upgrade_state('sidgen', 'update_sids', False) -+ return False, () -+ -+ - api.register(update_default_range) - api.register(update_default_trust_view) - api.register(update_oddjobd_for_adtrust) -+api.register(update_sids) -+api.register(update_sigden_extdom_broken_config) -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index 258d976c83844f89c1a939303b685fd6565b79e5..c53b19a937d559b25da256670a5205ab40e0cadb 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -1290,8 +1290,8 @@ def ds_enable_sidgen_extdom_plugins(ds): - root_logger.debug('sidgen and extdom plugins are enabled already') - return - -- ds.add_sidgen_plugin() -- ds.add_extdom_plugin() -+ ds.add_sidgen_plugin(api.env.basedn) -+ ds.add_extdom_plugin(api.env.basedn) - sysupgrade.set_upgrade_state('ds', 'enable_ds_sidgen_extdom_plugins', True) - - def ca_upgrade_schema(ca): --- -2.5.0 - diff --git a/SOURCES/0193-trusts-use-ipaNTTrustPartner-attribute-to-detect-tru.patch b/SOURCES/0193-trusts-use-ipaNTTrustPartner-attribute-to-detect-tru.patch deleted file mode 100644 index 03b2239..0000000 --- a/SOURCES/0193-trusts-use-ipaNTTrustPartner-attribute-to-detect-tru.patch +++ /dev/null @@ -1,63 +0,0 @@ -From 6f958201dc32a1043c77632fe98c05307a4ea671 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Mon, 22 Feb 2016 17:36:01 +0100 -Subject: [PATCH] trusts: use ipaNTTrustPartner attribute to detect trust - entries - -Trust entries were found by presence of ipaNTSecurityIdentifier -attribute. Unfortunately this attribute might not be there due the bug. -As replacement for this, attribute ipaNTTrustPartner can be used. - -Note: other non trust entries located in cn=trusts subtree can be -cross-realm principals. - -https://fedorahosted.org/freeipa/ticket/5665 - -Reviewed-By: Alexander Bokovoy -Reviewed-By: Tomas Babej ---- - ipalib/plugins/trust.py | 7 +++++-- - ipaserver/install/plugins/adtrust.py | 2 +- - 2 files changed, 6 insertions(+), 3 deletions(-) - -diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py -index 173463ae7d4134b5bd155cc5fa920bfabd0a6958..ff142591d385e715994f0381c6b23c416763cd03 100644 ---- a/ipalib/plugins/trust.py -+++ b/ipalib/plugins/trust.py -@@ -541,7 +541,10 @@ class trust(LDAPObject): - ldap = self.backend - filter = ldap.make_filter({'objectclass': ['ipaNTTrustedDomain'], 'cn': [keys[-1]] }, - rules=ldap.MATCH_ALL) -- filter = ldap.combine_filters((filter, "ipaNTSecurityIdentifier=*"), rules=ldap.MATCH_ALL) -+ # more type of objects can be located in subtree (for example -+ # cross-realm principals). we need this attr do detect trust -+ # entries -+ filter = ldap.combine_filters((filter, "ipaNTTrustPartner=*"), rules=ldap.MATCH_ALL) - result = ldap.get_entries(DN(self.container_dn, self.env.basedn), - ldap.SCOPE_SUBTREE, filter, ['']) - if len(result) > 1: -@@ -996,7 +999,7 @@ class trust_find(LDAPSearch): - # search needs to be done on a sub-tree scope - def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, *args, **options): - # list only trust, not trust domains -- trust_filter = '(ipaNTSecurityIdentifier=*)' -+ trust_filter = '(ipaNTTrustPartner=*)' - filter = ldap.combine_filters((filters, trust_filter), rules=ldap.MATCH_ALL) - return (filter, base_dn, ldap.SCOPE_SUBTREE) - -diff --git a/ipaserver/install/plugins/adtrust.py b/ipaserver/install/plugins/adtrust.py -index 4990a34f8972a0ffba098642c1ead09f976852e6..ea6de5cefe1dc56fc55cca076643867ecbeb08fe 100644 ---- a/ipaserver/install/plugins/adtrust.py -+++ b/ipaserver/install/plugins/adtrust.py -@@ -315,7 +315,7 @@ class update_sids(Updater): - attrs_list=["cn"], - # more types of trusts can be stored under cn=trusts, we need - # the type with ipaNTTrustPartner attribute -- filter="(!(%s=*))" % attr_name -+ filter="(&(ipaNTTrustPartner=*)(!(%s=*)))" % attr_name - ) - except errors.NotFound: - pass --- -2.5.0 - diff --git a/SOURCES/0194-Warn-user-if-trust-is-broken.patch b/SOURCES/0194-Warn-user-if-trust-is-broken.patch deleted file mode 100644 index bab8f9d..0000000 --- a/SOURCES/0194-Warn-user-if-trust-is-broken.patch +++ /dev/null @@ -1,115 +0,0 @@ -From b08bab80ab8c11681a96a10807930c830a2d096f Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Fri, 19 Feb 2016 14:55:34 +0100 -Subject: [PATCH] Warn user if trust is broken - -Detect missing ipaNTSecurityIdentifier and print message for a user, -that the trust is broken as result of trust-show and trust-find commands. - -https://fedorahosted.org/freeipa/ticket/5665 - -Reviewed-By: Alexander Bokovoy -Reviewed-By: Tomas Babej ---- - ipalib/messages.py | 11 +++++++++++ - ipalib/plugins/trust.py | 41 +++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 52 insertions(+) - -diff --git a/ipalib/messages.py b/ipalib/messages.py -index 58ae1f3ecbbf139f6f584c0ea2ebea6eb92e6e2b..ce92547de78a07f00d40fd850563faf1253826e3 100644 ---- a/ipalib/messages.py -+++ b/ipalib/messages.py -@@ -241,6 +241,17 @@ class DNSSECValidationFailingWarning(PublicMessage): - u"validation on all IPA servers.") - - -+class BrokenTrust(PublicMessage): -+ """ -+ **13018** Trust for a specified domain is broken -+ """ -+ -+ errno = 13018 -+ type = "warning" -+ format = _("Your trust to %(domain)s is broken. Please re-create it by " -+ "running 'ipa trust-add' again.") -+ -+ - def iter_messages(variables, base): - """Return a tuple with all subclasses - """ -diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py -index ff142591d385e715994f0381c6b23c416763cd03..d451325e31e4e1d8d7223f009677bbcb002c65cb 100644 ---- a/ipalib/plugins/trust.py -+++ b/ipalib/plugins/trust.py -@@ -18,6 +18,9 @@ - # You should have received a copy of the GNU General Public License - # along with this program. If not, see . - -+from ipalib.messages import ( -+ add_message, -+ BrokenTrust) - from ipalib.plugable import Registry - from ipalib.plugins.baseldap import * - from ipalib.plugins.dns import dns_container_exists -@@ -554,6 +557,30 @@ class trust(LDAPObject): - dn=make_trust_dn(self.env, trust_type, DN(*sdn)) - return dn - -+ def warning_if_ad_trust_dom_have_missing_SID(self, result, **options): -+ """Due bug https://fedorahosted.org/freeipa/ticket/5665 there might be -+ AD trust domain without generated SID, warn user about it. -+ """ -+ ldap = self.api.Backend.ldap2 -+ -+ try: -+ entries, truncated = ldap.find_entries( -+ base_dn=DN(self.container_dn, self.api.env.basedn), -+ attrs_list=['cn'], -+ filter='(&(ipaNTTrustPartner=*)' -+ '(!(ipaNTSecurityIdentifier=*)))', -+ ) -+ except errors.NotFound: -+ pass -+ else: -+ for entry in entries: -+ add_message( -+ options['version'], -+ result, -+ BrokenTrust(domain=entry.single_value['cn']) -+ ) -+ -+ - @register() - class trust_add(LDAPCreate): - __doc__ = _(''' -@@ -1003,6 +1030,13 @@ class trust_find(LDAPSearch): - filter = ldap.combine_filters((filters, trust_filter), rules=ldap.MATCH_ALL) - return (filter, base_dn, ldap.SCOPE_SUBTREE) - -+ def execute(self, *args, **options): -+ result = super(trust_find, self).execute(*args, **options) -+ -+ self.obj.warning_if_ad_trust_dom_have_missing_SID(result, **options) -+ -+ return result -+ - def post_callback(self, ldap, entries, truncated, *args, **options): - if options.get('pkey_only', False): - return truncated -@@ -1022,6 +1056,13 @@ class trust_show(LDAPRetrieve): - has_output_params = LDAPRetrieve.has_output_params + trust_output_params +\ - (Str('ipanttrusttype'), Str('ipanttrustdirection')) - -+ def execute(self, *keys, **options): -+ result = super(trust_show, self).execute(*keys, **options) -+ -+ self.obj.warning_if_ad_trust_dom_have_missing_SID(result, **options) -+ -+ return result -+ - def post_callback(self, ldap, dn, entry_attrs, *keys, **options): - - assert isinstance(dn, DN) --- -2.5.0 - diff --git a/SOURCES/0195-fix-upgrade-wait-for-proper-DS-socket-after-DS-resta.patch b/SOURCES/0195-fix-upgrade-wait-for-proper-DS-socket-after-DS-resta.patch deleted file mode 100644 index 040498d..0000000 --- a/SOURCES/0195-fix-upgrade-wait-for-proper-DS-socket-after-DS-resta.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 69322c06e8fd9f21867a9c7aa04f990be47536df Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Tue, 23 Feb 2016 10:37:47 +0100 -Subject: [PATCH] fix upgrade: wait for proper DS socket after DS restart - -DS restart executed by upgrade plugin causes that upgrade framework -is waiting for the improper socket. It leads to TimeoutError because -DS is not listening on 389 port during upgrade. This commit fixes the issue. - -Required for: https://fedorahosted.org/freeipa/ticket/5665 - -Reviewed-By: Alexander Bokovoy -Reviewed-By: Tomas Babej ---- - ipaserver/install/ldapupdate.py | 4 +--- - 1 file changed, 1 insertion(+), 3 deletions(-) - -diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py -index 6f796dfdc8bbac1bb99a8b5a1bd5a6aaa778db16..0e258612d3060188212fdd2625d7e62b5cb14ebf 100644 ---- a/ipaserver/install/ldapupdate.py -+++ b/ipaserver/install/ldapupdate.py -@@ -44,7 +44,6 @@ from ipaplatform.paths import paths - from ipaplatform import services - from ipapython.dn import DN - from ipapython.ipa_log_manager import * --from ipapython.ipautil import wait_for_open_socket - - UPDATES_DIR=paths.UPDATES_DIR - -@@ -932,5 +931,4 @@ class LDAPUpdate: - def restart_ds(self): - dirsrv = services.knownservices.dirsrv - self.log.debug('Restarting directory server to apply updates') -- dirsrv.restart() -- wait_for_open_socket(self.socket_name) -+ dirsrv.restart(ldapi=self.ldapi) --- -2.5.0 - diff --git a/SOURCES/0196-slapi-nis-update-configuration-to-allow-external-mem.patch b/SOURCES/0196-slapi-nis-update-configuration-to-allow-external-mem.patch deleted file mode 100644 index f9f9843..0000000 --- a/SOURCES/0196-slapi-nis-update-configuration-to-allow-external-mem.patch +++ /dev/null @@ -1,61 +0,0 @@ -From 01ccf0deee2cfa98f76d79eb435be74efecd4626 Mon Sep 17 00:00:00 2001 -From: Alexander Bokovoy -Date: Mon, 22 Feb 2016 12:40:03 +0200 -Subject: [PATCH] slapi-nis: update configuration to allow external members of - IPA groups - -Currently in an environment with trust to AD the compat tree does not -show AD users as members of IPA groups. The reason is that IPA groups -are read directly from the IPA DS tree and external groups are not -handled. - -slapi-nis project has added support for it in 0.55, make sure we update -configuration for the group map if it exists and depend on 0.55 version. - -https://fedorahosted.org/freeipa/ticket/4403 - -Reviewed-By: Tomas Babej ---- - freeipa.spec.in | 2 +- - install/updates/50-externalmembers.update | 3 +++ - install/updates/Makefile.am | 1 + - 3 files changed, 5 insertions(+), 1 deletion(-) - create mode 100644 install/updates/50-externalmembers.update - -diff --git a/freeipa.spec.in b/freeipa.spec.in -index cd26d4ce66e320f8b8bf6aaa3e738b4c11f89aa9..17b90fc4653bd7694bf389a19d5847d7df544890 100644 ---- a/freeipa.spec.in -+++ b/freeipa.spec.in -@@ -139,7 +139,7 @@ Requires(pre): systemd-units - Requires(post): systemd-units - Requires: selinux-policy >= %{selinux_policy_version} - Requires(post): selinux-policy-base --Requires: slapi-nis >= 0.54.2-1 -+Requires: slapi-nis >= 0.55-1 - Requires: pki-ca >= 10.2.5 - Requires: pki-kra >= 10.2.5 - Requires(preun): python systemd-units -diff --git a/install/updates/50-externalmembers.update b/install/updates/50-externalmembers.update -new file mode 100644 -index 0000000000000000000000000000000000000000..6b9c5dd23fac65fd5e9055b255e7c4d41e5cc66b ---- /dev/null -+++ b/install/updates/50-externalmembers.update -@@ -0,0 +1,3 @@ -+dn: cn=groups,cn=Schema Compatibility,cn=plugins,cn=config -+addifexist: schema-compat-entry-attribute: ipaexternalmember=%deref_r("member","ipaexternalmember") -+addifexist: schema-compat-entry-attribute: objectclass=ipaexternalgroup -diff --git a/install/updates/Makefile.am b/install/updates/Makefile.am -index 26e4c04ed66a4a2061a3bb3ca2f4a6cd84502598..86799838c8713d04d03a69167a00ee4baa6acd6c 100644 ---- a/install/updates/Makefile.am -+++ b/install/updates/Makefile.am -@@ -45,6 +45,7 @@ app_DATA = \ - 50-krbenctypes.update \ - 50-nis.update \ - 50-ipaconfig.update \ -+ 50-externalmembers.update \ - 55-pbacmemberof.update \ - 59-trusts-sysacount.update \ - 60-trusts.update \ --- -2.5.0 - diff --git a/SOURCES/0197-Insure-the-admin_conn-is-disconnected-on-stop.patch b/SOURCES/0197-Insure-the-admin_conn-is-disconnected-on-stop.patch deleted file mode 100644 index 1d60fc2..0000000 --- a/SOURCES/0197-Insure-the-admin_conn-is-disconnected-on-stop.patch +++ /dev/null @@ -1,36 +0,0 @@ -From 431f42703acfb2f22c034a336277dcb2c320928a Mon Sep 17 00:00:00 2001 -From: Simo Sorce -Date: Tue, 4 Aug 2015 10:15:36 -0400 -Subject: [PATCH] Insure the admin_conn is disconnected on stop - -If we stop or restart the server insure admin_conn gets reset or other -parts may fail to properly connect/authenticate - -Signed-off-by: Simo Sorce -Reviewed-By: Jan Cholasta ---- - ipaserver/install/dsinstance.py | 7 +++++++ - 1 file changed, 7 insertions(+) - -diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py -index 7044782bac8068f7470b62bd7489b5319269b119..cadf9ccbe8ed0a20813af3fd671b18942a918b0b 100644 ---- a/ipaserver/install/dsinstance.py -+++ b/ipaserver/install/dsinstance.py -@@ -478,7 +478,14 @@ class DsInstance(service.Service): - # Does not apply with newer DS releases - pass - -+ def stop(self, *args, **kwargs): -+ if self.admin_conn: -+ self.ldap_disconnect() -+ super(DsInstance, self).stop(*args, **kwargs) -+ - def restart(self, instance=''): -+ if self.admin_conn: -+ self.ldap_disconnect() - try: - super(DsInstance, self).restart(instance) - if not is_ds_running(instance): --- -2.5.0 - diff --git a/SOURCES/0198-Fix-connections-to-DS-during-installation.patch b/SOURCES/0198-Fix-connections-to-DS-during-installation.patch deleted file mode 100644 index 8a9e587..0000000 --- a/SOURCES/0198-Fix-connections-to-DS-during-installation.patch +++ /dev/null @@ -1,42 +0,0 @@ -From 520e2ed9c5b2cfe3e3231bd616639bddb16d6995 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Tue, 1 Mar 2016 17:36:55 +0100 -Subject: [PATCH] Fix connections to DS during installation - -Regression caused by commit 9818e463f5d0a91b300801ee7c8f31f25de402b2, -admin_conn should be connected in method if there is no connection. - -https://fedorahosted.org/freeipa/ticket/5665 - -Reviewed-By: Petr Vobornik ---- - ipaserver/install/dsinstance.py | 6 ++++++ - 1 file changed, 6 insertions(+) - -diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py -index cadf9ccbe8ed0a20813af3fd671b18942a918b0b..4ad0f9e7def8a10b1eaffce1b3d9cadd9cdcc689 100644 ---- a/ipaserver/install/dsinstance.py -+++ b/ipaserver/install/dsinstance.py -@@ -938,6 +938,9 @@ class DsInstance(service.Service): - """ - Add sidgen plugin configuration only if it does not already exist. - """ -+ if not self.admin_conn: -+ self.ldap_connect() -+ - dn = DN('cn=IPA SIDGEN,cn=plugins,cn=config') - try: - self.admin_conn.get_entry(dn) -@@ -956,6 +959,9 @@ class DsInstance(service.Service): - """ - Add extdom configuration if it does not already exist. - """ -+ if not self.admin_conn: -+ self.ldap_connect() -+ - dn = DN('cn=ipa_extdom_extop,cn=plugins,cn=config') - try: - self.admin_conn.get_entry(dn) --- -2.5.0 - diff --git a/SOURCES/0199-Fix-broken-trust-warnings.patch b/SOURCES/0199-Fix-broken-trust-warnings.patch deleted file mode 100644 index 3b650c6..0000000 --- a/SOURCES/0199-Fix-broken-trust-warnings.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 9f131566a8218a082b59ec980e04f9193e9c85f7 Mon Sep 17 00:00:00 2001 -From: Martin Basti -Date: Wed, 16 Mar 2016 13:41:51 +0100 -Subject: [PATCH] Fix broken trust warnings - -Warning should be shown only for parent entries of trust domain. Subdomains do not contain ipaNTSecurityIdentifier attribute at all. - -https://fedorahosted.org/freeipa/ticket/5737 - -Reviewed-By: Alexander Bokovoy ---- - ipalib/plugins/trust.py | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/ipalib/plugins/trust.py b/ipalib/plugins/trust.py -index d451325e31e4e1d8d7223f009677bbcb002c65cb..4b3cb7aab665e5cd952704a58e4b58ea55ecab0a 100644 ---- a/ipalib/plugins/trust.py -+++ b/ipalib/plugins/trust.py -@@ -565,7 +565,9 @@ class trust(LDAPObject): - - try: - entries, truncated = ldap.find_entries( -- base_dn=DN(self.container_dn, self.api.env.basedn), -+ base_dn=DN(self.api.env.container_adtrusts, -+ self.api.env.basedn), -+ scope=ldap.SCOPE_ONELEVEL, - attrs_list=['cn'], - filter='(&(ipaNTTrustPartner=*)' - '(!(ipaNTSecurityIdentifier=*)))', --- -2.5.0 - diff --git a/SOURCES/0200-replica-install-improvements-in-the-handling-of-CA-r.patch b/SOURCES/0200-replica-install-improvements-in-the-handling-of-CA-r.patch deleted file mode 100644 index e16c0c9..0000000 --- a/SOURCES/0200-replica-install-improvements-in-the-handling-of-CA-r.patch +++ /dev/null @@ -1,108 +0,0 @@ -From d1470a8a5d2f39b57d8d66e8d0d7e8437fcd2ae4 Mon Sep 17 00:00:00 2001 -From: Martin Babinsky -Date: Wed, 2 Dec 2015 12:22:45 +0100 -Subject: [PATCH] replica install: improvements in the handling of CA-related - IPA config entries - -When a CA-less replica is installed, its IPA config file should be updated so -that ca_host points to nearest CA master and all certificate requests are -forwarded to it. A subsequent installation of CA subsystem on the replica -should clear this entry from the config so that all certificate requests are -handled by freshly installed local CA. - -https://fedorahosted.org/freeipa/ticket/5506 - -Reviewed-By: Martin Basti ---- - ipaserver/install/ca.py | 16 ---------------- - ipaserver/install/cainstance.py | 18 ++++++++++++++++++ - ipaserver/install/server/replicainstall.py | 3 +++ - 3 files changed, 21 insertions(+), 16 deletions(-) - -diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py -index d2fb5feeaf96e8450eddb1bc4e65ef3316b05b38..b4db8dcbfad9d482e7106cd06b3d497ccf8954f0 100644 ---- a/ipaserver/install/ca.py -+++ b/ipaserver/install/ca.py -@@ -12,7 +12,6 @@ from ipaplatform.paths import paths - from ipaserver.install import installutils, certs - from ipaserver.install.replication import replica_conn_check - from ipalib import api, certstore, x509 --from ConfigParser import RawConfigParser - from ipapython.dn import DN - from ipapython.ipa_log_manager import root_logger - -@@ -240,21 +239,6 @@ def install_step_1(standalone, replica_config, options): - if standalone: - ca.start(ca.dogtag_constants.PKI_INSTANCE_NAME) - -- # Update config file -- try: -- parser = RawConfigParser() -- parser.read(paths.IPA_DEFAULT_CONF) -- parser.set('global', 'enable_ra', 'True') -- parser.set('global', 'ra_plugin', 'dogtag') -- parser.set('global', 'dogtag_version', -- str(dogtag_constants.DOGTAG_VERSION)) -- with open(paths.IPA_DEFAULT_CONF, 'w') as f: -- parser.write(f) -- except IOError, e: -- print "Failed to update /etc/ipa/default.conf" -- root_logger.error(str(e)) -- sys.exit(1) -- - # We need to restart apache as we drop a new config file in there - services.knownservices.httpd.restart(capture_output=True) - -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index 1a98c438786ae7dad208212fff23e3a760c95b3c..b06760308865aa42afac79d6750f4a422a5c8f95 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -482,6 +482,8 @@ class CAInstance(DogtagInstance): - self.step("importing IPA certificate profiles", - import_included_profiles) - self.step("adding default CA ACL", ensure_default_caacl) -+ self.step("updating IPA configuration", -+ lambda: update_ipa_conf(self.dogtag_constants)) - - self.start_creation(runtime=210) - -@@ -1880,6 +1882,22 @@ def ensure_default_caacl(): - api.Backend.ldap2.disconnect() - - -+def update_ipa_conf(dogtag_constants): -+ """ -+ Update IPA configuration file to ensure that RA plugins are enabled and -+ that CA host points to localhost -+ """ -+ parser = ConfigParser.RawConfigParser() -+ parser.read(paths.IPA_DEFAULT_CONF) -+ parser.set('global', 'enable_ra', 'True') -+ parser.set('global', 'ra_plugin', 'dogtag') -+ parser.set('global', 'dogtag_version', -+ str(dogtag_constants.DOGTAG_VERSION)) -+ parser.remove_option('global', 'ca_host') -+ with open(paths.IPA_DEFAULT_CONF, 'w') as f: -+ parser.write(f) -+ -+ - if __name__ == "__main__": - standard_logging_setup("install.log") - ds = dsinstance.DsInstance() -diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py -index 317eda92dd4322542f035c2df4dba919a5898cc7..2ab95add90d33eb191d4e75b62cb4eceac40551b 100644 ---- a/ipaserver/install/server/replicainstall.py -+++ b/ipaserver/install/server/replicainstall.py -@@ -378,6 +378,9 @@ def install_check(installer): - fd.write("ra_plugin=dogtag\n") - fd.write("dogtag_version=%s\n" % - dogtag.install_constants.DOGTAG_VERSION) -+ -+ if not config.setup_ca: -+ fd.write("ca_host={0}\n".format(config.master_host_name)) - else: - fd.write("enable_ra=False\n") - fd.write("ra_plugin=none\n") --- -2.5.0 - diff --git a/SOURCES/0201-certdb-never-use-the-r-option-of-certutil.patch b/SOURCES/0201-certdb-never-use-the-r-option-of-certutil.patch deleted file mode 100644 index 48c2bcc..0000000 --- a/SOURCES/0201-certdb-never-use-the-r-option-of-certutil.patch +++ /dev/null @@ -1,49 +0,0 @@ -From c0598b1af6885b1558ef592d6e2a5250f707e878 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Thu, 10 Mar 2016 13:16:41 +0100 -Subject: [PATCH] certdb: never use the -r option of certutil - -The -r option makes certutil output certificates in DER. If there are -multiple certificates sharing the same nickname, certutil will output -them concatenated into a single blob. The blob is not a valid DER -anymore and causes failures further in the code. - -Use the -a option instead to output the certificates in PEM and convert -them to DER on demand. - -https://fedorahosted.org/freeipa/ticket/5117 -https://fedorahosted.org/freeipa/ticket/5720 - -Reviewed-By: David Kupka ---- - ipapython/certdb.py | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/ipapython/certdb.py b/ipapython/certdb.py -index 5a6e494fb8a5963ae9c68c697234e83575bc89ec..63dc4580b43ec11329d2074fc9a33e55dac9cb03 100644 ---- a/ipapython/certdb.py -+++ b/ipapython/certdb.py -@@ -395,15 +395,15 @@ class NSSDatabase(object): - "Setting trust on %s failed" % root_nickname) - - def get_cert(self, nickname, pem=False): -- args = ['-L', '-n', nickname] -- if pem: -- args.append('-a') -- else: -- args.append('-r') -+ args = ['-L', '-n', nickname, '-a'] - try: - cert, err, returncode = self.run_certutil(args) - except ipautil.CalledProcessError: - raise RuntimeError("Failed to get %s" % nickname) -+ if not pem: -+ (cert, start) = find_cert_from_txt(cert, start=0) -+ cert = x509.strip_header(cert) -+ cert = base64.b64decode(cert) - return cert - - def has_nickname(self, nickname): --- -2.5.0 - diff --git a/SOURCES/0202-Prevent-replica-install-from-overwriting-cert-profil.patch b/SOURCES/0202-Prevent-replica-install-from-overwriting-cert-profil.patch deleted file mode 100644 index 45c936e..0000000 --- a/SOURCES/0202-Prevent-replica-install-from-overwriting-cert-profil.patch +++ /dev/null @@ -1,70 +0,0 @@ -From 81d5888a2dc512cd0295b860cf8f408dea2e46a0 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Wed, 11 May 2016 16:13:51 +1000 -Subject: [PATCH] Prevent replica install from overwriting cert profiles - -An earlier change that unconditionally triggers import of file-based -profiles to LDAP during server or replica install results in -replicas overwriting FreeIPA-managed profiles with profiles of the -same name shipped with Dogtag. ('caIPAserviceCert' is the affected -profile). - -Avoid this situation by never overwriting existing profiles during -the LDAP import. - -Fixes: https://fedorahosted.org/freeipa/ticket/5881 -Reviewed-By: Jan Cholasta ---- - ipaserver/install/cainstance.py | 18 ++++++++++++------ - 1 file changed, 12 insertions(+), 6 deletions(-) - -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index b06760308865aa42afac79d6750f4a422a5c8f95..50ca5d3aeb9be24d8e1e80ad408191fca76a459c 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -1763,7 +1763,9 @@ def import_included_profiles(): - conn.add_entry(entry) - profile_data = ipautil.template_file( - '/usr/share/ipa/profiles/{}.cfg'.format(profile_id), sub_dict) -- _create_dogtag_profile(profile_id, profile_data) -+ -+ # Create the profile, replacing any existing profile of same name -+ _create_dogtag_profile(profile_id, profile_data, overwrite=True) - root_logger.info("Imported profile '%s'", profile_id) - - api.Backend.ra_certprofile.override_port = None -@@ -1815,12 +1817,17 @@ def migrate_profiles_to_ldap(dogtag_constants): - profile_data += '\n' - profile_data += 'profileId={}\n'.format(profile_id) - profile_data += 'classId={}\n'.format(class_id) -- _create_dogtag_profile(profile_id, profile_data) -+ -+ # Import the profile, but do not replace it if it already exists. -+ # This prevents replicas from replacing IPA-managed profiles with -+ # Dogtag default profiles of same name. -+ # -+ _create_dogtag_profile(profile_id, profile_data, overwrite=False) - - api.Backend.ra_certprofile.override_port = None - - --def _create_dogtag_profile(profile_id, profile_data): -+def _create_dogtag_profile(profile_id, profile_data, overwrite): - with api.Backend.ra_certprofile as profile_api: - # import the profile - try: -@@ -1831,9 +1838,8 @@ def _create_dogtag_profile(profile_id, profile_data): - root_logger.debug("Error migrating '{}': {}".format( - profile_id, e)) - -- # conflicting profile; replace it if we are -- # installing IPA, but keep it for upgrades -- if api.env.context == 'installer': -+ # profile already exists -+ if overwrite: - try: - profile_api.disable_profile(profile_id) - except errors.RemoteRetrieveError: --- -2.5.5 - diff --git a/SOURCES/0203-Detect-and-repair-incorrect-caIPAserviceCert-config.patch b/SOURCES/0203-Detect-and-repair-incorrect-caIPAserviceCert-config.patch deleted file mode 100644 index c83ebe6..0000000 --- a/SOURCES/0203-Detect-and-repair-incorrect-caIPAserviceCert-config.patch +++ /dev/null @@ -1,118 +0,0 @@ -From 1eb9cc7556357b1b8d6d826321cb38b1f96c1b7e Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Wed, 18 May 2016 14:10:39 +1000 -Subject: [PATCH] Detect and repair incorrect caIPAserviceCert config - -A regression caused replica installation to replace the FreeIPA -version of caIPAserviceCert with the version shipped by Dogtag. - -During upgrade, detect and repair occurrences of this problem. - -Part of: https://fedorahosted.org/freeipa/ticket/5881 - -Reviewed-By: Jan Cholasta ---- - ipaserver/install/cainstance.py | 49 ++++++++++++++++++++++++++++++++++--- - ipaserver/install/server/upgrade.py | 3 +++ - 2 files changed, 49 insertions(+), 3 deletions(-) - -diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py -index 50ca5d3aeb9be24d8e1e80ad408191fca76a459c..a8a57c4ffdbec453c76a01b88a7d4a188c03be33 100644 ---- a/ipaserver/install/cainstance.py -+++ b/ipaserver/install/cainstance.py -@@ -1717,14 +1717,18 @@ def configure_profiles_acl(): - conn.disconnect() - return updated - --def import_included_profiles(): -+ -+def __get_profile_config(profile_id): - sub_dict = dict( - DOMAIN=ipautil.format_netloc(api.env.domain), - IPA_CA_RECORD=IPA_CA_RECORD, - CRL_ISSUER='CN=Certificate Authority,o=ipaca', - SUBJECT_DN_O=dsinstance.DsInstance().find_subject_base(), - ) -+ return ipautil.template_file( -+ '/usr/share/ipa/profiles/{}.cfg'.format(profile_id), sub_dict) - -+def import_included_profiles(): - server_id = installutils.realm_to_serverid(api.env.realm) - dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id - conn = ldap2.ldap2(api, ldap_uri=dogtag_uri) -@@ -1761,10 +1765,9 @@ def import_included_profiles(): - ipacertprofilestoreissued=['TRUE' if store_issued else 'FALSE'], - ) - conn.add_entry(entry) -- profile_data = ipautil.template_file( -- '/usr/share/ipa/profiles/{}.cfg'.format(profile_id), sub_dict) - - # Create the profile, replacing any existing profile of same name -+ profile_data = __get_profile_config(profile_id) - _create_dogtag_profile(profile_id, profile_data, overwrite=True) - root_logger.info("Imported profile '%s'", profile_id) - -@@ -1772,6 +1775,46 @@ def import_included_profiles(): - conn.disconnect() - - -+def repair_profile_caIPAserviceCert(): -+ """ -+ A regression caused replica installation to replace the FreeIPA -+ version of caIPAserviceCert with the version shipped by Dogtag. -+ -+ This function detects and repairs occurrences of this problem. -+ -+ """ -+ api.Backend.ra_certprofile._read_password() -+ api.Backend.ra_certprofile.override_port = 8443 -+ -+ profile_id = 'caIPAserviceCert' -+ -+ with api.Backend.ra_certprofile as profile_api: -+ try: -+ cur_config = profile_api.read_profile(profile_id).splitlines() -+ except errors.RemoteRetrieveError as e: -+ # no profile there to check/repair -+ api.Backend.ra_certprofile.override_port = None -+ return -+ -+ indicators = [ -+ "policyset.serverCertSet.1.default.params.name=" -+ "CN=$request.req_subject_name.cn$, OU=pki-ipa, O=IPA ", -+ "policyset.serverCertSet.9.default.params.crlDistPointsPointName_0=" -+ "https://ipa.example.com/ipa/crl/MasterCRL.bin", -+ ] -+ need_repair = all(l in cur_config for l in indicators) -+ -+ if need_repair: -+ root_logger.debug( -+ "Detected that profile '{}' has been replaced with " -+ "incorrect version; begin repair.".format(profile_id)) -+ _create_dogtag_profile( -+ profile_id, __get_profile_config(profile_id), overwrite=True) -+ root_logger.debug("Repair of profile '{}' complete.".format(profile_id)) -+ -+ api.Backend.ra_certprofile.override_port = None -+ -+ - def migrate_profiles_to_ldap(dogtag_constants): - """Migrate profiles from filesystem to LDAP. - -diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py -index c53b19a937d559b25da256670a5205ab40e0cadb..b0cd789d58408f720774adb276843a1b6ab6007d 100644 ---- a/ipaserver/install/server/upgrade.py -+++ b/ipaserver/install/server/upgrade.py -@@ -1554,6 +1554,9 @@ def upgrade_configuration(): - ca_import_included_profiles(ca) - add_default_caacl(ca) - -+ if ca.is_configured(): -+ cainstance.repair_profile_caIPAserviceCert() -+ - set_sssd_domain_option('ipa_server_mode', 'True') - - if ds_running and not ds.is_running(): --- -2.5.5 - diff --git a/SOURCES/0204-replica-install-do-not-set-CA-renewal-master-flag.patch b/SOURCES/0204-replica-install-do-not-set-CA-renewal-master-flag.patch deleted file mode 100644 index 8b03c3a..0000000 --- a/SOURCES/0204-replica-install-do-not-set-CA-renewal-master-flag.patch +++ /dev/null @@ -1,89 +0,0 @@ -From d279db85dbf455a6cbdacc48cbbc2081a9be5252 Mon Sep 17 00:00:00 2001 -From: Jan Cholasta -Date: Mon, 23 May 2016 16:18:02 +0200 -Subject: [PATCH] replica install: do not set CA renewal master flag - -The CA renewal master flag was uncoditionally set on every replica during -replica install. This causes the Dogtag certificates initially shared -among all replicas to differ after renewal. - -Do not set the CA renewal master flag in replica install anymore. On -upgrade, remove the flag from all but one IPA masters. - -https://fedorahosted.org/freeipa/ticket/5902 - -Reviewed-By: Martin Babinsky ---- - ipaserver/install/ca.py | 6 +++++- - ipaserver/install/plugins/ca_renewal_master.py | 24 ++++++++++++++++++++++-- - 2 files changed, 27 insertions(+), 3 deletions(-) - -diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py -index b4db8dcbfad9d482e7106cd06b3d497ccf8954f0..aa3fe991bd958c59dc369f41d4bd6fdfceee9370 100644 ---- a/ipaserver/install/ca.py -+++ b/ipaserver/install/ca.py -@@ -191,7 +191,11 @@ def install_step_1(standalone, replica_config, options): - ca.stop(ca.dogtag_constants.PKI_INSTANCE_NAME) - - # We need to ldap_enable the CA now that DS is up and running -- ca.ldap_enable('CA', host_name, dm_password, basedn, ['caRenewalMaster']) -+ if replica_config is None: -+ config = ['caRenewalMaster'] -+ else: -+ config = [] -+ ca.ldap_enable('CA', host_name, dm_password, basedn, config) - - # This is done within stopped_service context, which restarts CA - ca.enable_client_auth_to_db(dogtag_constants.CS_CFG_PATH) -diff --git a/ipaserver/install/plugins/ca_renewal_master.py b/ipaserver/install/plugins/ca_renewal_master.py -index dae976f02dc7f963736ca57344345135dbc1fe3b..c0c655c912a6b02da11d0feb333716f7653768ed 100644 ---- a/ipaserver/install/plugins/ca_renewal_master.py -+++ b/ipaserver/install/plugins/ca_renewal_master.py -@@ -42,6 +42,7 @@ class update_ca_renewal_master(Updater): - ldap = self.api.Backend.ldap2 - base_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), - self.api.env.basedn) -+ dn = DN(('cn', 'CA'), ('cn', self.api.env.host), base_dn) - filter = '(&(cn=CA)(ipaConfigString=caRenewalMaster))' - try: - entries = ldap.get_entries(base_dn=base_dn, filter=filter, -@@ -50,7 +51,27 @@ class update_ca_renewal_master(Updater): - pass - else: - self.debug("found CA renewal master %s", entries[0].dn[1].value) -- return False, [] -+ -+ master = False -+ updates = [] -+ -+ for entry in entries: -+ if entry.dn == dn: -+ master = True -+ continue -+ -+ updates.append({ -+ 'dn': entry.dn, -+ 'updates': [ -+ dict(action='remove', attr='ipaConfigString', -+ value='caRenewalMaster') -+ ], -+ }) -+ -+ if master: -+ return False, updates -+ else: -+ return False, [] - - criteria = { - 'cert-database': paths.HTTPD_ALIAS_DIR, -@@ -96,7 +117,6 @@ class update_ca_renewal_master(Updater): - "assuming local CA is renewal slave", config) - return (False, False, []) - -- dn = DN(('cn', 'CA'), ('cn', self.api.env.host), base_dn) - update = { - 'dn': dn, - 'updates': [ --- -2.5.5 - diff --git a/SOURCES/0205-mod_auth_gssapi-enable-unique-credential-caches-name.patch b/SOURCES/0205-mod_auth_gssapi-enable-unique-credential-caches-name.patch deleted file mode 100644 index e34f786..0000000 --- a/SOURCES/0205-mod_auth_gssapi-enable-unique-credential-caches-name.patch +++ /dev/null @@ -1,59 +0,0 @@ -From 42e65d58596222a5480e7ddf0c8d793a04156af7 Mon Sep 17 00:00:00 2001 -From: Petr Vobornik -Date: Thu, 23 Jun 2016 15:58:15 +0200 -Subject: [PATCH] mod_auth_gssapi: enable unique credential caches names - -mod_auth_gssapi > 1.4.0 implements support for unique ccaches names. -Without it ccache name is derived from pricipal name. - -It solves a race condition in two concurrent request of the same -principal. Where first request deletes the ccache and the second -tries to use it which then fails. It may lead e.g. to a failure of -two concurrent ipa-client-install. - -With this feature there are two ccaches so there is no clash. - -https://fedorahosted.org/freeipa/ticket/5653 - -Reviewed-By: Stanislav Laznicka -Reviewed-By: Robbie Harwood ---- - freeipa.spec.in | 2 +- - install/conf/ipa.conf | 3 ++- - 2 files changed, 3 insertions(+), 2 deletions(-) - -diff --git a/freeipa.spec.in b/freeipa.spec.in -index 17b90fc4653bd7694bf389a19d5847d7df544890..d3c5748ca5df9c7fa5e57287fb428aeb649620b8 100644 ---- a/freeipa.spec.in -+++ b/freeipa.spec.in -@@ -123,7 +123,7 @@ Requires: cyrus-sasl-gssapi%{?_isa} - Requires: ntp - Requires: httpd >= 2.4.6-6 - Requires: mod_wsgi --Requires: mod_auth_gssapi >= 1.1.0-2 -+Requires: mod_auth_gssapi >= 1.4.0 - Requires: mod_nss >= 1.0.8-26 - Requires: python-ldap >= 2.4.15 - Requires: python-krbV -diff --git a/install/conf/ipa.conf b/install/conf/ipa.conf -index e2b602c8573078f517badac00a8c8c5bd593db28..13df090eb214533ceb789a36327b76a74f80567f 100644 ---- a/install/conf/ipa.conf -+++ b/install/conf/ipa.conf -@@ -1,5 +1,5 @@ - # --# VERSION 18 - DO NOT REMOVE THIS LINE -+# VERSION 19 - DO NOT REMOVE THIS LINE - # - # This file may be overwritten on upgrades. - # -@@ -65,6 +65,7 @@ WSGIScriptReloading Off - GssapiCredStore keytab:/etc/httpd/conf/ipa.keytab - GssapiCredStore client_keytab:/etc/httpd/conf/ipa.keytab - GssapiDelegCcacheDir /var/run/httpd/ipa/clientcaches -+ GssapiDelegCcacheUnique On - GssapiUseS4U2Proxy on - Require valid-user - ErrorDocument 401 /ipa/errors/unauthorized.html --- -2.7.4 - diff --git a/SOURCES/0206-cert-revoke-fix-permission-check-bypass-CVE-2016-540.patch b/SOURCES/0206-cert-revoke-fix-permission-check-bypass-CVE-2016-540.patch deleted file mode 100644 index 8c70116..0000000 --- a/SOURCES/0206-cert-revoke-fix-permission-check-bypass-CVE-2016-540.patch +++ /dev/null @@ -1,115 +0,0 @@ -From a35c267ec03a56d02c5f86294d6ed16f0ee9ae57 Mon Sep 17 00:00:00 2001 -From: Fraser Tweedale -Date: Thu, 30 Jun 2016 10:21:01 +1000 -Subject: [PATCH] cert-revoke: fix permission check bypass (CVE-2016-5404) - -The 'cert_revoke' command checks the 'revoke certificate' -permission, however, if an ACIError is raised, it then invokes the -'cert_show' command. The rational was to re-use a "host manages -certificate" check that is part of the 'cert_show' command, however, -it is sufficient that 'cert_show' executes successfully for -'cert_revoke' to recover from the ACIError continue. Therefore, -anyone with 'retrieve certificate' permission can revoke *any* -certificate and cause various kinds of DoS. - -Fix the problem by extracting the "host manages certificate" check -to its own method and explicitly calling it from 'cert_revoke'. - -Fixes: https://fedorahosted.org/freeipa/ticket/6232 -Reviewed-By: Jan Cholasta ---- - ipalib/plugins/cert.py | 47 ++++++++++++++++++++++++++++++----------------- - 1 file changed, 30 insertions(+), 17 deletions(-) - -diff --git a/ipalib/plugins/cert.py b/ipalib/plugins/cert.py -index 7a07039a8488cc11d9bf05ef23642b8059d5921e..42dc4f571b9274f45bd6c20910362cf676764f3a 100644 ---- a/ipalib/plugins/cert.py -+++ b/ipalib/plugins/cert.py -@@ -236,6 +236,25 @@ def caacl_check(principal_type, principal_string, ca, profile_id): - ) - ) - -+ -+def bind_principal_can_manage_cert(cert): -+ """Check that the bind principal can manage the given cert. -+ -+ ``cert`` -+ An NSS certificate object. -+ -+ """ -+ bind_principal = getattr(context, 'principal') -+ if not bind_principal.startswith('host/'): -+ return False -+ -+ hostname = get_host_from_principal(bind_principal) -+ -+ # If we have a hostname we want to verify that the subject -+ # of the certificate matches it. -+ return hostname == cert.subject.common_name #pylint: disable=E1101 -+ -+ - @register() - class cert_request(VirtualCommand): - __doc__ = _('Submit a certificate signing request.') -@@ -601,29 +620,23 @@ class cert_show(VirtualCommand): - - def execute(self, serial_number, **options): - ca_enabled_check() -- hostname = None -+ -+ result=self.Backend.ra.get_certificate(serial_number) -+ cert = x509.load_certificate(result['certificate']) -+ - try: - self.check_access() -- except errors.ACIError, acierr: -+ except errors.ACIError as acierr: - self.debug("Not granted by ACI to retrieve certificate, looking at principal") -- bind_principal = getattr(context, 'principal') -- if not bind_principal.startswith('host/'): -- raise acierr -- hostname = get_host_from_principal(bind_principal) -+ if not bind_principal_can_manage_cert(cert): -+ raise acierr # pylint: disable=E0702 - -- result=self.Backend.ra.get_certificate(serial_number) -- cert = x509.load_certificate(result['certificate']) - result['subject'] = unicode(cert.subject) - result['issuer'] = unicode(cert.issuer) - result['valid_not_before'] = unicode(cert.valid_not_before_str) - result['valid_not_after'] = unicode(cert.valid_not_after_str) - result['md5_fingerprint'] = unicode(nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0]) - result['sha1_fingerprint'] = unicode(nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0]) -- if hostname: -- # If we have a hostname we want to verify that the subject -- # of the certificate matches it, otherwise raise an error -- if hostname != cert.subject.common_name: #pylint: disable=E1101 -- raise acierr - - return dict(result=result) - -@@ -669,17 +682,17 @@ class cert_revoke(VirtualCommand): - - def execute(self, serial_number, **kw): - ca_enabled_check() -- hostname = None - try: - self.check_access() - except errors.ACIError, acierr: - self.debug("Not granted by ACI to revoke certificate, looking at principal") - try: -- # Let cert_show() handle verifying that the subject of the -- # cert we're dealing with matches the hostname in the principal - result = api.Command['cert_show'](unicode(serial_number))['result'] -+ cert = x509.load_certificate(result['certificate']) -+ if not bind_principal_can_manage_cert(cert): -+ raise acierr - except errors.NotImplementedError: -- pass -+ raise acierr - revocation_reason = kw['revocation_reason'] - if revocation_reason == 7: - raise errors.CertificateOperationError(error=_('7 is not a valid revocation reason')) --- -2.9.3 - diff --git a/SOURCES/1001-Hide-pkinit-functionality-from-production-version.patch b/SOURCES/1001-Hide-pkinit-functionality-from-production-version.patch index 6cb68b1..949554b 100644 --- a/SOURCES/1001-Hide-pkinit-functionality-from-production-version.patch +++ b/SOURCES/1001-Hide-pkinit-functionality-from-production-version.patch @@ -1,4 +1,4 @@ -From b30152e2225fed9a991423c35506f3aa62b38350 Mon Sep 17 00:00:00 2001 +From 4651261af43a311d23efa759e61143a6413c5dc5 Mon Sep 17 00:00:00 2001 From: Martin Kosek Date: Fri, 5 Sep 2014 11:24:27 +0200 Subject: [PATCH] Hide pkinit functionality from production version @@ -7,26 +7,27 @@ Rebased from original patch from Jan Zeleny and Rob Crittenden. https://fedorahosted.org/freeipa/ticket/616 --- - ipaserver/install/ipa_replica_prepare.py | 20 +++----------------- - ipaserver/install/server/install.py | 4 ++++ - ipaserver/install/server/replicainstall.py | 1 + - 3 files changed, 8 insertions(+), 17 deletions(-) + ipaserver/install/ipa_replica_prepare.py | 21 ++++----------------- + ipaserver/install/server/common.py | 30 ++++++++---------------------- + ipaserver/install/server/install.py | 11 ----------- + ipaserver/install/server/replicainstall.py | 1 - + 4 files changed, 12 insertions(+), 51 deletions(-) diff --git a/ipaserver/install/ipa_replica_prepare.py b/ipaserver/install/ipa_replica_prepare.py -index b9ae60e9bc9d40be5f86e312980846b2ad80f67d..62cc8368abd999bec07154dc2c715431ff0c3b1a 100644 +index 80813086c6a7212bdb6ef9d54202b28808b80076..9ba536163bf5c2882d8fc593457dab78a08e849a 100644 --- a/ipaserver/install/ipa_replica_prepare.py +++ b/ipaserver/install/ipa_replica_prepare.py -@@ -65,9 +65,6 @@ class ReplicaPrepare(admintool.AdminTool): - parser.add_option("--no-reverse", dest="no_reverse", - action="store_true", default=False, - help="do not create reverse DNS zone") +@@ -85,9 +85,6 @@ class ReplicaPrepare(admintool.AdminTool): + parser.add_option("--allow-zone-overlap", dest="allow_zone_overlap", + action="store_true", default=False, help="create DNS " + "zone even if it already exists") - parser.add_option("--no-pkinit", dest="setup_pkinit", - action="store_false", default=True, - help="disables pkinit setup steps") parser.add_option("--ca", dest="ca_file", default=paths.CACERT_P12, metavar="FILE", help="location of CA PKCS#12 file, default /root/cacert.p12") -@@ -89,12 +86,6 @@ class ReplicaPrepare(admintool.AdminTool): +@@ -109,12 +106,6 @@ class ReplicaPrepare(admintool.AdminTool): group.add_option("--http_pkcs12", dest="http_cert_files", action="append", help=SUPPRESS_HELP) @@ -39,7 +40,7 @@ index b9ae60e9bc9d40be5f86e312980846b2ad80f67d..62cc8368abd999bec07154dc2c715431 group.add_option("--dirsrv-pin", dest="dirsrv_pin", sensitive=True, metavar="PIN", help="The password to unlock the Directory Server private key") -@@ -105,20 +96,12 @@ class ReplicaPrepare(admintool.AdminTool): +@@ -125,20 +116,12 @@ class ReplicaPrepare(admintool.AdminTool): help="The password to unlock the Apache Server private key") group.add_option("--http_pin", dest="http_pin", sensitive=True, help=SUPPRESS_HELP) @@ -60,65 +61,130 @@ index b9ae60e9bc9d40be5f86e312980846b2ad80f67d..62cc8368abd999bec07154dc2c715431 parser.add_option_group(group) def validate_options(self): -@@ -138,7 +121,10 @@ class ReplicaPrepare(admintool.AdminTool): +@@ -158,7 +141,11 @@ class ReplicaPrepare(admintool.AdminTool): "option together with --no-reverse") #Automatically disable pkinit w/ dogtag until that is supported + # pkinit is disabled in production version options.setup_pkinit = False -+ options.pkinit_pin = False -+ options.pkinit_cert_files = False ++ options.pkinit_cert_files = None ++ options.pkinit_pin = None ++ options.pkinit_cert_name = None # If any of the PKCS#12 options are selected, all are required. cert_file_req = (options.dirsrv_cert_files, options.http_cert_files) -diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py -index 01dffd08d4c929ebc5ecb6e6b0a8b685c1320dbd..a2a22c6334edf442e07ff3a1b4b9b309de2bc8a5 100644 ---- a/ipaserver/install/server/install.py -+++ b/ipaserver/install/server/install.py -@@ -1172,6 +1172,7 @@ class ServerCA(common.Installable, core.Group, core.Composite): - - no_pkinit = Knob( - bool, False, -+ initializable=False, - description="disables pkinit setup steps", +diff --git a/ipaserver/install/server/common.py b/ipaserver/install/server/common.py +index e6093d15cd1067a83ed89945c4a9c983c66ec06f..a64a0938f3829ce58e22b5b9043373aa7eb7dfe2 100644 +--- a/ipaserver/install/server/common.py ++++ b/ipaserver/install/server/common.py +@@ -72,13 +72,7 @@ class BaseServerCA(common.Installable, core.Group, core.Composite): + cli_metavar='FILE', ) -@@ -1195,6 +1196,7 @@ class ServerCA(common.Installable, core.Group, core.Composite): - - pkinit_cert_files = Knob( - (list, str), None, -+ initializable=False, - description=("File containing the Kerberos KDC SSL certificate and " - "private key"), - cli_name='pkinit-cert-file', -@@ -1220,6 +1222,7 @@ class ServerCA(common.Installable, core.Group, core.Composite): +- pkinit_cert_files = Knob( +- (list, str), None, +- description=("File containing the Kerberos KDC SSL certificate and " +- "private key"), +- cli_name='pkinit-cert-file', +- cli_metavar='FILE', +- ) ++ pkinit_cert_files = None - pkinit_pin = Knob( + dirsrv_pin = Knob( str, None, -+ initializable=False, - sensitive=True, - description="The password to unlock the Kerberos KDC private key", - cli_aliases=['pkinit_pin'], -@@ -1240,6 +1243,7 @@ class ServerCA(common.Installable, core.Group, core.Composite): +@@ -94,12 +88,7 @@ class BaseServerCA(common.Installable, core.Group, core.Composite): + cli_metavar='PIN', + ) + +- pkinit_pin = Knob( +- str, None, +- sensitive=True, +- description="The password to unlock the Kerberos KDC private key", +- cli_metavar='PIN', +- ) ++ pkinit_pin = None - pkinit_cert_name = Knob( + dirsrv_cert_name = Knob( str, None, -+ initializable=False, - description="Name of the Kerberos KDC SSL certificate to install", +@@ -113,11 +102,7 @@ class BaseServerCA(common.Installable, core.Group, core.Composite): cli_metavar='NAME', ) -diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py -index 2ab95add90d33eb191d4e75b62cb4eceac40551b..b000e8ce84df3cb2a6bc90520cb4713ab416f4da 100644 ---- a/ipaserver/install/server/replicainstall.py -+++ b/ipaserver/install/server/replicainstall.py -@@ -690,6 +690,7 @@ class ReplicaCA(common.Installable, core.Group, core.Composite): - no_pkinit = Knob( +- pkinit_cert_name = Knob( +- str, None, +- description="Name of the Kerberos KDC SSL certificate to install", +- cli_metavar='NAME', +- ) ++ pkinit_cert_name = None + + ca_cert_files = Knob( + (list, str), None, +@@ -341,10 +326,7 @@ class BaseServer(common.Installable, common.Interactive, core.Composite): + cli_short_name='N', + ) + +- no_pkinit = Knob( +- bool, False, +- description="disables pkinit setup steps", +- ) ++ no_pkinit = False + + no_ui_redirect = Knob( bool, False, -+ initializable=False, - description="disables pkinit setup steps", +@@ -384,6 +366,10 @@ class BaseServer(common.Installable, common.Interactive, core.Composite): + if not os.path.exists(value): + raise ValueError("File %s does not exist." % value) + ++ pkinit_cert_files = None ++ pkinit_pin = None ++ pkinit_cert_name = None ++ no_pkinit = False + + def __init__(self, **kwargs): + super(BaseServer, self).__init__(**kwargs) +diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py +index b33b0243d4d909a561b59d93f0014c390146b333..c292c4d24bfde1484769698ee2a7ef59a6fcc52c 100644 +--- a/ipaserver/install/server/install.py ++++ b/ipaserver/install/server/install.py +@@ -1169,11 +1169,6 @@ class ServerCA(BaseServerCA): + cli_aliases=['http_pkcs12'], + ) + +- pkinit_cert_files = Knob( +- BaseServerCA.pkinit_cert_files, +- cli_aliases=['pkinit_pkcs12'], +- ) +- + dirsrv_pin = Knob( + BaseServerCA.dirsrv_pin, + cli_aliases=['dirsrv_pin'], +@@ -1184,14 +1179,8 @@ class ServerCA(BaseServerCA): + cli_aliases=['http_pin'], ) +- pkinit_pin = Knob( +- BaseServerCA.pkinit_pin, +- cli_aliases=['pkinit_pin'], +- ) +- + dirsrv_cert_name = Knob(BaseServerCA.dirsrv_cert_name) + http_cert_name = Knob(BaseServerCA.http_cert_name) +- pkinit_cert_name = Knob(BaseServerCA.pkinit_cert_name) + ca_cert_files = Knob(BaseServerCA.ca_cert_files) + subject = Knob(BaseServerCA.subject) + ca_signing_algorithm = Knob(BaseServerCA.ca_signing_algorithm) +diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py +index f54ff7da06c57b9c8251429cbdacc5c300805f84..7695adf0d537237b24660e8871011f04f242e744 100644 +--- a/ipaserver/install/server/replicainstall.py ++++ b/ipaserver/install/server/replicainstall.py +@@ -1587,7 +1587,6 @@ class Replica(BaseServer): + mkhomedir = Knob(BaseServer.mkhomedir) + no_host_dns = Knob(BaseServer.no_host_dns) + no_ntp = Knob(BaseServer.no_ntp) +- no_pkinit = Knob(BaseServer.no_pkinit) + no_ui_redirect = Knob(BaseServer.no_ui_redirect) + ssh_trust_dns = Knob(BaseServer.ssh_trust_dns) + no_ssh = Knob(BaseServer.no_ssh) -- -2.5.0 +2.9.3 diff --git a/SOURCES/1002-Remove-pkinit-plugin.patch b/SOURCES/1002-Remove-pkinit-plugin.patch index 955364d..8e183e7 100644 --- a/SOURCES/1002-Remove-pkinit-plugin.patch +++ b/SOURCES/1002-Remove-pkinit-plugin.patch @@ -1,4 +1,4 @@ -From 414c1303d60e6e7ca46b29e0e2e066bca03c9e0b Mon Sep 17 00:00:00 2001 +From 4d7f256b83522de2046bcf783cd6bb2a4a025b29 Mon Sep 17 00:00:00 2001 From: Martin Kosek Date: Fri, 5 Sep 2014 11:26:18 +0200 Subject: [PATCH] Remove pkinit plugin @@ -11,31 +11,40 @@ Rebased patch by Jan Zeleny and Rob Crittenden. https://fedorahosted.org/freeipa/ticket/616 --- - API.txt | 5 --- - ipalib/plugins/pkinit.py | 105 ----------------------------------------------- - 2 files changed, 110 deletions(-) - delete mode 100644 ipalib/plugins/pkinit.py + API.txt | 7 --- + ipaserver/plugins/pkinit.py | 105 -------------------------------------------- + 2 files changed, 112 deletions(-) + delete mode 100644 ipaserver/plugins/pkinit.py diff --git a/API.txt b/API.txt -index 5253e1585e000f39d6e185a94548037dfe54d4d8..0b626cb0db44ec9adfb688bd5afddb4b17d950d6 100644 +index fb5bf83cea0633130217cf1327481c8e9b11c4fc..ab2262966d113fd91d13f36f73e691ce5178b50f 100644 --- a/API.txt +++ b/API.txt -@@ -3199,11 +3199,6 @@ command: ping +@@ -3583,11 +3583,6 @@ command: ping/1 args: 0,1,1 - option: Str('version?', exclude='webui') - output: Output('summary', (, ), None) --command: pkinit_anonymous + option: Str('version?') + output: Output('summary', type=[, ]) +-command: pkinit_anonymous/1 -args: 1,1,1 -arg: Str('action') --option: Str('version?', exclude='webui') --output: Output('result', None, None) - command: plugins +-option: Str('version?') +-output: Output('result') + command: plugins/1 args: 0,3,3 - option: Flag('all', autofill=True, cli_name='all', default=True, exclude='webui') -diff --git a/ipalib/plugins/pkinit.py b/ipalib/plugins/pkinit.py + option: Flag('all', autofill=True, cli_name='all', default=True) +@@ -6526,8 +6521,6 @@ default: permission_mod/1 + default: permission_remove_member/1 + default: permission_show/1 + default: ping/1 +-default: pkinit/1 +-default: pkinit_anonymous/1 + default: plugins/1 + default: privilege/1 + default: privilege_add/1 +diff --git a/ipaserver/plugins/pkinit.py b/ipaserver/plugins/pkinit.py deleted file mode 100644 -index 5f00b2b46ff94cca7f98876c0171f455c210d778..0000000000000000000000000000000000000000 ---- a/ipalib/plugins/pkinit.py +index 9aa101063705f54509d3de42c1acd23ca96f4a37..0000000000000000000000000000000000000000 +--- a/ipaserver/plugins/pkinit.py +++ /dev/null @@ -1,105 +0,0 @@ -# Authors: @@ -58,7 +67,7 @@ index 5f00b2b46ff94cca7f98876c0171f455c210d778..00000000000000000000000000000000 -# along with this program. If not, see . - -from ipalib import api, errors --from ipalib import Int, Str +-from ipalib import Str -from ipalib import Object, Command -from ipalib import _ -from ipalib.plugable import Registry @@ -144,5 +153,5 @@ index 5f00b2b46ff94cca7f98876c0171f455c210d778..00000000000000000000000000000000 - return dict(result=True) - -- -2.5.1 +2.7.4 diff --git a/SOURCES/1003-Remove-pkinit-references-from-tool-man-pages.patch b/SOURCES/1003-Remove-pkinit-references-from-tool-man-pages.patch index 32a27c7..453e1cf 100644 --- a/SOURCES/1003-Remove-pkinit-references-from-tool-man-pages.patch +++ b/SOURCES/1003-Remove-pkinit-references-from-tool-man-pages.patch @@ -1,25 +1,52 @@ -From b3173293d8b580beb4ffd8c3e05561f670387c04 Mon Sep 17 00:00:00 2001 +From c72d7d5cfbf22125defac401f7b70bd164ae0293 Mon Sep 17 00:00:00 2001 From: Martin Kosek Date: Wed, 22 May 2013 09:59:12 +0200 Subject: [PATCH] Remove pkinit references from tool man pages --- - install/tools/man/ipa-replica-install.1 | 3 --- + install/tools/man/ipa-replica-install.1 | 12 ------------ install/tools/man/ipa-replica-prepare.1 | 12 ------------ install/tools/man/ipa-server-install.1 | 12 ------------ - 3 files changed, 27 deletions(-) + 3 files changed, 36 deletions(-) diff --git a/install/tools/man/ipa-replica-install.1 b/install/tools/man/ipa-replica-install.1 -index 780febf9d597d7d36b6104c0fc1be8f3d1f8fdee..ab8a428da4047db4655dbe8b3c5488f1292f8982 100644 +index 55bae2cb77e1a1c520e0598983b8939a919a9ee9..1bc7ccd779baad3bc0bb269914fd136549c09c47 100644 --- a/install/tools/man/ipa-replica-install.1 +++ b/install/tools/man/ipa-replica-install.1 -@@ -77,9 +77,6 @@ An unattended installation that will never prompt for user input - - .SS "CERTIFICATE SYSTEM OPTIONS" +@@ -125,36 +125,24 @@ The path to LDIF file that will be used to modify configuration of dse.ldif duri + Install and configure a CA on this replica. If a CA is not configured then + certificate operations will be forwarded to a master with a CA installed. .TP -\fB\-\-no\-pkinit\fR -Disables pkinit setup steps -.TP + \fB\-\-dirsrv\-cert\-file\fR=FILE + File containing the Directory Server SSL certificate and private key + .TP + \fB\-\-http\-cert\-file\fR=FILE + File containing the Apache Server SSL certificate and private key + .TP +-\fB\-\-pkinit\-cert\-file\fR=FILE +-File containing the Kerberos KDC SSL certificate and private key +-.TP + \fB\-\-dirsrv\-pin\fR=PIN + The password to unlock the Directory Server private key + .TP + \fB\-\-http\-pin\fR=PIN + The password to unlock the Apache Server private key + .TP +-\fB\-\-pkinit\-pin\fR=PIN +-The password to unlock the Kerberos KDC private key +-.TP + \fB\-\-dirsrv\-cert\-name\fR=NAME + Name of the Directory Server SSL certificate to install + .TP + \fB\-\-http\-cert\-name\fR=NAME + Name of the Apache Server SSL certificate to install + .TP +-\fB\-\-pkinit\-cert\-name\fR=NAME +-Name of the Kerberos KDC SSL certificate to install +-.TP \fB\-\-skip\-schema\-check\fR Skip check for updated CA DS schema on the remote master @@ -66,10 +93,10 @@ index 2063657f8eb4e97fc11b1abb95a892e26b4344e6..afc5408ef87ec5cf967d00dd21aa8485 Prints info log messages to the output .SH "EXIT STATUS" diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1 -index 1eaed72119a9cd2f9876d3dc3c4a662782c18a36..3cea9fd66c133a25a611fa72a00d60a279da1b2a 100644 +index 55b49449e3c44aebfeefe5cb71d73e9abf07c5b2..697ee92f5d0b5b9ff9306e659aabe19295fc9fb9 100644 --- a/install/tools/man/ipa-server-install.1 +++ b/install/tools/man/ipa-server-install.1 -@@ -91,36 +91,24 @@ Type of the external CA. Possible values are "generic", "ms-cs". Default value i +@@ -96,36 +96,24 @@ Type of the external CA. Possible values are "generic", "ms-cs". Default value i \fB\-\-external\-cert\-file\fR=\fIFILE\fR File containing the IPA CA certificate and the external CA certificate chain. The file is accepted in PEM and DER certificate and PKCS#7 certificate chain formats. This option may be used multiple times. .TP @@ -107,5 +134,5 @@ index 1eaed72119a9cd2f9876d3dc3c4a662782c18a36..3cea9fd66c133a25a611fa72a00d60a2 File containing the CA certificate of the CA which issued the Directory Server, Apache Server and Kerberos KDC certificates. The file is accepted in PEM and DER certificate and PKCS#7 certificate chain formats. This option may be used multiple times. Use this option if the CA certificate is not present in the certificate files. .TP -- -2.1.0 +2.7.4 diff --git a/SOURCES/1004-Change-branding-to-IPA-and-Identity-Management.patch b/SOURCES/1004-Change-branding-to-IPA-and-Identity-Management.patch index 681bfbe..e06d7ff 100644 --- a/SOURCES/1004-Change-branding-to-IPA-and-Identity-Management.patch +++ b/SOURCES/1004-Change-branding-to-IPA-and-Identity-Management.patch @@ -1,9 +1,16 @@ -From 5e341cea66938c8dfd99d83c869a1f2ba71479be Mon Sep 17 00:00:00 2001 +From d9499d8d1a40b96e40c956dca25464fc129a9dec Mon Sep 17 00:00:00 2001 From: Martin Kosek Date: Fri, 5 Sep 2014 11:46:59 +0200 Subject: [PATCH] Change branding to IPA and Identity Management --- + client/man/default.conf.5 | 2 +- + client/man/ipa-certupdate.1 | 2 +- + client/man/ipa-client-automount.1 | 2 +- + client/man/ipa-client-install.1 | 2 +- + client/man/ipa-getkeytab.1 | 4 ++-- + client/man/ipa-join.1 | 2 +- + client/man/ipa-rmkeytab.1 | 2 +- install/html/browserconfig.html | 4 ++-- install/html/ssbrowser.html | 4 ++-- install/html/unauthorized.html | 4 ++-- @@ -38,13 +45,6 @@ Subject: [PATCH] Change branding to IPA and Identity Management install/ui/reset_password.html | 2 +- install/ui/src/freeipa/widgets/App.js | 2 +- install/ui/sync_otp.html | 2 +- - ipa-client/man/default.conf.5 | 2 +- - ipa-client/man/ipa-certupdate.1 | 2 +- - ipa-client/man/ipa-client-automount.1 | 2 +- - ipa-client/man/ipa-client-install.1 | 2 +- - ipa-client/man/ipa-getkeytab.1 | 4 ++-- - ipa-client/man/ipa-join.1 | 2 +- - ipa-client/man/ipa-rmkeytab.1 | 2 +- ipa.1 | 2 +- ipaserver/advise/plugins/legacy_clients.py | 8 ++++---- ipaserver/install/dns.py | 2 +- @@ -53,6 +53,106 @@ Subject: [PATCH] Change branding to IPA and Identity Management ipaserver/install/server/replicainstall.py | 2 +- 47 files changed, 57 insertions(+), 57 deletions(-) +diff --git a/client/man/default.conf.5 b/client/man/default.conf.5 +index 35ce6bb9f871365ffbc74b66be46d49fdcb3f7ad..b519d15bca9b7ddf8d22a776fa4f4a8c7fac0ca8 100644 +--- a/client/man/default.conf.5 ++++ b/client/man/default.conf.5 +@@ -16,7 +16,7 @@ + .\" + .\" Author: Rob Crittenden + .\" +-.TH "default.conf" "5" "Feb 21 2011" "FreeIPA" "FreeIPA Manual Pages" ++.TH "default.conf" "5" "Feb 21 2011" "IPA" "IPA Manual Pages" + .SH "NAME" + default.conf \- IPA configuration file + .SH "SYNOPSIS" +diff --git a/client/man/ipa-certupdate.1 b/client/man/ipa-certupdate.1 +index d95790a366aac4635e32bbc6bc81773bb9a52e68..431b395a907b6978d9e0dba9870ed0bd0c54f07b 100644 +--- a/client/man/ipa-certupdate.1 ++++ b/client/man/ipa-certupdate.1 +@@ -16,7 +16,7 @@ + .\" + .\" Author: Jan Cholasta + .\" +-.TH "ipa-certupdate" "1" "Jul 2 2014" "FreeIPA" "FreeIPA Manual Pages" ++.TH "ipa-certupdate" "1" "Jul 2 2014" "IPA" "IPA Manual Pages" + .SH "NAME" + ipa\-certupdate \- Update local IPA certificate databases with certificates from the server + .SH "SYNOPSIS" +diff --git a/client/man/ipa-client-automount.1 b/client/man/ipa-client-automount.1 +index 5b60503f1304d0a0b03a8862708ba126c50c7eff..2e6f78aa659e90f879f66431c4e52e303a4c9b15 100644 +--- a/client/man/ipa-client-automount.1 ++++ b/client/man/ipa-client-automount.1 +@@ -16,7 +16,7 @@ + .\" + .\" Author: Rob Crittenden + .\" +-.TH "ipa-client-automount" "1" "May 25 2012" "FreeIPA" "FreeIPA Manual Pages" ++.TH "ipa-client-automount" "1" "May 25 2012" "IPA" "IPA Manual Pages" + .SH "NAME" + ipa\-client\-automount \- Configure automount and NFS for IPA + .SH "SYNOPSIS" +diff --git a/client/man/ipa-client-install.1 b/client/man/ipa-client-install.1 +index 7f490d153b12d714e7bda7a6abe72fb0756d520c..438dbe440626763ce1dd9c1a3d36d8d67599e6ff 100644 +--- a/client/man/ipa-client-install.1 ++++ b/client/man/ipa-client-install.1 +@@ -16,7 +16,7 @@ + .\" + .\" Author: Rob Crittenden + .\" +-.TH "ipa-client-install" "1" "Jan 31 2013" "FreeIPA" "FreeIPA Manual Pages" ++.TH "ipa-client-install" "1" "Jan 31 2013" "IPA" "IPA Manual Pages" + .SH "NAME" + ipa\-client\-install \- Configure an IPA client + .SH "SYNOPSIS" +diff --git a/client/man/ipa-getkeytab.1 b/client/man/ipa-getkeytab.1 +index 1c270729e1ea224fb74271ad03dfb51c62d70465..11bc5154b2990aac8a4bf2c81fe2b70897b0d839 100644 +--- a/client/man/ipa-getkeytab.1 ++++ b/client/man/ipa-getkeytab.1 +@@ -17,7 +17,7 @@ + .\" Author: Karl MacMillan + .\" Author: Simo Sorce + .\" +-.TH "ipa-getkeytab" "1" "Oct 10 2007" "FreeIPA" "FreeIPA Manual Pages" ++.TH "ipa-getkeytab" "1" "Oct 10 2007" "IPA" "IPA Manual Pages" + .SH "NAME" + ipa\-getkeytab \- Get a keytab for a Kerberos principal + .SH "SYNOPSIS" +@@ -101,7 +101,7 @@ The LDAP password to use when not binding with Kerberos. + \fB\-r\fR + Retrieve mode. Retrieve an existing key from the server instead of generating a + new one. This is incompatibile with the \-\-password option, and will work only +-against a FreeIPA server more recent than version 3.3. The user requesting the ++against a IPA server more recent than version 3.3. The user requesting the + keytab must have access to the keys for this operation to succeed. + .SH "EXAMPLES" + Add and retrieve a keytab for the NFS service principal on +diff --git a/client/man/ipa-join.1 b/client/man/ipa-join.1 +index d881607842bb0227c2da863bd1674db01530e910..30b667558ba3105cf320896ef40b0661a18066f5 100644 +--- a/client/man/ipa-join.1 ++++ b/client/man/ipa-join.1 +@@ -16,7 +16,7 @@ + .\" + .\" Author: Rob Crittenden + .\" +-.TH "ipa-join" "1" "Oct 8 2009" "FreeIPA" "FreeIPA Manual Pages" ++.TH "ipa-join" "1" "Oct 8 2009" "IPA" "IPA Manual Pages" + .SH "NAME" + ipa\-join \- Join a machine to an IPA realm and get a keytab for the host service principal + .SH "SYNOPSIS" +diff --git a/client/man/ipa-rmkeytab.1 b/client/man/ipa-rmkeytab.1 +index 53f775439dbdb5a4b9dfee7fe6c7277fce10893c..2c8218c94996b1411637a7c53f2f5bc5612f3ea3 100644 +--- a/client/man/ipa-rmkeytab.1 ++++ b/client/man/ipa-rmkeytab.1 +@@ -17,7 +17,7 @@ + .\" Author: Rob Crittenden + .\" + .\" +-.TH "ipa-rmkeytab" "1" "Oct 30 2009" "FreeIPA" "FreeIPA Manual Pages" ++.TH "ipa-rmkeytab" "1" "Oct 30 2009" "IPA" "IPA Manual Pages" + .SH "NAME" + ipa\-rmkeytab \- Remove a kerberos principal from a keytab + .SH "SYNOPSIS" diff --git a/install/html/browserconfig.html b/install/html/browserconfig.html index 9c5cf68211281723e12b518f346aac43c1541cdc..14c4ca1f98a60cd8dfe486f8b942fcf9ae9de4c0 100644 --- a/install/html/browserconfig.html @@ -76,7 +176,7 @@ index 9c5cf68211281723e12b518f346aac43c1541cdc..14c4ca1f98a60cd8dfe486f8b942fcf9 diff --git a/install/html/ssbrowser.html b/install/html/ssbrowser.html -index 685800e16e6e77c70adf905acfca2996513d1e1d..8595f82ead70c8e6b2fcd38e2e290bd126d32e70 100644 +index 49d8c5be1a5c07fca0593b6c7d0252a2faf15abf..3c67c484162ad9f1897fc1707a89869ff2dbfa2b 100644 --- a/install/html/ssbrowser.html +++ b/install/html/ssbrowser.html @@ -2,7 +2,7 @@ @@ -88,7 +188,7 @@ index 685800e16e6e77c70adf905acfca2996513d1e1d..8595f82ead70c8e6b2fcd38e2e290bd1